MathUtils.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. const _lut = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff' ];
  2. let _seed = 1234567;
  3. const DEG2RAD = Math.PI / 180;
  4. const RAD2DEG = 180 / Math.PI;
  5. // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
  6. function generateUUID() {
  7. const d0 = Math.random() * 0xffffffff | 0;
  8. const d1 = Math.random() * 0xffffffff | 0;
  9. const d2 = Math.random() * 0xffffffff | 0;
  10. const d3 = Math.random() * 0xffffffff | 0;
  11. const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +
  12. _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +
  13. _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
  14. _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
  15. // .toLowerCase() here flattens concatenated strings to save heap memory space.
  16. return uuid.toLowerCase();
  17. }
  18. function clamp( value, min, max ) {
  19. return Math.max( min, Math.min( max, value ) );
  20. }
  21. // compute euclidean modulo of m % n
  22. // https://en.wikipedia.org/wiki/Modulo_operation
  23. function euclideanModulo( n, m ) {
  24. return ( ( n % m ) + m ) % m;
  25. }
  26. // Linear mapping from range <a1, a2> to range <b1, b2>
  27. function mapLinear( x, a1, a2, b1, b2 ) {
  28. return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
  29. }
  30. // https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/
  31. function inverseLerp( x, y, value ) {
  32. if ( x !== y ) {
  33. return ( value - x ) / ( y - x );
  34. } else {
  35. return 0;
  36. }
  37. }
  38. // https://en.wikipedia.org/wiki/Linear_interpolation
  39. function lerp( x, y, t ) {
  40. return ( 1 - t ) * x + t * y;
  41. }
  42. // http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/
  43. function damp( x, y, lambda, dt ) {
  44. return lerp( x, y, 1 - Math.exp( - lambda * dt ) );
  45. }
  46. // https://www.desmos.com/calculator/vcsjnyz7x4
  47. function pingpong( x, length = 1 ) {
  48. return length - Math.abs( euclideanModulo( x, length * 2 ) - length );
  49. }
  50. // http://en.wikipedia.org/wiki/Smoothstep
  51. function smoothstep( x, min, max ) {
  52. if ( x <= min ) return 0;
  53. if ( x >= max ) return 1;
  54. x = ( x - min ) / ( max - min );
  55. return x * x * ( 3 - 2 * x );
  56. }
  57. function smootherstep( x, min, max ) {
  58. if ( x <= min ) return 0;
  59. if ( x >= max ) return 1;
  60. x = ( x - min ) / ( max - min );
  61. return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
  62. }
  63. // Random integer from <low, high> interval
  64. function randInt( low, high ) {
  65. return low + Math.floor( Math.random() * ( high - low + 1 ) );
  66. }
  67. // Random float from <low, high> interval
  68. function randFloat( low, high ) {
  69. return low + Math.random() * ( high - low );
  70. }
  71. // Random float from <-range/2, range/2> interval
  72. function randFloatSpread( range ) {
  73. return range * ( 0.5 - Math.random() );
  74. }
  75. // Deterministic pseudo-random float in the interval [ 0, 1 ]
  76. function seededRandom( s ) {
  77. if ( s !== undefined ) _seed = s;
  78. // Mulberry32 generator
  79. let t = _seed += 0x6D2B79F5;
  80. t = Math.imul( t ^ t >>> 15, t | 1 );
  81. t ^= t + Math.imul( t ^ t >>> 7, t | 61 );
  82. return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296;
  83. }
  84. function degToRad( degrees ) {
  85. return degrees * DEG2RAD;
  86. }
  87. function radToDeg( radians ) {
  88. return radians * RAD2DEG;
  89. }
  90. function isPowerOfTwo( value ) {
  91. return ( value & ( value - 1 ) ) === 0 && value !== 0;
  92. }
  93. function ceilPowerOfTwo( value ) {
  94. return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );
  95. }
  96. function floorPowerOfTwo( value ) {
  97. return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );
  98. }
  99. function setQuaternionFromProperEuler( q, a, b, c, order ) {
  100. // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles
  101. // rotations are applied to the axes in the order specified by 'order'
  102. // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'
  103. // angles are in radians
  104. const cos = Math.cos;
  105. const sin = Math.sin;
  106. const c2 = cos( b / 2 );
  107. const s2 = sin( b / 2 );
  108. const c13 = cos( ( a + c ) / 2 );
  109. const s13 = sin( ( a + c ) / 2 );
  110. const c1_3 = cos( ( a - c ) / 2 );
  111. const s1_3 = sin( ( a - c ) / 2 );
  112. const c3_1 = cos( ( c - a ) / 2 );
  113. const s3_1 = sin( ( c - a ) / 2 );
  114. switch ( order ) {
  115. case 'XYX':
  116. q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
  117. break;
  118. case 'YZY':
  119. q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
  120. break;
  121. case 'ZXZ':
  122. q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
  123. break;
  124. case 'XZX':
  125. q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
  126. break;
  127. case 'YXY':
  128. q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
  129. break;
  130. case 'ZYZ':
  131. q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
  132. break;
  133. default:
  134. console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
  135. }
  136. }
  137. function denormalize( value, array ) {
  138. switch ( array.constructor ) {
  139. case Float32Array:
  140. return value;
  141. case Uint32Array:
  142. return value / 4294967295.0;
  143. case Uint16Array:
  144. return value / 65535.0;
  145. case Uint8Array:
  146. return value / 255.0;
  147. case Int32Array:
  148. return Math.max( value / 2147483647.0, - 1.0 );
  149. case Int16Array:
  150. return Math.max( value / 32767.0, - 1.0 );
  151. case Int8Array:
  152. return Math.max( value / 127.0, - 1.0 );
  153. default:
  154. throw new Error( 'Invalid component type.' );
  155. }
  156. }
  157. function normalize( value, array ) {
  158. switch ( array.constructor ) {
  159. case Float32Array:
  160. return value;
  161. case Uint32Array:
  162. return Math.round( value * 4294967295.0 );
  163. case Uint16Array:
  164. return Math.round( value * 65535.0 );
  165. case Uint8Array:
  166. return Math.round( value * 255.0 );
  167. case Int32Array:
  168. return Math.round( value * 2147483647.0 );
  169. case Int16Array:
  170. return Math.round( value * 32767.0 );
  171. case Int8Array:
  172. return Math.round( value * 127.0 );
  173. default:
  174. throw new Error( 'Invalid component type.' );
  175. }
  176. }
  177. const MathUtils = {
  178. DEG2RAD: DEG2RAD,
  179. RAD2DEG: RAD2DEG,
  180. generateUUID: generateUUID,
  181. clamp: clamp,
  182. euclideanModulo: euclideanModulo,
  183. mapLinear: mapLinear,
  184. inverseLerp: inverseLerp,
  185. lerp: lerp,
  186. damp: damp,
  187. pingpong: pingpong,
  188. smoothstep: smoothstep,
  189. smootherstep: smootherstep,
  190. randInt: randInt,
  191. randFloat: randFloat,
  192. randFloatSpread: randFloatSpread,
  193. seededRandom: seededRandom,
  194. degToRad: degToRad,
  195. radToDeg: radToDeg,
  196. isPowerOfTwo: isPowerOfTwo,
  197. ceilPowerOfTwo: ceilPowerOfTwo,
  198. floorPowerOfTwo: floorPowerOfTwo,
  199. setQuaternionFromProperEuler: setQuaternionFromProperEuler,
  200. normalize: normalize,
  201. denormalize: denormalize
  202. };
  203. export {
  204. DEG2RAD,
  205. RAD2DEG,
  206. generateUUID,
  207. clamp,
  208. euclideanModulo,
  209. mapLinear,
  210. inverseLerp,
  211. lerp,
  212. damp,
  213. pingpong,
  214. smoothstep,
  215. smootherstep,
  216. randInt,
  217. randFloat,
  218. randFloatSpread,
  219. seededRandom,
  220. degToRad,
  221. radToDeg,
  222. isPowerOfTwo,
  223. ceilPowerOfTwo,
  224. floorPowerOfTwo,
  225. setQuaternionFromProperEuler,
  226. normalize,
  227. denormalize,
  228. MathUtils
  229. };