Spelunx Cavern SDK
 
Loading...
Searching...
No Matches
BodyTrackerAvatar.cs
Go to the documentation of this file.
1using System.Collections;
2using System.Collections.Generic;
3using UnityEngine;
4using Microsoft.Azure.Kinect.BodyTracking;
5using System.Text;
6
7namespace Spelunx.Orbbec {
8 /// Maps a 3D avatar's movements to a BodyTracker skeleton.
9 /// Ensure that the Avatar's GameObjects in the scene matches what is defined in the FBX file, or it will break.
10 public class BodyTrackerAvatar : MonoBehaviour {
11 [Header("References")]
12 [SerializeField] private Animator avatarAnimator;
13 [SerializeField] private Transform avatarRoot;
14 [SerializeField] private Transform skeletonRootJoint;
15 [SerializeField] private BodyTracker bodyTracker;
16
17 // Internal variables.
18 private Dictionary<JointId, Quaternion> absoluteOffsetMap;
19 private Dictionary<JointId, Quaternion> relativeOffsetMap;
20
21 public Animator GetAvatarAnimator() { return avatarAnimator; }
22 public Transform GetAvatarRoot() { return avatarRoot; }
23
24 public void SetSkeletonRootJoint(Transform skeletonRoot) { this.skeletonRootJoint = skeletonRoot; }
25 public Transform GetSkeletonRootJoint() { return skeletonRootJoint; }
26
27 public void SetBodyTracker(BodyTracker bodyTracker) { this.bodyTracker = bodyTracker; }
28 public BodyTracker GetBodyTracker() { return bodyTracker; }
29
30 /// Map Microsoft Kinect's joints to Unity's joints. (https://docs.microsoft.com/en-us/azure/Kinect-dk/body-joints)
31 private static HumanBodyBones MapKinectJoint(JointId joint) {
32 switch (joint) {
33 case JointId.Pelvis: return HumanBodyBones.Hips;
34 case JointId.SpineNavel: return HumanBodyBones.Spine;
35 case JointId.SpineChest: return HumanBodyBones.Chest;
36 case JointId.Neck: return HumanBodyBones.Neck;
37 case JointId.Head: return HumanBodyBones.Head;
38 case JointId.HipLeft: return HumanBodyBones.LeftUpperLeg;
39 case JointId.KneeLeft: return HumanBodyBones.LeftLowerLeg;
40 case JointId.AnkleLeft: return HumanBodyBones.LeftFoot;
41 case JointId.FootLeft: return HumanBodyBones.LeftToes;
42 case JointId.HipRight: return HumanBodyBones.RightUpperLeg;
43 case JointId.KneeRight: return HumanBodyBones.RightLowerLeg;
44 case JointId.AnkleRight: return HumanBodyBones.RightFoot;
45 case JointId.FootRight: return HumanBodyBones.RightToes;
46 case JointId.ClavicleLeft: return HumanBodyBones.LeftShoulder;
47 case JointId.ShoulderLeft: return HumanBodyBones.LeftUpperArm;
48 case JointId.ElbowLeft: return HumanBodyBones.LeftLowerArm;
49 case JointId.WristLeft: return HumanBodyBones.LeftHand;
50 case JointId.ClavicleRight: return HumanBodyBones.RightShoulder;
51 case JointId.ShoulderRight: return HumanBodyBones.RightUpperArm;
52 case JointId.ElbowRight: return HumanBodyBones.RightLowerArm;
53 case JointId.WristRight: return HumanBodyBones.RightHand;
54 default: return HumanBodyBones.LastBone;
55 }
56 }
57
58 // WARNING: DO NOT RENAME YOUR MODEL'S GAMEOBJECT IN UNITY!
59 // What this function does is that it gets the skeleton names from the FBX file, and tries to map it to a GameObject in Unity.
60 // If the GameObject in Unity does not match the name in the FBX file, it breaks!
61 private static SkeletonBone GetSkeletonBone(Animator animator, string boneName) {
62 int count = 0;
63 string cloneName = boneName + "(Clone)";
64 foreach (SkeletonBone sb in animator.avatar.humanDescription.skeleton) {
65 if (sb.name == boneName || sb.name == cloneName) {
66 return animator.avatar.humanDescription.skeleton[count];
67 }
68 count++;
69 }
70 return new SkeletonBone();
71 }
72
73 private void InitRelativeOffsetMap() {
74 relativeOffsetMap = new Dictionary<JointId, Quaternion>();
75 for (int i = 0; i < (int)JointId.Count; i++) {
76 HumanBodyBones hbb = MapKinectJoint((JointId)i);
77 if (hbb != HumanBodyBones.LastBone) {
78 Transform boneTransform = avatarAnimator.GetBoneTransform(hbb);
79 relativeOffsetMap[(JointId)i] = GetSkeletonBone(avatarAnimator, boneTransform.name).rotation;
80 }
81 }
82 }
83
84 private void InitAbsoluteOffsetMap() {
85 // For every bone in the avatar, map it to a joint in the skeleton and find its absolute rotation.
86 absoluteOffsetMap = new Dictionary<JointId, Quaternion>();
87 for (int i = 0; i < (int)JointId.Count; i++) {
88 HumanBodyBones hbb = MapKinectJoint((JointId)i);
89 if (hbb != HumanBodyBones.LastBone) {
90 Transform boneTransform = avatarAnimator.GetBoneTransform(hbb);
91 Quaternion absOffset = GetSkeletonBone(avatarAnimator, boneTransform.name).rotation;
92 // find the absolute offset for the tpose
93 while (!ReferenceEquals(boneTransform, avatarRoot)) {
94 boneTransform = boneTransform.parent;
95 absOffset = GetSkeletonBone(avatarAnimator, boneTransform.name).rotation * absOffset;
96 }
97 absoluteOffsetMap[(JointId)i] = absOffset;
98 }
99 }
100 }
101
102 private void Start() {
103 InitRelativeOffsetMap();
104 InitAbsoluteOffsetMap();
105 }
106
107 private void LateUpdate() {
108 for (int j = 0; j < (int)JointId.Count; j++) {
109 if (MapKinectJoint((JointId)j) != HumanBodyBones.LastBone && absoluteOffsetMap.ContainsKey((JointId)j)) {
110 Quaternion absOffset = absoluteOffsetMap[(JointId)j];
111 Transform finalJoint = avatarAnimator.GetBoneTransform(MapKinectJoint((JointId)j));
112 if (j == (int)JointId.Pelvis) {
113 finalJoint.localRotation = bodyTracker.GetAbsoluteJointRotation((JointId)j) * relativeOffsetMap[(JointId)j];
114 finalJoint.localPosition = bodyTracker.GetJointPosition(JointId.Pelvis);
115 } else {
116 finalJoint.localRotation = bodyTracker.GetRelativeJointRotation((JointId)j) * relativeOffsetMap[(JointId)j];
117 }
118 }
119 }
120 }
121 }
122}
void SetSkeletonRootJoint(Transform skeletonRoot)
void SetBodyTracker(BodyTracker bodyTracker)
BodyTracker represents the BodyData from the ORBBEC sensor as a skeleton. Important: BodyTracker pref...
Definition: BodyTracker.cs:10
Quaternion GetAbsoluteJointRotation(JointId jointId)
Get the rotation of a joint, relative to the root.
Definition: BodyTracker.cs:247
Vector3 GetJointPosition(JointId jointId)
Definition: BodyTracker.cs:236
Quaternion GetRelativeJointRotation(JointId jointId)
Get the rotation of a joint, relative to its parent.
Definition: BodyTracker.cs:258