예제 #1
0
// Deform the vertex array in Dual Quaternion Skinning way.
void fbxLoader2::ComputeDualQuaternionDeformation(FbxAMatrix& pGlobalPosition, FbxMesh* pMesh, FbxTime& pTime, FbxPose* pPose, int frame)
{
	// All the links must have the same link mode.
	FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();

	int lVertexCount = pMesh->GetControlPointsCount();
	int lSkinCount = pMesh->GetDeformerCount(FbxDeformer::eSkin);

	FbxDualQuaternion* lDQClusterDeformation = new FbxDualQuaternion[lVertexCount];
	memset(lDQClusterDeformation, 0, lVertexCount * sizeof(FbxDualQuaternion));

	double* lClusterWeight = new double[lVertexCount];
	memset(lClusterWeight, 0, lVertexCount * sizeof(double));

	// For all skins and all clusters, accumulate their deformation and weight
	// on each vertices and store them in lClusterDeformation and lClusterWeight.
	for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex)
	{
		FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
		int lClusterCount = lSkinDeformer->GetClusterCount();
		for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex)
		{
			FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
			if (!lCluster->GetLink())
				continue;

			FbxAMatrix lVertexTransformMatrix;
			ComputeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose, frame);

			FbxQuaternion lQ = lVertexTransformMatrix.GetQ();
			FbxVector4 lT = lVertexTransformMatrix.GetT();
			FbxDualQuaternion lDualQuaternion(lQ, lT);

			int lVertexIndexCount = lCluster->GetControlPointIndicesCount();
			for (int k = 0; k < lVertexIndexCount; ++k) 
			{ 
				int lIndex = lCluster->GetControlPointIndices()[k];

				// Sometimes, the mesh can have less points than at the time of the skinning
				// because a smooth operator was active when skinning but has been deactivated during export.
				if (lIndex >= lVertexCount)
					continue;

				double lWeight = lCluster->GetControlPointWeights()[k];

				if (lWeight == 0.0)
					continue;

				// Compute the influence of the link on the vertex.
				FbxDualQuaternion lInfluence = lDualQuaternion * lWeight;
				if (lClusterMode == FbxCluster::eAdditive)
				{    
					// Simply influenced by the dual quaternion.
					lDQClusterDeformation[lIndex] = lInfluence;

					// Set the link to 1.0 just to know this vertex is influenced by a link.
					lClusterWeight[lIndex] = 1.0;
				}
				else // lLinkMode == FbxCluster::eNormalize || lLinkMode == FbxCluster::eTotalOne
				{
					if(lClusterIndex == 0)
					{
						lDQClusterDeformation[lIndex] = lInfluence;
					}
					else
					{
						// Add to the sum of the deformations on the vertex.
						// Make sure the deformation is accumulated in the same rotation direction. 
						// Use dot product to judge the sign.
						double lSign = lDQClusterDeformation[lIndex].GetFirstQuaternion().DotProduct(lDualQuaternion.GetFirstQuaternion());
						if( lSign >= 0.0 )
						{
							lDQClusterDeformation[lIndex] += lInfluence;
						}
						else
						{
							lDQClusterDeformation[lIndex] -= lInfluence;
						}
					}
					// Add to the sum of weights to either normalize or complete the vertex.
					lClusterWeight[lIndex] += lWeight;
				}
			}//For each vertex
		}//lClusterCount
	}

	//Actually deform each vertices here by information stored in lClusterDeformation and lClusterWeight
	/*for (int i = 0; i < lVertexCount; i++) 
	{
		FbxVector4 lSrcVertex = pVertexArray[i];
		FbxVector4& lDstVertex = pVertexArray[i];
		double lWeightSum = lClusterWeight[i];

		// Deform the vertex if there was at least a link with an influence on the vertex,
		if (lWeightSum != 0.0) 
		{
			lDQClusterDeformation[i].Normalize();
			lDstVertex = lDQClusterDeformation[i].Deform(lDstVertex);

			if (lClusterMode == FbxCluster::eNormalize)
			{
				// In the normalized link mode, a vertex is always totally influenced by the links. 
				lDstVertex /= lWeightSum;
			}
			else if (lClusterMode == FbxCluster::eTotalOne)
			{
				// In the total 1 link mode, a vertex can be partially influenced by the links. 
				lSrcVertex *= (1.0 - lWeightSum);
				lDstVertex += lSrcVertex;
			}
		} 
	}*/

	delete [] lDQClusterDeformation;
	delete [] lClusterWeight;
}
void Model::ComputeLinearDeformation( KFbxMesh *mesh, KTime &time, KFbxVector4 *vertices, KFbxPose *pose ) {
	
	KFbxCluster::ELinkMode cluster_mode = ((KFbxSkin*)mesh->GetDeformer(0, KFbxDeformer::eSKIN))->GetCluster(0)->GetLinkMode();

	int cp_count = mesh->GetControlPointsCount();
	KFbxXMatrix *cluster_deformations = new KFbxXMatrix[cp_count];
	memset( cluster_deformations, 0, cp_count * sizeof( KFbxXMatrix ) );

	double *cluster_weights = new double[cp_count];
	memset( cluster_weights, 0, cp_count * sizeof( double ) );

	if( cluster_mode == KFbxCluster::eADDITIVE ) {
		for( int i = 0;i < cp_count; i++ ) {
			cluster_deformations[i].SetIdentity();
		}
	}

	int skin_count = mesh->GetDeformerCount(KFbxDeformer::eSKIN);
	for( int skin_index = 0; skin_index < skin_count; skin_index++ ) {
		KFbxSkin *skin_deformer = (KFbxSkin*)mesh->GetDeformer(skin_index,KFbxDeformer::eSKIN);

		int cluster_count = skin_deformer->GetClusterCount();
		for( int cluster_index = 0; cluster_index < cluster_count; cluster_index++ ) {
			KFbxCluster *cluster = skin_deformer->GetCluster(cluster_index);
			if( !cluster->GetLink() ) continue;

			KFbxXMatrix vertex_transform_matrix;
			ComputeClusterDeformation( mesh, cluster, vertex_transform_matrix, time, pose );

			int vertex_index_count = cluster->GetControlPointIndicesCount();
			
			for( int k = 0; k < vertex_index_count; k++ ) {
				int index = cluster->GetControlPointIndices()[k];
				if( index >= cp_count ) continue;

				double weight = cluster->GetControlPointWeights()[k];

				if( weight == 0.0 ) continue;

				KFbxXMatrix influence = vertex_transform_matrix;
				MatrixScale( influence, weight );

				if( cluster_mode == KFbxCluster::eADDITIVE ) {
					MatrixAddToDiagonal( influence, 1.0 - weight );
					cluster_deformations[index] = influence * cluster_deformations[index];

					cluster_weights[index] = 1.0;
				} else { // linkmode == normalize or total1

					MatrixAdd( cluster_deformations[index], influence );

					cluster_weights[index] += weight;
				}
			}
		}
	}

	// actual deformation
	for( int i = 0; i < cp_count; i++ ) {
		KFbxVector4 source_vertex = vertices[i];
		KFbxVector4 &dest_vertex = vertices[i];
		double weight = cluster_weights[i];

		if( weight != 0.0 ) {
			dest_vertex = cluster_deformations[i].MultT( source_vertex );
			if( cluster_mode == KFbxCluster::eNORMALIZE ) {
				dest_vertex /= weight;
			} else if( cluster_mode == KFbxCluster::eTOTAL1 ) {
				source_vertex *= (1.0 - weight);
				dest_vertex += source_vertex;
			}
		}
	}

	delete[] cluster_deformations;
	delete[] cluster_weights;
}
예제 #3
0
// Deform the vertex array in classic linear way.
void fbxLoader2::ComputeLinearDeformation(FbxAMatrix& pGlobalPosition, FbxMesh* pMesh,  FbxTime& pTime, FbxPose* pPose, int frame)
{
	// All the links must have the same link mode.
	FbxCluster::ELinkMode lClusterMode = ((FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin))->GetCluster(0)->GetLinkMode();

	int lVertexCount = pMesh->GetControlPointsCount();
	FbxAMatrix* lClusterDeformation = new FbxAMatrix[lVertexCount];
	memset(lClusterDeformation, 0, lVertexCount * sizeof(FbxAMatrix));

	double* lClusterWeight = new double[lVertexCount];
	memset(lClusterWeight, 0, lVertexCount * sizeof(double));

	if (lClusterMode == FbxCluster::eAdditive)
	{
		for (int i = 0; i < lVertexCount; ++i)
		{
			lClusterDeformation[i].SetIdentity();
		}
	}

	// For all skins and all clusters, accumulate their deformation and weight
	// on each vertices and store them in lClusterDeformation and lClusterWeight.
	int lSkinCount = pMesh->GetDeformerCount(FbxDeformer::eSkin);
	for ( int lSkinIndex=0; lSkinIndex<lSkinCount; ++lSkinIndex)
	{
		FbxSkin * lSkinDeformer = (FbxSkin *)pMesh->GetDeformer(lSkinIndex, FbxDeformer::eSkin);
		
		int lClusterCount = lSkinDeformer->GetClusterCount();
		for ( int lClusterIndex=0; lClusterIndex<lClusterCount; ++lClusterIndex)
		{
			FbxCluster* lCluster = lSkinDeformer->GetCluster(lClusterIndex);
			if (!lCluster->GetLink())
				continue;

			FbxAMatrix lVertexTransformMatrix;

			ComputeClusterDeformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose, frame);

			//lVertexTransformMatrix.Transpose();
			FbxAMatrix identityM;
			identityM.SetIdentity();

			FbxVector4 rotation = lVertexTransformMatrix.GetROnly();
			FbxVector4 translation = lVertexTransformMatrix.GetT();
			FbxVector4 scaling = lVertexTransformMatrix.GetS();

			//rotation = FbxVector4(rotation.mData[0], rotation.mData[1], rotation.mData[2], rotation.mData[3]);
			//translation = FbxVector4 (translation.mData[0], translation.mData[1], translation.mData[2], translation.mData[3]);
			//scaling = FbxVector4 (scaling.mData[0], scaling.mData[1], scaling.mData[2], scaling.mData[3]);

			//lVertexTransformMatrix = FbxAMatrix(translation, rotation, scaling);			
			//lVertexTransformMatrix = FbxAMatrix(translation, rotation, scaling);	


			identityM = lVertexTransformMatrix * identityM;

			D3DXMATRIX convert = D3DXMATRIX(1,0,0,0,
											0,0,1,0,
											0,1,0,0,
											0,0,0,1);

			D3DXMATRIX setMatrix = D3DXMATRIX(	(float)identityM.mData[0].mData[0], (float)identityM.mData[1].mData[0], (float)identityM.mData[2].mData[0], (float)identityM.mData[3].mData[0],
												(float)identityM.mData[0].mData[1], (float)identityM.mData[1].mData[1], (float)identityM.mData[2].mData[1], (float)identityM.mData[3].mData[1],
												(float)identityM.mData[0].mData[2], (float)identityM.mData[1].mData[2], (float)identityM.mData[2].mData[2], (float)identityM.mData[3].mData[2],
												(float)identityM.mData[0].mData[3], (float)identityM.mData[1].mData[3], (float)identityM.mData[2].mData[3],1);

			//setMatrix *=0.5f;

			setMatrix = D3DXMATRIX(	(float)identityM.mData[0].mData[0], (float)identityM.mData[1].mData[0], (float)identityM.mData[2].mData[0], (float)identityM.mData[3].mData[0],
									(float)identityM.mData[0].mData[1], (float)identityM.mData[1].mData[1], (float)identityM.mData[2].mData[1], (float)identityM.mData[3].mData[1],
									//(float)identityM.mData[0].mData[2], (float)identityM.mData[1].mData[2], (float)identityM.mData[2].mData[2], (float)identityM.mData[3].mData[1],
									(float)identityM.mData[0].mData[2], (float)identityM.mData[1].mData[2], (float)identityM.mData[2].mData[2], (float)identityM.mData[3].mData[2],
									(float)identityM.mData[0].mData[3], (float)identityM.mData[1].mData[3], (float)identityM.mData[2].mData[3], 1);

			//setMatrix = setMatrix*convert;

			///////// juz prawie dziala. sprawdz jeszcze te addytywne itp.
			/// generalnie dodaj to do włosów i dorzuć poprzednią macierz, żeby liczyć przesunięcia.


			//setMatrix /= 2.54f; //skala jedna jest w cm, druga w inchach, nieważne czy zmieniam system skali ręcznie... bzdurka fbxa
			

			std::string nametype = lCluster->GetLink()->GetName();	

			animationStructure->GetSkeleton(frame)->GetBone(animationStructure->GetSkeleton(frame)->GetBoneByName(lCluster->GetLink()->GetName()))->SetTransformation(setMatrix);
		}//lClusterCount
	}

	delete [] lClusterDeformation;
	delete [] lClusterWeight;
}