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:
parent
a5180fbb28
commit
c7c99296cb
6 changed files with 42 additions and 53 deletions
|
@ -231,7 +231,7 @@ public:
|
||||||
|
|
||||||
static core::quaternion interpolateValue(core::quaternion from, core::quaternion to, f32 time) {
|
static core::quaternion interpolateValue(core::quaternion from, core::quaternion to, f32 time) {
|
||||||
core::quaternion result;
|
core::quaternion result;
|
||||||
result.slerp(from, to, time, 0.001f);
|
result.slerp(from, to, time);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "irrMath.h"
|
#include "irrMath.h"
|
||||||
#include <matrix4.h>
|
#include <matrix4.h>
|
||||||
#include <variant>
|
|
||||||
#include <vector3d.h>
|
#include <vector3d.h>
|
||||||
#include <quaternion.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 buildMatrix() const
|
||||||
{
|
{
|
||||||
matrix4 T;
|
matrix4 T;
|
||||||
T.setTranslation(translation);
|
T.setTranslation(translation);
|
||||||
matrix4 R;
|
matrix4 R;
|
||||||
// TODO this is sussy. probably shouldn't be doing this.
|
|
||||||
rotation.getMatrix_transposed(R);
|
rotation.getMatrix_transposed(R);
|
||||||
matrix4 S;
|
matrix4 S;
|
||||||
S.setScale(scale);
|
S.setScale(scale);
|
||||||
|
@ -41,4 +51,4 @@ struct Transform {
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace core
|
} // end namespace core
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
|
@ -180,7 +180,7 @@ public:
|
||||||
linear interpolation.
|
linear interpolation.
|
||||||
*/
|
*/
|
||||||
quaternion &slerp(quaternion q1, quaternion q2,
|
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.
|
//! Set this quaternion to represent a rotation from angle and axis.
|
||||||
/** Axis must be unit length.
|
/** Axis must be unit length.
|
||||||
|
|
|
@ -540,6 +540,8 @@ void CAnimatedMeshSceneNode::addJoints()
|
||||||
const auto &joints = static_cast<SkinnedMesh*>(Mesh)->getAllJoints();
|
const auto &joints = static_cast<SkinnedMesh*>(Mesh)->getAllJoints();
|
||||||
JointChildSceneNodes.clear();
|
JointChildSceneNodes.clear();
|
||||||
JointChildSceneNodes.reserve(joints.size());
|
JointChildSceneNodes.reserve(joints.size());
|
||||||
|
PretransitingSave.clear();
|
||||||
|
PretransitingSave.resize(JointChildSceneNodes.size());
|
||||||
for (size_t i = 0; i < joints.size(); ++i) {
|
for (size_t i = 0; i < joints.size(); ++i) {
|
||||||
const auto *joint = joints[i];
|
const auto *joint = joints[i];
|
||||||
ISceneNode *parent = this;
|
ISceneNode *parent = this;
|
||||||
|
@ -587,43 +589,11 @@ void CAnimatedMeshSceneNode::animateJoints()
|
||||||
//-----------------------------------------
|
//-----------------------------------------
|
||||||
|
|
||||||
if (Transiting != 0.f) {
|
if (Transiting != 0.f) {
|
||||||
// Init additional matrices
|
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) {
|
||||||
if (PretransitingSave.size() < JointChildSceneNodes.size()) {
|
if (PretransitingSave[i]) {
|
||||||
for (u32 n = PretransitingSave.size(); n < JointChildSceneNodes.size(); ++n)
|
JointChildSceneNodes[i]->setTransform(PretransitingSave[i]->interpolate(
|
||||||
PretransitingSave.push_back(core::matrix4());
|
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,16 +618,15 @@ void CAnimatedMeshSceneNode::beginTransition()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (TransitionTime != 0) {
|
if (TransitionTime != 0) {
|
||||||
// Check the array is big enough
|
// Copy the transforms of animated joints
|
||||||
if (PretransitingSave.size() < JointChildSceneNodes.size()) {
|
for (u32 i = 0; i < JointChildSceneNodes.size(); ++i) {
|
||||||
for (u32 n = PretransitingSave.size(); n < JointChildSceneNodes.size(); ++n)
|
if (!JointChildSceneNodes[i]->Matrix) {
|
||||||
PretransitingSave.push_back(core::matrix4());
|
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);
|
Transiting = core::reciprocal((f32)TransitionTime);
|
||||||
}
|
}
|
||||||
TransitingBlend = 0.f;
|
TransitingBlend = 0.f;
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "CBoneSceneNode.h"
|
||||||
#include "IAnimatedMeshSceneNode.h"
|
#include "IAnimatedMeshSceneNode.h"
|
||||||
#include "IAnimatedMesh.h"
|
#include "IAnimatedMesh.h"
|
||||||
|
|
||||||
#include "SkinnedMesh.h"
|
#include "SkinnedMesh.h"
|
||||||
#include "matrix4.h"
|
#include "Transform.h"
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
|
@ -171,8 +172,8 @@ private:
|
||||||
s32 PassCount;
|
s32 PassCount;
|
||||||
std::function<void(f32)> OnAnimateCallback;
|
std::function<void(f32)> OnAnimateCallback;
|
||||||
|
|
||||||
std::vector<IBoneSceneNode *> JointChildSceneNodes;
|
std::vector<CBoneSceneNode *> JointChildSceneNodes;
|
||||||
core::array<core::matrix4> PretransitingSave;
|
std::vector<std::optional<core::Transform>> PretransitingSave;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace scene
|
} // end namespace scene
|
||||||
|
|
|
@ -46,6 +46,15 @@ public:
|
||||||
setScale(transform.scale);
|
setScale(transform.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core::Transform getTransform() const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
getPosition(),
|
||||||
|
core::quaternion(getRotation() * core::DEGTORAD).makeInverse(),
|
||||||
|
getScale()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
core::matrix4 getRelativeTransformation() const override
|
core::matrix4 getRelativeTransformation() const override
|
||||||
{
|
{
|
||||||
if (Matrix)
|
if (Matrix)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue