Tanoda
HandUtils.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using Leap.Unity.Query;
11using UnityEngine;
12using UnityEngine.SceneManagement;
13using System.Collections.Generic;
14
15namespace Leap.Unity {
16
20 public static class Hands {
21
22 private static LeapProvider s_provider;
23 private static GameObject s_leapRig;
24
25 static Hands() {
26 InitStatic();
27 SceneManager.activeSceneChanged += InitStaticOnNewScene;
28 }
29
30 private static void InitStaticOnNewScene(Scene unused, Scene unused2) {
31 InitStatic();
32 }
33
34 private static void InitStatic() {
35 s_provider = Object.FindObjectOfType<LeapServiceProvider>();
36 if (s_provider == null) {
37 s_provider = Object.FindObjectOfType<LeapProvider>();
38 if (s_provider == null) {
39 return;
40 }
41 }
42
43 Camera providerCamera = s_provider.GetComponentInParent<Camera>();
44 if (providerCamera == null) return;
45 if (providerCamera.transform.parent == null) return;
46 s_leapRig = providerCamera.transform.parent.gameObject;
47 }
48
54 public static GameObject CameraRig {
55 get {
56 if (s_leapRig == null) {
57 InitStatic();
58 }
59 return s_leapRig;
60 }
61 }
62
75 public static LeapProvider Provider {
76 get {
77 if (s_provider == null) {
78 InitStatic();
79 }
80 return s_provider;
81 }
82 set { s_provider = value; }
83 }
84
89 public static Hand Get(Chirality chirality) {
90 if (chirality == Chirality.Left) return Left;
91 else return Right;
92 }
93
97 public static Hand GetFixed(Chirality chirality) {
98 if (chirality == Chirality.Left) return FixedLeft;
99 else return FixedRight;
100 }
101
106 public static Hand Left {
107 get {
108 if (Provider == null) return null;
109 if (Provider.CurrentFrame == null) return null;
110 return Provider.CurrentFrame.Hands.Query().FirstOrDefault(hand => hand.IsLeft);
111 }
112 }
113
118 public static Hand Right {
119 get {
120 if (Provider == null) return null;
121 if (Provider.CurrentFrame == null) return null;
122 else return Provider.CurrentFrame.Hands.Query().FirstOrDefault(hand => hand.IsRight);
123 }
124 }
125
130 public static Hand FixedLeft {
131 get {
132 if (Provider == null) return null;
133 if (Provider.CurrentFixedFrame == null) return null;
134 return Provider.CurrentFixedFrame.Hands.Query().FirstOrDefault(hand => hand.IsLeft);
135 }
136 }
137
142 public static Hand FixedRight {
143 get {
144 if (Provider == null) return null;
145 if (Provider.CurrentFixedFrame == null) return null;
146 else return Provider.CurrentFixedFrame.Hands.Query().FirstOrDefault(hand => hand.IsRight);
147 }
148 }
149
153 public static Finger GetThumb(this Hand hand) {
154 return hand.Fingers[(int)Leap.Finger.FingerType.TYPE_THUMB];
155 }
156
161 public static Finger GetIndex(this Hand hand) {
162 return hand.Fingers[(int)Leap.Finger.FingerType.TYPE_INDEX];
163 }
164
169 public static Finger GetMiddle(this Hand hand) {
170 return hand.Fingers[(int)Leap.Finger.FingerType.TYPE_MIDDLE];
171 }
172
177 public static Finger GetRing(this Hand hand) {
178 return hand.Fingers[(int)Leap.Finger.FingerType.TYPE_RING];
179 }
180
185 public static Finger GetPinky(this Hand hand) {
186 return hand.Fingers[(int)Leap.Finger.FingerType.TYPE_PINKY];
187 }
188
192 public static Pose GetPalmPose(this Hand hand) {
193 return new Pose(hand.PalmPosition.ToVector3(), hand.Rotation.ToQuaternion());
194 }
195
199 public static void SetPalmPose(this Hand hand, Pose newPalmPose) {
200 hand.SetTransform(newPalmPose.position, newPalmPose.rotation);
201 }
202
209 public static Vector3 PalmarAxis(this Hand hand) {
210 return -hand.Basis.yBasis.ToVector3();
211 }
212
219 public static Vector3 RadialAxis(this Hand hand) {
220 if (hand.IsRight) {
221 return -hand.Basis.xBasis.ToVector3();
222 }
223 else {
224 return hand.Basis.xBasis.ToVector3();
225 }
226 }
227
234 public static Vector3 DistalAxis (this Hand hand) {
235 return hand.Basis.zBasis.ToVector3();
236 }
237
242 public static bool IsPinching(this Hand hand) {
243 return hand.PinchStrength > 0.8F;
244 }
245
249 public static Vector3 GetPinchPosition(this Hand hand) {
250 Vector indexPosition = hand.Fingers[(int)Finger.FingerType.TYPE_INDEX].TipPosition;
251 Vector thumbPosition = hand.Fingers[(int)Finger.FingerType.TYPE_THUMB].TipPosition;
252 return (2 * thumbPosition + indexPosition).ToVector3() * 0.333333F;
253 }
254
261 public static Vector3 GetPredictedPinchPosition(this Hand hand) {
262 Vector3 indexTip = hand.GetIndex().TipPosition.ToVector3();
263 Vector3 thumbTip = hand.GetThumb().TipPosition.ToVector3();
264
265 // The predicted pinch point is a rigid point in hand-space linearly offset by the
266 // index finger knuckle position, scaled by the index finger's length, and lightly
267 // influenced by the actual thumb and index tip positions.
268 Vector3 indexKnuckle = hand.Fingers[1].bones[1].PrevJoint.ToVector3();
269 float indexLength = hand.Fingers[1].Length;
270 Vector3 radialAxis = hand.RadialAxis();
271 float thumbInfluence = Vector3.Dot((thumbTip - indexKnuckle).normalized, radialAxis).Map(0F, 1F, 0.5F, 0F);
272 Vector3 predictedPinchPoint = indexKnuckle + hand.PalmarAxis() * indexLength * 0.85F
273 + hand.DistalAxis() * indexLength * 0.20F
274 + radialAxis * indexLength * 0.20F;
275 predictedPinchPoint = Vector3.Lerp(predictedPinchPoint, thumbTip, thumbInfluence);
276 predictedPinchPoint = Vector3.Lerp(predictedPinchPoint, indexTip, 0.15F);
277
278 return predictedPinchPoint;
279 }
280
284 public static bool IsFacing(this Vector3 facingVector, Vector3 fromWorldPosition, Vector3 towardsWorldPosition, float maxOffsetAngleAllowed) {
285 Vector3 actualVectorTowardsWorldPosition = (towardsWorldPosition - fromWorldPosition).normalized;
286 return Vector3.Angle(facingVector, actualVectorTowardsWorldPosition) <= maxOffsetAngleAllowed;
287 }
288
292 public static float GetFistStrength(this Hand hand) {
293 return (Vector3.Dot(hand.Fingers[1].Direction.ToVector3(), -hand.DistalAxis() )
294 + Vector3.Dot(hand.Fingers[2].Direction.ToVector3(), -hand.DistalAxis() )
295 + Vector3.Dot(hand.Fingers[3].Direction.ToVector3(), -hand.DistalAxis() )
296 + Vector3.Dot(hand.Fingers[4].Direction.ToVector3(), -hand.DistalAxis() )
297 + Vector3.Dot(hand.Fingers[0].Direction.ToVector3(), -hand.RadialAxis() )
298 ).Map(-5, 5, 0, 1);
299 }
300
304 public static Ray HandRay(this Hand hand, Transform headTransform) {
305 Quaternion shoulderYaw = Quaternion.Euler(0f, headTransform.rotation.eulerAngles.y, 0f);
306 // Approximate shoulder position with magic values.
307 Vector3 ProjectionOrigin = headTransform.position
308 + (shoulderYaw * (new Vector3(0f, -0.13f, -0.1f)
309 + Vector3.left * 0.15f * (hand.IsLeft ? 1f : -1f)));
310 // Compare against this
311 //Vector3 ProjectionOrigin = headTransform.position + shoulderYaw *
312 // new Vector3(0.15f * (hand.IsLeft ? -1f : 1f), -0.13f, 0.05f);
313 Vector3 ProjectionDirection = hand.Fingers[1].bones[0].NextJoint.ToVector3() - ProjectionOrigin;
314 return new Ray(ProjectionOrigin, ProjectionDirection);
315 }
316
320 public static void Transform(this Bone bone, Vector3 position, Quaternion rotation) {
321 bone.Transform(new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
322 }
323
327 public static void Transform(this Finger finger, Vector3 position, Quaternion rotation) {
328 finger.Transform(new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
329 }
330
334 public static void Transform(this Hand hand, Vector3 position, Quaternion rotation) {
335 hand.Transform(new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
336 }
337
341 public static void Transform(this Frame frame, Vector3 position, Quaternion rotation) {
342 frame.Transform(new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
343 }
344
348 public static void SetTransform(this Bone bone, Vector3 position, Quaternion rotation) {
349 bone.Transform(Vector3.zero, (rotation * Quaternion.Inverse(bone.Rotation.ToQuaternion())));
350 bone.Transform(position - bone.PrevJoint.ToVector3(), Quaternion.identity);
351 }
352
356 public static void SetTipTransform(this Finger finger, Vector3 position, Quaternion rotation) {
357 finger.Transform(Vector3.zero, (rotation * Quaternion.Inverse(finger.bones[3].Rotation.ToQuaternion())));
358 finger.Transform(position - finger.bones[3].NextJoint.ToVector3(), Quaternion.identity);
359 }
360
364 public static void SetTransform(this Hand hand, Vector3 position, Quaternion rotation) {
365 hand.Transform(Vector3.zero, Quaternion.Slerp((rotation * Quaternion.Inverse(hand.Rotation.ToQuaternion())), Quaternion.identity, 0f));
366 hand.Transform(position - hand.PalmPosition.ToVector3(), Quaternion.identity);
367 }
368
369 }
370
374 public static class HandUtils {
375
380 public static void Fill(this Hand toFill,
381 long frameID,
382 int id,
383 float confidence,
384 float grabStrength,
385 float grabAngle,
386 float pinchStrength,
387 float pinchDistance,
388 float palmWidth,
389 bool isLeft,
390 float timeVisible,
391 /* Arm arm,*/
392 List<Finger> fingers,
393 Vector palmPosition,
394 Vector stabilizedPalmPosition,
395 Vector palmVelocity,
396 Vector palmNormal,
397 LeapQuaternion rotation,
398 Vector direction,
399 Vector wristPosition) {
400 toFill.FrameId = frameID;
401 toFill.Id = id;
402 toFill.Confidence = confidence;
403 toFill.GrabStrength = grabStrength;
404 toFill.GrabAngle = grabAngle;
405 toFill.PinchStrength = pinchStrength;
406 toFill.PinchDistance = pinchDistance;
407 toFill.PalmWidth = palmWidth;
408 toFill.IsLeft = isLeft;
409 toFill.TimeVisible = timeVisible;
410 if (fingers != null) toFill.Fingers = fingers;
411 toFill.PalmPosition = palmPosition;
412 toFill.StabilizedPalmPosition = stabilizedPalmPosition;
413 toFill.PalmVelocity = palmVelocity;
414 toFill.PalmNormal = palmNormal;
415 toFill.Rotation = rotation;
416 toFill.Direction = direction;
417 toFill.WristPosition = wristPosition;
418 }
419
423 public static void Fill(this Bone toFill,
424 Vector prevJoint,
425 Vector nextJoint,
426 Vector center,
427 Vector direction,
428 float length,
429 float width,
430 Bone.BoneType type,
431 LeapQuaternion rotation) {
432 toFill.PrevJoint = prevJoint;
433 toFill.NextJoint = nextJoint;
434 toFill.Center = center;
435 toFill.Direction = direction;
436 toFill.Length = length;
437 toFill.Width = width;
438 toFill.Type = type;
439 toFill.Rotation = rotation;
440 }
441
446 public static void Fill(this Finger toFill,
447 long frameId,
448 int handId,
449 int fingerId,
450 float timeVisible,
451 Vector tipPosition,
452 Vector direction,
453 float width,
454 float length,
455 bool isExtended,
456 Finger.FingerType type,
457 Bone metacarpal = null,
458 Bone proximal = null,
459 Bone intermediate = null,
460 Bone distal = null) {
461 toFill.Id = handId;
462 toFill.HandId = handId;
463 toFill.TimeVisible = timeVisible;
464 toFill.TipPosition = tipPosition;
465 toFill.Direction = direction;
466 toFill.Width = width;
467 toFill.Length = length;
468 toFill.IsExtended = isExtended;
469 toFill.Type = type;
470
471 if (metacarpal != null) toFill.bones[0] = metacarpal;
472 if (proximal != null) toFill.bones[1] = proximal;
473 if (intermediate != null) toFill.bones[2] = intermediate;
474 if (distal != null) toFill.bones[3] = distal;
475 }
476
480 public static void Fill(this Arm toFill,
481 Vector elbow,
482 Vector wrist,
483 Vector center,
484 Vector direction,
485 float length,
486 float width,
487 LeapQuaternion rotation) {
488 toFill.PrevJoint = elbow;
489 toFill.NextJoint = wrist;
490 toFill.Center = center;
491 toFill.Direction = direction;
492 toFill.Length = length;
493 toFill.Width = width;
494 toFill.Rotation = rotation;
495 }
496
501 public static void FillTemporalData(this Hand toFill,
502 Hand previousHand, float deltaTime) {
503 toFill.PalmVelocity = (toFill.PalmPosition - previousHand.PalmPosition)
504 / deltaTime;
505 }
506
507 #region Frame Utils
508
509 public static Hand Get(this Frame frame, Chirality whichHand) {
510 if (frame.Hands == null) { return null; }
511 return frame.Hands.Query().FirstOrDefault(
512 h => h.IsLeft == (whichHand == Chirality.Left));
513 }
514
515 #endregion
516
517 #region Provider Utils
518
519 public static Hand Get(this LeapProvider provider, Chirality whichHand) {
520 Frame frame;
521 if (Time.inFixedTimeStep) {
522 frame = provider.CurrentFixedFrame;
523 }
524 else {
525 frame = provider.CurrentFrame;
526 }
527
528 return frame.Get(whichHand);
529 }
530
531 #endregion
532
533 }
534
535}
The Finger class represents a tracked finger.
Definition: Finger.cs:20
FingerType
Enumerates the names of the fingers.
Definition: Finger.cs:167
UnityEngine.Object Object