From bb928c969e97454d272d9a5d686b461fcd140fc4 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Thu, 8 Aug 2024 20:55:43 +0800 Subject: [PATCH 1/4] NewFBXExtractKeyframe --- projects/FBX/FBXSDK.cpp | 73 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index 27518f3beb..6d476f9bf1 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -1253,16 +1253,16 @@ static vec3f transform_nrm(glm::mat4 &transform, vec3f pos) { return {p.x, p.y, p.z}; } -struct NewFBXRigPose : INode { - std::map getBoneNameMapping(PrimitiveObject *prim) { - auto boneName_count = prim->userData().get2("boneName_count"); - std::map boneNames; - for (auto i = 0; i < boneName_count; i++) { - auto boneName = prim->userData().get2(format("boneName_{}", i)); - boneNames[boneName] = i; - } - return boneNames; +static std::map getBoneNameMapping(PrimitiveObject *prim) { + auto boneName_count = prim->userData().get2("boneName_count"); + std::map boneNames; + for (auto i = 0; i < boneName_count; i++) { + auto boneName = prim->userData().get2(format("boneName_{}", i)); + boneNames[boneName] = i; } + return boneNames; +} +struct NewFBXRigPose : INode { std::vector TopologicalSorting(std::map bone_connects, std::shared_ptr skeleton) { std::vector ordering; std::set ordering_set; @@ -1499,6 +1499,61 @@ ZENDEFNODE(NewFBXBoneDeform, { {"primitive"}, }); +struct NewFBXExtractKeyframe : INode { + virtual void apply() override { + auto restPointTransformsPrim = get_input2("RestPointTransforms"); + auto restBoneNameMapping = getBoneNameMapping(restPointTransformsPrim.get()); + auto restPointTransformsInv = getInvertedBoneMatrix(restPointTransformsPrim.get()); + auto deformPointTransformsPrim = get_input2("DeformPointTransforms"); + auto deformPointTransforms = getBoneMatrix(deformPointTransformsPrim.get()); + std::vector keyframe_boneName; + std::vector keyframe_bone_matrix; + auto boneName_count = deformPointTransformsPrim->userData().get2("boneName_count"); + for (auto i = 0; i < boneName_count; i++) { + auto boneName = deformPointTransformsPrim->userData().get2(format("boneName_{}", i)); + if (restBoneNameMapping.count(boneName) == 0) { + continue; + } + keyframe_boneName.emplace_back(boneName); + glm::mat4 restPointTransformInv = restPointTransformsInv[restBoneNameMapping[boneName]]; + glm::mat4 deformPointTransform = deformPointTransforms[i]; + auto keyframeTransform = restPointTransformInv * deformPointTransform; + keyframe_bone_matrix.emplace_back(keyframeTransform); + } + + auto keyframe = std::make_shared(); + keyframe->userData().set2("boneName_count", int(keyframe_boneName.size())); + for (auto i = 0; i < keyframe_boneName.size(); i++) { + keyframe->userData().set2(format("boneName_{}", i), keyframe_boneName[i]); + } + keyframe->verts.resize(keyframe_boneName.size()); + auto &verts = keyframe->verts; + auto &transform_r0 = keyframe->verts.add_attr("transform_r0"); + auto &transform_r1 = keyframe->verts.add_attr("transform_r1"); + auto &transform_r2 = keyframe->verts.add_attr("transform_r2"); + for (auto i = 0; i < keyframe->verts.size(); i++) { + auto matrix = keyframe_bone_matrix[i]; + transform_r0[i] = {matrix[0][0], matrix[0][1], matrix[0][2]}; + transform_r1[i] = {matrix[1][0], matrix[1][1], matrix[1][2]}; + transform_r2[i] = {matrix[2][0], matrix[2][1], matrix[2][2]}; + verts[i] = {matrix[3][0], matrix[3][1], matrix[3][2]}; + } + set_output2("keyframe", keyframe); + } +}; + +ZENDEFNODE(NewFBXExtractKeyframe, { + { + "RestPointTransforms", + "DeformPointTransforms", + }, + { + "keyframe", + }, + {}, + {"primitive"}, +}); + struct NormalView : INode { virtual void apply() override { From e61f6699edb6d14474b972292ff4241f9d2aca38 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 9 Aug 2024 17:54:35 +0800 Subject: [PATCH 2/4] maybe work --- projects/FBX/FBXSDK.cpp | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index 6d476f9bf1..2d8a06cb72 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -1262,6 +1262,16 @@ static std::map getBoneNameMapping(PrimitiveObject *prim) { } return boneNames; } +static std::vector getBoneNames(PrimitiveObject *prim) { + auto boneName_count = prim->userData().get2("boneName_count"); + std::vector boneNames; + boneNames.reserve(boneName_count); + for (auto i = 0; i < boneName_count; i++) { + auto boneName = prim->userData().get2(format("boneName_{}", i)); + boneNames.emplace_back(boneName); + } + return boneNames; +} struct NewFBXRigPose : INode { std::vector TopologicalSorting(std::map bone_connects, std::shared_ptr skeleton) { std::vector ordering; @@ -1363,16 +1373,6 @@ ZENDEFNODE(NewFBXRigPose, { {"FBXSDK"}, }); struct NewFBXBoneDeform : INode { - std::vector getBoneNames(PrimitiveObject *prim) { - auto boneName_count = prim->userData().get2("boneName_count"); - std::vector boneNames; - boneNames.reserve(boneName_count); - for (auto i = 0; i < boneName_count; i++) { - auto boneName = prim->userData().get2(format("boneName_{}", i)); - boneNames.emplace_back(boneName); - } - return boneNames; - } std::vector getBoneMapping(std::vector &old, std::vector &_new) { std::vector mapping; mapping.reserve(old.size()); @@ -1500,14 +1500,28 @@ ZENDEFNODE(NewFBXBoneDeform, { }); struct NewFBXExtractKeyframe : INode { + std::map get_parent_name(PrimitiveObject *prim) { + std::vector bone_names = getBoneNames(prim); + std::map res; + for (auto i = 0; i < prim->polys.size(); i++) { + auto p = prim->loops[i * 2 + 0]; + auto s = prim->loops[i * 2 + 1]; + res[bone_names[s]] = bone_names[p]; + } + return res; + } virtual void apply() override { auto restPointTransformsPrim = get_input2("RestPointTransforms"); auto restBoneNameMapping = getBoneNameMapping(restPointTransformsPrim.get()); + auto restPointTransforms = getBoneMatrix(restPointTransformsPrim.get()); auto restPointTransformsInv = getInvertedBoneMatrix(restPointTransformsPrim.get()); auto deformPointTransformsPrim = get_input2("DeformPointTransforms"); + auto deformBoneNameMapping = getBoneNameMapping(deformPointTransformsPrim.get()); auto deformPointTransforms = getBoneMatrix(deformPointTransformsPrim.get()); + auto deformPointTransformsInv = getInvertedBoneMatrix(deformPointTransformsPrim.get()); std::vector keyframe_boneName; std::vector keyframe_bone_matrix; + auto parent_names = get_parent_name(deformPointTransformsPrim.get()); auto boneName_count = deformPointTransformsPrim->userData().get2("boneName_count"); for (auto i = 0; i < boneName_count; i++) { auto boneName = deformPointTransformsPrim->userData().get2(format("boneName_{}", i)); @@ -1515,9 +1529,14 @@ struct NewFBXExtractKeyframe : INode { continue; } keyframe_boneName.emplace_back(boneName); + glm::mat4 parent_matrix = glm::mat4(1); + if (parent_names.count(boneName)) { + int pi = deformBoneNameMapping[parent_names[boneName]]; + parent_matrix = restPointTransforms[pi] * deformPointTransformsInv[pi]; + } glm::mat4 restPointTransformInv = restPointTransformsInv[restBoneNameMapping[boneName]]; glm::mat4 deformPointTransform = deformPointTransforms[i]; - auto keyframeTransform = restPointTransformInv * deformPointTransform; + auto keyframeTransform = restPointTransformInv * parent_matrix * deformPointTransform; keyframe_bone_matrix.emplace_back(keyframeTransform); } From 51b6c0b56ea60bbb8d58923b5acfd2dc3aecef7b Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 9 Aug 2024 18:42:50 +0800 Subject: [PATCH 3/4] NewFBXGenerateAnimation --- projects/FBX/FBXSDK.cpp | 117 ++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index 2d8a06cb72..62f6643c3c 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -1272,39 +1272,39 @@ static std::vector getBoneNames(PrimitiveObject *prim) { } return boneNames; } -struct NewFBXRigPose : INode { - std::vector TopologicalSorting(std::map bone_connects, std::shared_ptr skeleton) { - std::vector ordering; - std::set ordering_set; - while (bone_connects.size()) { - std::set need_to_remove; - for (auto [s, p]: bone_connects) { - if (bone_connects.count(p) == 0) { - if (ordering_set.count(p) == 0) { - ordering.emplace_back(p); - ordering_set.insert(p); - } - need_to_remove.insert(s); +static std::vector TopologicalSorting(std::map bone_connects, zeno::PrimitiveObject* skeleton) { + std::vector ordering; + std::set ordering_set; + while (bone_connects.size()) { + std::set need_to_remove; + for (auto [s, p]: bone_connects) { + if (bone_connects.count(p) == 0) { + if (ordering_set.count(p) == 0) { + ordering.emplace_back(p); + ordering_set.insert(p); } - } - for (auto index: need_to_remove) { - bone_connects.erase(index); + need_to_remove.insert(s); } } - for (auto i = 0; i < skeleton->verts.size(); i++) { - if (ordering_set.count(i) == 0) { - ordering.push_back(i); - } + for (auto index: need_to_remove) { + bone_connects.erase(index); } - if (false) { // debug - for (auto i = 0; i < ordering.size(); i++) { - auto bi = ordering[i]; - auto bone_name = skeleton->userData().get2(format("boneName_{}", bi)); - zeno::log_info("{}: {}: {}", i, bi, bone_name); - } + } + for (auto i = 0; i < skeleton->verts.size(); i++) { + if (ordering_set.count(i) == 0) { + ordering.push_back(i); + } + } + if (false) { // debug + for (auto i = 0; i < ordering.size(); i++) { + auto bi = ordering[i]; + auto bone_name = skeleton->userData().get2(format("boneName_{}", bi)); + zeno::log_info("{}: {}: {}", i, bi, bone_name); } - return ordering; } + return ordering; +} +struct NewFBXRigPose : INode { virtual void apply() override { auto skeleton = std::dynamic_pointer_cast(get_input("skeleton")->clone()); auto nodelist = get_input("Transformations")->getRaw(); @@ -1327,7 +1327,7 @@ struct NewFBXRigPose : INode { bone_connects[skeleton->loops[i * 2 + 1]] = skeleton->loops[i * 2]; } - auto ordering = TopologicalSorting(bone_connects, skeleton); + auto ordering = TopologicalSorting(bone_connects, skeleton.get()); auto &verts = skeleton->verts; auto &transform_r0 = skeleton->verts.add_attr("transform_r0"); auto &transform_r1 = skeleton->verts.add_attr("transform_r1"); @@ -1557,6 +1557,8 @@ struct NewFBXExtractKeyframe : INode { transform_r2[i] = {matrix[2][0], matrix[2][1], matrix[2][2]}; verts[i] = {matrix[3][0], matrix[3][1], matrix[3][2]}; } + auto &boneNames = keyframe->verts.add_attr("boneName"); + std::iota(boneNames.begin(), boneNames.end(), 0); set_output2("keyframe", keyframe); } }; @@ -1574,6 +1576,65 @@ ZENDEFNODE(NewFBXExtractKeyframe, { }); +struct NewFBXGenerateAnimation : INode { + virtual void apply() override { + auto keyframe = get_input2("keyframe"); + std::map Transformations; + { + auto keyframe_matrix = getBoneMatrix(keyframe.get()); + auto boneNames = getBoneNames(keyframe.get()); + for (auto i = 0; i < boneNames.size(); i++) { + Transformations[boneNames[i]] = keyframe_matrix[i]; + } + } + + auto skeleton = std::dynamic_pointer_cast(get_input("skeleton")->clone()); + std::map bone_connects; + for (auto i = 0; i < skeleton->polys.size(); i++) { + bone_connects[skeleton->loops[i * 2 + 1]] = skeleton->loops[i * 2]; + } + auto ordering = TopologicalSorting(bone_connects, skeleton.get()); + auto &verts = skeleton->verts; + auto &transform_r0 = skeleton->verts.add_attr("transform_r0"); + auto &transform_r1 = skeleton->verts.add_attr("transform_r1"); + auto &transform_r2 = skeleton->verts.add_attr("transform_r2"); + auto transforms = getBoneMatrix(skeleton.get()); + auto transformsInv = getInvertedBoneMatrix(skeleton.get()); + auto boneNames = getBoneNames(skeleton.get()); + std::map cache; + for (auto bi: ordering) { + glm::mat4 transform = glm::mat4(1.0f); + if (Transformations.count(boneNames[bi])) { + auto trans = Transformations[boneNames[bi]]; + transform = transforms[bi] * trans * transformsInv[bi]; + } + if (bone_connects.count(bi)) { + transform = cache[bone_connects[bi]] * transform; + } + cache[bi] = transform; + verts[bi] = transform_pos(transform, verts[bi]); + transform_r0[bi] = transform_nrm(transform, transform_r0[bi]); + transform_r1[bi] = transform_nrm(transform, transform_r1[bi]); + transform_r2[bi] = transform_nrm(transform, transform_r2[bi]); + } + + set_output2("DeformPointTransforms", skeleton); + } +}; + +ZENDEFNODE(NewFBXGenerateAnimation, { + { + "skeleton", + "keyframe", + }, + { + "DeformPointTransforms", + }, + {}, + {"primitive"}, +}); + + struct NormalView : INode { virtual void apply() override { auto prim = get_input2("prim"); From 5cdc270563e800c291aa87566856cd8f03815419 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 9 Aug 2024 19:02:09 +0800 Subject: [PATCH 4/4] fix --- projects/FBX/FBXSDK.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/projects/FBX/FBXSDK.cpp b/projects/FBX/FBXSDK.cpp index 62f6643c3c..66dc96655d 100644 --- a/projects/FBX/FBXSDK.cpp +++ b/projects/FBX/FBXSDK.cpp @@ -1532,7 +1532,10 @@ struct NewFBXExtractKeyframe : INode { glm::mat4 parent_matrix = glm::mat4(1); if (parent_names.count(boneName)) { int pi = deformBoneNameMapping[parent_names[boneName]]; - parent_matrix = restPointTransforms[pi] * deformPointTransformsInv[pi]; + if (restBoneNameMapping.count(parent_names[boneName])) { + auto rpi = restBoneNameMapping[parent_names[boneName]]; + parent_matrix = restPointTransforms[rpi] * deformPointTransformsInv[pi]; + } } glm::mat4 restPointTransformInv = restPointTransformsInv[restBoneNameMapping[boneName]]; glm::mat4 deformPointTransform = deformPointTransforms[i];