CapsuleHand.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace Leap.Unity
  5. {
  6. public class CapsuleHand : IHandModel
  7. {
  8. public override ModelType HandModelType
  9. {
  10. get
  11. {
  12. return ModelType.Graphics;
  13. }
  14. }
  15. public override Chirality Handedness
  16. {
  17. get
  18. {
  19. return this.handedness;
  20. }
  21. set
  22. {
  23. }
  24. }
  25. public override bool SupportsEditorPersistence()
  26. {
  27. return true;
  28. }
  29. public override Hand GetLeapHand()
  30. {
  31. return this.hand_;
  32. }
  33. public override void SetLeapHand(Hand hand)
  34. {
  35. this.hand_ = hand;
  36. }
  37. private void OnValidate()
  38. {
  39. this._cylinderResolution = Mathf.Max(3, this._cylinderResolution);
  40. if (this._armRenderers != null)
  41. {
  42. this.updateArmVisibility();
  43. }
  44. }
  45. public override void InitHand()
  46. {
  47. if (this._material != null)
  48. {
  49. this.jointMat = new Material(this._material);
  50. this.jointMat.hideFlags = HideFlags.DontSaveInEditor;
  51. }
  52. if (this._serializedTransforms != null)
  53. {
  54. for (int i = 0; i < this._serializedTransforms.Count; i++)
  55. {
  56. Transform transform = this._serializedTransforms[i];
  57. if (transform != null)
  58. {
  59. UnityEngine.Object.DestroyImmediate(transform.gameObject);
  60. }
  61. }
  62. this._serializedTransforms.Clear();
  63. }
  64. else
  65. {
  66. this._serializedTransforms = new List<Transform>();
  67. }
  68. this._jointSpheres = new Transform[20];
  69. this._armRenderers = new List<Renderer>();
  70. this._cylinderTransforms = new List<Transform>();
  71. this._sphereATransforms = new List<Transform>();
  72. this._sphereBTransforms = new List<Transform>();
  73. this.createSpheres();
  74. this.createCylinders();
  75. this.updateArmVisibility();
  76. this._hasGeneratedMeshes = false;
  77. }
  78. public override void BeginHand()
  79. {
  80. base.BeginHand();
  81. if (this.hand_.IsLeft)
  82. {
  83. this.jointMat.color = CapsuleHand._leftColorList[CapsuleHand._leftColorIndex];
  84. CapsuleHand._leftColorIndex = (CapsuleHand._leftColorIndex + 1) % CapsuleHand._leftColorList.Length;
  85. }
  86. else
  87. {
  88. this.jointMat.color = CapsuleHand._rightColorList[CapsuleHand._rightColorIndex];
  89. CapsuleHand._rightColorIndex = (CapsuleHand._rightColorIndex + 1) % CapsuleHand._rightColorList.Length;
  90. }
  91. }
  92. public override void UpdateHand()
  93. {
  94. this.updateSpheres();
  95. if (this._showArm)
  96. {
  97. this.updateArm();
  98. }
  99. this.updateCylinders();
  100. }
  101. private void updateSpheres()
  102. {
  103. List<Finger> fingers = this.hand_.Fingers;
  104. for (int i = 0; i < fingers.Count; i++)
  105. {
  106. Finger finger = fingers[i];
  107. for (int j = 0; j < 4; j++)
  108. {
  109. int fingerJointIndex = this.getFingerJointIndex((int)finger.Type, j);
  110. Transform transform = this._jointSpheres[fingerJointIndex];
  111. transform.position = finger.Bone((Bone.BoneType)j).NextJoint.ToVector3();
  112. }
  113. }
  114. this.palmPositionSphere.position = this.hand_.PalmPosition.ToVector3();
  115. Vector3 position = this.hand_.PalmPosition.ToVector3();
  116. this.wristPositionSphere.position = position;
  117. Transform transform2 = this._jointSpheres[0];
  118. Vector3 inDirection = transform2.position - this.hand_.PalmPosition.ToVector3();
  119. this.mockThumbJointSphere.position = this.hand_.PalmPosition.ToVector3() + Vector3.Reflect(inDirection, this.hand_.Basis.xBasis.ToVector3());
  120. }
  121. private void updateArm()
  122. {
  123. Arm arm = this.hand_.Arm;
  124. Vector3 b = arm.Basis.xBasis.ToVector3() * arm.Width * 0.7f * 0.5f;
  125. Vector3 a = arm.WristPosition.ToVector3();
  126. Vector3 vector = arm.ElbowPosition.ToVector3();
  127. float d = Vector3.Distance(a, vector);
  128. a -= arm.Direction.ToVector3() * d * 0.05f;
  129. this.armFrontRight.position = a + b;
  130. this.armFrontLeft.position = a - b;
  131. this.armBackRight.position = vector + b;
  132. this.armBackLeft.position = vector - b;
  133. }
  134. private void updateCylinders()
  135. {
  136. for (int i = 0; i < this._cylinderTransforms.Count; i++)
  137. {
  138. Transform transform = this._cylinderTransforms[i];
  139. Transform transform2 = this._sphereATransforms[i];
  140. Transform transform3 = this._sphereBTransforms[i];
  141. Vector3 vector = transform2.position - transform3.position;
  142. if (!this._hasGeneratedMeshes)
  143. {
  144. MeshFilter component = transform.GetComponent<MeshFilter>();
  145. component.sharedMesh = this.generateCylinderMesh(vector.magnitude / base.transform.lossyScale.x);
  146. }
  147. transform.position = transform2.position;
  148. if (vector.sqrMagnitude > Mathf.Epsilon)
  149. {
  150. transform.LookAt(transform3);
  151. }
  152. }
  153. this._hasGeneratedMeshes = true;
  154. }
  155. private void updateArmVisibility()
  156. {
  157. for (int i = 0; i < this._armRenderers.Count; i++)
  158. {
  159. this._armRenderers[i].enabled = this._showArm;
  160. }
  161. }
  162. private void createSpheres()
  163. {
  164. List<Finger> fingers = this.hand_.Fingers;
  165. for (int i = 0; i < fingers.Count; i++)
  166. {
  167. Finger finger = fingers[i];
  168. for (int j = 0; j < 4; j++)
  169. {
  170. int fingerJointIndex = this.getFingerJointIndex((int)finger.Type, j);
  171. this._jointSpheres[fingerJointIndex] = this.createSphere("Joint", 0.008f, false);
  172. }
  173. }
  174. this.mockThumbJointSphere = this.createSphere("MockJoint", 0.008f, false);
  175. this.palmPositionSphere = this.createSphere("PalmPosition", 0.015f, false);
  176. this.wristPositionSphere = this.createSphere("WristPosition", 0.008f, false);
  177. this.armFrontLeft = this.createSphere("ArmFrontLeft", 0.008f, true);
  178. this.armFrontRight = this.createSphere("ArmFrontRight", 0.008f, true);
  179. this.armBackLeft = this.createSphere("ArmBackLeft", 0.008f, true);
  180. this.armBackRight = this.createSphere("ArmBackRight", 0.008f, true);
  181. }
  182. private void createCylinders()
  183. {
  184. for (int i = 0; i < 5; i++)
  185. {
  186. for (int j = 0; j < 3; j++)
  187. {
  188. int fingerJointIndex = this.getFingerJointIndex(i, j);
  189. int fingerJointIndex2 = this.getFingerJointIndex(i, j + 1);
  190. Transform jointA = this._jointSpheres[fingerJointIndex];
  191. Transform jointB = this._jointSpheres[fingerJointIndex2];
  192. this.createCylinder("Finger Joint", jointA, jointB, false);
  193. }
  194. }
  195. for (int k = 0; k < 4; k++)
  196. {
  197. int fingerJointIndex3 = this.getFingerJointIndex(k, 0);
  198. int fingerJointIndex4 = this.getFingerJointIndex(k + 1, 0);
  199. Transform jointA2 = this._jointSpheres[fingerJointIndex3];
  200. Transform jointB2 = this._jointSpheres[fingerJointIndex4];
  201. this.createCylinder("Hand Joints", jointA2, jointB2, false);
  202. }
  203. Transform jointA3 = this._jointSpheres[0];
  204. Transform jointA4 = this._jointSpheres[16];
  205. this.createCylinder("Hand Bottom", jointA3, this.mockThumbJointSphere, false);
  206. this.createCylinder("Hand Side", jointA4, this.mockThumbJointSphere, false);
  207. this.createCylinder("ArmFront", this.armFrontLeft, this.armFrontRight, true);
  208. this.createCylinder("ArmBack", this.armBackLeft, this.armBackRight, true);
  209. this.createCylinder("ArmLeft", this.armFrontLeft, this.armBackLeft, true);
  210. this.createCylinder("ArmRight", this.armFrontRight, this.armBackRight, true);
  211. }
  212. private int getFingerJointIndex(int fingerIndex, int jointIndex)
  213. {
  214. return fingerIndex * 4 + jointIndex;
  215. }
  216. private Transform createSphere(string name, float radius, bool isPartOfArm = false)
  217. {
  218. GameObject gameObject = new GameObject(name);
  219. this._serializedTransforms.Add(gameObject.transform);
  220. gameObject.AddComponent<MeshFilter>().mesh = this._sphereMesh;
  221. gameObject.AddComponent<MeshRenderer>().sharedMaterial = this.jointMat;
  222. gameObject.transform.parent = base.transform;
  223. gameObject.transform.localScale = Vector3.one * radius * 2f;
  224. gameObject.hideFlags = (HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild | HideFlags.DontUnloadUnusedAsset);
  225. gameObject.layer = base.gameObject.layer;
  226. if (isPartOfArm)
  227. {
  228. this._armRenderers.Add(gameObject.GetComponent<Renderer>());
  229. }
  230. return gameObject.transform;
  231. }
  232. private void createCylinder(string name, Transform jointA, Transform jointB, bool isPartOfArm = false)
  233. {
  234. GameObject gameObject = new GameObject(name);
  235. this._serializedTransforms.Add(gameObject.transform);
  236. gameObject.AddComponent<MeshFilter>();
  237. gameObject.AddComponent<MeshRenderer>().sharedMaterial = this._material;
  238. gameObject.transform.parent = base.transform;
  239. this._cylinderTransforms.Add(gameObject.transform);
  240. this._sphereATransforms.Add(jointA);
  241. this._sphereBTransforms.Add(jointB);
  242. gameObject.gameObject.layer = base.gameObject.layer;
  243. gameObject.hideFlags = (HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild | HideFlags.DontUnloadUnusedAsset);
  244. if (isPartOfArm)
  245. {
  246. this._armRenderers.Add(gameObject.GetComponent<Renderer>());
  247. }
  248. }
  249. private Mesh generateCylinderMesh(float length)
  250. {
  251. Mesh mesh = new Mesh();
  252. mesh.name = "GeneratedCylinder";
  253. mesh.hideFlags = HideFlags.DontSave;
  254. List<Vector3> list = new List<Vector3>();
  255. List<Color> list2 = new List<Color>();
  256. List<int> list3 = new List<int>();
  257. Vector3 zero = Vector3.zero;
  258. Vector3 a = Vector3.forward * length;
  259. for (int i = 0; i < this._cylinderResolution; i++)
  260. {
  261. float f = 6.28318548f * (float)i / (float)this._cylinderResolution;
  262. float x = 0.006f * Mathf.Cos(f);
  263. float y = 0.006f * Mathf.Sin(f);
  264. Vector3 b = new Vector3(x, y, 0f);
  265. list.Add((zero + b) * base.transform.lossyScale.x);
  266. list.Add((a + b) * base.transform.lossyScale.x);
  267. list2.Add(Color.white);
  268. list2.Add(Color.white);
  269. int count = list.Count;
  270. int num = this._cylinderResolution * 2;
  271. list3.Add(count % num);
  272. list3.Add((count + 2) % num);
  273. list3.Add((count + 1) % num);
  274. list3.Add((count + 2) % num);
  275. list3.Add((count + 3) % num);
  276. list3.Add((count + 1) % num);
  277. }
  278. mesh.SetVertices(list);
  279. mesh.SetIndices(list3.ToArray(), MeshTopology.Triangles, 0);
  280. mesh.RecalculateBounds();
  281. mesh.RecalculateNormals();
  282. mesh.UploadMeshData(true);
  283. return mesh;
  284. }
  285. private const int THUMB_BASE_INDEX = 0;
  286. private const int PINKY_BASE_INDEX = 16;
  287. private const float SPHERE_RADIUS = 0.008f;
  288. private const float CYLINDER_RADIUS = 0.006f;
  289. private const float PALM_RADIUS = 0.015f;
  290. private static int _leftColorIndex = 0;
  291. private static int _rightColorIndex = 0;
  292. private static Color[] _leftColorList = new Color[]
  293. {
  294. new Color(0f, 0f, 1f),
  295. new Color(0.2f, 0f, 0.4f),
  296. new Color(0f, 0.2f, 0.2f)
  297. };
  298. private static Color[] _rightColorList = new Color[]
  299. {
  300. new Color(1f, 0f, 0f),
  301. new Color(1f, 1f, 0f),
  302. new Color(1f, 0.5f, 0f)
  303. };
  304. [SerializeField]
  305. private Chirality handedness;
  306. [SerializeField]
  307. private bool _showArm = true;
  308. [SerializeField]
  309. private Material _material;
  310. [SerializeField]
  311. private Mesh _sphereMesh;
  312. [SerializeField]
  313. private int _cylinderResolution = 12;
  314. private bool _hasGeneratedMeshes;
  315. private Material jointMat;
  316. [SerializeField]
  317. [HideInInspector]
  318. private List<Transform> _serializedTransforms;
  319. private Transform[] _jointSpheres;
  320. private Transform mockThumbJointSphere;
  321. private Transform palmPositionSphere;
  322. private Transform wristPositionSphere;
  323. private List<Renderer> _armRenderers;
  324. private List<Transform> _cylinderTransforms;
  325. private List<Transform> _sphereATransforms;
  326. private List<Transform> _sphereBTransforms;
  327. private Transform armFrontLeft;
  328. private Transform armFrontRight;
  329. private Transform armBackLeft;
  330. private Transform armBackRight;
  331. private Hand hand_;
  332. }
  333. }