229 lines
9.6 KiB
C#

using UnityEngine;
namespace Passer.Humanoid {
using Passer.Tracking;
[System.Serializable]
public class UnityXRHand : ArmController {
#if pUNITYXR
public override string name => "Unity XR";
protected UnityXRTracker unityXR => humanoid.unityXR;
#region Manage
public override void CheckSensor(HandTarget handTarget) {
#if pUNITYXR
if (this.handTarget == null)
this.target = handTarget;
if (this.handTarget == null)
return;
if (unityXR.trackerComponent == null && enabled)
unityXR.CheckTracker(handTarget.humanoid);
if (enabled && unityXR.trackerComponent != null && unityXR.trackerComponent.enabled) {
if (controller == null) {
Vector3 position = handTarget.transform.TransformPoint(handTarget.isLeft ? -0.1F : 0.1F, -0.05F, 0.04F);
Quaternion localRotation = handTarget.isLeft ? Quaternion.Euler(180, 90, 90) : Quaternion.Euler(180, -90, -90);
Quaternion rotation = handTarget.transform.rotation * localRotation;
#if hSTEAMVR
if (UnityXRDevice.xrDevice == UnityXRDevice.XRDeviceType.OpenVR) {
SteamVR steamVR = unityXR.trackerComponent as SteamVR;
controller = steamVR.GetController(handTarget.isLeft, position, rotation);
}
else
#endif
{
UnityXR unityXRcomponent = unityXR.trackerComponent as UnityXR;
controller = unityXRcomponent.GetController(handTarget.isLeft, position, rotation);
}
}
if (controller != null)
sensorTransform = controller.transform;
if (!Application.isPlaying)
SetSensor2Target();
}
else {
#if UNITY_EDITOR
if (!Application.isPlaying) {
if (controller != null)
Object.DestroyImmediate(controller.gameObject, true);
}
#endif
controller = null;
sensorTransform = null;
}
#endif
}
#endregion Manage
#region Init
public override void Start(HumanoidControl _humanoid, Transform targetTransform) {
base.Start(_humanoid, targetTransform);
tracker = handTarget.humanoid.unityXR;
if (tracker == null || tracker.enabled == false)
return;
Vector3 position = handTarget.transform.TransformPoint(handTarget.isLeft ? -0.1F : 0.1F, -0.05F, 0.04F);
Quaternion localRotation = handTarget.isLeft ? Quaternion.Euler(180, 90, 90) : Quaternion.Euler(180, -90, -90);
Quaternion rotation = handTarget.transform.rotation * localRotation;
UnityXR unityXRcomponent = unityXR.trackerComponent as UnityXR;
if (unityXRcomponent != null)
controller = unityXRcomponent.GetController(handTarget.isLeft, position, rotation);
if (controller != null) {
controller.show = handTarget.humanoid.showRealObjects && handTarget.showRealObjects;
sensorTransform = controller.transform;
}
SetSensor2Target();
#if UNITY_ANDROID && hOCHAND
if (unityXR.oculusHandTracking)
handSkeleton = OculusHandSkeleton.Get(unityXR.trackerComponent.transform, handTarget.isLeft);
#endif
#if hVIVEHAND
if (unityXR.viveHandTracking)
handSkeleton = ViveHandSkeleton.Get(unityXR.trackerComponent.transform, handTarget.isLeft);
#endif
}
#endregion Init
#region Update
public override void Update() {
status = Tracker.Status.Unavailable;
if (tracker == null || tracker.enabled == false || !enabled)
return;
if (controller != null) {
controller.UpdateComponent();
UpdateInput();
}
if (handSkeleton != null) {
handSkeleton.show = humanoid.showSkeletons;
handSkeleton.UpdateComponent();
}
if (controller != null && controller.status == Tracker.Status.Tracking)
UpdateTarget(handTarget.hand.target, controller);
else if (handSkeleton != null && handSkeleton.status == Tracker.Status.Tracking)
UpdateHandFromSkeleton();
}
#region Controller
private void UpdateInput() {
if (controllerInput == null)
return;
if (handTarget.isLeft)
UpdateInputSide(controllerInput.left);
else
UpdateInputSide(controllerInput.right);
}
private void UpdateInputSide(ControllerSide controllerInputSide) {
if (controllerInputSide == null || controller == null)
return;
controllerInputSide.stickHorizontal += controller.primaryAxis.x;
controllerInputSide.stickVertical += controller.primaryAxis.y;
controllerInputSide.stickButton |= (controller.primaryAxis.z > 0.5F);
controllerInputSide.stickTouch |= (controller.primaryAxis.z > -0.5F);
controllerInputSide.touchpadHorizontal += controller.secondaryAxis.x;
controllerInputSide.touchpadVertical += controller.secondaryAxis.y;
controllerInputSide.touchpadPress |= (controller.secondaryAxis.z > 0.5F);
controllerInputSide.touchpadTouch |= (controller.secondaryAxis.z > -0.5F);
controllerInputSide.buttons[0] |= (controller.button1 > 0.5F);
controllerInputSide.buttons[1] |= (controller.button2 > 0.5F);
controllerInputSide.trigger1 += controller.trigger1;
controllerInputSide.trigger2 += controller.trigger2;
controllerInputSide.option |= controller.option > 0;
}
// arm model for 3DOF tracking: position is calculated from rotation
static public Vector3 CalculateHandPosition(HandTarget handTarget, Vector3 sensor2TargetPosition) {
Quaternion hipsYRotation = Quaternion.AngleAxis(handTarget.humanoid.hipsTarget.transform.eulerAngles.y, handTarget.humanoid.up);
Vector3 pivotPoint = handTarget.humanoid.hipsTarget.transform.position + hipsYRotation * (handTarget.isLeft ? new Vector3(-0.25F, 0.15F, -0.05F) : new Vector3(0.25F, 0.15F, -0.05F));
Quaternion forearmRotation = handTarget.hand.target.transform.rotation * (handTarget.isLeft ? Quaternion.Euler(0, -90, 0) : Quaternion.Euler(0, 90, 0));
Vector3 localForearmDirection = handTarget.humanoid.hipsTarget.transform.InverseTransformDirection(forearmRotation * Vector3.forward);
if (localForearmDirection.x < 0 || localForearmDirection.y > 0) {
pivotPoint += hipsYRotation * Vector3.forward * Mathf.Lerp(0, 0.15F, -localForearmDirection.x * 3 + localForearmDirection.y);
}
if (localForearmDirection.y > 0) {
pivotPoint += hipsYRotation * Vector3.up * Mathf.Lerp(0, 0.2F, localForearmDirection.y);
}
if (localForearmDirection.z < 0.2F) {
localForearmDirection = new Vector3(localForearmDirection.x, localForearmDirection.y, 0.2F);
forearmRotation = Quaternion.LookRotation(handTarget.humanoid.hipsTarget.transform.TransformDirection(localForearmDirection), forearmRotation * Vector3.up);
}
handTarget.hand.target.transform.position = pivotPoint + forearmRotation * Vector3.forward * handTarget.forearm.bone.length;
Vector3 handPosition = handTarget.hand.target.transform.TransformPoint(-sensor2TargetPosition);
return handPosition;
}
#endregion Controller
#region Skeleton
protected override void UpdateHandFromSkeleton() {
Transform wristBone = handSkeleton.GetWristBone();
handTarget.hand.target.transform.position = wristBone.transform.position;
if (handTarget.isLeft)
handTarget.hand.target.transform.rotation = wristBone.transform.rotation * Quaternion.Euler(180, 180, 0);
else
handTarget.hand.target.transform.rotation = wristBone.transform.rotation * Quaternion.Euler(0, 180, 0);
UpdateThumbFromSkeleton();
UpdateIndexFingerFromSkeleton();
UpdateMiddleFingerFromSkeleton();
UpdateRingFingerFromSkeleton();
UpdateLittleFingerFromSkeleton();
}
protected override void UpdateFingerBoneFromSkeleton(Transform targetTransform, Tracking.Finger finger, Tracking.FingerBone fingerBone) {
if (handSkeleton == null)
return;
Transform thisBoneTransform = handSkeleton.GetBone(finger, fingerBone);
if (thisBoneTransform == null) {
Debug.Log(finger + " " + fingerBone + " " + thisBoneTransform);
return;
}
Transform nextBoneTransform = handSkeleton.GetBone(finger, fingerBone + 1);
if (thisBoneTransform == null || nextBoneTransform == null)
return;
Vector3 direction = nextBoneTransform.position - thisBoneTransform.position;
if (handTarget.isLeft)
targetTransform.rotation = Quaternion.LookRotation(direction, handTarget.hand.target.transform.forward) * Quaternion.Euler(-90, 0, 90);
else
targetTransform.rotation = Quaternion.LookRotation(direction, handTarget.hand.target.transform.forward) * Quaternion.Euler(-90, 0, -90);
}
#endregion
#endregion
#endif
}
}