comparison Orchestland/Assets/LeapMotion/Scripts/Hands/FingerModel.cs @ 3:0030a1b971fb default tip

merge
author Yuta ANSE <e135745@ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2015 23:23:43 +0900
parents f7675884f2a1
children
comparison
equal deleted inserted replaced
2:fdab88fc2cb9 3:0030a1b971fb
1 /******************************************************************************\
2 * Copyright (C) Leap Motion, Inc. 2011-2014. *
3 * Leap Motion proprietary. Licensed under Apache 2.0 *
4 * Available at http://www.apache.org/licenses/LICENSE-2.0.html *
5 \******************************************************************************/
6
7 using UnityEngine;
8 using System.Collections;
9 using Leap;
10
11 /**
12 * The base class for all fingers.
13 *
14 * This class serves as the interface between the HandController object,
15 * the parent Hand object and the concrete finger objects.
16 *
17 * Subclasses of FingerModel must implement InitFinger() and UpdateFinger(). The InitHand() function
18 * is typically called by the parent HandModel InitHand() method; likewise, the UpdateFinger()
19 * function is typically called by the parent HandModel UpdateHand() function.
20 */
21
22 public abstract class FingerModel : MonoBehaviour {
23
24 /** The number of bones in a finger. */
25 public const int NUM_BONES = 4;
26
27 /** The number of joints in a finger. */
28 public const int NUM_JOINTS = 3;
29
30 [HideInInspector]
31 public Finger.FingerType fingerType = Finger.FingerType.TYPE_INDEX;
32
33 // Unity references
34 /** Bones positioned and rotated by FingerModel. */
35 public Transform[] bones = new Transform[NUM_BONES];
36 /** Joints positioned and rotated by FingerModel. */
37 public Transform[] joints = new Transform[NUM_BONES - 1];
38
39 // Leap references
40 /** The Leap Hand object. */
41 protected Hand hand_;
42 /** The Leap Finger object. */
43 protected Finger finger_;
44 /** An added offset vector. */
45 protected Vector3 offset_ = Vector3.zero;
46 /** Whether this finger is mirrored. */
47 protected bool mirror_z_axis_ = false;
48
49 /** The parent HandController instance. */
50 protected HandController controller_;
51
52 /** Assigns the HandController parent for this FingerModel object. */
53 public void SetController(HandController controller) {
54 controller_ = controller;
55 }
56
57 /** The parent HandController instance. */
58 public HandController GetController() {
59 return controller_;
60 }
61
62 /** Sets the Leap Hand and Leap Finger for this finger.
63 * Note that Leap Hand and Finger objects are recreated every frame. The
64 * parent HandModel object calls this function to set or update the underlying
65 * finger. The tracking data in the Leap objects are used to update the FingerModel.
66 */
67 public void SetLeapHand(Hand hand) {
68 hand_ = hand;
69 if (hand_ != null)
70 finger_ = hand.Fingers[(int)fingerType];
71 }
72
73 /** Sets an offset vector to displace the finger from its normally calculated
74 * position relative to the HandController. Typically, this offset is used to
75 * give the virtual hands a larger range of motion then they would have based on their
76 * scaled size in the Unity scene.
77 */
78 public void SetOffset(Vector3 offset) {
79 offset_ = offset;
80 }
81
82 /**
83 * Sets the mirror z-axis flag for this Finger Model.
84 * Mirroring the z axis reverses the hand so that they face the opposite direction -- as if in a mirror.
85 * @param mirror Set true, the default value to mirror; false for normal rendering.
86 */
87 public void MirrorZAxis(bool mirror = true) {
88 mirror_z_axis_ = mirror;
89 }
90
91 /** The Leap Hand object. */
92 public Hand GetLeapHand() { return hand_; }
93 /** The Leap Finger object. */
94 public Finger GetLeapFinger() { return finger_; }
95
96 /**
97 * Implement this function to initialize this finger after it is created.
98 * Typically, this function is called by the parent HandModel object.
99 */
100 public virtual void InitFinger() {
101 UpdateFinger();
102 }
103
104 /**
105 * Implement this function to update this finger once per game loop.
106 * Typically, this function is called by the parent HandModel object's
107 * UpdateHand() function, which is called in the Unity Update() phase for
108 * graphics hand models and in the FixedUpdate() phase for physics hand
109 * models.
110 */
111 public abstract void UpdateFinger();
112
113 /** Returns any additional movement the finger needs because of non-relative palm movement.*/
114 public Vector3 GetOffset() {
115 return offset_;
116 }
117
118 /** Returns the location of the tip of the finger in relation to the controller.*/
119 public Vector3 GetTipPosition() {
120 if (controller_ != null && finger_ != null) {
121 Vector3 local_tip = finger_.Bone ((Bone.BoneType.TYPE_DISTAL)).NextJoint.ToUnityScaled (mirror_z_axis_);
122 return controller_.transform.TransformPoint (local_tip) + offset_;
123 }
124 if (bones [NUM_BONES - 1] && joints [NUM_JOINTS - 2]) {
125 return 2f*bones [NUM_BONES - 1].position - joints [NUM_JOINTS - 2].position;
126 }
127 return Vector3.zero;
128 }
129
130 /** Returns the location of the given joint on the finger in relation to the controller.*/
131 public Vector3 GetJointPosition(int joint) {
132 if (joint >= NUM_BONES) {
133 return GetTipPosition ();
134 }
135 if (controller_ != null && finger_ != null) {
136 Vector3 local_position = finger_.Bone ((Bone.BoneType)(joint)).PrevJoint.ToUnityScaled (mirror_z_axis_);
137 return controller_.transform.TransformPoint (local_position) + offset_;
138 }
139 if (joints [joint]) {
140 return joints[joint].position;
141 }
142 return Vector3.zero;
143 }
144
145 /** Returns a ray from the tip of the finger in the direction it is pointing.*/
146 public Ray GetRay() {
147 Ray ray = new Ray(GetTipPosition(), GetBoneDirection(NUM_BONES - 1));
148 return ray;
149 }
150
151 /** Returns the center of the given bone on the finger in relation to the controller.*/
152 public Vector3 GetBoneCenter(int bone_type) {
153 if (controller_ != null && finger_ != null) {
154 Bone bone = finger_.Bone ((Bone.BoneType)(bone_type));
155 return controller_.transform.TransformPoint (bone.Center.ToUnityScaled (mirror_z_axis_)) + offset_;
156 }
157 if (bones [bone_type]) {
158 return bones[bone_type].position;
159 }
160 return Vector3.zero;
161 }
162
163 /** Returns the direction the given bone is facing on the finger in relation to the controller.*/
164 public Vector3 GetBoneDirection(int bone_type) {
165 if (controller_ != null && finger_ != null) {
166 Vector3 direction = GetJointPosition (bone_type + 1) - GetJointPosition (bone_type);
167 return direction.normalized;
168 }
169 if (bones[bone_type]) {
170 return bones[bone_type].forward;
171 }
172 return Vector3.forward;
173 }
174
175 /** Returns the rotation quaternion of the given bone in relation to the controller.*/
176 public Quaternion GetBoneRotation(int bone_type) {
177 if (controller_ != null && finger_ != null) {
178 Quaternion local_rotation = finger_.Bone ((Bone.BoneType)(bone_type)).Basis.Rotation (mirror_z_axis_);
179 return controller_.transform.rotation * local_rotation;
180 }
181 if (bones[bone_type]) {
182 return bones[bone_type].rotation;
183 }
184 return Quaternion.identity;
185 }
186
187 /** Returns the length of the finger bone.*/
188 public float GetBoneLength(int bone_type) {
189 return finger_.Bone ((Bone.BoneType)(bone_type)).Length * UnityVectorExtension.INPUT_SCALE;
190 }
191
192 /** Returns the width of the finger bone.*/
193 public float GetBoneWidth(int bone_type) {
194 return finger_.Bone((Bone.BoneType)(bone_type)).Width * UnityVectorExtension.INPUT_SCALE;
195 }
196
197 /**
198 * Returns Mecanim stretch angle in the range (-180, +180]
199 * NOTE: Positive stretch opens the hand.
200 * For the thumb this moves it away from the palm.
201 */
202 public float GetFingerJointStretchMecanim(int joint_type) {
203 // The successive actions of local rotations on a vector yield the global rotation,
204 // so the inverse of the parent rotation appears on the left.
205 Quaternion jointRotation = Quaternion.identity;
206 if (finger_ != null) {
207 jointRotation = Quaternion.Inverse (finger_.Bone ((Bone.BoneType)(joint_type)).Basis.Rotation (mirror_z_axis_))
208 * finger_.Bone ((Bone.BoneType)(joint_type + 1)).Basis.Rotation (mirror_z_axis_);
209 } else if (bones [joint_type] && bones [joint_type + 1]) {
210 jointRotation = Quaternion.Inverse (GetBoneRotation (joint_type)) * GetBoneRotation (joint_type + 1);
211 }
212 // Stretch is a rotation around the X axis of the base bone
213 // Positive stretch opens joints
214 float stretchAngle = -jointRotation.eulerAngles.x;
215 if (stretchAngle <= -180f) {
216 stretchAngle += 360f;
217 }
218 // NOTE: eulerAngles range is [0, 360) so stretchAngle > +180f will not occur.
219 return stretchAngle;
220 }
221
222 /**
223 * Returns Mecanim spread angle, which only applies to joint_type = 0
224 * NOTE: Positive spread is towards thumb for index and middle,
225 * but is in the opposite direction for the ring and pinky.
226 * For the thumb negative spread rotates the thumb in to the palm.
227 * */
228 public float GetFingerJointSpreadMecanim() {
229 // The successive actions of local rotations on a vector yield the global rotation,
230 // so the inverse of the parent rotation appears on the left.
231 Quaternion jointRotation = Quaternion.identity;
232 if (finger_ != null) {
233 jointRotation = Quaternion.Inverse (finger_.Bone ((Bone.BoneType)(0)).Basis.Rotation (mirror_z_axis_))
234 * finger_.Bone ((Bone.BoneType)(1)).Basis.Rotation (mirror_z_axis_);
235 } else if (bones [0] && bones [1]) {
236 jointRotation = Quaternion.Inverse (GetBoneRotation (0)) * GetBoneRotation (1);
237 }
238 // Spread is a rotation around the Y axis of the base bone when joint_type = 0
239 float spreadAngle = 0f;
240 Finger.FingerType fType = fingerType;
241 if (finger_ != null) {
242 fingerType = finger_.Type;
243 }
244
245 if (fType == Finger.FingerType.TYPE_INDEX ||
246 fType == Finger.FingerType.TYPE_MIDDLE) {
247 spreadAngle = jointRotation.eulerAngles.y;
248 if (spreadAngle > 180f) {
249 spreadAngle -= 360f;
250 }
251 // NOTE: eulerAngles range is [0, 360) so spreadAngle <= -180f will not occur.
252 }
253 if (fType == Finger.FingerType.TYPE_THUMB ||
254 fType == Finger.FingerType.TYPE_RING ||
255 fType == Finger.FingerType.TYPE_PINKY) {
256 spreadAngle = -jointRotation.eulerAngles.y;
257 if (spreadAngle <= -180f) {
258 spreadAngle += 360f;
259 }
260 // NOTE: eulerAngles range is [0, 360) so spreadAngle > +180f will not occur.
261 }
262 return spreadAngle;
263 }
264 }