diff --git a/AlternateIKSystem/IK/IKCalibrator.cs b/AlternateIKSystem/IK/IKCalibrator.cs index 1b3fde1..b617614 100644 --- a/AlternateIKSystem/IK/IKCalibrator.cs +++ b/AlternateIKSystem/IK/IKCalibrator.cs @@ -188,36 +188,43 @@ internal static class IKCalibrator public static void SetupHeadIKTarget(VRIK vrik, Transform parent = null) { - // VR Camera may have Head IK Target from previous avatar Transform existingTarget = parent?.Find("Head IK Target"); if (existingTarget != null) Object.DestroyImmediate(existingTarget.gameObject); parent ??= vrik.references.head; - - // Lazy HeadIKTarget calibration - vrik.solver.spine.headTarget = new GameObject("Head IK Target").transform; - vrik.solver.spine.headTarget.parent = vrik.references.head; - vrik.solver.spine.headTarget.localRotation = Quaternion.identity; - - vrik.solver.spine.headTarget.parent = parent; - vrik.solver.spine.headTarget.localPosition = Vector3.zero; - vrik.solver.spine.headTarget.localScale = Vector3.one; - } - public static void SetupHandIKTarget(VRIK vrik, Transform handOffset, Transform handAnchor, bool isLeft) + vrik.solver.spine.headTarget = new GameObject("Head IK Target").transform; + vrik.solver.spine.headTarget.SetParent(parent); + vrik.solver.spine.headTarget.localPosition = Vector3.zero; + vrik.solver.spine.headTarget.localRotation = CalculateLocalRotation(vrik.references.root, vrik.references.head); + } + + public static void SetupHandIKTarget(VRIK vrik, Transform handAnchor, bool isLeft) { - handAnchor.SetParent(isLeft ? vrik.references.leftHand : vrik.references.rightHand); - handAnchor.localPosition = Vector3.zero; - handAnchor.localRotation = Quaternion.identity; - handAnchor.SetParent(handOffset, true); + Transform parent = handAnchor.parent; + Transform handRef = isLeft ? vrik.references.leftHand : vrik.references.rightHand; + + handAnchor.SetParent(parent); handAnchor.localPosition = Vector3.zero; + handAnchor.localRotation = CalculateLocalRotation(vrik.references.root, handRef); if (isLeft) vrik.solver.leftArm.target = handAnchor; else vrik.solver.rightArm.target = handAnchor; } - + + #endregion + + #region Private Methods + + private static Quaternion CalculateLocalRotation(Transform root, Transform reference) + { + Vector3 forward = Quaternion.Inverse(reference.rotation) * root.forward; + Vector3 upwards = Quaternion.Inverse(reference.rotation) * root.up; + return Quaternion.Inverse(reference.rotation * Quaternion.LookRotation(forward, upwards)) * reference.rotation; + } + #endregion } \ No newline at end of file diff --git a/AlternateIKSystem/IK/IKManager.cs b/AlternateIKSystem/IK/IKManager.cs index 02ff0b0..abf009d 100644 --- a/AlternateIKSystem/IK/IKManager.cs +++ b/AlternateIKSystem/IK/IKManager.cs @@ -43,9 +43,9 @@ public class IKManager : MonoBehaviour private Transform _rightHandRotations; // Hand Anchor Offsets - private Vector3 _handAnchorPositionOffset = new Vector3(-0.038f, 0.0389f, -0.138f); - private Vector3 _handAnchorRotationOffset = Vector3.zero; - + private readonly Vector3 _handAnchorPositionOffset = new Vector3(-0.038f, 0.0389f, -0.138f); + private readonly Vector3 _handAnchorRotationOffset = new Vector3(55, 10, 50); + // Avatar Info private Animator _animator; private Transform _hipTransform; @@ -224,8 +224,8 @@ public class IKManager : MonoBehaviour _ikHandler = new IKHandlerHalfBody(_vrik); IKCalibrator.SetupHeadIKTarget(_vrik, _vrHeadTarget); - IKCalibrator.SetupHandIKTarget(_vrik, _leftHandTarget, _leftHandRotations, true); - IKCalibrator.SetupHandIKTarget(_vrik, _rightHandTarget, _rightHandRotations, false); + IKCalibrator.SetupHandIKTarget(_vrik, _leftHandRotations, true); + IKCalibrator.SetupHandIKTarget(_vrik, _rightHandRotations, false); // Configure controller offsets _leftHandTarget.localPosition = _handAnchorPositionOffset;