mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-04 07:19:22 +00:00
[AlternateIKSystem] Slight cleanup
This commit is contained in:
parent
684b330a4c
commit
cd34aebeb0
10 changed files with 380 additions and 203 deletions
|
@ -2,28 +2,22 @@
|
|||
|
||||
namespace NAK.AlternateIKSystem.VRIKHelpers;
|
||||
|
||||
public struct VRIKCalibrationData
|
||||
public struct VRIKLocomotionData
|
||||
{
|
||||
public Vector3 KneeNormalLeft;
|
||||
public Vector3 KneeNormalRight;
|
||||
public Vector3 InitialFootPosLeft;
|
||||
public Vector3 InitialFootPosRight;
|
||||
public Quaternion InitialFootRotLeft;
|
||||
public Quaternion InitialFootRotRight;
|
||||
public float InitialHeadHeight;
|
||||
public float InitialFootDistance;
|
||||
public float InitialStepThreshold;
|
||||
public float InitialStepHeight;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
KneeNormalLeft = Vector3.zero;
|
||||
KneeNormalRight = Vector3.zero;
|
||||
InitialFootPosLeft = Vector3.zero;
|
||||
InitialFootPosRight = Vector3.zero;
|
||||
InitialFootRotLeft = Quaternion.identity;
|
||||
InitialFootRotRight = Quaternion.identity;
|
||||
InitialHeadHeight = 0f;
|
||||
InitialFootDistance = 0f;
|
||||
InitialStepThreshold = 0f;
|
||||
InitialStepHeight = 0f;
|
|
@ -5,72 +5,18 @@ namespace NAK.AlternateIKSystem.VRIKHelpers;
|
|||
|
||||
public static class VRIKUtils
|
||||
{
|
||||
public static void CalculateKneeBendNormals(VRIK vrik, ref VRIKCalibrationData calibrationData)
|
||||
{
|
||||
// Helper function to get position or default to Vector3.zero
|
||||
Vector3 GetPositionOrDefault(Transform transform) => transform?.position ?? Vector3.zero;
|
||||
|
||||
// Get assumed left knee normal
|
||||
Vector3[] leftVectors = {
|
||||
GetPositionOrDefault(vrik.references.leftThigh),
|
||||
GetPositionOrDefault(vrik.references.leftCalf),
|
||||
GetPositionOrDefault(vrik.references.leftFoot)
|
||||
};
|
||||
calibrationData.KneeNormalLeft = Quaternion.Inverse(vrik.references.root.rotation) * GetNormalFromArray(leftVectors);
|
||||
|
||||
// Get assumed right knee normal
|
||||
Vector3[] rightVectors = {
|
||||
GetPositionOrDefault(vrik.references.rightThigh),
|
||||
GetPositionOrDefault(vrik.references.rightCalf),
|
||||
GetPositionOrDefault(vrik.references.rightFoot)
|
||||
};
|
||||
calibrationData.KneeNormalRight = Quaternion.Inverse(vrik.references.root.rotation) * GetNormalFromArray(rightVectors);
|
||||
}
|
||||
|
||||
public static void ApplyKneeBendNormals(VRIK vrik, VRIKCalibrationData calibrationData)
|
||||
{
|
||||
// 0 uses bendNormalRelToPelvis, 1 is bendNormalRelToTarget
|
||||
// modifying pelvis normal weight is easier math
|
||||
vrik.solver.leftLeg.bendToTargetWeight = 0f;
|
||||
vrik.solver.rightLeg.bendToTargetWeight = 0f;
|
||||
|
||||
var pelvis_localRotationInverse = Quaternion.Inverse(vrik.references.pelvis.localRotation);
|
||||
vrik.solver.leftLeg.bendNormalRelToPelvis = pelvis_localRotationInverse * calibrationData.KneeNormalLeft;
|
||||
vrik.solver.rightLeg.bendNormalRelToPelvis = pelvis_localRotationInverse * calibrationData.KneeNormalRight;
|
||||
}
|
||||
|
||||
private static Vector3 GetNormalFromArray(Vector3[] positions)
|
||||
{
|
||||
Vector3 centroid = Vector3.zero;
|
||||
for (int i = 0; i < positions.Length; i++)
|
||||
{
|
||||
centroid += positions[i];
|
||||
}
|
||||
centroid /= positions.Length;
|
||||
|
||||
Vector3 normal = Vector3.zero;
|
||||
for (int i = 0; i < positions.Length - 2; i++)
|
||||
{
|
||||
Vector3 side1 = positions[i] - centroid;
|
||||
Vector3 side2 = positions[i + 1] - centroid;
|
||||
normal += Vector3.Cross(side1, side2);
|
||||
}
|
||||
return normal.normalized;
|
||||
}
|
||||
|
||||
public static void CalculateInitialIKScaling(VRIK vrik, ref VRIKCalibrationData calibrationData)
|
||||
public static void CalculateInitialIKScaling(VRIK vrik, ref VRIKLocomotionData locomotionData)
|
||||
{
|
||||
// Get distance between feet and thighs
|
||||
float scaleModifier = Mathf.Max(1f, vrik.references.pelvis.lossyScale.x);
|
||||
float footDistance = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.rightFoot.position);
|
||||
|
||||
calibrationData.InitialFootDistance = footDistance * 0.5f;
|
||||
calibrationData.InitialStepThreshold = footDistance * scaleModifier;
|
||||
calibrationData.InitialStepHeight = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.leftCalf.position) * 0.2f;
|
||||
calibrationData.InitialHeadHeight = Mathf.Abs(vrik.references.head.position.y - vrik.references.rightFoot.position.y);
|
||||
locomotionData.InitialFootDistance = footDistance * 0.5f;
|
||||
locomotionData.InitialStepThreshold = footDistance * scaleModifier;
|
||||
locomotionData.InitialStepHeight = Vector3.Distance(vrik.references.leftFoot.position, vrik.references.leftCalf.position) * 0.2f;
|
||||
}
|
||||
|
||||
public static void CalculateInitialFootsteps(VRIK vrik, ref VRIKCalibrationData calibrationData)
|
||||
public static void CalculateInitialFootsteps(VRIK vrik, ref VRIKLocomotionData locomotionData)
|
||||
{
|
||||
Transform root = vrik.references.root;
|
||||
Transform leftFoot = vrik.references.leftFoot;
|
||||
|
@ -80,46 +26,37 @@ public static class VRIKUtils
|
|||
Quaternion rootWorldRot = root.rotation;
|
||||
|
||||
// Calculate the world rotation of the left and right feet relative to the root bone
|
||||
calibrationData.InitialFootPosLeft = root.parent.InverseTransformPoint(leftFoot.position);
|
||||
calibrationData.InitialFootPosRight = root.parent.InverseTransformPoint(rightFoot.position);
|
||||
calibrationData.InitialFootRotLeft = Quaternion.Inverse(rootWorldRot) * leftFoot.rotation;
|
||||
calibrationData.InitialFootRotRight = Quaternion.Inverse(rootWorldRot) * rightFoot.rotation;
|
||||
locomotionData.InitialFootPosLeft = root.InverseTransformPoint(leftFoot.position);
|
||||
locomotionData.InitialFootPosRight = root.InverseTransformPoint(rightFoot.position);
|
||||
locomotionData.InitialFootRotLeft = Quaternion.Inverse(rootWorldRot) * leftFoot.rotation;
|
||||
locomotionData.InitialFootRotRight = Quaternion.Inverse(rootWorldRot) * rightFoot.rotation;
|
||||
}
|
||||
|
||||
public static void ResetToInitialFootsteps(VRIK vrik, VRIKCalibrationData calibrationData, float scaleModifier)
|
||||
public static void ResetToInitialFootsteps(VRIK vrik, VRIKLocomotionData locomotionData, float scaleModifier)
|
||||
{
|
||||
var locomotionSolver = vrik.solver.locomotion;
|
||||
Transform root = vrik.references.root;
|
||||
Quaternion rootWorldRot = vrik.references.root.rotation;
|
||||
|
||||
var footsteps = locomotionSolver.footsteps;
|
||||
var footstepLeft = footsteps[0];
|
||||
var footstepRight = footsteps[1];
|
||||
|
||||
var root = vrik.references.root;
|
||||
var rootWorldRot = vrik.references.root.rotation;
|
||||
|
||||
// hack, use parent transform instead as setting feet position moves root
|
||||
footstepLeft.Reset(rootWorldRot, root.parent.TransformPoint(calibrationData.InitialFootPosLeft * scaleModifier), rootWorldRot * calibrationData.InitialFootRotLeft);
|
||||
footstepRight.Reset(rootWorldRot, root.parent.TransformPoint(calibrationData.InitialFootPosRight * scaleModifier), rootWorldRot * calibrationData.InitialFootRotRight);
|
||||
// hack, use parent transform instead as setting feet position moves root (root.parent), but does not work for VR
|
||||
var footsteps = vrik.solver.locomotion.footsteps;
|
||||
footsteps[0].Reset(rootWorldRot, root.TransformPoint(locomotionData.InitialFootPosLeft * scaleModifier),
|
||||
rootWorldRot * locomotionData.InitialFootRotLeft);
|
||||
footsteps[1].Reset(rootWorldRot, root.TransformPoint(locomotionData.InitialFootPosRight * scaleModifier),
|
||||
rootWorldRot * locomotionData.InitialFootRotRight);
|
||||
}
|
||||
|
||||
public static void ApplyScaleToVRIK(VRIK vrik, VRIKCalibrationData calibrationData, float scaleModifier)
|
||||
public static void ApplyScaleToVRIK(VRIK vrik, VRIKLocomotionData locomotionData, float scaleModifier)
|
||||
{
|
||||
var locomotionSolver = vrik.solver.locomotion;
|
||||
locomotionSolver.footDistance = calibrationData.InitialFootDistance * scaleModifier;
|
||||
locomotionSolver.stepThreshold = calibrationData.InitialStepThreshold * scaleModifier;
|
||||
ScaleStepHeight(locomotionSolver.stepHeight, calibrationData.InitialStepHeight * scaleModifier);
|
||||
IKSolverVR.Locomotion locomotionSolver = vrik.solver.locomotion;
|
||||
locomotionSolver.footDistance = locomotionData.InitialFootDistance * scaleModifier;
|
||||
locomotionSolver.stepThreshold = locomotionData.InitialStepThreshold * scaleModifier;
|
||||
ScaleStepHeight(locomotionSolver.stepHeight, locomotionData.InitialStepHeight * scaleModifier);
|
||||
}
|
||||
|
||||
static void ScaleStepHeight(AnimationCurve stepHeightCurve, float mag)
|
||||
private static void ScaleStepHeight(AnimationCurve stepHeightCurve, float mag)
|
||||
{
|
||||
Keyframe[] keyframes = stepHeightCurve.keys;
|
||||
var keyframes = stepHeightCurve.keys;
|
||||
keyframes[1].value = mag;
|
||||
stepHeightCurve.keys = keyframes;
|
||||
}
|
||||
|
||||
public static void InitiateVRIKSolver(VRIK vrik)
|
||||
{
|
||||
vrik.solver.SetToReferences(vrik.references);
|
||||
vrik.solver.Initiate(vrik.transform);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue