HandModel.cs
8.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2017. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion and you, your company or other organization. *
******************************************************************************/
using UnityEngine;
using System.Collections;
using Leap;
namespace Leap.Unity{
/**
* The base class for all hand models, both graphics and physics.
*
* This class serves as the interface between the HandController object
* and the concrete hand object containing the graphics and physics of a hand.
*
* Subclasses of HandModel must implement InitHand() and UpdateHand(). The UpdateHand()
* function is called in the Unity Update() phase for graphics HandModel instances;
* and in the Unity FixedUpdate() phase for physics objects. InitHand() is called once,
* when the hand is created and is followed by a call to UpdateHand().
*/
public abstract class HandModel : HandModelBase {
[SerializeField]
private Chirality handedness;
public override Chirality Handedness {
get { return handedness; }
set { handedness = value; }
}
private ModelType handModelType;
public override abstract ModelType HandModelType {
get;
}
/** The number of fingers on a hand.*/
public const int NUM_FINGERS = 5;
/** The model width of the hand in meters. This value is used with the measured value
* of the user's hand to scale the model proportionally.
*/
public float handModelPalmWidth = 0.085f;
/** The array of finger objects for this hand. The array is ordered from thumb (element 0) to pinky (element 4).*/
public FingerModel[] fingers = new FingerModel[NUM_FINGERS];
// Unity references
/** Transform object for the palm object of this hand. */
public Transform palm;
/** Transform object for the forearm object of this hand. */
public Transform forearm;
/** Transform object for the wrist joint of this hand. */
public Transform wristJoint;
/** Transform object for the elbow joint of this hand. */
public Transform elbowJoint;
// Leap references
/** The Leap Hand object this hand model represents. */
protected Hand hand_;
/** Calculates the position of the palm in global coordinates.
* @returns A Vector3 containing the Unity coordinates of the palm position.
*/
public Vector3 GetPalmPosition() {
return hand_.PalmPosition.ToVector3();
}
/** Calculates the rotation of the hand in global coordinates.
* @returns A Quaternion representing the rotation of the hand.
*/
public Quaternion GetPalmRotation() {
if (hand_ != null) {
// The hand Basis vectors are calculated explicitly. This requires using Basis.CalculateRotation()
// instead of Basis.quaternion.
return hand_.Basis.CalculateRotation();
}
if (palm) {
return palm.rotation;
}
return Quaternion.identity;
}
/** Calculates the direction vector of the hand in global coordinates.
* @returns A Vector3 representing the direction of the hand.
*/
public Vector3 GetPalmDirection() {
if (hand_ != null) {
return hand_.Direction.ToVector3();
}
if (palm) {
return palm.forward;
}
return Vector3.forward;
}
/** Calculates the normal vector projecting from the hand in global coordinates.
* @returns A Vector3 representing the vector perpendicular to the palm.
*/
public Vector3 GetPalmNormal() {
if (hand_ != null) {
return hand_.PalmNormal.ToVector3();
}
if (palm) {
return -palm.up;
}
return -Vector3.up;
}
/** Calculates the direction vector of the forearm in global coordinates.
* @returns A Vector3 representing the direction of the forearm (pointing from elbow to wrist).
*/
public Vector3 GetArmDirection() {
if (hand_ != null) {
return hand_.Arm.Direction.ToVector3();
}
if (forearm) {
return forearm.forward;
}
return Vector3.forward;
}
/** Calculates the center of the forearm in global coordinates.
* @returns A Vector3 containing the Unity coordinates of the center of the forearm.
*/
public Vector3 GetArmCenter() {
if (hand_ != null) {
Vector leap_center = 0.5f * (hand_.Arm.WristPosition + hand_.Arm.ElbowPosition);
return leap_center.ToVector3();
}
if (forearm) {
return forearm.position;
}
return Vector3.zero;
}
/** Returns the measured length of the forearm in meters.*/
public float GetArmLength() {
return (hand_.Arm.WristPosition - hand_.Arm.ElbowPosition).Magnitude;
}
/** Returns the measured width of the forearm in meters.*/
public float GetArmWidth() {
return hand_.Arm.Width;
}
/** Calculates the position of the elbow in global coordinates.
* @returns A Vector3 containing the Unity coordinates of the elbow.
*/
public Vector3 GetElbowPosition() {
if (hand_ != null) {
Vector3 local_position = hand_.Arm.ElbowPosition.ToVector3();
return local_position;
}
if (elbowJoint) {
return elbowJoint.position;
}
return Vector3.zero;
}
/** Calculates the position of the wrist in global coordinates.
* @returns A Vector3 containing the Unity coordinates of the wrist.
*/
public Vector3 GetWristPosition() {
if (hand_ != null) {
Vector3 local_position = hand_.Arm.WristPosition.ToVector3();
return local_position;
}
if (wristJoint) {
return wristJoint.position;
}
return Vector3.zero;
}
/** Calculates the rotation of the forearm in global coordinates.
* @returns A Quaternion representing the rotation of the arm.
*/
public Quaternion GetArmRotation() {
if (hand_ != null) {
Quaternion local_rotation = hand_.Arm.Rotation.ToQuaternion();
return local_rotation;
}
if (forearm) {
return forearm.rotation;
}
return Quaternion.identity;
}
/**
* Returns the Leap Hand object represented by this HandModel.
* Note that any physical quantities and directions obtained from the
* Leap Hand object are relative to the Leap Motion coordinate system,
* which uses a right-handed axes and units of millimeters.
*/
public override Hand GetLeapHand() {
return hand_;
}
/**
* Assigns a Leap Hand object to this hand model.
* Note that the Leap Hand objects are recreated every frame. The parent
* HandController calls this method to set or update the underlying hand.
*/
public override void SetLeapHand(Hand hand) {
hand_ = hand;
for (int i = 0; i < fingers.Length; ++i) {
if (fingers[i] != null) {
fingers[i].SetLeapHand(hand_);
}
}
}
/**
* Implement this function to initialise this hand after it is created.
* This function is called by the HandController during the Unity Update() phase when a new hand is detected
* by the Leap Motion device.
*/
public override void InitHand() {
for (int f = 0; f < fingers.Length; ++f) {
if (fingers[f] != null) {
fingers[f].fingerType = (Finger.FingerType)f;
fingers[f].InitFinger();
}
}
}
/**
* Returns the ID associated with the hand in the Leap API.
* This ID is guaranteed to be unique among all hands in a frame,
* and is invariant for the lifetime of the hand model.
*/
public int LeapID() {
if (hand_ != null) {
return hand_.Id;
}
return -1;
}
/**
* Implement this function to update this hand once every game loop.
* For HandModel instances assigned to the HandController graphics hand list, the HandController calls this
* function during the Unity Update() phase. For HandModel instances in the physics hand list, the HandController
* calls this function in the FixedUpdate() phase.
*/
public override abstract void UpdateHand();
}
}