Files
VR-WuKong/Packages/PICO Unity Integration SDK-3.3.2-20251111/Runtime/Scripts/Hand/PXR_HandPosePreview.cs
2025-11-13 17:40:28 +08:00

363 lines
16 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if !PICO_OPENXR_SDK
/*******************************************************************************
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
NOTICEAll 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<Transform> handJoints = new List<Transform>(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<Transform> flexionTransforms = new List<Transform>();
public List<MeshRenderer> flexionMeshRenderers = new List<MeshRenderer>();
public List<Transform> curlTransforms = new List<Transform>();
public List<MeshRenderer> curlMeshRenderers = new List<MeshRenderer>();
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<MeshRenderer>());
flexionMeshRenderers.Add(flexionTransform.Find("Pointer").GetComponent<MeshRenderer>());
flexionMeshRenderers.Add(flexionTransform.parent.Find("Bone").GetComponent<MeshRenderer>());
}
foreach (var curlTransform in curlTransforms)
{
var mesh = curlTransform.Find("Bone").GetComponent<MeshRenderer>();
if (!curlMeshRenderers.Contains(mesh)) curlMeshRenderers.Add(mesh);
mesh = curlTransform.Find("Pointer").GetComponent<MeshRenderer>();
if (!curlMeshRenderers.Contains(mesh)) curlMeshRenderers.Add(mesh);
mesh = curlTransform.parent.Find("Bone").GetComponent<MeshRenderer>();
if (!curlMeshRenderers.Contains(mesh)) curlMeshRenderers.Add(mesh);
}
if (Type != FingerType.thumb)
{
var m = GetModelJoint(baseTransform, ModelJoint.tip).Find("Pointer")
.GetComponent<MeshRenderer>();
if (!curlMeshRenderers.Contains(m)) curlMeshRenderers.Add(m);
}
else
{
var m = GetModelJoint(baseTransform, ModelJoint.distal).Find("Pointer")
.GetComponent<MeshRenderer>();
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