node-red-contrib-leap-motion
Version:
Node-Red nodes for leap motion
164 lines (129 loc) • 3.95 kB
JavaScript
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 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
];
};