From a1165ab956b5f3493266ba4b7cad4625e50effed Mon Sep 17 00:00:00 2001 From: seungho baek Date: Tue, 18 Apr 2023 14:47:24 +0900 Subject: [PATCH] Fix transform issue of skinned mesh Change-Id: I5acd990e1e1ae586a0b6c66af3aefc99c991e206 Signed-off-by: seungho baek --- automated-tests/resources/dli_pbr.vsh | 6 +- .../utc-Dali-DliLoaderImpl.cpp | 4 - .../utc-Dali-Gltf2LoaderImpl.cpp | 4 - .../internal/controls/model/model-impl.cpp | 1 - .../default-physically-based-shader.vert | 6 +- .../model-components/model-node-data-impl.cpp | 7 +- .../public-api/loader/scene-definition.cpp | 217 ------------------ .../public-api/loader/scene-definition.h | 12 - .../public-api/loader/skinning-details.cpp | 1 - .../public-api/loader/skinning-details.h | 1 - 10 files changed, 13 insertions(+), 246 deletions(-) diff --git a/automated-tests/resources/dli_pbr.vsh b/automated-tests/resources/dli_pbr.vsh index d1be30484e..fa6b480b6e 100644 --- a/automated-tests/resources/dli_pbr.vsh +++ b/automated-tests/resources/dli_pbr.vsh @@ -128,9 +128,13 @@ void main() position = bone * position; normal = (bone * vec4(normal, 0.0)).xyz; tangent = (bone * vec4(tangent, 0.0)).xyz; -#endif + normal = normalize(normal); + tangent = normalize(tangent); + vec4 vPosition = position; +#else vec4 vPosition = uModelMatrix * position; +#endif vNormal = normalize(uNormalMatrix * normal); diff --git a/automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp index e23616e416..acfa4ea84f 100644 --- a/automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-DliLoaderImpl.cpp @@ -231,7 +231,6 @@ int UtcDaliDliLoaderLoadSceneExercise(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); @@ -350,7 +349,6 @@ int UtcDaliDliLoaderLoadSceneMorph(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); @@ -415,7 +413,6 @@ int UtcDaliDliLoaderLoadSceneArc(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); @@ -696,7 +693,6 @@ int UtcDaliDliLoaderLoadCoverageTest(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); diff --git a/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp index a40ccaca98..1f274d0605 100644 --- a/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp @@ -616,7 +616,6 @@ int UtcDaliGltfLoaderMRendererTest(void) ctx.resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); root.Add(actor); @@ -672,7 +671,6 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); root.Add(actor); @@ -726,7 +724,6 @@ int UtcDaliGltfLoaderImageFromBufferView(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); root.Add(actor); @@ -776,7 +773,6 @@ int UtcDaliGltfLoaderUint8Indices(void) resources.LoadResources(ctx.pathProvider); if(auto actor = scene.CreateNodes(iRoot, choices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); scene.ApplyConstraints(actor, std::move(nodeParams.mConstrainables)); root.Add(actor); diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index 2f29b25521..be1b7925d0 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -842,7 +842,6 @@ void Model::CreateModel() { if(auto actor = scene.CreateNodes(iRoot, resourceChoices, nodeParams)) { - scene.ConfigureSkeletonJoints(iRoot, resources.mSkeletons, actor); scene.ConfigureSkinningShaders(resources, actor, std::move(nodeParams.mSkinnables)); ConfigureBlendShapeShaders(resources, scene, actor, std::move(nodeParams.mBlendshapeRequests)); diff --git a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert index 4161b3a028..35323d3493 100644 --- a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert +++ b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert @@ -140,9 +140,13 @@ void main() position = bone * position; normal = (bone * vec4(normal, 0.0)).xyz; tangent = (bone * vec4(tangent, 0.0)).xyz; -#endif + normal = normalize(normal); + tangent = normalize(tangent); + highp vec4 positionW = position; +#else highp vec4 positionW = uModelMatrix * position; +#endif highp vec4 positionV = uViewMatrix * positionW; vPositionToCamera = transpose(mat3(uViewMatrix)) * -vec3(positionV.xyz / positionV.w); diff --git a/dali-scene3d/internal/model-components/model-node-data-impl.cpp b/dali-scene3d/internal/model-components/model-node-data-impl.cpp index 308dad90d3..c1d3dbd315 100644 --- a/dali-scene3d/internal/model-components/model-node-data-impl.cpp +++ b/dali-scene3d/internal/model-components/model-node-data-impl.cpp @@ -247,10 +247,9 @@ void ModelNode::Impl::UpdateBoneMatrix(Scene3D::ModelPrimitive primitive) boneData.constraint = Constraint::New(shader, propBoneXform, [inverseMatrix](Matrix& output, const PropertyInputContainer& inputs) { Matrix::Multiply(output, inverseMatrix, inputs[0]->GetMatrix()); }); - Actor joint = mModelNodeImpl.Self(); - auto propJointMatrix = joint.GetPropertyIndex(Dali::Scene3D::Loader::Skinning::JOINT_MATRIX); - boneData.constraint.AddSource(Source{joint, propJointMatrix}); - boneData.constraint.Apply(); + Actor joint = mModelNodeImpl.Self(); + boneData.constraint.AddSource(Source{joint, Actor::Property::WORLD_MATRIX}); + boneData.constraint.ApplyPost(); } break; } diff --git a/dali-scene3d/public-api/loader/scene-definition.cpp b/dali-scene3d/public-api/loader/scene-definition.cpp index 8cc5385451..b1617de5fc 100644 --- a/dali-scene3d/public-api/loader/scene-definition.cpp +++ b/dali-scene3d/public-api/loader/scene-definition.cpp @@ -207,62 +207,6 @@ private: ModelNode mRoot; }; -bool IsAncestor(const SceneDefinition& scene, Index ancestor, Index node, Index rootHint = INVALID_INDEX) -{ - bool isAncestor = false; - while(node != rootHint && !isAncestor) - { - node = scene.GetNode(node)->mParentIdx; - isAncestor = ancestor == node; - } - return isAncestor; -} - -void InsertUniqueSorted(std::vector& data, Index value) -{ - auto iInsert = std::lower_bound(data.begin(), data.end(), value); - if(iInsert == data.end() || *iInsert != value) - { - data.insert(iInsert, value); - } -} - -void RemoveFromSorted(std::vector& data, Index value) -{ - auto iRemove = std::lower_bound(data.begin(), data.end(), value); - if(iRemove != data.end() && *iRemove == value) - { - data.erase(iRemove); - } -} - -Property::Index ConfigureJointMatrix(Actor actor, Actor ancestor, Property::Index propJointMatrix) -{ - Actor parent = actor.GetParent(); - if(parent != ancestor) - { - propJointMatrix = ConfigureJointMatrix(parent, ancestor, propJointMatrix); - } - - auto myPropJointMatrix = actor.GetPropertyIndex(Skinning::JOINT_MATRIX); - if(myPropJointMatrix == Property::INVALID_INDEX) - { - myPropJointMatrix = actor.RegisterProperty(Skinning::JOINT_MATRIX, Matrix{false}); - Constraint constraint = Constraint::New(actor, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) { - Matrix jointMatrix{false}; - jointMatrix.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3()); - - Matrix::Multiply(output, jointMatrix, inputs[2]->GetMatrix()); - }); - constraint.AddSource(Source{actor, Actor::Property::ORIENTATION}); - constraint.AddSource(Source{actor, Actor::Property::POSITION}); - constraint.AddSource(Source{parent, propJointMatrix}); - constraint.Apply(); - } - - return myPropJointMatrix; -} - void SortAndDeduplicateSkinningRequests(std::vector& requests) { // Sort requests by shaders. @@ -813,167 +757,6 @@ void SceneDefinition::ApplyConstraints(Actor& root, } } -void SceneDefinition::ConfigureSkeletonJoints(uint32_t iRoot, const SkeletonDefinition::Vector& skeletons, Actor root) const -{ - // 1, For each skeleton, for each joint, walk upwards until we reach mNodes[iRoot]. If we do, record +1 - // to the refcount of each node we have visited, in our temporary registry. Those with refcount 1 - // are the leaves, while the most descendant node with the highest refcount is the root of the skeleton. - std::map> rootsJoints; - std::vector path; - path.reserve(16); - for(auto& s : skeletons) - { - std::map jointRefs; - for(auto& j : s.mJoints) - { - auto nodeIdx = j.mNodeIdx; - do // Traverse upwards and record each node we have visited until we reach the scene root. - { - path.push_back(nodeIdx); - if(nodeIdx == iRoot) - { - break; - } - auto node = GetNode(nodeIdx); - nodeIdx = node->mParentIdx; - } while(nodeIdx != INVALID_INDEX); - - if(nodeIdx == iRoot) // If the joint is in the correct scene, increment the reference count for all visited nodes. - { - for(auto i : path) - { - ++jointRefs[i]; - } - } - - path.clear(); - } - - // Only record the skeleton if we have encountered the root of the current scene. - if(jointRefs.empty()) - { - continue; - } - - Index root = s.mRootNodeIdx; - uint32_t maxRef = 0; - auto iFind = jointRefs.find(root); - if(iFind != jointRefs.end()) - { - maxRef = iFind->second; - } - - std::vector joints; - for(auto& j : jointRefs) // NOTE: jointRefs are sorted, so joints will also be. - { - // The most descendant node with the highest ref count is the root of the skeleton. - if(j.second > maxRef || (j.second == maxRef && IsAncestor(*this, root, j.first, iRoot))) - { - maxRef = j.second; - - RemoveFromSorted(joints, root); - root = j.first; - } - else if(j.second == 1) // This one's a leaf. - { - InsertUniqueSorted(joints, j.first); - } - } - - // Merge skeletons that share the same root. - auto& finalJoints = rootsJoints[root]; - for(auto j : joints) - { - if(std::find_if(finalJoints.begin(), finalJoints.end(), [this, j, root](Index jj) { - return IsAncestor(*this, j, jj, root); - }) != finalJoints.end()) - { - continue; // if the joint is found to be an ancestor of another joint already registered, move on. - } - - auto i = j; - while(i != root) // See if the current joint is a better leaf, i.e. descended from another leaf - which we'll then remove. - { - auto node = GetNode(i); - i = node->mParentIdx; - - RemoveFromSorted(finalJoints, i); - } - - InsertUniqueSorted(finalJoints, j); - } - } - - // 2, Merge records where one root joint is descendant of another. Handle leaf node changes - remove previous - // leaf nodes that now have descendants, and add new ones. - auto iRoots = rootsJoints.begin(); - auto iRootsEnd = rootsJoints.end(); - while(iRoots != iRootsEnd) - { - auto i = iRoots->first; - bool merged = false; - while(i != iRoot) // Starting with the root joint of the skeleton, traverse upwards. - { - auto node = GetNode(i); - i = node->mParentIdx; - - auto iFind = rootsJoints.find(i); - if(iFind != rootsJoints.end()) // Check if we've reached the root of another skeleton. - { - // Now find out which leaf of iFind is an ancestor, if any. - auto iFindLeaf = std::find_if(iFind->second.begin(), iFind->second.end(), [this, iRoots, iFind](Index j) { - return IsAncestor(*this, j, iRoots->first, iFind->first); - }); - if(iFindLeaf != iFind->second.end()) - { - iFind->second.erase(iFindLeaf); // Will no longer be a leaf -- remove it. - } - - // Merge iRoots with iFind - auto& targetJoints = iFind->second; - if(iRoots->second.empty()) // The root is a leaf. - { - InsertUniqueSorted(targetJoints, iRoots->first); - } - else - for(auto j : iRoots->second) - { - InsertUniqueSorted(targetJoints, j); - } - - merged = true; - break; // Traverse no more - } - } - - iRoots = merged ? rootsJoints.erase(iRoots) : std::next(iRoots); - } - - // 3, For each root, register joint matrices and constraints - for(const auto& r : rootsJoints) - { - auto node = GetNode(r.first); - auto rootJoint = root.FindChildByName(node->mName); - DALI_ASSERT_ALWAYS(!!rootJoint); - - DALI_ASSERT_DEBUG(rootJoint.GetPropertyIndex(Skinning::JOINT_MATRIX) == Property::INVALID_INDEX); - auto propJointMatrix = rootJoint.RegisterProperty(Skinning::JOINT_MATRIX, Matrix{false}); - Constraint constraint = Constraint::New(rootJoint, propJointMatrix, [](Matrix& output, const PropertyInputContainer& inputs) { - output.SetTransformComponents(Vector3::ONE, inputs[0]->GetQuaternion(), inputs[1]->GetVector3()); - }); - constraint.AddSource(Source(rootJoint, Actor::Property::ORIENTATION)); - constraint.AddSource(Source(rootJoint, Actor::Property::POSITION)); - constraint.Apply(); - - for(const auto j : r.second) - { - node = GetNode(j); - auto joint = rootJoint.FindChildByName(node->mName); - ConfigureJointMatrix(joint, rootJoint, propJointMatrix); - } - } -} - void SceneDefinition::EnsureUniqueSkinningShaderInstances(ResourceBundle& resources) const { std::map>> skinningShaderUsers; diff --git a/dali-scene3d/public-api/loader/scene-definition.h b/dali-scene3d/public-api/loader/scene-definition.h index 06d24dbb35..312b9e601e 100644 --- a/dali-scene3d/public-api/loader/scene-definition.h +++ b/dali-scene3d/public-api/loader/scene-definition.h @@ -198,18 +198,6 @@ public: // METHODS std::vector&& constrainables, StringCallback onError = DefaultErrorCallback) const; - /* - * @brief Sets up joint matrix properties and constraints on actors that are involved in skeletal - * animation (i.e. those that are between (inclusive) the lower and upper bounds of any skeleton), - * to ensure the correct update of meshes skinned to these skeletons. - * @param iRoot The index of the scene root node. Skeletons that aren't descendants of this node - * will be ignored. - * @param skeletons The list of skeletons that require setting up. - * @param rootActor The Actor corresponding to the root node, which will be used to locate - * other actors. - */ - void ConfigureSkeletonJoints(uint32_t iRoot, const SkeletonDefinition::Vector& skeletons, Actor rootActor) const; - /* * @brief Ensures that there is no overlap between shaders used by nodes that have * meshes skinned to different skeletons. diff --git a/dali-scene3d/public-api/loader/skinning-details.cpp b/dali-scene3d/public-api/loader/skinning-details.cpp index fc18d40f34..0e5e499ac0 100644 --- a/dali-scene3d/public-api/loader/skinning-details.cpp +++ b/dali-scene3d/public-api/loader/skinning-details.cpp @@ -28,5 +28,4 @@ namespace Dali::Scene3D::Loader const unsigned int Skinning::MAX_JOINTS = 64; const char* Skinning::BONE_UNIFORM_NAME = "uBone"; -const char* Skinning::JOINT_MATRIX = "jointMatrix"; } // namespace Dali::Scene3D::Loader diff --git a/dali-scene3d/public-api/loader/skinning-details.h b/dali-scene3d/public-api/loader/skinning-details.h index ca0bdc2514..59f778a160 100644 --- a/dali-scene3d/public-api/loader/skinning-details.h +++ b/dali-scene3d/public-api/loader/skinning-details.h @@ -50,7 +50,6 @@ public: * @brief Name of bone matrix uniform (array). */ static const char* BONE_UNIFORM_NAME; - static const char* JOINT_MATRIX; Skinning() = delete; }; -- 2.34.1