void dgCollisionUserMesh::GetCollisionInfo(dgCollisionInfo* info) const
{
	dgCollision::GetCollisionInfo(info);
	info->m_offsetMatrix = GetOffsetMatrix();
	if (m_getInfo) {
		m_getInfo (m_userData, info);
	}
}
void dgCollisionCone::GetCollisionInfo(dgCollisionInfo* info) const
{
	dgCollisionConvex::GetCollisionInfo(info);

	info->m_cone.m_r = m_radius;
	info->m_cone.m_height = m_height * dgFloat32 (2.0f);
	info->m_offsetMatrix = GetOffsetMatrix();
//	strcpy (info->m_collisionType, "cone");
	info->m_collisionType = m_collsionId;
}
void dgCollisionChamferCylinder::GetCollisionInfo(dgCollisionInfo* info) const
{
	dgCollisionConvex::GetCollisionInfo(info);

	info->m_chamferCylinder.m_r = m_radius + m_height;
	info->m_chamferCylinder.m_height = m_height * dgFloat32 (2.0f);
	info->m_offsetMatrix = GetOffsetMatrix();
//	strcpy (info->m_collisionType, "chamferCylinder");
	info->m_collisionType = m_collsionId;

}
dgFloat32 dgCollisionCone::CalculateMassProperties (dgVector& inertia, dgVector& crossInertia, dgVector& centerOfMass) const
{
	dgFloat32 volume;
	dgFloat32 inertaxx;
	dgFloat32 inertayyzz;

//dgVector centerOfMass1;
//dgVector inertia1;
//dgVector crossInertia1;
//volume = dgCollisionConvex::CalculateMassProperties (inertia1, crossInertia1, centerOfMass1);

	volume = dgFloat32 (3.1616f * 2.0f / 3.0f) * m_radius * m_radius * m_height; 

	centerOfMass = GetOffsetMatrix().m_posit - GetOffsetMatrix().m_front.Scale (dgFloat32 (0.5f) * m_height);

	inertaxx   = dgFloat32 (3.0f / 10.0f) * m_radius *  m_radius * volume;
	inertayyzz = (dgFloat32 (3.0f / 20.0f) * m_radius *  m_radius + dgFloat32 (4.0f / 10.0f) * m_height * m_height) * volume;

	dgMatrix inertiaTensor (dgGetIdentityMatrix());

	inertiaTensor[0][0] = inertaxx;
	inertiaTensor[1][1] = inertayyzz;
	inertiaTensor[2][2] = inertayyzz;

	inertiaTensor = GetOffsetMatrix().Inverse() * inertiaTensor * GetOffsetMatrix();

	crossInertia.m_x = inertiaTensor[1][2] - volume * centerOfMass.m_y * centerOfMass.m_z;
	crossInertia.m_y = inertiaTensor[0][2] - volume * centerOfMass.m_z * centerOfMass.m_x;
	crossInertia.m_z = inertiaTensor[0][1] - volume * centerOfMass.m_x * centerOfMass.m_y;

	dgVector central (centerOfMass.CompProduct(centerOfMass));
	inertia.m_x = inertiaTensor[0][0] + volume * (central.m_y + central.m_z);
	inertia.m_y = inertiaTensor[1][1] + volume * (central.m_z + central.m_x);
	inertia.m_z = inertiaTensor[2][2] + volume * (central.m_x + central.m_y);

	centerOfMass = centerOfMass.Scale (volume);
	return volume;
}
void dgCollisionConvexHull::GetCollisionInfo(dgCollisionInfo* info) const
{
	dgCollisionConvex::GetCollisionInfo(info);

	info->m_offsetMatrix = GetOffsetMatrix();
//	strcpy (info->m_collisionType, "convexHull");
	info->m_collisionType = m_collsionId;

	info->m_convexHull.m_vertexCount = m_vertexCount;
	info->m_convexHull.m_strideInBytes = sizeof (dgVector);
	info->m_convexHull.m_faceCount = m_faceCount;
	info->m_convexHull.m_vertex = &m_vertex[0];

}
void dgCollisionCone::DebugCollision (const dgMatrix& matrixPtr, OnDebugCollisionMeshCallback callback, void* const userData) const
{
	dgInt32 i;
	dgInt32 j;
	dgFloat32 y;
	dgFloat32 z;
	dgFloat32 angle;

	#define NUMBER_OF_DEBUG_SEGMENTS  24
	dgTriplex pool[NUMBER_OF_DEBUG_SEGMENTS + 1];
	dgTriplex face[NUMBER_OF_DEBUG_SEGMENTS];

	angle = dgFloat32 (0.0f);
	for (i = 0; i < NUMBER_OF_DEBUG_SEGMENTS; i ++) {
		z = dgSin (angle) * m_radius;
		y = dgCos (angle) * m_radius;
		pool[i].m_x = - m_height;
		pool[i].m_y = y;
		pool[i].m_z = z;
		angle += dgPI2 / dgFloat32 (NUMBER_OF_DEBUG_SEGMENTS);
	}
	
	pool[i].m_x = m_height;
	pool[i].m_y = dgFloat32 (0.0f);
	pool[i].m_z = dgFloat32 (0.0f);

//	const dgMatrix &matrix = myBody.GetCollisionMatrix();
	dgMatrix matrix (GetOffsetMatrix() * matrixPtr);
	matrix.TransformTriplex (pool, sizeof (dgTriplex), pool, sizeof (dgTriplex), NUMBER_OF_DEBUG_SEGMENTS + 1);

	j = NUMBER_OF_DEBUG_SEGMENTS - 1;
	for (i = 0; i < NUMBER_OF_DEBUG_SEGMENTS; i ++) { 
		face[0] = pool[j];
		face[1] = pool[i];
		face[2] = pool[NUMBER_OF_DEBUG_SEGMENTS];
		j = i;
		callback (userData, 3, &face[0].m_x, 0);
	}

	for (i = 0; i < NUMBER_OF_DEBUG_SEGMENTS; i ++) { 
		face[i] = pool[NUMBER_OF_DEBUG_SEGMENTS - 1 - i];
	}
	callback (userData, NUMBER_OF_DEBUG_SEGMENTS, &face[0].m_x, 0);
}
void dgCollisionBVH::GetCollisionInfo(dgCollisionInfo* info) const
{
	dgCollision::GetCollisionInfo(info);

	info->m_offsetMatrix = GetOffsetMatrix();
	info->m_collisionType = m_collsionId;
		
	dgGetVertexListIndexList data;
	data.m_indexList = NULL;
	data.m_userDataList = NULL;
	data.m_maxIndexCount = 1000000000;
	data.m_triangleCount = 0; 
	dgVector p0 (-1.0e10f, -1.0e10f, -1.0e10f, 1.0f);
	dgVector p1 ( 1.0e10f,  1.0e10f,  1.0e10f, 1.0f);
	ForAllSectors (p0, p1, GetTriangleCount, &data);

	info->m_bvhCollision.m_vertexCount = GetVertexCount();
	info->m_bvhCollision.m_indexCount = data.m_triangleCount * 3;
}
void dgCollisionConvexHull::DebugCollision (const dgMatrix& matrixPtr, OnDebugCollisionMeshCallback callback, void* const userData) const
{
	dgInt32 i;
	dgInt32 count;
	dgConvexSimplexEdge *ptr;
	dgConvexSimplexEdge *face;
	
	dgStack<dgTriplex> tmp (m_vertexCount);
	dgMatrix matrix (GetOffsetMatrix() * matrixPtr);
	matrix.TransformTriplex (&tmp[0].m_x, sizeof (dgTriplex), &m_vertex[0].m_x, sizeof (dgVector), m_vertexCount);

	for (i = 0; i < m_faceCount; i ++) {
		face = m_faceArray[i];
		ptr = face;
		count = 0;
		dgTriplex vertex[256];
		do {
			vertex[count] = tmp[ptr->m_vertex];
			count ++;
			ptr = ptr->m_next;
		} while (ptr != face);
		callback (userData, count, &vertex[0].m_x, 0);
	}
}
void dgCollisionChamferCylinder::DebugCollision (const dgMatrix& matrixPtr, OnDebugCollisionMeshCallback callback, void* const userData) const
{
	dgInt32 i;
	dgInt32 j;
	dgInt32 index;
	dgInt32 index0;
	dgInt32 brakes;
	dgInt32 slices;
	dgFloat32 sliceStep;
	dgFloat32 sliceAngle;
	dgFloat32 breakStep;
	dgFloat32 breakAngle;

	slices = 12;
	brakes = 24;
	sliceAngle = dgFloat32 (0.0f);
	breakAngle = dgFloat32 (0.0f); 
	sliceStep = dgPI  / slices; 
	breakStep = dgPI2 / brakes;

	dgTriplex pool[24 * (12 + 1)];

	dgMatrix rot (dgPitchMatrix (breakStep));	
	index = 0;
	for (j = 0; j <= slices; j ++) {
		dgVector p0 (-m_height * dgCos(sliceAngle), dgFloat32 (0.0f), m_radius + m_height * dgSin(sliceAngle), dgFloat32 (0.0f));
		sliceAngle += sliceStep;
		for (i = 0; i < brakes; i ++) {
			pool[index].m_x = p0.m_x;
			pool[index].m_y = p0.m_y;
			pool[index].m_z = p0.m_z;
			index ++;
			p0 = rot.UnrotateVector (p0);
		}
	}

//	const dgMatrix &matrix = myBody.GetCollisionMatrix();
	dgMatrix matrix (GetOffsetMatrix() * matrixPtr);
	matrix.TransformTriplex (&pool[0].m_x, sizeof (dgTriplex), &pool[0].m_x, sizeof (dgTriplex), 24 * (12 + 1));

	dgTriplex face[32];

	index = 0;
	for (j = 0; j < slices; j ++) {
		index0 = index + brakes - 1;
		for (i = 0; i < brakes; i ++) {
			face[0] = pool[index];
			face[1] = pool[index0];
			face[2] = pool[index0 + brakes];
			face[3] = pool[index + brakes];
			index0 = index;
			index ++;
			callback (userData, 4, &face[0].m_x, 0);
		}
	}

	for (i = 0; i < brakes; i ++) { 
		face[i] = pool[i];
	}
	callback (userData, 24, &face[0].m_x, 0);

	for (i = 0; i < brakes; i ++) { 
		face[i] = pool[brakes * (slices + 1) - i - 1];
	}
	callback (userData, 24, &face[0].m_x, 0);
}
示例#10
0
    void ModelDefinition::Serialize(Serializer &serializer) const
    {
        BasicSerializer intermediarySerializer;


        /////////////////////////////////////
        // Bones

        intermediarySerializer.Write(static_cast<uint32_t>(m_bones.count));
        
        // Local information.
        for (size_t iBone = 0; iBone < m_bones.count; ++iBone)
        {
            auto bone = m_bones[iBone];
            assert(bone != nullptr);
            {
                // Name.
                intermediarySerializer.WriteString(bone->GetName());

                // Relative transformation.
                intermediarySerializer.Write(bone->GetPosition());
                intermediarySerializer.Write(bone->GetRotation());
                intermediarySerializer.Write(bone->GetScale());

                // 4x4 offset matrix.
                intermediarySerializer.Write(bone->GetOffsetMatrix());
            }
        }

        // Parents. -1 for bones without parents.
        for (size_t iBone = 0; iBone < m_bones.count; ++iBone)
        {
            auto bone = m_bones[iBone];
            assert(bone != nullptr);
            {
                auto parentBone = bone->GetParent();
                if (parentBone != nullptr)
                {
                    size_t parentBoneIndex;
                    if (!this->FindBoneIndex(parentBone, parentBoneIndex))
                    {
                        assert(false);
                    }
                    
                    intermediarySerializer.Write(static_cast<uint32_t>(parentBoneIndex));
                }
                else
                {
                    intermediarySerializer.Write(static_cast<uint32_t>(-1));
                }
            }
        }

        Serialization::ChunkHeader header;
        header.id          = Serialization::ChunkID_Model_Bones;
        header.version     = 1;
        header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes();
        serializer.Write(header);
        serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes);



        /////////////////////////////////////
        // Meshes
        //
        // Vertex data is always saved in P3T2N3T3B3 format. Bones are referenced using an integer to index into the list of bones defined above.

        intermediarySerializer.Clear();
        intermediarySerializer.Write(static_cast<uint32_t>(this->meshes.count));

        for (size_t iMesh = 0; iMesh < this->meshes.count; ++iMesh)
        {
            // Name.
            intermediarySerializer.WriteString(this->meshes[iMesh].name);


            // Material.
            intermediarySerializer.WriteString(this->meshes[iMesh].material->GetDefinition().relativePath);


            // Vertices.
            auto vertexArray = this->meshes[iMesh].geometry;
            assert(vertexArray != nullptr);
            {
                // Vertex Format.
                vertexArray->GetFormat().Serialize(intermediarySerializer);


                // Vertices.
                intermediarySerializer.Write(static_cast<uint32_t>(vertexArray->GetVertexCount()));

                if (vertexArray->GetVertexCount() > 0)
                {
                    intermediarySerializer.Write(vertexArray->GetVertexDataPtr(), vertexArray->GetFormat().GetSizeInBytes() * vertexArray->GetVertexCount());
                }


                // Indices.
                intermediarySerializer.Write(static_cast<uint32_t>(vertexArray->GetIndexCount()));

                if (vertexArray->GetIndexCount() > 0)
                {
                    intermediarySerializer.Write(vertexArray->GetIndexDataPtr(), sizeof(uint32_t) * vertexArray->GetIndexCount());
                }


                // Skinning Vertex Attributes.
                if (this->meshes[iMesh].skinningVertexAttributes != nullptr)
                {
                    intermediarySerializer.Write(static_cast<uint32_t>(vertexArray->GetVertexCount()));

                    if (vertexArray->GetVertexCount() > 0)
                    {
                        uint32_t totalBoneWeights = 0;


                        // Bone Counts.
                        for (size_t iVertex = 0; iVertex < vertexArray->GetVertexCount(); ++iVertex)
                        {
                            uint16_t count = static_cast<uint16_t>(this->meshes[iMesh].skinningVertexAttributes[iVertex].bones.count);
                            intermediarySerializer.Write(count);

                            totalBoneWeights += count;
                        }

                            
                        // Bone/Weight Pairs.
                        intermediarySerializer.Write(totalBoneWeights);

                        for (size_t iVertex = 0; iVertex < vertexArray->GetVertexCount(); ++iVertex)
                        {
                            auto &bones = this->meshes[iMesh].skinningVertexAttributes[iVertex].bones;
                            {
                                for (size_t iBone = 0; iBone < bones.count; ++iBone)
                                {
                                    auto &bone = bones[iBone];

                                    intermediarySerializer.Write(static_cast<uint32_t>(bone.boneIndex));
                                    intermediarySerializer.Write(static_cast<float   >(bone.weight));
                                }
                            }
                        }
                    }
                }
                else
                {
                    intermediarySerializer.Write(static_cast<uint32_t>(0));
                }


                // Default uniforms.
                this->meshes[iMesh].defaultUniforms.Serialize(intermediarySerializer);
            }
        }

        header.id          = Serialization::ChunkID_Model_Meshes;
        header.version     = 1;
        header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes();
        serializer.Write(header);
        serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes);



        /////////////////////////////////////
        // Animation

        intermediarySerializer.Clear();
        intermediarySerializer.Write(static_cast<uint32_t>(m_animation.GetKeyFrameCount()));

        for (uint32_t iKeyFrame = 0; iKeyFrame < m_animation.GetKeyFrameCount(); ++iKeyFrame)
        {
            // Time.
            intermediarySerializer.Write(static_cast<float>(m_animation.GetKeyFrameTimeByIndex(iKeyFrame)));
            
            
            // Channels.
            intermediarySerializer.Write(static_cast<uint32_t>(this->animationChannelBones.count));

            for (size_t iChannel = 0; iChannel < this->animationChannelBones.count; ++iChannel)
            {
                auto channel = this->animationChannelBones.buffer[iChannel]->value;
                auto bone    = this->animationChannelBones.buffer[iChannel]->key;

                assert(channel != nullptr);
                assert(bone    != nullptr);
                {
                    // Bone Index.
                    size_t boneIndex;
                    this->FindBoneIndex(bone, boneIndex);

                    intermediarySerializer.Write(static_cast<uint32_t>(boneIndex));


                    // Bone Transformation.
                    glm::vec3 position;
                    glm::quat rotation;
                    glm::vec3 scale;

                    auto key = static_cast<TransformAnimationKey*>(channel->GetKey(iKeyFrame));
                    if (key != nullptr)
                    {
                        position = key->position;
                        rotation = key->rotation;
                        scale    = key->scale;
                    }
                    else
                    {
                        // We should never actually get here, but for completeness we'll just write identities.
                        position = bone->GetPosition();
                        rotation = bone->GetRotation();
                        scale    = bone->GetScale();
                    }

                    intermediarySerializer.Write(position);
                    intermediarySerializer.Write(rotation);
                    intermediarySerializer.Write(scale);
                }
            }
        }

        intermediarySerializer.Write(this->animationAABBPadding);


        header.id          = Serialization::ChunkID_Model_Animation;
        header.version     = 1;
        header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes();
        serializer.Write(header);
        serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes);



        /////////////////////////////////////
        // Animation Segments

        intermediarySerializer.Clear();
        intermediarySerializer.Write(static_cast<uint32_t>(m_animation.GetNamedSegmentCount()));

        for (size_t iSegment = 0; iSegment < m_animation.GetNamedSegmentCount(); ++iSegment)
        {
            auto segment = m_animation.GetNamedSegmentByIndex(iSegment);
            assert(segment != nullptr);
            {
                intermediarySerializer.WriteString(segment->name);
                intermediarySerializer.Write(static_cast<uint32_t>(segment->startKeyFrame));
                intermediarySerializer.Write(static_cast<uint32_t>(segment->endKeyFrame));
            }
        }

        header.id          = Serialization::ChunkID_Model_AnimationSegments;
        header.version     = 1;
        header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes();
        serializer.Write(header);
        serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes);



        /////////////////////////////////////
        // Animation Sequences

        /*
        intermediarySerializer.Clear();
        intermediarySerializer.Write(static_cast<uint32_t>(this->animationSequences.count));

        for (size_t iSequence = 0; iSequence < this->animationSequences.count; ++iSequence)
        {
        }

        header.id          = Serialization::ChunkID_Model_AnimationSequences;
        header.version     = 1;
        header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes();
        serializer.Write(header);
        serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes);
        */


        /////////////////////////////////////
        // Convex Hulls

        intermediarySerializer.Clear();
        intermediarySerializer.Write(static_cast<uint32_t>(m_convexHulls.count));

        Vector<uint32_t> vertexCounts(m_convexHulls.count);
        Vector<uint32_t> indexCounts( m_convexHulls.count);
        Vector<float>    vertices;
        Vector<uint32_t> indices;

        for (size_t iConvexHull = 0; iConvexHull < m_convexHulls.count; ++iConvexHull)
        {
            auto convexHull = m_convexHulls[iConvexHull];
            assert(convexHull != nullptr);
            {
                uint32_t vertexCount = static_cast<uint32_t>(convexHull->GetVertexCount());
                uint32_t indexCount  = static_cast<uint32_t>(convexHull->GetIndexCount());

                vertexCounts.PushBack(vertexCount);
                indexCounts.PushBack( indexCount);

                for (uint32_t iVertex = 0; iVertex < vertexCount; ++iVertex)
                {
                    vertices.PushBack(convexHull->GetVertices()[iVertex * 3 + 0]);
                    vertices.PushBack(convexHull->GetVertices()[iVertex * 3 + 1]);
                    vertices.PushBack(convexHull->GetVertices()[iVertex * 3 + 2]);
                }

                for (uint32_t iIndex = 0; iIndex < indexCount; ++iIndex)
                {
                    indices.PushBack(convexHull->GetIndices()[iIndex]);
                }
            }
        }

        intermediarySerializer.Write(vertexCounts.buffer, vertexCounts.count * 4);
        intermediarySerializer.Write(indexCounts.buffer,  indexCounts.count  * 4);

        intermediarySerializer.Write(static_cast<uint32_t>(vertices.count));
        intermediarySerializer.Write(static_cast<uint32_t>(indices.count));

        intermediarySerializer.Write(vertices.buffer, vertices.count * 4);
        intermediarySerializer.Write(indices.buffer,  indices.count  * 4);

        intermediarySerializer.Write(this->convexHullBuildSettings);


        header.id          = Serialization::ChunkID_Model_ConvexHulls;
        header.version     = 1;
        header.sizeInBytes = intermediarySerializer.GetBufferSizeInBytes();
        serializer.Write(header);
        serializer.Write(intermediarySerializer.GetBuffer(), header.sizeInBytes);



        /////////////////////////////////////
        // Null Chunk

        header.id          = Serialization::ChunkID_Null;
        header.version     = 1;
        header.sizeInBytes = 0;
        serializer.Write(header);
    }