13using System.Collections.Generic;
20 public static class Hands {
22 private static LeapProvider s_provider;
23 private static GameObject s_leapRig;
27 SceneManager.activeSceneChanged += InitStaticOnNewScene;
30 private static void InitStaticOnNewScene(Scene unused, Scene unused2) {
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) {
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;
54 public static GameObject CameraRig {
56 if (s_leapRig ==
null) {
75 public static LeapProvider Provider {
77 if (s_provider ==
null) {
82 set { s_provider = value; }
98 if (chirality ==
Chirality.Left)
return FixedLeft;
99 else return FixedRight;
108 if (Provider ==
null)
return null;
109 if (Provider.CurrentFrame ==
null)
return null;
110 return Provider.CurrentFrame.Hands.Query().FirstOrDefault(hand => hand.IsLeft);
120 if (Provider ==
null)
return null;
121 if (Provider.CurrentFrame ==
null)
return null;
122 else return Provider.CurrentFrame.Hands.Query().FirstOrDefault(hand => hand.IsRight);
130 public static Hand FixedLeft {
132 if (Provider ==
null)
return null;
133 if (Provider.CurrentFixedFrame ==
null)
return null;
134 return Provider.CurrentFixedFrame.Hands.Query().FirstOrDefault(hand => hand.IsLeft);
142 public static Hand FixedRight {
144 if (Provider ==
null)
return null;
145 if (Provider.CurrentFixedFrame ==
null)
return null;
146 else return Provider.CurrentFixedFrame.Hands.Query().FirstOrDefault(hand => hand.IsRight);
153 public static Finger GetThumb(
this Hand hand) {
161 public static Finger GetIndex(
this Hand hand) {
169 public static Finger GetMiddle(
this Hand hand) {
177 public static Finger GetRing(
this Hand hand) {
185 public static Finger GetPinky(
this Hand hand) {
192 public static Pose GetPalmPose(
this Hand hand) {
193 return new Pose(hand.PalmPosition.ToVector3(), hand.Rotation.ToQuaternion());
199 public static void SetPalmPose(
this Hand hand, Pose newPalmPose) {
200 hand.SetTransform(newPalmPose.position, newPalmPose.rotation);
209 public static Vector3 PalmarAxis(
this Hand hand) {
210 return -hand.Basis.yBasis.ToVector3();
219 public static Vector3 RadialAxis(
this Hand hand) {
221 return -hand.Basis.xBasis.ToVector3();
224 return hand.Basis.xBasis.ToVector3();
234 public static Vector3 DistalAxis (
this Hand hand) {
235 return hand.Basis.zBasis.ToVector3();
242 public static bool IsPinching(
this Hand hand) {
243 return hand.PinchStrength > 0.8F;
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;
261 public static Vector3 GetPredictedPinchPosition(
this Hand hand) {
262 Vector3 indexTip = hand.GetIndex().TipPosition.ToVector3();
263 Vector3 thumbTip = hand.GetThumb().TipPosition.ToVector3();
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);
278 return predictedPinchPoint;
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;
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() )
304 public static Ray HandRay(
this Hand hand, Transform headTransform) {
307 Vector3 ProjectionOrigin = headTransform.position
308 + (shoulderYaw * (
new Vector3(0f, -0.13f, -0.1f)
309 +
Vector3.left * 0.15f * (hand.IsLeft ? 1f : -1f)));
313 Vector3 ProjectionDirection = hand.Fingers[1].bones[0].NextJoint.ToVector3() - ProjectionOrigin;
314 return new Ray(ProjectionOrigin, ProjectionDirection);
320 public static void Transform(
this Bone bone, Vector3 position, Quaternion rotation) {
321 bone.Transform(
new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
327 public static void Transform(
this Finger finger, Vector3 position, Quaternion rotation) {
328 finger.Transform(
new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
334 public static void Transform(
this Hand hand, Vector3 position, Quaternion rotation) {
335 hand.Transform(
new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
341 public static void Transform(
this Frame frame, Vector3 position, Quaternion rotation) {
342 frame.Transform(
new LeapTransform(position.ToVector(), rotation.ToLeapQuaternion()));
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);
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);
364 public static void SetTransform(
this Hand hand, Vector3 position, Quaternion rotation) {
366 hand.Transform(position - hand.PalmPosition.ToVector3(),
Quaternion.identity);
374 public static class HandUtils {
380 public static void Fill(
this Hand toFill,
392 List<Finger> fingers,
394 Vector stabilizedPalmPosition,
397 LeapQuaternion rotation,
399 Vector wristPosition) {
400 toFill.FrameId = frameID;
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;
423 public static void Fill(
this Bone toFill,
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;
439 toFill.Rotation = rotation;
446 public static void Fill(
this Finger toFill,
456 Finger.FingerType type,
457 Bone metacarpal =
null,
458 Bone proximal =
null,
459 Bone intermediate =
null,
460 Bone distal =
null) {
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;
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;
480 public static void Fill(
this Arm toFill,
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;
501 public static void FillTemporalData(
this Hand toFill,
502 Hand previousHand,
float deltaTime) {
503 toFill.PalmVelocity = (toFill.PalmPosition - previousHand.PalmPosition)
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));
517 #region Provider Utils
519 public static Hand Get(
this LeapProvider provider,
Chirality whichHand) {
521 if (Time.inFixedTimeStep) {
522 frame = provider.CurrentFixedFrame;
525 frame = provider.CurrentFrame;
528 return frame.Get(whichHand);
The Finger class represents a tracked finger.
FingerType
Enumerates the names of the fingers.