191 lines
7.7 KiB
C#
191 lines
7.7 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using VIVE.HandTracking;
|
|
|
|
namespace VIVE.HandTracking.Sample
|
|
{
|
|
public class RenderHand : MonoBehaviour
|
|
{
|
|
// Links between keypoints, 2*i & 2*i+1 forms a link.
|
|
// keypoint index: 1: palm, 2-5: thumb, 6-10: index, 11-15: middle, 16-20: ring, 21-25: pinky
|
|
// fingers are counted from bottom to top
|
|
private static int[] Connections = new int[] {
|
|
1, 2, 1, 6, 1, 11, 1, 16, 1, 21, // palm and finger starts
|
|
2, 6, 6, 11, 11, 16, 16, 21, // finger starts
|
|
2, 3, 3, 4, 4, 5, // thumb
|
|
6, 7, 7, 8, 8, 9, 9, 10, // index
|
|
11, 12, 12, 13, 13, 14, 14, 15, // middle
|
|
16, 17, 17, 18, 18, 19, 19, 20, // ring
|
|
21, 22, 22, 23, 23, 24, 24, 25 // pinky
|
|
};
|
|
[Tooltip("Draw left hand if true, right hand otherwise")]
|
|
public bool isLeft = false;
|
|
[Tooltip("Use inferred or last-known posed when hand loses tracking if true.")]
|
|
public bool allowUntrackedPose = false;
|
|
[Tooltip("Default color of hand points")]
|
|
public Color pointColor = Color.green;
|
|
[Tooltip("Default color of links between keypoints in skeleton mode")]
|
|
public Color linkColor = Color.white;
|
|
[Tooltip("Material for hand points and links")]
|
|
[SerializeField]
|
|
private Material material = null;
|
|
private XrHandJointsMotionRangeEXT MotionType = XrHandJointsMotionRangeEXT.XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT;
|
|
[Tooltip("Type of hand joints range of motion")]
|
|
[ReadOnly] public string HandJointsMotionRange;
|
|
|
|
private List<GameObject> points = new List<GameObject>();
|
|
// list of links created (only for skeleton)
|
|
private List<GameObject> links = new List<GameObject>();
|
|
// Start is called before the first frame update
|
|
private XrHandJointLocationEXT[] HandjointLocations = new
|
|
XrHandJointLocationEXT[(int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT];
|
|
// shared material for all point objects
|
|
private Material pointMat = null;
|
|
// shared material for all link objects
|
|
private Material linkMat = null;
|
|
private void Start()
|
|
{
|
|
HandManager.StartFrameWork(isLeft);
|
|
pointMat = new Material(material);
|
|
if (isLeft)
|
|
{
|
|
pointColor = Color.blue;
|
|
}
|
|
else
|
|
{
|
|
pointColor = Color.red;
|
|
}
|
|
pointMat.color = pointColor;
|
|
linkMat = new Material(material);
|
|
linkMat.color = linkColor;
|
|
|
|
for (int i = 0; i < (int)XrHandJointEXT.XR_HAND_JOINT_MAX_ENUM_EXT; i++)
|
|
{
|
|
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
|
go.name = ((XrHandJointEXT)i).ToString();
|
|
go.transform.parent = transform;
|
|
go.transform.localScale = Vector3.one * 0.012f;
|
|
go.SetActive(false);
|
|
points.Add(go);
|
|
go.transform.position = new Vector3((float)i * 0.1f, 0, 0);
|
|
// handle layer
|
|
go.layer = gameObject.layer;
|
|
// handle material
|
|
go.GetComponent<Renderer>().sharedMaterial = pointMat;
|
|
}
|
|
|
|
// create game objects for links between keypoints, only used in skeleton mode
|
|
for (int i = 0; i < Connections.Length; i += 2)
|
|
{
|
|
var go = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
|
go.name = "link" + i;
|
|
go.transform.parent = transform;
|
|
go.transform.localScale = Vector3.one * 0.005f;
|
|
go.SetActive(false);
|
|
links.Add(go);
|
|
// handle layer
|
|
go.layer = gameObject.layer;
|
|
// handle material
|
|
go.GetComponent<Renderer>().sharedMaterial = linkMat;
|
|
}
|
|
}
|
|
// Update is called once per frame
|
|
private void Update()
|
|
{
|
|
if (HandManager.GetJointLocation(isLeft, out HandjointLocations, ref MotionType))
|
|
{
|
|
UpdateJointLocation();
|
|
switch (MotionType)
|
|
{
|
|
case XrHandJointsMotionRangeEXT.XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT:
|
|
HandJointsMotionRange = "UNOBSTRUCTED";
|
|
break;
|
|
case XrHandJointsMotionRangeEXT.XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT:
|
|
HandJointsMotionRange = "CONTROLLER";
|
|
break;
|
|
default:
|
|
HandJointsMotionRange = "";
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < points.Count; i++)
|
|
{
|
|
var go = points[i];
|
|
go.SetActive(false);
|
|
}
|
|
|
|
for (int i = 0; i < links.Count; i++)
|
|
{
|
|
var link = links[i];
|
|
link.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateJointLocation()
|
|
{
|
|
for (int i = 0; i < points.Count; i++)
|
|
{
|
|
var go = points[i];
|
|
XrQuaternionf orientation;
|
|
XrVector3f position;
|
|
float radius = HandjointLocations[i].radius;
|
|
if (allowUntrackedPose) //Use inferred or last-known pose when lost tracking
|
|
{
|
|
orientation = HandjointLocations[i].pose.orientation;
|
|
position = HandjointLocations[i].pose.position;
|
|
go.transform.localPosition = new Vector3(position.x, position.y, -position.z);
|
|
go.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
if ((HandjointLocations[i].locationFlags & (ulong)XrSpaceLocationFlags.XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT) != 0)
|
|
{
|
|
orientation = HandjointLocations[i].pose.orientation;
|
|
}
|
|
if ((HandjointLocations[i].locationFlags & (ulong)XrSpaceLocationFlags.XR_SPACE_LOCATION_POSITION_TRACKED_BIT) != 0)
|
|
{
|
|
position = HandjointLocations[i].pose.position;
|
|
go.transform.localPosition = new Vector3(position.x, position.y, -position.z);
|
|
go.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
UnityEngine.Debug.Log("Lost tracking");
|
|
go.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < links.Count; i++)
|
|
{
|
|
var link = links[i];
|
|
var pose1 = points[Connections[i * 2]].transform.position;
|
|
var pose2 = points[Connections[i * 2 + 1]].transform.position;
|
|
|
|
// calculate link position and rotation based on points on both end
|
|
link.SetActive(true);
|
|
link.transform.position = (pose1 + pose2) / 2;
|
|
var direction = pose2 - pose1;
|
|
link.transform.rotation = Quaternion.FromToRotation(Vector3.up, direction);
|
|
link.transform.localScale = new Vector3(0.006f, direction.magnitude / 2f - 0.0051f, 0.006f);
|
|
}
|
|
|
|
}
|
|
private void OnDestroy()
|
|
{
|
|
HandManager.StopFrameWork(isLeft);
|
|
UnityEngine.Debug.Log("OnDestroy");
|
|
}
|
|
|
|
//public void setHandVisible(bool isVisible)
|
|
//{
|
|
// Hand.SetActive(isVisible);
|
|
//}
|
|
}
|
|
|
|
}
|