From cf7df156490ea5e40545ea1cc1f30d562061ea2c Mon Sep 17 00:00:00 2001 From: FirEmerald Date: Fri, 30 Jan 2026 21:26:32 -0600 Subject: [PATCH 1/3] Remove redundant trig functions remove a redundant acos() call in SolveTwoBoneIK calculate sinAlpha directly from cosAlpha --- src/hooking/skeleton.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hooking/skeleton.cpp b/src/hooking/skeleton.cpp index 43e56e6..d88b5b3 100644 --- a/src/hooking/skeleton.cpp +++ b/src/hooking/skeleton.cpp @@ -134,8 +134,8 @@ class Skeleton { dist = glm::clamp(dist, epsilon, l1 + l2 - epsilon); // law of cosines for angle at shoulder (alpha) - float cosAlpha = (l1 * l1 + dist * dist - l2 * l2) / (2 * l1 * dist); - float alpha = glm::acos(glm::clamp(cosAlpha, -1.0f, 1.0f)); + float cosAlpha = std::clamp((l1 * l1 + dist * dist - l2 * l2) / (2 * l1 * dist), -1.0f, 1.0f); + float sinAlpha = std::sqrt(1.0 - cosAlpha * cosAlpha); // plane construction glm::vec3 dirNorm = glm::normalize(dir); @@ -143,7 +143,7 @@ class Skeleton { glm::vec3 ortho = glm::normalize(glm::cross(planeNormal, dirNorm)); // arm 1 direction (world) - glm::vec3 arm1Dir = glm::normalize(dirNorm * cos(alpha) + ortho * sin(alpha)); + glm::vec3 arm1Dir = glm::normalize(dirNorm * cosAlpha + ortho * sinAlpha); // arm 2 direction (world) glm::vec3 elbowPos = rootPos + arm1Dir * l1; From 28f717d23112e743d240db33b34588e43e289fd0 Mon Sep 17 00:00:00 2001 From: FirEmerald Date: Fri, 30 Jan 2026 21:33:17 -0600 Subject: [PATCH 2/3] propagate back arm IK inversion fix propagate negations all the way back into poleDir negate sinAlpha to counteract --- src/hooking/skeleton.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooking/skeleton.cpp b/src/hooking/skeleton.cpp index d88b5b3..3c997f2 100644 --- a/src/hooking/skeleton.cpp +++ b/src/hooking/skeleton.cpp @@ -135,7 +135,7 @@ class Skeleton { // law of cosines for angle at shoulder (alpha) float cosAlpha = std::clamp((l1 * l1 + dist * dist - l2 * l2) / (2 * l1 * dist), -1.0f, 1.0f); - float sinAlpha = std::sqrt(1.0 - cosAlpha * cosAlpha); + float sinAlpha = -std::sqrt(1.0 - cosAlpha * cosAlpha); // plane construction glm::vec3 dirNorm = glm::normalize(dir); @@ -153,12 +153,12 @@ class Skeleton { glm::vec3 x1 = arm1Dir * boneForwardSign; glm::vec3 z1 = planeNormal; glm::vec3 y1 = glm::cross(z1, x1); - glm::mat3 rot1World = glm::mat3(x1, -y1, -z1); + glm::mat3 rot1World = glm::mat3(x1, y1, z1); glm::vec3 x2 = arm2Dir * boneForwardSign; glm::vec3 z2 = planeNormal; glm::vec3 y2 = glm::cross(z2, x2); - glm::mat3 rot2World = glm::mat3(x2, -y2, -z2); + glm::mat3 rot2World = glm::mat3(x2, y2, z2); // convert to local space glm::mat4 arm1Local = glm::inverse(parentWorld) * glm::mat4(rot1World); @@ -465,7 +465,7 @@ void CemuHooks::hook_ModifyBoneMatrix(PPCInterpreter_t* hCPU) { // pole vector (elbow direction) // left: left-down-back, right: right-down-back - glm::vec3 poleDir = isLeft ? glm::vec3(1.0f, -1.0f, -0.5f) : glm::vec3(-1.0f, -1.0f, -0.5f); + glm::vec3 poleDir = isLeft ? glm::vec3(-1.0f, 1.0f, 0.5f) : glm::vec3(1.0f, 1.0f, 0.5f); // rotate pole vector by body rotation (Skl_Root) if (Bone* rootBone = s_skeleton.GetBone("Skl_Root")) { From 2ba0b3210e0f044d0bb7e2f02a87f0d9b7e859bb Mon Sep 17 00:00:00 2001 From: FirEmerald Date: Fri, 30 Jan 2026 21:45:12 -0600 Subject: [PATCH 3/3] Fix comment describing poledir --- src/hooking/skeleton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooking/skeleton.cpp b/src/hooking/skeleton.cpp index 3c997f2..3548ed5 100644 --- a/src/hooking/skeleton.cpp +++ b/src/hooking/skeleton.cpp @@ -464,7 +464,7 @@ void CemuHooks::hook_ModifyBoneMatrix(PPCInterpreter_t* hCPU) { glm::vec3 targetPos = glm::vec3(targetModel[3]); // pole vector (elbow direction) - // left: left-down-back, right: right-down-back + // left: right-up-front, right: left-up-front glm::vec3 poleDir = isLeft ? glm::vec3(-1.0f, 1.0f, 0.5f) : glm::vec3(1.0f, 1.0f, 0.5f); // rotate pole vector by body rotation (Skl_Root)