Fix bone-attached entities (#10015) master
authorhecktest <42101236+hecktest@users.noreply.github.com>
Thu, 25 Jun 2020 22:06:29 +0000 (00:06 +0200)
committerGitHub <noreply@github.com>
Thu, 25 Jun 2020 22:06:29 +0000 (00:06 +0200)
src/client/content_cao.cpp

index 7f573b5a10b149afd9b08e05c8de38e08cde0c29..4f949f6b037f2cd56e3234556e4e2fe6eb7b5253 100644 (file)
@@ -162,6 +162,15 @@ static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
        matrix.setTextureScale(txs, tys);
 }
 
        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
 */
 /*
        TestCAO
 */
@@ -929,11 +938,6 @@ void GenericCAO::updateNodePos()
 
 void GenericCAO::step(float dtime, ClientEnvironment *env)
 {
 
 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();
        // 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();
        }
                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()
 }
 
 void GenericCAO::updateTexturePos()
@@ -1444,6 +1460,18 @@ void GenericCAO::updateBonePosition()
                        bone->updateAbsolutePosition();
                }
        }
                        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()
 }
 
 void GenericCAO::updateAttachments()