#if !PICO_OPENXR_SDK /******************************************************************************* Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved. NOTICE:All information contained herein is, and remains the property of PICO Technology Co., Ltd. The intellectual and technical concepts contained herein are proprietary to PICO Technology Co., Ltd. and may be covered by patents, patents in process, and are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from PICO Technology Co., Ltd. *******************************************************************************/ using System.Collections.Generic; using UnityEngine; using Unity.XR.PXR; using System; [ExecuteInEditMode] public class PXR_HandPosePreview : MonoBehaviour { [HideInInspector]public List handJoints = new List(new Transform[(int)HandJoint.JointMax]); [HideInInspector] public Vector3[] jointAngles = new Vector3[(int)HandJoint.JointMax]; [HideInInspector] public Transform posePreviewX; [HideInInspector] public Transform posePreviewY; [HideInInspector] public Transform handModel; [HideInInspector] public SkinnedMeshRenderer handAxis; [HideInInspector] public Transform headModel; [HideInInspector] public Transform handShadow; [HideInInspector] public ModelFinger modelThumb = new ModelFinger(ModelFinger.FingerType.thumb); [HideInInspector] public ModelFinger modelIndex = new ModelFinger(ModelFinger.FingerType.index); [HideInInspector] public ModelFinger modelMiddle = new ModelFinger(ModelFinger.FingerType.middle); [HideInInspector] public ModelFinger modelRing = new ModelFinger(ModelFinger.FingerType.ring); [HideInInspector] public ModelFinger modelLittle = new ModelFinger(ModelFinger.FingerType.little); [HideInInspector] public Material openMaterial; [HideInInspector] public Material anyMaterial; [HideInInspector] public Material openFadeMaterial; [HideInInspector] public Material anyFadeMaterial; [HideInInspector] public Material highLightMaterial; private Vector4 highLightBlendPower; private int blendPower = Shader.PropertyToID("_BlendPower"); public void UpdateShapeState(ShapesRecognizer shapesConfig) { var thumb = shapesConfig.thumb; var index = shapesConfig.index; var middle = shapesConfig.middle; var ring = shapesConfig.ring; var little = shapesConfig.pinky; int joint = 0; Vector3 angle = Vector3.zero; //thumb joint = (int)HandJoint.JointThumbProximal; angle = thumb.flexion == ShapesRecognizer.Flexion.Close ? new Vector3(52f, -37, -8) : thumb.abduction == ShapesRecognizer.Abduction.Close ? new Vector3(58f, 16, 1) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointThumbDistal; angle = thumb.curl == ShapesRecognizer.Curl.Close ? new Vector3(36, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; modelThumb.HighlightModelJoints(this,thumb.flexion, thumb.curl); //index joint = (int)HandJoint.JointIndexProximal; angle = index.flexion == ShapesRecognizer.Flexion.Close ? new Vector3(jointAngles[joint].x + 68, jointAngles[joint].y, jointAngles[joint].z) : index.abduction == ShapesRecognizer.Abduction.Close ? new Vector3(jointAngles[joint].x, 18, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointIndexIntermediate; angle = index.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 60, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointIndexDistal; angle = index.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 65, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; modelIndex.HighlightModelJoints(this, index.flexion, index.curl); //middle joint = (int)HandJoint.JointMiddleProximal; angle = middle.flexion == ShapesRecognizer.Flexion.Close ? new Vector3(jointAngles[joint].x + 68, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointMiddleIntermediate; angle = middle.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 60, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointMiddleDistal; angle = middle.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 65, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; modelMiddle.HighlightModelJoints(this, middle.flexion, middle.curl); //ring joint = (int)HandJoint.JointRingProximal; angle = ring.flexion == ShapesRecognizer.Flexion.Close ? new Vector3(jointAngles[joint].x + 68, jointAngles[joint].y, jointAngles[joint].z) : middle.abduction == ShapesRecognizer.Abduction.Close ? new Vector3(jointAngles[joint].x, -18, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointRingIntermediate; angle = ring.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 60, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointRingDistal; angle = ring.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 65, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; modelRing.HighlightModelJoints(this, ring.flexion, ring.curl); //little joint = (int)HandJoint.JointLittleProximal; angle = little.flexion == ShapesRecognizer.Flexion.Close ? new Vector3(jointAngles[joint].x + 68, jointAngles[joint].y, jointAngles[joint].z) : ring.abduction == ShapesRecognizer.Abduction.Close ? new Vector3(jointAngles[joint].x, -18, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointLittleIntermediate; angle = little.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 60, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; joint = (int)HandJoint.JointLittleDistal; angle = little.curl == ShapesRecognizer.Curl.Close ? new Vector3(jointAngles[joint].x + 65, jointAngles[joint].y, jointAngles[joint].z) : jointAngles[joint]; handJoints[joint].localEulerAngles = angle; modelLittle.HighlightModelJoints(this, little.flexion, little.curl); //abduction highlight highLightBlendPower.w = thumb.abduction == ShapesRecognizer.Abduction.Any ? 0 : 1; highLightBlendPower.x = index.abduction == ShapesRecognizer.Abduction.Any ? 0 : 1; highLightBlendPower.y = middle.abduction == ShapesRecognizer.Abduction.Any ? 0 : 1; highLightBlendPower.z = ring.abduction == ShapesRecognizer.Abduction.Any ? 0 : 1; highLightMaterial.SetVector(blendPower, highLightBlendPower); } public void ResetShapeState() { for (int i = 0; i < handJoints.Count; i++) { handJoints[i].localEulerAngles = jointAngles[i]; } modelThumb.HighlightModelJoints(this, ShapesRecognizer.Flexion.Any, ShapesRecognizer.Curl.Any); modelIndex.HighlightModelJoints(this, ShapesRecognizer.Flexion.Any, ShapesRecognizer.Curl.Any); modelMiddle.HighlightModelJoints(this, ShapesRecognizer.Flexion.Any, ShapesRecognizer.Curl.Any); modelRing.HighlightModelJoints(this, ShapesRecognizer.Flexion.Any, ShapesRecognizer.Curl.Any); modelLittle.HighlightModelJoints(this, ShapesRecognizer.Flexion.Any, ShapesRecognizer.Curl.Any); highLightMaterial.SetVector(blendPower, Vector4.zero); } public void ResetTransformState() { headModel.gameObject.SetActive(false); handAxis.gameObject.SetActive(false); handModel.localEulerAngles = new Vector3(-90, 180, 0); } public void UpdateTransformState(TransRecognizer transRecognizer) { handAxis.gameObject.SetActive(true); switch (transRecognizer.trackAxis) { case TransRecognizer.TrackAxis.Fingers: handAxis.SetBlendShapeWeight(0, 100); handAxis.SetBlendShapeWeight(1, 0); handAxis.SetBlendShapeWeight(2, 0); break; case TransRecognizer.TrackAxis.Palm: handAxis.SetBlendShapeWeight(0, 0); handAxis.SetBlendShapeWeight(1, 0); handAxis.SetBlendShapeWeight(2, 100); break; case TransRecognizer.TrackAxis.Thumb: handAxis.SetBlendShapeWeight(0, 0); handAxis.SetBlendShapeWeight(1, 100); handAxis.SetBlendShapeWeight(2, 0); break; default: break; } switch (transRecognizer.trackTarget) { case TransRecognizer.TrackTarget.TowardsFace: headModel.gameObject.SetActive(true); headModel.localPosition = new Vector3(0, 0.05f, -0.24f); headModel.localEulerAngles = Vector3.zero; handModel.localEulerAngles = transRecognizer.trackAxis == TransRecognizer.TrackAxis.Fingers ? new Vector3(0, 180, 0) : transRecognizer.trackAxis == TransRecognizer.TrackAxis.Palm ? new Vector3(-90, 180, 0) : new Vector3(-90, 0, -90); break; case TransRecognizer.TrackTarget.AwayFromFace: headModel.gameObject.SetActive(true); headModel.localPosition = new Vector3(0, 0.05f, 0.24f); headModel.localEulerAngles = new Vector3(0, 180, 0); handModel.localEulerAngles = transRecognizer.trackAxis == TransRecognizer.TrackAxis.Fingers ? new Vector3(0, 180, 0) : transRecognizer.trackAxis == TransRecognizer.TrackAxis.Palm ? new Vector3(-90, 180, 0) : new Vector3(-90, 0, -90); break; case TransRecognizer.TrackTarget.WorldUp: headModel.gameObject.SetActive(false); handModel.localEulerAngles = transRecognizer.trackAxis == TransRecognizer.TrackAxis.Fingers ? new Vector3(-90, 0, 0) : transRecognizer.trackAxis == TransRecognizer.TrackAxis.Palm ? new Vector3(0, 0, 180) : new Vector3(0, 0, -90); break; case TransRecognizer.TrackTarget.WorldDown: headModel.gameObject.SetActive(false); handModel.localEulerAngles = transRecognizer.trackAxis == TransRecognizer.TrackAxis.Fingers ? new Vector3(90, 0, 0) : transRecognizer.trackAxis == TransRecognizer.TrackAxis.Palm ? Vector3.zero : new Vector3(0, 0, 90); break; default: break; } if (handModel.localEulerAngles.x == 0) { handShadow.GetChild(0).gameObject.SetActive(false); handShadow.GetChild(1).gameObject.SetActive(true); } else { handShadow.GetChild(0).gameObject.SetActive(true); handShadow.GetChild(1).gameObject.SetActive(false); } } [Serializable] public class ModelFinger { public FingerType Type; public List flexionTransforms = new List(); public List flexionMeshRenderers = new List(); public List curlTransforms = new List(); public List curlMeshRenderers = new List(); public enum ModelJoint { metacarpal = 0, proximal = 1, intermediate = 2, distal = 3, tip = 4 } public enum FingerType { thumb, index, middle, ring, little } public ModelFinger(FingerType type) { Type = type; } public void RefreshModelJoints(Transform transform) { if (flexionTransforms.Count == 0 || curlTransforms.Count == 0) { flexionTransforms.Clear(); curlTransforms.Clear(); flexionMeshRenderers.Clear(); curlMeshRenderers.Clear(); var baseTransform = transform.GetChild(1); for (int i = 0; i < baseTransform.childCount; i++) { if (baseTransform.GetChild(i).name.EndsWith($"{Type}_{ModelJoint.metacarpal}")) { baseTransform = baseTransform.GetChild(i); break; } } flexionTransforms.Add(GetModelJoint(baseTransform, ModelJoint.proximal)); curlTransforms.Add(GetModelJoint(baseTransform, ModelJoint.intermediate)); if (Type != FingerType.thumb) { curlTransforms.Add(GetModelJoint(baseTransform, ModelJoint.distal)); } foreach (var flexionTransform in flexionTransforms) { flexionMeshRenderers.Add(flexionTransform.Find("Bone").GetComponent()); flexionMeshRenderers.Add(flexionTransform.Find("Pointer").GetComponent()); flexionMeshRenderers.Add(flexionTransform.parent.Find("Bone").GetComponent()); } foreach (var curlTransform in curlTransforms) { var mesh = curlTransform.Find("Bone").GetComponent(); if (!curlMeshRenderers.Contains(mesh)) curlMeshRenderers.Add(mesh); mesh = curlTransform.Find("Pointer").GetComponent(); if (!curlMeshRenderers.Contains(mesh)) curlMeshRenderers.Add(mesh); mesh = curlTransform.parent.Find("Bone").GetComponent(); if (!curlMeshRenderers.Contains(mesh)) curlMeshRenderers.Add(mesh); } if (Type != FingerType.thumb) { var m = GetModelJoint(baseTransform, ModelJoint.tip).Find("Pointer") .GetComponent(); if (!curlMeshRenderers.Contains(m)) curlMeshRenderers.Add(m); } else { var m = GetModelJoint(baseTransform, ModelJoint.distal).Find("Pointer") .GetComponent(); if (!curlMeshRenderers.Contains(m)) curlMeshRenderers.Add(m); } } } public void HighlightModelJoints(PXR_HandPosePreview handPosePreview, ShapesRecognizer.Flexion flexion, ShapesRecognizer.Curl curl) { foreach (var mesh in flexionMeshRenderers) { mesh.material = flexion != ShapesRecognizer.Flexion.Any ? handPosePreview.openMaterial : handPosePreview.anyMaterial; } foreach (var mesh in curlMeshRenderers) { mesh.material = curl != ShapesRecognizer.Curl.Any ? handPosePreview.openMaterial : handPosePreview.anyMaterial; } flexionMeshRenderers[2].material = flexion != ShapesRecognizer.Flexion.Any ? handPosePreview.openFadeMaterial : handPosePreview.anyFadeMaterial; } private Transform GetModelJoint(Transform tran, ModelJoint type) { for (int i = 0; i < (int)type; i++) { tran = tran.GetChild(2); } return tran; } } } #endif