three
Version:
JavaScript 3D library
259 lines (161 loc) • 5.26 kB
JavaScript
const _lut = [];
for ( let i = 0; i < 256; i ++ ) {
_lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
}
let _seed = 1234567;
const DEG2RAD = Math.PI / 180;
const RAD2DEG = 180 / Math.PI;
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
function generateUUID() {
const d0 = Math.random() * 0xffffffff | 0;
const d1 = Math.random() * 0xffffffff | 0;
const d2 = Math.random() * 0xffffffff | 0;
const d3 = Math.random() * 0xffffffff | 0;
const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
// .toUpperCase() here flattens concatenated strings to save heap memory space.
return uuid.toUpperCase();
}
function clamp( value, min, max ) {
return Math.max( min, Math.min( max, value ) );
}
// compute euclidian modulo of m % n
// https://en.wikipedia.org/wiki/Modulo_operation
function euclideanModulo( n, m ) {
return ( ( n % m ) + m ) % m;
}
// Linear mapping from range <a1, a2> to range <b1, b2>
function mapLinear( x, a1, a2, b1, b2 ) {
return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
}
// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
function inverseLerp( x, y, value ) {
if ( x !== y ) {
return ( value - x ) / ( y - x );
} else {
return 0;
}
}
// https://en.wikipedia.org/wiki/Linear_interpolation
function lerp( x, y, t ) {
return ( 1 - t ) * x + t * y;
}
// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
function damp( x, y, lambda, dt ) {
return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
}
// https://www.desmos.com/calculator/vcsjnyz7x4
function pingpong( x, length = 1 ) {
return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
}
// http://en.wikipedia.org/wiki/Smoothstep
function smoothstep( x, min, max ) {
if ( x <= min ) return 0;
if ( x >= max ) return 1;
x = ( x - min ) / ( max - min );
return x * x * ( 3 - 2 * x );
}
function smootherstep( 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
function randInt( low, high ) {
return low + Math.floor( Math.random() * ( high - low + 1 ) );
}
// Random float from <low, high> interval
function randFloat( low, high ) {
return low + Math.random() * ( high - low );
}
// Random float from <-range/2, range/2> interval
function randFloatSpread( range ) {
return range * ( 0.5 - Math.random() );
}
// Deterministic pseudo-random float in the interval [ 0, 1 ]
function seededRandom( s ) {
if ( s !== undefined ) _seed = s % 2147483647;
// Park-Miller algorithm
_seed = _seed * 16807 % 2147483647;
return ( _seed - 1 ) / 2147483646;
}
function degToRad( degrees ) {
return degrees * DEG2RAD;
}
function radToDeg( radians ) {
return radians * RAD2DEG;
}
function isPowerOfTwo( value ) {
return ( value & ( value - 1 ) ) === 0 && value !== 0;
}
function ceilPowerOfTwo( value ) {
return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
}
function floorPowerOfTwo( value ) {
return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
}
function setQuaternionFromProperEuler( q, a, b, c, order ) {
// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
// rotations are applied to the axes in the order specified by 'order'
// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
// angles are in radians
const cos = Math.cos;
const sin = Math.sin;
const c2 = cos( b / 2 );
const s2 = sin( b / 2 );
const c13 = cos( ( a + c ) / 2 );
const s13 = sin( ( a + c ) / 2 );
const c1_3 = cos( ( a - c ) / 2 );
const s1_3 = sin( ( a - c ) / 2 );
const c3_1 = cos( ( c - a ) / 2 );
const s3_1 = sin( ( c - a ) / 2 );
switch ( order ) {
case 'XYX':
q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
break;
case 'YZY':
q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
break;
case 'ZXZ':
q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
break;
case 'XZX':
q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
break;
case 'YXY':
q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
break;
case 'ZYZ':
q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
break;
default:
console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
}
}
export {
DEG2RAD,
RAD2DEG,
generateUUID,
clamp,
euclideanModulo,
mapLinear,
inverseLerp,
lerp,
damp,
pingpong,
smoothstep,
smootherstep,
randInt,
randFloat,
randFloatSpread,
seededRandom,
degToRad,
radToDeg,
isPowerOfTwo,
ceilPowerOfTwo,
floorPowerOfTwo,
setQuaternionFromProperEuler,
};