From e1fc72c6f3450c82e2dd3e0892838498a6a8a092 Mon Sep 17 00:00:00 2001 From: theviper121 Date: Sun, 26 Apr 2020 12:32:04 -0500 Subject: [PATCH] Fix UpdateBonePosition() breaking animations (#9577) --- src/client/content_cao.cpp | 48 +++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index e9e1cebd3..aadd33bb9 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -890,6 +890,11 @@ 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(); @@ -1360,16 +1365,41 @@ void GenericCAO::updateBonePosition() return; m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render - for(std::unordered_map>::const_iterator - ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { - std::string bone_name = (*ii).first; - v3f bone_pos = (*ii).second.X; - v3f bone_rot = (*ii).second.Y; + for (auto &it : m_bone_position) { + std::string bone_name = it.first; irr::scene::IBoneSceneNode* bone = m_animated_meshnode->getJointNode(bone_name.c_str()); - if(bone) - { - bone->setPosition(bone_pos); + if (bone) { + bone->setPosition(it.second.X); + bone->setRotation(it.second.Y); + } + } + + // search through bones to find mistakenly rotated bones due to bug in Irrlicht + for (u32 i = 0; i < m_animated_meshnode->getJointCount(); ++i) { + irr::scene::IBoneSceneNode *bone = m_animated_meshnode->getJointNode(i); + if (!bone) + continue; + + //If bone is manually positioned there is no need to perform the bug check + bool skip = false; + for (auto &it : m_bone_position) { + if (it.first == bone->getName()) { + skip = true; + break; + } + } + if (skip) + continue; + + // Workaround for Irrlicht bug + // We check each bone to see if it has been rotated ~180deg from its expected position due to a bug in Irricht + // when using EJUOR_CONTROL joint control. If the bug is detected we update the bone to the proper position + // and update the bones transformation. + v3f bone_rot = bone->getRelativeTransformation().getRotationDegrees(); + float offset = fabsf(bone_rot.X - bone->getRotation().X); + if (offset > 179.9f && offset < 180.1f) { bone->setRotation(bone_rot); + bone->updateAbsolutePosition(); } } } @@ -1583,7 +1613,7 @@ void GenericCAO::processMessage(const std::string &data) v3f rotation = readV3F32(is); m_bone_position[bone] = core::vector2d(position, rotation); - updateBonePosition(); + // updateBonePosition(); now called every step } else if (cmd == AO_CMD_ATTACH_TO) { u16 parent_id = readS16(is); std::string bone = deSerializeString(is);