Tanoda
RiggedFinger.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 UnityEngine;
10using System.Collections;
11using Leap;
12
13namespace Leap.Unity {
14
22 public class RiggedFinger : FingerModel {
23
28 [HideInInspector]
29 public bool deformPosition = false;
30
31 [HideInInspector]
32 public bool scaleLastFingerBone = false;
33
34 public Vector3 modelFingerPointing = Vector3.forward;
35 public Vector3 modelPalmFacing = -Vector3.up;
36
37 public Quaternion Reorientation() {
38 return Quaternion.Inverse(Quaternion.LookRotation(modelFingerPointing, -modelPalmFacing));
39 }
40
41
45 private static float[] s_standardFingertipLengths = null;
46 static RiggedFinger() {
47 // Calculate standard fingertip lengths.
48 s_standardFingertipLengths = new float[5];
49 var testHand = TestHandFactory.MakeTestHand(isLeft: true,
50 unitType: TestHandFactory.UnitType.UnityUnits);
51 for (int i = 0; i < 5; i++) {
52 var fingertipBone = testHand.Fingers[i].bones[3];
53 s_standardFingertipLengths[i] = fingertipBone.Length;
54 }
55 }
56
57 private RiggedHand _parentRiggedHand = null;
61 public override void UpdateFinger() {
62 for (int i = 0; i < bones.Length; ++i) {
63 if (bones[i] != null) {
64 bones[i].rotation = GetBoneRotation(i) * Reorientation();
65 if (deformPosition) {
66 var boneRootPos = GetJointPosition(i);
67 bones[i].position = boneRootPos;
68
69 if (i == 3 && scaleLastFingerBone) {
70 // Set fingertip base bone scale to match the bone length to the fingertip.
71 // This will only scale correctly if the model was constructed to match
72 // the standard "test" edit-time hand model from the TestHandFactory.
73 var boneTipPos = GetJointPosition(i + 1);
74 var boneVec = boneTipPos - boneRootPos;
75
76 // If the rigged hand is scaled (due to a scaled rig), we'll need to divide
77 // out that scale from the bone length to get its normal length.
78 if (_parentRiggedHand == null) {
79 _parentRiggedHand = GetComponentInParent<RiggedHand>();
80 }
81 if (_parentRiggedHand != null) {
82 var parentRiggedHandScale = _parentRiggedHand.transform.lossyScale.x;
83 if (parentRiggedHandScale != 0f && parentRiggedHandScale != 1f) {
84 boneVec /= parentRiggedHandScale;
85 }
86 }
87
88 var boneLen = boneVec.magnitude;
89
90 var standardLen = s_standardFingertipLengths[(int)this.fingerType];
91 var newScale = bones[i].transform.localScale;
92 var lengthComponentIdx = getLargestComponentIndex(modelFingerPointing);
93 newScale[lengthComponentIdx] = boneLen / standardLen;
94 bones[i].transform.localScale = newScale;
95 }
96 }
97 }
98 }
99 }
100
101 private int getLargestComponentIndex(Vector3 pointingVector) {
102 var largestValue = 0f;
103 var largestIdx = 0;
104 for (int i = 0; i < 3; i++) {
105 var testValue = pointingVector[i];
106 if (Mathf.Abs(testValue) > largestValue) {
107 largestIdx = i;
108 largestValue = Mathf.Abs(testValue);
109 }
110 }
111 return largestIdx;
112 }
113
114 public void SetupRiggedFinger (bool useMetaCarpals) {
115 findBoneTransforms(useMetaCarpals);
116 modelFingerPointing = calulateModelFingerPointing();
117 }
118
119 private void findBoneTransforms(bool useMetaCarpals) {
120 if (!useMetaCarpals || fingerType == Finger.FingerType.TYPE_THUMB) {
121 bones[1] = transform;
122 bones[2] = transform.GetChild(0).transform;
123 bones[3] = transform.GetChild(0).transform.GetChild(0).transform;
124 }
125 else {
126 bones[0] = transform;
127 bones[1] = transform.GetChild(0).transform;
128 bones[2] = transform.GetChild(0).transform.GetChild(0).transform;
129 bones[3] = transform.GetChild(0).transform.GetChild(0).transform.GetChild(0).transform;
130
131 }
132 }
133
134 private Vector3 calulateModelFingerPointing() {
135 Vector3 distance = transform.InverseTransformPoint(transform.position) - transform.InverseTransformPoint(transform.GetChild(0).transform.position);
136 Vector3 zeroed = RiggedHand.CalculateZeroedVector(distance);
137 return zeroed;
138 }
139
140 }
141}
The Finger class represents a tracked finger.
Definition: Finger.cs:20
FingerType
Enumerates the names of the fingers.
Definition: Finger.cs:167
Quaternion GetBoneRotation(int bone_type)
Definition: FingerModel.cs:140
Finger.FingerType fingerType
Definition: FingerModel.cs:34
Vector3 GetJointPosition(int joint)
Definition: FingerModel.cs:95
Manages the position and orientation of the bones in a model rigged for skeletal animation.
Definition: RiggedFinger.cs:22
bool deformPosition
Allows the mesh to be stretched to align with finger joint positions. Only set to true when mesh is n...
Definition: RiggedFinger.cs:29
Quaternion Reorientation()
Definition: RiggedFinger.cs:37
void SetupRiggedFinger(bool useMetaCarpals)
override void UpdateFinger()
Updates model bone positions and rotations based on tracked hand data.
Definition: RiggedFinger.cs:61
A skinned and jointed 3D HandModel.
Definition: RiggedHand.cs:20
static Vector3 CalculateZeroedVector(Vector3 vectorToZero)
Definition: RiggedHand.cs:266