NRHandCapsuleVisual.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal
  10. {
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using UnityEngine;
  14. public class NRHandCapsuleVisual : MonoBehaviour
  15. {
  16. public class CapsuleVisualInfo
  17. {
  18. public bool shouldRender;
  19. public HandJointID startHandJointID;
  20. public HandJointID endHandJointID;
  21. public float capsuleRadius;
  22. public Vector3 startPos;
  23. public Vector3 endPos;
  24. public Material capsuleMat;
  25. public CapsuleVisualInfo(HandJointID startHandJointID, HandJointID endHandJointID)
  26. {
  27. this.startHandJointID = startHandJointID;
  28. this.endHandJointID = endHandJointID;
  29. }
  30. }
  31. public class CapsuleVisual
  32. {
  33. public CapsuleVisualInfo capsuleVisualInfo;
  34. private GameObject m_VisualGO;
  35. private Vector3 m_CapsuleScale;
  36. private MeshRenderer m_Renderer;
  37. private CapsuleCollider m_Collider;
  38. public CapsuleVisual(GameObject rootGO, CapsuleVisualInfo capsuleVisualInfo)
  39. {
  40. this.capsuleVisualInfo = capsuleVisualInfo;
  41. m_VisualGO = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
  42. m_VisualGO.transform.SetParent(rootGO.transform);
  43. m_Collider = m_VisualGO.GetComponent<CapsuleCollider>();
  44. if (m_Collider)
  45. {
  46. m_Collider.enabled = false;
  47. }
  48. m_Renderer = m_VisualGO.GetComponent<MeshRenderer>();
  49. if (capsuleVisualInfo.capsuleMat)
  50. {
  51. m_Renderer.material = capsuleVisualInfo.capsuleMat;
  52. }
  53. m_CapsuleScale = Vector3.zero;
  54. m_VisualGO.transform.localScale = m_CapsuleScale;
  55. }
  56. public void OnUpdate()
  57. {
  58. if (m_VisualGO == null)
  59. return;
  60. if (capsuleVisualInfo.shouldRender)
  61. {
  62. DrawCapsuleVisual(capsuleVisualInfo.startPos, capsuleVisualInfo.endPos, capsuleVisualInfo.capsuleRadius);
  63. }
  64. else
  65. {
  66. m_VisualGO.SetActive(false);
  67. }
  68. }
  69. private void DrawCapsuleVisual(Vector3 a, Vector3 b, float radius)
  70. {
  71. m_VisualGO.SetActive(true);
  72. m_VisualGO.transform.position = (a + b) * 0.5f;
  73. m_VisualGO.transform.up = a - b;
  74. m_CapsuleScale = Vector3.one;
  75. m_CapsuleScale.y = Vector3.Distance(a, b) * 0.5f;
  76. m_CapsuleScale.x = m_CapsuleScale.z = radius * 2f;
  77. m_VisualGO.transform.localScale = m_CapsuleScale;
  78. }
  79. }
  80. public class JointVisualInfo
  81. {
  82. public bool shouldRender;
  83. public HandJointID handJointID;
  84. public float jointRadius;
  85. public Vector3 jointPos;
  86. public Material jointMat;
  87. public JointVisualInfo(HandJointID handJointID)
  88. {
  89. this.handJointID = handJointID;
  90. }
  91. }
  92. public class JointVisual
  93. {
  94. public JointVisualInfo jointVisualInfo;
  95. private GameObject m_VisualGO;
  96. private Vector3 m_JointScale;
  97. private MeshRenderer m_Renderer;
  98. private SphereCollider m_Collider;
  99. public JointVisual(GameObject rootGO, JointVisualInfo jointVisualInfo)
  100. {
  101. this.jointVisualInfo = jointVisualInfo;
  102. m_VisualGO = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  103. m_VisualGO.transform.SetParent(rootGO.transform);
  104. m_Collider = m_VisualGO.GetComponent<SphereCollider>();
  105. if (m_Collider)
  106. {
  107. m_Collider.enabled = false;
  108. }
  109. m_Renderer = m_VisualGO.GetComponent<MeshRenderer>();
  110. if (jointVisualInfo.jointMat)
  111. {
  112. m_Renderer.material = jointVisualInfo.jointMat;
  113. }
  114. m_JointScale = Vector3.zero;
  115. m_VisualGO.transform.localScale = m_JointScale;
  116. }
  117. public void OnUpdate()
  118. {
  119. if (m_VisualGO == null)
  120. return;
  121. if (jointVisualInfo.shouldRender)
  122. {
  123. DrawJointVisual(jointVisualInfo.jointPos, jointVisualInfo.jointRadius);
  124. }
  125. else
  126. {
  127. m_VisualGO.SetActive(false);
  128. }
  129. }
  130. private void DrawJointVisual(Vector3 pos, float radius)
  131. {
  132. m_VisualGO.SetActive(true);
  133. m_VisualGO.transform.position = pos;
  134. m_JointScale = Vector3.one * radius * 2f;
  135. m_VisualGO.transform.localScale = m_JointScale;
  136. }
  137. }
  138. public HandEnum handEnum;
  139. public Material capsuleMat;
  140. public float capsuleRadius = 0.003f;
  141. public bool showCapsule = true;
  142. public Material jointMat;
  143. public float jointRadius = 0.005f;
  144. public bool showJoint = true;
  145. private List<CapsuleVisual> m_CapsuleVisuals;
  146. private List<JointVisual> m_JointVisuals;
  147. private void Start()
  148. {
  149. CreateCapsuleVisuals();
  150. CreateJointVisuals();
  151. }
  152. private void CreateCapsuleVisuals()
  153. {
  154. var capsuleVisualInfoList = new List<CapsuleVisualInfo>()
  155. {
  156. new CapsuleVisualInfo(HandJointID.Wrist, HandJointID.ThumbMetacarpal),
  157. new CapsuleVisualInfo(HandJointID.Wrist, HandJointID.PinkyMetacarpal),
  158. new CapsuleVisualInfo(HandJointID.ThumbMetacarpal, HandJointID.ThumbProximal),
  159. new CapsuleVisualInfo(HandJointID.PinkyMetacarpal, HandJointID.PinkyProximal),
  160. new CapsuleVisualInfo(HandJointID.ThumbProximal, HandJointID.ThumbDistal),
  161. new CapsuleVisualInfo(HandJointID.ThumbDistal, HandJointID.ThumbTip),
  162. new CapsuleVisualInfo(HandJointID.IndexProximal, HandJointID.IndexMiddle),
  163. new CapsuleVisualInfo(HandJointID.IndexMiddle, HandJointID.IndexDistal),
  164. new CapsuleVisualInfo(HandJointID.IndexDistal, HandJointID.IndexTip),
  165. new CapsuleVisualInfo(HandJointID.MiddleProximal, HandJointID.MiddleMiddle),
  166. new CapsuleVisualInfo(HandJointID.MiddleMiddle, HandJointID.MiddleDistal),
  167. new CapsuleVisualInfo(HandJointID.MiddleDistal, HandJointID.MiddleTip),
  168. new CapsuleVisualInfo(HandJointID.RingProximal, HandJointID.RingMiddle),
  169. new CapsuleVisualInfo(HandJointID.RingMiddle, HandJointID.RingDistal),
  170. new CapsuleVisualInfo(HandJointID.RingDistal, HandJointID.RingTip),
  171. new CapsuleVisualInfo(HandJointID.PinkyProximal, HandJointID.PinkyMiddle),
  172. new CapsuleVisualInfo(HandJointID.PinkyMiddle, HandJointID.PinkyDistal),
  173. new CapsuleVisualInfo(HandJointID.PinkyDistal, HandJointID.PinkyTip),
  174. new CapsuleVisualInfo(HandJointID.ThumbProximal, HandJointID.IndexProximal),
  175. new CapsuleVisualInfo(HandJointID.IndexProximal, HandJointID.MiddleProximal),
  176. new CapsuleVisualInfo(HandJointID.MiddleProximal, HandJointID.RingProximal),
  177. new CapsuleVisualInfo(HandJointID.RingProximal, HandJointID.PinkyProximal)
  178. };
  179. m_CapsuleVisuals = new List<CapsuleVisual>();
  180. for (int i = 0; i < capsuleVisualInfoList.Count; i++)
  181. {
  182. var capsuleInfo = capsuleVisualInfoList[i];
  183. capsuleInfo.capsuleMat = capsuleMat;
  184. m_CapsuleVisuals.Add(new CapsuleVisual(gameObject, capsuleInfo));
  185. }
  186. }
  187. private void CreateJointVisuals()
  188. {
  189. m_JointVisuals = new List<JointVisual>();
  190. foreach (var item in System.Enum.GetValues(typeof(HandJointID)))
  191. {
  192. var jointID = (HandJointID)item;
  193. if (jointID > HandJointID.Invalid && jointID < HandJointID.Max)
  194. {
  195. var jointVisualInfo = new JointVisualInfo(jointID);
  196. jointVisualInfo.jointMat = jointMat;
  197. m_JointVisuals.Add(new JointVisual(gameObject, jointVisualInfo));
  198. }
  199. }
  200. }
  201. private void OnEnable()
  202. {
  203. NRInput.Hands.OnHandStatesUpdated += OnHandTracking;
  204. NRInput.Hands.OnHandTrackingStopped += OnHandTrackingStopped;
  205. }
  206. private void OnDisable()
  207. {
  208. NRInput.Hands.OnHandStatesUpdated -= OnHandTracking;
  209. NRInput.Hands.OnHandTrackingStopped -= OnHandTrackingStopped;
  210. }
  211. private void OnHandTrackingStopped()
  212. {
  213. OnHandingTrackingLost();
  214. }
  215. private void OnHandTracking()
  216. {
  217. var handState = NRInput.Hands.GetHandState(handEnum);
  218. if (m_CapsuleVisuals != null)
  219. {
  220. for (int i = 0; i < m_CapsuleVisuals.Count; i++)
  221. {
  222. var capsuleVisual = m_CapsuleVisuals[i];
  223. UpstateCapsuleVisualInfo(capsuleVisual.capsuleVisualInfo, handState);
  224. capsuleVisual.OnUpdate();
  225. }
  226. }
  227. if (m_JointVisuals != null)
  228. {
  229. for (int i = 0; i < m_JointVisuals.Count; i++)
  230. {
  231. var jointVisual = m_JointVisuals[i];
  232. UpdateJointVisualInfo(jointVisual.jointVisualInfo, handState);
  233. jointVisual.OnUpdate();
  234. }
  235. }
  236. }
  237. private void UpstateCapsuleVisualInfo(CapsuleVisualInfo info, HandState handState)
  238. {
  239. info.shouldRender = handState.isTracked;
  240. info.startPos = handState.GetJointPose(info.startHandJointID).position;
  241. info.endPos = handState.GetJointPose(info.endHandJointID).position;
  242. info.capsuleRadius = capsuleRadius;
  243. }
  244. private void UpdateJointVisualInfo(JointVisualInfo info, HandState handState)
  245. {
  246. info.shouldRender = handState.isTracked;
  247. info.jointPos = handState.GetJointPose(info.handJointID).position;
  248. info.jointRadius = jointRadius;
  249. }
  250. private void OnHandingTrackingLost()
  251. {
  252. //force refresh visual
  253. OnHandTracking();
  254. }
  255. }
  256. }