diff --git a/irr/include/SkinnedMesh.h b/irr/include/SkinnedMesh.h index f9c80b318..c3ecfc68a 100644 --- a/irr/include/SkinnedMesh.h +++ b/irr/include/SkinnedMesh.h @@ -231,7 +231,7 @@ public: static core::quaternion interpolateValue(core::quaternion from, core::quaternion to, f32 time) { core::quaternion result; - result.slerp(from, to, time, 0.001f); + result.slerp(from, to, time); return result; } diff --git a/irr/include/Transform.h b/irr/include/Transform.h index dbc8294e6..ca9c1339e 100644 --- a/irr/include/Transform.h +++ b/irr/include/Transform.h @@ -2,7 +2,6 @@ #include "irrMath.h" #include -#include #include #include @@ -27,12 +26,23 @@ struct Transform { }; } + + Transform interpolate(Transform to, f32 time) const + { + core::quaternion interpolated_rotation; + interpolated_rotation.slerp(rotation, to.rotation, time); + return { + to.translation.getInterpolated(translation, time), + interpolated_rotation, + to.scale.getInterpolated(scale, time), + }; + } + matrix4 buildMatrix() const { matrix4 T; T.setTranslation(translation); matrix4 R; - // TODO this is sussy. probably shouldn't be doing this. rotation.getMatrix_transposed(R); matrix4 S; S.setScale(scale); @@ -41,4 +51,4 @@ struct Transform { }; } // end namespace core -} // end namespace irr \ No newline at end of file +} // end namespace irr diff --git a/irr/include/quaternion.h b/irr/include/quaternion.h index e23b1317d..42e0428a9 100644 --- a/irr/include/quaternion.h +++ b/irr/include/quaternion.h @@ -180,7 +180,7 @@ public: linear interpolation. */ quaternion &slerp(quaternion q1, quaternion q2, - f32 time, f32 threshold = .05f); + f32 time, f32 threshold = .001f); //! Set this quaternion to represent a rotation from angle and axis. /** Axis must be unit length. diff --git a/irr/src/CAnimatedMeshSceneNode.cpp b/irr/src/CAnimatedMeshSceneNode.cpp index b68963aeb..19dd47cb2 100644 --- a/irr/src/CAnimatedMeshSceneNode.cpp +++ b/irr/src/CAnimatedMeshSceneNode.cpp @@ -540,6 +540,8 @@ void CAnimatedMeshSceneNode::addJoints() const auto &joints = static_cast(Mesh)->getAllJoints(); JointChildSceneNodes.clear(); JointChildSceneNodes.reserve(joints.size()); + PretransitingSave.clear(); + PretransitingSave.resize(JointChildSceneNodes.size()); for (size_t i = 0; i < joints.size(); ++i) { const auto *joint = joints[i]; ISceneNode *parent = this; @@ -587,43 +589,11 @@ void CAnimatedMeshSceneNode::animateJoints() //----------------------------------------- if (Transiting != 0.f) { - // Init additional matrices - if (PretransitingSave.size() < JointChildSceneNodes.size()) { - for (u32 n = PretransitingSave.size(); n < JointChildSceneNodes.size(); ++n) - PretransitingSave.push_back(core::matrix4()); - } - - for (u32 n = 0; n < JointChildSceneNodes.size(); ++n) { - //------Position------ - - JointChildSceneNodes[n]->setPosition( - core::lerp( - PretransitingSave[n].getTranslation(), - JointChildSceneNodes[n]->getPosition(), - TransitingBlend)); - - //------Rotation------ - - // Code is slow, needs to be fixed up - - const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees() * core::DEGTORAD); - const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation() * core::DEGTORAD); - - core::quaternion QRotation; - QRotation.slerp(RotationStart, RotationEnd, TransitingBlend); - - core::vector3df tmpVector; - QRotation.toEuler(tmpVector); - tmpVector *= core::RADTODEG; // convert from radians back to degrees - JointChildSceneNodes[n]->setRotation(tmpVector); - - //------Scale------ - - // JointChildSceneNodes[n]->setScale( - // core::lerp( - // PretransitingSave[n].getScale(), - // JointChildSceneNodes[n]->getScale(), - // TransitingBlend)); + for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) { + if (PretransitingSave[i]) { + JointChildSceneNodes[i]->setTransform(PretransitingSave[i]->interpolate( + JointChildSceneNodes[i]->getTransform(), TransitingBlend)); + } } } } @@ -648,16 +618,15 @@ void CAnimatedMeshSceneNode::beginTransition() return; if (TransitionTime != 0) { - // Check the array is big enough - if (PretransitingSave.size() < JointChildSceneNodes.size()) { - for (u32 n = PretransitingSave.size(); n < JointChildSceneNodes.size(); ++n) - PretransitingSave.push_back(core::matrix4()); + // Copy the transforms of animated joints + for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) { + if (!JointChildSceneNodes[i]->Matrix) { + PretransitingSave[i] = JointChildSceneNodes[i]->getTransform(); + } else { + PretransitingSave[i] = std::nullopt; + } } - // Copy the position of joints - for (u32 n = 0; n < JointChildSceneNodes.size(); ++n) - PretransitingSave[n] = JointChildSceneNodes[n]->getRelativeTransformation(); - Transiting = core::reciprocal((f32)TransitionTime); } TransitingBlend = 0.f; diff --git a/irr/src/CAnimatedMeshSceneNode.h b/irr/src/CAnimatedMeshSceneNode.h index 73c258546..daf9dbb4b 100644 --- a/irr/src/CAnimatedMeshSceneNode.h +++ b/irr/src/CAnimatedMeshSceneNode.h @@ -4,11 +4,12 @@ #pragma once +#include "CBoneSceneNode.h" #include "IAnimatedMeshSceneNode.h" #include "IAnimatedMesh.h" #include "SkinnedMesh.h" -#include "matrix4.h" +#include "Transform.h" namespace irr { @@ -171,8 +172,8 @@ private: s32 PassCount; std::function OnAnimateCallback; - std::vector JointChildSceneNodes; - core::array PretransitingSave; + std::vector JointChildSceneNodes; + std::vector> PretransitingSave; }; } // end namespace scene diff --git a/irr/src/CBoneSceneNode.h b/irr/src/CBoneSceneNode.h index bdb5e75a6..4151f7372 100644 --- a/irr/src/CBoneSceneNode.h +++ b/irr/src/CBoneSceneNode.h @@ -46,6 +46,15 @@ public: setScale(transform.scale); } + core::Transform getTransform() const + { + return { + getPosition(), + core::quaternion(getRotation() * core::DEGTORAD).makeInverse(), + getScale() + }; + } + core::matrix4 getRelativeTransformation() const override { if (Matrix)