From 7be082f9a8bb6bd46c226d7ef4c42f0fd9fe7314 Mon Sep 17 00:00:00 2001 From: hecktest <42101236+hecktest@users.noreply.github.com> Date: Fri, 26 Jun 2020 00:06:29 +0200 Subject: [PATCH] Fix bone-attached entities (#10015) --- src/client/content_cao.cpp | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 7f573b5a1..4f949f6b0 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -162,6 +162,15 @@ static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill, matrix.setTextureScale(txs, tys); } +// Evaluate transform chain recursively; irrlicht does not do this for us +static void updatePositionRecursive(scene::ISceneNode *node) +{ + scene::ISceneNode *parent = node->getParent(); + if (parent) + updatePositionRecursive(parent); + node->updateAbsolutePosition(); +} + /* TestCAO */ @@ -929,11 +938,6 @@ void GenericCAO::updateNodePos() void GenericCAO::step(float dtime, ClientEnvironment *env) { - if (m_animated_meshnode) { - m_animated_meshnode->animateJoints(); - updateBonePosition(); - } - // Handle model animations and update positions instantly to prevent lags if (m_is_local_player) { LocalPlayer *player = m_env->getLocalPlayer(); @@ -1143,6 +1147,18 @@ void GenericCAO::step(float dtime, ClientEnvironment *env) rot_translator.val_current = m_rotation; updateNodePos(); } + + if (m_animated_meshnode) { + // Everything must be updated; the whole transform + // chain as well as the animated mesh node. + // Otherwise, bone attachments would be relative to + // a position that's one frame old. + if (m_matrixnode) + updatePositionRecursive(m_matrixnode); + m_animated_meshnode->updateAbsolutePosition(); + m_animated_meshnode->animateJoints(); + updateBonePosition(); + } } void GenericCAO::updateTexturePos() @@ -1444,6 +1460,18 @@ void GenericCAO::updateBonePosition() bone->updateAbsolutePosition(); } } + // The following is needed for set_bone_pos to propagate to + // attached objects correctly. + // Irrlicht ought to do this, but doesn't when using EJUOR_CONTROL. + for (u32 i = 0; i < m_animated_meshnode->getJointCount(); ++i) { + auto bone = m_animated_meshnode->getJointNode(i); + // Look for the root bone. + if (bone && bone->getParent() == m_animated_meshnode) { + // Update entire skeleton. + bone->updateAbsolutePositionOfAllChildren(); + break; + } + } } void GenericCAO::updateAttachments()