Exemplo n.º 1
0
//////////////////////////////////////////////////////////////////////////
// splitIntoBonePalettes
std::vector< MdlMesh >& MdlMesh::splitIntoBonePalettes( BcU32 PaletteSize )
{
	// Empty current submeshes.
	SubMeshes_.clear();

	// Build a triangle array.
	MdlTriangleArray Triangles;
	BcU32 NoofTriangles = aIndices_.size() / 3;
	Triangles.reserve( NoofTriangles );
	for( BcU32 Idx = 0; Idx < NoofTriangles; ++Idx )
	{
		BcU32 StartIndex = Idx * 3;
		MdlTriangle Triangle = 
		{
			aVertices_[ aIndices_[ StartIndex + 0 ].iVertex_ ],
			aVertices_[ aIndices_[ StartIndex + 1 ].iVertex_ ],
			aVertices_[ aIndices_[ StartIndex + 2 ].iVertex_ ]
		};
		Triangles.push_back( Triangle );
	}

	while( Triangles.size() > 0 )
	{
		MdlBonePalette NewBonePalette( PaletteSize );
		MdlTriangleArray NewTriangles;
		NewTriangles.reserve( Triangles.size() );

		// Iterate over triangles, and add them to the bone palette if possible.
		for( MdlTriangleArray::iterator It( Triangles.begin() ); It != Triangles.end(); )
		{
			MdlTriangle& Triangle = (*It);

			// If we can add it, add it to the new triangles array + erase it.
			if( NewBonePalette.addTriangle( Triangle ) )
			{
				NewTriangles.push_back( Triangle );
				It = Triangles.erase( It );
			}
			else
			{
				++It;
			}
		}

		// Construct a new mesh for the triangles.
		MdlMesh NewMesh;
		NewMesh.bonePalette( NewBonePalette );

		// Add materials.
		BcAssert( aMaterials_.size() == 1 );
		for( BcU32 Idx = 0; Idx < aMaterials_.size(); ++Idx )
		{
			NewMesh.addMaterial( aMaterials_[ Idx ] );
		}

		// Add triangles.
		for( BcU32 Idx = 0; Idx < NewTriangles.size(); ++Idx )
		{
			const MdlTriangle& Triangle( NewTriangles[ Idx ] );
			
			for( BcU32 VertIdx = 0; VertIdx < 3; ++VertIdx )
			{
				MdlIndex Index;
				Index.iVertex_ = NewMesh.addVertexShared( Triangle.Vertex_[ VertIdx ] );
				Index.iMaterial_ = 0;
				NewMesh.addIndex( Index );
			}
		}

		BcAssert( NewMesh.findBoneCount() <= PaletteSize );

		SubMeshes_.push_back( NewMesh );
	}
	
	return SubMeshes_;
}
Exemplo n.º 2
0
//////////////////////////////////////////////////////////////////////////
// buildBindPose
void MD5MeshLoader::buildBindPose( MdlNode* pNode, BcU32 iMesh )
{
	// Skin the mesh.
	MD5_Joint* pJoints = pJoint( 0 );
	MD5_Mesh* pMeshes = pMesh( iMesh );

	// This node is a mesh if we have 1 joint, skin if we have more.
	MdlMesh* pMesh = NULL;
	if( nJoints_ == 1 )
	{
		pNode->type( eNT_MESH );
		pMesh = pNode->pMeshObject();
		
	}
	else
	{
		pNode->type( eNT_SKIN );
		pMesh = pNode->pSkinObject();
	}
	// Add material.
	MdlMaterial Material;
	Material.default3d();
	Material.Name_ = pMeshes->Shader_;
	BcU32 iMaterial = pMesh->addMaterial( Material );

	// Add indices.
	for( BcU32 i = 0; i < pMeshes->nIndices_; ++i )
	{
		MdlIndex Index;
		Index.iMaterial_ = iMaterial;
		Index.iVertex_ = pMeshes->pIndices_[ i ];
		pMesh->addIndex( Index );
	}

	BcVec3d WeightPos;

	for ( BcU32 i = 0; i < pMeshes->nVerts_; ++i )
	{
		MD5_Vert* pMD5Vert = &pMeshes->pVerts_[ i ];
		BcVec3d Position( 0.0f, 0.0f, 0.0f );

		// Setup vertex.
		MdlVertex Vert;

		Vert.bUV_ = BcTrue;
		Vert.UV_.x( pMD5Vert->U_ );
		Vert.UV_.y( pMD5Vert->V_ );

		for ( BcU32 j = 0; j < 4; ++j )
		{
			Vert.Weights_[ j ] = 0.0f;
			Vert.iJoints_[ j ]  = 0;
		}

		// Get bind pose vertex.
		Vert.nWeights_ = 0;

		for ( BcU32 j = 0; j < pMD5Vert->nWeights_; ++j )
		{
			if ( j > 4 ) 
			{
				break;
			}

			BcU32 WeightIndex = pMD5Vert->WeightIndex_ + j;
			MD5_Weight* pMD5Weight = &pMeshes->pWeights_[ WeightIndex ];

			// Fix up a joint.
			MD5_Joint* pJoint = &pJoints[ pMD5Weight->JointID_ ];
			BcVec3d JointTran( pJoint->TX_, pJoint->TY_, pJoint->TZ_ );
			BcQuat JointRot( pJoint->QX_, pJoint->QY_, pJoint->QZ_, 0.0f );
			JointRot.calcFromXYZ();

			//
			const BcReal WeightVal = pMD5Weight->Weight_;

			WeightPos.set( pMD5Weight->X_, pMD5Weight->Y_, pMD5Weight->Z_ );

			JointRot.rotateVector( WeightPos );
			Position += ( WeightPos + JointTran ) * WeightVal;

			// Setup vertex indices and weights:
			Vert.iJoints_[ j ] = pMD5Weight->JointID_;
			Vert.Weights_[ j ] = WeightVal;
			Vert.nWeights_++;
		}

		// Correct weights.
		BcReal WeightTotal = 0.0f;

		for( BcU32 j = 0; j < Vert.nWeights_; ++j )
		{
			WeightTotal += Vert.Weights_[ j ];
		}

		for( BcU32 j = 0; j < Vert.nWeights_; ++j )
		{
			Vert.Weights_[ j ] = Vert.Weights_[ j ] / WeightTotal;
		}


		Vert.bPosition_ = BcTrue;
		Vert.Position_ = Position;

		pMesh->addVertex( Vert );
	}

	pMesh->sortIndicesByMaterial();
	pMesh->buildNormals();
	pMesh->buildTangents();

	// Setup AABB to be larger than the skin to account for motion.
	BcAABB AABB = pMesh->findAABB();

	AABB.min( AABB.min() * 1.5f );
	AABB.max( AABB.max() * 1.5f );

	pNode->aabb( AABB );

	// TODO: Refine into bone palettes properly.
}