void Utilities::WriteMatrix(std::ostream& inStream, FbxMatrix& inMatrix, bool inIsRoot) { inStream << "<mat>" << static_cast<float>(inMatrix.Get(0, 0)) << "," << static_cast<float>(inMatrix.Get(0, 1)) << "," << static_cast<float>(inMatrix.Get(0, 2)) << "," << static_cast<float>(inMatrix.Get(0, 3)) << "," << static_cast<float>(inMatrix.Get(1, 0)) << "," << static_cast<float>(inMatrix.Get(1, 1)) << "," << static_cast<float>(inMatrix.Get(1, 2)) << "," << static_cast<float>(inMatrix.Get(1, 3)) << "," << static_cast<float>(inMatrix.Get(2, 0)) << "," << static_cast<float>(inMatrix.Get(2, 1)) << "," << static_cast<float>(inMatrix.Get(2, 2)) << "," << static_cast<float>(inMatrix.Get(2, 3)) << "," << static_cast<float>(inMatrix.Get(3, 0)) << "," << static_cast<float>(inMatrix.Get(3, 1)) << "," << static_cast<float>(inMatrix.Get(3, 2)) << "," << static_cast<float>(inMatrix.Get(3, 3)) << "</mat>\n"; }
FbxMatrix FBXSceneInstance::GetAbsoluteTransformFromCurrentTake2(FbxNode* pNode, FbxTime time) { if( !pNode ) { FbxMatrix mat; mat.SetIdentity(); return mat; } FbxMatrix matFBXGlobal = mScene->GetScene()->GetEvaluator()->GetNodeGlobalTransform(pNode, time); return matFBXGlobal; }
//----------------------------------------------------------------------------------- static Matrix4x4 GetGeometricTransform(FbxNode* node) { Matrix4x4 returnMatrix = Matrix4x4::IDENTITY; if ((node != nullptr) && (node->GetNodeAttribute() != nullptr)) { const FbxVector4 geoTrans = node->GetGeometricTranslation(FbxNode::eSourcePivot); const FbxVector4 geoRot = node->GetGeometricRotation(FbxNode::eSourcePivot); const FbxVector4 geoScale = node->GetGeometricScaling(FbxNode::eSourcePivot); FbxMatrix geoMat; geoMat.SetTRS(geoTrans, geoRot, geoScale); returnMatrix = ToEngineMatrix(geoMat); } return returnMatrix; }
void copyMatrix(const FbxMatrix& fbxMatrix, Matrix& matrix) { int i = 0; for (int row = 0; row < 4; ++row) { for (int col = 0; col < 4; ++col) { matrix.m[i++] = (float)fbxMatrix.Get(row, col); } } }
glm::mat4 fromFBXMatrix(FbxMatrix& fm) { glm::mat4 mat; for (int i=0; i<4; i++) { for (int j=0; j<4; j++) { mat[i][j] = fm.Get(i, j); } } return mat; }
void CFBXLoader::ComputeNodeMatrix(FbxNode* pNode, FBX_MESH_NODE* meshNode) { if(!pNode || !meshNode) { return ; } FbxAnimEvaluator* lEvaluator = mScene->GetAnimationEvaluator(); FbxMatrix lGlobal; lGlobal.SetIdentity(); if(pNode != mScene->GetRootNode()) { lGlobal= lEvaluator->GetNodeGlobalTransform(pNode); FBXMatrixToFloat16( &lGlobal, meshNode->mat4x4 ); } else { FBXMatrixToFloat16( &lGlobal, meshNode->mat4x4 ); } }
void Utilities::PrintMatrix(FbxMatrix& inMatrix) { FbxString lMatrixValue; for (int k = 0; k<4; ++k) { FbxVector4 lRow = inMatrix.GetRow(k); char lRowValue[1024]; FBXSDK_sprintf(lRowValue, 1024, "%9.4f %9.4f %9.4f %9.4f\n", lRow[0], lRow[1], lRow[2], lRow[3]); lMatrixValue += FbxString(" ") + FbxString(lRowValue); } std::cout << lMatrixValue.Buffer(); }
reNode* reFBXAsset::importNode(FbxNode* fbxNode, reNode* parent) { reNode* node = new reNode; node->name(fbxNode->GetName()); FbxMatrix mat = fbxNode->EvaluateGlobalTransform(FbxTime(0)); FbxNode *fbxParent = fbxNode->GetParent(); if (!fbxParent) { node->transform (reTransform(fromFBXMatrix(mat))); } else { FbxMatrix pmat = fbxParent->EvaluateGlobalTransform(FbxTime(0)); node->transform(reTransform(fromFBXMatrix(pmat.Inverse()) * fromFBXMatrix(mat))); } if (fbxNode->GetNodeAttribute() ) { FbxNodeAttribute::EType attrType = (fbxNode->GetNodeAttribute()->GetAttributeType()); switch (attrType) { case FbxNodeAttribute::eMesh: reMesh* mesh = importMesh(fbxNode); node->renderables->add(mesh); break; } } for(int i = 0; i < fbxNode->GetChildCount(); i++) { reNode* child = importNode(fbxNode->GetChild(i), node); node->children->add(child); } return node; };
web::json::value BabylonMesh::toJson() { auto jobj = BabylonAbstractMesh::toJson(); jobj[L"id"] = web::json::value::string(_id); jobj[L"name"] = web::json::value::string(_id); if (_parentId.size() > 0) jobj[L"parentId"] = web::json::value::string(_parentId); if (_materialId.size() > 0) jobj[L"materialId"] = web::json::value::string(_materialId); jobj[L"isEnabled"] = web::json::value::boolean(_isEnabled); jobj[L"isVisible"] = web::json::value::boolean(_isVisible); jobj[L"pickable"] = web::json::value::boolean(_pickable); jobj[L"hasVertexAlpha"] = web::json::value::boolean(_hasVertexAlpha); jobj[L"checkCollision"] = web::json::value::boolean(_checkCollision); jobj[L"receiveShadows"] = web::json::value::boolean(_receiveShadows); jobj[L"infiniteDistance"] = web::json::value::boolean(_infiniteDistance); jobj[L"billboardMode"] = web::json::value::number(_billboardMode); jobj[L"visibility"] = web::json::value::number(_visibility); jobj[L"skeletonId"] = web::json::value::number(_skeletonId); auto submeshesArray = web::json::value::array(); for (auto ix = 0u; ix < submeshes().size(); ++ix){ submeshesArray[ix] = submeshes()[ix].toJson(); } jobj[L"subMeshes"] = submeshesArray; jobj[L"showBoundingBox"] = web::json::value::boolean(_showBoundingBox); jobj[L"showSubMeshesBoundingBox"] = web::json::value::boolean(_showSubMeshesBoundingBox); jobj[L"applyFog"] = web::json::value::boolean(_applyFog); jobj[L"alphaIndex"] = web::json::value::number(_alphaIndex); if (_positions.size() > 0) jobj[L"positions"] = convertToJson(_positions); if (_normals.size() > 0) jobj[L"normals"] = convertToJson(_normals); if (_uvs.size() > 0) jobj[L"uvs"] = convertToJson(_uvs); if (_uvs2.size() > 0) jobj[L"uvs2"] = convertToJson(_uvs2); if (_uvs3.size() > 0) jobj[L"uvs3"] = convertToJson(_uvs3); if (_uvs4.size() > 0) jobj[L"uvs4"] = convertToJson(_uvs4); if (_uvs5.size() > 0) jobj[L"uvs5"] = convertToJson(_uvs5); if (_uvs6.size() > 0) jobj[L"uvs6"] = convertToJson(_uvs6); if (_colors.size() > 0) jobj[L"colors"] = convertToJson(_colors); if (_indices.size() > 0) jobj[L"indices"] = convertToJson(_indices, false); if (_boneIndices.size() > 0){ jobj[L"matricesIndices"] = convertToJson(_boneIndices); } if (_boneWeights.size() > 0){ jobj[L"matricesWeights"] = convertToJson(_boneWeights); } if (animations.size() == 0 && !associatedSkeleton){ jobj[L"autoAnimate"] = web::json::value::boolean(false); jobj[L"autoAnimateLoop"] = web::json::value::boolean(false); jobj[L"autoAnimateFrom"] = web::json::value::number(0); jobj[L"autoAnimateTo"] = web::json::value::number(0); } else if (animations.size()>0){ jobj[L"autoAnimate"] = web::json::value::boolean(animations[0]->autoAnimate); jobj[L"autoAnimateLoop"] = web::json::value::boolean(animations[0]->autoAnimateLoop); jobj[L"autoAnimateFrom"] = web::json::value::number(animations[0]->autoAnimateFrom); jobj[L"autoAnimateTo"] = web::json::value::number(animations[0]->autoAnimateTo); } else{ jobj[L"autoAnimate"] = web::json::value::boolean(associatedSkeleton->bones[0].animation->autoAnimate); jobj[L"autoAnimateLoop"] = web::json::value::boolean(associatedSkeleton->bones[0].animation->autoAnimateLoop); jobj[L"autoAnimateFrom"] = web::json::value::number(associatedSkeleton->bones[0].animation->autoAnimateFrom); jobj[L"autoAnimateTo"] = web::json::value::number(associatedSkeleton->bones[0].animation->autoAnimateTo); } auto janimations = web::json::value::array(); for (const auto& anim : animations){ janimations[janimations.size()] = anim->toJson(); } jobj[L"animations"] = janimations; FbxMatrix identity; identity.SetIdentity(); if (pivotMatrix != identity){ auto jpivot = web::json::value::array(); for (auto x = 0; x < 4; ++x){ for (auto y = 0; y < 4; ++y){ jpivot[x * 4 + y] = web::json::value::number( pivotMatrix[x][y]); } } jobj[L"pivotMatrix"] = jpivot; } auto jinstances = web::json::value::array(); for (auto& instance : _instances) { jinstances[jinstances.size()] = instance.toJson(); } jobj[L"instances"] = jinstances; return jobj; }
//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); } } }
void FBXImporter::FbxMatrixToXMMATRIX(XMMATRIX& out, const FbxMatrix& in) { out = XMMatrixSet(in.Get(0, 0), in.Get(0, 1), in.Get(0, 2), in.Get(0, 3), in.Get(1, 0), in.Get(1, 1), in.Get(1, 2), in.Get(1, 3), in.Get(2, 0), in.Get(2, 1), in.Get(2, 2), in.Get(2, 3), in.Get(3, 0), in.Get(3, 1), in.Get(3, 2), in.Get(3, 3)); }