SkeletonHandler.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. //======= Copyright (c) Stereolabs Corporation, All rights reserved. ===============
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System;
  6. public class SkeletonHandler : ScriptableObject
  7. {
  8. // For Skeleton Display
  9. private const int
  10. // JointType
  11. JointType_Head = 26,
  12. JointType_Neck = 3,
  13. JointType_ClavicleRight = 11,
  14. JointType_ShoulderRight = 12,
  15. JointType_ElbowRight = 13,
  16. JointType_WristRight = 14,
  17. JointType_ClavicleLeft = 4,
  18. JointType_ShoulderLeft = 5,
  19. JointType_ElbowLeft = 6,
  20. JointType_WristLeft = 7,
  21. JointType_HipRight = 22,
  22. JointType_KneeRight = 23,
  23. JointType_AnkleRight = 24,
  24. JointType_FootRight = 25,
  25. JointType_HeelRight = 33,
  26. JointType_HipLeft = 18,
  27. JointType_KneeLeft = 19,
  28. JointType_AnkleLeft = 20,
  29. JointType_FootLeft = 21,
  30. JointType_HeelLeft = 32,
  31. JointType_EyesRight = 30,
  32. JointType_EyesLeft = 28,
  33. JointType_EarRight = 30,
  34. JointType_EarLeft = 29,
  35. JointType_SpineBase = 0,
  36. JointType_SpineNaval = 1,
  37. JointType_SpineChest = 2,
  38. JointType_Nose = 27,
  39. jointCount = 34;
  40. // List of bones (pair of joints). Used for Skeleton mode.
  41. private static readonly int[] bonesList = new int[] {
  42. JointType_SpineBase, JointType_HipRight,
  43. JointType_HipLeft, JointType_SpineBase,
  44. JointType_SpineBase, JointType_SpineNaval,
  45. JointType_SpineNaval, JointType_SpineChest,
  46. JointType_SpineChest, JointType_Neck,
  47. JointType_EarRight, JointType_EyesRight,
  48. JointType_EarLeft, JointType_EyesLeft,
  49. JointType_EyesRight, JointType_Nose,
  50. JointType_EyesLeft, JointType_Nose,
  51. JointType_Nose, JointType_Neck,
  52. // left
  53. JointType_SpineChest, JointType_ClavicleLeft,
  54. JointType_ClavicleLeft, JointType_ShoulderLeft,
  55. JointType_ShoulderLeft, JointType_ElbowLeft, // LeftUpperArm
  56. JointType_ElbowLeft, JointType_WristLeft, // LeftLowerArm
  57. JointType_HipLeft, JointType_KneeLeft, // LeftUpperLeg
  58. JointType_KneeLeft, JointType_AnkleLeft, // LeftLowerLeg6
  59. JointType_AnkleLeft, JointType_FootLeft,
  60. JointType_AnkleLeft, JointType_HeelLeft,
  61. JointType_FootLeft, JointType_HeelLeft,
  62. // right
  63. JointType_SpineChest, JointType_ClavicleRight,
  64. JointType_ClavicleRight, JointType_ShoulderRight,
  65. JointType_ShoulderRight, JointType_ElbowRight, // RightUpperArm
  66. JointType_ElbowRight, JointType_WristRight, // RightLowerArm
  67. JointType_HipRight, JointType_KneeRight, // RightUpperLeg
  68. JointType_KneeRight, JointType_AnkleRight, // RightLowerLeg
  69. JointType_AnkleRight, JointType_FootRight,
  70. JointType_AnkleRight, JointType_HeelRight,
  71. JointType_FootRight, JointType_HeelRight
  72. };
  73. // List of joint that will be rendered as a sphere in the Skeleton mode
  74. private static readonly int[] sphereList = new int[] {
  75. JointType_SpineBase,
  76. JointType_SpineNaval,
  77. JointType_SpineChest,
  78. JointType_Neck,
  79. JointType_HipLeft,
  80. JointType_HipRight,
  81. JointType_ClavicleLeft,
  82. JointType_ShoulderLeft,
  83. JointType_ElbowLeft,
  84. JointType_WristLeft,
  85. JointType_KneeLeft,
  86. JointType_AnkleLeft,
  87. JointType_FootLeft,
  88. JointType_HeelLeft,
  89. JointType_ClavicleRight,
  90. JointType_ShoulderRight,
  91. JointType_ElbowRight,
  92. JointType_WristRight,
  93. JointType_KneeRight,
  94. JointType_AnkleRight,
  95. JointType_FootRight,
  96. JointType_HeelRight,
  97. JointType_EyesLeft,
  98. JointType_EyesRight,
  99. JointType_EarRight,
  100. JointType_EarLeft,
  101. JointType_Nose
  102. };
  103. // List of available colors for Skeletons
  104. private Color[] colors = new Color[]{
  105. new Color( 232.0f / 255.0f, 176.0f / 255.0f,59.0f / 255.0f),
  106. new Color(175.0f / 255.0f, 208.0f / 255.0f,25.0f / 255.0f),
  107. new Color(102.0f / 255.0f / 255.0f, 205.0f / 255.0f,105.0f / 255.0f),
  108. new Color(185.0f / 255.0f, 0.0f / 255.0f,255.0f / 255.0f),
  109. new Color(99.0f / 255.0f, 107.0f / 255.0f,252.0f / 255.0f),
  110. new Color(252.0f / 255.0f, 225.0f / 255.0f, 8.0f / 255.0f),
  111. new Color(167.0f / 255.0f, 130.0f / 255.0f, 141.0f / 255.0f),
  112. new Color(194.0f / 255.0f, 72.0f / 255.0f, 113.0f / 255.0f)
  113. };
  114. public Vector3[] joints = new Vector3[jointCount];
  115. GameObject skeleton;
  116. public GameObject[] bones;
  117. public GameObject[] spheres;
  118. // Index of bone parent
  119. private static readonly int[] parentsIdx = new int[]{
  120. -1,
  121. 0,
  122. 1,
  123. 2,
  124. 2,
  125. 4,
  126. 5,
  127. 6,
  128. 7,
  129. 8,
  130. 7,
  131. 2,
  132. 11,
  133. 12,
  134. 13,
  135. 14,
  136. 15,
  137. 14,
  138. 0,
  139. 18,
  140. 19,
  141. 20,
  142. 0,
  143. 22,
  144. 23,
  145. 24,
  146. 3,
  147. 26,
  148. 26,
  149. 26,
  150. 26,
  151. 26
  152. };
  153. // Bones output by the ZED SDK (in this order)
  154. private static HumanBodyBones[] humanBone = new HumanBodyBones[] {
  155. HumanBodyBones.Hips,
  156. HumanBodyBones.Spine,
  157. HumanBodyBones.UpperChest,
  158. HumanBodyBones.Neck,
  159. HumanBodyBones.LeftShoulder,
  160. HumanBodyBones.LeftUpperArm,
  161. HumanBodyBones.LeftLowerArm,
  162. HumanBodyBones.LeftHand, // Left Wrist
  163. HumanBodyBones.LastBone, // Left Hand
  164. HumanBodyBones.LastBone, // Left HandTip
  165. HumanBodyBones.LeftThumbDistal,
  166. HumanBodyBones.RightShoulder,
  167. HumanBodyBones.RightUpperArm,
  168. HumanBodyBones.RightLowerArm,
  169. HumanBodyBones.RightHand, // Right Wrist
  170. HumanBodyBones.LastBone, // Right Hand
  171. HumanBodyBones.LastBone, // Right HandTip
  172. HumanBodyBones.RightThumbDistal,
  173. HumanBodyBones.LeftUpperLeg,
  174. HumanBodyBones.LeftLowerLeg,
  175. HumanBodyBones.LeftFoot,
  176. HumanBodyBones.LeftToes,
  177. HumanBodyBones.RightUpperLeg,
  178. HumanBodyBones.RightLowerLeg,
  179. HumanBodyBones.RightFoot,
  180. HumanBodyBones.RightToes,
  181. HumanBodyBones.Head,
  182. HumanBodyBones.LastBone, // Nose
  183. HumanBodyBones.LastBone, // Left Eye
  184. HumanBodyBones.LastBone, // Left Ear
  185. HumanBodyBones.LastBone, // Right Eye
  186. HumanBodyBones.LastBone, // Right Ear
  187. // HumanBodyBones.LastBone, // Left Heel
  188. // HumanBodyBones.LastBone, // Right Heel
  189. };
  190. private GameObject humanoid;
  191. private Dictionary<HumanBodyBones, RigBone> rigBone = null;
  192. private Dictionary<HumanBodyBones, Quaternion> rigBoneTarget = null;
  193. private Dictionary<HumanBodyBones, Quaternion> default_rotations = null;
  194. private List<GameObject> sphere = new List<GameObject>();// = GameObject.CreatePrimitive (PrimitiveType.Sphere);
  195. private Vector3 targetBodyPosition = new Vector3(0.0f, 0.0f, 0.0f);
  196. public Quaternion targetBodyOrientation = Quaternion.identity;
  197. private float heightOffset = 0.5f;
  198. /// <summary>
  199. /// Sets the smooth factor.
  200. /// </summary>
  201. /// <param name="smooth">Smooth.</param>
  202. public void SetHeightOffset(float offset)
  203. {
  204. heightOffset = offset;
  205. }
  206. /// <summary>
  207. /// Create the avatar control
  208. /// </summary>
  209. /// <param name="h">The height.</param>
  210. public void Create(GameObject h)
  211. {
  212. humanoid = (GameObject)Instantiate(h, Vector3.zero, Quaternion.identity);
  213. var invisiblelayer = LayerMask.NameToLayer("tagInvisibleToZED");
  214. //humanoid.layer = invisiblelayer;
  215. foreach (Transform child in humanoid.transform)
  216. {
  217. child.gameObject.layer = invisiblelayer;
  218. }
  219. // Init list of bones that will be updated by the data retrieved from the ZED SDK
  220. rigBone = new Dictionary<HumanBodyBones, RigBone>();
  221. rigBoneTarget = new Dictionary<HumanBodyBones, Quaternion>();
  222. default_rotations = new Dictionary<HumanBodyBones, Quaternion>();
  223. foreach (HumanBodyBones bone in humanBone)
  224. {
  225. if (bone != HumanBodyBones.LastBone)
  226. {
  227. rigBone[bone] = new RigBone(humanoid, bone);
  228. if (h.GetComponent<Animator>())
  229. {
  230. default_rotations[bone] = humanoid.GetComponent<Animator>().GetBoneTransform(bone).localRotation;
  231. }
  232. }
  233. rigBoneTarget[bone] = Quaternion.identity;
  234. }
  235. }
  236. public void Destroy()
  237. {
  238. GameObject.Destroy(humanoid);
  239. GameObject.Destroy(skeleton);
  240. rigBone.Clear();
  241. rigBoneTarget.Clear();
  242. Array.Clear(bones, 0, bones.Length);
  243. Array.Clear(spheres, 0, spheres.Length);
  244. }
  245. /// <summary>
  246. /// Function that handles the humanoid position, rotation and bones movement
  247. /// </summary>
  248. /// <param name="position_center">Position center.</param>
  249. private void setHumanPoseControl(Vector3 rootPosition, Quaternion rootRotation, Quaternion[] jointsRotation)
  250. {
  251. // Store any joint local rotation (if the bone exists)
  252. if (rigBone[HumanBodyBones.Hips].transform)
  253. {
  254. rigBoneTarget[HumanBodyBones.Hips] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.Hips)];
  255. }
  256. if (rigBone[HumanBodyBones.Hips].transform)
  257. {
  258. rigBoneTarget[HumanBodyBones.Spine] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.Spine)];
  259. }
  260. if (rigBone[HumanBodyBones.UpperChest].transform)
  261. {
  262. rigBoneTarget[HumanBodyBones.UpperChest] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.UpperChest)];
  263. }
  264. if (rigBone[HumanBodyBones.RightShoulder].transform)
  265. {
  266. rigBoneTarget[HumanBodyBones.RightShoulder] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightShoulder)];
  267. }
  268. if (rigBone[HumanBodyBones.RightUpperArm].transform)
  269. {
  270. rigBoneTarget[HumanBodyBones.RightUpperArm] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightUpperArm)];
  271. }
  272. if (rigBone[HumanBodyBones.RightLowerArm].transform)
  273. {
  274. rigBoneTarget[HumanBodyBones.RightLowerArm] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightLowerArm)];
  275. }
  276. if (rigBone[HumanBodyBones.RightHand].transform)
  277. {
  278. rigBoneTarget[HumanBodyBones.RightHand] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightHand)];
  279. }
  280. if (rigBone[HumanBodyBones.LeftShoulder].transform)
  281. {
  282. rigBoneTarget[HumanBodyBones.LeftShoulder] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftShoulder)];
  283. }
  284. if (rigBone[HumanBodyBones.LeftUpperArm].transform)
  285. {
  286. rigBoneTarget[HumanBodyBones.LeftUpperArm] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftUpperArm)];
  287. }
  288. if (rigBone[HumanBodyBones.LeftLowerArm].transform)
  289. {
  290. rigBoneTarget[HumanBodyBones.LeftLowerArm] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftLowerArm)];
  291. }
  292. if (rigBone[HumanBodyBones.LeftHand].transform)
  293. {
  294. rigBoneTarget[HumanBodyBones.LeftHand] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftHand)];
  295. }
  296. if (rigBone[HumanBodyBones.Neck].transform)
  297. {
  298. rigBoneTarget[HumanBodyBones.Neck] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.Neck)];
  299. }
  300. if (rigBone[HumanBodyBones.Head].transform)
  301. {
  302. rigBoneTarget[HumanBodyBones.Head] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.Head)];
  303. }
  304. if (rigBone[HumanBodyBones.RightUpperLeg].transform)
  305. {
  306. rigBoneTarget[HumanBodyBones.RightUpperLeg] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightUpperLeg)];
  307. }
  308. if (rigBone[HumanBodyBones.RightLowerLeg].transform)
  309. {
  310. rigBoneTarget[HumanBodyBones.RightLowerLeg] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightLowerLeg)];
  311. }
  312. if (rigBone[HumanBodyBones.RightFoot].transform)
  313. {
  314. rigBoneTarget[HumanBodyBones.RightFoot] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.RightFoot)];
  315. }
  316. if (rigBone[HumanBodyBones.LeftUpperLeg].transform)
  317. {
  318. rigBoneTarget[HumanBodyBones.LeftUpperLeg] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftUpperLeg)];
  319. }
  320. if (rigBone[HumanBodyBones.LeftLowerLeg].transform)
  321. {
  322. rigBoneTarget[HumanBodyBones.LeftLowerLeg] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftLowerLeg)];
  323. }
  324. if (rigBone[HumanBodyBones.LeftFoot].transform)
  325. {
  326. rigBoneTarget[HumanBodyBones.LeftFoot] = jointsRotation[Array.IndexOf(humanBone, HumanBodyBones.LeftFoot)];
  327. }
  328. // Store global transform (to be applied to the Hips joint).
  329. targetBodyOrientation = rootRotation;
  330. targetBodyPosition = rootPosition;
  331. }
  332. // Init skeleton display
  333. public void initSkeleton(int person_id)
  334. {
  335. bones = new GameObject[bonesList.Length / 2];
  336. spheres = new GameObject[sphereList.Length];
  337. skeleton = new GameObject();
  338. skeleton.name = "Skeleton_ID_" + person_id;
  339. float width = 0.025f;
  340. Color color = colors[person_id % colors.Length];
  341. for (int i = 0; i < bones.Length; i++)
  342. {
  343. GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
  344. cylinder.GetComponent<Renderer>().material.color = color;
  345. cylinder.transform.parent = skeleton.transform;
  346. bones[i] = cylinder;
  347. }
  348. for (int j = 0; j < spheres.Length; j++)
  349. {
  350. GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
  351. sphere.GetComponent<Renderer>().material.color = color;
  352. sphere.transform.localScale = new Vector3(width * 2, width * 2, width * 2);
  353. sphere.transform.parent = skeleton.transform;
  354. spheres[j] = sphere;
  355. }
  356. }
  357. // Update skeleton display with new SDK data
  358. void updateSkeleton()
  359. {
  360. float width = 0.025f;
  361. for (int j = 0; j < spheres.Length; j++)
  362. {
  363. if (ZEDSupportFunctions.IsVector3NaN(joints[sphereList[j]]))
  364. {
  365. spheres[j].transform.position = Vector3.zero;
  366. spheres[j].SetActive(false);
  367. }
  368. else
  369. {
  370. spheres[j].transform.position = joints[sphereList[j]];
  371. spheres[j].SetActive(true);
  372. }
  373. }
  374. for (int i = 0; i < bones.Length; i++)
  375. {
  376. Vector3 start = spheres[Array.IndexOf(sphereList, bonesList[2 * i])].transform.position;
  377. Vector3 end = spheres[Array.IndexOf(sphereList, bonesList[2 * i + 1])].transform.position;
  378. if (start == Vector3.zero || end == Vector3.zero)
  379. {
  380. bones[i].SetActive(false);
  381. continue;
  382. }
  383. bones[i].SetActive(true);
  384. Vector3 offset = end - start;
  385. Vector3 scale = new Vector3(width, offset.magnitude / 2.0f, width);
  386. Vector3 position = start + (offset / 2.0f);
  387. bones[i].transform.position = position;
  388. bones[i].transform.up = offset;
  389. bones[i].transform.localScale = scale;
  390. }
  391. }
  392. /// <summary>
  393. /// Sets the avatar control with joint position.
  394. /// </summary>
  395. /// <param name="jt">Jt.</param>
  396. /// <param name="position_center">Position center.</param>
  397. public void setControlWithJointPosition(Vector3[] jointsPosition, Quaternion[] jointsRotation, Quaternion rootRotation, bool useAvatar)
  398. {
  399. joints = jointsPosition;
  400. humanoid.SetActive(useAvatar);
  401. skeleton.SetActive(!useAvatar);
  402. if (useAvatar)
  403. {
  404. setHumanPoseControl(jointsPosition[0], rootRotation, jointsRotation);
  405. }
  406. else
  407. {
  408. updateSkeleton();
  409. }
  410. }
  411. void PropagateRestPoseRotations(int parentIdx, Dictionary<HumanBodyBones, RigBone> outPose, Quaternion restPosRot, bool inverse)
  412. {
  413. for (int i = 0; i < humanBone.Length; i++)
  414. {
  415. if (humanBone[i] != HumanBodyBones.LastBone && outPose[humanBone[i]].transform)
  416. {
  417. Transform outPoseTransform = outPose[humanBone[i]].transform;
  418. if (parentsIdx[i] == parentIdx)
  419. {
  420. Quaternion restPoseRotation = default_rotations[humanBone[i]];
  421. Quaternion restPoseRotChild = new Quaternion();
  422. if (parentsIdx[i] != -1)
  423. {
  424. Quaternion jointRotation = restPosRot * outPoseTransform.localRotation;
  425. outPoseTransform.localRotation = jointRotation;
  426. if (!inverse)
  427. {
  428. restPoseRotChild = restPosRot * restPoseRotation;
  429. }
  430. else
  431. {
  432. restPoseRotChild = Quaternion.Inverse(restPoseRotation) * restPosRot;
  433. }
  434. }
  435. else
  436. {
  437. restPoseRotChild = restPosRot;
  438. }
  439. PropagateRestPoseRotations(i, outPose, restPoseRotChild, inverse);
  440. }
  441. }
  442. }
  443. }
  444. /// <summary>
  445. /// Set Humanoid position. Called in Update() function
  446. /// </summary>
  447. public void MoveAvatar()
  448. {
  449. // Put in Ref Pose
  450. foreach (HumanBodyBones bone in humanBone)
  451. {
  452. if (bone != HumanBodyBones.LastBone)
  453. {
  454. if (rigBone[bone].transform)
  455. {
  456. rigBone[bone].transform.localRotation = default_rotations[bone];
  457. }
  458. }
  459. }
  460. PropagateRestPoseRotations(0, rigBone, default_rotations[0], false);
  461. for (int i = 0; i < humanBone.Length; i++)
  462. {
  463. if (humanBone[i] != HumanBodyBones.LastBone && rigBone[humanBone[i]].transform)
  464. {
  465. if (parentsIdx[i] != -1)
  466. {
  467. Quaternion newRotation = rigBoneTarget[humanBone[i]] * rigBone[humanBone[i]].transform.localRotation;
  468. rigBone[humanBone[i]].transform.localRotation = newRotation;
  469. }
  470. }
  471. }
  472. PropagateRestPoseRotations(0, rigBone, Quaternion.Inverse(default_rotations[0]), true);
  473. // Apply global transform
  474. if (rigBone[HumanBodyBones.Hips].transform)
  475. {
  476. var animator = humanoid.GetComponent<Animator>();
  477. // There is an offset between the joint "Hips" and the equivalent in the ZED SDK. This offset compensates it.
  478. Vector3 offset = new Vector3(0, (animator.GetBoneTransform(HumanBodyBones.Hips).position.y - animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg).position.y), 0);
  479. rigBone[HumanBodyBones.Hips].transform.position = targetBodyPosition + offset + new Vector3(0, heightOffset, 0);
  480. rigBone[HumanBodyBones.Hips].transform.rotation = targetBodyOrientation;
  481. }
  482. }
  483. /// <summary>
  484. /// Update Engine function (move this avatar)
  485. /// </summary>
  486. public void Move()
  487. {
  488. MoveAvatar();
  489. }
  490. }