1 | var Pointable = require('./pointable'),
|
2 | glMatrix = require("gl-matrix")
|
3 | , vec3 = glMatrix.vec3
|
4 | , mat3 = glMatrix.mat3
|
5 | , mat4 = glMatrix.mat4
|
6 | , _ = require('underscore');
|
7 |
|
8 |
|
9 | var Bone = module.exports = function(finger, data) {
|
10 | this.finger = finger;
|
11 |
|
12 | this._center = null, this._matrix = null;
|
13 |
|
14 | /**
|
15 | * An integer code for the name of this bone.
|
16 | *
|
17 | * * 0 -- metacarpal
|
18 | * * 1 -- proximal
|
19 | * * 2 -- medial
|
20 | * * 3 -- distal
|
21 | * * 4 -- arm
|
22 | *
|
23 | * @member type
|
24 | * @type {number}
|
25 | * @memberof Leap.Bone.prototype
|
26 | */
|
27 | this.type = data.type;
|
28 |
|
29 | /**
|
30 | * The position of the previous, or base joint of the bone closer to the wrist.
|
31 | * @type {vector3}
|
32 | */
|
33 | this.prevJoint = data.prevJoint;
|
34 |
|
35 | /**
|
36 | * The position of the next joint, or the end of the bone closer to the finger tip.
|
37 | * @type {vector3}
|
38 | */
|
39 | this.nextJoint = data.nextJoint;
|
40 |
|
41 | /**
|
42 | * The estimated width of the tool in millimeters.
|
43 | *
|
44 | * The reported width is the average width of the visible portion of the
|
45 | * tool from the hand to the tip. If the width isn't known,
|
46 | * then a value of 0 is returned.
|
47 | *
|
48 | * Pointable objects representing fingers do not have a width property.
|
49 | *
|
50 | * @member width
|
51 | * @type {number}
|
52 | * @memberof Leap.Pointable.prototype
|
53 | */
|
54 | this.width = data.width;
|
55 |
|
56 | var displacement = new Array(3);
|
57 | vec3.sub(displacement, data.nextJoint, data.prevJoint);
|
58 |
|
59 | this.length = vec3.length(displacement);
|
60 |
|
61 |
|
62 | /**
|
63 | *
|
64 | * These fully-specify the orientation of the bone.
|
65 | * See examples/threejs-bones.html for more info
|
66 | * Three vec3s:
|
67 | * x (red): The rotation axis of the finger, pointing outwards. (In general, away from the thumb )
|
68 | * y (green): The "up" vector, orienting the top of the finger
|
69 | * z (blue): The roll axis of the bone.
|
70 | *
|
71 | * Most up vectors will be pointing the same direction, except for the thumb, which is more rightwards.
|
72 | *
|
73 | * The thumb has one fewer bones than the fingers, but there are the same number of joints & joint-bases provided
|
74 | * the first two appear in the same position, but only the second (proximal) rotates.
|
75 | *
|
76 | * Normalized.
|
77 | */
|
78 | this.basis = data.basis;
|
79 | };
|
80 |
|
81 | Bone.prototype.left = function(){
|
82 |
|
83 | if (this._left) return this._left;
|
84 |
|
85 | this._left = mat3.determinant(this.basis[0].concat(this.basis[1]).concat(this.basis[2])) < 0;
|
86 |
|
87 | return this._left;
|
88 |
|
89 | };
|
90 |
|
91 |
|
92 | /**
|
93 | * The Affine transformation matrix describing the orientation of the bone, in global Leap-space.
|
94 | * It contains a 3x3 rotation matrix (in the "top left"), and center coordinates in the fourth column.
|
95 | *
|
96 | * Unlike the basis, the right and left hands have the same coordinate system.
|
97 | *
|
98 | */
|
99 | Bone.prototype.matrix = function(){
|
100 |
|
101 | if (this._matrix) return this._matrix;
|
102 |
|
103 | var b = this.basis,
|
104 | t = this._matrix = mat4.create();
|
105 |
|
106 | // open transform mat4 from rotation mat3
|
107 | t[0] = b[0][0], t[1] = b[0][1], t[2] = b[0][2];
|
108 | t[4] = b[1][0], t[5] = b[1][1], t[6] = b[1][2];
|
109 | t[8] = b[2][0], t[9] = b[2][1], t[10] = b[2][2];
|
110 |
|
111 | t[3] = this.center()[0];
|
112 | t[7] = this.center()[1];
|
113 | t[11] = this.center()[2];
|
114 |
|
115 | if ( this.left() ) {
|
116 | // flip the basis to be right-handed
|
117 | t[0] *= -1;
|
118 | t[1] *= -1;
|
119 | t[2] *= -1;
|
120 | }
|
121 |
|
122 | return this._matrix;
|
123 | };
|
124 |
|
125 | /**
|
126 | * Helper method to linearly interpolate between the two ends of the bone.
|
127 | *
|
128 | * when t = 0, the position of prevJoint will be returned
|
129 | * when t = 1, the position of nextJoint will be returned
|
130 | */
|
131 | Bone.prototype.lerp = function(out, t){
|
132 |
|
133 | vec3.lerp(out, this.prevJoint, this.nextJoint, t);
|
134 |
|
135 | };
|
136 |
|
137 | /**
|
138 | *
|
139 | * The center position of the bone
|
140 | * Returns a vec3 array.
|
141 | *
|
142 | */
|
143 | Bone.prototype.center = function(){
|
144 |
|
145 | if (this._center) return this._center;
|
146 |
|
147 | var center = vec3.create();
|
148 | this.lerp(center, 0.5);
|
149 | this._center = center;
|
150 | return center;
|
151 |
|
152 | };
|
153 |
|
154 | // The negative of the z-basis
|
155 | Bone.prototype.direction = function(){
|
156 |
|
157 | return [
|
158 | this.basis[2][0] * -1,
|
159 | this.basis[2][1] * -1,
|
160 | this.basis[2][2] * -1
|
161 | ];
|
162 |
|
163 | };
|