5411 lines
96 KiB
JavaScript
5411 lines
96 KiB
JavaScript
(function (global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
|
|
typeof define === 'function' && define.amd ? define(factory) :
|
|
(factory());
|
|
}(this, (function () { 'use strict';
|
|
|
|
/**
|
|
* @author alteredq / http://alteredqualia.com/
|
|
* @author mrdoob / http://mrdoob.com/
|
|
*/
|
|
|
|
var _Math = {
|
|
|
|
DEG2RAD: Math.PI / 180,
|
|
RAD2DEG: 180 / Math.PI,
|
|
|
|
generateUUID: function () {
|
|
|
|
// http://www.broofa.com/Tools/Math.uuid.htm
|
|
|
|
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split( '' );
|
|
var uuid = new Array( 36 );
|
|
var rnd = 0, r;
|
|
|
|
return function generateUUID() {
|
|
|
|
for ( var i = 0; i < 36; i ++ ) {
|
|
|
|
if ( i === 8 || i === 13 || i === 18 || i === 23 ) {
|
|
|
|
uuid[ i ] = '-';
|
|
|
|
} else if ( i === 14 ) {
|
|
|
|
uuid[ i ] = '4';
|
|
|
|
} else {
|
|
|
|
if ( rnd <= 0x02 ) rnd = 0x2000000 + ( Math.random() * 0x1000000 ) | 0;
|
|
r = rnd & 0xf;
|
|
rnd = rnd >> 4;
|
|
uuid[ i ] = chars[ ( i === 19 ) ? ( r & 0x3 ) | 0x8 : r ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return uuid.join( '' );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
clamp: function ( value, min, max ) {
|
|
|
|
return Math.max( min, Math.min( max, value ) );
|
|
|
|
},
|
|
|
|
// compute euclidian modulo of m % n
|
|
// https://en.wikipedia.org/wiki/Modulo_operation
|
|
|
|
euclideanModulo: function ( n, m ) {
|
|
|
|
return ( ( n % m ) + m ) % m;
|
|
|
|
},
|
|
|
|
// Linear mapping from range <a1, a2> to range <b1, b2>
|
|
|
|
mapLinear: function ( x, a1, a2, b1, b2 ) {
|
|
|
|
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
|
|
|
|
},
|
|
|
|
// https://en.wikipedia.org/wiki/Linear_interpolation
|
|
|
|
lerp: function ( x, y, t ) {
|
|
|
|
return ( 1 - t ) * x + t * y;
|
|
|
|
},
|
|
|
|
// http://en.wikipedia.org/wiki/Smoothstep
|
|
|
|
smoothstep: function ( x, min, max ) {
|
|
|
|
if ( x <= min ) return 0;
|
|
if ( x >= max ) return 1;
|
|
|
|
x = ( x - min ) / ( max - min );
|
|
|
|
return x * x * ( 3 - 2 * x );
|
|
|
|
},
|
|
|
|
smootherstep: function ( x, min, max ) {
|
|
|
|
if ( x <= min ) return 0;
|
|
if ( x >= max ) return 1;
|
|
|
|
x = ( x - min ) / ( max - min );
|
|
|
|
return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
|
|
|
|
},
|
|
|
|
// Random integer from <low, high> interval
|
|
|
|
randInt: function ( low, high ) {
|
|
|
|
return low + Math.floor( Math.random() * ( high - low + 1 ) );
|
|
|
|
},
|
|
|
|
// Random float from <low, high> interval
|
|
|
|
randFloat: function ( low, high ) {
|
|
|
|
return low + Math.random() * ( high - low );
|
|
|
|
},
|
|
|
|
// Random float from <-range/2, range/2> interval
|
|
|
|
randFloatSpread: function ( range ) {
|
|
|
|
return range * ( 0.5 - Math.random() );
|
|
|
|
},
|
|
|
|
degToRad: function ( degrees ) {
|
|
|
|
return degrees * _Math.DEG2RAD;
|
|
|
|
},
|
|
|
|
radToDeg: function ( radians ) {
|
|
|
|
return radians * _Math.RAD2DEG;
|
|
|
|
},
|
|
|
|
isPowerOfTwo: function ( value ) {
|
|
|
|
return ( value & ( value - 1 ) ) === 0 && value !== 0;
|
|
|
|
},
|
|
|
|
nearestPowerOfTwo: function ( value ) {
|
|
|
|
return Math.pow( 2, Math.round( Math.log( value ) / Math.LN2 ) );
|
|
|
|
},
|
|
|
|
nextPowerOfTwo: function ( value ) {
|
|
|
|
value --;
|
|
value |= value >> 1;
|
|
value |= value >> 2;
|
|
value |= value >> 4;
|
|
value |= value >> 8;
|
|
value |= value >> 16;
|
|
value ++;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
* @author supereggbert / http://www.paulbrunt.co.uk/
|
|
* @author philogb / http://blog.thejit.org/
|
|
* @author jordi_ros / http://plattsoft.com
|
|
* @author D1plo1d / http://github.com/D1plo1d
|
|
* @author alteredq / http://alteredqualia.com/
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author timknip / http://www.floorplanner.com/
|
|
* @author bhouston / http://clara.io
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
*/
|
|
|
|
function Matrix4() {
|
|
|
|
this.elements = [
|
|
|
|
1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1
|
|
|
|
];
|
|
|
|
if ( arguments.length > 0 ) {
|
|
|
|
console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Object.assign( Matrix4.prototype, {
|
|
|
|
isMatrix4: true,
|
|
|
|
set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
|
|
|
|
var te = this.elements;
|
|
|
|
te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
|
|
te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
|
|
te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
|
|
te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
identity: function () {
|
|
|
|
this.set(
|
|
|
|
1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new Matrix4().fromArray( this.elements );
|
|
|
|
},
|
|
|
|
copy: function ( m ) {
|
|
|
|
var te = this.elements;
|
|
var me = m.elements;
|
|
|
|
te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];
|
|
te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];
|
|
te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];
|
|
te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
copyPosition: function ( m ) {
|
|
|
|
var te = this.elements, me = m.elements;
|
|
|
|
te[ 12 ] = me[ 12 ];
|
|
te[ 13 ] = me[ 13 ];
|
|
te[ 14 ] = me[ 14 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
extractBasis: function ( xAxis, yAxis, zAxis ) {
|
|
|
|
xAxis.setFromMatrixColumn( this, 0 );
|
|
yAxis.setFromMatrixColumn( this, 1 );
|
|
zAxis.setFromMatrixColumn( this, 2 );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeBasis: function ( xAxis, yAxis, zAxis ) {
|
|
|
|
this.set(
|
|
xAxis.x, yAxis.x, zAxis.x, 0,
|
|
xAxis.y, yAxis.y, zAxis.y, 0,
|
|
xAxis.z, yAxis.z, zAxis.z, 0,
|
|
0, 0, 0, 1
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
extractRotation: function () {
|
|
|
|
var v1;
|
|
|
|
return function extractRotation( m ) {
|
|
|
|
if ( v1 === undefined ) v1 = new Vector3();
|
|
|
|
var te = this.elements;
|
|
var me = m.elements;
|
|
|
|
var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length();
|
|
var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length();
|
|
var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length();
|
|
|
|
te[ 0 ] = me[ 0 ] * scaleX;
|
|
te[ 1 ] = me[ 1 ] * scaleX;
|
|
te[ 2 ] = me[ 2 ] * scaleX;
|
|
|
|
te[ 4 ] = me[ 4 ] * scaleY;
|
|
te[ 5 ] = me[ 5 ] * scaleY;
|
|
te[ 6 ] = me[ 6 ] * scaleY;
|
|
|
|
te[ 8 ] = me[ 8 ] * scaleZ;
|
|
te[ 9 ] = me[ 9 ] * scaleZ;
|
|
te[ 10 ] = me[ 10 ] * scaleZ;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
makeRotationFromEuler: function ( euler ) {
|
|
|
|
if ( ( euler && euler.isEuler ) === false ) {
|
|
|
|
console.error( 'THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );
|
|
|
|
}
|
|
|
|
var te = this.elements;
|
|
|
|
var x = euler.x, y = euler.y, z = euler.z;
|
|
var a = Math.cos( x ), b = Math.sin( x );
|
|
var c = Math.cos( y ), d = Math.sin( y );
|
|
var e = Math.cos( z ), f = Math.sin( z );
|
|
|
|
if ( euler.order === 'XYZ' ) {
|
|
|
|
var ae = a * e, af = a * f, be = b * e, bf = b * f;
|
|
|
|
te[ 0 ] = c * e;
|
|
te[ 4 ] = - c * f;
|
|
te[ 8 ] = d;
|
|
|
|
te[ 1 ] = af + be * d;
|
|
te[ 5 ] = ae - bf * d;
|
|
te[ 9 ] = - b * c;
|
|
|
|
te[ 2 ] = bf - ae * d;
|
|
te[ 6 ] = be + af * d;
|
|
te[ 10 ] = a * c;
|
|
|
|
} else if ( euler.order === 'YXZ' ) {
|
|
|
|
var ce = c * e, cf = c * f, de = d * e, df = d * f;
|
|
|
|
te[ 0 ] = ce + df * b;
|
|
te[ 4 ] = de * b - cf;
|
|
te[ 8 ] = a * d;
|
|
|
|
te[ 1 ] = a * f;
|
|
te[ 5 ] = a * e;
|
|
te[ 9 ] = - b;
|
|
|
|
te[ 2 ] = cf * b - de;
|
|
te[ 6 ] = df + ce * b;
|
|
te[ 10 ] = a * c;
|
|
|
|
} else if ( euler.order === 'ZXY' ) {
|
|
|
|
var ce = c * e, cf = c * f, de = d * e, df = d * f;
|
|
|
|
te[ 0 ] = ce - df * b;
|
|
te[ 4 ] = - a * f;
|
|
te[ 8 ] = de + cf * b;
|
|
|
|
te[ 1 ] = cf + de * b;
|
|
te[ 5 ] = a * e;
|
|
te[ 9 ] = df - ce * b;
|
|
|
|
te[ 2 ] = - a * d;
|
|
te[ 6 ] = b;
|
|
te[ 10 ] = a * c;
|
|
|
|
} else if ( euler.order === 'ZYX' ) {
|
|
|
|
var ae = a * e, af = a * f, be = b * e, bf = b * f;
|
|
|
|
te[ 0 ] = c * e;
|
|
te[ 4 ] = be * d - af;
|
|
te[ 8 ] = ae * d + bf;
|
|
|
|
te[ 1 ] = c * f;
|
|
te[ 5 ] = bf * d + ae;
|
|
te[ 9 ] = af * d - be;
|
|
|
|
te[ 2 ] = - d;
|
|
te[ 6 ] = b * c;
|
|
te[ 10 ] = a * c;
|
|
|
|
} else if ( euler.order === 'YZX' ) {
|
|
|
|
var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
|
|
|
|
te[ 0 ] = c * e;
|
|
te[ 4 ] = bd - ac * f;
|
|
te[ 8 ] = bc * f + ad;
|
|
|
|
te[ 1 ] = f;
|
|
te[ 5 ] = a * e;
|
|
te[ 9 ] = - b * e;
|
|
|
|
te[ 2 ] = - d * e;
|
|
te[ 6 ] = ad * f + bc;
|
|
te[ 10 ] = ac - bd * f;
|
|
|
|
} else if ( euler.order === 'XZY' ) {
|
|
|
|
var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
|
|
|
|
te[ 0 ] = c * e;
|
|
te[ 4 ] = - f;
|
|
te[ 8 ] = d * e;
|
|
|
|
te[ 1 ] = ac * f + bd;
|
|
te[ 5 ] = a * e;
|
|
te[ 9 ] = ad * f - bc;
|
|
|
|
te[ 2 ] = bc * f - ad;
|
|
te[ 6 ] = b * e;
|
|
te[ 10 ] = bd * f + ac;
|
|
|
|
}
|
|
|
|
// last column
|
|
te[ 3 ] = 0;
|
|
te[ 7 ] = 0;
|
|
te[ 11 ] = 0;
|
|
|
|
// bottom row
|
|
te[ 12 ] = 0;
|
|
te[ 13 ] = 0;
|
|
te[ 14 ] = 0;
|
|
te[ 15 ] = 1;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeRotationFromQuaternion: function ( q ) {
|
|
|
|
var te = this.elements;
|
|
|
|
var x = q._x, y = q._y, z = q._z, w = q._w;
|
|
var x2 = x + x, y2 = y + y, z2 = z + z;
|
|
var xx = x * x2, xy = x * y2, xz = x * z2;
|
|
var yy = y * y2, yz = y * z2, zz = z * z2;
|
|
var wx = w * x2, wy = w * y2, wz = w * z2;
|
|
|
|
te[ 0 ] = 1 - ( yy + zz );
|
|
te[ 4 ] = xy - wz;
|
|
te[ 8 ] = xz + wy;
|
|
|
|
te[ 1 ] = xy + wz;
|
|
te[ 5 ] = 1 - ( xx + zz );
|
|
te[ 9 ] = yz - wx;
|
|
|
|
te[ 2 ] = xz - wy;
|
|
te[ 6 ] = yz + wx;
|
|
te[ 10 ] = 1 - ( xx + yy );
|
|
|
|
// last column
|
|
te[ 3 ] = 0;
|
|
te[ 7 ] = 0;
|
|
te[ 11 ] = 0;
|
|
|
|
// bottom row
|
|
te[ 12 ] = 0;
|
|
te[ 13 ] = 0;
|
|
te[ 14 ] = 0;
|
|
te[ 15 ] = 1;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
lookAt: function () {
|
|
|
|
var x, y, z;
|
|
|
|
return function lookAt( eye, target, up ) {
|
|
|
|
if ( x === undefined ) {
|
|
|
|
x = new Vector3();
|
|
y = new Vector3();
|
|
z = new Vector3();
|
|
|
|
}
|
|
|
|
var te = this.elements;
|
|
|
|
z.subVectors( eye, target );
|
|
|
|
if ( z.lengthSq() === 0 ) {
|
|
|
|
// eye and target are in the same position
|
|
|
|
z.z = 1;
|
|
|
|
}
|
|
|
|
z.normalize();
|
|
x.crossVectors( up, z );
|
|
|
|
if ( x.lengthSq() === 0 ) {
|
|
|
|
// eye and target are in the same vertical
|
|
|
|
z.z += 0.0001;
|
|
x.crossVectors( up, z );
|
|
|
|
}
|
|
|
|
x.normalize();
|
|
y.crossVectors( z, x );
|
|
|
|
te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
|
|
te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
|
|
te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
multiply: function ( m, n ) {
|
|
|
|
if ( n !== undefined ) {
|
|
|
|
console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );
|
|
return this.multiplyMatrices( m, n );
|
|
|
|
}
|
|
|
|
return this.multiplyMatrices( this, m );
|
|
|
|
},
|
|
|
|
premultiply: function ( m ) {
|
|
|
|
return this.multiplyMatrices( m, this );
|
|
|
|
},
|
|
|
|
multiplyMatrices: function ( a, b ) {
|
|
|
|
var ae = a.elements;
|
|
var be = b.elements;
|
|
var te = this.elements;
|
|
|
|
var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
|
|
var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
|
|
var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
|
|
var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];
|
|
|
|
var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
|
|
var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
|
|
var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
|
|
var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];
|
|
|
|
te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
|
|
te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
|
|
te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
|
|
te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
|
|
|
|
te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
|
|
te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
|
|
te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
|
|
te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
|
|
|
|
te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
|
|
te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
|
|
te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
|
|
te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
|
|
|
|
te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
|
|
te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
|
|
te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
|
|
te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyScalar: function ( s ) {
|
|
|
|
var te = this.elements;
|
|
|
|
te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;
|
|
te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;
|
|
te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;
|
|
te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
determinant: function () {
|
|
|
|
var te = this.elements;
|
|
|
|
var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];
|
|
var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];
|
|
var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];
|
|
var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];
|
|
|
|
//TODO: make this more efficient
|
|
//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
|
|
|
|
return (
|
|
n41 * (
|
|
+ n14 * n23 * n32
|
|
- n13 * n24 * n32
|
|
- n14 * n22 * n33
|
|
+ n12 * n24 * n33
|
|
+ n13 * n22 * n34
|
|
- n12 * n23 * n34
|
|
) +
|
|
n42 * (
|
|
+ n11 * n23 * n34
|
|
- n11 * n24 * n33
|
|
+ n14 * n21 * n33
|
|
- n13 * n21 * n34
|
|
+ n13 * n24 * n31
|
|
- n14 * n23 * n31
|
|
) +
|
|
n43 * (
|
|
+ n11 * n24 * n32
|
|
- n11 * n22 * n34
|
|
- n14 * n21 * n32
|
|
+ n12 * n21 * n34
|
|
+ n14 * n22 * n31
|
|
- n12 * n24 * n31
|
|
) +
|
|
n44 * (
|
|
- n13 * n22 * n31
|
|
- n11 * n23 * n32
|
|
+ n11 * n22 * n33
|
|
+ n13 * n21 * n32
|
|
- n12 * n21 * n33
|
|
+ n12 * n23 * n31
|
|
)
|
|
|
|
);
|
|
|
|
},
|
|
|
|
transpose: function () {
|
|
|
|
var te = this.elements;
|
|
var tmp;
|
|
|
|
tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;
|
|
tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;
|
|
tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;
|
|
|
|
tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;
|
|
tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;
|
|
tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setPosition: function ( v ) {
|
|
|
|
var te = this.elements;
|
|
|
|
te[ 12 ] = v.x;
|
|
te[ 13 ] = v.y;
|
|
te[ 14 ] = v.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getInverse: function ( m, throwOnDegenerate ) {
|
|
|
|
// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
|
|
var te = this.elements,
|
|
me = m.elements,
|
|
|
|
n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],
|
|
n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],
|
|
n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],
|
|
n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],
|
|
|
|
t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
|
|
t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
|
|
t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
|
|
t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
|
|
|
|
var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
|
|
|
|
if ( det === 0 ) {
|
|
|
|
var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0";
|
|
|
|
if ( throwOnDegenerate === true ) {
|
|
|
|
throw new Error( msg );
|
|
|
|
} else {
|
|
|
|
console.warn( msg );
|
|
|
|
}
|
|
|
|
return this.identity();
|
|
|
|
}
|
|
|
|
var detInv = 1 / det;
|
|
|
|
te[ 0 ] = t11 * detInv;
|
|
te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
|
|
te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
|
|
te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
|
|
|
|
te[ 4 ] = t12 * detInv;
|
|
te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
|
|
te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
|
|
te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
|
|
|
|
te[ 8 ] = t13 * detInv;
|
|
te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
|
|
te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
|
|
te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
|
|
|
|
te[ 12 ] = t14 * detInv;
|
|
te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
|
|
te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
|
|
te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
scale: function ( v ) {
|
|
|
|
var te = this.elements;
|
|
var x = v.x, y = v.y, z = v.z;
|
|
|
|
te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;
|
|
te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;
|
|
te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;
|
|
te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getMaxScaleOnAxis: function () {
|
|
|
|
var te = this.elements;
|
|
|
|
var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];
|
|
var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];
|
|
var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];
|
|
|
|
return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );
|
|
|
|
},
|
|
|
|
makeTranslation: function ( x, y, z ) {
|
|
|
|
this.set(
|
|
|
|
1, 0, 0, x,
|
|
0, 1, 0, y,
|
|
0, 0, 1, z,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeRotationX: function ( theta ) {
|
|
|
|
var c = Math.cos( theta ), s = Math.sin( theta );
|
|
|
|
this.set(
|
|
|
|
1, 0, 0, 0,
|
|
0, c, - s, 0,
|
|
0, s, c, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeRotationY: function ( theta ) {
|
|
|
|
var c = Math.cos( theta ), s = Math.sin( theta );
|
|
|
|
this.set(
|
|
|
|
c, 0, s, 0,
|
|
0, 1, 0, 0,
|
|
- s, 0, c, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeRotationZ: function ( theta ) {
|
|
|
|
var c = Math.cos( theta ), s = Math.sin( theta );
|
|
|
|
this.set(
|
|
|
|
c, - s, 0, 0,
|
|
s, c, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeRotationAxis: function ( axis, angle ) {
|
|
|
|
// Based on http://www.gamedev.net/reference/articles/article1199.asp
|
|
|
|
var c = Math.cos( angle );
|
|
var s = Math.sin( angle );
|
|
var t = 1 - c;
|
|
var x = axis.x, y = axis.y, z = axis.z;
|
|
var tx = t * x, ty = t * y;
|
|
|
|
this.set(
|
|
|
|
tx * x + c, tx * y - s * z, tx * z + s * y, 0,
|
|
tx * y + s * z, ty * y + c, ty * z - s * x, 0,
|
|
tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeScale: function ( x, y, z ) {
|
|
|
|
this.set(
|
|
|
|
x, 0, 0, 0,
|
|
0, y, 0, 0,
|
|
0, 0, z, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeShear: function ( x, y, z ) {
|
|
|
|
this.set(
|
|
|
|
1, y, z, 0,
|
|
x, 1, z, 0,
|
|
x, y, 1, 0,
|
|
0, 0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
compose: function ( position, quaternion, scale ) {
|
|
|
|
this.makeRotationFromQuaternion( quaternion );
|
|
this.scale( scale );
|
|
this.setPosition( position );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
decompose: function () {
|
|
|
|
var vector, matrix;
|
|
|
|
return function decompose( position, quaternion, scale ) {
|
|
|
|
if ( vector === undefined ) {
|
|
|
|
vector = new Vector3();
|
|
matrix = new Matrix4();
|
|
|
|
}
|
|
|
|
var te = this.elements;
|
|
|
|
var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();
|
|
var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();
|
|
var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();
|
|
|
|
// if determine is negative, we need to invert one scale
|
|
var det = this.determinant();
|
|
if ( det < 0 ) sx = - sx;
|
|
|
|
position.x = te[ 12 ];
|
|
position.y = te[ 13 ];
|
|
position.z = te[ 14 ];
|
|
|
|
// scale the rotation part
|
|
matrix.copy( this );
|
|
|
|
var invSX = 1 / sx;
|
|
var invSY = 1 / sy;
|
|
var invSZ = 1 / sz;
|
|
|
|
matrix.elements[ 0 ] *= invSX;
|
|
matrix.elements[ 1 ] *= invSX;
|
|
matrix.elements[ 2 ] *= invSX;
|
|
|
|
matrix.elements[ 4 ] *= invSY;
|
|
matrix.elements[ 5 ] *= invSY;
|
|
matrix.elements[ 6 ] *= invSY;
|
|
|
|
matrix.elements[ 8 ] *= invSZ;
|
|
matrix.elements[ 9 ] *= invSZ;
|
|
matrix.elements[ 10 ] *= invSZ;
|
|
|
|
quaternion.setFromRotationMatrix( matrix );
|
|
|
|
scale.x = sx;
|
|
scale.y = sy;
|
|
scale.z = sz;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
makePerspective: function ( left, right, top, bottom, near, far ) {
|
|
|
|
if ( far === undefined ) {
|
|
|
|
console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );
|
|
|
|
}
|
|
|
|
var te = this.elements;
|
|
var x = 2 * near / ( right - left );
|
|
var y = 2 * near / ( top - bottom );
|
|
|
|
var a = ( right + left ) / ( right - left );
|
|
var b = ( top + bottom ) / ( top - bottom );
|
|
var c = - ( far + near ) / ( far - near );
|
|
var d = - 2 * far * near / ( far - near );
|
|
|
|
te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
|
|
te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
|
|
te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
|
|
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
makeOrthographic: function ( left, right, top, bottom, near, far ) {
|
|
|
|
var te = this.elements;
|
|
var w = 1.0 / ( right - left );
|
|
var h = 1.0 / ( top - bottom );
|
|
var p = 1.0 / ( far - near );
|
|
|
|
var x = ( right + left ) * w;
|
|
var y = ( top + bottom ) * h;
|
|
var z = ( far + near ) * p;
|
|
|
|
te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x;
|
|
te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y;
|
|
te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z;
|
|
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
equals: function ( matrix ) {
|
|
|
|
var te = this.elements;
|
|
var me = matrix.elements;
|
|
|
|
for ( var i = 0; i < 16; i ++ ) {
|
|
|
|
if ( te[ i ] !== me[ i ] ) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
for ( var i = 0; i < 16; i ++ ) {
|
|
|
|
this.elements[ i ] = array[ i + offset ];
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
var te = this.elements;
|
|
|
|
array[ offset ] = te[ 0 ];
|
|
array[ offset + 1 ] = te[ 1 ];
|
|
array[ offset + 2 ] = te[ 2 ];
|
|
array[ offset + 3 ] = te[ 3 ];
|
|
|
|
array[ offset + 4 ] = te[ 4 ];
|
|
array[ offset + 5 ] = te[ 5 ];
|
|
array[ offset + 6 ] = te[ 6 ];
|
|
array[ offset + 7 ] = te[ 7 ];
|
|
|
|
array[ offset + 8 ] = te[ 8 ];
|
|
array[ offset + 9 ] = te[ 9 ];
|
|
array[ offset + 10 ] = te[ 10 ];
|
|
array[ offset + 11 ] = te[ 11 ];
|
|
|
|
array[ offset + 12 ] = te[ 12 ];
|
|
array[ offset + 13 ] = te[ 13 ];
|
|
array[ offset + 14 ] = te[ 14 ];
|
|
array[ offset + 15 ] = te[ 15 ];
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
* @author *kile / http://kile.stravaganza.org/
|
|
* @author philogb / http://blog.thejit.org/
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author egraether / http://egraether.com/
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
*/
|
|
|
|
function Vector3( x, y, z ) {
|
|
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
|
|
}
|
|
|
|
Object.assign( Vector3.prototype, {
|
|
|
|
isVector3: true,
|
|
|
|
set: function ( x, y, z ) {
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setScalar: function ( scalar ) {
|
|
|
|
this.x = scalar;
|
|
this.y = scalar;
|
|
this.z = scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setX: function ( x ) {
|
|
|
|
this.x = x;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setY: function ( y ) {
|
|
|
|
this.y = y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setZ: function ( z ) {
|
|
|
|
this.z = z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setComponent: function ( index, value ) {
|
|
|
|
switch ( index ) {
|
|
|
|
case 0: this.x = value; break;
|
|
case 1: this.y = value; break;
|
|
case 2: this.z = value; break;
|
|
default: throw new Error( 'index is out of range: ' + index );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getComponent: function ( index ) {
|
|
|
|
switch ( index ) {
|
|
|
|
case 0: return this.x;
|
|
case 1: return this.y;
|
|
case 2: return this.z;
|
|
default: throw new Error( 'index is out of range: ' + index );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor( this.x, this.y, this.z );
|
|
|
|
},
|
|
|
|
copy: function ( v ) {
|
|
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = v.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
add: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
|
|
return this.addVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScalar: function ( s ) {
|
|
|
|
this.x += s;
|
|
this.y += s;
|
|
this.z += s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addVectors: function ( a, b ) {
|
|
|
|
this.x = a.x + b.x;
|
|
this.y = a.y + b.y;
|
|
this.z = a.z + b.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScaledVector: function ( v, s ) {
|
|
|
|
this.x += v.x * s;
|
|
this.y += v.y * s;
|
|
this.z += v.z * s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
sub: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
|
|
return this.subVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
subScalar: function ( s ) {
|
|
|
|
this.x -= s;
|
|
this.y -= s;
|
|
this.z -= s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
subVectors: function ( a, b ) {
|
|
|
|
this.x = a.x - b.x;
|
|
this.y = a.y - b.y;
|
|
this.z = a.z - b.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiply: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );
|
|
return this.multiplyVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
this.z *= v.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyScalar: function ( scalar ) {
|
|
|
|
this.x *= scalar;
|
|
this.y *= scalar;
|
|
this.z *= scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyVectors: function ( a, b ) {
|
|
|
|
this.x = a.x * b.x;
|
|
this.y = a.y * b.y;
|
|
this.z = a.z * b.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
applyEuler: function () {
|
|
|
|
var quaternion;
|
|
|
|
return function applyEuler( euler ) {
|
|
|
|
if ( ( euler && euler.isEuler ) === false ) {
|
|
|
|
console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );
|
|
|
|
}
|
|
|
|
if ( quaternion === undefined ) quaternion = new Quaternion();
|
|
|
|
return this.applyQuaternion( quaternion.setFromEuler( euler ) );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
applyAxisAngle: function () {
|
|
|
|
var quaternion;
|
|
|
|
return function applyAxisAngle( axis, angle ) {
|
|
|
|
if ( quaternion === undefined ) quaternion = new Quaternion();
|
|
|
|
return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
applyMatrix3: function ( m ) {
|
|
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var e = m.elements;
|
|
|
|
this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;
|
|
this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;
|
|
this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
applyMatrix4: function ( m ) {
|
|
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var e = m.elements;
|
|
|
|
this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ];
|
|
this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ];
|
|
this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ];
|
|
var w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ];
|
|
|
|
return this.divideScalar( w );
|
|
|
|
},
|
|
|
|
applyQuaternion: function ( q ) {
|
|
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var qx = q.x, qy = q.y, qz = q.z, qw = q.w;
|
|
|
|
// calculate quat * vector
|
|
|
|
var ix = qw * x + qy * z - qz * y;
|
|
var iy = qw * y + qz * x - qx * z;
|
|
var iz = qw * z + qx * y - qy * x;
|
|
var iw = - qx * x - qy * y - qz * z;
|
|
|
|
// calculate result * inverse quat
|
|
|
|
this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;
|
|
this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;
|
|
this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
transformDirection: function ( m ) {
|
|
|
|
// input: THREE.Matrix4 affine matrix
|
|
// vector interpreted as a direction
|
|
|
|
var x = this.x, y = this.y, z = this.z;
|
|
var e = m.elements;
|
|
|
|
this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;
|
|
this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;
|
|
this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
|
|
|
|
return this.normalize();
|
|
|
|
},
|
|
|
|
divide: function ( v ) {
|
|
|
|
this.x /= v.x;
|
|
this.y /= v.y;
|
|
this.z /= v.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
divideScalar: function ( scalar ) {
|
|
|
|
return this.multiplyScalar( 1 / scalar );
|
|
|
|
},
|
|
|
|
min: function ( v ) {
|
|
|
|
this.x = Math.min( this.x, v.x );
|
|
this.y = Math.min( this.y, v.y );
|
|
this.z = Math.min( this.z, v.z );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
max: function ( v ) {
|
|
|
|
this.x = Math.max( this.x, v.x );
|
|
this.y = Math.max( this.y, v.y );
|
|
this.z = Math.max( this.z, v.z );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clamp: function ( min, max ) {
|
|
|
|
// This function assumes min < max, if this assumption isn't true it will not operate correctly
|
|
|
|
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
|
|
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
|
|
this.z = Math.max( min.z, Math.min( max.z, this.z ) );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clampScalar: function () {
|
|
|
|
var min, max;
|
|
|
|
return function clampScalar( minVal, maxVal ) {
|
|
|
|
if ( min === undefined ) {
|
|
|
|
min = new Vector3();
|
|
max = new Vector3();
|
|
|
|
}
|
|
|
|
min.set( minVal, minVal, minVal );
|
|
max.set( maxVal, maxVal, maxVal );
|
|
|
|
return this.clamp( min, max );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
clampLength: function ( min, max ) {
|
|
|
|
var length = this.length();
|
|
|
|
return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
|
|
|
|
},
|
|
|
|
floor: function () {
|
|
|
|
this.x = Math.floor( this.x );
|
|
this.y = Math.floor( this.y );
|
|
this.z = Math.floor( this.z );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
ceil: function () {
|
|
|
|
this.x = Math.ceil( this.x );
|
|
this.y = Math.ceil( this.y );
|
|
this.z = Math.ceil( this.z );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
round: function () {
|
|
|
|
this.x = Math.round( this.x );
|
|
this.y = Math.round( this.y );
|
|
this.z = Math.round( this.z );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
roundToZero: function () {
|
|
|
|
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
|
|
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
|
|
this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
negate: function () {
|
|
|
|
this.x = - this.x;
|
|
this.y = - this.y;
|
|
this.z = - this.z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
dot: function ( v ) {
|
|
|
|
return this.x * v.x + this.y * v.y + this.z * v.z;
|
|
|
|
},
|
|
|
|
// TODO lengthSquared?
|
|
|
|
lengthSq: function () {
|
|
|
|
return this.x * this.x + this.y * this.y + this.z * this.z;
|
|
|
|
},
|
|
|
|
length: function () {
|
|
|
|
return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );
|
|
|
|
},
|
|
|
|
lengthManhattan: function () {
|
|
|
|
return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
|
|
|
|
},
|
|
|
|
normalize: function () {
|
|
|
|
return this.divideScalar( this.length() );
|
|
|
|
},
|
|
|
|
setLength: function ( length ) {
|
|
|
|
return this.multiplyScalar( length / this.length() );
|
|
|
|
},
|
|
|
|
lerp: function ( v, alpha ) {
|
|
|
|
this.x += ( v.x - this.x ) * alpha;
|
|
this.y += ( v.y - this.y ) * alpha;
|
|
this.z += ( v.z - this.z ) * alpha;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
lerpVectors: function ( v1, v2, alpha ) {
|
|
|
|
return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
|
|
|
|
},
|
|
|
|
cross: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );
|
|
return this.crossVectors( v, w );
|
|
|
|
}
|
|
|
|
var x = this.x, y = this.y, z = this.z;
|
|
|
|
this.x = y * v.z - z * v.y;
|
|
this.y = z * v.x - x * v.z;
|
|
this.z = x * v.y - y * v.x;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
crossVectors: function ( a, b ) {
|
|
|
|
var ax = a.x, ay = a.y, az = a.z;
|
|
var bx = b.x, by = b.y, bz = b.z;
|
|
|
|
this.x = ay * bz - az * by;
|
|
this.y = az * bx - ax * bz;
|
|
this.z = ax * by - ay * bx;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
projectOnVector: function ( vector ) {
|
|
|
|
var scalar = vector.dot( this ) / vector.lengthSq();
|
|
|
|
return this.copy( vector ).multiplyScalar( scalar );
|
|
|
|
},
|
|
|
|
projectOnPlane: function () {
|
|
|
|
var v1;
|
|
|
|
return function projectOnPlane( planeNormal ) {
|
|
|
|
if ( v1 === undefined ) v1 = new Vector3();
|
|
|
|
v1.copy( this ).projectOnVector( planeNormal );
|
|
|
|
return this.sub( v1 );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
reflect: function () {
|
|
|
|
// reflect incident vector off plane orthogonal to normal
|
|
// normal is assumed to have unit length
|
|
|
|
var v1;
|
|
|
|
return function reflect( normal ) {
|
|
|
|
if ( v1 === undefined ) v1 = new Vector3();
|
|
|
|
return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
angleTo: function ( v ) {
|
|
|
|
var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) );
|
|
|
|
// clamp, to handle numerical problems
|
|
|
|
return Math.acos( _Math.clamp( theta, - 1, 1 ) );
|
|
|
|
},
|
|
|
|
distanceTo: function ( v ) {
|
|
|
|
return Math.sqrt( this.distanceToSquared( v ) );
|
|
|
|
},
|
|
|
|
distanceToSquared: function ( v ) {
|
|
|
|
var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;
|
|
|
|
return dx * dx + dy * dy + dz * dz;
|
|
|
|
},
|
|
|
|
distanceToManhattan: function ( v ) {
|
|
|
|
return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );
|
|
|
|
},
|
|
|
|
setFromMatrixPosition: function ( m ) {
|
|
|
|
return this.setFromMatrixColumn( m, 3 );
|
|
|
|
},
|
|
|
|
setFromMatrixScale: function ( m ) {
|
|
|
|
var sx = this.setFromMatrixColumn( m, 0 ).length();
|
|
var sy = this.setFromMatrixColumn( m, 1 ).length();
|
|
var sz = this.setFromMatrixColumn( m, 2 ).length();
|
|
|
|
this.x = sx;
|
|
this.y = sy;
|
|
this.z = sz;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromMatrixColumn: function ( m, index ) {
|
|
|
|
|
|
return this.fromArray( m.elements, index * 4 );
|
|
|
|
},
|
|
|
|
equals: function ( v ) {
|
|
|
|
return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
this.x = array[ offset ];
|
|
this.y = array[ offset + 1 ];
|
|
this.z = array[ offset + 2 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
array[ offset ] = this.x;
|
|
array[ offset + 1 ] = this.y;
|
|
array[ offset + 2 ] = this.z;
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author alteredq / http://alteredqualia.com/
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
* @author bhouston / http://clara.io
|
|
*/
|
|
|
|
function Quaternion( x, y, z, w ) {
|
|
|
|
this._x = x || 0;
|
|
this._y = y || 0;
|
|
this._z = z || 0;
|
|
this._w = ( w !== undefined ) ? w : 1;
|
|
|
|
}
|
|
|
|
Object.assign( Quaternion, {
|
|
|
|
slerp: function ( qa, qb, qm, t ) {
|
|
|
|
return qm.copy( qa ).slerp( qb, t );
|
|
|
|
},
|
|
|
|
slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {
|
|
|
|
// fuzz-free, array-based Quaternion SLERP operation
|
|
|
|
var x0 = src0[ srcOffset0 + 0 ],
|
|
y0 = src0[ srcOffset0 + 1 ],
|
|
z0 = src0[ srcOffset0 + 2 ],
|
|
w0 = src0[ srcOffset0 + 3 ],
|
|
|
|
x1 = src1[ srcOffset1 + 0 ],
|
|
y1 = src1[ srcOffset1 + 1 ],
|
|
z1 = src1[ srcOffset1 + 2 ],
|
|
w1 = src1[ srcOffset1 + 3 ];
|
|
|
|
if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
|
|
|
|
var s = 1 - t,
|
|
|
|
cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
|
|
|
|
dir = ( cos >= 0 ? 1 : - 1 ),
|
|
sqrSin = 1 - cos * cos;
|
|
|
|
// Skip the Slerp for tiny steps to avoid numeric problems:
|
|
if ( sqrSin > Number.EPSILON ) {
|
|
|
|
var sin = Math.sqrt( sqrSin ),
|
|
len = Math.atan2( sin, cos * dir );
|
|
|
|
s = Math.sin( s * len ) / sin;
|
|
t = Math.sin( t * len ) / sin;
|
|
|
|
}
|
|
|
|
var tDir = t * dir;
|
|
|
|
x0 = x0 * s + x1 * tDir;
|
|
y0 = y0 * s + y1 * tDir;
|
|
z0 = z0 * s + z1 * tDir;
|
|
w0 = w0 * s + w1 * tDir;
|
|
|
|
// Normalize in case we just did a lerp:
|
|
if ( s === 1 - t ) {
|
|
|
|
var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
|
|
|
|
x0 *= f;
|
|
y0 *= f;
|
|
z0 *= f;
|
|
w0 *= f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dst[ dstOffset ] = x0;
|
|
dst[ dstOffset + 1 ] = y0;
|
|
dst[ dstOffset + 2 ] = z0;
|
|
dst[ dstOffset + 3 ] = w0;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
Object.defineProperties( Quaternion.prototype, {
|
|
|
|
x: {
|
|
|
|
get: function () {
|
|
|
|
return this._x;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._x = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
y: {
|
|
|
|
get: function () {
|
|
|
|
return this._y;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._y = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
z: {
|
|
|
|
get: function () {
|
|
|
|
return this._z;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._z = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
w: {
|
|
|
|
get: function () {
|
|
|
|
return this._w;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._w = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
Object.assign( Quaternion.prototype, {
|
|
|
|
set: function ( x, y, z, w ) {
|
|
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._w = w;
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor( this._x, this._y, this._z, this._w );
|
|
|
|
},
|
|
|
|
copy: function ( quaternion ) {
|
|
|
|
this._x = quaternion.x;
|
|
this._y = quaternion.y;
|
|
this._z = quaternion.z;
|
|
this._w = quaternion.w;
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromEuler: function ( euler, update ) {
|
|
|
|
if ( ( euler && euler.isEuler ) === false ) {
|
|
|
|
throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
|
|
|
|
}
|
|
|
|
var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
|
|
|
|
// http://www.mathworks.com/matlabcentral/fileexchange/
|
|
// 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
|
|
// content/SpinCalc.m
|
|
|
|
var cos = Math.cos;
|
|
var sin = Math.sin;
|
|
|
|
var c1 = cos( x / 2 );
|
|
var c2 = cos( y / 2 );
|
|
var c3 = cos( z / 2 );
|
|
|
|
var s1 = sin( x / 2 );
|
|
var s2 = sin( y / 2 );
|
|
var s3 = sin( z / 2 );
|
|
|
|
if ( 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;
|
|
|
|
} else if ( 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;
|
|
|
|
} else if ( 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;
|
|
|
|
} else if ( 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;
|
|
|
|
} else if ( 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;
|
|
|
|
} else if ( 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;
|
|
|
|
}
|
|
|
|
if ( update !== false ) this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromAxisAngle: function ( axis, angle ) {
|
|
|
|
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
|
|
|
|
// assumes axis is normalized
|
|
|
|
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.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromRotationMatrix: function ( m ) {
|
|
|
|
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
|
|
|
|
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
|
|
|
|
var te = m.elements,
|
|
|
|
m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
|
|
m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
|
|
m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],
|
|
|
|
trace = m11 + m22 + m33,
|
|
s;
|
|
|
|
if ( trace > 0 ) {
|
|
|
|
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;
|
|
|
|
} 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;
|
|
|
|
} 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;
|
|
|
|
} 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.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromUnitVectors: function () {
|
|
|
|
// assumes direction vectors vFrom and vTo are normalized
|
|
|
|
var v1, r;
|
|
|
|
var EPS = 0.000001;
|
|
|
|
return function setFromUnitVectors( vFrom, vTo ) {
|
|
|
|
if ( v1 === undefined ) v1 = new Vector3();
|
|
|
|
r = vFrom.dot( vTo ) + 1;
|
|
|
|
if ( r < EPS ) {
|
|
|
|
r = 0;
|
|
|
|
if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {
|
|
|
|
v1.set( - vFrom.y, vFrom.x, 0 );
|
|
|
|
} else {
|
|
|
|
v1.set( 0, - vFrom.z, vFrom.y );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
v1.crossVectors( vFrom, vTo );
|
|
|
|
}
|
|
|
|
this._x = v1.x;
|
|
this._y = v1.y;
|
|
this._z = v1.z;
|
|
this._w = r;
|
|
|
|
return this.normalize();
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
inverse: function () {
|
|
|
|
return this.conjugate().normalize();
|
|
|
|
},
|
|
|
|
conjugate: function () {
|
|
|
|
this._x *= - 1;
|
|
this._y *= - 1;
|
|
this._z *= - 1;
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
dot: function ( v ) {
|
|
|
|
return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
|
|
|
|
},
|
|
|
|
lengthSq: function () {
|
|
|
|
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 );
|
|
|
|
},
|
|
|
|
normalize: function () {
|
|
|
|
var l = this.length();
|
|
|
|
if ( l === 0 ) {
|
|
|
|
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.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiply: function ( q, p ) {
|
|
|
|
if ( p !== undefined ) {
|
|
|
|
console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );
|
|
return this.multiplyQuaternions( q, p );
|
|
|
|
}
|
|
|
|
return this.multiplyQuaternions( this, q );
|
|
|
|
},
|
|
|
|
premultiply: function ( q ) {
|
|
|
|
return this.multiplyQuaternions( q, this );
|
|
|
|
},
|
|
|
|
multiplyQuaternions: function ( a, b ) {
|
|
|
|
// 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;
|
|
|
|
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.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
slerp: function ( qb, t ) {
|
|
|
|
if ( t === 0 ) return this;
|
|
if ( t === 1 ) return this.copy( qb );
|
|
|
|
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;
|
|
|
|
if ( cosHalfTheta < 0 ) {
|
|
|
|
this._w = - qb._w;
|
|
this._x = - qb._x;
|
|
this._y = - qb._y;
|
|
this._z = - qb._z;
|
|
|
|
cosHalfTheta = - cosHalfTheta;
|
|
|
|
} else {
|
|
|
|
this.copy( qb );
|
|
|
|
}
|
|
|
|
if ( cosHalfTheta >= 1.0 ) {
|
|
|
|
this._w = w;
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
|
|
|
|
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 );
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );
|
|
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.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
equals: function ( quaternion ) {
|
|
|
|
return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
this._x = array[ offset ];
|
|
this._y = array[ offset + 1 ];
|
|
this._z = array[ offset + 2 ];
|
|
this._w = array[ offset + 3 ];
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
array[ offset ] = this._x;
|
|
array[ offset + 1 ] = this._y;
|
|
array[ offset + 2 ] = this._z;
|
|
array[ offset + 3 ] = this._w;
|
|
|
|
return array;
|
|
|
|
},
|
|
|
|
onChange: function ( callback ) {
|
|
|
|
this.onChangeCallback = callback;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
onChangeCallback: function () {}
|
|
|
|
} );
|
|
|
|
/**
|
|
* https://github.com/mrdoob/eventdispatcher.js/
|
|
*/
|
|
|
|
function EventDispatcher() {}
|
|
|
|
Object.assign( EventDispatcher.prototype, {
|
|
|
|
addEventListener: function ( type, listener ) {
|
|
|
|
if ( this._listeners === undefined ) this._listeners = {};
|
|
|
|
var listeners = this._listeners;
|
|
|
|
if ( listeners[ type ] === undefined ) {
|
|
|
|
listeners[ type ] = [];
|
|
|
|
}
|
|
|
|
if ( listeners[ type ].indexOf( listener ) === - 1 ) {
|
|
|
|
listeners[ type ].push( listener );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
hasEventListener: function ( type, listener ) {
|
|
|
|
if ( this._listeners === undefined ) return false;
|
|
|
|
var listeners = this._listeners;
|
|
|
|
return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
|
|
|
|
},
|
|
|
|
removeEventListener: function ( type, listener ) {
|
|
|
|
if ( this._listeners === undefined ) return;
|
|
|
|
var listeners = this._listeners;
|
|
var listenerArray = listeners[ type ];
|
|
|
|
if ( listenerArray !== undefined ) {
|
|
|
|
var index = listenerArray.indexOf( listener );
|
|
|
|
if ( index !== - 1 ) {
|
|
|
|
listenerArray.splice( index, 1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
dispatchEvent: function ( event ) {
|
|
|
|
if ( this._listeners === undefined ) return;
|
|
|
|
var listeners = this._listeners;
|
|
var listenerArray = listeners[ event.type ];
|
|
|
|
if ( listenerArray !== undefined ) {
|
|
|
|
event.target = this;
|
|
|
|
var array = [], i = 0;
|
|
var length = listenerArray.length;
|
|
|
|
for ( i = 0; i < length; i ++ ) {
|
|
|
|
array[ i ] = listenerArray[ i ];
|
|
|
|
}
|
|
|
|
for ( i = 0; i < length; i ++ ) {
|
|
|
|
array[ i ].call( this, event );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
* @author bhouston / http://clara.io
|
|
*/
|
|
|
|
function Euler( x, y, z, order ) {
|
|
|
|
this._x = x || 0;
|
|
this._y = y || 0;
|
|
this._z = z || 0;
|
|
this._order = order || Euler.DefaultOrder;
|
|
|
|
}
|
|
|
|
Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];
|
|
|
|
Euler.DefaultOrder = 'XYZ';
|
|
|
|
Object.defineProperties( Euler.prototype, {
|
|
|
|
x: {
|
|
|
|
get: function () {
|
|
|
|
return this._x;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._x = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
y: {
|
|
|
|
get: function () {
|
|
|
|
return this._y;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._y = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
z: {
|
|
|
|
get: function () {
|
|
|
|
return this._z;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._z = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
order: {
|
|
|
|
get: function () {
|
|
|
|
return this._order;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this._order = value;
|
|
this.onChangeCallback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
Object.assign( Euler.prototype, {
|
|
|
|
isEuler: true,
|
|
|
|
set: function ( x, y, z, order ) {
|
|
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._order = order || this._order;
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor( this._x, this._y, this._z, this._order );
|
|
|
|
},
|
|
|
|
copy: function ( euler ) {
|
|
|
|
this._x = euler._x;
|
|
this._y = euler._y;
|
|
this._z = euler._z;
|
|
this._order = euler._order;
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromRotationMatrix: function ( m, order, update ) {
|
|
|
|
var clamp = _Math.clamp;
|
|
|
|
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
|
|
|
|
var te = m.elements;
|
|
var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];
|
|
var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];
|
|
var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
|
|
|
|
order = order || this._order;
|
|
|
|
if ( order === 'XYZ' ) {
|
|
|
|
this._y = Math.asin( clamp( m13, - 1, 1 ) );
|
|
|
|
if ( Math.abs( m13 ) < 0.99999 ) {
|
|
|
|
this._x = Math.atan2( - m23, m33 );
|
|
this._z = Math.atan2( - m12, m11 );
|
|
|
|
} else {
|
|
|
|
this._x = Math.atan2( m32, m22 );
|
|
this._z = 0;
|
|
|
|
}
|
|
|
|
} else if ( order === 'YXZ' ) {
|
|
|
|
this._x = Math.asin( - clamp( m23, - 1, 1 ) );
|
|
|
|
if ( Math.abs( m23 ) < 0.99999 ) {
|
|
|
|
this._y = Math.atan2( m13, m33 );
|
|
this._z = Math.atan2( m21, m22 );
|
|
|
|
} else {
|
|
|
|
this._y = Math.atan2( - m31, m11 );
|
|
this._z = 0;
|
|
|
|
}
|
|
|
|
} else if ( order === 'ZXY' ) {
|
|
|
|
this._x = Math.asin( clamp( m32, - 1, 1 ) );
|
|
|
|
if ( Math.abs( m32 ) < 0.99999 ) {
|
|
|
|
this._y = Math.atan2( - m31, m33 );
|
|
this._z = Math.atan2( - m12, m22 );
|
|
|
|
} else {
|
|
|
|
this._y = 0;
|
|
this._z = Math.atan2( m21, m11 );
|
|
|
|
}
|
|
|
|
} else if ( order === 'ZYX' ) {
|
|
|
|
this._y = Math.asin( - clamp( m31, - 1, 1 ) );
|
|
|
|
if ( Math.abs( m31 ) < 0.99999 ) {
|
|
|
|
this._x = Math.atan2( m32, m33 );
|
|
this._z = Math.atan2( m21, m11 );
|
|
|
|
} else {
|
|
|
|
this._x = 0;
|
|
this._z = Math.atan2( - m12, m22 );
|
|
|
|
}
|
|
|
|
} else if ( order === 'YZX' ) {
|
|
|
|
this._z = Math.asin( clamp( m21, - 1, 1 ) );
|
|
|
|
if ( Math.abs( m21 ) < 0.99999 ) {
|
|
|
|
this._x = Math.atan2( - m23, m22 );
|
|
this._y = Math.atan2( - m31, m11 );
|
|
|
|
} else {
|
|
|
|
this._x = 0;
|
|
this._y = Math.atan2( m13, m33 );
|
|
|
|
}
|
|
|
|
} else if ( order === 'XZY' ) {
|
|
|
|
this._z = Math.asin( - clamp( m12, - 1, 1 ) );
|
|
|
|
if ( Math.abs( m12 ) < 0.99999 ) {
|
|
|
|
this._x = Math.atan2( m32, m22 );
|
|
this._y = Math.atan2( m13, m11 );
|
|
|
|
} else {
|
|
|
|
this._x = Math.atan2( - m23, m33 );
|
|
this._y = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );
|
|
|
|
}
|
|
|
|
this._order = order;
|
|
|
|
if ( update !== false ) this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromQuaternion: function () {
|
|
|
|
var matrix;
|
|
|
|
return function setFromQuaternion( q, order, update ) {
|
|
|
|
if ( matrix === undefined ) matrix = new Matrix4();
|
|
|
|
matrix.makeRotationFromQuaternion( q );
|
|
|
|
return this.setFromRotationMatrix( matrix, order, update );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
setFromVector3: function ( v, order ) {
|
|
|
|
return this.set( v.x, v.y, v.z, order || this._order );
|
|
|
|
},
|
|
|
|
reorder: function () {
|
|
|
|
// WARNING: this discards revolution information -bhouston
|
|
|
|
var q = new Quaternion();
|
|
|
|
return function reorder( newOrder ) {
|
|
|
|
q.setFromEuler( this );
|
|
|
|
return this.setFromQuaternion( q, newOrder );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
equals: function ( euler ) {
|
|
|
|
return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );
|
|
|
|
},
|
|
|
|
fromArray: function ( array ) {
|
|
|
|
this._x = array[ 0 ];
|
|
this._y = array[ 1 ];
|
|
this._z = array[ 2 ];
|
|
if ( array[ 3 ] !== undefined ) this._order = array[ 3 ];
|
|
|
|
this.onChangeCallback();
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
array[ offset ] = this._x;
|
|
array[ offset + 1 ] = this._y;
|
|
array[ offset + 2 ] = this._z;
|
|
array[ offset + 3 ] = this._order;
|
|
|
|
return array;
|
|
|
|
},
|
|
|
|
toVector3: function ( optionalResult ) {
|
|
|
|
if ( optionalResult ) {
|
|
|
|
return optionalResult.set( this._x, this._y, this._z );
|
|
|
|
} else {
|
|
|
|
return new Vector3( this._x, this._y, this._z );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onChange: function ( callback ) {
|
|
|
|
this.onChangeCallback = callback;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
onChangeCallback: function () {}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
*/
|
|
|
|
function Layers() {
|
|
|
|
this.mask = 1 | 0;
|
|
|
|
}
|
|
|
|
Object.assign( Layers.prototype, {
|
|
|
|
set: function ( channel ) {
|
|
|
|
this.mask = 1 << channel | 0;
|
|
|
|
},
|
|
|
|
enable: function ( channel ) {
|
|
|
|
this.mask |= 1 << channel | 0;
|
|
|
|
},
|
|
|
|
toggle: function ( channel ) {
|
|
|
|
this.mask ^= 1 << channel | 0;
|
|
|
|
},
|
|
|
|
disable: function ( channel ) {
|
|
|
|
this.mask &= ~ ( 1 << channel | 0 );
|
|
|
|
},
|
|
|
|
test: function ( layers ) {
|
|
|
|
return ( this.mask & layers.mask ) !== 0;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author alteredq / http://alteredqualia.com/
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
* @author bhouston / http://clara.io
|
|
* @author tschw
|
|
*/
|
|
|
|
function Matrix3() {
|
|
|
|
this.elements = [
|
|
|
|
1, 0, 0,
|
|
0, 1, 0,
|
|
0, 0, 1
|
|
|
|
];
|
|
|
|
if ( arguments.length > 0 ) {
|
|
|
|
console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Object.assign( Matrix3.prototype, {
|
|
|
|
isMatrix3: true,
|
|
|
|
set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
|
|
|
|
var te = this.elements;
|
|
|
|
te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
|
|
te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
|
|
te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
identity: function () {
|
|
|
|
this.set(
|
|
|
|
1, 0, 0,
|
|
0, 1, 0,
|
|
0, 0, 1
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor().fromArray( this.elements );
|
|
|
|
},
|
|
|
|
copy: function ( m ) {
|
|
|
|
var te = this.elements;
|
|
var me = m.elements;
|
|
|
|
te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
|
|
te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
|
|
te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setFromMatrix4: function ( m ) {
|
|
|
|
var me = m.elements;
|
|
|
|
this.set(
|
|
|
|
me[ 0 ], me[ 4 ], me[ 8 ],
|
|
me[ 1 ], me[ 5 ], me[ 9 ],
|
|
me[ 2 ], me[ 6 ], me[ 10 ]
|
|
|
|
);
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
applyToBufferAttribute: function () {
|
|
|
|
var v1;
|
|
|
|
return function applyToBufferAttribute( attribute ) {
|
|
|
|
if ( v1 === undefined ) v1 = new Vector3();
|
|
|
|
for ( var i = 0, l = attribute.count; i < l; i ++ ) {
|
|
|
|
v1.x = attribute.getX( i );
|
|
v1.y = attribute.getY( i );
|
|
v1.z = attribute.getZ( i );
|
|
|
|
v1.applyMatrix3( this );
|
|
|
|
attribute.setXYZ( i, v1.x, v1.y, v1.z );
|
|
|
|
}
|
|
|
|
return attribute;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
multiply: function ( m ) {
|
|
|
|
return this.multiplyMatrices( this, m );
|
|
|
|
},
|
|
|
|
premultiply: function ( m ) {
|
|
|
|
return this.multiplyMatrices( m, this );
|
|
|
|
},
|
|
|
|
multiplyMatrices: function ( a, b ) {
|
|
|
|
var ae = a.elements;
|
|
var be = b.elements;
|
|
var te = this.elements;
|
|
|
|
var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
|
|
var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
|
|
var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
|
|
|
|
var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
|
|
var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
|
|
var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
|
|
|
|
te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
|
|
te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
|
|
te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
|
|
|
|
te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
|
|
te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
|
|
te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
|
|
|
|
te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
|
|
te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
|
|
te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyScalar: function ( s ) {
|
|
|
|
var te = this.elements;
|
|
|
|
te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;
|
|
te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;
|
|
te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
determinant: function () {
|
|
|
|
var te = this.elements;
|
|
|
|
var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],
|
|
d = te[ 3 ], e = te[ 4 ], f = te[ 5 ],
|
|
g = te[ 6 ], h = te[ 7 ], i = te[ 8 ];
|
|
|
|
return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
|
|
|
|
},
|
|
|
|
getInverse: function ( matrix, throwOnDegenerate ) {
|
|
|
|
if ( matrix && matrix.isMatrix4 ) {
|
|
|
|
console.error( "THREE.Matrix3.getInverse no longer takes a Matrix4 argument." );
|
|
|
|
}
|
|
|
|
var me = matrix.elements,
|
|
te = this.elements,
|
|
|
|
n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],
|
|
n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],
|
|
n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],
|
|
|
|
t11 = n33 * n22 - n32 * n23,
|
|
t12 = n32 * n13 - n33 * n12,
|
|
t13 = n23 * n12 - n22 * n13,
|
|
|
|
det = n11 * t11 + n21 * t12 + n31 * t13;
|
|
|
|
if ( det === 0 ) {
|
|
|
|
var msg = "THREE.Matrix3.getInverse(): can't invert matrix, determinant is 0";
|
|
|
|
if ( throwOnDegenerate === true ) {
|
|
|
|
throw new Error( msg );
|
|
|
|
} else {
|
|
|
|
console.warn( msg );
|
|
|
|
}
|
|
|
|
return this.identity();
|
|
|
|
}
|
|
|
|
var detInv = 1 / det;
|
|
|
|
te[ 0 ] = t11 * detInv;
|
|
te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
|
|
te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
|
|
|
|
te[ 3 ] = t12 * detInv;
|
|
te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
|
|
te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
|
|
|
|
te[ 6 ] = t13 * detInv;
|
|
te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
|
|
te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
transpose: function () {
|
|
|
|
var tmp, m = this.elements;
|
|
|
|
tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
|
|
tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
|
|
tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getNormalMatrix: function ( matrix4 ) {
|
|
|
|
return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();
|
|
|
|
},
|
|
|
|
transposeIntoArray: function ( r ) {
|
|
|
|
var m = this.elements;
|
|
|
|
r[ 0 ] = m[ 0 ];
|
|
r[ 1 ] = m[ 3 ];
|
|
r[ 2 ] = m[ 6 ];
|
|
r[ 3 ] = m[ 1 ];
|
|
r[ 4 ] = m[ 4 ];
|
|
r[ 5 ] = m[ 7 ];
|
|
r[ 6 ] = m[ 2 ];
|
|
r[ 7 ] = m[ 5 ];
|
|
r[ 8 ] = m[ 8 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
equals: function ( matrix ) {
|
|
|
|
var te = this.elements;
|
|
var me = matrix.elements;
|
|
|
|
for ( var i = 0; i < 9; i ++ ) {
|
|
|
|
if ( te[ i ] !== me[ i ] ) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
for ( var i = 0; i < 9; i ++ ) {
|
|
|
|
this.elements[ i ] = array[ i + offset ];
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
var te = this.elements;
|
|
|
|
array[ offset ] = te[ 0 ];
|
|
array[ offset + 1 ] = te[ 1 ];
|
|
array[ offset + 2 ] = te[ 2 ];
|
|
|
|
array[ offset + 3 ] = te[ 3 ];
|
|
array[ offset + 4 ] = te[ 4 ];
|
|
array[ offset + 5 ] = te[ 5 ];
|
|
|
|
array[ offset + 6 ] = te[ 6 ];
|
|
array[ offset + 7 ] = te[ 7 ];
|
|
array[ offset + 8 ] = te[ 8 ];
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author alteredq / http://alteredqualia.com/
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
* @author elephantatwork / www.elephantatwork.ch
|
|
*/
|
|
|
|
var object3DId = 0;
|
|
|
|
function Object3D() {
|
|
|
|
Object.defineProperty( this, 'id', { value: object3DId ++ } );
|
|
|
|
this.uuid = _Math.generateUUID();
|
|
|
|
this.name = '';
|
|
this.type = 'Object3D';
|
|
|
|
this.parent = null;
|
|
this.children = [];
|
|
|
|
this.up = Object3D.DefaultUp.clone();
|
|
|
|
var position = new Vector3();
|
|
var rotation = new Euler();
|
|
var quaternion = new Quaternion();
|
|
var scale = new Vector3( 1, 1, 1 );
|
|
|
|
function onRotationChange() {
|
|
|
|
quaternion.setFromEuler( rotation, false );
|
|
|
|
}
|
|
|
|
function onQuaternionChange() {
|
|
|
|
rotation.setFromQuaternion( quaternion, undefined, false );
|
|
|
|
}
|
|
|
|
rotation.onChange( onRotationChange );
|
|
quaternion.onChange( onQuaternionChange );
|
|
|
|
Object.defineProperties( this, {
|
|
position: {
|
|
enumerable: true,
|
|
value: position
|
|
},
|
|
rotation: {
|
|
enumerable: true,
|
|
value: rotation
|
|
},
|
|
quaternion: {
|
|
enumerable: true,
|
|
value: quaternion
|
|
},
|
|
scale: {
|
|
enumerable: true,
|
|
value: scale
|
|
},
|
|
modelViewMatrix: {
|
|
value: new Matrix4()
|
|
},
|
|
normalMatrix: {
|
|
value: new Matrix3()
|
|
}
|
|
} );
|
|
|
|
this.matrix = new Matrix4();
|
|
this.matrixWorld = new Matrix4();
|
|
|
|
this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
|
|
this.matrixWorldNeedsUpdate = false;
|
|
|
|
this.layers = new Layers();
|
|
this.visible = true;
|
|
|
|
this.castShadow = false;
|
|
this.receiveShadow = false;
|
|
|
|
this.frustumCulled = true;
|
|
this.renderOrder = 0;
|
|
|
|
this.userData = {};
|
|
|
|
this.onBeforeRender = function () {};
|
|
this.onAfterRender = function () {};
|
|
|
|
}
|
|
|
|
Object3D.DefaultUp = new Vector3( 0, 1, 0 );
|
|
Object3D.DefaultMatrixAutoUpdate = true;
|
|
|
|
Object.assign( Object3D.prototype, EventDispatcher.prototype, {
|
|
|
|
isObject3D: true,
|
|
|
|
applyMatrix: function ( matrix ) {
|
|
|
|
this.matrix.multiplyMatrices( matrix, this.matrix );
|
|
|
|
this.matrix.decompose( this.position, this.quaternion, this.scale );
|
|
|
|
},
|
|
|
|
setRotationFromAxisAngle: function ( axis, angle ) {
|
|
|
|
// assumes axis is normalized
|
|
|
|
this.quaternion.setFromAxisAngle( axis, angle );
|
|
|
|
},
|
|
|
|
setRotationFromEuler: function ( euler ) {
|
|
|
|
this.quaternion.setFromEuler( euler, true );
|
|
|
|
},
|
|
|
|
setRotationFromMatrix: function ( m ) {
|
|
|
|
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
|
|
|
|
this.quaternion.setFromRotationMatrix( m );
|
|
|
|
},
|
|
|
|
setRotationFromQuaternion: function ( q ) {
|
|
|
|
// assumes q is normalized
|
|
|
|
this.quaternion.copy( q );
|
|
|
|
},
|
|
|
|
rotateOnAxis: function () {
|
|
|
|
// rotate object on axis in object space
|
|
// axis is assumed to be normalized
|
|
|
|
var q1 = new Quaternion();
|
|
|
|
return function rotateOnAxis( axis, angle ) {
|
|
|
|
q1.setFromAxisAngle( axis, angle );
|
|
|
|
this.quaternion.multiply( q1 );
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
rotateX: function () {
|
|
|
|
var v1 = new Vector3( 1, 0, 0 );
|
|
|
|
return function rotateX( angle ) {
|
|
|
|
return this.rotateOnAxis( v1, angle );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
rotateY: function () {
|
|
|
|
var v1 = new Vector3( 0, 1, 0 );
|
|
|
|
return function rotateY( angle ) {
|
|
|
|
return this.rotateOnAxis( v1, angle );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
rotateZ: function () {
|
|
|
|
var v1 = new Vector3( 0, 0, 1 );
|
|
|
|
return function rotateZ( angle ) {
|
|
|
|
return this.rotateOnAxis( v1, angle );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
translateOnAxis: function () {
|
|
|
|
// translate object by distance along axis in object space
|
|
// axis is assumed to be normalized
|
|
|
|
var v1 = new Vector3();
|
|
|
|
return function translateOnAxis( axis, distance ) {
|
|
|
|
v1.copy( axis ).applyQuaternion( this.quaternion );
|
|
|
|
this.position.add( v1.multiplyScalar( distance ) );
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
translateX: function () {
|
|
|
|
var v1 = new Vector3( 1, 0, 0 );
|
|
|
|
return function translateX( distance ) {
|
|
|
|
return this.translateOnAxis( v1, distance );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
translateY: function () {
|
|
|
|
var v1 = new Vector3( 0, 1, 0 );
|
|
|
|
return function translateY( distance ) {
|
|
|
|
return this.translateOnAxis( v1, distance );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
translateZ: function () {
|
|
|
|
var v1 = new Vector3( 0, 0, 1 );
|
|
|
|
return function translateZ( distance ) {
|
|
|
|
return this.translateOnAxis( v1, distance );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
localToWorld: function ( vector ) {
|
|
|
|
return vector.applyMatrix4( this.matrixWorld );
|
|
|
|
},
|
|
|
|
worldToLocal: function () {
|
|
|
|
var m1 = new Matrix4();
|
|
|
|
return function worldToLocal( vector ) {
|
|
|
|
return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
lookAt: function () {
|
|
|
|
// This routine does not support objects with rotated and/or translated parent(s)
|
|
|
|
var m1 = new Matrix4();
|
|
|
|
return function lookAt( vector ) {
|
|
|
|
if ( this.isCamera ) {
|
|
|
|
m1.lookAt( this.position, vector, this.up );
|
|
|
|
} else {
|
|
|
|
m1.lookAt( vector, this.position, this.up );
|
|
|
|
}
|
|
|
|
this.quaternion.setFromRotationMatrix( m1 );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
add: function ( object ) {
|
|
|
|
if ( arguments.length > 1 ) {
|
|
|
|
for ( var i = 0; i < arguments.length; i ++ ) {
|
|
|
|
this.add( arguments[ i ] );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
if ( object === this ) {
|
|
|
|
console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object );
|
|
return this;
|
|
|
|
}
|
|
|
|
if ( ( object && object.isObject3D ) ) {
|
|
|
|
if ( object.parent !== null ) {
|
|
|
|
object.parent.remove( object );
|
|
|
|
}
|
|
|
|
object.parent = this;
|
|
object.dispatchEvent( { type: 'added' } );
|
|
|
|
this.children.push( object );
|
|
|
|
} else {
|
|
|
|
console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
remove: function ( object ) {
|
|
|
|
if ( arguments.length > 1 ) {
|
|
|
|
for ( var i = 0; i < arguments.length; i ++ ) {
|
|
|
|
this.remove( arguments[ i ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var index = this.children.indexOf( object );
|
|
|
|
if ( index !== - 1 ) {
|
|
|
|
object.parent = null;
|
|
|
|
object.dispatchEvent( { type: 'removed' } );
|
|
|
|
this.children.splice( index, 1 );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
getObjectById: function ( id ) {
|
|
|
|
return this.getObjectByProperty( 'id', id );
|
|
|
|
},
|
|
|
|
getObjectByName: function ( name ) {
|
|
|
|
return this.getObjectByProperty( 'name', name );
|
|
|
|
},
|
|
|
|
getObjectByProperty: function ( name, value ) {
|
|
|
|
if ( this[ name ] === value ) return this;
|
|
|
|
for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
|
|
|
var child = this.children[ i ];
|
|
var object = child.getObjectByProperty( name, value );
|
|
|
|
if ( object !== undefined ) {
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
},
|
|
|
|
getWorldPosition: function ( optionalTarget ) {
|
|
|
|
var result = optionalTarget || new Vector3();
|
|
|
|
this.updateMatrixWorld( true );
|
|
|
|
return result.setFromMatrixPosition( this.matrixWorld );
|
|
|
|
},
|
|
|
|
getWorldQuaternion: function () {
|
|
|
|
var position = new Vector3();
|
|
var scale = new Vector3();
|
|
|
|
return function getWorldQuaternion( optionalTarget ) {
|
|
|
|
var result = optionalTarget || new Quaternion();
|
|
|
|
this.updateMatrixWorld( true );
|
|
|
|
this.matrixWorld.decompose( position, result, scale );
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
getWorldRotation: function () {
|
|
|
|
var quaternion = new Quaternion();
|
|
|
|
return function getWorldRotation( optionalTarget ) {
|
|
|
|
var result = optionalTarget || new Euler();
|
|
|
|
this.getWorldQuaternion( quaternion );
|
|
|
|
return result.setFromQuaternion( quaternion, this.rotation.order, false );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
getWorldScale: function () {
|
|
|
|
var position = new Vector3();
|
|
var quaternion = new Quaternion();
|
|
|
|
return function getWorldScale( optionalTarget ) {
|
|
|
|
var result = optionalTarget || new Vector3();
|
|
|
|
this.updateMatrixWorld( true );
|
|
|
|
this.matrixWorld.decompose( position, quaternion, result );
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
getWorldDirection: function () {
|
|
|
|
var quaternion = new Quaternion();
|
|
|
|
return function getWorldDirection( optionalTarget ) {
|
|
|
|
var result = optionalTarget || new Vector3();
|
|
|
|
this.getWorldQuaternion( quaternion );
|
|
|
|
return result.set( 0, 0, 1 ).applyQuaternion( quaternion );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
raycast: function () {},
|
|
|
|
traverse: function ( callback ) {
|
|
|
|
callback( this );
|
|
|
|
var children = this.children;
|
|
|
|
for ( var i = 0, l = children.length; i < l; i ++ ) {
|
|
|
|
children[ i ].traverse( callback );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
traverseVisible: function ( callback ) {
|
|
|
|
if ( this.visible === false ) return;
|
|
|
|
callback( this );
|
|
|
|
var children = this.children;
|
|
|
|
for ( var i = 0, l = children.length; i < l; i ++ ) {
|
|
|
|
children[ i ].traverseVisible( callback );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
traverseAncestors: function ( callback ) {
|
|
|
|
var parent = this.parent;
|
|
|
|
if ( parent !== null ) {
|
|
|
|
callback( parent );
|
|
|
|
parent.traverseAncestors( callback );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
updateMatrix: function () {
|
|
|
|
this.matrix.compose( this.position, this.quaternion, this.scale );
|
|
|
|
this.matrixWorldNeedsUpdate = true;
|
|
|
|
},
|
|
|
|
updateMatrixWorld: function ( force ) {
|
|
|
|
if ( this.matrixAutoUpdate ) this.updateMatrix();
|
|
|
|
if ( this.matrixWorldNeedsUpdate || force ) {
|
|
|
|
if ( this.parent === null ) {
|
|
|
|
this.matrixWorld.copy( this.matrix );
|
|
|
|
} else {
|
|
|
|
this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
|
|
|
|
}
|
|
|
|
this.matrixWorldNeedsUpdate = false;
|
|
|
|
force = true;
|
|
|
|
}
|
|
|
|
// update children
|
|
|
|
var children = this.children;
|
|
|
|
for ( var i = 0, l = children.length; i < l; i ++ ) {
|
|
|
|
children[ i ].updateMatrixWorld( force );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
toJSON: function ( meta ) {
|
|
|
|
// meta is '' when called from JSON.stringify
|
|
var isRootObject = ( meta === undefined || meta === '' );
|
|
|
|
var output = {};
|
|
|
|
// meta is a hash used to collect geometries, materials.
|
|
// not providing it implies that this is the root object
|
|
// being serialized.
|
|
if ( isRootObject ) {
|
|
|
|
// initialize meta obj
|
|
meta = {
|
|
geometries: {},
|
|
materials: {},
|
|
textures: {},
|
|
images: {}
|
|
};
|
|
|
|
output.metadata = {
|
|
version: 4.5,
|
|
type: 'Object',
|
|
generator: 'Object3D.toJSON'
|
|
};
|
|
|
|
}
|
|
|
|
// standard Object3D serialization
|
|
|
|
var object = {};
|
|
|
|
object.uuid = this.uuid;
|
|
object.type = this.type;
|
|
|
|
if ( this.name !== '' ) object.name = this.name;
|
|
if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
|
|
if ( this.castShadow === true ) object.castShadow = true;
|
|
if ( this.receiveShadow === true ) object.receiveShadow = true;
|
|
if ( this.visible === false ) object.visible = false;
|
|
|
|
object.matrix = this.matrix.toArray();
|
|
|
|
//
|
|
|
|
function serialize( library, element ) {
|
|
|
|
if ( library[ element.uuid ] === undefined ) {
|
|
|
|
library[ element.uuid ] = element.toJSON( meta );
|
|
|
|
}
|
|
|
|
return element.uuid;
|
|
|
|
}
|
|
|
|
if ( this.geometry !== undefined ) {
|
|
|
|
object.geometry = serialize( meta.geometries, this.geometry );
|
|
|
|
}
|
|
|
|
if ( this.material !== undefined ) {
|
|
|
|
if ( Array.isArray( this.material ) ) {
|
|
|
|
var uuids = [];
|
|
|
|
for ( var i = 0, l = this.material.length; i < l; i ++ ) {
|
|
|
|
uuids.push( serialize( meta.materials, this.material[ i ] ) );
|
|
|
|
}
|
|
|
|
object.material = uuids;
|
|
|
|
} else {
|
|
|
|
object.material = serialize( meta.materials, this.material );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
if ( this.children.length > 0 ) {
|
|
|
|
object.children = [];
|
|
|
|
for ( var i = 0; i < this.children.length; i ++ ) {
|
|
|
|
object.children.push( this.children[ i ].toJSON( meta ).object );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( isRootObject ) {
|
|
|
|
var geometries = extractFromCache( meta.geometries );
|
|
var materials = extractFromCache( meta.materials );
|
|
var textures = extractFromCache( meta.textures );
|
|
var images = extractFromCache( meta.images );
|
|
|
|
if ( geometries.length > 0 ) output.geometries = geometries;
|
|
if ( materials.length > 0 ) output.materials = materials;
|
|
if ( textures.length > 0 ) output.textures = textures;
|
|
if ( images.length > 0 ) output.images = images;
|
|
|
|
}
|
|
|
|
output.object = object;
|
|
|
|
return output;
|
|
|
|
// extract data from the cache hash
|
|
// remove metadata on each item
|
|
// and return as array
|
|
function extractFromCache( cache ) {
|
|
|
|
var values = [];
|
|
for ( var key in cache ) {
|
|
|
|
var data = cache[ key ];
|
|
delete data.metadata;
|
|
values.push( data );
|
|
|
|
}
|
|
return values;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
clone: function ( recursive ) {
|
|
|
|
return new this.constructor().copy( this, recursive );
|
|
|
|
},
|
|
|
|
copy: function ( source, recursive ) {
|
|
|
|
if ( recursive === undefined ) recursive = true;
|
|
|
|
this.name = source.name;
|
|
|
|
this.up.copy( source.up );
|
|
|
|
this.position.copy( source.position );
|
|
this.quaternion.copy( source.quaternion );
|
|
this.scale.copy( source.scale );
|
|
|
|
this.matrix.copy( source.matrix );
|
|
this.matrixWorld.copy( source.matrixWorld );
|
|
|
|
this.matrixAutoUpdate = source.matrixAutoUpdate;
|
|
this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
|
|
|
|
this.layers.mask = source.layers.mask;
|
|
this.visible = source.visible;
|
|
|
|
this.castShadow = source.castShadow;
|
|
this.receiveShadow = source.receiveShadow;
|
|
|
|
this.frustumCulled = source.frustumCulled;
|
|
this.renderOrder = source.renderOrder;
|
|
|
|
this.userData = JSON.parse( JSON.stringify( source.userData ) );
|
|
|
|
if ( recursive === true ) {
|
|
|
|
for ( var i = 0; i < source.children.length; i ++ ) {
|
|
|
|
var child = source.children[ i ];
|
|
this.add( child.clone() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
*/
|
|
|
|
function Color( r, g, b ) {
|
|
|
|
if ( g === undefined && b === undefined ) {
|
|
|
|
// r is THREE.Color, hex or string
|
|
return this.set( r );
|
|
|
|
}
|
|
|
|
return this.setRGB( r, g, b );
|
|
|
|
}
|
|
|
|
Object.assign( Color.prototype, {
|
|
|
|
isColor: true,
|
|
|
|
r: 1, g: 1, b: 1,
|
|
|
|
set: function ( value ) {
|
|
|
|
if ( value && value.isColor ) {
|
|
|
|
this.copy( value );
|
|
|
|
} else if ( typeof value === 'number' ) {
|
|
|
|
this.setHex( value );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setScalar: function ( scalar ) {
|
|
|
|
this.r = scalar;
|
|
this.g = scalar;
|
|
this.b = scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setHex: function ( hex ) {
|
|
|
|
hex = Math.floor( hex );
|
|
|
|
this.r = ( hex >> 16 & 255 ) / 255;
|
|
this.g = ( hex >> 8 & 255 ) / 255;
|
|
this.b = ( hex & 255 ) / 255;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setRGB: function ( r, g, b ) {
|
|
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setHSL: function () {
|
|
|
|
function hue2rgb( p, q, t ) {
|
|
|
|
if ( t < 0 ) t += 1;
|
|
if ( t > 1 ) t -= 1;
|
|
if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;
|
|
if ( t < 1 / 2 ) return q;
|
|
if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );
|
|
return p;
|
|
|
|
}
|
|
|
|
return function setHSL( h, s, l ) {
|
|
|
|
// h,s,l ranges are in 0.0 - 1.0
|
|
h = _Math.euclideanModulo( h, 1 );
|
|
s = _Math.clamp( s, 0, 1 );
|
|
l = _Math.clamp( l, 0, 1 );
|
|
|
|
if ( s === 0 ) {
|
|
|
|
this.r = this.g = this.b = l;
|
|
|
|
} else {
|
|
|
|
var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );
|
|
var q = ( 2 * l ) - p;
|
|
|
|
this.r = hue2rgb( q, p, h + 1 / 3 );
|
|
this.g = hue2rgb( q, p, h );
|
|
this.b = hue2rgb( q, p, h - 1 / 3 );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
setStyle: function ( style ) {
|
|
|
|
var m;
|
|
|
|
if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) {
|
|
|
|
// hex color
|
|
|
|
var hex = m[ 1 ];
|
|
var size = hex.length;
|
|
|
|
if ( size === 3 ) {
|
|
|
|
// #ff0
|
|
this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;
|
|
this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;
|
|
this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;
|
|
|
|
return this;
|
|
|
|
} else if ( size === 6 ) {
|
|
|
|
// #ff0000
|
|
this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;
|
|
this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;
|
|
this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor( this.r, this.g, this.b );
|
|
|
|
},
|
|
|
|
copy: function ( color ) {
|
|
|
|
this.r = color.r;
|
|
this.g = color.g;
|
|
this.b = color.b;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
copyGammaToLinear: function ( color, gammaFactor ) {
|
|
|
|
if ( gammaFactor === undefined ) gammaFactor = 2.0;
|
|
|
|
this.r = Math.pow( color.r, gammaFactor );
|
|
this.g = Math.pow( color.g, gammaFactor );
|
|
this.b = Math.pow( color.b, gammaFactor );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
copyLinearToGamma: function ( color, gammaFactor ) {
|
|
|
|
if ( gammaFactor === undefined ) gammaFactor = 2.0;
|
|
|
|
var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
|
|
|
|
this.r = Math.pow( color.r, safeInverse );
|
|
this.g = Math.pow( color.g, safeInverse );
|
|
this.b = Math.pow( color.b, safeInverse );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
convertGammaToLinear: function () {
|
|
|
|
var r = this.r, g = this.g, b = this.b;
|
|
|
|
this.r = r * r;
|
|
this.g = g * g;
|
|
this.b = b * b;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
convertLinearToGamma: function () {
|
|
|
|
this.r = Math.sqrt( this.r );
|
|
this.g = Math.sqrt( this.g );
|
|
this.b = Math.sqrt( this.b );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getHex: function () {
|
|
|
|
return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
|
|
|
|
},
|
|
|
|
getHexString: function () {
|
|
|
|
return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );
|
|
|
|
},
|
|
|
|
getHSL: function ( optionalTarget ) {
|
|
|
|
// h,s,l ranges are in 0.0 - 1.0
|
|
|
|
var hsl = optionalTarget || { h: 0, s: 0, l: 0 };
|
|
|
|
var r = this.r, g = this.g, b = this.b;
|
|
|
|
var max = Math.max( r, g, b );
|
|
var min = Math.min( r, g, b );
|
|
|
|
var hue, saturation;
|
|
var lightness = ( min + max ) / 2.0;
|
|
|
|
if ( min === max ) {
|
|
|
|
hue = 0;
|
|
saturation = 0;
|
|
|
|
} else {
|
|
|
|
var delta = max - min;
|
|
|
|
saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
|
|
|
|
switch ( max ) {
|
|
|
|
case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
|
|
case g: hue = ( b - r ) / delta + 2; break;
|
|
case b: hue = ( r - g ) / delta + 4; break;
|
|
|
|
}
|
|
|
|
hue /= 6;
|
|
|
|
}
|
|
|
|
hsl.h = hue;
|
|
hsl.s = saturation;
|
|
hsl.l = lightness;
|
|
|
|
return hsl;
|
|
|
|
},
|
|
|
|
getStyle: function () {
|
|
|
|
return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
|
|
|
|
},
|
|
|
|
offsetHSL: function ( h, s, l ) {
|
|
|
|
var hsl = this.getHSL();
|
|
|
|
hsl.h += h; hsl.s += s; hsl.l += l;
|
|
|
|
this.setHSL( hsl.h, hsl.s, hsl.l );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
add: function ( color ) {
|
|
|
|
this.r += color.r;
|
|
this.g += color.g;
|
|
this.b += color.b;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addColors: function ( color1, color2 ) {
|
|
|
|
this.r = color1.r + color2.r;
|
|
this.g = color1.g + color2.g;
|
|
this.b = color1.b + color2.b;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScalar: function ( s ) {
|
|
|
|
this.r += s;
|
|
this.g += s;
|
|
this.b += s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
sub: function( color ) {
|
|
|
|
this.r = Math.max( 0, this.r - color.r );
|
|
this.g = Math.max( 0, this.g - color.g );
|
|
this.b = Math.max( 0, this.b - color.b );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiply: function ( color ) {
|
|
|
|
this.r *= color.r;
|
|
this.g *= color.g;
|
|
this.b *= color.b;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyScalar: function ( s ) {
|
|
|
|
this.r *= s;
|
|
this.g *= s;
|
|
this.b *= s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
lerp: function ( color, alpha ) {
|
|
|
|
this.r += ( color.r - this.r ) * alpha;
|
|
this.g += ( color.g - this.g ) * alpha;
|
|
this.b += ( color.b - this.b ) * alpha;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
equals: function ( c ) {
|
|
|
|
return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
this.r = array[ offset ];
|
|
this.g = array[ offset + 1 ];
|
|
this.b = array[ offset + 2 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
array[ offset ] = this.r;
|
|
array[ offset + 1 ] = this.g;
|
|
array[ offset + 2 ] = this.b;
|
|
|
|
return array;
|
|
|
|
},
|
|
|
|
toJSON: function () {
|
|
|
|
return this.getHex();
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author mrdoob / http://mrdoob.com/
|
|
* @author philogb / http://blog.thejit.org/
|
|
* @author egraether / http://egraether.com/
|
|
* @author zz85 / http://www.lab4games.net/zz85/blog
|
|
*/
|
|
|
|
function Vector2( x, y ) {
|
|
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
|
|
}
|
|
|
|
Object.defineProperties( Vector2.prototype, {
|
|
|
|
"width" : {
|
|
|
|
get: function () {
|
|
|
|
return this.x;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this.x = value;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"height" : {
|
|
|
|
get: function () {
|
|
|
|
return this.y;
|
|
|
|
},
|
|
|
|
set: function ( value ) {
|
|
|
|
this.y = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
Object.assign( Vector2.prototype, {
|
|
|
|
isVector2: true,
|
|
|
|
set: function ( x, y ) {
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setScalar: function ( scalar ) {
|
|
|
|
this.x = scalar;
|
|
this.y = scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setX: function ( x ) {
|
|
|
|
this.x = x;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setY: function ( y ) {
|
|
|
|
this.y = y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setComponent: function ( index, value ) {
|
|
|
|
switch ( index ) {
|
|
|
|
case 0: this.x = value; break;
|
|
case 1: this.y = value; break;
|
|
default: throw new Error( 'index is out of range: ' + index );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getComponent: function ( index ) {
|
|
|
|
switch ( index ) {
|
|
|
|
case 0: return this.x;
|
|
case 1: return this.y;
|
|
default: throw new Error( 'index is out of range: ' + index );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor( this.x, this.y );
|
|
|
|
},
|
|
|
|
copy: function ( v ) {
|
|
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
add: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
|
|
return this.addVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScalar: function ( s ) {
|
|
|
|
this.x += s;
|
|
this.y += s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addVectors: function ( a, b ) {
|
|
|
|
this.x = a.x + b.x;
|
|
this.y = a.y + b.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScaledVector: function ( v, s ) {
|
|
|
|
this.x += v.x * s;
|
|
this.y += v.y * s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
sub: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
|
|
return this.subVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
subScalar: function ( s ) {
|
|
|
|
this.x -= s;
|
|
this.y -= s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
subVectors: function ( a, b ) {
|
|
|
|
this.x = a.x - b.x;
|
|
this.y = a.y - b.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiply: function ( v ) {
|
|
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyScalar: function ( scalar ) {
|
|
|
|
this.x *= scalar;
|
|
this.y *= scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
divide: function ( v ) {
|
|
|
|
this.x /= v.x;
|
|
this.y /= v.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
divideScalar: function ( scalar ) {
|
|
|
|
return this.multiplyScalar( 1 / scalar );
|
|
|
|
},
|
|
|
|
min: function ( v ) {
|
|
|
|
this.x = Math.min( this.x, v.x );
|
|
this.y = Math.min( this.y, v.y );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
max: function ( v ) {
|
|
|
|
this.x = Math.max( this.x, v.x );
|
|
this.y = Math.max( this.y, v.y );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clamp: function ( min, max ) {
|
|
|
|
// This function assumes min < max, if this assumption isn't true it will not operate correctly
|
|
|
|
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
|
|
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clampScalar: function () {
|
|
|
|
var min, max;
|
|
|
|
return function clampScalar( minVal, maxVal ) {
|
|
|
|
if ( min === undefined ) {
|
|
|
|
min = new Vector2();
|
|
max = new Vector2();
|
|
|
|
}
|
|
|
|
min.set( minVal, minVal );
|
|
max.set( maxVal, maxVal );
|
|
|
|
return this.clamp( min, max );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
clampLength: function ( min, max ) {
|
|
|
|
var length = this.length();
|
|
|
|
return this.multiplyScalar( Math.max( min, Math.min( max, length ) ) / length );
|
|
|
|
},
|
|
|
|
floor: function () {
|
|
|
|
this.x = Math.floor( this.x );
|
|
this.y = Math.floor( this.y );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
ceil: function () {
|
|
|
|
this.x = Math.ceil( this.x );
|
|
this.y = Math.ceil( this.y );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
round: function () {
|
|
|
|
this.x = Math.round( this.x );
|
|
this.y = Math.round( this.y );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
roundToZero: function () {
|
|
|
|
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
|
|
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
negate: function () {
|
|
|
|
this.x = - this.x;
|
|
this.y = - this.y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
dot: function ( v ) {
|
|
|
|
return this.x * v.x + this.y * v.y;
|
|
|
|
},
|
|
|
|
lengthSq: function () {
|
|
|
|
return this.x * this.x + this.y * this.y;
|
|
|
|
},
|
|
|
|
length: function () {
|
|
|
|
return Math.sqrt( this.x * this.x + this.y * this.y );
|
|
|
|
},
|
|
|
|
lengthManhattan: function() {
|
|
|
|
return Math.abs( this.x ) + Math.abs( this.y );
|
|
|
|
},
|
|
|
|
normalize: function () {
|
|
|
|
return this.divideScalar( this.length() );
|
|
|
|
},
|
|
|
|
angle: function () {
|
|
|
|
// computes the angle in radians with respect to the positive x-axis
|
|
|
|
var angle = Math.atan2( this.y, this.x );
|
|
|
|
if ( angle < 0 ) angle += 2 * Math.PI;
|
|
|
|
return angle;
|
|
|
|
},
|
|
|
|
distanceTo: function ( v ) {
|
|
|
|
return Math.sqrt( this.distanceToSquared( v ) );
|
|
|
|
},
|
|
|
|
distanceToSquared: function ( v ) {
|
|
|
|
var dx = this.x - v.x, dy = this.y - v.y;
|
|
return dx * dx + dy * dy;
|
|
|
|
},
|
|
|
|
distanceToManhattan: function ( v ) {
|
|
|
|
return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );
|
|
|
|
},
|
|
|
|
setLength: function ( length ) {
|
|
|
|
return this.multiplyScalar( length / this.length() );
|
|
|
|
},
|
|
|
|
lerp: function ( v, alpha ) {
|
|
|
|
this.x += ( v.x - this.x ) * alpha;
|
|
this.y += ( v.y - this.y ) * alpha;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
lerpVectors: function ( v1, v2, alpha ) {
|
|
|
|
return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
|
|
|
|
},
|
|
|
|
equals: function ( v ) {
|
|
|
|
return ( ( v.x === this.x ) && ( v.y === this.y ) );
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
this.x = array[ offset ];
|
|
this.y = array[ offset + 1 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
array[ offset ] = this.x;
|
|
array[ offset + 1 ] = this.y;
|
|
|
|
return array;
|
|
|
|
},
|
|
|
|
rotateAround: function ( center, angle ) {
|
|
|
|
var c = Math.cos( angle ), s = Math.sin( angle );
|
|
|
|
var x = this.x - center.x;
|
|
var y = this.y - center.y;
|
|
|
|
this.x = x * c - y * s + center.x;
|
|
this.y = x * s + y * c + center.y;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
/**
|
|
* @author supereggbert / http://www.paulbrunt.co.uk/
|
|
* @author philogb / http://blog.thejit.org/
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author egraether / http://egraether.com/
|
|
* @author WestLangley / http://github.com/WestLangley
|
|
*/
|
|
|
|
function Vector4( x, y, z, w ) {
|
|
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
this.w = ( w !== undefined ) ? w : 1;
|
|
|
|
}
|
|
|
|
Object.assign( Vector4.prototype, {
|
|
|
|
isVector4: true,
|
|
|
|
set: function ( x, y, z, w ) {
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setScalar: function ( scalar ) {
|
|
|
|
this.x = scalar;
|
|
this.y = scalar;
|
|
this.z = scalar;
|
|
this.w = scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setX: function ( x ) {
|
|
|
|
this.x = x;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setY: function ( y ) {
|
|
|
|
this.y = y;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setZ: function ( z ) {
|
|
|
|
this.z = z;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setW: function ( w ) {
|
|
|
|
this.w = w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setComponent: function ( index, value ) {
|
|
|
|
switch ( index ) {
|
|
|
|
case 0: this.x = value; break;
|
|
case 1: this.y = value; break;
|
|
case 2: this.z = value; break;
|
|
case 3: this.w = value; break;
|
|
default: throw new Error( 'index is out of range: ' + index );
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
getComponent: function ( index ) {
|
|
|
|
switch ( index ) {
|
|
|
|
case 0: return this.x;
|
|
case 1: return this.y;
|
|
case 2: return this.z;
|
|
case 3: return this.w;
|
|
default: throw new Error( 'index is out of range: ' + index );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
clone: function () {
|
|
|
|
return new this.constructor( this.x, this.y, this.z, this.w );
|
|
|
|
},
|
|
|
|
copy: function ( v ) {
|
|
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = v.z;
|
|
this.w = ( v.w !== undefined ) ? v.w : 1;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
add: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );
|
|
return this.addVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z;
|
|
this.w += v.w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScalar: function ( s ) {
|
|
|
|
this.x += s;
|
|
this.y += s;
|
|
this.z += s;
|
|
this.w += s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addVectors: function ( a, b ) {
|
|
|
|
this.x = a.x + b.x;
|
|
this.y = a.y + b.y;
|
|
this.z = a.z + b.z;
|
|
this.w = a.w + b.w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
addScaledVector: function ( v, s ) {
|
|
|
|
this.x += v.x * s;
|
|
this.y += v.y * s;
|
|
this.z += v.z * s;
|
|
this.w += v.w * s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
sub: function ( v, w ) {
|
|
|
|
if ( w !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );
|
|
return this.subVectors( v, w );
|
|
|
|
}
|
|
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z;
|
|
this.w -= v.w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
subScalar: function ( s ) {
|
|
|
|
this.x -= s;
|
|
this.y -= s;
|
|
this.z -= s;
|
|
this.w -= s;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
subVectors: function ( a, b ) {
|
|
|
|
this.x = a.x - b.x;
|
|
this.y = a.y - b.y;
|
|
this.z = a.z - b.z;
|
|
this.w = a.w - b.w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
multiplyScalar: function ( scalar ) {
|
|
|
|
this.x *= scalar;
|
|
this.y *= scalar;
|
|
this.z *= scalar;
|
|
this.w *= scalar;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
applyMatrix4: function ( m ) {
|
|
|
|
var x = this.x, y = this.y, z = this.z, w = this.w;
|
|
var e = m.elements;
|
|
|
|
this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;
|
|
this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;
|
|
this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;
|
|
this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
divideScalar: function ( scalar ) {
|
|
|
|
return this.multiplyScalar( 1 / scalar );
|
|
|
|
},
|
|
|
|
setAxisAngleFromQuaternion: function ( q ) {
|
|
|
|
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
|
|
|
|
// q is assumed to be normalized
|
|
|
|
this.w = 2 * Math.acos( q.w );
|
|
|
|
var s = Math.sqrt( 1 - q.w * q.w );
|
|
|
|
if ( s < 0.0001 ) {
|
|
|
|
this.x = 1;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
|
|
} else {
|
|
|
|
this.x = q.x / s;
|
|
this.y = q.y / s;
|
|
this.z = q.z / s;
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
setAxisAngleFromRotationMatrix: function ( m ) {
|
|
|
|
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
|
|
|
|
// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
|
|
|
|
var angle, x, y, z, // variables for result
|
|
epsilon = 0.01, // margin to allow for rounding errors
|
|
epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees
|
|
|
|
te = m.elements,
|
|
|
|
m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],
|
|
m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],
|
|
m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];
|
|
|
|
if ( ( Math.abs( m12 - m21 ) < epsilon ) &&
|
|
( Math.abs( m13 - m31 ) < epsilon ) &&
|
|
( Math.abs( m23 - m32 ) < epsilon ) ) {
|
|
|
|
// singularity found
|
|
// first check for identity matrix which must have +1 for all terms
|
|
// in leading diagonal and zero in other terms
|
|
|
|
if ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&
|
|
( Math.abs( m13 + m31 ) < epsilon2 ) &&
|
|
( Math.abs( m23 + m32 ) < epsilon2 ) &&
|
|
( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
|
|
|
|
// this singularity is identity matrix so angle = 0
|
|
|
|
this.set( 1, 0, 0, 0 );
|
|
|
|
return this; // zero angle, arbitrary axis
|
|
|
|
}
|
|
|
|
// otherwise this singularity is angle = 180
|
|
|
|
angle = Math.PI;
|
|
|
|
var xx = ( m11 + 1 ) / 2;
|
|
var yy = ( m22 + 1 ) / 2;
|
|
var zz = ( m33 + 1 ) / 2;
|
|
var xy = ( m12 + m21 ) / 4;
|
|
var xz = ( m13 + m31 ) / 4;
|
|
var yz = ( m23 + m32 ) / 4;
|
|
|
|
if ( ( xx > yy ) && ( xx > zz ) ) {
|
|
|
|
// m11 is the largest diagonal term
|
|
|
|
if ( xx < epsilon ) {
|
|
|
|
x = 0;
|
|
y = 0.707106781;
|
|
z = 0.707106781;
|
|
|
|
} else {
|
|
|
|
x = Math.sqrt( xx );
|
|
y = xy / x;
|
|
z = xz / x;
|
|
|
|
}
|
|
|
|
} else if ( yy > zz ) {
|
|
|
|
// m22 is the largest diagonal term
|
|
|
|
if ( yy < epsilon ) {
|
|
|
|
x = 0.707106781;
|
|
y = 0;
|
|
z = 0.707106781;
|
|
|
|
} else {
|
|
|
|
y = Math.sqrt( yy );
|
|
x = xy / y;
|
|
z = yz / y;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// m33 is the largest diagonal term so base result on this
|
|
|
|
if ( zz < epsilon ) {
|
|
|
|
x = 0.707106781;
|
|
y = 0.707106781;
|
|
z = 0;
|
|
|
|
} else {
|
|
|
|
z = Math.sqrt( zz );
|
|
x = xz / z;
|
|
y = yz / z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.set( x, y, z, angle );
|
|
|
|
return this; // return 180 deg rotation
|
|
|
|
}
|
|
|
|
// as we have reached here there are no singularities so we can handle normally
|
|
|
|
var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
|
|
( m13 - m31 ) * ( m13 - m31 ) +
|
|
( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
|
|
|
|
if ( Math.abs( s ) < 0.001 ) s = 1;
|
|
|
|
// prevent divide by zero, should not happen if matrix is orthogonal and should be
|
|
// caught by singularity test above, but I've left it in just in case
|
|
|
|
this.x = ( m32 - m23 ) / s;
|
|
this.y = ( m13 - m31 ) / s;
|
|
this.z = ( m21 - m12 ) / s;
|
|
this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
min: function ( v ) {
|
|
|
|
this.x = Math.min( this.x, v.x );
|
|
this.y = Math.min( this.y, v.y );
|
|
this.z = Math.min( this.z, v.z );
|
|
this.w = Math.min( this.w, v.w );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
max: function ( v ) {
|
|
|
|
this.x = Math.max( this.x, v.x );
|
|
this.y = Math.max( this.y, v.y );
|
|
this.z = Math.max( this.z, v.z );
|
|
this.w = Math.max( this.w, v.w );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clamp: function ( min, max ) {
|
|
|
|
// This function assumes min < max, if this assumption isn't true it will not operate correctly
|
|
|
|
this.x = Math.max( min.x, Math.min( max.x, this.x ) );
|
|
this.y = Math.max( min.y, Math.min( max.y, this.y ) );
|
|
this.z = Math.max( min.z, Math.min( max.z, this.z ) );
|
|
this.w = Math.max( min.w, Math.min( max.w, this.w ) );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
clampScalar: function () {
|
|
|
|
var min = new Vector4();
|
|
var max = new Vector4();
|
|
|
|
return function clampScalar( minVal, maxVal ) {
|
|
|
|
min.set( minVal, minVal, minVal, minVal );
|
|
max.set( maxVal, maxVal, maxVal, maxVal );
|
|
|
|
return this.clamp( min, max );
|
|
|
|
};
|
|
|
|
}(),
|
|
|
|
floor: function () {
|
|
|
|
this.x = Math.floor( this.x );
|
|
this.y = Math.floor( this.y );
|
|
this.z = Math.floor( this.z );
|
|
this.w = Math.floor( this.w );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
ceil: function () {
|
|
|
|
this.x = Math.ceil( this.x );
|
|
this.y = Math.ceil( this.y );
|
|
this.z = Math.ceil( this.z );
|
|
this.w = Math.ceil( this.w );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
round: function () {
|
|
|
|
this.x = Math.round( this.x );
|
|
this.y = Math.round( this.y );
|
|
this.z = Math.round( this.z );
|
|
this.w = Math.round( this.w );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
roundToZero: function () {
|
|
|
|
this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );
|
|
this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );
|
|
this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );
|
|
this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
negate: function () {
|
|
|
|
this.x = - this.x;
|
|
this.y = - this.y;
|
|
this.z = - this.z;
|
|
this.w = - this.w;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
dot: function ( v ) {
|
|
|
|
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
|
|
|
|
},
|
|
|
|
lengthSq: function () {
|
|
|
|
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 );
|
|
|
|
},
|
|
|
|
lengthManhattan: function () {
|
|
|
|
return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
|
|
|
|
},
|
|
|
|
normalize: function () {
|
|
|
|
return this.divideScalar( this.length() );
|
|
|
|
},
|
|
|
|
setLength: function ( length ) {
|
|
|
|
return this.multiplyScalar( length / this.length() );
|
|
|
|
},
|
|
|
|
lerp: function ( v, alpha ) {
|
|
|
|
this.x += ( v.x - this.x ) * alpha;
|
|
this.y += ( v.y - this.y ) * alpha;
|
|
this.z += ( v.z - this.z ) * alpha;
|
|
this.w += ( v.w - this.w ) * alpha;
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
lerpVectors: function ( v1, v2, alpha ) {
|
|
|
|
return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );
|
|
|
|
},
|
|
|
|
equals: function ( v ) {
|
|
|
|
return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );
|
|
|
|
},
|
|
|
|
fromArray: function ( array, offset ) {
|
|
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
this.x = array[ offset ];
|
|
this.y = array[ offset + 1 ];
|
|
this.z = array[ offset + 2 ];
|
|
this.w = array[ offset + 3 ];
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
toArray: function ( array, offset ) {
|
|
|
|
if ( array === undefined ) array = [];
|
|
if ( offset === undefined ) offset = 0;
|
|
|
|
array[ offset ] = this.x;
|
|
array[ offset + 1 ] = this.y;
|
|
array[ offset + 2 ] = this.z;
|
|
array[ offset + 3 ] = this.w;
|
|
|
|
return array;
|
|
|
|
},
|
|
|
|
fromBufferAttribute: function ( attribute, index, offset ) {
|
|
|
|
if ( offset !== undefined ) {
|
|
|
|
console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );
|
|
|
|
}
|
|
|
|
this.x = attribute.getX( index );
|
|
this.y = attribute.getY( index );
|
|
this.z = attribute.getZ( index );
|
|
this.w = attribute.getW( index );
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
if(global.realThree) {
|
|
module.exports = require('three/three.min.js');
|
|
}
|
|
else {
|
|
module.exports.Object3D = Object3D;
|
|
module.exports.Layers = Layers;
|
|
module.exports.EventDispatcher = EventDispatcher;
|
|
module.exports.Color = Color;
|
|
module.exports.Euler = Euler;
|
|
module.exports.Math = _Math;
|
|
module.exports.Matrix3 = Matrix3;
|
|
module.exports.Matrix4 = Matrix4;
|
|
module.exports.Quaternion = Quaternion;
|
|
module.exports.Vector2 = Vector2;
|
|
module.exports.Vector3 = Vector3;
|
|
module.exports.Vector4 = Vector4;
|
|
}
|
|
|
|
})));
|