mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Fix and clean up skeletal animation (#15722)
* Fix attachments lagging behind their parents (#14818) * Fix animation blending (#14817) * Bring back cool guy as another .x smoke test * Add .x mesh loader unittest * Do bounding box & matrix calculation at proper point in time * Remove obsolete `SAnimatedMesh`
This commit is contained in:
parent
0bb87eb1ff
commit
fde6384a09
40 changed files with 856 additions and 1388 deletions
|
@ -539,34 +539,25 @@ static core::matrix4 loadTransform(const tiniergltf::Node::Matrix &m, SkinnedMes
|
|||
mat[i] = static_cast<f32>(m[i]);
|
||||
mat = convertHandedness(mat);
|
||||
|
||||
// Decompose the matrix into translation, scale, and rotation.
|
||||
joint->Animatedposition = mat.getTranslation();
|
||||
|
||||
auto scale = mat.getScale();
|
||||
joint->Animatedscale = scale;
|
||||
joint->Animatedrotation = mat.getRotationRadians(scale);
|
||||
// Invert the rotation because it is applied using `getMatrix_transposed`,
|
||||
// which again inverts.
|
||||
joint->Animatedrotation.makeInverse();
|
||||
|
||||
// Note: "When a node is targeted for animation [...],
|
||||
// only TRS properties MAY be present; matrix MUST NOT be present."
|
||||
// Thus we MUST NOT do any decomposition, which in general need not exist.
|
||||
joint->transform = mat;
|
||||
return mat;
|
||||
}
|
||||
|
||||
static core::matrix4 loadTransform(const tiniergltf::Node::TRS &trs, SkinnedMesh::SJoint *joint)
|
||||
{
|
||||
const auto &trans = trs.translation;
|
||||
const auto &rot = trs.rotation;
|
||||
const auto &scale = trs.scale;
|
||||
core::matrix4 transMat;
|
||||
joint->Animatedposition = convertHandedness(core::vector3df(trans[0], trans[1], trans[2]));
|
||||
transMat.setTranslation(joint->Animatedposition);
|
||||
core::matrix4 rotMat;
|
||||
joint->Animatedrotation = convertHandedness(core::quaternion(rot[0], rot[1], rot[2], rot[3]));
|
||||
core::quaternion(joint->Animatedrotation).getMatrix_transposed(rotMat);
|
||||
joint->Animatedscale = core::vector3df(scale[0], scale[1], scale[2]);
|
||||
core::matrix4 scaleMat;
|
||||
scaleMat.setScale(joint->Animatedscale);
|
||||
return transMat * rotMat * scaleMat;
|
||||
const auto &t = trs.translation;
|
||||
const auto &r = trs.rotation;
|
||||
const auto &s = trs.scale;
|
||||
core::Transform transform{
|
||||
convertHandedness(core::vector3df(t[0], t[1], t[2])),
|
||||
convertHandedness(core::quaternion(r[0], r[1], r[2], r[3])),
|
||||
core::vector3df(s[0], s[1], s[2]),
|
||||
};
|
||||
joint->transform = transform;
|
||||
return transform.buildMatrix();
|
||||
}
|
||||
|
||||
static core::matrix4 loadTransform(std::optional<std::variant<tiniergltf::Node::Matrix, tiniergltf::Node::TRS>> transform,
|
||||
|
@ -584,8 +575,7 @@ void SelfType::MeshExtractor::loadNode(
|
|||
const auto &node = m_gltf_model.nodes->at(nodeIdx);
|
||||
auto *joint = m_irr_model->addJoint(parent);
|
||||
const core::matrix4 transform = loadTransform(node.transform, joint);
|
||||
joint->LocalMatrix = transform;
|
||||
joint->GlobalMatrix = parent ? parent->GlobalMatrix * joint->LocalMatrix : joint->LocalMatrix;
|
||||
joint->GlobalMatrix = parent ? parent->GlobalMatrix * transform : transform;
|
||||
if (node.name.has_value()) {
|
||||
joint->Name = node.name->c_str();
|
||||
}
|
||||
|
@ -642,7 +632,6 @@ void SelfType::MeshExtractor::loadAnimation(const std::size_t animIdx)
|
|||
{
|
||||
const auto &anim = m_gltf_model.animations->at(animIdx);
|
||||
for (const auto &channel : anim.channels) {
|
||||
|
||||
const auto &sampler = anim.samplers.at(channel.sampler);
|
||||
|
||||
bool interpolate = ([&]() {
|
||||
|
@ -663,6 +652,11 @@ void SelfType::MeshExtractor::loadAnimation(const std::size_t animIdx)
|
|||
throw std::runtime_error("no animated node");
|
||||
|
||||
auto *joint = m_loaded_nodes.at(*channel.target.node);
|
||||
if (std::holds_alternative<core::matrix4>(joint->transform)) {
|
||||
warn("nodes using matrix transforms must not be animated");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (channel.target.path) {
|
||||
case tiniergltf::AnimationChannelTarget::Path::TRANSLATION: {
|
||||
const auto outputAccessor = Accessor<core::vector3df>::make(m_gltf_model, sampler.output);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue