FTransform FFbxDataConverter::ConvertTransform(FbxAMatrix Matrix) { FTransform Out; FQuat Rotation = ConvertRotToQuat(Matrix.GetQ()); FVector Origin = ConvertPos(Matrix.GetT()); FVector Scale = ConvertScale(Matrix.GetS()); Out.SetTranslation(Origin); Out.SetScale3D(Scale); Out.SetRotation(Rotation); return Out; }
void FbxParser::ProcessLight(FbxNode* pNode, std::vector<GS::Light*>& lights) { FbxLight* llight = (FbxLight*) pNode->GetNodeAttribute(); if (!llight) return ; // Get the light color. FbxDouble3 c = llight->Color.Get(); GS::float4 lcolor( c[0], c[1], c[2], 1.0 ); float intensity = llight->Intensity.Get(); if (intensity) lcolor= lcolor*(intensity/100); // to do so far, we only process directional light if (llight->LightType.Get() == FbxLight::eDirectional) { //FbxDouble3 dir = pNode->LclRotation.Get(); FbxAnimEvaluator* lEvaluator = mpFbxScene->GetAnimationEvaluator(); FbxAMatrix lGlobal; lGlobal= lEvaluator->GetNodeGlobalTransform( pNode); FbxVector4 rotation = lGlobal.GetR(); FbxVector4 tran = lGlobal.GetT(); FbxQuaternion quaternion = lGlobal.GetQ(); GS::float4 q(quaternion[0], quaternion[1], quaternion[2],quaternion[3]); GS::float4x4 rotMat = GS::quat_rotation_matrix(q); GS::float4 dir(mul(rotMat, GS::float4(0, 0, -1, 1))); /* dir(0,0,-1); FbxQuaternion quaternion = lGlobal.GetQ(); quaternion. LcLRotation3f quaternion3f(quaternion[0], quaternion[1], quaternion[2], quaternion[3]); LcLTransform3f rot3f(quaternion3f); LcLVec3f rot_dir = dir * rot3f;*/ } }
// Deform the vertex array in Dual Quaternion Skinning way. void compute_dual_quaternion_deformation(FbxAMatrix& pGlobalPosition, FbxMesh* pMesh, FbxTime& pTime, FbxVector4* pVertexArray, FbxPose* pPose) { // 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; compute_cluster_deformation(pGlobalPosition, pMesh, lCluster, lVertexTransformMatrix, pTime, pPose); 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; }