-
Notifications
You must be signed in to change notification settings - Fork 445
/
Copy pathbone.js
165 lines (131 loc) · 3.93 KB
/
bone.js
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
var Pointable = require('./pointable'),
glMatrix = require("gl-matrix")
, vec3 = glMatrix.vec3
, mat3 = glMatrix.mat3
, mat4 = glMatrix.mat4
, _ = require('underscore');
var Bone = module.exports = function(finger, data) {
this.finger = finger;
this._center = null, this._matrix = null;
/**
* An integer code for the name of this bone.
*
* * 0 -- metacarpal
* * 1 -- proximal
* * 2 -- medial
* * 3 -- distal
* * 4 -- arm
*
* @member type
* @type {number}
* @memberof Leap.Bone.prototype
*/
this.type = data.type;
/**
* The position of the previous, or base joint of the bone closer to the wrist.
* @type {vector3}
*/
this.prevJoint = data.prevJoint;
/**
* The position of the next joint, or the end of the bone closer to the finger tip.
* @type {vector3}
*/
this.nextJoint = data.nextJoint;
/**
* The estimated width of the tool in millimeters.
*
* The reported width is the average width of the visible portion of the
* tool from the hand to the tip. If the width isn't known,
* then a value of 0 is returned.
*
* Pointable objects representing fingers do not have a width property.
*
* @member width
* @type {number}
* @memberof Leap.Pointable.prototype
*/
this.width = data.width;
var displacement = new Array(3);
vec3.sub(displacement, data.nextJoint, data.prevJoint);
this.length = vec3.length(displacement);
/**
*
* These fully-specify the orientation of the bone.
* See examples/threejs-bones.html or https://developer.leapmotion.com/gallery/bone-basis-arrows for more info
*
* Three vec3s:
* x (red): The rotation axis of the finger, pointing outwards. (In general, away from the thumb )
* y (green): The "up" vector, orienting the top of the finger
* z (blue): The roll axis of the bone.
*
* Most up vectors will be pointing the same direction, except for the thumb, which is more rightwards.
*
* The thumb has one fewer bones than the fingers, but there are the same number of joints & joint-bases provided
* the first two appear in the same position, but only the second (proximal) rotates.
*
* Normalized.
*
*/
this.basis = data.basis;
};
Bone.prototype.left = function(){
if (this._left) return this._left;
this._left = mat3.determinant(this.basis[0].concat(this.basis[1]).concat(this.basis[2])) < 0;
return this._left;
};
/**
* The Affine transformation matrix describing the orientation of the bone, in global Leap-space.
* It contains a 3x3 rotation matrix (in the "top left"), and center coordinates in the fourth column.
*
* Unlike the basis, the right and left hands have the same coordinate system.
*
*/
Bone.prototype.matrix = function(){
if (this._matrix) return this._matrix;
var b = this.basis,
t = this._matrix = mat4.create();
// open transform mat4 from rotation mat3
t[0] = b[0][0], t[1] = b[0][1], t[2] = b[0][2];
t[4] = b[1][0], t[5] = b[1][1], t[6] = b[1][2];
t[8] = b[2][0], t[9] = b[2][1], t[10] = b[2][2];
t[3] = this.center()[0];
t[7] = this.center()[1];
t[11] = this.center()[2];
if ( this.left() ) {
// flip the basis to be right-handed
t[0] *= -1;
t[1] *= -1;
t[2] *= -1;
}
return this._matrix;
};
/**
* Helper method to linearly interpolate between the two ends of the bone.
*
* when t = 0, the position of prevJoint will be returned
* when t = 1, the position of nextJoint will be returned
*/
Bone.prototype.lerp = function(out, t){
vec3.lerp(out, this.prevJoint, this.nextJoint, t);
};
/**
*
* The center position of the bone
* Returns a vec3 array.
*
*/
Bone.prototype.center = function(){
if (this._center) return this._center;
var center = vec3.create();
this.lerp(center, 0.5);
this._center = center;
return center;
};
// The negative of the z-basis
Bone.prototype.direction = function(){
return [
this.basis[2][0] * -1,
this.basis[2][1] * -1,
this.basis[2][2] * -1
];
};