MathUtils.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. const _lut = [];
  2. for ( let i = 0; i < 256; i ++ ) {
  3. _lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );
  4. }
  5. let _seed = 1234567;
  6. const MathUtils = {
  7. DEG2RAD: Math.PI / 180,
  8. RAD2DEG: 180 / Math.PI,
  9. generateUUID: function () {
  10. // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
  11. const d0 = Math.random() * 0xffffffff | 0;
  12. const d1 = Math.random() * 0xffffffff | 0;
  13. const d2 = Math.random() * 0xffffffff | 0;
  14. const d3 = Math.random() * 0xffffffff | 0;
  15. const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
  16. _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
  17. _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
  18. _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
  19. // .toUpperCase() here flattens concatenated strings to save heap memory space.
  20. return uuid.toUpperCase();
  21. },
  22. clamp: function ( value, min, max ) {
  23. return Math.max( min, Math.min( max, value ) );
  24. },
  25. // compute euclidian modulo of m % n
  26. // https://en.wikipedia.org/wiki/Modulo_operation
  27. euclideanModulo: function ( n, m ) {
  28. return ( ( n % m ) + m ) % m;
  29. },
  30. // Linear mapping from range <a1, a2> to range <b1, b2>
  31. mapLinear: function ( x, a1, a2, b1, b2 ) {
  32. return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
  33. },
  34. // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
  35. inverseLerp: function ( x, y, value ) {
  36. if ( x !== y ) {
  37. return ( value - x ) / ( y - x );
  38. } else {
  39. return 0;
  40. }
  41. },
  42. // https://en.wikipedia.org/wiki/Linear_interpolation
  43. lerp: function ( x, y, t ) {
  44. return ( 1 - t ) * x + t * y;
  45. },
  46. // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
  47. damp: function ( x, y, lambda, dt ) {
  48. return MathUtils.lerp( x, y, 1 - Math.exp( - lambda * dt ) );
  49. },
  50. // https://www.desmos.com/calculator/vcsjnyz7x4
  51. pingpong: function ( x, length = 1 ) {
  52. return length - Math.abs( MathUtils.euclideanModulo( x, length * 2 ) - length );
  53. },
  54. // http://en.wikipedia.org/wiki/Smoothstep
  55. smoothstep: function ( x, min, max ) {
  56. if ( x <= min ) return 0;
  57. if ( x >= max ) return 1;
  58. x = ( x - min ) / ( max - min );
  59. return x * x * ( 3 - 2 * x );
  60. },
  61. smootherstep: function ( x, min, max ) {
  62. if ( x <= min ) return 0;
  63. if ( x >= max ) return 1;
  64. x = ( x - min ) / ( max - min );
  65. return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
  66. },
  67. // Random integer from <low, high> interval
  68. randInt: function ( low, high ) {
  69. return low + Math.floor( Math.random() * ( high - low + 1 ) );
  70. },
  71. // Random float from <low, high> interval
  72. randFloat: function ( low, high ) {
  73. return low + Math.random() * ( high - low );
  74. },
  75. // Random float from <-range/2, range/2> interval
  76. randFloatSpread: function ( range ) {
  77. return range * ( 0.5 - Math.random() );
  78. },
  79. // Deterministic pseudo-random float in the interval [ 0, 1 ]
  80. seededRandom: function ( s ) {
  81. if ( s !== undefined ) _seed = s % 2147483647;
  82. // Park-Miller algorithm
  83. _seed = _seed * 16807 % 2147483647;
  84. return ( _seed - 1 ) / 2147483646;
  85. },
  86. degToRad: function ( degrees ) {
  87. return degrees * MathUtils.DEG2RAD;
  88. },
  89. radToDeg: function ( radians ) {
  90. return radians * MathUtils.RAD2DEG;
  91. },
  92. isPowerOfTwo: function ( value ) {
  93. return ( value & ( value - 1 ) ) === 0 && value !== 0;
  94. },
  95. ceilPowerOfTwo: function ( value ) {
  96. return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
  97. },
  98. floorPowerOfTwo: function ( value ) {
  99. return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
  100. },
  101. setQuaternionFromProperEuler: function ( q, a, b, c, order ) {
  102. // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
  103. // rotations are applied to the axes in the order specified by 'order'
  104. // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
  105. // angles are in radians
  106. const cos = Math.cos;
  107. const sin = Math.sin;
  108. const c2 = cos( b / 2 );
  109. const s2 = sin( b / 2 );
  110. const c13 = cos( ( a + c ) / 2 );
  111. const s13 = sin( ( a + c ) / 2 );
  112. const c1_3 = cos( ( a - c ) / 2 );
  113. const s1_3 = sin( ( a - c ) / 2 );
  114. const c3_1 = cos( ( c - a ) / 2 );
  115. const s3_1 = sin( ( c - a ) / 2 );
  116. switch ( order ) {
  117. case 'XYX':
  118. q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
  119. break;
  120. case 'YZY':
  121. q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
  122. break;
  123. case 'ZXZ':
  124. q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
  125. break;
  126. case 'XZX':
  127. q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
  128. break;
  129. case 'YXY':
  130. q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
  131. break;
  132. case 'ZYZ':
  133. q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
  134. break;
  135. default:
  136. console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
  137. }
  138. }
  139. };
  140. export { MathUtils };
粤ICP备19079148号