From 2365334d6c93acdada88db7c82e3fe90e91f26d6 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Wed, 21 Aug 2024 14:44:46 +0800 Subject: [PATCH 1/3] apply root transform --- projects/FBX/FBXSDK.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index 013118ca88..c0ecd76369 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -343,6 +343,7 @@ struct ReadFBXFile: INode { // Import the contents of the file into the scene. lImporter->Import(fbx_object->lScene); + FbxRootNodeUtility::RemoveAllFbxRoots(fbx_object->lScene); // The file is imported; so get rid of the importer. lImporter->Destroy(); From 40daa9cad8ab8aece511c071af57ccb3e0721667 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Thu, 22 Aug 2024 14:47:45 +0800 Subject: [PATCH 2/3] temp --- projects/FBX/FBXSDK.cpp | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index c0ecd76369..737c8106eb 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -10,6 +10,7 @@ #include #include "zeno/utils/log.h" +#include "zeno/utils/bit_operations.h" #include #include "zeno/types/PrimitiveObject.h" #include "zeno/utils/scope_exit.h" @@ -596,6 +597,85 @@ std::shared_ptr GetMesh(FbxNode* pNode) { return prim; } +std::shared_ptr GetSkeleton(FbxNode* pNode) { + FbxMesh* pMesh = pNode->GetMesh(); + if (!pMesh) return nullptr; + std::vector bone_names; + std::vector poss; + std::vector transform_r0; + std::vector transform_r1; + std::vector transform_r2; + std::map parent_mapping; + if (pMesh->GetDeformerCount(FbxDeformer::eSkin)) { + FbxSkin* pSkin = (FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin); + // Iterate over each cluster (bone) + for (int j = 0; j < pSkin->GetClusterCount(); ++j) { + FbxCluster* pCluster = pSkin->GetCluster(j); + + FbxNode* pBoneNode = pCluster->GetLink(); + if (!pBoneNode) continue; + FbxAMatrix transformLinkMatrix; + pCluster->GetTransformLinkMatrix(transformLinkMatrix); + + // The transformation of the mesh at binding time + FbxAMatrix transformMatrix; + pCluster->GetTransformMatrix(transformMatrix); + + // Inverse bind matrix. + FbxAMatrix bindMatrix_ = transformMatrix.Inverse() * transformLinkMatrix; + auto bindMatrix = bit_cast(bindMatrix_); + auto t = bindMatrix.GetRow(3); + poss.emplace_back(t[0], t[1], t[2]); + + auto r0 = bindMatrix.GetRow(0); + auto r1 = bindMatrix.GetRow(1); + auto r2 = bindMatrix.GetRow(2); + transform_r0.emplace_back(r0[0], r0[1], r0[2]); + transform_r1.emplace_back(r1[0], r1[1], r1[2]); + transform_r2.emplace_back(r2[0], r2[1], r2[2]); + std::string boneName = pBoneNode->GetName(); + bone_names.emplace_back(boneName); + auto pParentNode = pBoneNode->GetParent(); + if (pParentNode) { + std::string parentName = pParentNode->GetName(); + parent_mapping[boneName] = parentName; + } + } + } + std::string nodeName = pNode->GetName(); + auto prim = std::make_shared(); + prim->userData().set2("RootName", nodeName); + prim->verts.resize(bone_names.size()); + prim->verts.values = poss; + prim->verts.add_attr("transform_r0") = transform_r0; + prim->verts.add_attr("transform_r1") = transform_r1; + prim->verts.add_attr("transform_r2") = transform_r2; + std::vector bone_connects; + for (auto bone_name: bone_names) { + if (parent_mapping.count(bone_name)) { + auto parent_name = parent_mapping[bone_name]; + if (std::count(bone_names.begin(), bone_names.end(), parent_name)) { + auto self_index = std::find(bone_names.begin(), bone_names.end(), bone_name) - bone_names.begin(); + auto parent_index = std::find(bone_names.begin(), bone_names.end(), parent_name) - bone_names.begin(); + bone_connects.push_back(parent_index); + bone_connects.push_back(self_index); + } + } + } + prim->loops.values = bone_connects; + prim->polys.resize(bone_connects.size() / 2); + for (auto j = 0; j < bone_connects.size() / 2; j++) { + prim->polys[j] = {j * 2, 2}; + } + auto &boneNames = prim->verts.add_attr("boneName"); + std::iota(boneNames.begin(), boneNames.end(), 0); + prim->userData().set2("boneName_count", int(bone_names.size())); + for (auto i = 0; i < bone_names.size(); i++) { + prim->userData().set2(zeno::format("boneName_{}", i), bone_names[i]); + } + return prim; +} + void TraverseNodesToGetNames(FbxNode* pNode, std::vector &names) { if (!pNode) return; @@ -629,6 +709,25 @@ void TraverseNodesToGetPrim(FbxNode* pNode, std::string target_name, std::shared TraverseNodesToGetPrim(pNode->GetChild(i), target_name, prim); } } +void TraverseNodesToGetSkeleton(FbxNode* pNode, std::string target_name, std::shared_ptr &prim) { + if (!pNode) return; + + FbxMesh* mesh = pNode->GetMesh(); + if (mesh) { + auto name = pNode->GetName(); + if (target_name == name) { + auto sub_prim = GetSkeleton(pNode); + if (sub_prim) { + prim = sub_prim; + } + return; + } + } + + for (int i = 0; i < pNode->GetChildCount(); i++) { + TraverseNodesToGetSkeleton(pNode->GetChild(i), target_name, prim); + } +} void TraverseNodesToGetPrims(FbxNode* pNode, std::vector> &prims) { if (!pNode) return; @@ -885,6 +984,39 @@ ZENDEFNODE(NewFBXImportSkeleton, { {"primitive"}, }); +struct NewFBXImportSkeleton2 : INode { + virtual void apply() override { + auto fbx_object = get_input2("fbx_object"); + auto lSdkManager = fbx_object->lSdkManager; + auto lScene = fbx_object->lScene; + + auto prim = std::make_shared(); + + FbxNode* lRootNode = lScene->GetRootNode(); + std::vector availableRootNames; + TraverseNodesToGetNames(lRootNode, availableRootNames); + for (auto name: availableRootNames) { + zeno::log_info("fuck: {}", name); + } + TraverseNodesToGetSkeleton(lRootNode, get_input2("name"), prim); + + set_output("prim", prim); + } +}; + +ZENDEFNODE(NewFBXImportSkeleton2, { + { + "fbx_object", + {"bool", "ConvertUnits", "0"}, + {"string", "name", "0"}, + }, + { + "prim", + }, + {}, + {"deprecated"}, +}); + struct NewFBXImportAnimation : INode { virtual void apply() override { int frameid; From edbc21d6c9c51067a326d1d4006e0f0d9169c6e4 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 23 Aug 2024 15:36:11 +0800 Subject: [PATCH 3/3] improve skeleton import --- projects/FBX/FBXSDK.cpp | 322 +++++++++++++++++++++++----------------- 1 file changed, 188 insertions(+), 134 deletions(-) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index 737c8106eb..dbc62d6e32 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -465,7 +465,7 @@ void getAttr(T* arr, std::string name, std::shared_ptr prim) { } } -std::shared_ptr GetMesh(FbxNode* pNode) { +static std::shared_ptr GetMesh(FbxNode* pNode) { FbxMesh* pMesh = pNode->GetMesh(); if (!pMesh) return nullptr; std::string nodeName = pNode->GetName(); @@ -597,7 +597,7 @@ std::shared_ptr GetMesh(FbxNode* pNode) { return prim; } -std::shared_ptr GetSkeleton(FbxNode* pNode) { +static std::shared_ptr GetSkeleton(FbxNode* pNode) { FbxMesh* pMesh = pNode->GetMesh(); if (!pMesh) return nullptr; std::vector bone_names; @@ -676,7 +676,7 @@ std::shared_ptr GetSkeleton(FbxNode* pNode) { return prim; } -void TraverseNodesToGetNames(FbxNode* pNode, std::vector &names) { +static void TraverseNodesToGetNames(FbxNode* pNode, std::vector &names) { if (!pNode) return; FbxMesh* mesh = pNode->GetMesh(); @@ -690,7 +690,7 @@ void TraverseNodesToGetNames(FbxNode* pNode, std::vector &names) { } } -void TraverseNodesToGetPrim(FbxNode* pNode, std::string target_name, std::shared_ptr &prim) { +static void TraverseNodesToGetPrim(FbxNode* pNode, std::string target_name, std::shared_ptr &prim) { if (!pNode) return; FbxMesh* mesh = pNode->GetMesh(); @@ -709,26 +709,7 @@ void TraverseNodesToGetPrim(FbxNode* pNode, std::string target_name, std::shared TraverseNodesToGetPrim(pNode->GetChild(i), target_name, prim); } } -void TraverseNodesToGetSkeleton(FbxNode* pNode, std::string target_name, std::shared_ptr &prim) { - if (!pNode) return; - - FbxMesh* mesh = pNode->GetMesh(); - if (mesh) { - auto name = pNode->GetName(); - if (target_name == name) { - auto sub_prim = GetSkeleton(pNode); - if (sub_prim) { - prim = sub_prim; - } - return; - } - } - - for (int i = 0; i < pNode->GetChildCount(); i++) { - TraverseNodesToGetSkeleton(pNode->GetChild(i), target_name, prim); - } -} -void TraverseNodesToGetPrims(FbxNode* pNode, std::vector> &prims) { +static void TraverseNodesToGetPrims(FbxNode* pNode, std::vector> &prims) { if (!pNode) return; FbxMesh* mesh = pNode->GetMesh(); @@ -858,101 +839,206 @@ ZENDEFNODE(NewFBXImportSkin, { {"primitive"}, }); -struct NewFBXImportSkeleton : INode { - virtual void apply() override { - auto fbx_object = get_input2("fbx_object"); - auto lSdkManager = fbx_object->lSdkManager; - auto lScene = fbx_object->lScene; - - // Print the nodes of the scene and their attributes recursively. - // Note that we are not printing the root node because it should - // not contain any attributes. - auto prim = std::make_shared(); +static int GetSkeletonFromBindPose(FbxManager* lSdkManager, FbxScene* lScene, std::shared_ptr& prim) { + auto pose_count = lScene->GetPoseCount(); + bool found_bind_pose = false; + for (auto i = 0; i < pose_count; i++) { + auto pose = lScene->GetPose(i); + if (pose == nullptr || !pose->IsBindPose()) { + continue; + } + found_bind_pose = true; + } + if (found_bind_pose == false) { + lSdkManager->CreateMissingBindPoses(lScene); + } + pose_count = lScene->GetPoseCount(); - auto pose_count = lScene->GetPoseCount(); - bool found_bind_pose = false; - for (auto i = 0; i < pose_count; i++) { - auto pose = lScene->GetPose(i); - if (pose == nullptr || !pose->IsBindPose()) { + std::vector bone_names; + std::map parent_mapping; + std::vector poss; + std::vector transform_r0; + std::vector transform_r1; + std::vector transform_r2; + for (auto i = 0; i < pose_count; i++) { + auto pose = lScene->GetPose(i); + if (pose == nullptr || !pose->IsBindPose()) { + continue; + } + for (int j = 1; j < pose->GetCount(); ++j) { + std::string bone_name = pose->GetNode(j)->GetName(); + if (std::count(bone_names.begin(), bone_names.end(), bone_name)) { continue; } - found_bind_pose = true; + + FbxMatrix transformMatrix = pose->GetMatrix(j); + auto t = transformMatrix.GetRow(3); + poss.emplace_back(t[0], t[1], t[2]); + + auto r0 = transformMatrix.GetRow(0); + auto r1 = transformMatrix.GetRow(1); + auto r2 = transformMatrix.GetRow(2); + transform_r0.emplace_back(r0[0], r0[1], r0[2]); + transform_r1.emplace_back(r1[0], r1[1], r1[2]); + transform_r2.emplace_back(r2[0], r2[1], r2[2]); + + bone_names.emplace_back(pose->GetNode(j)->GetName()); } - if (found_bind_pose == false) { - lSdkManager->CreateMissingBindPoses(lScene); + for (int j = 1; j < pose->GetCount(); ++j) { + auto self_name = pose->GetNode(j)->GetName(); + auto parent = pose->GetNode(j)->GetParent(); + if (parent) { + auto parent_name = parent->GetName(); + parent_mapping[self_name] = parent_name; + } } - pose_count = lScene->GetPoseCount(); + } + { + prim->verts.resize(bone_names.size()); + prim->verts.values = poss; + prim->verts.add_attr("transform_r0") = transform_r0; + prim->verts.add_attr("transform_r1") = transform_r1; + prim->verts.add_attr("transform_r2") = transform_r2; + auto &boneNames = prim->verts.add_attr("boneName"); + std::iota(boneNames.begin(), boneNames.end(), 0); + std::vector bone_connects; + for (auto bone_name: bone_names) { + if (parent_mapping.count(bone_name)) { + auto parent_name = parent_mapping[bone_name]; + if (std::count(bone_names.begin(), bone_names.end(), parent_name)) { + auto self_index = std::find(bone_names.begin(), bone_names.end(), bone_name) - bone_names.begin(); + auto parent_index = std::find(bone_names.begin(), bone_names.end(), parent_name) - bone_names.begin(); + bone_connects.push_back(parent_index); + bone_connects.push_back(self_index); + } + } + } + prim->loops.values = bone_connects; + prim->polys.resize(bone_connects.size() / 2); + for (auto j = 0; j < bone_connects.size() / 2; j++) { + prim->polys[j] = {j * 2, 2}; + } + + prim->userData().set2("boneName_count", int(bone_names.size())); + for (auto i = 0; i < bone_names.size(); i++) { + prim->userData().set2(zeno::format("boneName_{}", i), bone_names[i]); + } + } +} + +static void TraverseNodesToGetSkeleton(FbxNode* pNode, std::vector &bone_names, std::vector &transforms, std::map &parent_mapping) { + if (!pNode) return; + + FbxMesh* pMesh = pNode->GetMesh(); + if (pMesh && pMesh->GetDeformerCount(FbxDeformer::eSkin)) { + FbxSkin* pSkin = (FbxSkin*)pMesh->GetDeformer(0, FbxDeformer::eSkin); + // Iterate over each cluster (bone) + for (int j = 0; j < pSkin->GetClusterCount(); ++j) { + FbxCluster* pCluster = pSkin->GetCluster(j); + + FbxNode* pBoneNode = pCluster->GetLink(); + if (!pBoneNode) continue; + std::string boneName = pBoneNode->GetName(); + if (std::count(bone_names.begin(), bone_names.end(), boneName)) { + continue; + } + bone_names.emplace_back(boneName); + FbxAMatrix transformLinkMatrix; + pCluster->GetTransformLinkMatrix(transformLinkMatrix); + + // The transformation of the mesh at binding time + FbxAMatrix transformMatrix; + pCluster->GetTransformMatrix(transformMatrix); + + // Inverse bind matrix. + FbxAMatrix bindMatrix_ = transformMatrix.Inverse() * transformLinkMatrix; + auto bindMatrix = bit_cast(bindMatrix_); + transforms.emplace_back(bindMatrix); + + auto pParentNode = pBoneNode->GetParent(); + if (pParentNode) { + std::string parentName = pParentNode->GetName(); + parent_mapping[boneName] = parentName; + } + } + } + + for (int i = 0; i < pNode->GetChildCount(); i++) { + TraverseNodesToGetSkeleton(pNode->GetChild(i), bone_names, transforms, parent_mapping); + } +} +std::shared_ptr GetSkeletonFromMesh(FbxScene* lScene) { + auto prim = std::make_shared(); + + FbxNode* lRootNode = lScene->GetRootNode(); + if (lRootNode) { std::vector bone_names; + std::vector transforms; std::map parent_mapping; + TraverseNodesToGetSkeleton(lRootNode, bone_names, transforms, parent_mapping); std::vector poss; std::vector transform_r0; std::vector transform_r1; std::vector transform_r2; - for (auto i = 0; i < pose_count; i++) { - auto pose = lScene->GetPose(i); - if (pose == nullptr || !pose->IsBindPose()) { - continue; - } - for (int j = 1; j < pose->GetCount(); ++j) { - std::string bone_name = pose->GetNode(j)->GetName(); - if (std::count(bone_names.begin(), bone_names.end(), bone_name)) { - continue; - } - - FbxMatrix transformMatrix = pose->GetMatrix(j); - auto t = transformMatrix.GetRow(3); - poss.emplace_back(t[0], t[1], t[2]); - - auto r0 = transformMatrix.GetRow(0); - auto r1 = transformMatrix.GetRow(1); - auto r2 = transformMatrix.GetRow(2); - transform_r0.emplace_back(r0[0], r0[1], r0[2]); - transform_r1.emplace_back(r1[0], r1[1], r1[2]); - transform_r2.emplace_back(r2[0], r2[1], r2[2]); + for (auto i = 0; i < bone_names.size(); i++) { + auto bone_name = bone_names[i]; + auto bindMatrix = transforms[i]; + auto t = bindMatrix.GetRow(3); + poss.emplace_back(t[0], t[1], t[2]); - bone_names.emplace_back(pose->GetNode(j)->GetName()); - } - for (int j = 1; j < pose->GetCount(); ++j) { - auto self_name = pose->GetNode(j)->GetName(); - auto parent = pose->GetNode(j)->GetParent(); - if (parent) { - auto parent_name = parent->GetName(); - parent_mapping[self_name] = parent_name; + auto r0 = bindMatrix.GetRow(0); + auto r1 = bindMatrix.GetRow(1); + auto r2 = bindMatrix.GetRow(2); + transform_r0.emplace_back(r0[0], r0[1], r0[2]); + transform_r1.emplace_back(r1[0], r1[1], r1[2]); + transform_r2.emplace_back(r2[0], r2[1], r2[2]); + } + prim->verts.resize(bone_names.size()); + prim->verts.values = poss; + prim->verts.add_attr("transform_r0") = transform_r0; + prim->verts.add_attr("transform_r1") = transform_r1; + prim->verts.add_attr("transform_r2") = transform_r2; + std::vector bone_connects; + for (auto bone_name: bone_names) { + if (parent_mapping.count(bone_name)) { + auto parent_name = parent_mapping[bone_name]; + if (std::count(bone_names.begin(), bone_names.end(), parent_name)) { + auto self_index = std::find(bone_names.begin(), bone_names.end(), bone_name) - bone_names.begin(); + auto parent_index = std::find(bone_names.begin(), bone_names.end(), parent_name) - bone_names.begin(); + bone_connects.push_back(parent_index); + bone_connects.push_back(self_index); } } } - { - prim->verts.resize(bone_names.size()); - prim->verts.values = poss; - prim->verts.add_attr("transform_r0") = transform_r0; - prim->verts.add_attr("transform_r1") = transform_r1; - prim->verts.add_attr("transform_r2") = transform_r2; - auto &boneNames = prim->verts.add_attr("boneName"); - std::iota(boneNames.begin(), boneNames.end(), 0); + prim->loops.values = bone_connects; + prim->polys.resize(bone_connects.size() / 2); + for (auto j = 0; j < bone_connects.size() / 2; j++) { + prim->polys[j] = {j * 2, 2}; + } + auto &boneNames = prim->verts.add_attr("boneName"); + std::iota(boneNames.begin(), boneNames.end(), 0); + prim->userData().set2("boneName_count", int(bone_names.size())); + for (auto i = 0; i < bone_names.size(); i++) { + prim->userData().set2(zeno::format("boneName_{}", i), bone_names[i]); + } + } + return prim; +} +struct NewFBXImportSkeleton : INode { + virtual void apply() override { + auto fbx_object = get_input2("fbx_object"); + auto lSdkManager = fbx_object->lSdkManager; + auto lScene = fbx_object->lScene; - std::vector bone_connects; - for (auto bone_name: bone_names) { - if (parent_mapping.count(bone_name)) { - auto parent_name = parent_mapping[bone_name]; - if (std::count(bone_names.begin(), bone_names.end(), parent_name)) { - auto self_index = std::find(bone_names.begin(), bone_names.end(), bone_name) - bone_names.begin(); - auto parent_index = std::find(bone_names.begin(), bone_names.end(), parent_name) - bone_names.begin(); - bone_connects.push_back(parent_index); - bone_connects.push_back(self_index); - } - } - } - prim->loops.values = bone_connects; - prim->polys.resize(bone_connects.size() / 2); - for (auto j = 0; j < bone_connects.size() / 2; j++) { - prim->polys[j] = {j * 2, 2}; - } + // Print the nodes of the scene and their attributes recursively. + // Note that we are not printing the root node because it should + // not contain any attributes. + auto prim = std::make_shared(); - prim->userData().set2("boneName_count", int(bone_names.size())); - for (auto i = 0; i < bone_names.size(); i++) { - prim->userData().set2(zeno::format("boneName_{}", i), bone_names[i]); - } + auto pose_count = GetSkeletonFromBindPose(lSdkManager, lScene, prim); + if (pose_count == 0 || get_input2("ForceFromMesh")) { + prim = GetSkeletonFromMesh(lScene); } if (get_input2("ConvertUnits")) { @@ -976,6 +1062,7 @@ ZENDEFNODE(NewFBXImportSkeleton, { { "fbx_object", {"bool", "ConvertUnits", "0"}, + {"bool", "ForceFromMesh", "0"}, }, { "prim", @@ -984,39 +1071,6 @@ ZENDEFNODE(NewFBXImportSkeleton, { {"primitive"}, }); -struct NewFBXImportSkeleton2 : INode { - virtual void apply() override { - auto fbx_object = get_input2("fbx_object"); - auto lSdkManager = fbx_object->lSdkManager; - auto lScene = fbx_object->lScene; - - auto prim = std::make_shared(); - - FbxNode* lRootNode = lScene->GetRootNode(); - std::vector availableRootNames; - TraverseNodesToGetNames(lRootNode, availableRootNames); - for (auto name: availableRootNames) { - zeno::log_info("fuck: {}", name); - } - TraverseNodesToGetSkeleton(lRootNode, get_input2("name"), prim); - - set_output("prim", prim); - } -}; - -ZENDEFNODE(NewFBXImportSkeleton2, { - { - "fbx_object", - {"bool", "ConvertUnits", "0"}, - {"string", "name", "0"}, - }, - { - "prim", - }, - {}, - {"deprecated"}, -}); - struct NewFBXImportAnimation : INode { virtual void apply() override { int frameid;