Mercurial > hg > Game > Games
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 } |