ArmIK usage

Elbows tracking
Tracking without VR controllers
This commit is contained in:
SDraw 2022-10-18 00:22:20 +03:00
parent 3b33dc0cfb
commit 7fcfb04e0f
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
11 changed files with 238 additions and 121 deletions

View file

@ -2,6 +2,7 @@
using ABI_RC.Core.Savior;
using ABI_RC.Systems.IK;
using RootMotion.FinalIK;
using System.Reflection;
using UnityEngine;
namespace ml_lme
@ -9,20 +10,28 @@ namespace ml_lme
[DisallowMultipleComponent]
class LeapTracked : MonoBehaviour
{
static readonly float[] ms_tposeMuscles = typeof(ABI_RC.Systems.IK.SubSystems.BodySystem).GetField("TPoseMuscles", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as float[];
static readonly Quaternion ms_offsetLeft = Quaternion.Euler(0f, 0f, 270f);
static readonly Quaternion ms_offsetRight = Quaternion.Euler(0f, 0f, 90f);
static readonly Quaternion ms_offsetLeftDesktop = Quaternion.Euler(0f, 90f, 0f);
static readonly Quaternion ms_offsetRightDesktop = Quaternion.Euler(0f, 270f, 0f);
IndexIK m_indexIK = null;
VRIK m_vrIK = null;
Vector2 m_armsWeights = Vector2.zero;
bool m_enabled = true;
bool m_fingersOnly = false;
bool m_trackElbows = true;
LeapIK m_leapIK = null;
ArmIK m_leftIK = null;
ArmIK m_rightIK = null;
Transform m_leftHand = null;
Transform m_rightHand = null;
Transform m_leftHandTarget = null;
Transform m_rightHandTarget = null;
Transform m_leftElbow = null;
Transform m_rightElbow = null;
bool m_leftTargetActive = false;
bool m_rightTargetActive = false;
@ -56,8 +65,11 @@ namespace ml_lme
CVRInputManager.Instance.individualFingerTracking = (m_enabled || Utils.AreKnucklesInUse());
}
if(m_leapIK != null)
m_leapIK.SetEnabled(m_enabled);
if((m_leftIK != null) && (m_rightIK != null))
{
m_leftIK.enabled = (m_enabled && !m_fingersOnly);
m_rightIK.enabled = (m_enabled && !m_fingersOnly);
}
if(!m_enabled || m_fingersOnly)
RestoreIK();
@ -67,25 +79,55 @@ namespace ml_lme
{
m_fingersOnly = p_state;
if(m_leapIK != null)
m_leapIK.SetFingersOnly(m_fingersOnly);
if((m_leftIK != null) && (m_rightIK != null))
{
m_leftIK.enabled = (m_enabled && !m_fingersOnly);
m_rightIK.enabled = (m_enabled && !m_fingersOnly);
}
if(!m_enabled || m_fingersOnly)
RestoreIK();
}
public void SetHands(Transform p_left, Transform p_right)
public void SetTrackElbows(bool p_state)
{
m_trackElbows = p_state;
if((m_leftIK != null) && (m_rightIK != null))
{
m_leftIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_rightIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
}
if(m_vrIK != null)
{
if(m_leftTargetActive)
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
if(m_rightTargetActive)
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
}
}
public void SetTransforms(Transform p_left, Transform p_right, Transform p_leftElbow, Transform p_rightElbow)
{
m_leftHand = p_left;
m_rightHand = p_right;
m_leftElbow = p_leftElbow;
m_rightElbow = p_rightElbow;
}
public void UpdateTracking(GestureMatcher.GesturesData p_gesturesData)
{
if(m_enabled && (m_indexIK != null))
{
if(m_leapIK != null)
m_leapIK.SetHandsVisibility(p_gesturesData.m_handsPresenses[0], p_gesturesData.m_handsPresenses[1]);
if((m_leftIK != null) && (m_rightIK != null))
{
m_leftIK.solver.IKPositionWeight = Mathf.Lerp(m_leftIK.solver.IKPositionWeight, (p_gesturesData.m_handsPresenses[0] && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_leftIK.solver.IKRotationWeight = Mathf.Lerp(m_leftIK.solver.IKRotationWeight, (p_gesturesData.m_handsPresenses[0] && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_rightIK.solver.IKPositionWeight = Mathf.Lerp(m_rightIK.solver.IKPositionWeight, (p_gesturesData.m_handsPresenses[1] && !m_fingersOnly) ? 1f : 0f, 0.25f);
m_rightIK.solver.IKRotationWeight = Mathf.Lerp(m_rightIK.solver.IKPositionWeight, (p_gesturesData.m_handsPresenses[1] && !m_fingersOnly) ? 1f : 0f, 0.25f);
}
if(p_gesturesData.m_handsPresenses[0])
{
@ -128,22 +170,30 @@ namespace ml_lme
if(p_gesturesData.m_handsPresenses[0] && !m_leftTargetActive)
{
m_vrIK.solver.leftArm.target = m_leftHandTarget;
m_vrIK.solver.leftArm.bendGoal = m_leftElbow;
m_vrIK.solver.leftArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_leftTargetActive = true;
}
if(!p_gesturesData.m_handsPresenses[0] && m_leftTargetActive)
{
m_vrIK.solver.leftArm.target = IKSystem.Instance.leftHandAnchor;
m_vrIK.solver.leftArm.bendGoal = null;
m_vrIK.solver.leftArm.bendGoalWeight = 0f;
m_leftTargetActive = false;
}
if(p_gesturesData.m_handsPresenses[1] && !m_rightTargetActive)
{
m_vrIK.solver.rightArm.target = m_rightHandTarget;
m_vrIK.solver.rightArm.bendGoal = m_rightElbow;
m_vrIK.solver.rightArm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_rightTargetActive = true;
}
if(!p_gesturesData.m_handsPresenses[1] && m_rightTargetActive)
{
m_vrIK.solver.rightArm.target = IKSystem.Instance.rightHandAnchor;
m_vrIK.solver.rightArm.bendGoal = null;
m_vrIK.solver.rightArm.bendGoalWeight = 0f;
m_rightTargetActive = false;
}
}
@ -152,8 +202,9 @@ namespace ml_lme
public void OnAvatarClear()
{
m_leapIK = null;
m_vrIK = null;
m_leftIK = null;
m_rightIK = null;
m_leftTargetActive = false;
m_rightTargetActive = false;
@ -161,6 +212,8 @@ namespace ml_lme
m_leftHandTarget.localRotation = Quaternion.identity;
m_rightHandTarget.localPosition = Vector3.zero;
m_rightHandTarget.localRotation = Quaternion.identity;
m_armsWeights.Set(0f, 0f);
}
public void OnCalibrateAvatar()
@ -176,24 +229,107 @@ namespace ml_lme
if(PlayerSetup.Instance._animator.isHuman)
{
HumanPoseHandler l_poseHandler = null;
HumanPose l_initPose = new HumanPose();
// Force desktop non-VRIK avatar into T-Pose
if(m_vrIK == null)
{
l_poseHandler = new HumanPoseHandler(PlayerSetup.Instance._animator.avatar, PlayerSetup.Instance._avatar.transform);
l_poseHandler.GetHumanPose(ref l_initPose);
HumanPose l_tPose = new HumanPose();
l_tPose.bodyPosition = l_initPose.bodyPosition;
l_tPose.bodyRotation = l_initPose.bodyRotation;
l_tPose.muscles = new float[l_initPose.muscles.Length];
for(int i = 0; i < l_tPose.muscles.Length; i++)
l_tPose.muscles[i] = ms_tposeMuscles[i];
l_poseHandler.SetHumanPose(ref l_tPose);
}
Transform l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand);
if(l_hand != null)
m_leftHandTarget.localRotation = ms_offsetLeft * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
m_leftHandTarget.localRotation = ((m_vrIK != null) ? ms_offsetLeft : ms_offsetLeftDesktop) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
l_hand = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand);
if(l_hand != null)
m_rightHandTarget.localRotation = ms_offsetRight * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
m_rightHandTarget.localRotation = ((m_vrIK != null) ? ms_offsetRight : ms_offsetRightDesktop) * (PlayerSetup.Instance._avatar.transform.GetMatrix().inverse * l_hand.GetMatrix()).rotation;
if(m_vrIK == null)
{
m_leapIK = PlayerSetup.Instance._animator.gameObject.AddComponent<LeapIK>();
m_leapIK.SetHands(m_leftHand, m_rightHand);
m_leapIK.SetEnabled(m_enabled);
m_leapIK.SetFingersOnly(m_fingersOnly);
Transform l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.UpperChest);
if(l_chest == null)
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Chest);
if(l_chest == null)
l_chest = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Spine);
m_leftIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
m_leftIK.solver.isLeft = true;
m_leftIK.solver.SetChain(
l_chest,
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftShoulder),
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftUpperArm),
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftLowerArm),
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.LeftHand),
PlayerSetup.Instance._animator.transform
);
m_leftIK.solver.arm.target = m_leftHandTarget;
m_leftIK.solver.arm.bendGoal = m_leftElbow;
m_leftIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_leftIK.enabled = (m_enabled && !m_fingersOnly);
m_rightIK = PlayerSetup.Instance._avatar.AddComponent<ArmIK>();
m_rightIK.solver.isLeft = false;
m_rightIK.solver.SetChain(
l_chest,
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightShoulder),
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightUpperArm),
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightLowerArm),
PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.RightHand),
PlayerSetup.Instance._animator.transform
);
m_rightIK.solver.arm.target = m_rightHandTarget;
m_rightIK.solver.arm.bendGoal = m_rightElbow;
m_rightIK.solver.arm.bendGoalWeight = (m_trackElbows ? 1f : 0f);
m_rightIK.enabled = (m_enabled && !m_fingersOnly);
l_poseHandler.SetHumanPose(ref l_initPose);
}
else
{
m_vrIK.onPreSolverUpdate.AddListener(this.OnIKPreUpdate);
m_vrIK.onPostSolverUpdate.AddListener(this.OnIKPostUpdate);
}
l_poseHandler?.Dispose();
}
}
void OnIKPreUpdate()
{
m_armsWeights.Set(m_vrIK.solver.leftArm.positionWeight, m_vrIK.solver.rightArm.positionWeight);
if(m_leftTargetActive && Mathf.Approximately(m_armsWeights.x, 0f))
{
m_vrIK.solver.leftArm.positionWeight = 1f;
m_vrIK.solver.leftArm.rotationWeight = 1f;
}
if(m_rightTargetActive && Mathf.Approximately(m_armsWeights.y, 0f))
{
m_vrIK.solver.rightArm.positionWeight = 1f;
m_vrIK.solver.rightArm.rotationWeight = 1f;
}
}
void OnIKPostUpdate()
{
m_vrIK.solver.leftArm.positionWeight = m_armsWeights.x;
m_vrIK.solver.leftArm.rotationWeight = m_armsWeights.x;
m_vrIK.solver.rightArm.positionWeight = m_armsWeights.y;
m_vrIK.solver.rightArm.rotationWeight = m_armsWeights.y;
}
void RestoreIK()
{
if(m_vrIK != null)
@ -201,11 +337,15 @@ namespace ml_lme
if(m_leftTargetActive)
{
m_vrIK.solver.leftArm.target = IKSystem.Instance.leftHandAnchor;
m_vrIK.solver.leftArm.bendGoal = null;
m_vrIK.solver.leftArm.bendGoalWeight = 0f;
m_leftTargetActive = false;
}
if(m_rightTargetActive)
{
m_vrIK.solver.rightArm.target = IKSystem.Instance.rightHandAnchor;
m_vrIK.solver.rightArm.bendGoal = null;
m_vrIK.solver.rightArm.bendGoalWeight = 0f;
m_rightTargetActive = false;
}
}