1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Fix animation blending

This commit is contained in:
Lars Mueller 2025-01-26 17:38:50 +01:00
parent a5180fbb28
commit c7c99296cb
6 changed files with 42 additions and 53 deletions

View file

@ -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;
}

View file

@ -2,7 +2,6 @@
#include "irrMath.h"
#include <matrix4.h>
#include <variant>
#include <vector3d.h>
#include <quaternion.h>
@ -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);

View file

@ -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.

View file

@ -540,6 +540,8 @@ void CAnimatedMeshSceneNode::addJoints()
const auto &joints = static_cast<SkinnedMesh*>(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 i = 0; i < JointChildSceneNodes.size(); ++i) {
if (PretransitingSave[i]) {
JointChildSceneNodes[i]->setTransform(PretransitingSave[i]->interpolate(
JointChildSceneNodes[i]->getTransform(), TransitingBlend));
}
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));
}
}
}
@ -648,15 +618,14 @@ 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);
}

View file

@ -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<void(f32)> OnAnimateCallback;
std::vector<IBoneSceneNode *> JointChildSceneNodes;
core::array<core::matrix4> PretransitingSave;
std::vector<CBoneSceneNode *> JointChildSceneNodes;
std::vector<std::optional<core::Transform>> PretransitingSave;
};
} // end namespace scene

View file

@ -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)