diff --git a/DesktopVRIK/DesktopVRIKSystem.cs b/DesktopVRIK/DesktopVRIKSystem.cs index 50a0cec..bc11fa0 100644 --- a/DesktopVRIK/DesktopVRIKSystem.cs +++ b/DesktopVRIK/DesktopVRIKSystem.cs @@ -124,6 +124,7 @@ internal class DesktopVRIKSystem : MonoBehaviour // DesktopVRIK Settings public bool Setting_Enabled = true; public bool Setting_PlantFeet = true; + public bool Setting_ResetFootsteps; public float Setting_BodyLeanWeight; public float Setting_BodyHeadingLimit; public float Setting_PelvisHeadingWeight; @@ -161,6 +162,8 @@ internal class DesktopVRIKSystem : MonoBehaviour // VRIK Calibration Info Vector3 _leftKneeNormal; Vector3 _rightKneeNormal; + Vector3 _initialFootStepLeft; + Vector3 _initialFootStepRight; float _initialFootDistance; float _initialStepThreshold; float _initialStepHeight; @@ -212,8 +215,8 @@ internal class DesktopVRIKSystem : MonoBehaviour bool isFlying = movementSystem.flying; // Why do it myself if VRIK already does the maths - Vector3 headLocalPos = avatarIKSolver.spine.headPosition - avatarIKSolver.spine.rootPosition; - float upright = 1f + (headLocalPos.y - avatarIKSolver.spine.headHeight); + Vector3 headLocalPos = avatarTransform.TransformPoint(avatarIKSolver.spine.headPosition); + float upright = 1f + (avatarIKSolver.spine.headHeight - headLocalPos.y); if (isMoving || isCrouching || isProne || isFlying || !isGrounded) { @@ -310,7 +313,7 @@ internal class DesktopVRIKSystem : MonoBehaviour if (avatarVRIK == null) return; if (isEmotePlaying == _isEmotePlaying) return; - + _isEmotePlaying = isEmotePlaying; if (avatarLookAtIK != null) @@ -359,6 +362,12 @@ internal class DesktopVRIKSystem : MonoBehaviour if (_isEmotePlaying) return; + // Constantly reset footsteps until fully idle + if (_locomotionWeightLerp < 0.99f) + { + ResetFootsteps(); + } + // Set plant feet avatarIKSolver.plantFeet = Setting_PlantFeet; @@ -401,6 +410,19 @@ internal class DesktopVRIKSystem : MonoBehaviour _simulatedRootAngle = transform.eulerAngles.y; } + void ResetFootsteps() + { + if (!Setting_ResetFootsteps) return; + IKSolverVR.Footstep footstepLeft = avatarIKSolver.locomotion.footsteps[0]; + IKSolverVR.Footstep footstepRight = avatarIKSolver.locomotion.footsteps[1]; + Vector3 globalLeft = movementSystem.transform.TransformPoint(_initialFootStepLeft); + Vector3 globalRight = movementSystem.transform.TransformPoint(_initialFootStepRight); + footstepLeft.Reset(avatarTransform.rotation, globalLeft, footstepLeft.stepToRot); + footstepRight.Reset(avatarTransform.rotation, globalRight, footstepRight.stepToRot); + //footstepRight.StepTo(globalRight, avatarTransform.rotation, 100f); + //footstepLeft.StepTo(globalLeft, avatarTransform.rotation, 100f); + } + void CalibrateDesktopVRIK() { ScanAvatar(); @@ -514,6 +536,9 @@ internal class DesktopVRIKSystem : MonoBehaviour // Calculate initial IK scaling values with IKPose VRIKUtils.CalculateInitialIKScaling(avatarVRIK, out _initialFootDistance, out _initialStepThreshold, out _initialStepHeight); + // Calculate initial Footstep positions + VRIKUtils.CalculateInitialFootsteps(avatarVRIK, out _initialFootStepLeft, out _initialFootStepRight); + // Setup HeadIKTarget VRIKUtils.SetupHeadIKTarget(avatarVRIK); diff --git a/DesktopVRIK/Integrations/BTKUIAddon.cs b/DesktopVRIK/Integrations/BTKUIAddon.cs index 33a512c..a0b4ea7 100644 --- a/DesktopVRIK/Integrations/BTKUIAddon.cs +++ b/DesktopVRIK/Integrations/BTKUIAddon.cs @@ -26,6 +26,7 @@ public static class BTKUIAddon // General Settings AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryEnabled); AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryPlantFeet); + AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryResetFootstepsOnIdle); // Calibration Settings AddMelonToggle(ref desktopVRIKCategory, DesktopVRIKMod.EntryUseVRIKToes); diff --git a/DesktopVRIK/Main.cs b/DesktopVRIK/Main.cs index bb82623..109bf76 100644 --- a/DesktopVRIK/Main.cs +++ b/DesktopVRIK/Main.cs @@ -18,6 +18,9 @@ public class DesktopVRIKMod : MelonMod public static readonly MelonPreferences_Entry EntryUseVRIKToes = CategoryDesktopVRIK.CreateEntry("Use VRIK Toes", false, description: "Determines if VRIK uses humanoid toes for IK solving, which can cause feet to idle behind the avatar."); + public static readonly MelonPreferences_Entry EntryResetFootstepsOnIdle = + CategoryDesktopVRIK.CreateEntry("Reset Footsteps on Idle", false, description: "Forces Locomotion Footsteps to reset to their initial position on return to idle. This is a bit aggressive."); + public static readonly MelonPreferences_Entry EntryFindUnmappedToes = CategoryDesktopVRIK.CreateEntry("Find Unmapped Toes", false, description: "Determines if DesktopVRIK should look for unmapped toe bones if the humanoid rig does not have any."); @@ -55,6 +58,7 @@ public class DesktopVRIKMod : MelonMod // DesktopVRIK Settings DesktopVRIKSystem.Instance.Setting_Enabled = EntryEnabled.Value; DesktopVRIKSystem.Instance.Setting_PlantFeet = EntryPlantFeet.Value; + DesktopVRIKSystem.Instance.Setting_ResetFootsteps = EntryResetFootstepsOnIdle.Value; DesktopVRIKSystem.Instance.Setting_BodyLeanWeight = Mathf.Clamp01(EntryBodyLeanWeight.Value); DesktopVRIKSystem.Instance.Setting_BodyHeadingLimit = Mathf.Clamp(EntryBodyHeadingLimit.Value, 0f, 90f); diff --git a/DesktopVRIK/VRIKUtils.cs b/DesktopVRIK/VRIKUtils.cs index 0444c79..32fedd7 100644 --- a/DesktopVRIK/VRIKUtils.cs +++ b/DesktopVRIK/VRIKUtils.cs @@ -154,6 +154,12 @@ public static class VRIKUtils initialStepHeight = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.leftCalf.position) * 0.2f; } + public static void CalculateInitialFootsteps(VRIK vrik, out Vector3 initialFootstepLeft, out Vector3 initialFootstepRight) + { + initialFootstepLeft = vrik.references.root.InverseTransformPoint(vrik.references.leftFoot.position); + initialFootstepRight = vrik.references.root.InverseTransformPoint(vrik.references.rightFoot.position); + } + public static void SetupHeadIKTarget(VRIK vrik) { // Lazy HeadIKTarget calibration