Example #1
0
// This method, called by the system, modifies the items...
void SpherifyMod::ModifyObject(TimeValue t, ModContext &mc, 
	ObjectState *os, INode *node) {	

	Matrix3 mat, invmat;

	// Get the deformation space tm from the ModContext.  We use this to
	// transform our points in and out of deformation space.
	if (mc.tm)
		mat = *mc.tm;		
	else
		mat.IdentityMatrix();	
	
	// Compute the tm's inverse
	invmat = Inverse(mat);
 
	// Call the Deform method of the object passing it our deformer.
	// The Deform method of the object calls the Map method of the 
	// deformer we pass one point at a time.
	os->obj->Deform(&GetDeformer(t, mc, mat, invmat), TRUE);

	// This informs the system that the object may need to be re-evaluated
	// if the user moves to a new time.  We pass the channel we have 
	// modified, and the interval of our modification.
	os->obj->UpdateValidity(GEOM_CHAN_NUM, SpherifyValidity(t));
}
void patchSkins(FbxNode* currentRoot, const std::map<std::string, FbxNode*>& animatedNodes, const std::string& prefix){
	auto mesh = currentRoot->GetMesh();
	if (mesh){
		auto skinCount = mesh->GetDeformerCount(FbxDeformer::EDeformerType::eSkin);
		for (auto ix = 0; ix < skinCount; ++ix){
			auto skin = (FbxSkin*) mesh->GetDeformer(ix, FbxDeformer::EDeformerType::eSkin);
			if (skin){
				std::vector<FbxCluster*> replacements;
				auto clusterCount = skin->GetClusterCount();
				for (auto clusterIx = 0; clusterIx < clusterCount; ++clusterIx){
					auto cluster = skin->GetCluster(clusterIx);
					if (cluster){
						auto linkNode = cluster->GetLink();
						if (linkNode){
							auto candidateName = prefix;
							candidateName.append(linkNode->GetName());
							auto found = animatedNodes.find(candidateName);
							if (found != animatedNodes.end()){
								FbxCluster* newCluster = FbxCluster::Create(currentRoot->GetScene(), "");
								newCluster->SetLink(found->second);
								newCluster->SetLinkMode(cluster->GetLinkMode());
								FbxAMatrix mat;
								newCluster->SetTransformAssociateModelMatrix(cluster->GetTransformAssociateModelMatrix(mat));
								newCluster->SetAssociateModel(cluster->GetAssociateModel());
								newCluster->SetTransformLinkMatrix(cluster->GetTransformLinkMatrix(mat));
								newCluster->SetTransformMatrix(cluster->GetTransformMatrix(mat));
								newCluster->SetTransformParentMatrix(cluster->GetTransformParentMatrix(mat));

								auto indicesAndWeightsCount = cluster->GetControlPointIndicesCount();
								for (auto ix = 0; ix < indicesAndWeightsCount; ++ix){
									newCluster->AddControlPointIndex(cluster->GetControlPointIndices()[ix], cluster->GetControlPointWeights()[ix]);

								}


								replacements.push_back(newCluster);
							}
						}
					}
				}
				if (replacements.size() == clusterCount){
					while (skin->GetClusterCount()>0){
						auto oldCluster = skin->GetCluster(skin->GetClusterCount() - 1);
						skin->RemoveCluster(oldCluster);
						oldCluster->Destroy();
					}
					for (auto c : replacements){
						skin->AddCluster(c);
					}
				}
				else{
					for (auto c : replacements){
						c->Destroy();
					}
				}
			}
		}
	}

	for (auto ix = 0; ix < currentRoot->GetChildCount(); ++ix){
		patchSkins(currentRoot->GetChild(ix), animatedNodes, prefix);
	}
}
Example #3
0
		void FbxLoader::ProcessBoneAndAnimation(FbxNode* node, Node& meshNode)
		{
			auto currMesh = node->GetMesh();
			if(!currMesh) return;

			FbxVector4 lT = node->GetGeometricTranslation(FbxNode::eSourcePivot);
			FbxVector4 lR = node->GetGeometricRotation(FbxNode::eSourcePivot);
			FbxVector4 lS = node->GetGeometricScaling(FbxNode::eSourcePivot);

			FbxAMatrix geometryTransform = FbxAMatrix(lT, lR, lS);

			FbxSkin* skin = nullptr;
			const int deformerCnt = currMesh->GetDeformerCount();
			for(int deformerIndex = 0; deformerIndex < deformerCnt; ++deformerIndex) {
				skin = (FbxSkin*)(currMesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
				if(skin) break;
			}
			if(!skin) return;

			meshNode.useSkinnedMesh = true;
			const size_t nClusters = skin->GetClusterCount();
			if(nClusters < 1) return;

			for(auto& clip : animationClips)
				clip.second->transformCurves.resize(nClusters);

			meshNode.bones.resize(nClusters);
			const int animCount = scene->GetSrcObjectCount<FbxAnimStack>();

			float time = 0;
			for(int ci = 0; ci < nClusters; ++ci) {
				FbxCluster* cluster = skin->GetCluster(ci);
				auto elink = cluster->GetLinkMode();
				std::string boneName = cluster->GetLink()->GetName();

				FbxAMatrix transformMatrix, transformLinkMatrix, globalBindposeInverse;
				cluster->GetTransformMatrix(transformMatrix);
				cluster->GetTransformLinkMatrix(transformLinkMatrix);
				globalBindposeInverse = transformLinkMatrix.Inverse() * geometryTransform * transformMatrix;

				FbxNode* boneNode = cluster->GetLink();
				Bone& bone = meshNode.bones[ci];
				bone.name = boneName;
				bone.index = ci;

				auto T = globalBindposeInverse.GetT() * factor;
				
				if(axismode == eLeftHanded) {
					auto R = globalBindposeInverse.GetR();
					T[0] *= -1; R[1] *= -1; R[2] *= -1;
					globalBindposeInverse.SetR(R);
				}
				globalBindposeInverse.SetT(T);

				ConvertMatrix(bone.bindPoseInverse, globalBindposeInverse);

				const int nCtrl = cluster->GetControlPointIndicesCount();

				for(int ctrlIndex = 0; ctrlIndex < nCtrl; ++ctrlIndex) {
					BlendWeightPair pair;
					pair.boneIndex = ci;
					pair.weight = (float)cluster->GetControlPointWeights()[ctrlIndex];
					meshNode.controlPoints[cluster->GetControlPointIndices()[ctrlIndex]].blendWeigths.push_back(pair);
				}

				FbxAMatrix preRot;
				auto preR = boneNode->GetPreRotation(FbxNode::eSourcePivot);
				preRot.SetR(preR);

				for(int ai = 0; ai < animCount; ++ai) {
					auto animStack = scene->GetSrcObject<FbxAnimStack>(ai);
					scene->SetCurrentAnimationStack(animStack);
					std::string animName = animStack->GetName();
					auto& clip = animationClips[animName];
					auto& transformCurve = clip->transformCurves[ci];
					transformCurve.boneName = boneName;
					transformCurve.begin = 0;

					auto animLayer = animStack->GetMember<FbxAnimLayer>(0);
					FbxAnimCurve* fbxTCurves[3];
					FbxAnimCurve* fbxRCurves[3];
					FbxAnimCurve* fbxSCurves[3];

					fbxTCurves[0] = boneNode->LclTranslation.GetCurve(animLayer, "X");

					if(!fbxTCurves[0])
						continue;
					
					fbxTCurves[1] = boneNode->LclTranslation.GetCurve(animLayer, "Y");
					fbxTCurves[2] = boneNode->LclTranslation.GetCurve(animLayer, "Z");

					fbxRCurves[0] = boneNode->LclRotation.GetCurve(animLayer, "X");
					fbxRCurves[1] = boneNode->LclRotation.GetCurve(animLayer, "Y");
					fbxRCurves[2] = boneNode->LclRotation.GetCurve(animLayer, "Z");

					fbxSCurves[0] = boneNode->LclScaling.GetCurve(animLayer, "X");
					fbxSCurves[1] = boneNode->LclScaling.GetCurve(animLayer, "Y");
					fbxSCurves[2] = boneNode->LclScaling.GetCurve(animLayer, "Z");

					// set & apply filter
					FbxAnimCurveFilterKeyReducer keyReducer;
					keyReducer.SetKeySync(false);
					keyReducer.Apply(fbxTCurves, 3);
					keyReducer.Apply(fbxSCurves, 3);
					keyReducer.SetKeySync(true);
					keyReducer.Apply(fbxRCurves, 3);

					FbxAnimCurveFilterUnroll unroll;
					unroll.SetForceAutoTangents(true);
					unroll.Apply(fbxRCurves, 3);

					FbxAnimCurveFilterTSS tss;
					FbxTime tt;
					tt.SetSecondDouble(-fbxTCurves[0]->KeyGetTime(0).GetSecondDouble());
					tss.SetShift(tt);
					tss.Apply(fbxTCurves, 3);
					tss.Apply(fbxRCurves, 3);
					tss.Apply(fbxSCurves, 3);
					//

					// process curves
					if(fbxTCurves[0]->KeyGetCount() > 0) {
						ProcessAnimCurveT(fbxTCurves, transformCurve);
						ProcessAnimCurveS(fbxSCurves, transformCurve);
						ProcessAnimCurveR(fbxRCurves, transformCurve, preRot);

						//clamping by reduced keyframes
						clip->startTime = 0;
						clip->lengthInSeconds = transformCurve.end;
						clip->lengthInFrames = (int)(1.5f + (transformCurve.end / (1 / 30.0f)));
					}
				} // animations loop
			} // cluster loop
		}