From a5180fbb2899258d2acf126215261506601cfdb6 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Sun, 26 Jan 2025 01:37:39 +0100 Subject: [PATCH] do it properly --- irr/include/SkinnedMesh.h | 10 +++--- irr/src/CAnimatedMeshSceneNode.cpp | 23 ++++++------ irr/src/CBoneSceneNode.h | 18 ++++++++-- irr/src/MatrixBoneSceneNode.h | 56 ------------------------------ irr/src/SkinnedMesh.cpp | 1 - 5 files changed, 33 insertions(+), 75 deletions(-) delete mode 100644 irr/src/MatrixBoneSceneNode.h diff --git a/irr/include/SkinnedMesh.h b/irr/include/SkinnedMesh.h index fbfd29aa8..f9c80b318 100644 --- a/irr/include/SkinnedMesh.h +++ b/irr/include/SkinnedMesh.h @@ -319,8 +319,10 @@ public: return transform; if (std::holds_alternative(transform)) { - // TODO raise a warning: Attempt to animate a static joint. - return transform; + // .x lets animations override matrix transforms entirely. + core::Transform trs; + keys.updateTransform(frame, trs); + return {trs}; } auto trs = std::get(transform); @@ -346,7 +348,7 @@ public: // The .x and .gltf formats pre-calculate this std::optional GlobalInversedMatrix; - + // TODO friends? u16 JointID; // TODO refactor away: pointers -> IDs std::optional ParentJointID; @@ -357,7 +359,7 @@ public: core::aabbox3df calculateBoundingBox( const std::vector &global_transforms); - + void recalculateBaseBoundingBoxes(); const std::vector &getAllJoints() const { diff --git a/irr/src/CAnimatedMeshSceneNode.cpp b/irr/src/CAnimatedMeshSceneNode.cpp index a5cd190d8..b68963aeb 100644 --- a/irr/src/CAnimatedMeshSceneNode.cpp +++ b/irr/src/CAnimatedMeshSceneNode.cpp @@ -6,7 +6,6 @@ #include "CBoneSceneNode.h" #include "IVideoDriver.h" #include "ISceneManager.h" -#include "MatrixBoneSceneNode.h" #include "S3DVertex.h" #include "Transform.h" #include "matrix4.h" @@ -22,6 +21,7 @@ #include "quaternion.h" #include #include +#include namespace irr { @@ -546,14 +546,11 @@ void CAnimatedMeshSceneNode::addJoints() if (joint->ParentJointID) parent = JointChildSceneNodes.at(*joint->ParentJointID); // exists because of topo. order assert(parent); - if (const auto *matrix = std::get_if(&joint->transform)) { - JointChildSceneNodes.push_back(new MatrixBoneSceneNode( - parent, SceneManager, 0, i, joint->Name, *matrix)); - } else { - JointChildSceneNodes.push_back(new CBoneSceneNode( - parent, SceneManager, 0, i, joint->Name, - std::get(joint->transform))); - } + const auto *matrix = std::get_if(&joint->transform); + JointChildSceneNodes.push_back(new CBoneSceneNode( + parent, SceneManager, 0, i, joint->Name, + matrix ? core::Transform{} : std::get(joint->transform), + matrix ? *matrix : std::optional{})); } } @@ -562,11 +559,13 @@ void CAnimatedMeshSceneNode::updateJointSceneNodes( { for (size_t i = 0; i < transforms.size(); ++i) { const auto &transform = transforms[i]; - IBoneSceneNode *node = JointChildSceneNodes[i]; + auto *node = static_cast(JointChildSceneNodes[i]); if (const auto *trs = std::get_if(&transform)) { - dynamic_cast(node)->setTransform(*trs); + node->setTransform(*trs); + // .x lets animations override matrix transforms entirely. + node->Matrix = std::nullopt; } else { - assert(dynamic_cast(node)); + node->Matrix = std::get(transform); } } } diff --git a/irr/src/CBoneSceneNode.h b/irr/src/CBoneSceneNode.h index 1da8fca8d..bdb5e75a6 100644 --- a/irr/src/CBoneSceneNode.h +++ b/irr/src/CBoneSceneNode.h @@ -8,6 +8,7 @@ #include "IBoneSceneNode.h" #include "Transform.h" +#include "matrix4.h" #include @@ -23,8 +24,10 @@ public: CBoneSceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id = -1, u32 boneIndex = 0, const std::optional &boneName = std::nullopt, - const core::Transform &transform = {}) : - IBoneSceneNode(parent, mgr, id, boneIndex, boneName) + const core::Transform &transform = {}, + const std::optional &matrix = std::nullopt) : + IBoneSceneNode(parent, mgr, id, boneIndex, boneName), + Matrix(matrix) { setTransform(transform); } @@ -42,6 +45,17 @@ public: } setScale(transform.scale); } + + core::matrix4 getRelativeTransformation() const override + { + if (Matrix) + return *Matrix; + return IBoneSceneNode::getRelativeTransformation(); + } + + //! Some file formats alternatively let bones specify a transformation matrix. + //! If this is set, it overrides the TRS properties. + std::optional Matrix; }; } // end namespace scene diff --git a/irr/src/MatrixBoneSceneNode.h b/irr/src/MatrixBoneSceneNode.h deleted file mode 100644 index c56fb02ae..000000000 --- a/irr/src/MatrixBoneSceneNode.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2025 Joe Mama -// SPDX-License-Identifier: LGPL-2.1-or-later - -#pragma once - -#include "IBoneSceneNode.h" -#include "matrix4.h" -#include "vector3d.h" -#include - -#include - -// We must represent some transforms differently: -// Bones can have static non-TRS matrix transforms, -// for example shearing (can not be decomposed at all) -// or negatively scaling an axis (can not be decomposed uniquely). -// Hence well-defined animation is not possible for such nodes -// (and in fact glTF even guarantees that they will never be animated). - -namespace irr -{ -namespace scene -{ - -class MatrixBoneSceneNode : public IBoneSceneNode -{ -public: - //! constructor - MatrixBoneSceneNode(ISceneNode *parent, ISceneManager *mgr, - s32 id = -1, u32 boneIndex = 0, - const std::optional &boneName = std::nullopt, - const core::matrix4 &matrix = core::IdentityMatrix) : - IBoneSceneNode(parent, mgr, id, boneIndex, boneName), - matrix(matrix) - {} - - const core::matrix4 matrix; - - // Matrix nodes should not be fake decomposed. - const core::vector3df &getPosition() const override { assert(false); } - const core::vector3df &getRotation() const override { assert(false); } - const core::vector3df &getScale() const override { assert(false); } - - // This node should be static. - void setPosition(const core::vector3df &pos) override { assert(false); } - void setRotation(const core::vector3df &euler_deg) override { assert(false); } - void setScale(const core::vector3df &scale) override { assert(false); } - - core::matrix4 getRelativeTransformation() const override - { - return matrix; - } -}; - -} // end namespace scene -} // end namespace irr diff --git a/irr/src/SkinnedMesh.cpp b/irr/src/SkinnedMesh.cpp index 1237c3b6d..8b3fba427 100644 --- a/irr/src/SkinnedMesh.cpp +++ b/irr/src/SkinnedMesh.cpp @@ -6,7 +6,6 @@ #include "IBoneSceneNode.h" #include "CBoneSceneNode.h" #include "IAnimatedMeshSceneNode.h" -#include "MatrixBoneSceneNode.h" #include "SSkinMeshBuffer.h" #include "Transform.h" #include "aabbox3d.h"