@hughsk/fulltilt
Version:
Standalone device orientation + device motion normalization and conversion library
213 lines (133 loc) • 3.97 kB
JavaScript
////// FULLTILT.Quaternion //////
FULLTILT.Quaternion = function ( x, y, z, w ) {
var quat, outQuat;
this.set = function ( x, y, z, w ) {
this.x = x || 0;
this.y = y || 0;
this.z = z || 0;
this.w = w || 1;
};
this.copy = function ( quaternion ) {
this.x = quaternion.x;
this.y = quaternion.y;
this.z = quaternion.z;
this.w = quaternion.w;
};
this.setFromEuler = (function () {
var _x, _y, _z;
var _x_2, _y_2, _z_2;
var cX, cY, cZ, sX, sY, sZ;
return function ( euler ) {
euler = euler || {};
_z = ( euler.alpha || 0 ) * degToRad;
_x = ( euler.beta || 0 ) * degToRad;
_y = ( euler.gamma || 0 ) * degToRad;
_z_2 = _z / 2;
_x_2 = _x / 2;
_y_2 = _y / 2;
cX = Math.cos( _x_2 );
cY = Math.cos( _y_2 );
cZ = Math.cos( _z_2 );
sX = Math.sin( _x_2 );
sY = Math.sin( _y_2 );
sZ = Math.sin( _z_2 );
this.set(
sX * cY * cZ - cX * sY * sZ, // x
cX * sY * cZ + sX * cY * sZ, // y
cX * cY * sZ + sX * sY * cZ, // z
cX * cY * cZ - sX * sY * sZ // w
);
this.normalize();
return this;
};
})();
this.setFromRotationMatrix = (function () {
var R;
return function( matrix ) {
R = matrix.elements;
this.set(
0.5 * Math.sqrt( 1 + R[0] - R[4] - R[8] ) * sign( R[7] - R[5] ), // x
0.5 * Math.sqrt( 1 - R[0] + R[4] - R[8] ) * sign( R[2] - R[6] ), // y
0.5 * Math.sqrt( 1 - R[0] - R[4] + R[8] ) * sign( R[3] - R[1] ), // z
0.5 * Math.sqrt( 1 + R[0] + R[4] + R[8] ) // w
);
return this;
};
})();
this.multiply = function ( quaternion ) {
outQuat = FULLTILT.Quaternion.prototype.multiplyQuaternions( this, quaternion );
this.copy( outQuat );
return this;
};
this.rotateX = function ( angle ) {
outQuat = FULLTILT.Quaternion.prototype.rotateByAxisAngle( this, [ 1, 0, 0 ], angle );
this.copy( outQuat );
return this;
};
this.rotateY = function ( angle ) {
outQuat = FULLTILT.Quaternion.prototype.rotateByAxisAngle( this, [ 0, 1, 0 ], angle );
this.copy( outQuat );
return this;
};
this.rotateZ = function ( angle ) {
outQuat = FULLTILT.Quaternion.prototype.rotateByAxisAngle( this, [ 0, 0, 1 ], angle );
this.copy( outQuat );
return this;
};
this.normalize = function () {
return FULLTILT.Quaternion.prototype.normalize( this );
};
// Initialize object values
this.set( x, y, z, w );
};
FULLTILT.Quaternion.prototype = {
constructor: FULLTILT.Quaternion,
multiplyQuaternions: function () {
var multipliedQuat = new FULLTILT.Quaternion();
return function ( a, b ) {
var qax = a.x, qay = a.y, qaz = a.z, qaw = a.w;
var qbx = b.x, qby = b.y, qbz = b.z, qbw = b.w;
multipliedQuat.set(
qax * qbw + qaw * qbx + qay * qbz - qaz * qby, // x
qay * qbw + qaw * qby + qaz * qbx - qax * qbz, // y
qaz * qbw + qaw * qbz + qax * qby - qay * qbx, // z
qaw * qbw - qax * qbx - qay * qby - qaz * qbz // w
);
return multipliedQuat;
};
}(),
normalize: function( q ) {
var len = Math.sqrt( q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w );
if ( len === 0 ) {
q.x = 0;
q.y = 0;
q.z = 0;
q.w = 1;
} else {
len = 1 / len;
q.x *= len;
q.y *= len;
q.z *= len;
q.w *= len;
}
return q;
},
rotateByAxisAngle: function () {
var outputQuaternion = new FULLTILT.Quaternion();
var transformQuaternion = new FULLTILT.Quaternion();
var halfAngle, sA;
return function ( targetQuaternion, axis, angle ) {
halfAngle = ( angle || 0 ) / 2;
sA = Math.sin( halfAngle );
transformQuaternion.set(
( axis[ 0 ] || 0 ) * sA, // x
( axis[ 1 ] || 0 ) * sA, // y
( axis[ 2 ] || 0 ) * sA, // z
Math.cos( halfAngle ) // w
);
// Multiply quaternion by q
outputQuaternion = FULLTILT.Quaternion.prototype.multiplyQuaternions( targetQuaternion, transformQuaternion );
return FULLTILT.Quaternion.prototype.normalize( outputQuaternion );
};
}()
};