|
@@ -5,12 +5,12 @@
|
|
|
* @author bhouston / http://exocortex.com
|
|
|
*/
|
|
|
|
|
|
-THREE.Quaternion = function( x, y, z, w ) {
|
|
|
+THREE.Quaternion = function ( x, y, z, w ) {
|
|
|
|
|
|
- this.x = x || 0;
|
|
|
- this.y = y || 0;
|
|
|
- this.z = z || 0;
|
|
|
- this.w = ( w !== undefined ) ? w : 1;
|
|
|
+ this._x = x || 0;
|
|
|
+ this._y = y || 0;
|
|
|
+ this._z = z || 0;
|
|
|
+ this._w = ( w !== undefined ) ? w : 1;
|
|
|
|
|
|
};
|
|
|
|
|
@@ -18,29 +18,99 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
constructor: THREE.Quaternion,
|
|
|
|
|
|
+ _x: 0,_y: 0, _z: 0, _w: 0,
|
|
|
+
|
|
|
+ _euler: undefined,
|
|
|
+
|
|
|
+ _updateEuler: function ( callback ) {
|
|
|
+
|
|
|
+ if ( this._euler !== undefined ) {
|
|
|
+
|
|
|
+ this._euler.setFromQuaternion( this, undefined, false );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ get x () {
|
|
|
+
|
|
|
+ return this._x;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ set x ( value ) {
|
|
|
+
|
|
|
+ this._x = value;
|
|
|
+ this._updateEuler();
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ get y () {
|
|
|
+
|
|
|
+ return this._y;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ set y ( value ) {
|
|
|
+
|
|
|
+ this._y = value;
|
|
|
+ this._updateEuler();
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ get z () {
|
|
|
+
|
|
|
+ return this._z;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ set z ( value ) {
|
|
|
+
|
|
|
+ this._z = value;
|
|
|
+ this._updateEuler();
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ get w () {
|
|
|
+
|
|
|
+ return this._w;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ set w ( value ) {
|
|
|
+
|
|
|
+ this._w = value;
|
|
|
+ this._updateEuler();
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
set: function ( x, y, z, w ) {
|
|
|
|
|
|
- this.x = x;
|
|
|
- this.y = y;
|
|
|
- this.z = z;
|
|
|
- this.w = w;
|
|
|
+ this._x = x;
|
|
|
+ this._y = y;
|
|
|
+ this._z = z;
|
|
|
+ this._w = w;
|
|
|
+
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- copy: function ( q ) {
|
|
|
+ copy: function ( quaternion ) {
|
|
|
+
|
|
|
+ this._x = quaternion._x;
|
|
|
+ this._y = quaternion._y;
|
|
|
+ this._z = quaternion._z;
|
|
|
+ this._w = quaternion._w;
|
|
|
|
|
|
- this.x = q.x;
|
|
|
- this.y = q.y;
|
|
|
- this.z = q.z;
|
|
|
- this.w = q.w;
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- setFromEuler: function ( euler ) {
|
|
|
+ setFromEuler: function ( euler, update ) {
|
|
|
|
|
|
if ( typeof euler['order'] === undefined ) {
|
|
|
|
|
@@ -51,57 +121,59 @@ THREE.Quaternion.prototype = {
|
|
|
// 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
|
|
|
// content/SpinCalc.m
|
|
|
|
|
|
- var c1 = Math.cos( euler.x / 2 );
|
|
|
- var c2 = Math.cos( euler.y / 2 );
|
|
|
- var c3 = Math.cos( euler.z / 2 );
|
|
|
- var s1 = Math.sin( euler.x / 2 );
|
|
|
- var s2 = Math.sin( euler.y / 2 );
|
|
|
- var s3 = Math.sin( euler.z / 2 );
|
|
|
+ var c1 = Math.cos( euler._x / 2 );
|
|
|
+ var c2 = Math.cos( euler._y / 2 );
|
|
|
+ var c3 = Math.cos( euler._z / 2 );
|
|
|
+ var s1 = Math.sin( euler._x / 2 );
|
|
|
+ var s2 = Math.sin( euler._y / 2 );
|
|
|
+ var s3 = Math.sin( euler._z / 2 );
|
|
|
|
|
|
if ( euler.order === undefined || euler.order === 'XYZ' ) {
|
|
|
|
|
|
- this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
|
- this.y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
|
- this.z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
|
- this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
|
+ this._x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
|
+ this._y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
|
+ this._z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
|
+ this._w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
|
|
|
|
} else if ( euler.order === 'YXZ' ) {
|
|
|
|
|
|
- this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
|
- this.y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
|
- this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
|
- this.w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
|
+ this._x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
|
+ this._y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
|
+ this._z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
|
+ this._w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
|
|
|
|
} else if ( euler.order === 'ZXY' ) {
|
|
|
|
|
|
- this.x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
|
- this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
|
- this.z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
|
- this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
|
+ this._x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
|
+ this._y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
|
+ this._z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
|
+ this._w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
|
|
|
|
} else if ( euler.order === 'ZYX' ) {
|
|
|
|
|
|
- this.x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
|
- this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
|
- this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
|
- this.w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
|
+ this._x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
|
+ this._y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
|
+ this._z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
|
+ this._w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
|
|
|
|
} else if ( euler.order === 'YZX' ) {
|
|
|
|
|
|
- this.x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
|
- this.y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
|
- this.z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
|
- this.w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
|
+ this._x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
|
+ this._y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
|
+ this._z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
|
+ this._w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
|
|
|
|
} else if ( euler.order === 'XZY' ) {
|
|
|
|
|
|
- this.x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
|
- this.y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
|
- this.z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
|
- this.w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
|
+ this._x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
|
+ this._y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
|
+ this._z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
|
+ this._w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ if ( update !== false ) this._updateEuler();
|
|
|
+
|
|
|
return this;
|
|
|
|
|
|
},
|
|
@@ -111,13 +183,14 @@ THREE.Quaternion.prototype = {
|
|
|
// from http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
|
|
|
// axis have to be normalized
|
|
|
|
|
|
- var halfAngle = angle / 2,
|
|
|
- s = Math.sin( halfAngle );
|
|
|
+ var halfAngle = angle / 2, s = Math.sin( halfAngle );
|
|
|
|
|
|
- this.x = axis.x * s;
|
|
|
- this.y = axis.y * s;
|
|
|
- this.z = axis.z * s;
|
|
|
- this.w = Math.cos( halfAngle );
|
|
|
+ this._x = axis.x * s;
|
|
|
+ this._y = axis.y * s;
|
|
|
+ this._z = axis.z * s;
|
|
|
+ this._w = Math.cos( halfAngle );
|
|
|
+
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
@@ -142,40 +215,42 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
s = 0.5 / Math.sqrt( trace + 1.0 );
|
|
|
|
|
|
- this.w = 0.25 / s;
|
|
|
- this.x = ( m32 - m23 ) * s;
|
|
|
- this.y = ( m13 - m31 ) * s;
|
|
|
- this.z = ( m21 - m12 ) * s;
|
|
|
+ this._w = 0.25 / s;
|
|
|
+ this._x = ( m32 - m23 ) * s;
|
|
|
+ this._y = ( m13 - m31 ) * s;
|
|
|
+ this._z = ( m21 - m12 ) * s;
|
|
|
|
|
|
} else if ( m11 > m22 && m11 > m33 ) {
|
|
|
|
|
|
s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
|
|
|
|
|
|
- this.w = (m32 - m23 ) / s;
|
|
|
- this.x = 0.25 * s;
|
|
|
- this.y = (m12 + m21 ) / s;
|
|
|
- this.z = (m13 + m31 ) / s;
|
|
|
+ this._w = (m32 - m23 ) / s;
|
|
|
+ this._x = 0.25 * s;
|
|
|
+ this._y = (m12 + m21 ) / s;
|
|
|
+ this._z = (m13 + m31 ) / s;
|
|
|
|
|
|
} else if ( m22 > m33 ) {
|
|
|
|
|
|
s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
|
|
|
|
|
|
- this.w = (m13 - m31 ) / s;
|
|
|
- this.x = (m12 + m21 ) / s;
|
|
|
- this.y = 0.25 * s;
|
|
|
- this.z = (m23 + m32 ) / s;
|
|
|
+ this._w = (m13 - m31 ) / s;
|
|
|
+ this._x = (m12 + m21 ) / s;
|
|
|
+ this._y = 0.25 * s;
|
|
|
+ this._z = (m23 + m32 ) / s;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
|
|
|
|
|
|
- this.w = ( m21 - m12 ) / s;
|
|
|
- this.x = ( m13 + m31 ) / s;
|
|
|
- this.y = ( m23 + m32 ) / s;
|
|
|
- this.z = 0.25 * s;
|
|
|
+ this._w = ( m21 - m12 ) / s;
|
|
|
+ this._x = ( m13 + m31 ) / s;
|
|
|
+ this._y = ( m23 + m32 ) / s;
|
|
|
+ this._z = 0.25 * s;
|
|
|
|
|
|
}
|
|
|
|
|
|
+ this._updateEuler();
|
|
|
+
|
|
|
return this;
|
|
|
|
|
|
},
|
|
@@ -190,9 +265,11 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
conjugate: function () {
|
|
|
|
|
|
- this.x *= -1;
|
|
|
- this.y *= -1;
|
|
|
- this.z *= -1;
|
|
|
+ this._x *= -1;
|
|
|
+ this._y *= -1;
|
|
|
+ this._z *= -1;
|
|
|
+
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
@@ -200,13 +277,13 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
lengthSq: function () {
|
|
|
|
|
|
- return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
|
|
+ return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
|
|
|
|
|
|
},
|
|
|
|
|
|
length: function () {
|
|
|
|
|
|
- return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
|
|
|
+ return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
|
|
|
|
|
|
},
|
|
|
|
|
@@ -216,19 +293,19 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
if ( l === 0 ) {
|
|
|
|
|
|
- this.x = 0;
|
|
|
- this.y = 0;
|
|
|
- this.z = 0;
|
|
|
- this.w = 1;
|
|
|
+ this._x = 0;
|
|
|
+ this._y = 0;
|
|
|
+ this._z = 0;
|
|
|
+ this._w = 1;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
l = 1 / l;
|
|
|
|
|
|
- this.x = this.x * l;
|
|
|
- this.y = this.y * l;
|
|
|
- this.z = this.z * l;
|
|
|
- this.w = this.w * l;
|
|
|
+ this._x = this._x * l;
|
|
|
+ this._y = this._y * l;
|
|
|
+ this._z = this._z * l;
|
|
|
+ this._w = this._w * l;
|
|
|
|
|
|
}
|
|
|
|
|
@@ -253,13 +330,15 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
|
|
|
|
|
|
- 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;
|
|
|
+ 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;
|
|
|
|
|
|
- this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
|
|
|
- this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
|
|
|
- this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
|
|
|
- this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
|
|
|
+ this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
|
|
|
+ this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
|
|
|
+ this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
|
|
|
+ this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
|
|
|
+
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
@@ -274,18 +353,18 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
slerp: function ( qb, t ) {
|
|
|
|
|
|
- var x = this.x, y = this.y, z = this.z, w = this.w;
|
|
|
+ var x = this._x, y = this._y, z = this._z, w = this._w;
|
|
|
|
|
|
// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
|
|
|
|
|
|
- var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
|
|
|
+ var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
|
|
|
|
|
|
if ( cosHalfTheta < 0 ) {
|
|
|
|
|
|
- this.w = -qb.w;
|
|
|
- this.x = -qb.x;
|
|
|
- this.y = -qb.y;
|
|
|
- this.z = -qb.z;
|
|
|
+ this._w = -qb._w;
|
|
|
+ this._x = -qb._x;
|
|
|
+ this._y = -qb._y;
|
|
|
+ this._z = -qb._z;
|
|
|
|
|
|
cosHalfTheta = -cosHalfTheta;
|
|
|
|
|
@@ -297,10 +376,10 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
if ( cosHalfTheta >= 1.0 ) {
|
|
|
|
|
|
- this.w = w;
|
|
|
- this.x = x;
|
|
|
- this.y = y;
|
|
|
- this.z = z;
|
|
|
+ this._w = w;
|
|
|
+ this._x = x;
|
|
|
+ this._y = y;
|
|
|
+ this._z = z;
|
|
|
|
|
|
return this;
|
|
|
|
|
@@ -311,10 +390,10 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
if ( Math.abs( sinHalfTheta ) < 0.001 ) {
|
|
|
|
|
|
- this.w = 0.5 * ( w + this.w );
|
|
|
- this.x = 0.5 * ( x + this.x );
|
|
|
- this.y = 0.5 * ( y + this.y );
|
|
|
- this.z = 0.5 * ( z + this.z );
|
|
|
+ this._w = 0.5 * ( w + this._w );
|
|
|
+ this._x = 0.5 * ( x + this._x );
|
|
|
+ this._y = 0.5 * ( y + this._y );
|
|
|
+ this._z = 0.5 * ( z + this._z );
|
|
|
|
|
|
return this;
|
|
|
|
|
@@ -323,27 +402,31 @@ THREE.Quaternion.prototype = {
|
|
|
var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
|
|
|
ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
|
|
|
|
|
|
- this.w = ( w * ratioA + this.w * ratioB );
|
|
|
- this.x = ( x * ratioA + this.x * ratioB );
|
|
|
- this.y = ( y * ratioA + this.y * ratioB );
|
|
|
- this.z = ( z * ratioA + this.z * ratioB );
|
|
|
+ this._w = ( w * ratioA + this._w * ratioB );
|
|
|
+ this._x = ( x * ratioA + this._x * ratioB );
|
|
|
+ this._y = ( y * ratioA + this._y * ratioB );
|
|
|
+ this._z = ( z * ratioA + this._z * ratioB );
|
|
|
+
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
|
},
|
|
|
|
|
|
- equals: function ( v ) {
|
|
|
+ equals: function ( quaternion ) {
|
|
|
|
|
|
- return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
|
|
|
+ return ( quaternion._x === this._x ) && ( quaternion._y === this.y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
|
|
|
|
|
|
},
|
|
|
|
|
|
fromArray: function ( array ) {
|
|
|
|
|
|
- this.x = array[ 0 ];
|
|
|
- this.y = array[ 1 ];
|
|
|
- this.z = array[ 2 ];
|
|
|
- this.w = array[ 3 ];
|
|
|
+ this._x = array[ 0 ];
|
|
|
+ this._y = array[ 1 ];
|
|
|
+ this._z = array[ 2 ];
|
|
|
+ this._w = array[ 3 ];
|
|
|
+
|
|
|
+ this._updateEuler();
|
|
|
|
|
|
return this;
|
|
|
|
|
@@ -351,13 +434,13 @@ THREE.Quaternion.prototype = {
|
|
|
|
|
|
toArray: function () {
|
|
|
|
|
|
- return [ this.x, this.y, this.z, this.w ];
|
|
|
+ return [ this._x, this._y, this._z, this._w ];
|
|
|
|
|
|
},
|
|
|
|
|
|
clone: function () {
|
|
|
|
|
|
- return new THREE.Quaternion( this.x, this.y, this.z, this.w );
|
|
|
+ return new THREE.Quaternion( this._x, this._y, this._z, this._w );
|
|
|
|
|
|
}
|
|
|
|