FbxAMatrix	LoaderFbxMesh::parseTransformMatrixOther(FbxCluster* cluster, FbxMesh* mesh, FbxPose* fbxPose, FbxAMatrix globalPosition)
{
	FbxAMatrix referenceGeometry;
	FbxAMatrix referenceGlobalInitPosition;
	FbxAMatrix referenceGlobalCurrentPosition;

	FbxAMatrix clusterGeometry;
	FbxAMatrix clusterGlobalInitPosition;
	FbxAMatrix clusterGlobalCurrentPosition;

	FbxAMatrix clusterRelativeInitPosition;
	FbxAMatrix clusterRelativeCurrentPositionInverse;

	FbxTime time(0);

	FbxAMatrix fbxMatrixIdentity;
	fbxMatrixIdentity.SetIdentity();

	cluster->GetTransformMatrix(referenceGlobalInitPosition);
	referenceGlobalCurrentPosition = globalPosition;
	referenceGeometry = getGeometry(mesh->GetNode());
	referenceGlobalInitPosition *= referenceGeometry;

	cluster->GetTransformLinkMatrix(clusterGlobalInitPosition);
	clusterGlobalCurrentPosition = getGlobalPosition(cluster->GetLink(), time, fbxPose, nullptr);

	clusterRelativeInitPosition = clusterGlobalInitPosition.Inverse() * referenceGlobalInitPosition;
	clusterRelativeCurrentPositionInverse = referenceGlobalCurrentPosition.Inverse() * clusterGlobalCurrentPosition;
	
	FbxAMatrix offsetMatrix;
	offsetMatrix = clusterRelativeCurrentPositionInverse * clusterRelativeInitPosition;
	
	return offsetMatrix;
}
/*
The result of this function is a matrix which transforms the verts from their position (where they were when the skeleton was bound to them) to the space of the bone when the verts were bound.
We can then append the bone's current transform in the animation to get the verts into worls space at the current point in the animation.
*/
void Cluster::computeClusterInitTransforms(FbxMesh* mesh, FbxCluster* cluster)
{
	FbxCluster::ELinkMode lClusterMode = cluster->GetLinkMode();

	FbxAMatrix lReferenceGlobalInitPosition;
	FbxAMatrix lAssociateGlobalInitPosition;
	FbxAMatrix lClusterGlobalInitPosition;

	FbxAMatrix lClusterGeometry;
	FbxAMatrix lReferenceGeometry;

	if (lClusterMode == FbxCluster::eAdditive && cluster->GetAssociateModel())
	{
		throw "Addative skinning mode not supported";
	}
	else
	{
		// Transform from the verts' local position at bind time (which is their position when loaded from file) to world space.
		cluster->GetTransformMatrix(lReferenceGlobalInitPosition);
		

		lReferenceGeometry = getGeometry(mesh->GetNode());
		lReferenceGlobalInitPosition *= lReferenceGeometry;
		// Get the link initial global position and the link current global position.
		cluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
		// Transform from world space to bones space at binding time
		FbxAMatrix globalInitPosInv = lClusterGlobalInitPosition.Inverse();
		FbxAMatrix initTransform = globalInitPosInv * lReferenceGlobalInitPosition;
		meshToBoneTransform = Matrix44<float>(
			initTransform[0][0], initTransform[0][1], initTransform[0][2], initTransform[0][3],
			initTransform[1][0], initTransform[1][1], initTransform[1][2], initTransform[1][3],
			initTransform[2][0], initTransform[2][1], initTransform[2][2], initTransform[2][3],
			initTransform[3][0], initTransform[3][1], initTransform[3][2], initTransform[3][3]);
	}
}
FbxAMatrix  LoaderFbxMesh::parseTransformMatrix_debug(FbxCluster* cluster, FbxMesh* mesh, FbxPose* fbxPose, FbxAMatrix globalPosition)
{
	FbxAMatrix transform;
	FbxAMatrix bindPoseTransform;
	FbxAMatrix bindPoseTransformInverse;
	FbxAMatrix boneReferenceTransform;
	FbxAMatrix boneReferenceTransformInverse;
	FbxAMatrix meshGeometryMatrix;

	cluster->GetTransformLinkMatrix(bindPoseTransform);
	cluster->GetTransformMatrix(boneReferenceTransform);

	bindPoseTransformInverse		= bindPoseTransform.Inverse();
	boneReferenceTransformInverse	= boneReferenceTransform.Inverse(); 

	meshGeometryMatrix = getGeometry(mesh->GetNode());

	transform = bindPoseTransformInverse * boneReferenceTransform;

	return transform;
}
示例#4
0
bool ParseMeshSkinning( FbxMesh* pMesh, SkinData* pSkinData )
{
    DWORD dwDeformerCount = pMesh->GetDeformerCount( FbxDeformer::eSkin );
    if( dwDeformerCount == 0 )
        return false;

    ExportLog::LogMsg( 4, "Parsing skin weights on mesh %s", pMesh->GetName() );

    const DWORD dwVertexCount = pMesh->GetControlPointsCount();
    const DWORD dwStride = 4;
    pSkinData->Alloc( dwVertexCount, dwStride );

    for( DWORD dwDeformerIndex = 0; dwDeformerIndex < dwDeformerCount; ++dwDeformerIndex )
    {
        auto pSkin = reinterpret_cast<FbxSkin*>( pMesh->GetDeformer( dwDeformerIndex, FbxDeformer::eSkin ) );
        DWORD dwClusterCount = pSkin->GetClusterCount();

        for( DWORD dwClusterIndex = 0; dwClusterIndex < dwClusterCount; ++dwClusterIndex )
        {
            auto pCluster = pSkin->GetCluster( dwClusterIndex );
            DWORD dwClusterSize = pCluster->GetControlPointIndicesCount();
            if( dwClusterSize == 0 )
                continue;

            auto pLink = pCluster->GetLink();

            DWORD dwBoneIndex = pSkinData->GetBoneCount();
            pSkinData->InfluenceNodes.push_back( pLink );
            ExportLog::LogMsg( 4, "Influence %u: %s", dwBoneIndex, pLink->GetName() );
            
            FbxAMatrix matXBindPose;
            pCluster->GetTransformLinkMatrix( matXBindPose );
            FbxAMatrix matReferenceGlobalInitPosition;
            pCluster->GetTransformMatrix(matReferenceGlobalInitPosition);
 
            FbxMatrix matBindPose = matReferenceGlobalInitPosition.Inverse() * matXBindPose;

            CaptureBindPoseMatrix( pLink, matBindPose );

            INT* pIndices = pCluster->GetControlPointIndices();
            DOUBLE* pWeights = pCluster->GetControlPointWeights();

            for( DWORD i = 0; i < dwClusterSize; ++i )
            {
                pSkinData->InsertWeight( pIndices[i], dwBoneIndex, (float)pWeights[i] );
            }
        }
    }

    return true;
}
FbxAMatrix	LoaderFbxMesh::parseTransformMatrixAssociateModel(FbxCluster* cluster, FbxMesh* mesh, FbxPose* fbxPose, FbxAMatrix globalPosition)
{
	FbxAMatrix associateGeometry;
	FbxAMatrix associateGlobalInitPosition;
	FbxAMatrix associateGlobalCurrentPosition;

	FbxAMatrix referenceGeometry;
	FbxAMatrix referenceGlobalInitPosition;
	FbxAMatrix referenceGlobalCurrentPosition;

	FbxAMatrix clusterGeometry;
	FbxAMatrix clusterGlobalInitPosition;
	FbxAMatrix clusterGlobalCurrentPosition;

	FbxTime time(0);

	cluster->GetTransformAssociateModelMatrix(associateGlobalInitPosition);
	associateGeometry = getGeometry(cluster->GetAssociateModel());
	associateGlobalInitPosition *= associateGeometry;
	associateGlobalCurrentPosition = getGlobalPosition(cluster->GetAssociateModel(), time, fbxPose, nullptr);

	cluster->GetTransformMatrix(referenceGlobalInitPosition);
	referenceGeometry = getGeometry(mesh->GetNode());
	referenceGlobalInitPosition *= referenceGeometry;
	referenceGlobalCurrentPosition = globalPosition;

	cluster->GetTransformLinkMatrix(clusterGlobalInitPosition);
	clusterGeometry = getGeometry(cluster->GetLink());
	clusterGlobalInitPosition *= clusterGeometry;
	clusterGlobalCurrentPosition = getGlobalPosition(cluster->GetLink(), time, fbxPose, nullptr);

	FbxAMatrix offsetMatrix;
	offsetMatrix = referenceGlobalInitPosition.Inverse() * associateGlobalInitPosition * associateGlobalCurrentPosition.Inverse() *
			clusterGlobalCurrentPosition * clusterGlobalInitPosition.Inverse() * referenceGlobalInitPosition;

	return offsetMatrix;
}
示例#6
0
void fbxLoader2::setBindPoseCluster(FbxNode *node)
{
	if( node->GetNodeAttribute())
	{
		switch(node->GetNodeAttribute()->GetAttributeType())
		{
		case FbxNodeAttribute::eMesh: 
			FbxMesh *mesh = node->GetMesh();

			for (int j = 0; j<mesh->GetDeformerCount(); j++)
			{
				FbxSkin *skin = (FbxSkin*) mesh->GetDeformer(j,FbxDeformer::eSkin);
				int clusters = skin->GetClusterCount();
				for(int k = 0; k<clusters; k++)
				{
					FbxCluster* cluster = skin->GetCluster(k);
					FbxNode* boneLink = cluster->GetLink();

					if(boneLink)
					{
						std::string nameLink = boneLink->GetName();
						FbxAMatrix translationM;
						FbxAMatrix invert;
						cluster->GetTransformLinkMatrix(translationM);
						cluster->GetTransformMatrix(invert);

						translationM = translationM * invert.Inverse();

						D3DXMATRIX mat = D3DXMATRIX((float)translationM.mData[0].mData[0], (float)translationM.mData[0].mData[1], (float)translationM.mData[0].mData[2], (float)translationM.mData[3].mData[0],
													(float)translationM.mData[1].mData[0], (float)translationM.mData[1].mData[1], (float)translationM.mData[1].mData[2], (float)translationM.mData[3].mData[1],
													(float)translationM.mData[2].mData[0], (float)translationM.mData[2].mData[1], (float)translationM.mData[2].mData[2], (float)translationM.mData[3].mData[2],
													0,0,0,1);

						skeleton->GetBone(skeleton->GetBoneByName(nameLink))->SetTransformation(mat);
					}
				}
			}
			break;
		}
	}
	for (int i = 0; i<node->GetChildCount(); i++)
	{
		FbxNode* child = node->GetChild(i);
		setBindPoseCluster(child);
	}
}
void FBXSceneEncoder::loadSkin(FbxMesh* fbxMesh, Model* model)
{
    const int deformerCount = fbxMesh->GetDeformerCount();
    for (int i = 0; i < deformerCount; ++i)
    {
        FbxDeformer* deformer = fbxMesh->GetDeformer(i);
        if (deformer->GetDeformerType() == FbxDeformer::eSkin)
        {
            FbxSkin* fbxSkin = FbxCast<FbxSkin>(deformer);

            MeshSkin* skin = new MeshSkin();

            vector<string> jointNames;
            vector<Node*> joints;
            vector<Matrix> bindPoses;

            const int clusterCount = fbxSkin->GetClusterCount();
            for (int j = 0; j < clusterCount; ++j)
            {
                FbxCluster* cluster = fbxSkin->GetCluster(j);
                assert(cluster);
                FbxNode* linkedNode = cluster->GetLink();
                if (linkedNode && linkedNode->GetSkeleton())
                {
                    const char* jointName = linkedNode->GetName();
                    assert(jointName);
                    jointNames.push_back(jointName);
                    Node* joint = loadNode(linkedNode);
                    assert(joint);
                    joints.push_back(joint);

                    FbxAMatrix matrix;
                    cluster->GetTransformLinkMatrix(matrix);
                    Matrix m;
                    copyMatrix(matrix.Inverse(), m);
                    bindPoses.push_back(m);
                }
            }
            skin->setJointNames(jointNames);
            skin->setJoints(joints);
            skin->setBindPoses(bindPoses);
            model->setSkin(skin);
            break;
        }
    }
}
示例#8
0
//Compute the transform matrix that the cluster will transform the vertex.
void compute_cluster_deformation(FbxAMatrix& pGlobalPosition,
                                 FbxMesh* pMesh,
                                 FbxCluster* pCluster,
                                 FbxAMatrix& pVertexTransformMatrix,
                                 FbxTime pTime,
                                 FbxPose* pPose)
{
  FbxCluster::ELinkMode lClusterMode = pCluster->GetLinkMode();

  FbxAMatrix lReferenceGlobalInitPosition;
  FbxAMatrix lReferenceGlobalCurrentPosition;
  FbxAMatrix lAssociateGlobalInitPosition;
  FbxAMatrix lAssociateGlobalCurrentPosition;
  FbxAMatrix lClusterGlobalInitPosition;
  FbxAMatrix lClusterGlobalCurrentPosition;

  FbxAMatrix lReferenceGeometry;
  FbxAMatrix lAssociateGeometry;
  FbxAMatrix lClusterGeometry;

  FbxAMatrix lClusterRelativeInitPosition;
  FbxAMatrix lClusterRelativeCurrentPositionInverse;

  if(lClusterMode == FbxCluster::eAdditive && pCluster->GetAssociateModel()) {
    pCluster->GetTransformAssociateModelMatrix(lAssociateGlobalInitPosition);
    // Geometric transform of the model
    lAssociateGeometry = get_geometry(pCluster->GetAssociateModel());
    lAssociateGlobalInitPosition *= lAssociateGeometry;
    lAssociateGlobalCurrentPosition = get_global_position(pCluster->GetAssociateModel(), pTime, pPose);

    pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
    // Multiply lReferenceGlobalInitPosition by Geometric Transformation
    lReferenceGeometry = get_geometry(pMesh->GetNode());
    lReferenceGlobalInitPosition *= lReferenceGeometry;
    lReferenceGlobalCurrentPosition = pGlobalPosition;

    // Get the link initial global position and the link current global position.
    pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
    // Multiply lClusterGlobalInitPosition by Geometric Transformation
    lClusterGeometry = get_geometry(pCluster->GetLink());
    lClusterGlobalInitPosition *= lClusterGeometry;
    lClusterGlobalCurrentPosition = get_global_position(pCluster->GetLink(), pTime, pPose);

    // Compute the shift of the link relative to the reference.
    //ModelM-1 * AssoM * AssoGX-1 * LinkGX * LinkM-1*ModelM
    pVertexTransformMatrix = lReferenceGlobalInitPosition.Inverse() * lAssociateGlobalInitPosition * lAssociateGlobalCurrentPosition.Inverse() *
                             lClusterGlobalCurrentPosition * lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
  } else {
    pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
    lReferenceGlobalCurrentPosition = pGlobalPosition;
    // Multiply lReferenceGlobalInitPosition by Geometric Transformation
    lReferenceGeometry = get_geometry(pMesh->GetNode());
    lReferenceGlobalInitPosition *= lReferenceGeometry;

    // Get the link initial global position and the link current global position.
    pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
    lClusterGlobalCurrentPosition = get_global_position(pCluster->GetLink(), pTime, pPose);

    // Compute the initial position of the link relative to the reference.
    lClusterRelativeInitPosition = lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;

    // Compute the current position of the link relative to the reference.
    lClusterRelativeCurrentPositionInverse = lReferenceGlobalCurrentPosition.Inverse() * lClusterGlobalCurrentPosition;

    // Compute the shift of the link relative to the reference.
    pVertexTransformMatrix = lClusterRelativeCurrentPositionInverse * lClusterRelativeInitPosition;
  }
}
void MeshImporter::LoadWeight(FbxMesh* fbxMesh, MeshEntry* mesh)
{
	int numSkin = fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
	
	if (numSkin == 0)
	{
		return;
	}

	assert(numSkin == 1);

	// Assume only one deformer
	FbxSkin* fbxSkin = static_cast<FbxSkin*>(fbxMesh->GetDeformer(0, FbxDeformer::eSkin));
	int numCluster = fbxSkin->GetClusterCount();
	int numControlPoints = fbxMesh->GetControlPointsCount();
	vector<VertexWeight> tmpWeightList(numControlPoints);

	for (int i = 0; i < numCluster; i++)
	{
		FbxCluster* fbxCluster = fbxSkin->GetCluster(i);

		if (!fbxCluster->GetLink())
		{
			continue;
		}

		unsigned int boneIndex = model->skeleton->bones.size();

		assert(fbxCluster->GetLinkMode() == FbxCluster::eNormalize);

		// Read skeleton bones data (transformation matrix of each bone)
		string boneName(fbxCluster->GetLink()->GetName());

		if (!model->skeleton->FindBoneByName(boneName))
		{
			if (boneIndex >= MAXBONE)
			{
				PrintTab("Too many bones to load!!");
			}
			else
			{
				// Read weights of each vertex
				int numIndexInCluster = fbxCluster->GetControlPointIndicesCount();
				int* indicesInCluster = fbxCluster->GetControlPointIndices();
				double* weights = fbxCluster->GetControlPointWeights();

				for (int j = 0; j < numIndexInCluster; j++)
				{
					tmpWeightList[indicesInCluster[j]].AddBoneData(boneIndex, weights[j]);
				}

				// Normalize weights
				/*for (int inVert = 0; inVert < tmpWeightList.size(); inVert++)
				{
					tmpWeightList[inVert].Normalize();
				}*/

				// Read animation bone matrix
				FbxAMatrix fbxGlobalBoneBaseMatrix;// = fbxCluster->GetLink()->EvaluateGlobalTransform().Inverse().Transpose();

				FbxAMatrix referenceGlobalInitPosition;
				FbxAMatrix clusterGlobalInitPosition;

				fbxCluster->GetTransformMatrix(referenceGlobalInitPosition);
				fbxCluster->GetTransformLinkMatrix(clusterGlobalInitPosition);

				fbxGlobalBoneBaseMatrix = clusterGlobalInitPosition.Inverse() * referenceGlobalInitPosition;

				// To be considered when importing Maya fbx model
				//FbxAMatrix geoMatrix = GetTransformMatrix(fbxCluster->GetLink());

				Bone bone;
				bone.name = boneName;
				bone.boneIndex = boneIndex;
				bone.fbxNode = fbxCluster->GetLink();
				bone.globalBindposeInverseMatrix = fbxGlobalBoneBaseMatrix;

				model->skeleton->bones.push_back(bone);
			}
		}
	}

	// Deployed in the index
	for (unsigned int i = 0; i < mesh->numVertices; i++)
	{
		mesh->vertices[i].boneIndices.x = tmpWeightList[mesh->indices[i]].boneWeight[0].first;
		mesh->vertices[i].boneIndices.y = tmpWeightList[mesh->indices[i]].boneWeight[1].first;
		mesh->vertices[i].boneIndices.z = tmpWeightList[mesh->indices[i]].boneWeight[2].first;
		mesh->vertices[i].boneIndices.w = tmpWeightList[mesh->indices[i]].boneWeight[3].first;

		mesh->vertices[i].weights.x = tmpWeightList[mesh->indices[i]].boneWeight[0].second;
		mesh->vertices[i].weights.y = tmpWeightList[mesh->indices[i]].boneWeight[1].second;
		mesh->vertices[i].weights.z = tmpWeightList[mesh->indices[i]].boneWeight[2].second;
		mesh->vertices[i].weights.w = tmpWeightList[mesh->indices[i]].boneWeight[3].second;
	}
}
示例#10
0
//FbxAMatrix ComputeTotalMatrix(FbxNode* node, FbxTime time = FBXSDK_TIME_INFINITE){
//
//}
SkinInfo::SkinInfo(FbxNode* meshNode) :
_node(meshNode), _mesh(meshNode->GetMesh()), _skin(nullptr)
{
	int deformerCount = _mesh->GetDeformerCount();
	for (auto ix = 0; ix < deformerCount; ++ix){
		auto skin = reinterpret_cast<FbxSkin*>(_mesh->GetDeformer(ix, FbxDeformer::eSkin));
		if (skin){
			_skin = skin;
			break;
		}
	}
	if (!_skin){
		return;
	}

	std::vector<FbxPose*> bindPoses;
	auto poseCount = _node->GetScene()->GetPoseCount();
	for (auto ix = 0; ix < poseCount; ++ix){
		auto pose = _node->GetScene()->GetPose(ix);
		if (pose->IsBindPose()){
			bindPoses.push_back(pose);
		}
	}

	std::vector<FbxNode*> unsortedFlatListOfNodes;
	std::vector<FbxCluster*> unsortedFlatListOfClusters;
	auto clusterCount = _skin->GetClusterCount();
	for (auto ix = 0; ix < clusterCount; ++ix){
		auto cluster = _skin->GetCluster(ix);
		if (!cluster)
		{
			std::cout << "Invalid skin" << std::endl;
			_skin = nullptr;
			return;
		}
		auto linkNode = cluster->GetLink();
		if (!linkNode){
			std::cout << "Invalid skin" << std::endl;
			_skin = nullptr;
			return;
		}
		unsortedFlatListOfClusters.push_back(cluster);
		unsortedFlatListOfNodes.push_back(linkNode);
	}

	ComputeBoneHierarchy(unsortedFlatListOfNodes, unsortedFlatListOfClusters, _bones, _fbxClusterIndexToBoneIndex, _controlPointToBoneIndicesAndWeights);
	auto deformType = _skin->GetDeformerType();

	auto geometryTransform = GetGeometryTransformation(meshNode);
	// compute all bones global inverse and global matrix
	for (auto& bone : _bones){
		FbxAMatrix transformMatrix;
		FbxAMatrix transformLinkMatrix;
		FbxMatrix globalBindposeInverseMatrix;

		bone.cluster->GetTransformMatrix(transformMatrix);	// The transformation of the mesh at binding time
		bone.cluster->GetTransformLinkMatrix(transformLinkMatrix);	// The transformation of the cluster(joint) at binding time from joint space to world space
		/*for (auto pose : bindPoses){
			auto inPoseIndex = pose->Find(bone.linkNode);
			if (inPoseIndex >= 0){
				auto tempMat = pose->GetMatrix(inPoseIndex);
				transformLinkMatrix = *(FbxAMatrix*) (double*) &tempMat;
				break;
			}
		}*/
		globalBindposeInverseMatrix = FbxMatrix(transformLinkMatrix.Inverse()) * FbxMatrix(transformMatrix) * geometryTransform;


		bone.matrixGlobalBindPose = ConvertToBabylonCoordinateSystem(globalBindposeInverseMatrix.Inverse());
	

		if (bone.parentBoneIndex == -1){
			bone.matrixLocalBindPose = bone.matrixGlobalBindPose;
		}
		else{
			bone.matrixLocalBindPose =
				_bones[bone.parentBoneIndex].matrixGlobalBindPose.Inverse()* bone.matrixGlobalBindPose;
			
		}
	}


	// compute anim
	auto animStack = _node->GetScene()->GetCurrentAnimationStack();
	FbxString animStackName = animStack->GetName();
	//FbxTakeInfo* takeInfo = node->GetScene()->GetTakeInfo(animStackName);
	auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
	auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
	auto startFrame = animStack->GetLocalTimeSpan().GetStart().GetFrameCount(animTimeMode);
	auto endFrame = animStack->GetLocalTimeSpan().GetStop().GetFrameCount(animTimeMode);
	auto animLengthInFrame = endFrame - startFrame + 1;


	for (auto ix = 0; ix < animLengthInFrame; ix++){
		FbxTime currTime;
		currTime.SetFrame(startFrame + ix, animTimeMode);


		auto currTransformOffset = FbxMatrix(meshNode->EvaluateGlobalTransform(currTime)) * geometryTransform;
		auto currTransformOffsetInverse = currTransformOffset.Inverse();

		// compute global transform and local
		for (auto& bone : _bones){
			BoneAnimKeyFrame kf;
			kf.frame = ix;
			kf.matrixGlobal = ConvertToBabylonCoordinateSystem(currTransformOffsetInverse*bone.linkNode->EvaluateGlobalTransform(currTime));
			


			if (bone.parentBoneIndex == -1){
				kf.matrixLocal = kf.matrixGlobal;
			}
			else{
				auto& parentBone = _bones[bone.parentBoneIndex];
				
				kf.matrixLocal = //bone.matrixLocalBindPose;
					parentBone.keyFrames[parentBone.keyFrames.size() - 1].matrixGlobal.Inverse()* kf.matrixGlobal;

			}


			bone.keyFrames.push_back(kf);
		}

	}
}
示例#11
0
//Compute the transform matrix that the cluster will transform the vertex.
void ofxFBXMesh::computeClusterDeformation(FbxAMatrix& pGlobalPosition,
                                           FbxMesh* pMesh,
                                           FbxCluster* pCluster,
                                           FbxAMatrix& pVertexTransformMatrix,
                                           FbxTime pTime,
                                           FbxPose* pPose) {
    FbxCluster::ELinkMode lClusterMode = pCluster->GetLinkMode();
    
	FbxAMatrix lReferenceGlobalInitPosition;
	FbxAMatrix lReferenceGlobalCurrentPosition;
	FbxAMatrix lAssociateGlobalInitPosition;
	FbxAMatrix lAssociateGlobalCurrentPosition;
	FbxAMatrix lClusterGlobalInitPosition;
	FbxAMatrix lClusterGlobalCurrentPosition;
    
	FbxAMatrix lReferenceGeometry;
	FbxAMatrix lAssociateGeometry;
	FbxAMatrix lClusterGeometry;
    
	FbxAMatrix lClusterRelativeInitPosition;
	FbxAMatrix lClusterRelativeCurrentPositionInverse;
    
    ofxFBXBone* bone        = NULL;
    ofxFBXCluster* cluster  = NULL; 
    
    if(pCluster->GetLink()) {
        FbxNode* boneNode = pCluster->GetLink();
        if(boneNode->GetUserDataPtr()) {
            bone = static_cast<ofxFBXBone *>(boneNode->GetUserDataPtr());
        }
    }
    
    if(bone != NULL) {
        if(pCluster->GetUserDataPtr()) {
            cluster = static_cast<ofxFBXCluster *>(pCluster->GetUserDataPtr());
//            cluster->update( pTime, pPose );
        }
    }
    
    if( bone != NULL && cluster != NULL ) {
//        cout << "We have cached cluster and bone! " << bone->getName() << endl;
        pVertexTransformMatrix = cluster->preTrans * bone->fbxTransform * cluster->postTrans;
    } else {
        // nothing is setup for the control of the bones, so we are just doing animation
        // right now, can't do animation and control the bones at the same time.
        if (lClusterMode == FbxCluster::eAdditive && pCluster->GetAssociateModel()) {
            pCluster->GetTransformAssociateModelMatrix(lAssociateGlobalInitPosition);
            // Geometric transform of the model
            lAssociateGeometry = GetGeometry(pCluster->GetAssociateModel());
            lAssociateGlobalInitPosition *= lAssociateGeometry;
            lAssociateGlobalCurrentPosition = GetGlobalPosition(pCluster->GetAssociateModel(), pTime, pPose);
            
            pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
            // Multiply lReferenceGlobalInitPosition by Geometric Transformation
            lReferenceGeometry = GetGeometry(pMesh->GetNode());
            lReferenceGlobalInitPosition *= lReferenceGeometry;
            lReferenceGlobalCurrentPosition = pGlobalPosition;
            
            // Get the link initial global position and the link current global position.
            pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
            // Multiply lClusterGlobalInitPosition by Geometric Transformation
            lClusterGeometry = GetGeometry(pCluster->GetLink());
            lClusterGlobalInitPosition *= lClusterGeometry;
            lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), pTime, pPose);
            
            // Compute the shift of the link relative to the reference.
            //ModelM-1 * AssoM * AssoGX-1 * LinkGX * LinkM-1*ModelM
            pVertexTransformMatrix = lReferenceGlobalInitPosition.Inverse() * lAssociateGlobalInitPosition * lAssociateGlobalCurrentPosition.Inverse() *
            lClusterGlobalCurrentPosition * lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
        } else {
            pCluster->GetTransformMatrix(lReferenceGlobalInitPosition);
            lReferenceGlobalCurrentPosition = pGlobalPosition;
            // Multiply lReferenceGlobalInitPosition by Geometric Transformation
            lReferenceGeometry = GetGeometry(pMesh->GetNode());
            lReferenceGlobalInitPosition *= lReferenceGeometry;
            
            // Get the link initial global position and the link current global position.
            pCluster->GetTransformLinkMatrix(lClusterGlobalInitPosition);
            lClusterGlobalCurrentPosition = GetGlobalPosition(pCluster->GetLink(), pTime, pPose);
            
            // Compute the initial position of the link relative to the reference.
            lClusterRelativeInitPosition = lClusterGlobalInitPosition.Inverse() * lReferenceGlobalInitPosition;
            
            // Compute the current position of the link relative to the reference.
            lClusterRelativeCurrentPositionInverse = lReferenceGlobalCurrentPosition.Inverse() * lClusterGlobalCurrentPosition;
            
            // Compute the shift of the link relative to the reference.
            pVertexTransformMatrix = lClusterRelativeCurrentPositionInverse * lClusterRelativeInitPosition;
        }
    }
}
示例#12
0
//===============================================================================================================================
void FBXLoader::LoadJointsAndAnimation(FbxNode* inNode)
{
	// This is how each subset gets its bone/joint for animation
	FBXSubsets* subset = mSubsets[iCurrentSubset];
	
	FbxMesh* mesh = inNode->GetMesh();
	
	uint32 numOfDeformers = mesh->GetDeformerCount();
	
	FbxAMatrix geomTrans = ZShadeSandboxMesh::FBXHelper::GetGeometryTransformation(inNode);
	
	// A deformer contains clusters.
	// A cluster contains a link, which is a joint.
	// Normally, There is only one deformer in a mesh but Maya has many types.
	for (uint32 deformerIndex = 0; deformerIndex < numOfDeformers; ++deformerIndex)
	{
		// Lets see if this deformer is a skin
		FbxSkin* skin = reinterpret_cast<FbxSkin*>(mesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
		
		if (!skin) continue;
		
		uint32 numOfClusters = skin->GetClusterCount();
		
		for (uint32 clusterIndex = 0; clusterIndex < numOfClusters; ++clusterIndex)
		{
			FbxCluster* cluster = skin->GetCluster(clusterIndex);
			
			string jointName = cluster->GetLink()->GetName();
			uint32 jointIndex = FindJointIndexUsingName(jointName);
			
			subset->mJoints.push_back(jointIndex);
			
			FbxAMatrix transform;
			FbxAMatrix transformLink;
			FbxAMatrix globalBindposeInverse;
			
			// The transformation of the mesh at binding time
			cluster->GetTransformMatrix(transform);
			
			// The transformation of the cluster (joint) at binding time from joint space to world space
			cluster->GetTransformLinkMatrix(transformLink);
			
			globalBindposeInverse = transformLink.Inverse() * transform * geomTrans;
			
			
			// Update skeletal information
			mSkeleton.joints[jointIndex].globalBindposeInverse = globalBindposeInverse;
			mSkeleton.joints[jointIndex].node = cluster->GetLink();
			
			// Associate each joint with the control points it affects
			uint32 numOfIndices = cluster->GetControlPointIndicesCount();
			
			for (uint32 i = 0; i < numOfIndices; ++i)
			{
				ZShadeSandboxMesh::BlendingIndexWeightPair currBlendingIndexWeightPair;
				currBlendingIndexWeightPair.blendingIndex = jointIndex;
				currBlendingIndexWeightPair.blendingWeight = cluster->GetControlPointWeights()[i];
				mControlPoints[cluster->GetControlPointIndices()[i]]->blendingInfo.push_back(currBlendingIndexWeightPair);
			}
			
			// Animation information
			FbxAnimStack* animStack = m_pFbxScene->GetSrcObject<FbxAnimStack>(0);
			FbxString animStackName = animStack->GetName();
			mAnimationName = animStackName.Buffer();
			FbxTakeInfo* takeInfo = m_pFbxScene->GetTakeInfo(animStackName);
			FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
			FbxTime end = takeInfo->mLocalTimeSpan.GetStop();
			mAnimationLength = end.GetFrameCount(FbxTime::eFrames24) - start.GetFrameCount(FbxTime::eFrames24) + 1;
			FBXKeyframe** anim = &mSkeleton.joints[jointIndex].animation;
			
			for (FbxLongLong i = start.GetFrameCount(FbxTime::eFrames24); i <= end.GetFrameCount(FbxTime::eFrames24); ++i)
			{
				FbxTime time;
				time.SetFrame(i, FbxTime::eFrames24);
				*anim = new FBXKeyframe();
				(*anim)->frameNum = i;
				FbxAMatrix currentTransformOffset = inNode->EvaluateGlobalTransform(time) * geomTrans;
				(*anim)->globalTransform = currentTransformOffset.Inverse() * cluster->GetLink()->EvaluateGlobalTransform(time);
				anim = &((*anim)->next);
			}
		}
	}
	
	// Some control points have less than 4 joints
	// For a normal renderer, there are usually 4 joints
	ZShadeSandboxMesh::BlendingIndexWeightPair currBlendingIndexWeightPair;
	currBlendingIndexWeightPair.blendingIndex = 0;
	currBlendingIndexWeightPair.blendingWeight = 0;
	for (auto itr = mControlPoints.begin(); itr != mControlPoints.end(); ++itr)
	{
		for (unsigned int i = itr->second->blendingInfo.size(); i <= 4; ++i)
		{
			itr->second->blendingInfo.push_back(currBlendingIndexWeightPair);
		}
	}
}
示例#13
0
void ParseMesh( FbxNode* pNode, FbxMesh* pFbxMesh, ExportFrame* pParentFrame, bool bSubDProcess, const CHAR* strSuffix )
{
    if( !g_pScene->Settings().bExportMeshes )
        return;

    if( !pNode || !pFbxMesh )
        return;

    const CHAR* strName = pFbxMesh->GetName();
    if( !strName || strName[0] == '\0' )
        strName = pParentFrame->GetName().SafeString();

    if( !strSuffix )
    {
        strSuffix = "";
    }
    CHAR strDecoratedName[512];
    sprintf_s( strDecoratedName, "%s_%s%s", g_pScene->Settings().strMeshNameDecoration, strName, strSuffix );
    ExportMesh* pMesh = new ExportMesh( strDecoratedName );
    pMesh->SetDCCObject( pFbxMesh );

    bool bSmoothMesh = false;

    auto Smoothness = pFbxMesh->GetMeshSmoothness();
    if( Smoothness != FbxMesh::eHull && g_pScene->Settings().bConvertMeshesToSubD )
    {
        bSubDProcess = true;
        bSmoothMesh = true;
    }

    ExportLog::LogMsg( 2, "Parsing %s mesh \"%s\", renamed to \"%s\"", bSmoothMesh ? "smooth" : "poly", strName, strDecoratedName );

    SkinData skindata;
    bool bSkinnedMesh = ParseMeshSkinning( pFbxMesh, &skindata );
    if( bSkinnedMesh )
    {
        DWORD dwBoneCount = skindata.GetBoneCount();
        for( DWORD i = 0; i < dwBoneCount; ++i )
        {
            pMesh->AddInfluence( skindata.InfluenceNodes[i]->GetName() );
        }
    }

    bool bExportColors = g_pScene->Settings().bExportColors;
    pMesh->SetVertexColorCount( 0 );

    // Vertex normals and tangent spaces
    if( !g_pScene->Settings().bExportNormals )
    {
        pMesh->SetVertexNormalCount( 0 );
    }
    else if( g_pScene->Settings().bComputeVertexTangentSpace )
    {
        if( g_pScene->Settings().bExportBinormal )
            pMesh->SetVertexNormalCount( 3 );
        else
            pMesh->SetVertexNormalCount( 2 );
    }
    else
    {
        pMesh->SetVertexNormalCount( 1 );
    }

    DWORD dwLayerCount = pFbxMesh->GetLayerCount();
    ExportLog::LogMsg( 4, "%u layers in FBX mesh", dwLayerCount );

    if (!dwLayerCount || !pFbxMesh->GetLayer(0)->GetNormals())
    {
        ExportLog::LogMsg( 4, "Generating normals..." );
        pFbxMesh->InitNormals();
#if (FBXSDK_VERSION_MAJOR >= 2015)
        pFbxMesh->GenerateNormals();
#else
        pFbxMesh->ComputeVertexNormals();
#endif
    }

    DWORD dwVertexColorCount = 0;
    FbxLayerElementVertexColor* pVertexColorSet = nullptr;
    DWORD dwUVSetCount = 0;
    FbxLayerElementMaterial* pMaterialSet = nullptr;
    std::vector<FbxLayerElementUV*> VertexUVSets;
    for( DWORD dwLayerIndex = 0; dwLayerIndex < dwLayerCount; ++dwLayerIndex )
    {
        if( pFbxMesh->GetLayer(dwLayerIndex)->GetVertexColors() && bExportColors )
        {
            if( dwVertexColorCount == 0 )
            {
                dwVertexColorCount++;
                pVertexColorSet = pFbxMesh->GetLayer(dwLayerIndex)->GetVertexColors();
            }
            else
            {
                ExportLog::LogWarning( "Only one vertex color set is allowed; ignoring additional vertex color sets." );
            }
        }
        if( pFbxMesh->GetLayer(dwLayerIndex)->GetUVs() )
        {
            dwUVSetCount++;
            VertexUVSets.push_back( pFbxMesh->GetLayer(dwLayerIndex)->GetUVs() );
        }
        if( pFbxMesh->GetLayer(dwLayerIndex)->GetMaterials() )
        {
            if( pMaterialSet )
            {
                ExportLog::LogWarning( "Multiple material layers detected on mesh %s.  Some will be ignored.", pMesh->GetName().SafeString() );
            }
            pMaterialSet = pFbxMesh->GetLayer(dwLayerIndex)->GetMaterials();
        }
    }

    std::vector<ExportMaterial*> MaterialList;
    for( int dwMaterial = 0; dwMaterial < pNode->GetMaterialCount(); ++dwMaterial )
    {
        auto pMat = pNode->GetMaterial( dwMaterial );
        if ( !pMat )
            continue;

        auto pMaterial = ParseMaterial( pMat );
        MaterialList.push_back( pMaterial );
    }

    ExportLog::LogMsg( 4, "Found %u UV sets", dwUVSetCount );
    dwUVSetCount = std::min<DWORD>( dwUVSetCount, g_pScene->Settings().iMaxUVSetCount );
    ExportLog::LogMsg( 4, "Using %u UV sets", dwUVSetCount );

    pMesh->SetVertexColorCount( dwVertexColorCount );
    pMesh->SetVertexUVCount( dwUVSetCount );
    // TODO: Does FBX only support 2D texture coordinates?
    pMesh->SetVertexUVDimension( 2 );

    DWORD dwMeshOptimizationFlags = 0;
    if( g_pScene->Settings().bCompressVertexData )
        dwMeshOptimizationFlags |= ExportMesh::COMPRESS_VERTEX_DATA;

    DWORD dwPolyCount = pFbxMesh->GetPolygonCount();
    // Assume that polys are usually quads.
    g_MeshTriangleAllocator.SetSizeHint( dwPolyCount * 2 );

    DWORD dwVertexCount = pFbxMesh->GetControlPointsCount();
    auto pVertexPositions = pFbxMesh->GetControlPoints();

    if( bSkinnedMesh )
    {
        assert( skindata.dwVertexCount == dwVertexCount );
    }
    
    ExportLog::LogMsg( 4, "%u vertices, %u polygons", dwVertexCount, dwPolyCount );

    DWORD dwNonConformingSubDPolys = 0;

    // Compute total transformation
    FbxAMatrix vertMatrix;
    FbxAMatrix normMatrix;
    {
        auto trans = pNode->GetGeometricTranslation( FbxNode::eSourcePivot );
        auto rot = pNode->GetGeometricRotation( FbxNode::eSourcePivot );
        auto scale = pNode->GetGeometricScaling( FbxNode::eSourcePivot );

        FbxAMatrix geom;
        geom.SetT( trans );
        geom.SetR( rot );
        geom.SetS( scale );

        if ( g_pScene->Settings().bExportAnimations || !g_pScene->Settings().bApplyGlobalTrans )
        {
            vertMatrix = geom;
        }
        else
        {
            auto global = pNode->EvaluateGlobalTransform();
            vertMatrix = global * geom;
        }

        // Calculate the normal transform matrix (inverse-transpose)
        normMatrix = vertMatrix;
        normMatrix = normMatrix.Inverse();
        normMatrix = normMatrix.Transpose();
    }

    const bool bInvertTexVCoord = g_pScene->Settings().bInvertTexVCoord;
    
    // Loop over polygons.
    DWORD basePolyIndex = 0;
    for( DWORD dwPolyIndex = 0; dwPolyIndex < dwPolyCount; ++dwPolyIndex )
    {
        // Triangulate each polygon into one or more triangles.
        DWORD dwPolySize = pFbxMesh->GetPolygonSize( dwPolyIndex );
        assert( dwPolySize >= 3 );
        DWORD dwTriangleCount = dwPolySize - 2;
        assert( dwTriangleCount > 0 );

        if( dwPolySize > 4 )
        {
            ++dwNonConformingSubDPolys;
        }

        DWORD dwMaterialIndex = 0;
        if( pMaterialSet )
        {
            switch( pMaterialSet->GetMappingMode() )
            {
            case FbxLayerElement::eByPolygon:
                switch( pMaterialSet->GetReferenceMode() )
                {
                case FbxLayerElement::eDirect:
                    dwMaterialIndex = dwPolyIndex;
                    break;
                case FbxLayerElement::eIndex:
                case FbxLayerElement::eIndexToDirect:
                    dwMaterialIndex = pMaterialSet->GetIndexArray().GetAt( dwPolyIndex );
                    break;
                }
            }
        }

        DWORD dwCornerIndices[3];
        // Loop over triangles in the polygon.
        for( DWORD dwTriangleIndex = 0; dwTriangleIndex < dwTriangleCount; ++dwTriangleIndex )
        {
            dwCornerIndices[0] = pFbxMesh->GetPolygonVertex( dwPolyIndex, 0 );
            dwCornerIndices[1] = pFbxMesh->GetPolygonVertex( dwPolyIndex, dwTriangleIndex + 1 );
            dwCornerIndices[2] = pFbxMesh->GetPolygonVertex( dwPolyIndex, dwTriangleIndex + 2 );

            //ExportLog::LogMsg( 4, "Poly %d Triangle %d: %d %d %d", dwPolyIndex, dwTriangleIndex, dwCornerIndices[0], dwCornerIndices[1], dwCornerIndices[2] );

            FbxVector4 vNormals[3];
            ZeroMemory( vNormals, 3 * sizeof(FbxVector4) );
            INT iPolyIndex = static_cast<INT>( dwPolyIndex );
            INT iVertIndex[3] = { 0, static_cast<INT>( dwTriangleIndex + 1 ), static_cast<INT>( dwTriangleIndex + 2 ) };
            pFbxMesh->GetPolygonVertexNormal( iPolyIndex, iVertIndex[0], vNormals[0] );
            pFbxMesh->GetPolygonVertexNormal( iPolyIndex, iVertIndex[1], vNormals[1] );
            pFbxMesh->GetPolygonVertexNormal( iPolyIndex, iVertIndex[2], vNormals[2] );

            // Build the raw triangle.
            auto pTriangle = g_MeshTriangleAllocator.GetNewTriangle();

            // Store polygon index
            pTriangle->PolygonIndex = static_cast<INT>( dwPolyIndex );

            // Store material subset index
            pTriangle->SubsetIndex = dwMaterialIndex;

            for( DWORD dwCornerIndex = 0; dwCornerIndex < 3; ++dwCornerIndex )
            {
                const DWORD& dwDCCIndex = dwCornerIndices[dwCornerIndex];
                // Store DCC vertex index (this helps the mesh reduction/VB generation code)
                pTriangle->Vertex[dwCornerIndex].DCCVertexIndex = dwDCCIndex;

                // Store vertex position
                auto finalPos = vertMatrix.MultT( pVertexPositions[dwDCCIndex] );

                pTriangle->Vertex[dwCornerIndex].Position.x = (float)finalPos.mData[0];
                pTriangle->Vertex[dwCornerIndex].Position.y = (float)finalPos.mData[1];
                pTriangle->Vertex[dwCornerIndex].Position.z = (float)finalPos.mData[2];

                // Store vertex normal
                auto finalNorm = vNormals[dwCornerIndex];
                finalNorm.mData[3] = 0.0;
                finalNorm = normMatrix.MultT( finalNorm );
                finalNorm.Normalize();

                pTriangle->Vertex[dwCornerIndex].Normal.x = (float)finalNorm.mData[0];
                pTriangle->Vertex[dwCornerIndex].Normal.y = (float)finalNorm.mData[1];
                pTriangle->Vertex[dwCornerIndex].Normal.z = (float)finalNorm.mData[2];

                // Store UV sets
                for( DWORD dwUVIndex = 0; dwUVIndex < dwUVSetCount; ++dwUVIndex )
                {
                    // Crack apart the FBX dereferencing system for UV coordinates
                    FbxLayerElementUV* pUVSet = VertexUVSets[dwUVIndex];
                    FbxVector2 Value( 0, 0 );
                    switch( pUVSet->GetMappingMode() )
                    {
                    case FbxLayerElement::eByControlPoint:
                        switch (pUVSet->GetReferenceMode())
                        {
                        case FbxLayerElement::eDirect:
                            Value = pUVSet->GetDirectArray().GetAt(dwDCCIndex);
                            break;

                        case FbxLayerElement::eIndex:
                        case FbxLayerElement::eIndexToDirect:
                            {
                                int iUVIndex = pUVSet->GetIndexArray().GetAt(dwDCCIndex);
                                Value = pUVSet->GetDirectArray().GetAt(iUVIndex);
                            }
                            break;
                        }
                        break;

                    case FbxLayerElement::eByPolygonVertex:
                        switch (pUVSet->GetReferenceMode())
                        {
                        case FbxLayerElement::eDirect:
                            Value = pUVSet->GetDirectArray().GetAt( basePolyIndex + iVertIndex[dwCornerIndex] );
                            break;

                        case FbxLayerElement::eIndex:
                        case FbxLayerElement::eIndexToDirect:
                            {
                                int iUVIndex = pUVSet->GetIndexArray().GetAt( basePolyIndex + iVertIndex[dwCornerIndex] );
#ifdef _DEBUG
                                if (!dwUVIndex)
                                {
                                    // Warning: pFbxMesh->GetTextureUVIndex only works for the first layer of the mesh
                                    int iUVIndex2 = pFbxMesh->GetTextureUVIndex(iPolyIndex, iVertIndex[dwCornerIndex]);
                                    assert(iUVIndex == iUVIndex2);
                                }
#endif
                                Value = pUVSet->GetDirectArray().GetAt( iUVIndex );
                            }
                            break;
                        }
                        break;
                    }

                    // Store a single UV set
                    pTriangle->Vertex[dwCornerIndex].TexCoords[dwUVIndex].x = (float)Value.mData[0];
                    if( bInvertTexVCoord )
                    {
                        pTriangle->Vertex[dwCornerIndex].TexCoords[dwUVIndex].y = 1.0f - (float) Value.mData[1];
                    }
                    else
                    {
                        pTriangle->Vertex[dwCornerIndex].TexCoords[dwUVIndex].y = (float)Value.mData[1];
                    }
                }

                // Store vertex color set
                if( dwVertexColorCount > 0 && pVertexColorSet )
                {
                    // Crack apart the FBX dereferencing system for Color coordinates
                    FbxColor Value( 1, 1, 1, 1 );
                    switch( pVertexColorSet->GetMappingMode() )
                    {
                    case FbxLayerElement::eByControlPoint:
                        switch( pVertexColorSet->GetReferenceMode() )
                        {
                        case FbxLayerElement::eDirect:
                            Value = pVertexColorSet->GetDirectArray().GetAt( dwDCCIndex );
                            break;
                        case FbxLayerElement::eIndex:
                        case FbxLayerElement::eIndexToDirect:
                            {
                                int iColorIndex = pVertexColorSet->GetIndexArray().GetAt(dwDCCIndex);
                                Value = pVertexColorSet->GetDirectArray().GetAt(iColorIndex);
                            }
                            break;
                        }
                        break;

                    case FbxLayerElement::eByPolygonVertex:
                        switch( pVertexColorSet->GetReferenceMode() )
                        {
                        case FbxLayerElement::eDirect:
                            Value = pVertexColorSet->GetDirectArray().GetAt( basePolyIndex + iVertIndex[dwCornerIndex] );
                            break;
                        case FbxLayerElement::eIndex:
                        case FbxLayerElement::eIndexToDirect:
                            {
                                int iColorIndex = pVertexColorSet->GetIndexArray().GetAt( basePolyIndex + iVertIndex[dwCornerIndex] );
                                Value = pVertexColorSet->GetDirectArray().GetAt(iColorIndex);
                            }
                            break;
                        }
                        break;
                    }

                    // Store a single vertex color set
                    pTriangle->Vertex[dwCornerIndex].Color.x = (float)Value.mRed;
                    pTriangle->Vertex[dwCornerIndex].Color.y = (float)Value.mGreen;
                    pTriangle->Vertex[dwCornerIndex].Color.z = (float)Value.mBlue;
                    pTriangle->Vertex[dwCornerIndex].Color.w = (float)Value.mAlpha;
                }

                // Store skin weights
                if( bSkinnedMesh )
                {
                    memcpy( &pTriangle->Vertex[dwCornerIndex].BoneIndices, skindata.GetIndices( dwDCCIndex ), sizeof(PackedVector::XMUBYTE4) );
                    memcpy( &pTriangle->Vertex[dwCornerIndex].BoneWeights, skindata.GetWeights( dwDCCIndex ), sizeof(XMFLOAT4) );
                }
            }

            // Add raw triangle to the mesh.
            pMesh->AddRawTriangle( pTriangle );
        }

        basePolyIndex += dwPolySize;
    }

    if( bSubDProcess )
    {
        dwMeshOptimizationFlags |= ExportMesh::FORCE_SUBD_CONVERSION;
    }

    if ( g_pScene->Settings().bCleanMeshes )
    {
        dwMeshOptimizationFlags |= ExportMesh::CLEAN_MESHES;
    }

    if ( g_pScene->Settings().bOptimizeVCache )
    {
        dwMeshOptimizationFlags |= ExportMesh::CLEAN_MESHES | ExportMesh::VCACHE_OPT;
    }

    pMesh->Optimize( dwMeshOptimizationFlags );

    ExportModel* pModel = new ExportModel( pMesh );
    size_t dwMaterialCount = MaterialList.size();
    if( !pMesh->GetSubDMesh() )
    {
        for( size_t dwSubset = 0; dwSubset < dwMaterialCount; ++dwSubset )
        {
            auto pMaterial = MaterialList[dwSubset];
            auto pSubset = pMesh->GetSubset( dwSubset );
            CHAR strUniqueSubsetName[100];
            sprintf_s( strUniqueSubsetName, "subset%Iu_%s", dwSubset, pMaterial->GetName().SafeString() );
            pSubset->SetName( strUniqueSubsetName );
            pModel->SetSubsetBinding( pSubset->GetName(), pMaterial );
        }
    }
    else
    {
        auto pSubDMesh = pMesh->GetSubDMesh();
        size_t dwSubsetCount = pSubDMesh->GetSubsetCount();
        for( size_t dwSubset = 0; dwSubset < dwSubsetCount; ++dwSubset )
        {
            auto pSubset = pSubDMesh->GetSubset( dwSubset );
            assert( pSubset != nullptr );
            assert( pSubset->iOriginalMeshSubset < static_cast<INT>( dwMaterialCount ) );
            auto pMaterial = MaterialList[pSubset->iOriginalMeshSubset];
            CHAR strUniqueSubsetName[100];
            sprintf_s( strUniqueSubsetName, "subset%Iu_%s", dwSubset, pMaterial->GetName().SafeString() );
            pSubset->Name = strUniqueSubsetName;
            pModel->SetSubsetBinding( pSubset->Name, pMaterial, true );
        }
    }

    if( bSubDProcess && ( dwNonConformingSubDPolys > 0 ) )
    {
        ExportLog::LogWarning( "Encountered %u polygons with 5 or more sides in mesh \"%s\", which were subdivided into quad and triangle patches.  Mesh appearance may have been affected.", dwNonConformingSubDPolys, pMesh->GetName().SafeString() );
    }

    // update statistics
    if( pMesh->GetSubDMesh() )
    {
        g_pScene->Statistics().SubDMeshesProcessed++;
        g_pScene->Statistics().SubDQuadsProcessed += pMesh->GetSubDMesh()->GetQuadPatchCount();
        g_pScene->Statistics().SubDTrisProcessed += pMesh->GetSubDMesh()->GetTrianglePatchCount();
    }
    else
    {
        g_pScene->Statistics().TrisExported += pMesh->GetIB()->GetIndexCount() / 3;
        g_pScene->Statistics().VertsExported += pMesh->GetVB()->GetVertexCount();
        g_pScene->Statistics().MeshesExported++;
    }

    pParentFrame->AddModel( pModel );
    g_pScene->AddMesh( pMesh );
}
示例#14
0
void LoadAnimation(AnimationData& aAnimation,FbxNode* aNode,FbxAMatrix& aParentOrientation, FbxPose* aPose, FbxAnimLayer* aCurrentAnimLayer, int parentBone)
{
	FbxAMatrix lGlobalPosition = GetGlobalPosition(aNode, static_cast<FbxTime>(0.0f), aPose, &aParentOrientation);
	FbxNodeAttribute* lNodeAttribute = aNode->GetNodeAttribute();
	int boneId = -1;
	if (lNodeAttribute)
	{
		if(lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eSkeleton)
		{
			Bone newBone;
			newBone.myAnimationTime = GetAnimationTime(aNode,aCurrentAnimLayer);
			float oneFrameTime = 1.0f/24.0f;
				
			CU::Matrix44f fixMatrix;
			fixMatrix.myMatrix[0] = -1;
			FbxAMatrix lLocalTransform = aNode->EvaluateLocalTransform();
			newBone.myBaseOrientation = fixMatrix * CreateMatrix(lLocalTransform) * fixMatrix;

			char buffer[32];
			_itoa_s<32>(parentBone,buffer,10);
			newBone.myName = aNode->GetName();	
			newBone.myName += buffer;

			int lNodeIndex = aPose->Find(aNode);
			auto bindPoseMatrix = aPose->GetMatrix(lNodeIndex);

			FbxAMatrix bindMatrix;
			memcpy((double*)bindMatrix, (double*)bindPoseMatrix, sizeof(bindMatrix.mData));

			FbxAMatrix localPosOffset;
				
			memcpy((double*)localPosOffset, (double*)bindPoseMatrix, sizeof(localPosOffset.mData));
			localPosOffset =  localPosOffset * aParentOrientation.Inverse();

			newBone.myBindMatrix = fixMatrix * CreateMatrix(lGlobalPosition.Inverse()) * fixMatrix;

			CU::Matrix44f localStartOffset = CreateMatrix(bindMatrix.Inverse());
			for(float currentFrameTime = 0.0f;currentFrameTime < newBone.myAnimationTime;currentFrameTime+= oneFrameTime)
			{
				KeyFrame keyFrame;
				keyFrame.myTime = currentFrameTime;

				FbxTime time;
				time.SetSecondDouble(currentFrameTime);
				keyFrame.myMatrix = fixMatrix * CreateMatrix(aNode->EvaluateLocalTransform(time)) * fixMatrix;
				newBone.myFrames.push_back(keyFrame);
			}
			FbxAMatrix animationMatrix;

			FbxSkeleton* sekeleton = aNode->GetSkeleton();
			if(sekeleton->IsSkeletonRoot())
			{
				aAnimation.myBindMatrix = CU::Matrix44<float>();
				aAnimation.myRootBone = aAnimation.myBones.size();
			}
			boneId = aAnimation.myBones.size();
			aNode->SetUserDataPtr((void*)boneId);

			if(parentBone != -1)
			{
				aAnimation.myBones[parentBone].myChilds.push_back(boneId);
			}
			newBone.myId = boneId;
			aAnimation.myBones.push_back(newBone);
		}
	}

	const int lChildCount = aNode->GetChildCount();
	for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex)
	{
		LoadAnimation( aAnimation, aNode->GetChild(lChildIndex), lGlobalPosition , aPose, aCurrentAnimLayer, boneId);
	}
}