t1 / TFDContents / Assets / KinectScripts / AvatarController.cs @ 3
이력 | 보기 | 이력해설 | 다운로드 (52.5 KB)
1 | 3 | KTH | using UnityEngine; |
---|---|---|---|
2 | //using Windows.Kinect; |
||
3 | |||
4 | using System; |
||
5 | using System.Collections; |
||
6 | using System.Collections.Generic; |
||
7 | using System.Runtime.InteropServices; |
||
8 | using System.IO; |
||
9 | using System.Text; |
||
10 | |||
11 | |||
12 | /// <summary> |
||
13 | /// Avatar controller is the component that transfers the captured user motion to a humanoid model (avatar). |
||
14 | /// </summary> |
||
15 | [RequireComponent(typeof(Animator))] |
||
16 | public class AvatarController : MonoBehaviour |
||
17 | { |
||
18 | [Tooltip("Index of the player, tracked by this component. 0 means the 1st player, 1 - the 2nd one, 2 - the 3rd one, etc.")] |
||
19 | public int playerIndex = 0; |
||
20 | |||
21 | [Tooltip("Whether the avatar is facing the player or not.")] |
||
22 | public bool mirroredMovement = false; |
||
23 | |||
24 | [Tooltip("Whether the avatar is allowed to move vertically or not.")] |
||
25 | public bool verticalMovement = false; |
||
26 | |||
27 | [Tooltip("Whether the avatar's root motion is applied by other component or script.")] |
||
28 | public bool externalRootMotion = false; |
||
29 | |||
30 | [Tooltip("Whether the head rotation is controlled externally (e.g. by VR-headset)" )] |
||
31 | public bool externalHeadRotation = false; |
||
32 | |||
33 | [Tooltip("Whether the finger orientations are allowed or not.")] |
||
34 | public bool fingerOrientations = false; |
||
35 | |||
36 | [Tooltip("Rate at which the avatar will move through the scene.")] |
||
37 | public float moveRate = 1f; |
||
38 | |||
39 | [Tooltip("Smooth factor used for avatar movements and joint rotations.")] |
||
40 | public float smoothFactor = 10f; |
||
41 | |||
42 | [Tooltip("Game object this transform is relative to (optional).")] |
||
43 | public GameObject offsetNode; |
||
44 | |||
45 | [Tooltip("If enabled, makes the avatar position relative to this camera to be the same as the player's position to the sensor.")] |
||
46 | public Camera posRelativeToCamera; |
||
47 | |||
48 | [Tooltip("Whether the avatar's position should match the color image (in Pos-rel-to-camera mode only).")] |
||
49 | public bool posRelOverlayColor = false; |
||
50 | |||
51 | [Tooltip("Whether z-axis movement needs to be inverted (Pos-Relative mode only).")] |
||
52 | public bool posRelInvertedZ = false; |
||
53 | |||
54 | [Tooltip("Whether the avatar's feet must stick to the ground.")] |
||
55 | public bool groundedFeet = false; |
||
56 | |||
57 | [Tooltip("Whether to apply the humanoid muscle limits or not.")] |
||
58 | public bool applyMuscleLimits = false; |
||
59 | |||
60 | [Tooltip("Whether to flip left and right, relative to the sensor.")] |
||
61 | public bool flipLeftRight = false; |
||
62 | |||
63 | |||
64 | [Tooltip("Vertical offset of the avatar with respect to the position of user's spine-base.")] |
||
65 | [Range(-0.5f, 0.5f)] |
||
66 | public float verticalOffset = 0f; |
||
67 | |||
68 | [Tooltip("Forward (Z) offset of the avatar with respect to the position of user's spine-base.")] |
||
69 | [Range(-0.5f, 0.5f)] |
||
70 | public float forwardOffset = 0f; |
||
71 | |||
72 | // userId of the player |
||
73 | [NonSerialized] |
||
74 | public Int64 playerId = 0; |
||
75 | |||
76 | |||
77 | // The body root node |
||
78 | protected Transform bodyRoot; |
||
79 | |||
80 | // Variable to hold all them bones. It will initialize the same size as initialRotations. |
||
81 | protected Transform[] bones; |
||
82 | |||
83 | // Rotations of the bones when the Kinect tracking starts. |
||
84 | protected Quaternion[] initialRotations; |
||
85 | protected Quaternion[] localRotations; |
||
86 | protected bool[] isBoneDisabled; |
||
87 | |||
88 | // Local rotations of finger bones |
||
89 | protected Dictionary<HumanBodyBones, Quaternion> fingerBoneLocalRotations = new Dictionary<HumanBodyBones, Quaternion>(); |
||
90 | protected Dictionary<HumanBodyBones, Vector3> fingerBoneLocalAxes = new Dictionary<HumanBodyBones, Vector3>(); |
||
91 | |||
92 | // Initial position and rotation of the transform |
||
93 | protected Vector3 initialPosition; |
||
94 | protected Quaternion initialRotation; |
||
95 | protected Vector3 initialHipsPosition; |
||
96 | protected Quaternion initialHipsRotation; |
||
97 | |||
98 | protected Vector3 offsetNodePos; |
||
99 | protected Quaternion offsetNodeRot; |
||
100 | protected Vector3 bodyRootPosition; |
||
101 | |||
102 | // Calibration Offset Variables for Character Position. |
||
103 | [NonSerialized] |
||
104 | public bool offsetCalibrated = false; |
||
105 | protected Vector3 offsetPos = Vector3.zero; |
||
106 | //protected float xOffset, yOffset, zOffset; |
||
107 | //private Quaternion originalRotation; |
||
108 | |||
109 | private Animator animatorComponent = null; |
||
110 | private HumanPoseHandler humanPoseHandler = null; |
||
111 | private HumanPose humanPose = new HumanPose(); |
||
112 | |||
113 | // whether the parent transform obeys physics |
||
114 | protected bool isRigidBody = false; |
||
115 | |||
116 | // private instance of the KinectManager |
||
117 | protected KinectManager kinectManager; |
||
118 | |||
119 | // last hand events |
||
120 | private InteractionManager.HandEventType lastLeftHandEvent = InteractionManager.HandEventType.Release; |
||
121 | private InteractionManager.HandEventType lastRightHandEvent = InteractionManager.HandEventType.Release; |
||
122 | |||
123 | // fist states |
||
124 | private bool bLeftFistDone = false; |
||
125 | private bool bRightFistDone = false; |
||
126 | |||
127 | // grounder constants and variables |
||
128 | private const int raycastLayers = ~2; // Ignore Raycast |
||
129 | private const float maxFootDistanceGround = 0.02f; // maximum distance from lower foot to the ground |
||
130 | private const float maxFootDistanceTime = 0.2f; // 1.0f; // maximum allowed time, the lower foot to be distant from the ground |
||
131 | private Transform leftFoot, rightFoot; |
||
132 | |||
133 | private float fFootDistanceInitial = 0f; |
||
134 | private float fFootDistance = 0f; |
||
135 | private float fFootDistanceTime = 0f; |
||
136 | |||
137 | |||
138 | /// <summary> |
||
139 | /// Gets the number of bone transforms (array length). |
||
140 | /// </summary> |
||
141 | /// <returns>The number of bone transforms.</returns> |
||
142 | public int GetBoneTransformCount() |
||
143 | { |
||
144 | return bones != null ? bones.Length : 0; |
||
145 | } |
||
146 | |||
147 | /// <summary> |
||
148 | /// Gets the bone transform by index. |
||
149 | /// </summary> |
||
150 | /// <returns>The bone transform.</returns> |
||
151 | /// <param name="index">Index</param> |
||
152 | public Transform GetBoneTransform(int index) |
||
153 | { |
||
154 | if(index >= 0 && index < bones.Length) |
||
155 | { |
||
156 | return bones[index]; |
||
157 | } |
||
158 | |||
159 | return null; |
||
160 | } |
||
161 | |||
162 | /// <summary> |
||
163 | /// Get joint position with respect of player world and kinect offsets ( //!!still some problems with accurate Y pos, probably connected with kinect sensor height estimation ) |
||
164 | /// </summary> |
||
165 | /// <param name="jointType"></param> |
||
166 | /// <returns></returns> |
||
167 | public Vector3 GetJointWorldPos( KinectInterop.JointType jointType ) |
||
168 | { |
||
169 | if( !kinectManager ) |
||
170 | { |
||
171 | return Vector3.zero; |
||
172 | } |
||
173 | |||
174 | Vector3 jointPosition = kinectManager.GetJointPosition( playerId, (int)jointType ); |
||
175 | Vector3 worldPosition = new Vector3( |
||
176 | jointPosition.x - offsetPos.x, |
||
177 | // jointPosition.y - offsetPos.y + kinectManager.sensorHeight, //!! this should be better investigated .. |
||
178 | jointPosition.y + offsetPos.y - kinectManager.sensorHeight, //!! this workds better on my example |
||
179 | !mirroredMovement && !posRelativeToCamera ? (-jointPosition.z - offsetPos.z) : (jointPosition.z - offsetPos.z)); |
||
180 | |||
181 | Quaternion posRotation = mirroredMovement ? Quaternion.Euler (0f, 180f, 0f) * initialRotation : initialRotation; |
||
182 | worldPosition = posRotation * worldPosition; |
||
183 | |||
184 | return bodyRootPosition + worldPosition; |
||
185 | } |
||
186 | |||
187 | /// <summary> |
||
188 | /// Disables the bone and optionally resets its orientation. |
||
189 | /// </summary> |
||
190 | /// <param name="index">Bone index.</param> |
||
191 | /// <param name="resetBone">If set to <c>true</c> resets bone orientation.</param> |
||
192 | public void DisableBone(int index, bool resetBone) |
||
193 | { |
||
194 | if(index >= 0 && index < bones.Length) |
||
195 | { |
||
196 | isBoneDisabled[index] = true; |
||
197 | |||
198 | if (resetBone && bones[index] != null) |
||
199 | { |
||
200 | bones[index].rotation = localRotations[index]; |
||
201 | } |
||
202 | } |
||
203 | } |
||
204 | |||
205 | /// <summary> |
||
206 | /// Enables the bone, so AvatarController could update its orientation. |
||
207 | /// </summary> |
||
208 | /// <param name="index">Bone index.</param> |
||
209 | public void EnableBone(int index) |
||
210 | { |
||
211 | if(index >= 0 && index < bones.Length) |
||
212 | { |
||
213 | isBoneDisabled[index] = false; |
||
214 | } |
||
215 | } |
||
216 | |||
217 | /// <summary> |
||
218 | /// Determines whether the bone orientation update is enabled or not. |
||
219 | /// </summary> |
||
220 | /// <returns><c>true</c> if the bone update is enabled; otherwise, <c>false</c>.</returns> |
||
221 | /// <param name="index">Bone index.</param> |
||
222 | public bool IsBoneEnabled(int index) |
||
223 | { |
||
224 | if(index >= 0 && index < bones.Length) |
||
225 | { |
||
226 | return !isBoneDisabled[index]; |
||
227 | } |
||
228 | |||
229 | return false; |
||
230 | } |
||
231 | |||
232 | /// <summary> |
||
233 | /// Gets the bone index by joint type. |
||
234 | /// </summary> |
||
235 | /// <returns>The bone index.</returns> |
||
236 | /// <param name="joint">Joint type</param> |
||
237 | /// <param name="bMirrored">If set to <c>true</c> gets the mirrored joint index.</param> |
||
238 | public int GetBoneIndexByJoint(KinectInterop.JointType joint, bool bMirrored) |
||
239 | { |
||
240 | int boneIndex = -1; |
||
241 | |||
242 | if(jointMap2boneIndex.ContainsKey(joint)) |
||
243 | { |
||
244 | boneIndex = !bMirrored ? jointMap2boneIndex[joint] : mirrorJointMap2boneIndex[joint]; |
||
245 | } |
||
246 | |||
247 | return boneIndex; |
||
248 | } |
||
249 | |||
250 | /// <summary> |
||
251 | /// Gets the special index by two joint types. |
||
252 | /// </summary> |
||
253 | /// <returns>The spec index by joint.</returns> |
||
254 | /// <param name="joint1">Joint 1 type.</param> |
||
255 | /// <param name="joint2">Joint 2 type.</param> |
||
256 | /// <param name="bMirrored">If set to <c>true</c> gets the mirrored joint index.</param> |
||
257 | public int GetSpecIndexByJoint(KinectInterop.JointType joint1, KinectInterop.JointType joint2, bool bMirrored) |
||
258 | { |
||
259 | int boneIndex = -1; |
||
260 | |||
261 | if((joint1 == KinectInterop.JointType.ShoulderLeft && joint2 == KinectInterop.JointType.SpineShoulder) || |
||
262 | (joint2 == KinectInterop.JointType.ShoulderLeft && joint1 == KinectInterop.JointType.SpineShoulder)) |
||
263 | { |
||
264 | return (!bMirrored ? 25 : 26); |
||
265 | } |
||
266 | else if((joint1 == KinectInterop.JointType.ShoulderRight && joint2 == KinectInterop.JointType.SpineShoulder) || |
||
267 | (joint2 == KinectInterop.JointType.ShoulderRight && joint1 == KinectInterop.JointType.SpineShoulder)) |
||
268 | { |
||
269 | return (!bMirrored ? 26 : 25); |
||
270 | } |
||
271 | else if((joint1 == KinectInterop.JointType.HandTipLeft && joint2 == KinectInterop.JointType.HandLeft) || |
||
272 | (joint2 == KinectInterop.JointType.HandTipLeft && joint1 == KinectInterop.JointType.HandLeft)) |
||
273 | { |
||
274 | return (!bMirrored ? 27 : 28); |
||
275 | } |
||
276 | else if((joint1 == KinectInterop.JointType.HandTipRight && joint2 == KinectInterop.JointType.HandRight) || |
||
277 | (joint2 == KinectInterop.JointType.HandTipRight && joint1 == KinectInterop.JointType.HandRight)) |
||
278 | { |
||
279 | return (!bMirrored ? 28 : 27); |
||
280 | } |
||
281 | else if((joint1 == KinectInterop.JointType.ThumbLeft && joint2 == KinectInterop.JointType.HandLeft) || |
||
282 | (joint2 == KinectInterop.JointType.ThumbLeft && joint1 == KinectInterop.JointType.HandLeft)) |
||
283 | { |
||
284 | return (!bMirrored ? 29 : 30); |
||
285 | } |
||
286 | else if((joint1 == KinectInterop.JointType.ThumbRight && joint2 == KinectInterop.JointType.HandRight) || |
||
287 | (joint2 == KinectInterop.JointType.ThumbRight && joint1 == KinectInterop.JointType.HandRight)) |
||
288 | { |
||
289 | return (!bMirrored ? 30 : 29); |
||
290 | } |
||
291 | |||
292 | return boneIndex; |
||
293 | } |
||
294 | |||
295 | |||
296 | // transform caching gives performance boost since Unity calls GetComponent<Transform>() each time you call transform |
||
297 | private Transform _transformCache; |
||
298 | public new Transform transform |
||
299 | { |
||
300 | get |
||
301 | { |
||
302 | if (!_transformCache) |
||
303 | { |
||
304 | _transformCache = base.transform; |
||
305 | } |
||
306 | |||
307 | return _transformCache; |
||
308 | } |
||
309 | } |
||
310 | |||
311 | |||
312 | public void Awake() |
||
313 | { |
||
314 | // check for double start |
||
315 | if(bones != null) |
||
316 | return; |
||
317 | if(!gameObject.activeInHierarchy) |
||
318 | return; |
||
319 | |||
320 | // inits the bones array |
||
321 | bones = new Transform[31]; |
||
322 | |||
323 | // get the animator reference |
||
324 | animatorComponent = GetComponent<Animator>(); |
||
325 | |||
326 | // Map bones to the points the Kinect tracks |
||
327 | MapBones(); |
||
328 | |||
329 | // Set model's arms to be in T-pose, if needed |
||
330 | SetModelArmsInTpose(); |
||
331 | |||
332 | // Initial rotations and directions of the bones. |
||
333 | initialRotations = new Quaternion[bones.Length]; |
||
334 | localRotations = new Quaternion[bones.Length]; |
||
335 | isBoneDisabled = new bool[bones.Length]; |
||
336 | |||
337 | // Get initial bone rotations |
||
338 | GetInitialRotations(); |
||
339 | |||
340 | // enable all bones |
||
341 | for(int i = 0; i < bones.Length; i++) |
||
342 | { |
||
343 | isBoneDisabled[i] = false; |
||
344 | } |
||
345 | |||
346 | // get initial distance to ground |
||
347 | fFootDistanceInitial = GetDistanceToGround(); |
||
348 | fFootDistance = 0f; |
||
349 | fFootDistanceTime = 0f; |
||
350 | |||
351 | // if parent transform uses physics |
||
352 | isRigidBody = (gameObject.GetComponent<Rigidbody>() != null); |
||
353 | |||
354 | // get the pose handler reference |
||
355 | if (animatorComponent && animatorComponent.avatar && animatorComponent.avatar.isHuman) |
||
356 | { |
||
357 | //Transform hipsTransform = animator.GetBoneTransform(HumanBodyBones.Hips); |
||
358 | //Transform rootTransform = hipsTransform.parent; |
||
359 | Transform rootTransform = transform; |
||
360 | |||
361 | humanPoseHandler = new HumanPoseHandler(animatorComponent.avatar, rootTransform); |
||
362 | humanPoseHandler.GetHumanPose(ref humanPose); |
||
363 | } |
||
364 | } |
||
365 | |||
366 | |||
367 | // applies the muscle limits for humanoid avatar |
||
368 | private void CheckMuscleLimits() |
||
369 | { |
||
370 | if (humanPoseHandler == null) |
||
371 | return; |
||
372 | |||
373 | humanPoseHandler.GetHumanPose(ref humanPose); |
||
374 | |||
375 | //Debug.Log(playerId + " - Trans: " + transform.position + ", body: " + humanPose.bodyPosition); |
||
376 | |||
377 | bool isPoseChanged = false; |
||
378 | |||
379 | float muscleMin = -1f; |
||
380 | float muscleMax = 1f; |
||
381 | |||
382 | for (int i = 0; i < humanPose.muscles.Length; i++) |
||
383 | { |
||
384 | if (float.IsNaN(humanPose.muscles[i])) |
||
385 | { |
||
386 | //humanPose.muscles[i] = 0f; |
||
387 | continue; |
||
388 | } |
||
389 | |||
390 | if (humanPose.muscles[i] < muscleMin) |
||
391 | { |
||
392 | humanPose.muscles[i] = muscleMin; |
||
393 | isPoseChanged = true; |
||
394 | } |
||
395 | else if (humanPose.muscles[i] > muscleMax) |
||
396 | { |
||
397 | humanPose.muscles[i] = muscleMax; |
||
398 | isPoseChanged = true; |
||
399 | } |
||
400 | } |
||
401 | |||
402 | if (isPoseChanged) |
||
403 | { |
||
404 | Quaternion localBodyRot = Quaternion.Inverse(transform.rotation) * humanPose.bodyRotation; |
||
405 | |||
406 | // recover the body position & orientation |
||
407 | //humanPose.bodyPosition = Vector3.zero; |
||
408 | //humanPose.bodyPosition.y = initialHipsPosition.y; |
||
409 | humanPose.bodyPosition = initialHipsPosition; |
||
410 | humanPose.bodyRotation = localBodyRot; // Quaternion.identity; |
||
411 | |||
412 | humanPoseHandler.SetHumanPose(ref humanPose); |
||
413 | //Debug.Log(" Human pose updated."); |
||
414 | } |
||
415 | |||
416 | } |
||
417 | |||
418 | |||
419 | /// <summary> |
||
420 | /// Updates the avatar each frame. |
||
421 | /// </summary> |
||
422 | /// <param name="UserID">User ID</param> |
||
423 | public void UpdateAvatar(Int64 UserID) |
||
424 | { |
||
425 | if(!gameObject.activeInHierarchy) |
||
426 | return; |
||
427 | |||
428 | // Get the KinectManager instance |
||
429 | if(kinectManager == null) |
||
430 | { |
||
431 | kinectManager = KinectManager.Instance; |
||
432 | } |
||
433 | |||
434 | // move the avatar to its Kinect position |
||
435 | if(!externalRootMotion) |
||
436 | { |
||
437 | MoveAvatar(UserID); |
||
438 | } |
||
439 | |||
440 | // get the left hand state and event |
||
441 | if(kinectManager && kinectManager.GetJointTrackingState(UserID, (int)KinectInterop.JointType.HandLeft) != KinectInterop.TrackingState.NotTracked) |
||
442 | { |
||
443 | KinectInterop.HandState leftHandState = kinectManager.GetLeftHandState(UserID); |
||
444 | InteractionManager.HandEventType leftHandEvent = InteractionManager.HandStateToEvent(leftHandState, lastLeftHandEvent); |
||
445 | |||
446 | if(leftHandEvent != InteractionManager.HandEventType.None) |
||
447 | { |
||
448 | lastLeftHandEvent = leftHandEvent; |
||
449 | } |
||
450 | } |
||
451 | |||
452 | // get the right hand state and event |
||
453 | if(kinectManager && kinectManager.GetJointTrackingState(UserID, (int)KinectInterop.JointType.HandRight) != KinectInterop.TrackingState.NotTracked) |
||
454 | { |
||
455 | KinectInterop.HandState rightHandState = kinectManager.GetRightHandState(UserID); |
||
456 | InteractionManager.HandEventType rightHandEvent = InteractionManager.HandStateToEvent(rightHandState, lastRightHandEvent); |
||
457 | |||
458 | if(rightHandEvent != InteractionManager.HandEventType.None) |
||
459 | { |
||
460 | lastRightHandEvent = rightHandEvent; |
||
461 | } |
||
462 | } |
||
463 | |||
464 | // rotate the avatar bones |
||
465 | for (var boneIndex = 0; boneIndex < bones.Length; boneIndex++) |
||
466 | { |
||
467 | if (!bones[boneIndex] || isBoneDisabled[boneIndex]) |
||
468 | continue; |
||
469 | |||
470 | if(boneIndex2JointMap.ContainsKey(boneIndex)) |
||
471 | { |
||
472 | KinectInterop.JointType joint = !(mirroredMovement ^ flipLeftRight) ? |
||
473 | boneIndex2JointMap[boneIndex] : boneIndex2MirrorJointMap[boneIndex]; |
||
474 | |||
475 | if( externalHeadRotation && joint == KinectInterop.JointType.Head ) // skip head if moved externally |
||
476 | { |
||
477 | continue; |
||
478 | } |
||
479 | |||
480 | TransformBone(UserID, joint, boneIndex, !(mirroredMovement ^ flipLeftRight)); |
||
481 | } |
||
482 | else if(specIndex2JointMap.ContainsKey(boneIndex)) |
||
483 | { |
||
484 | // special bones (clavicles) |
||
485 | List<KinectInterop.JointType> alJoints = !(mirroredMovement ^ flipLeftRight) ? |
||
486 | specIndex2JointMap[boneIndex] : specIndex2MirrorMap[boneIndex]; |
||
487 | |||
488 | if(alJoints.Count >= 2) |
||
489 | { |
||
490 | //Debug.Log(alJoints[0].ToString()); |
||
491 | Vector3 baseDir = alJoints[0].ToString().EndsWith("Left") ? Vector3.left : Vector3.right; |
||
492 | TransformSpecialBone(UserID, alJoints[0], alJoints[1], boneIndex, baseDir, !(mirroredMovement ^ flipLeftRight)); |
||
493 | } |
||
494 | } |
||
495 | } |
||
496 | |||
497 | if (applyMuscleLimits && kinectManager && kinectManager.IsUserTracked(UserID)) |
||
498 | { |
||
499 | // check for limits |
||
500 | CheckMuscleLimits(); |
||
501 | } |
||
502 | } |
||
503 | |||
504 | /// <summary> |
||
505 | /// Resets bones to their initial positions and rotations. This also releases avatar control from KM, by settings playerId to 0 |
||
506 | /// </summary> |
||
507 | public virtual void ResetToInitialPosition() |
||
508 | { |
||
509 | playerId = 0; |
||
510 | |||
511 | if(bones == null) |
||
512 | return; |
||
513 | |||
514 | // For each bone that was defined, reset to initial position. |
||
515 | transform.rotation = Quaternion.identity; |
||
516 | |||
517 | for(int pass = 0; pass < 2; pass++) // 2 passes because clavicles are at the end |
||
518 | { |
||
519 | for(int i = 0; i < bones.Length; i++) |
||
520 | { |
||
521 | if(bones[i] != null) |
||
522 | { |
||
523 | bones[i].rotation = initialRotations[i]; |
||
524 | } |
||
525 | } |
||
526 | } |
||
527 | |||
528 | // reset finger bones to initial position |
||
529 | //Animator animatorComponent = GetComponent<Animator>(); |
||
530 | foreach(HumanBodyBones bone in fingerBoneLocalRotations.Keys) |
||
531 | { |
||
532 | Transform boneTransform = animatorComponent ? animatorComponent.GetBoneTransform(bone) : null; |
||
533 | |||
534 | if(boneTransform) |
||
535 | { |
||
536 | boneTransform.localRotation = fingerBoneLocalRotations[bone]; |
||
537 | } |
||
538 | } |
||
539 | |||
540 | // if(bodyRoot != null) |
||
541 | // { |
||
542 | // bodyRoot.localPosition = Vector3.zero; |
||
543 | // bodyRoot.localRotation = Quaternion.identity; |
||
544 | // } |
||
545 | |||
546 | // Restore the offset's position and rotation |
||
547 | if(offsetNode != null) |
||
548 | { |
||
549 | offsetNode.transform.position = offsetNodePos; |
||
550 | offsetNode.transform.rotation = offsetNodeRot; |
||
551 | } |
||
552 | |||
553 | transform.position = initialPosition; |
||
554 | transform.rotation = initialRotation; |
||
555 | |||
556 | if (bones[0]) |
||
557 | { |
||
558 | bones[0].localPosition = initialHipsPosition; |
||
559 | bones[0].localRotation = initialHipsRotation; |
||
560 | } |
||
561 | } |
||
562 | |||
563 | /// <summary> |
||
564 | /// Invoked on the successful calibration of the player. |
||
565 | /// </summary> |
||
566 | /// <param name="userId">User identifier.</param> |
||
567 | public virtual void SuccessfulCalibration(Int64 userId, bool resetInitialTransform) |
||
568 | { |
||
569 | playerId = userId; |
||
570 | |||
571 | // reset the models position |
||
572 | if(offsetNode != null) |
||
573 | { |
||
574 | offsetNode.transform.position = offsetNodePos; |
||
575 | offsetNode.transform.rotation = offsetNodeRot; |
||
576 | } |
||
577 | |||
578 | // reset initial position / rotation if needed |
||
579 | if(resetInitialTransform) |
||
580 | { |
||
581 | bodyRootPosition = transform.position; |
||
582 | initialPosition = transform.position; |
||
583 | initialRotation = transform.rotation; |
||
584 | } |
||
585 | |||
586 | transform.position = initialPosition; |
||
587 | transform.rotation = initialRotation; |
||
588 | |||
589 | // // enable all bones |
||
590 | // for(int i = 0; i < bones.Length; i++) |
||
591 | // { |
||
592 | // isBoneDisabled[i] = false; |
||
593 | // } |
||
594 | |||
595 | // re-calibrate the position offset |
||
596 | offsetCalibrated = false; |
||
597 | } |
||
598 | |||
599 | /// <summary> |
||
600 | /// Moves the avatar to its initial/base position |
||
601 | /// </summary> |
||
602 | /// <param name="position"> world position </param> |
||
603 | /// <param name="rotation"> rotation offset </param> |
||
604 | public void resetInitialTransform( Vector3 position, Vector3 rotation ) |
||
605 | { |
||
606 | bodyRootPosition = position; |
||
607 | initialPosition = position; |
||
608 | initialRotation = Quaternion.Euler( rotation ); |
||
609 | |||
610 | transform.position = initialPosition; |
||
611 | transform.rotation = initialRotation; |
||
612 | |||
613 | offsetCalibrated = false; // this cause also calibrating kinect offset in moveAvatar function |
||
614 | } |
||
615 | |||
616 | // Apply the rotations tracked by kinect to the joints. |
||
617 | protected void TransformBone(Int64 userId, KinectInterop.JointType joint, int boneIndex, bool flip) |
||
618 | { |
||
619 | Transform boneTransform = bones[boneIndex]; |
||
620 | if(boneTransform == null || kinectManager == null) |
||
621 | return; |
||
622 | |||
623 | int iJoint = (int)joint; |
||
624 | if(iJoint < 0 || !kinectManager.IsJointTracked(userId, iJoint)) |
||
625 | return; |
||
626 | |||
627 | // Get Kinect joint orientation |
||
628 | Quaternion jointRotation = kinectManager.GetJointOrientation(userId, iJoint, flip); |
||
629 | if(jointRotation == Quaternion.identity) |
||
630 | return; |
||
631 | |||
632 | // calculate the new orientation |
||
633 | Quaternion newRotation = Kinect2AvatarRot(jointRotation, boneIndex); |
||
634 | |||
635 | if(externalRootMotion) |
||
636 | { |
||
637 | newRotation = transform.rotation * newRotation; |
||
638 | } |
||
639 | |||
640 | // Smoothly transition to the new rotation |
||
641 | if(smoothFactor != 0f) |
||
642 | boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime); |
||
643 | else |
||
644 | boneTransform.rotation = newRotation; |
||
645 | } |
||
646 | |||
647 | // Apply the rotations tracked by kinect to a special joint |
||
648 | protected void TransformSpecialBone(Int64 userId, KinectInterop.JointType joint, KinectInterop.JointType jointParent, int boneIndex, Vector3 baseDir, bool flip) |
||
649 | { |
||
650 | Transform boneTransform = bones[boneIndex]; |
||
651 | if(boneTransform == null || kinectManager == null) |
||
652 | return; |
||
653 | |||
654 | if(!kinectManager.IsJointTracked(userId, (int)joint) || |
||
655 | !kinectManager.IsJointTracked(userId, (int)jointParent)) |
||
656 | { |
||
657 | return; |
||
658 | } |
||
659 | |||
660 | if(boneIndex >= 27 && boneIndex <= 30) |
||
661 | { |
||
662 | // fingers or thumbs |
||
663 | if(fingerOrientations) |
||
664 | { |
||
665 | TransformSpecialBoneFingers(userId, (int)joint, boneIndex, flip); |
||
666 | } |
||
667 | |||
668 | return; |
||
669 | } |
||
670 | |||
671 | Vector3 jointDir = kinectManager.GetJointDirection(userId, (int)joint, false, true); |
||
672 | Quaternion jointRotation = jointDir != Vector3.zero ? Quaternion.FromToRotation(baseDir, jointDir) : Quaternion.identity; |
||
673 | |||
674 | if(!flip) |
||
675 | { |
||
676 | Vector3 mirroredAngles = jointRotation.eulerAngles; |
||
677 | mirroredAngles.y = -mirroredAngles.y; |
||
678 | mirroredAngles.z = -mirroredAngles.z; |
||
679 | |||
680 | jointRotation = Quaternion.Euler(mirroredAngles); |
||
681 | } |
||
682 | |||
683 | if(jointRotation != Quaternion.identity) |
||
684 | { |
||
685 | // Smoothly transition to the new rotation |
||
686 | Quaternion newRotation = Kinect2AvatarRot(jointRotation, boneIndex); |
||
687 | |||
688 | if(externalRootMotion) |
||
689 | { |
||
690 | newRotation = transform.rotation * newRotation; |
||
691 | } |
||
692 | |||
693 | if(smoothFactor != 0f) |
||
694 | boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime); |
||
695 | else |
||
696 | boneTransform.rotation = newRotation; |
||
697 | } |
||
698 | |||
699 | } |
||
700 | |||
701 | // Apply the rotations tracked by kinect to fingers (one joint = multiple bones) |
||
702 | protected void TransformSpecialBoneFingers(Int64 userId, int joint, int boneIndex, bool flip) |
||
703 | { |
||
704 | // check for hand grips |
||
705 | if(joint == (int)KinectInterop.JointType.HandTipLeft || joint == (int)KinectInterop.JointType.ThumbLeft) |
||
706 | { |
||
707 | if(lastLeftHandEvent == InteractionManager.HandEventType.Grip) |
||
708 | { |
||
709 | if(!bLeftFistDone) |
||
710 | { |
||
711 | float angleSign = !mirroredMovement /**(boneIndex == 27 || boneIndex == 29)*/ ? -1f : -1f; |
||
712 | float angleRot = angleSign * 60f; |
||
713 | |||
714 | TransformSpecialBoneFist(boneIndex, angleRot); |
||
715 | bLeftFistDone = (boneIndex >= 29); |
||
716 | } |
||
717 | |||
718 | return; |
||
719 | } |
||
720 | else if(bLeftFistDone && lastLeftHandEvent == InteractionManager.HandEventType.Release) |
||
721 | { |
||
722 | TransformSpecialBoneUnfist(boneIndex); |
||
723 | bLeftFistDone = !(boneIndex >= 29); |
||
724 | } |
||
725 | } |
||
726 | else if(joint == (int)KinectInterop.JointType.HandTipRight || joint == (int)KinectInterop.JointType.ThumbRight) |
||
727 | { |
||
728 | if(lastRightHandEvent == InteractionManager.HandEventType.Grip) |
||
729 | { |
||
730 | if(!bRightFistDone) |
||
731 | { |
||
732 | float angleSign = !mirroredMovement /**(boneIndex == 27 || boneIndex == 29)*/ ? -1f : -1f; |
||
733 | float angleRot = angleSign * 60f; |
||
734 | |||
735 | TransformSpecialBoneFist(boneIndex, angleRot); |
||
736 | bRightFistDone = (boneIndex >= 29); |
||
737 | } |
||
738 | |||
739 | return; |
||
740 | } |
||
741 | else if(bRightFistDone && lastRightHandEvent == InteractionManager.HandEventType.Release) |
||
742 | { |
||
743 | TransformSpecialBoneUnfist(boneIndex); |
||
744 | bRightFistDone = !(boneIndex >= 29); |
||
745 | } |
||
746 | } |
||
747 | |||
748 | // get the animator component |
||
749 | //Animator animatorComponent = GetComponent<Animator>(); |
||
750 | if(!animatorComponent) |
||
751 | return; |
||
752 | |||
753 | // Get Kinect joint orientation |
||
754 | Quaternion jointRotation = kinectManager.GetJointOrientation(userId, joint, flip); |
||
755 | if(jointRotation == Quaternion.identity) |
||
756 | return; |
||
757 | |||
758 | // calculate the new orientation |
||
759 | Quaternion newRotation = Kinect2AvatarRot(jointRotation, boneIndex); |
||
760 | |||
761 | if(externalRootMotion) |
||
762 | { |
||
763 | newRotation = transform.rotation * newRotation; |
||
764 | } |
||
765 | |||
766 | // get the list of bones |
||
767 | //List<HumanBodyBones> alBones = flip ? specialIndex2MultiBoneMap[boneIndex] : specialIndex2MirrorBoneMap[boneIndex]; |
||
768 | List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex]; |
||
769 | |||
770 | // Smoothly transition to the new rotation |
||
771 | for(int i = 0; i < alBones.Count; i++) |
||
772 | { |
||
773 | Transform boneTransform = animatorComponent.GetBoneTransform(alBones[i]); |
||
774 | if(!boneTransform) |
||
775 | continue; |
||
776 | |||
777 | if(smoothFactor != 0f) |
||
778 | boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime); |
||
779 | else |
||
780 | boneTransform.rotation = newRotation; |
||
781 | } |
||
782 | } |
||
783 | |||
784 | // Apply the rotations needed to transform fingers to fist |
||
785 | protected void TransformSpecialBoneFist(int boneIndex, float angle) |
||
786 | { |
||
787 | // // do fist only for fingers |
||
788 | // if(boneIndex != 27 && boneIndex != 28) |
||
789 | // return; |
||
790 | |||
791 | // get the animator component |
||
792 | //Animator animatorComponent = GetComponent<Animator>(); |
||
793 | if(!animatorComponent) |
||
794 | return; |
||
795 | |||
796 | // get the list of bones |
||
797 | List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex]; |
||
798 | |||
799 | for(int i = 0; i < alBones.Count; i++) |
||
800 | { |
||
801 | if(i < 1 && (boneIndex == 29 || boneIndex == 30)) // skip the first two thumb bones |
||
802 | continue; |
||
803 | |||
804 | HumanBodyBones bone = alBones[i]; |
||
805 | Transform boneTransform = animatorComponent.GetBoneTransform(bone); |
||
806 | |||
807 | // set the fist rotation |
||
808 | if(boneTransform && fingerBoneLocalAxes[bone] != Vector3.zero) |
||
809 | { |
||
810 | Quaternion qRotFinger = Quaternion.AngleAxis(angle, fingerBoneLocalAxes[bone]); |
||
811 | boneTransform.localRotation = fingerBoneLocalRotations[bone] * qRotFinger; |
||
812 | } |
||
813 | } |
||
814 | |||
815 | } |
||
816 | |||
817 | // Apply the initial rotations fingers |
||
818 | protected void TransformSpecialBoneUnfist(int boneIndex) |
||
819 | { |
||
820 | // // do fist only for fingers |
||
821 | // if(boneIndex != 27 && boneIndex != 28) |
||
822 | // return; |
||
823 | |||
824 | // get the animator component |
||
825 | //Animator animatorComponent = GetComponent<Animator>(); |
||
826 | if(!animatorComponent) |
||
827 | return; |
||
828 | |||
829 | // get the list of bones |
||
830 | List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex]; |
||
831 | |||
832 | for(int i = 0; i < alBones.Count; i++) |
||
833 | { |
||
834 | HumanBodyBones bone = alBones[i]; |
||
835 | Transform boneTransform = animatorComponent.GetBoneTransform(bone); |
||
836 | |||
837 | // set the initial rotation |
||
838 | if(boneTransform) |
||
839 | { |
||
840 | boneTransform.localRotation = fingerBoneLocalRotations[bone]; |
||
841 | } |
||
842 | } |
||
843 | } |
||
844 | |||
845 | // Moves the avatar - gets the tracked position of the user and applies it to avatar. |
||
846 | protected void MoveAvatar(Int64 UserID) |
||
847 | { |
||
848 | if((moveRate == 0f) || !kinectManager || |
||
849 | !kinectManager.IsJointTracked(UserID, (int)KinectInterop.JointType.SpineBase)) |
||
850 | { |
||
851 | return; |
||
852 | } |
||
853 | |||
854 | // get the position of user's spine base |
||
855 | Vector3 trans = kinectManager.GetUserPosition(UserID); |
||
856 | if(flipLeftRight) |
||
857 | trans.x = -trans.x; |
||
858 | |||
859 | // use the color overlay position if needed |
||
860 | if(posRelativeToCamera && posRelOverlayColor) |
||
861 | { |
||
862 | Rect backgroundRect = posRelativeToCamera.pixelRect; |
||
863 | PortraitBackground portraitBack = PortraitBackground.Instance; |
||
864 | |||
865 | if(portraitBack && portraitBack.enabled) |
||
866 | { |
||
867 | backgroundRect = portraitBack.GetBackgroundRect(); |
||
868 | } |
||
869 | |||
870 | trans = kinectManager.GetJointPosColorOverlay(UserID, (int)KinectInterop.JointType.SpineBase, posRelativeToCamera, backgroundRect); |
||
871 | if(flipLeftRight) |
||
872 | trans.x = -trans.x; |
||
873 | } |
||
874 | |||
875 | // invert the z-coordinate, if needed |
||
876 | if(posRelativeToCamera && posRelInvertedZ) |
||
877 | { |
||
878 | trans.z = -trans.z; |
||
879 | } |
||
880 | |||
881 | if(!offsetCalibrated) |
||
882 | { |
||
883 | offsetCalibrated = true; |
||
884 | |||
885 | offsetPos.x = trans.x; // !mirroredMovement ? trans.x * moveRate : -trans.x * moveRate; |
||
886 | offsetPos.y = trans.y; // trans.y * moveRate; |
||
887 | offsetPos.z = !mirroredMovement && !posRelativeToCamera ? -trans.z : trans.z; // -trans.z * moveRate; |
||
888 | |||
889 | if(posRelativeToCamera) |
||
890 | { |
||
891 | Vector3 cameraPos = posRelativeToCamera.transform.position; |
||
892 | Vector3 bodyRootPos = bodyRoot != null ? bodyRoot.position : transform.position; |
||
893 | Vector3 hipCenterPos = bodyRoot != null ? bodyRoot.position : (bones != null && bones.Length > 0 && bones[0] != null ? bones[0].position : Vector3.zero); |
||
894 | |||
895 | float yRelToAvatar = 0f; |
||
896 | if(verticalMovement) |
||
897 | { |
||
898 | yRelToAvatar = (trans.y - cameraPos.y) - (hipCenterPos - bodyRootPos).magnitude; |
||
899 | } |
||
900 | else |
||
901 | { |
||
902 | yRelToAvatar = bodyRootPos.y - cameraPos.y; |
||
903 | } |
||
904 | |||
905 | Vector3 relativePos = new Vector3(trans.x, yRelToAvatar, trans.z); |
||
906 | Vector3 newBodyRootPos = cameraPos + relativePos; |
||
907 | |||
908 | // if(offsetNode != null) |
||
909 | // { |
||
910 | // newBodyRootPos += offsetNode.transform.position; |
||
911 | // } |
||
912 | |||
913 | if(bodyRoot != null) |
||
914 | { |
||
915 | bodyRoot.position = newBodyRootPos; |
||
916 | } |
||
917 | else |
||
918 | { |
||
919 | transform.position = newBodyRootPos; |
||
920 | } |
||
921 | |||
922 | bodyRootPosition = newBodyRootPos; |
||
923 | } |
||
924 | } |
||
925 | |||
926 | // transition to the new position |
||
927 | Vector3 targetPos = bodyRootPosition + Kinect2AvatarPos(trans, verticalMovement); |
||
928 | |||
929 | if(isRigidBody && !verticalMovement) |
||
930 | { |
||
931 | // workaround for obeying the physics (e.g. gravity falling) |
||
932 | targetPos.y = bodyRoot != null ? bodyRoot.position.y : transform.position.y; |
||
933 | } |
||
934 | |||
935 | if (verticalMovement && verticalOffset != 0f && |
||
936 | bones[0] != null && bones[3] != null) |
||
937 | { |
||
938 | Vector3 dirSpine = bones[3].position - bones[0].position; |
||
939 | targetPos += dirSpine.normalized * verticalOffset; |
||
940 | } |
||
941 | |||
942 | if (forwardOffset != 0f && |
||
943 | bones[0] != null && bones[3] != null && bones[5] != null && bones[11] != null) |
||
944 | { |
||
945 | Vector3 dirSpine = (bones[3].position - bones[0].position).normalized; |
||
946 | Vector3 dirShoulders = (bones[11].position - bones[5].position).normalized; |
||
947 | Vector3 dirForward = Vector3.Cross(dirShoulders, dirSpine).normalized; |
||
948 | |||
949 | targetPos += dirForward * forwardOffset; |
||
950 | } |
||
951 | |||
952 | if(groundedFeet) |
||
953 | { |
||
954 | // keep the current correction |
||
955 | float fLastTgtY = targetPos.y; |
||
956 | targetPos.y += fFootDistance; |
||
957 | |||
958 | float fNewDistance = GetDistanceToGround(); |
||
959 | float fNewDistanceTime = Time.time; |
||
960 | |||
961 | // Debug.Log(string.Format("PosY: {0:F2}, LastY: {1:F2}, TgrY: {2:F2}, NewDist: {3:F2}, Corr: {4:F2}, Time: {5:F2}", bodyRoot != null ? bodyRoot.position.y : transform.position.y, |
||
962 | // fLastTgtY, targetPos.y, fNewDistance, fFootDistance, fNewDistanceTime)); |
||
963 | |||
964 | if(Mathf.Abs(fNewDistance) >= 0.01f && Mathf.Abs(fNewDistance - fFootDistanceInitial) >= maxFootDistanceGround) |
||
965 | { |
||
966 | if((fNewDistanceTime - fFootDistanceTime) >= maxFootDistanceTime) |
||
967 | { |
||
968 | fFootDistance += (fNewDistance - fFootDistanceInitial); |
||
969 | fFootDistanceTime = fNewDistanceTime; |
||
970 | |||
971 | targetPos.y = fLastTgtY + fFootDistance; |
||
972 | |||
973 | // Debug.Log(string.Format(" >> change({0:F2})! - Corr: {1:F2}, LastY: {2:F2}, TgrY: {3:F2} at time {4:F2}", |
||
974 | // (fNewDistance - fFootDistanceInitial), fFootDistance, fLastTgtY, targetPos.y, fFootDistanceTime)); |
||
975 | } |
||
976 | } |
||
977 | else |
||
978 | { |
||
979 | fFootDistanceTime = fNewDistanceTime; |
||
980 | } |
||
981 | } |
||
982 | |||
983 | if(bodyRoot != null) |
||
984 | { |
||
985 | bodyRoot.position = smoothFactor != 0f ? |
||
986 | Vector3.Lerp(bodyRoot.position, targetPos, smoothFactor * Time.deltaTime) : targetPos; |
||
987 | } |
||
988 | else |
||
989 | { |
||
990 | transform.position = smoothFactor != 0f ? |
||
991 | Vector3.Lerp(transform.position, targetPos, smoothFactor * Time.deltaTime) : targetPos; |
||
992 | } |
||
993 | } |
||
994 | |||
995 | // Set model's arms to be in T-pose |
||
996 | protected void SetModelArmsInTpose() |
||
997 | { |
||
998 | Vector3 vTposeLeftDir = transform.TransformDirection(Vector3.left); |
||
999 | Vector3 vTposeRightDir = transform.TransformDirection(Vector3.right); |
||
1000 | |||
1001 | Transform transLeftUarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ShoulderLeft, false)); // animator.GetBoneTransform(HumanBodyBones.LeftUpperArm); |
||
1002 | Transform transLeftLarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ElbowLeft, false)); // animator.GetBoneTransform(HumanBodyBones.LeftLowerArm); |
||
1003 | Transform transLeftHand = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.WristLeft, false)); // animator.GetBoneTransform(HumanBodyBones.LeftHand); |
||
1004 | |||
1005 | if(transLeftUarm != null && transLeftLarm != null) |
||
1006 | { |
||
1007 | Vector3 vUarmLeftDir = transLeftLarm.position - transLeftUarm.position; |
||
1008 | float fUarmLeftAngle = Vector3.Angle(vUarmLeftDir, vTposeLeftDir); |
||
1009 | |||
1010 | if(Mathf.Abs(fUarmLeftAngle) >= 5f) |
||
1011 | { |
||
1012 | Quaternion vFixRotation = Quaternion.FromToRotation(vUarmLeftDir, vTposeLeftDir); |
||
1013 | transLeftUarm.rotation = vFixRotation * transLeftUarm.rotation; |
||
1014 | } |
||
1015 | |||
1016 | if(transLeftHand != null) |
||
1017 | { |
||
1018 | Vector3 vLarmLeftDir = transLeftHand.position - transLeftLarm.position; |
||
1019 | float fLarmLeftAngle = Vector3.Angle(vLarmLeftDir, vTposeLeftDir); |
||
1020 | |||
1021 | if(Mathf.Abs(fLarmLeftAngle) >= 5f) |
||
1022 | { |
||
1023 | Quaternion vFixRotation = Quaternion.FromToRotation(vLarmLeftDir, vTposeLeftDir); |
||
1024 | transLeftLarm.rotation = vFixRotation * transLeftLarm.rotation; |
||
1025 | } |
||
1026 | } |
||
1027 | } |
||
1028 | |||
1029 | Transform transRightUarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ShoulderRight, false)); // animator.GetBoneTransform(HumanBodyBones.RightUpperArm); |
||
1030 | Transform transRightLarm = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.ElbowRight, false)); // animator.GetBoneTransform(HumanBodyBones.RightLowerArm); |
||
1031 | Transform transRightHand = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.WristRight, false)); // animator.GetBoneTransform(HumanBodyBones.RightHand); |
||
1032 | |||
1033 | if(transRightUarm != null && transRightLarm != null) |
||
1034 | { |
||
1035 | Vector3 vUarmRightDir = transRightLarm.position - transRightUarm.position; |
||
1036 | float fUarmRightAngle = Vector3.Angle(vUarmRightDir, vTposeRightDir); |
||
1037 | |||
1038 | if(Mathf.Abs(fUarmRightAngle) >= 5f) |
||
1039 | { |
||
1040 | Quaternion vFixRotation = Quaternion.FromToRotation(vUarmRightDir, vTposeRightDir); |
||
1041 | transRightUarm.rotation = vFixRotation * transRightUarm.rotation; |
||
1042 | } |
||
1043 | |||
1044 | if(transRightHand != null) |
||
1045 | { |
||
1046 | Vector3 vLarmRightDir = transRightHand.position - transRightLarm.position; |
||
1047 | float fLarmRightAngle = Vector3.Angle(vLarmRightDir, vTposeRightDir); |
||
1048 | |||
1049 | if(Mathf.Abs(fLarmRightAngle) >= 5f) |
||
1050 | { |
||
1051 | Quaternion vFixRotation = Quaternion.FromToRotation(vLarmRightDir, vTposeRightDir); |
||
1052 | transRightLarm.rotation = vFixRotation * transRightLarm.rotation; |
||
1053 | } |
||
1054 | } |
||
1055 | } |
||
1056 | |||
1057 | } |
||
1058 | |||
1059 | // If the bones to be mapped have been declared, map that bone to the model. |
||
1060 | protected virtual void MapBones() |
||
1061 | { |
||
1062 | // // make OffsetNode as a parent of model transform. |
||
1063 | // offsetNode = new GameObject(name + "Ctrl") { layer = transform.gameObject.layer, tag = transform.gameObject.tag }; |
||
1064 | // offsetNode.transform.position = transform.position; |
||
1065 | // offsetNode.transform.rotation = transform.rotation; |
||
1066 | // offsetNode.transform.parent = transform.parent; |
||
1067 | |||
1068 | // // take model transform as body root |
||
1069 | // transform.parent = offsetNode.transform; |
||
1070 | // transform.localPosition = Vector3.zero; |
||
1071 | // transform.localRotation = Quaternion.identity; |
||
1072 | |||
1073 | //bodyRoot = transform; |
||
1074 | |||
1075 | // get bone transforms from the animator component |
||
1076 | //Animator animatorComponent = GetComponent<Animator>(); |
||
1077 | |||
1078 | for (int boneIndex = 0; boneIndex < bones.Length; boneIndex++) |
||
1079 | { |
||
1080 | if (!boneIndex2MecanimMap.ContainsKey(boneIndex)) |
||
1081 | continue; |
||
1082 | |||
1083 | bones[boneIndex] = animatorComponent ? animatorComponent.GetBoneTransform(boneIndex2MecanimMap[boneIndex]) : null; |
||
1084 | } |
||
1085 | } |
||
1086 | |||
1087 | // Capture the initial rotations of the bones |
||
1088 | protected void GetInitialRotations() |
||
1089 | { |
||
1090 | // save the initial rotation |
||
1091 | if(offsetNode != null) |
||
1092 | { |
||
1093 | offsetNodePos = offsetNode.transform.position; |
||
1094 | offsetNodeRot = offsetNode.transform.rotation; |
||
1095 | } |
||
1096 | |||
1097 | initialPosition = transform.position; |
||
1098 | initialRotation = transform.rotation; |
||
1099 | |||
1100 | initialHipsPosition = bones[0] ? bones[0].localPosition : Vector3.zero; |
||
1101 | initialHipsRotation = bones[0] ? bones[0].localRotation : Quaternion.identity; |
||
1102 | |||
1103 | // if(offsetNode != null) |
||
1104 | // { |
||
1105 | // initialRotation = Quaternion.Inverse(offsetNodeRot) * initialRotation; |
||
1106 | // } |
||
1107 | |||
1108 | transform.rotation = Quaternion.identity; |
||
1109 | |||
1110 | // save the body root initial position |
||
1111 | if(bodyRoot != null) |
||
1112 | { |
||
1113 | bodyRootPosition = bodyRoot.position; |
||
1114 | } |
||
1115 | else |
||
1116 | { |
||
1117 | bodyRootPosition = transform.position; |
||
1118 | } |
||
1119 | |||
1120 | if(offsetNode != null) |
||
1121 | { |
||
1122 | bodyRootPosition = bodyRootPosition - offsetNodePos; |
||
1123 | } |
||
1124 | |||
1125 | // save the initial bone rotations |
||
1126 | for (int i = 0; i < bones.Length; i++) |
||
1127 | { |
||
1128 | if (bones[i] != null) |
||
1129 | { |
||
1130 | initialRotations[i] = bones[i].rotation; |
||
1131 | localRotations[i] = bones[i].localRotation; |
||
1132 | } |
||
1133 | } |
||
1134 | |||
1135 | // get finger bones' local rotations |
||
1136 | //Animator animatorComponent = GetComponent<Animator>(); |
||
1137 | foreach(int boneIndex in specialIndex2MultiBoneMap.Keys) |
||
1138 | { |
||
1139 | List<HumanBodyBones> alBones = specialIndex2MultiBoneMap[boneIndex]; |
||
1140 | //Transform handTransform = animatorComponent.GetBoneTransform((boneIndex == 27 || boneIndex == 29) ? HumanBodyBones.LeftHand : HumanBodyBones.RightHand); |
||
1141 | |||
1142 | for(int b = 0; b < alBones.Count; b++) |
||
1143 | { |
||
1144 | HumanBodyBones bone = alBones[b]; |
||
1145 | Transform boneTransform = animatorComponent ? animatorComponent.GetBoneTransform(bone) : null; |
||
1146 | |||
1147 | // get the finger's 1st transform |
||
1148 | Transform fingerBaseTransform = animatorComponent ? animatorComponent.GetBoneTransform(alBones[b - (b % 3)]) : null; |
||
1149 | //Vector3 vBoneDirParent = handTransform && fingerBaseTransform ? (handTransform.position - fingerBaseTransform.position).normalized : Vector3.zero; |
||
1150 | |||
1151 | // get the finger's 2nd transform |
||
1152 | Transform baseChildTransform = fingerBaseTransform && fingerBaseTransform.childCount > 0 ? fingerBaseTransform.GetChild(0) : null; |
||
1153 | Vector3 vBoneDirChild = baseChildTransform && fingerBaseTransform ? (baseChildTransform.position - fingerBaseTransform.position).normalized : Vector3.zero; |
||
1154 | Vector3 vOrthoDirChild = Vector3.Cross(vBoneDirChild, Vector3.up).normalized; |
||
1155 | |||
1156 | if(boneTransform) |
||
1157 | { |
||
1158 | fingerBoneLocalRotations[bone] = boneTransform.localRotation; |
||
1159 | |||
1160 | if (vBoneDirChild != Vector3.zero) |
||
1161 | { |
||
1162 | fingerBoneLocalAxes[bone] = boneTransform.InverseTransformDirection(vOrthoDirChild).normalized; |
||
1163 | } |
||
1164 | else |
||
1165 | { |
||
1166 | fingerBoneLocalAxes [bone] = Vector3.zero; |
||
1167 | } |
||
1168 | |||
1169 | // Transform bparTransform = boneTransform ? boneTransform.parent : null; |
||
1170 | // Transform bchildTransform = boneTransform && boneTransform.childCount > 0 ? boneTransform.GetChild(0) : null; |
||
1171 | // |
||
1172 | // // get the finger base transform (1st joint) |
||
1173 | // Transform fingerBaseTransform = animatorComponent.GetBoneTransform(alBones[b - (b % 3)]); |
||
1174 | // Vector3 vBoneDir2 = (handTransform.position - fingerBaseTransform.position).normalized; |
||
1175 | // |
||
1176 | // // set the fist rotation |
||
1177 | // if(boneTransform && fingerBaseTransform && handTransform) |
||
1178 | // { |
||
1179 | // Vector3 vBoneDir = bchildTransform ? (bchildTransform.position - boneTransform.position).normalized : |
||
1180 | // (bparTransform ? (boneTransform.position - bparTransform.position).normalized : Vector3.zero); |
||
1181 | // |
||
1182 | // Vector3 vOrthoDir = Vector3.Cross(vBoneDir2, vBoneDir).normalized; |
||
1183 | // fingerBoneLocalAxes[bone] = boneTransform.InverseTransformDirection(vOrthoDir); |
||
1184 | // } |
||
1185 | } |
||
1186 | } |
||
1187 | } |
||
1188 | |||
1189 | // Restore the initial rotation |
||
1190 | transform.rotation = initialRotation; |
||
1191 | } |
||
1192 | |||
1193 | // Converts kinect joint rotation to avatar joint rotation, depending on joint initial rotation and offset rotation |
||
1194 | protected Quaternion Kinect2AvatarRot(Quaternion jointRotation, int boneIndex) |
||
1195 | { |
||
1196 | Quaternion newRotation = jointRotation * initialRotations[boneIndex]; |
||
1197 | //newRotation = initialRotation * newRotation; |
||
1198 | |||
1199 | // if(offsetNode != null) |
||
1200 | // { |
||
1201 | // newRotation = offsetNode.transform.rotation * newRotation; |
||
1202 | // } |
||
1203 | // else |
||
1204 | { |
||
1205 | newRotation = initialRotation * newRotation; |
||
1206 | } |
||
1207 | |||
1208 | return newRotation; |
||
1209 | } |
||
1210 | |||
1211 | // Converts Kinect position to avatar skeleton position, depending on initial position, mirroring and move rate |
||
1212 | protected Vector3 Kinect2AvatarPos(Vector3 jointPosition, bool bMoveVertically) |
||
1213 | { |
||
1214 | float xPos = (jointPosition.x - offsetPos.x) * moveRate; |
||
1215 | float yPos = (jointPosition.y - offsetPos.y) * moveRate; |
||
1216 | float zPos = !mirroredMovement && !posRelativeToCamera ? (-jointPosition.z - offsetPos.z) * moveRate : (jointPosition.z - offsetPos.z) * moveRate; |
||
1217 | |||
1218 | Vector3 newPosition = new Vector3(xPos, bMoveVertically ? yPos : 0f, zPos); |
||
1219 | |||
1220 | Quaternion posRotation = mirroredMovement ? Quaternion.Euler (0f, 180f, 0f) * initialRotation : initialRotation; |
||
1221 | newPosition = posRotation * newPosition; |
||
1222 | |||
1223 | if(offsetNode != null) |
||
1224 | { |
||
1225 | //newPosition += offsetNode.transform.position; |
||
1226 | newPosition = offsetNode.transform.position; |
||
1227 | } |
||
1228 | |||
1229 | return newPosition; |
||
1230 | } |
||
1231 | |||
1232 | // returns distance from the given transform to the underlying object. The player must be in IgnoreRaycast layer. |
||
1233 | protected virtual float GetTransformDistanceToGround(Transform trans) |
||
1234 | { |
||
1235 | if(!trans) |
||
1236 | return 0f; |
||
1237 | |||
1238 | // RaycastHit hit; |
||
1239 | // if(Physics.Raycast(trans.position, Vector3.down, out hit, 2f, raycastLayers)) |
||
1240 | // { |
||
1241 | // return -hit.distance; |
||
1242 | // } |
||
1243 | // else if(Physics.Raycast(trans.position, Vector3.up, out hit, 2f, raycastLayers)) |
||
1244 | // { |
||
1245 | // return hit.distance; |
||
1246 | // } |
||
1247 | // else |
||
1248 | // { |
||
1249 | // if (trans.position.y < 0) |
||
1250 | // return -trans.position.y; |
||
1251 | // else |
||
1252 | // return 1000f; |
||
1253 | // } |
||
1254 | |||
1255 | return -trans.position.y; |
||
1256 | } |
||
1257 | |||
1258 | // returns the lower distance distance from left or right foot to the ground, or 1000f if no LF/RF transforms are found |
||
1259 | protected virtual float GetDistanceToGround() |
||
1260 | { |
||
1261 | if(leftFoot == null && rightFoot == null) |
||
1262 | { |
||
1263 | // Animator animatorComponent = GetComponent<Animator>(); |
||
1264 | // |
||
1265 | // if(animatorComponent) |
||
1266 | // { |
||
1267 | // leftFoot = animatorComponent.GetBoneTransform(HumanBodyBones.LeftFoot); |
||
1268 | // rightFoot = animatorComponent.GetBoneTransform(HumanBodyBones.RightFoot); |
||
1269 | // } |
||
1270 | |||
1271 | leftFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.FootLeft, false)); |
||
1272 | rightFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.FootRight, false)); |
||
1273 | |||
1274 | if (leftFoot == null || rightFoot == null) |
||
1275 | { |
||
1276 | leftFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.AnkleLeft, false)); |
||
1277 | rightFoot = GetBoneTransform(GetBoneIndexByJoint(KinectInterop.JointType.AnkleRight, false)); |
||
1278 | } |
||
1279 | } |
||
1280 | |||
1281 | float fDistMin = 1000f; |
||
1282 | float fDistLeft = leftFoot ? GetTransformDistanceToGround(leftFoot) : fDistMin; |
||
1283 | float fDistRight = rightFoot ? GetTransformDistanceToGround(rightFoot) : fDistMin; |
||
1284 | fDistMin = Mathf.Abs(fDistLeft) < Mathf.Abs(fDistRight) ? fDistLeft : fDistRight; |
||
1285 | |||
1286 | if(fDistMin == 1000f) |
||
1287 | { |
||
1288 | fDistMin = 0f; // fFootDistanceInitial; |
||
1289 | } |
||
1290 | |||
1291 | // Debug.Log (string.Format ("LFootY: {0:F2}, Dist: {1:F2}, RFootY: {2:F2}, Dist: {3:F2}, Min: {4:F2}", leftFoot ? leftFoot.position.y : 0f, fDistLeft, |
||
1292 | // rightFoot ? rightFoot.position.y : 0f, fDistRight, fDistMin)); |
||
1293 | |||
1294 | return fDistMin; |
||
1295 | } |
||
1296 | |||
1297 | // protected void OnCollisionEnter(Collision col) |
||
1298 | // { |
||
1299 | // Debug.Log("Collision entered"); |
||
1300 | // } |
||
1301 | // |
||
1302 | // protected void OnCollisionExit(Collision col) |
||
1303 | // { |
||
1304 | // Debug.Log("Collision exited"); |
||
1305 | // } |
||
1306 | |||
1307 | // dictionaries to speed up bones' processing |
||
1308 | // the author of the terrific idea for kinect-joints to mecanim-bones mapping |
||
1309 | // along with its initial implementation, including following dictionary is |
||
1310 | // Mikhail Korchun (korchoon@gmail.com). Big thanks to this guy! |
||
1311 | protected static readonly Dictionary<int, HumanBodyBones> boneIndex2MecanimMap = new Dictionary<int, HumanBodyBones> |
||
1312 | { |
||
1313 | {0, HumanBodyBones.Hips}, |
||
1314 | {1, HumanBodyBones.Spine}, |
||
1315 | // {2, HumanBodyBones.Chest}, |
||
1316 | {3, HumanBodyBones.Neck}, |
||
1317 | // {4, HumanBodyBones.Head}, |
||
1318 | |||
1319 | {5, HumanBodyBones.LeftUpperArm}, |
||
1320 | {6, HumanBodyBones.LeftLowerArm}, |
||
1321 | {7, HumanBodyBones.LeftHand}, |
||
1322 | // {8, HumanBodyBones.LeftIndexProximal}, |
||
1323 | // {9, HumanBodyBones.LeftIndexIntermediate}, |
||
1324 | // {10, HumanBodyBones.LeftThumbProximal}, |
||
1325 | |||
1326 | {11, HumanBodyBones.RightUpperArm}, |
||
1327 | {12, HumanBodyBones.RightLowerArm}, |
||
1328 | {13, HumanBodyBones.RightHand}, |
||
1329 | // {14, HumanBodyBones.RightIndexProximal}, |
||
1330 | // {15, HumanBodyBones.RightIndexIntermediate}, |
||
1331 | // {16, HumanBodyBones.RightThumbProximal}, |
||
1332 | |||
1333 | {17, HumanBodyBones.LeftUpperLeg}, |
||
1334 | {18, HumanBodyBones.LeftLowerLeg}, |
||
1335 | {19, HumanBodyBones.LeftFoot}, |
||
1336 | // {20, HumanBodyBones.LeftToes}, |
||
1337 | |||
1338 | {21, HumanBodyBones.RightUpperLeg}, |
||
1339 | {22, HumanBodyBones.RightLowerLeg}, |
||
1340 | {23, HumanBodyBones.RightFoot}, |
||
1341 | // {24, HumanBodyBones.RightToes}, |
||
1342 | |||
1343 | {25, HumanBodyBones.LeftShoulder}, |
||
1344 | {26, HumanBodyBones.RightShoulder}, |
||
1345 | {27, HumanBodyBones.LeftIndexProximal}, |
||
1346 | {28, HumanBodyBones.RightIndexProximal}, |
||
1347 | {29, HumanBodyBones.LeftThumbProximal}, |
||
1348 | {30, HumanBodyBones.RightThumbProximal}, |
||
1349 | }; |
||
1350 | |||
1351 | protected static readonly Dictionary<int, KinectInterop.JointType> boneIndex2JointMap = new Dictionary<int, KinectInterop.JointType> |
||
1352 | { |
||
1353 | {0, KinectInterop.JointType.SpineBase}, |
||
1354 | {1, KinectInterop.JointType.SpineMid}, |
||
1355 | {2, KinectInterop.JointType.SpineShoulder}, |
||
1356 | {3, KinectInterop.JointType.Neck}, |
||
1357 | {4, KinectInterop.JointType.Head}, |
||
1358 | |||
1359 | {5, KinectInterop.JointType.ShoulderLeft}, |
||
1360 | {6, KinectInterop.JointType.ElbowLeft}, |
||
1361 | {7, KinectInterop.JointType.WristLeft}, |
||
1362 | {8, KinectInterop.JointType.HandLeft}, |
||
1363 | |||
1364 | {9, KinectInterop.JointType.HandTipLeft}, |
||
1365 | {10, KinectInterop.JointType.ThumbLeft}, |
||
1366 | |||
1367 | {11, KinectInterop.JointType.ShoulderRight}, |
||
1368 | {12, KinectInterop.JointType.ElbowRight}, |
||
1369 | {13, KinectInterop.JointType.WristRight}, |
||
1370 | {14, KinectInterop.JointType.HandRight}, |
||
1371 | |||
1372 | {15, KinectInterop.JointType.HandTipRight}, |
||
1373 | {16, KinectInterop.JointType.ThumbRight}, |
||
1374 | |||
1375 | {17, KinectInterop.JointType.HipLeft}, |
||
1376 | {18, KinectInterop.JointType.KneeLeft}, |
||
1377 | {19, KinectInterop.JointType.AnkleLeft}, |
||
1378 | {20, KinectInterop.JointType.FootLeft}, |
||
1379 | |||
1380 | {21, KinectInterop.JointType.HipRight}, |
||
1381 | {22, KinectInterop.JointType.KneeRight}, |
||
1382 | {23, KinectInterop.JointType.AnkleRight}, |
||
1383 | {24, KinectInterop.JointType.FootRight}, |
||
1384 | }; |
||
1385 | |||
1386 | protected static readonly Dictionary<int, List<KinectInterop.JointType>> specIndex2JointMap = new Dictionary<int, List<KinectInterop.JointType>> |
||
1387 | { |
||
1388 | {25, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderLeft, KinectInterop.JointType.SpineShoulder} }, |
||
1389 | {26, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderRight, KinectInterop.JointType.SpineShoulder} }, |
||
1390 | {27, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipLeft, KinectInterop.JointType.HandLeft} }, |
||
1391 | {28, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipRight, KinectInterop.JointType.HandRight} }, |
||
1392 | {29, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbLeft, KinectInterop.JointType.HandLeft} }, |
||
1393 | {30, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbRight, KinectInterop.JointType.HandRight} }, |
||
1394 | }; |
||
1395 | |||
1396 | protected static readonly Dictionary<int, KinectInterop.JointType> boneIndex2MirrorJointMap = new Dictionary<int, KinectInterop.JointType> |
||
1397 | { |
||
1398 | {0, KinectInterop.JointType.SpineBase}, |
||
1399 | {1, KinectInterop.JointType.SpineMid}, |
||
1400 | {2, KinectInterop.JointType.SpineShoulder}, |
||
1401 | {3, KinectInterop.JointType.Neck}, |
||
1402 | {4, KinectInterop.JointType.Head}, |
||
1403 | |||
1404 | {5, KinectInterop.JointType.ShoulderRight}, |
||
1405 | {6, KinectInterop.JointType.ElbowRight}, |
||
1406 | {7, KinectInterop.JointType.WristRight}, |
||
1407 | {8, KinectInterop.JointType.HandRight}, |
||
1408 | |||
1409 | {9, KinectInterop.JointType.HandTipRight}, |
||
1410 | {10, KinectInterop.JointType.ThumbRight}, |
||
1411 | |||
1412 | {11, KinectInterop.JointType.ShoulderLeft}, |
||
1413 | {12, KinectInterop.JointType.ElbowLeft}, |
||
1414 | {13, KinectInterop.JointType.WristLeft}, |
||
1415 | {14, KinectInterop.JointType.HandLeft}, |
||
1416 | |||
1417 | {15, KinectInterop.JointType.HandTipLeft}, |
||
1418 | {16, KinectInterop.JointType.ThumbLeft}, |
||
1419 | |||
1420 | {17, KinectInterop.JointType.HipRight}, |
||
1421 | {18, KinectInterop.JointType.KneeRight}, |
||
1422 | {19, KinectInterop.JointType.AnkleRight}, |
||
1423 | {20, KinectInterop.JointType.FootRight}, |
||
1424 | |||
1425 | {21, KinectInterop.JointType.HipLeft}, |
||
1426 | {22, KinectInterop.JointType.KneeLeft}, |
||
1427 | {23, KinectInterop.JointType.AnkleLeft}, |
||
1428 | {24, KinectInterop.JointType.FootLeft}, |
||
1429 | }; |
||
1430 | |||
1431 | protected static readonly Dictionary<int, List<KinectInterop.JointType>> specIndex2MirrorMap = new Dictionary<int, List<KinectInterop.JointType>> |
||
1432 | { |
||
1433 | {25, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderRight, KinectInterop.JointType.SpineShoulder} }, |
||
1434 | {26, new List<KinectInterop.JointType> {KinectInterop.JointType.ShoulderLeft, KinectInterop.JointType.SpineShoulder} }, |
||
1435 | {27, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipRight, KinectInterop.JointType.HandRight} }, |
||
1436 | {28, new List<KinectInterop.JointType> {KinectInterop.JointType.HandTipLeft, KinectInterop.JointType.HandLeft} }, |
||
1437 | {29, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbRight, KinectInterop.JointType.HandRight} }, |
||
1438 | {30, new List<KinectInterop.JointType> {KinectInterop.JointType.ThumbLeft, KinectInterop.JointType.HandLeft} }, |
||
1439 | }; |
||
1440 | |||
1441 | protected static readonly Dictionary<KinectInterop.JointType, int> jointMap2boneIndex = new Dictionary<KinectInterop.JointType, int> |
||
1442 | { |
||
1443 | {KinectInterop.JointType.SpineBase, 0}, |
||
1444 | {KinectInterop.JointType.SpineMid, 1}, |
||
1445 | {KinectInterop.JointType.SpineShoulder, 2}, |
||
1446 | {KinectInterop.JointType.Neck, 3}, |
||
1447 | {KinectInterop.JointType.Head, 4}, |
||
1448 | |||
1449 | {KinectInterop.JointType.ShoulderLeft, 5}, |
||
1450 | {KinectInterop.JointType.ElbowLeft, 6}, |
||
1451 | {KinectInterop.JointType.WristLeft, 7}, |
||
1452 | {KinectInterop.JointType.HandLeft, 8}, |
||
1453 | |||
1454 | {KinectInterop.JointType.HandTipLeft, 9}, |
||
1455 | {KinectInterop.JointType.ThumbLeft, 10}, |
||
1456 | |||
1457 | {KinectInterop.JointType.ShoulderRight, 11}, |
||
1458 | {KinectInterop.JointType.ElbowRight, 12}, |
||
1459 | {KinectInterop.JointType.WristRight, 13}, |
||
1460 | {KinectInterop.JointType.HandRight, 14}, |
||
1461 | |||
1462 | {KinectInterop.JointType.HandTipRight, 15}, |
||
1463 | {KinectInterop.JointType.ThumbRight, 16}, |
||
1464 | |||
1465 | {KinectInterop.JointType.HipLeft, 17}, |
||
1466 | {KinectInterop.JointType.KneeLeft, 18}, |
||
1467 | {KinectInterop.JointType.AnkleLeft, 19}, |
||
1468 | {KinectInterop.JointType.FootLeft, 20}, |
||
1469 | |||
1470 | {KinectInterop.JointType.HipRight, 21}, |
||
1471 | {KinectInterop.JointType.KneeRight, 22}, |
||
1472 | {KinectInterop.JointType.AnkleRight, 23}, |
||
1473 | {KinectInterop.JointType.FootRight, 24}, |
||
1474 | }; |
||
1475 | |||
1476 | protected static readonly Dictionary<KinectInterop.JointType, int> mirrorJointMap2boneIndex = new Dictionary<KinectInterop.JointType, int> |
||
1477 | { |
||
1478 | {KinectInterop.JointType.SpineBase, 0}, |
||
1479 | {KinectInterop.JointType.SpineMid, 1}, |
||
1480 | {KinectInterop.JointType.SpineShoulder, 2}, |
||
1481 | {KinectInterop.JointType.Neck, 3}, |
||
1482 | {KinectInterop.JointType.Head, 4}, |
||
1483 | |||
1484 | {KinectInterop.JointType.ShoulderRight, 5}, |
||
1485 | {KinectInterop.JointType.ElbowRight, 6}, |
||
1486 | {KinectInterop.JointType.WristRight, 7}, |
||
1487 | {KinectInterop.JointType.HandRight, 8}, |
||
1488 | |||
1489 | {KinectInterop.JointType.HandTipRight, 9}, |
||
1490 | {KinectInterop.JointType.ThumbRight, 10}, |
||
1491 | |||
1492 | {KinectInterop.JointType.ShoulderLeft, 11}, |
||
1493 | {KinectInterop.JointType.ElbowLeft, 12}, |
||
1494 | {KinectInterop.JointType.WristLeft, 13}, |
||
1495 | {KinectInterop.JointType.HandLeft, 14}, |
||
1496 | |||
1497 | {KinectInterop.JointType.HandTipLeft, 15}, |
||
1498 | {KinectInterop.JointType.ThumbLeft, 16}, |
||
1499 | |||
1500 | {KinectInterop.JointType.HipRight, 17}, |
||
1501 | {KinectInterop.JointType.KneeRight, 18}, |
||
1502 | {KinectInterop.JointType.AnkleRight, 19}, |
||
1503 | {KinectInterop.JointType.FootRight, 20}, |
||
1504 | |||
1505 | {KinectInterop.JointType.HipLeft, 21}, |
||
1506 | {KinectInterop.JointType.KneeLeft, 22}, |
||
1507 | {KinectInterop.JointType.AnkleLeft, 23}, |
||
1508 | {KinectInterop.JointType.FootLeft, 24}, |
||
1509 | }; |
||
1510 | |||
1511 | |||
1512 | protected static readonly Dictionary<int, List<HumanBodyBones>> specialIndex2MultiBoneMap = new Dictionary<int, List<HumanBodyBones>> |
||
1513 | { |
||
1514 | {27, new List<HumanBodyBones> { // left fingers |
||
1515 | HumanBodyBones.LeftIndexProximal, |
||
1516 | HumanBodyBones.LeftIndexIntermediate, |
||
1517 | HumanBodyBones.LeftIndexDistal, |
||
1518 | HumanBodyBones.LeftMiddleProximal, |
||
1519 | HumanBodyBones.LeftMiddleIntermediate, |
||
1520 | HumanBodyBones.LeftMiddleDistal, |
||
1521 | HumanBodyBones.LeftRingProximal, |
||
1522 | HumanBodyBones.LeftRingIntermediate, |
||
1523 | HumanBodyBones.LeftRingDistal, |
||
1524 | HumanBodyBones.LeftLittleProximal, |
||
1525 | HumanBodyBones.LeftLittleIntermediate, |
||
1526 | HumanBodyBones.LeftLittleDistal, |
||
1527 | }}, |
||
1528 | {28, new List<HumanBodyBones> { // right fingers |
||
1529 | HumanBodyBones.RightIndexProximal, |
||
1530 | HumanBodyBones.RightIndexIntermediate, |
||
1531 | HumanBodyBones.RightIndexDistal, |
||
1532 | HumanBodyBones.RightMiddleProximal, |
||
1533 | HumanBodyBones.RightMiddleIntermediate, |
||
1534 | HumanBodyBones.RightMiddleDistal, |
||
1535 | HumanBodyBones.RightRingProximal, |
||
1536 | HumanBodyBones.RightRingIntermediate, |
||
1537 | HumanBodyBones.RightRingDistal, |
||
1538 | HumanBodyBones.RightLittleProximal, |
||
1539 | HumanBodyBones.RightLittleIntermediate, |
||
1540 | HumanBodyBones.RightLittleDistal, |
||
1541 | }}, |
||
1542 | {29, new List<HumanBodyBones> { // left thumb |
||
1543 | HumanBodyBones.LeftThumbProximal, |
||
1544 | HumanBodyBones.LeftThumbIntermediate, |
||
1545 | HumanBodyBones.LeftThumbDistal, |
||
1546 | }}, |
||
1547 | {30, new List<HumanBodyBones> { // right thumb |
||
1548 | HumanBodyBones.RightThumbProximal, |
||
1549 | HumanBodyBones.RightThumbIntermediate, |
||
1550 | HumanBodyBones.RightThumbDistal, |
||
1551 | }}, |
||
1552 | }; |
||
1553 | |||
1554 | } |