VirtualHandRenderer.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Ximmerse.XR.Utils;
  5. namespace Ximmerse.XR.InputSystems
  6. {
  7. /// <summary>
  8. /// Virtual hand renderer, for hand tracking.
  9. /// </summary>
  10. public class VirtualHandRenderer : MonoBehaviour
  11. {
  12. /// <summary>
  13. /// If true, colliders are disabled when start the behaviour.
  14. /// </summary>
  15. public bool DisableCollidersAtStartup = true;
  16. /// <summary>
  17. /// The game object prefab of palm.
  18. /// </summary>
  19. public GameObject palm;
  20. /// <summary>
  21. /// Joints of thumb finger
  22. /// </summary>
  23. public GameObject[] thumbJoints;
  24. public GameObject[] thumbConnections;
  25. /// <summary>
  26. /// Joints of index finger
  27. /// </summary>
  28. public GameObject[] indexJoints;
  29. public GameObject[] indexConnections;
  30. /// <summary>
  31. /// Joints of middle finger
  32. /// </summary>
  33. public GameObject[] middleJoints;
  34. public GameObject[] middleConnections;
  35. /// <summary>
  36. /// Joints of ring finger
  37. /// </summary>
  38. public GameObject[] ringJoints;
  39. public GameObject[] ringConnections;
  40. /// <summary>
  41. /// Joints of little finger
  42. /// </summary>
  43. public GameObject[] littleJoints;
  44. public GameObject[] littleConnections;
  45. /// <summary>
  46. /// Deactivate model time valve.
  47. /// </summary>
  48. const float kDeactiveTimeValve = 0.10f;
  49. float deactiveTimeCounter = 0;
  50. private bool isHandModelActive = false;
  51. Collider[] subColliders = null;
  52. private void Awake()
  53. {
  54. subColliders = GetComponentsInChildren<Collider>(true);
  55. }
  56. private void Start()
  57. {
  58. EnableHandModel(false);
  59. if(DisableCollidersAtStartup)
  60. {
  61. this.EnableSubColliders(false);
  62. }
  63. }
  64. // Update is called once per frame
  65. void LateUpdate()
  66. {
  67. if (HandTracking.IsHandTrackingEnable)
  68. {
  69. if (isHandModelActive)
  70. {
  71. UpdateHandTransforms();
  72. }
  73. var trackedInfo = HandTracking.HandTrackingInfo;
  74. if (!trackedInfo.IsValid)
  75. {
  76. deactiveTimeCounter += Time.deltaTime;
  77. if (deactiveTimeCounter >= kDeactiveTimeValve && isHandModelActive)
  78. {
  79. EnableHandModel(false);
  80. }
  81. }
  82. else
  83. {
  84. if (!isHandModelActive)
  85. {
  86. EnableHandModel(true);
  87. }
  88. deactiveTimeCounter = 0;//reset time counter on valid hand case.
  89. }
  90. }
  91. }
  92. /// <summary>
  93. /// update transforms of each finger's joint and connection.
  94. /// </summary>
  95. private void UpdateHandTransforms()
  96. {
  97. var trackedInfo = HandTracking.HandTrackingInfo;
  98. this.palm.transform.SetPositionAndRotation(trackedInfo.PalmPosition, trackedInfo.PalmRotation);
  99. this.palm.transform.localScale = trackedInfo.PalmScale;
  100. UpdateFingerJoints(this.thumbJoints, this.thumbConnections, trackedInfo.ThumbFinger);
  101. UpdateFingerJoints(this.indexJoints, this.indexConnections, trackedInfo.IndexFinger);
  102. UpdateFingerJoints(this.middleJoints, this.middleConnections, trackedInfo.MiddleFinger);
  103. UpdateFingerJoints(this.ringJoints, this.ringConnections, trackedInfo.RingFinger);
  104. UpdateFingerJoints(this.littleJoints, this.littleConnections, trackedInfo.LittleFinger);
  105. }
  106. private void UpdateFingerJoints(GameObject[] joints, GameObject[] connections, RawFingerTrackingInfo fingerTrackInfo)
  107. {
  108. for (int i = 0, iMax = joints.Length; i < iMax; i++)
  109. {
  110. joints[i].transform.position = fingerTrackInfo.Positions[i];
  111. }
  112. for (int i = 0, iMax = connections.Length; i < iMax; i++)
  113. {
  114. connections[i].transform.position = (fingerTrackInfo.Positions[i + 1] + fingerTrackInfo.Positions[i]) / 2;
  115. connections[i].transform.up = (fingerTrackInfo.Positions[i + 1] - fingerTrackInfo.Positions[i]).normalized;
  116. }
  117. }
  118. /// <summary>
  119. /// Activate / Deactivate hand model
  120. /// </summary>
  121. /// <param name="enabled"></param>
  122. void EnableHandModel(bool enabled)
  123. {
  124. isHandModelActive = enabled;
  125. palm.gameObject.SetActive(enabled);
  126. foreach (var g in thumbJoints)
  127. {
  128. g.gameObject.SetActive(enabled);
  129. }
  130. foreach (var g in indexJoints)
  131. {
  132. g.gameObject.SetActive(enabled);
  133. }
  134. foreach (var g in middleJoints)
  135. {
  136. g.gameObject.SetActive(enabled);
  137. }
  138. foreach (var g in ringJoints)
  139. {
  140. g.gameObject.SetActive(enabled);
  141. }
  142. foreach (var g in littleJoints)
  143. {
  144. g.gameObject.SetActive(enabled);
  145. }
  146. foreach (var g in thumbConnections)
  147. {
  148. g.gameObject.SetActive(enabled);
  149. }
  150. foreach (var g in indexConnections)
  151. {
  152. g.gameObject.SetActive(enabled);
  153. }
  154. foreach (var g in middleConnections)
  155. {
  156. g.gameObject.SetActive(enabled);
  157. }
  158. foreach (var g in ringConnections)
  159. {
  160. g.gameObject.SetActive(enabled);
  161. }
  162. foreach (var g in littleConnections)
  163. {
  164. g.gameObject.SetActive(enabled);
  165. }
  166. }
  167. /// <summary>
  168. /// Enable/disable sub colliders
  169. /// </summary>
  170. public void EnableSubColliders(bool enable)
  171. {
  172. foreach(var c in subColliders)
  173. {
  174. c.enabled = enable;
  175. }
  176. }
  177. }
  178. }