@woosh/meep-engine 2.37.17 → 2.37.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/core/assert.js +1 -1
  2. package/core/binary/float2uint8.js +8 -0
  3. package/core/binary/uint82float.js +8 -0
  4. package/core/bvh2/bvh3/ExplicitBinaryBoundingVolumeHierarchy.js +6 -4
  5. package/core/collection/array/typed/isTypedArray.js +20 -0
  6. package/core/collection/array/typedArrayToDataType.js +1 -0
  7. package/core/collection/list/List.d.ts +1 -1
  8. package/core/collection/table/RowFirstTable.js +34 -0
  9. package/core/collection/table/RowFirstTable.spec.js +59 -1
  10. package/core/color/Color.js +83 -1
  11. package/core/color/YCbCr_to_rgb_uint24.js +3 -4
  12. package/core/color/hsv2rgb.js +4 -3
  13. package/core/color/linear_to_sRGB.js +4 -5
  14. package/core/color/rgb2hex.js +1 -1
  15. package/core/color/rgb2uint24.js +6 -4
  16. package/core/color/rgb_to_YCbCr_uint24.js +11 -13
  17. package/core/events/signal/Signal.d.ts +11 -9
  18. package/core/events/signal/Signal.js +8 -8
  19. package/core/events/signal/Signal.spec.js +16 -0
  20. package/core/geom/2d/quad-tree/qt_collect_by_circle.js +67 -0
  21. package/core/geom/Quaternion.d.ts +21 -1
  22. package/core/geom/Quaternion.js +279 -200
  23. package/core/geom/Quaternion.spec.js +71 -2
  24. package/core/geom/Vector2.js +3 -3
  25. package/core/geom/Vector3.d.ts +2 -0
  26. package/core/geom/Vector3.js +31 -7
  27. package/core/geom/Vector3.schema.json +16 -0
  28. package/core/geom/Vector4.js +16 -0
  29. package/core/json/JsonUtils.js +2 -20
  30. package/core/math/bell_membership_function.js +19 -0
  31. package/core/math/exp2.js +8 -0
  32. package/core/math/interval/NumericInterval.js +17 -0
  33. package/core/math/physics/brdf/brdf_burley.js +25 -0
  34. package/core/math/physics/bsdf/bsdf_schlick.js +22 -0
  35. package/core/math/physics/irradiance/interpolate_irradiance_linear.js +18 -0
  36. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundLogarithmic.js → core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js} +2 -2
  37. package/{engine/sound/ecs/emitter/attenuate/attenuateSoundSmith.js → core/math/physics/irradiance/interpolate_irradiance_smith.js} +1 -1
  38. package/core/model/ObservedEnum.js +8 -0
  39. package/editor/Editor.js +97 -1
  40. package/editor/actions/concrete/ModifyPatchSampler2DAction.js +118 -0
  41. package/editor/actions/concrete/ModifyPatchSampler2DAction.spec.js +30 -0
  42. package/editor/actions/concrete/PatchTerrainHeightAction.js +13 -105
  43. package/editor/ecs/component/FieldDescriptor.js +34 -0
  44. package/editor/ecs/component/FieldValueAdapter.js +20 -0
  45. package/editor/ecs/component/TypeEditor.js +33 -0
  46. package/editor/ecs/component/TypeSchema.d.ts +38 -0
  47. package/editor/ecs/component/createFieldEditor.js +90 -0
  48. package/editor/ecs/component/createObjectEditor.js +266 -60
  49. package/editor/ecs/component/editors/ColorEditor.js +39 -0
  50. package/editor/ecs/component/editors/HTMLElementEditor.js +17 -0
  51. package/editor/ecs/component/editors/ImagePathEditor.js +50 -0
  52. package/editor/ecs/component/editors/NumericIntervalEditor.js +86 -0
  53. package/editor/ecs/component/editors/ObservedBooleanEditor.js +13 -0
  54. package/editor/ecs/component/editors/ObservedEnumEditor.js +32 -0
  55. package/editor/ecs/component/editors/ObservedIntegerEditor.js +43 -0
  56. package/editor/ecs/component/editors/ObservedStringEditor.js +51 -0
  57. package/editor/ecs/component/editors/Sampler2DEditor.js +107 -0
  58. package/editor/ecs/component/editors/collection/ListEditor.js +83 -0
  59. package/editor/ecs/component/editors/common/BitFlagsEditor.js +80 -0
  60. package/editor/ecs/component/editors/common/EnumEditor.js +41 -0
  61. package/editor/ecs/component/editors/common/makeV3_editor.js +85 -0
  62. package/editor/ecs/component/editors/common/noEditor.js +9 -0
  63. package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +17 -0
  64. package/editor/ecs/component/editors/ecs/MinimapMarkerEditor.js +16 -0
  65. package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +44 -0
  66. package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -0
  67. package/editor/ecs/component/editors/ecs/ParticleEmitterEditor.js +58 -0
  68. package/editor/ecs/component/editors/ecs/ParticleEmitterLayerEditor.js +54 -0
  69. package/editor/ecs/component/editors/ecs/SimulationStepDefinitionEditor.js +21 -0
  70. package/editor/ecs/component/editors/ecs/Trail2DEditor.js +33 -0
  71. package/editor/ecs/component/editors/ecs/TransformEditor.js +23 -0
  72. package/editor/ecs/component/editors/ecs/terrain/SplatMappingEditor.js +21 -0
  73. package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +89 -0
  74. package/editor/ecs/component/editors/ecs/terrain/TerrainLayerEditor.js +18 -0
  75. package/editor/ecs/component/editors/ecs/terrain/TerrainLayersEditor.js +22 -0
  76. package/editor/ecs/component/editors/ecs/terrain/TerrainOverlayEditor.js +20 -0
  77. package/editor/ecs/component/editors/geom/QuaternionEditor.js +56 -0
  78. package/editor/ecs/component/editors/geom/Vector1Editor.js +57 -0
  79. package/editor/ecs/component/editors/geom/Vector2Editor.js +11 -0
  80. package/editor/ecs/component/editors/geom/Vector3Editor.js +13 -0
  81. package/editor/ecs/component/editors/geom/Vector4Editor.js +12 -0
  82. package/editor/ecs/component/editors/primitive/ArrayEditor.js +46 -0
  83. package/editor/ecs/component/editors/primitive/BooleanEditor.js +27 -0
  84. package/editor/ecs/component/editors/primitive/FunctionEditor.js +29 -0
  85. package/editor/ecs/component/editors/primitive/NumberEditor.js +60 -0
  86. package/editor/ecs/component/editors/primitive/ObjectEditor.js +12 -0
  87. package/editor/ecs/component/editors/primitive/StringEditor.js +31 -0
  88. package/editor/ecs/component/editors/three/BufferGeometryEditor.js +28 -0
  89. package/editor/ecs/component/editors/three/MaterialEditor.js +27 -0
  90. package/editor/ecs/component/editors/three/MeshEditor.js +35 -0
  91. package/editor/ecs/component/editors/three/TextureEditor.js +32 -0
  92. package/editor/ecs/component/findNearestRegisteredType.js +59 -0
  93. package/editor/ecs/component/prototypeObjectEditor.js +379 -0
  94. package/editor/tools/SelectionTool.js +1 -1
  95. package/editor/tools/paint/TerrainHeightPaintTool.js +88 -68
  96. package/editor/tools/paint/TerrainPaintTool.js +2 -1
  97. package/editor/tools/paint/TerrainTexturePaintTool.js +8 -73
  98. package/editor/view/EditorView.js +1 -1
  99. package/editor/view/ecs/ComponentControlView.js +2 -30
  100. package/editor/view/ecs/EntityEditor.js +61 -139
  101. package/editor/view/ecs/components/GridObstacleController.js +4 -4
  102. package/editor/view/ecs/components/TerrainController.js +1 -1
  103. package/editor/view/ecs/components/common/NumberController.js +19 -7
  104. package/engine/animation/keyed2/AnimationTrack.js +1 -1
  105. package/engine/asset/AssetManager.d.ts +1 -1
  106. package/engine/asset/AssetManager.js +390 -388
  107. package/engine/asset/loaders/gltf/extensions/MSFT_texture_dds.js +14 -2
  108. package/engine/ecs/components/TagEditor.js +15 -0
  109. package/engine/ecs/fow/FogOfWarEditor.js +13 -0
  110. package/engine/ecs/terrain/ecs/OffsetScaleTransform2D.d.ts +6 -0
  111. package/engine/ecs/terrain/ecs/Terrain.js +44 -43
  112. package/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
  113. package/engine/ecs/terrain/ecs/layers/TerrainLayer.js +1 -1
  114. package/engine/ecs/terrain/ecs/splat/SplatMapping.js +26 -28
  115. package/engine/ecs/terrain/overlay/TerrainOverlay.js +71 -66
  116. package/engine/ecs/terrain/tiles/TerrainTileManager.js +23 -0
  117. package/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +1 -1
  118. package/engine/ecs/terrain/util/paintTerrainOverlayViaLookupTable.js +13 -7
  119. package/engine/ecs/transform/Transform.d.ts +2 -0
  120. package/engine/ecs/transform/Transform.editor.schema.json +16 -0
  121. package/engine/ecs/transform/Transform.js +3 -0
  122. package/engine/graphics/ecs/highlight/HighlightEditor.js +17 -0
  123. package/engine/graphics/ecs/light/Light.js +0 -47
  124. package/engine/graphics/ecs/light/LightSerializationAdapter.js +50 -0
  125. package/engine/graphics/ecs/mesh/MeshEditor.js +28 -0
  126. package/engine/graphics/ecs/mesh-v2/DrawMode.js +2 -1
  127. package/engine/graphics/ecs/mesh-v2/aggregate/prototypeSGMesh.js +3 -3
  128. package/engine/graphics/ecs/mesh-v2/build_three_object.js +3 -1
  129. package/engine/graphics/ecs/sprite/Sprite.js +11 -0
  130. package/engine/graphics/ecs/sprite/SpriteSystemPE.js +133 -0
  131. package/engine/graphics/ecs/sprite/prototypeSpriteSystem.js +1566 -0
  132. package/engine/graphics/micron/prototypeVirtualGeometry.js +2 -2
  133. package/engine/graphics/micron/render/instanced/shader/shader_rewrite_standard.js +15 -15
  134. package/engine/graphics/particles/particular/engine/ParticularEngine.js +5 -0
  135. package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +17 -9
  136. package/engine/graphics/particles/particular/engine/renderers/ParticleRenderer.js +12 -10
  137. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +7 -2
  138. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticlePool.js +27 -0
  139. package/engine/graphics/particles/particular/engine/renderers/billboard/SoftBillboardParticleRenderer.js +80 -0
  140. package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +16 -4
  141. package/engine/graphics/shaders/TerrainShader.js +8 -8
  142. package/engine/graphics/texture/atlas/TextureAtlasDebugger.js +2 -1
  143. package/engine/graphics/texture/sampler/Sampler2D.js +206 -201
  144. package/engine/graphics/texture/sampler/Sampler2D.spec.js +34 -35
  145. package/engine/graphics/texture/sampler/bicubic.js +59 -0
  146. package/engine/graphics/texture/sampler/downsampleSample2D.spec.js +2 -2
  147. package/engine/graphics/texture/sampler/genericResampleSampler2D.js +0 -2
  148. package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +146 -0
  149. package/engine/graphics/texture/sampler/{downsampleSampler2D.js → sampler2D_scale_down_linear.js} +8 -4
  150. package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +140 -0
  151. package/engine/graphics/texture/sampler/scaleSampler2D.js +3 -3
  152. package/engine/graphics/texture/sampler/writeSampler2DDataToDataTexture.js +1 -1
  153. package/engine/graphics/util/ScaleObject3ToBox.js +14 -1
  154. package/engine/graphics/util/makeMeshPreviewScene.js +2 -1
  155. package/engine/grid/components/GridObstacle.js +0 -44
  156. package/engine/grid/components/GridObstacleSerializationAdapter.js +46 -0
  157. package/engine/input/ecs/util/TerrainCameraTargetSampler.js +2 -2
  158. package/engine/navigation/ecs/components/Path.d.ts +2 -0
  159. package/engine/navigation/ecs/components/Path.js +6 -1
  160. package/engine/navigation/ecs/components/computeNonuniformCatmullRomSplineSample.js +117 -0
  161. package/engine/platform/GetURLHash.js +27 -0
  162. package/engine/platform/WebEnginePlatform.js +1 -22
  163. package/engine/sound/ecs/emitter/SoundEmitter.js +10 -6
  164. package/generation/GridGenerator.js +7 -6
  165. package/generation/example/SampleGenerator0.js +39 -35
  166. package/generation/example/filters/SampleGroundMoistureFilter.js +58 -17
  167. package/generation/example/generators/interactive/mir_generator_place_buff_objects.js +7 -6
  168. package/generation/example/generators/mir_generator_place_bases.js +7 -3
  169. package/generation/example/generators/mir_generator_place_road_decorators.js +3 -3
  170. package/generation/example/generators/mir_generator_place_starting_point.js +3 -2
  171. package/generation/example/themes/SampleTheme0.js +11 -7
  172. package/generation/filtering/numeric/CellFilterLiteralFloat.js +5 -0
  173. package/generation/filtering/numeric/complex/CellFilterDilate.js +36 -0
  174. package/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +15 -5
  175. package/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +53 -1
  176. package/generation/filtering/numeric/math/CellFilterMax2.js +3 -0
  177. package/generation/filtering/numeric/math/CellFilterMembershipGeneralizedBell.js +55 -0
  178. package/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +42 -0
  179. package/generation/filtering/numeric/sampling/CellFilterSampleLayerCubic.js +36 -0
  180. package/generation/filtering/numeric/sampling/CellFilterSampleLayerLinear.js +41 -0
  181. package/generation/grid/GridData.d.ts +5 -1
  182. package/generation/grid/GridData.js +35 -36
  183. package/generation/grid/MarkerMatchCounter.js +5 -3
  184. package/generation/markers/GridActionRuleSet.js +15 -32
  185. package/generation/markers/GridCellActionPlaceMarker.js +12 -8
  186. package/generation/markers/debug/visualizeMarkers.js +56 -36
  187. package/generation/markers/emitter/MarkerNodeEmitterFromAction.js +8 -8
  188. package/generation/markers/prototypeGridCellActionPlaceMarker.js +209 -0
  189. package/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +1 -5
  190. package/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.spec.js +2 -2
  191. package/generation/placement/GridCellPlacementRule.js +31 -25
  192. package/generation/theme/ThemeEngine.js +1 -1
  193. package/package.json +1 -1
  194. package/samples/terrain/from_image.js +7 -3
  195. package/samples/terrain/main.js +1 -1
  196. package/view/View.js +23 -1
  197. package/view/common/LabelView.js +1 -1
  198. package/view/compose3x3transform.js +32 -8
  199. package/view/controller/dat/DatGuiUtils.js +1 -1
  200. package/view/elements/DropDownSelectionView.js +11 -3
  201. package/view/elements/image/ImageView.js +3 -1
  202. package/core/model/ObservedReal.js +0 -55
  203. package/editor/ecs/component/ObjectEditor.js +0 -0
  204. package/engine/graphics/particles/particular/engine/renderers/SoftBillboardParticleRenderer.js +0 -7
  205. package/engine/sound/ecs/emitter/attenuate/attenuateSoundLinear.js +0 -11
  206. package/generation/filtering/numeric/CellFilterReadGridLayer.js +0 -73
@@ -7,11 +7,12 @@ import { Matrix4 as ThreeMatrix4 } from "three";
7
7
  import { assert } from "../assert.js";
8
8
  import Signal from "../events/signal/Signal.js";
9
9
  import { clamp } from "../math/clamp.js";
10
- import { copysign } from "../math/copysign.js";
11
10
  import { lerp } from "../math/lerp.js";
12
- import { EPSILON, epsilonEquals, PI2, PI_HALF } from "../math/MathUtils.js";
11
+ import { EPSILON, epsilonEquals, PI2 } from "../math/MathUtils.js";
13
12
  import Vector3 from "./Vector3.js";
14
13
  import { v3_dot } from "./v3_dot.js";
14
+ import { min2 } from "../math/min2.js";
15
+ import { computeHashFloat } from "../math/hash/computeHashFloat.js";
15
16
 
16
17
  const matrix = new ThreeMatrix4();
17
18
 
@@ -46,39 +47,46 @@ class Quaternion {
46
47
  * @param {Number} [w=1]
47
48
  * @constructor
48
49
  */
49
- constructor(x, y, z, w) {
50
- this.x = (typeof x === "number") ? x : 0;
51
- this.y = (typeof x === "number") ? y : 0;
52
- this.z = (typeof z === "number") ? z : 0;
53
- this.w = (typeof w === "number") ? w : 1;
50
+ constructor(x = 0, y = 0, z = 0, w = 1) {
51
+
52
+ /**
53
+ *
54
+ * @type {Number}
55
+ */
56
+ this.x = x;
57
+ /**
58
+ *
59
+ * @type {Number}
60
+ */
61
+ this.y = y;
62
+ /**
63
+ *
64
+ * @type {Number}
65
+ */
66
+ this.z = z;
67
+ /**
68
+ *
69
+ * @type {Number}
70
+ */
71
+ this.w = w;
54
72
 
55
73
  this.onChanged = new Signal();
56
74
  }
57
75
 
58
- /**
59
- *
60
- * @param {Vector3} forwardVector
61
- * @return {Quaternion}
62
- */
63
- lookRotation_2(forwardVector) {
64
-
65
-
66
- const dot = Vector3.forward.dot(forwardVector);
67
- if (Math.abs(dot - (-1.0)) < 0.000001) {
68
- return this.set(Vector3.up.x, Vector3.up.y, Vector3.up.z, 3.1415926535897932);
69
- }
70
- if (Math.abs(dot - (1.0)) < 0.000001) {
71
- return this.set(0, 0, 0, 1);
72
- }
76
+ get 0() {
77
+ return this.x;
78
+ }
73
79
 
74
- const rotAngle = Math.acos(dot);
75
- rotAxis.copy(Vector3.forward);
76
- rotAxis.cross(forwardVector);
77
- rotAxis.normalize();
80
+ get 1() {
81
+ return this.y;
82
+ }
78
83
 
79
- quat3_createFromAxisAngle(rotAxis, rotAngle, this);
84
+ get 2() {
85
+ return this.z;
86
+ }
80
87
 
81
- return this;
88
+ get 3() {
89
+ return this.w;
82
90
  }
83
91
 
84
92
  /**
@@ -172,30 +180,6 @@ class Quaternion {
172
180
  return euler.setFromRotationMatrix(matrix);
173
181
  }
174
182
 
175
- /**
176
- *
177
- * @param {Vector3} direction
178
- * @param {Vector3} reference Reference direction, for example if you want to align Up direction or Forward, supply those here
179
- * @param {number} limit
180
- */
181
- lookRotation_3(direction, reference, limit) {
182
- const q = new Quaternion();
183
-
184
- const f = new Vector3();
185
-
186
- f.copy(reference);
187
-
188
- f.applyQuaternion(this);
189
-
190
- f.normalize();
191
-
192
- //
193
- q.fromUnitVectors2(f, direction);
194
-
195
- console.log(f.toJSON(), q.toJSON(), direction.toJSON(), reference.toJSON());
196
-
197
- this.multiply(q);
198
- }
199
183
 
200
184
  /**
201
185
  *
@@ -318,11 +302,10 @@ class Quaternion {
318
302
  }
319
303
 
320
304
  /**
321
- *
305
+ * @see https://stackoverflow.com/questions/3684269/component-of-a-quaternion-rotation-around-an-axis
322
306
  * @param {Vector3} axis
323
307
  * @param {Quaternion} swing
324
308
  * @param {Quaternion} twist
325
- * @returns {number}
326
309
  */
327
310
  computeSwingAndTwist(axis, swing, twist) {
328
311
  const x = this.x;
@@ -330,17 +313,48 @@ class Quaternion {
330
313
  const z = this.z;
331
314
  const w = this.w;
332
315
 
333
- const p = new Vector3();
316
+ // perform projection of rotation onto axis
317
+ const d = v3_dot(x, y, z, axis.x, axis.y, axis.z);
318
+
319
+ const mag2 = (axis.x * axis.x + axis.y * axis.y + axis.z * axis.z);
334
320
 
335
- p._projectVectors(x, y, z, axis.x, axis.y, axis.z);
321
+ const m = d / mag2;
322
+
323
+ const px = axis.x * m;
324
+ const py = axis.y * m;
325
+ const pz = axis.z * m;
326
+
327
+ if (d < 0) {
328
+ // axis points in the opposite direction from calculated twist, invert all components
329
+ twist.set(-px, -py, -pz, -w);
330
+ } else {
331
+ twist.set(px, py, pz, w);
332
+
333
+ }
336
334
 
337
- twist.set(p.x, p.y, p.z, w);
338
335
  twist.normalize();
339
336
 
340
337
  // rotation * twist.conjugated()
341
338
  swing._multiplyQuaternions(x, y, z, w, -twist.x, -twist.y, -twist.z, twist.w);
342
339
  }
343
340
 
341
+ /**
342
+ * Compute rotation (twist) around input axis
343
+ * @param {Vector3} axis
344
+ * @returns {number} in radians
345
+ */
346
+ computeTwistAngle(axis) {
347
+ assert.defined(axis, "axis");
348
+
349
+ const swing = new Quaternion();
350
+ const twist = new Quaternion();
351
+
352
+ this.computeSwingAndTwist(axis, swing, twist);
353
+
354
+ // extract twist angle from quaternion, see {@link #toAxisAngle}
355
+ return Math.acos(twist.w) * 2;
356
+ }
357
+
344
358
  /**
345
359
  *
346
360
  * @param {Vector3} axis
@@ -367,7 +381,8 @@ class Quaternion {
367
381
  normalize() {
368
382
  let l = this.length();
369
383
 
370
- if (l === 0) {
384
+ if (l < EPSILON) {
385
+ // use identity
371
386
  this.set(0, 0, 0, 1);
372
387
  } else {
373
388
  const m = 1 / l;
@@ -473,10 +488,9 @@ class Quaternion {
473
488
  lookAt(source, target) {
474
489
  const forward = new Vector3();
475
490
 
476
- forward
477
- .copy(target)
478
- .sub(source)
479
- .normalize();
491
+ forward.subVectors(target, source);
492
+
493
+ forward.normalize();
480
494
 
481
495
  this.alignToDirection(forward);
482
496
  }
@@ -503,92 +517,41 @@ class Quaternion {
503
517
 
504
518
  // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
505
519
 
506
- const cos = Math.cos;
507
- const sin = Math.sin;
508
-
509
- const half_x = x * 0.5;
510
- const half_y = y * 0.5;
511
- const half_z = z * 0.5;
512
-
513
- const c1 = cos(half_x);
514
- const c2 = cos(half_y);
515
- const c3 = cos(half_z);
516
-
517
- const s1 = sin(half_x);
518
- const s2 = sin(half_y);
519
- const s3 = sin(half_z);
520
-
521
520
  if (order === 'XYZ') {
522
521
 
523
- return this.set(
524
- s1 * c2 * c3 + c1 * s2 * s3,
525
- c1 * s2 * c3 - s1 * c2 * s3,
526
- c1 * c2 * s3 + s1 * s2 * c3,
527
- c1 * c2 * c3 - s1 * s2 * s3
528
- );
522
+ this.fromEulerAnglesXYZ(x, y, z);
529
523
 
530
524
  } else if (order === 'YXZ') {
531
525
 
532
-
533
- return this.set(
534
- s1 * c2 * c3 + c1 * s2 * s3,
535
- c1 * s2 * c3 - s1 * c2 * s3,
536
- c1 * c2 * s3 - s1 * s2 * c3,
537
- c1 * c2 * c3 + s1 * s2 * s3
538
- );
539
-
540
- // return this.set(
541
- // c1 * s2 * c3 + s1 * c2 * s3,
542
- // s1 * c2 * c3 - c1 * s2 * s3,
543
- // c1 * c2 * s3 - s1 * s2 * c3,
544
- // c1 * c2 * c3 + s1 * s2 * s3
545
- // );
526
+ this.fromEulerAnglesYXZ(x, y, z);
546
527
 
547
528
  } else if (order === 'ZXY') {
548
529
 
549
- return this.set(
550
- s1 * c2 * c3 - c1 * s2 * s3,
551
- c1 * s2 * c3 + s1 * c2 * s3,
552
- c1 * c2 * s3 + s1 * s2 * c3,
553
- c1 * c2 * c3 - s1 * s2 * s3
554
- );
530
+ this.fromEulerAnglesZXY(x, y, z);
555
531
 
556
532
  } else if (order === 'ZYX') {
557
533
 
558
- return this.set(
559
- s1 * c2 * c3 - c1 * s2 * s3,
560
- c1 * s2 * c3 + s1 * c2 * s3,
561
- c1 * c2 * s3 - s1 * s2 * c3,
562
- c1 * c2 * c3 + s1 * s2 * s3
563
- );
534
+ this.fromEulerAnglesZYX(x, y, z);
564
535
 
565
536
  } else if (order === 'YZX') {
566
537
 
567
- return this.set(
568
- s1 * c2 * c3 + c1 * s2 * s3,
569
- c1 * s2 * c3 + s1 * c2 * s3,
570
- c1 * c2 * s3 - s1 * s2 * c3,
571
- c1 * c2 * c3 - s1 * s2 * s3
572
- );
538
+ this.fromEulerAnglesYZX(x, y, z);
573
539
 
574
540
  } else if (order === 'XZY') {
575
541
 
576
- return this.set(
577
- s1 * c2 * c3 - c1 * s2 * s3,
578
- c1 * s2 * c3 - s1 * c2 * s3,
579
- c1 * c2 * s3 + s1 * s2 * c3,
580
- c1 * c2 * c3 + s1 * s2 * s3
581
- );
542
+ this.fromEulerAnglesXZY(x, y, z);
582
543
 
583
544
  }
545
+
546
+ return this;
584
547
  }
585
548
 
586
549
  /**
587
- *
550
+ * @see https://localcoder.org/euler-angle-to-quaternion-then-quaternion-to-euler-angle
551
+ * @see https://discourse.mcneel.com/t/what-is-the-right-method-to-convert-quaternion-to-plane-using-rhinocommon/92411/21?page=2
588
552
  * @param {Vector3} result
589
553
  */
590
554
  toEulerAnglesXYZ(result) {
591
-
592
555
  const x = this.x;
593
556
  const y = this.y;
594
557
  const z = this.z;
@@ -599,9 +562,19 @@ class Quaternion {
599
562
  const y2 = y * y;
600
563
  const z2 = z * z;
601
564
 
602
- const psi = Math.atan2(-2 * (x * w - y * z), (w2 - x2 - y2 + z2));
603
- const theta = Math.asin(2 * (x * z + y * w));
604
- const phi = Math.atan2(-2 * (z * w - x * y), (w2 + x2 - y2 - z2));
565
+ const r31 = 2 * (x * w - y * z);
566
+ const r32 = w2 - x2 - y2 + z2;
567
+
568
+ const psi = Math.atan2(r31, r32);
569
+
570
+ const r21 = 2 * (x * z + y * w);
571
+
572
+ const theta = Math.asin(r21);
573
+
574
+ const r11 = 2 * (z * w - x * y);
575
+ const r12 = w2 + x2 - y2 - z2;
576
+
577
+ const phi = Math.atan2(r11, r12);
605
578
 
606
579
  result.set(psi, theta, phi);
607
580
  }
@@ -727,64 +700,75 @@ class Quaternion {
727
700
  }
728
701
 
729
702
  /**
730
- * Writes Pitch(Y), Yaw(Z), Roll(X) to a given vector
731
- * @param {Vector3} result
703
+ * XYZ order
704
+ * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
705
+ * @param {number} x angle in X axis in radians
706
+ * @param {number} y angle in Y axis in radians
707
+ * @param {number} z angle in Z axis in radians
732
708
  */
733
- toEulerAngles2(result) {
734
- const x = this.x;
735
- const y = this.y;
736
- const z = this.z;
737
- const w = this.w;
709
+ fromEulerAngles(x, y, z) {
710
+ return this.fromEulerAnglesXYZ(x, y, z);
711
+ }
738
712
 
739
- const yy = y * y;
740
- const xx = x * x;
741
- const zz = z * z;
713
+ /**
714
+ * XYZ order
715
+ * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
716
+ * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
717
+ * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
718
+ * @param {number} x angle in X axis in radians
719
+ * @param {number} y angle in Y axis in radians
720
+ * @param {number} z angle in Z axis in radians
721
+ */
722
+ fromEulerAnglesXYZ(x, y, z) {
723
+ const half_x = x * 0.5;
724
+ const half_y = y * 0.5;
725
+ const half_z = z * 0.5;
742
726
 
743
- // roll (x-axis rotation)
744
- const sinr_cosp = +2.0 * (w * x + y * z);
745
- const cosr_cosp = +1.0 - 2.0 * (xx + yy);
746
- const roll = Math.atan2(sinr_cosp, cosr_cosp);
727
+ const sin = Math.sin;
728
+ const cos = Math.cos;
747
729
 
748
- let pitch;
749
- // pitch (y-axis rotation)
750
- const sinp = +2.0 * (w * y - z * x);
751
- if (Math.abs(sinp) >= 1) {
752
- pitch = copysign(Math.PI / 2, sinp); // use 90 degrees if out of range
753
- } else {
754
- pitch = Math.asin(sinp);
755
- }
730
+ const s1 = sin(half_x);
731
+ const s2 = sin(half_y);
732
+ const s3 = sin(half_z);
756
733
 
757
- // yaw (z-axis rotation)
758
- const siny_cosp = +2.0 * (w * z + x * y);
759
- const cosy_cosp = +1.0 - 2.0 * (yy + zz);
760
- const yaw = Math.atan2(siny_cosp, cosy_cosp);
734
+ const c1 = cos(half_x);
735
+ const c2 = cos(half_y);
736
+ const c3 = cos(half_z);
737
+
738
+ const _x = s1 * c2 * c3 + c1 * s2 * s3;
739
+ const _y = c1 * s2 * c3 - s1 * c2 * s3;
740
+ const _z = c1 * c2 * s3 + s1 * s2 * c3;
741
+ const _w = c1 * c2 * c3 - s1 * s2 * s3;
761
742
 
762
- result.set(roll, pitch, yaw);
743
+ this.set(_x, _y, _z, _w);
763
744
  }
764
745
 
765
746
  /**
766
747
  * XYZ order
767
748
  * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
749
+ * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
750
+ * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
768
751
  * @param {number} x angle in X axis in radians
769
752
  * @param {number} y angle in Y axis in radians
770
753
  * @param {number} z angle in Z axis in radians
771
754
  */
772
- fromEulerAngles(x, y, z) {
755
+ fromEulerAnglesYXZ(x, y, z) {
773
756
  const scaled_x = x * 0.5;
774
757
  const scaled_y = y * 0.5;
775
758
  const scaled_z = z * 0.5;
776
759
 
777
- const sx = Math.sin(scaled_x);
778
- const cx = Math.cos(scaled_x);
779
- const sy = Math.sin(scaled_y);
780
- const cy = Math.cos(scaled_y);
781
- const sz = Math.sin(scaled_z);
782
- const cz = Math.cos(scaled_z);
760
+ const s1 = Math.sin(scaled_x);
761
+ const s2 = Math.sin(scaled_y);
762
+ const s3 = Math.sin(scaled_z);
783
763
 
784
- const _x = sx * cy * cz - cx * sy * sz;
785
- const _y = cx * sy * cz + sx * cy * sz;
786
- const _z = cx * cy * sz - sx * sy * cz;
787
- const _w = cx * cy * cz + sx * sy * sz;
764
+ const c1 = Math.cos(scaled_x);
765
+ const c2 = Math.cos(scaled_y);
766
+ const c3 = Math.cos(scaled_z);
767
+
768
+ const _x = s1 * c2 * c3 + c1 * s2 * s3;
769
+ const _y = c1 * s2 * c3 - s1 * c2 * s3;
770
+ const _z = c1 * c2 * s3 - s1 * s2 * c3;
771
+ const _w = c1 * c2 * c3 + s1 * s2 * s3;
788
772
 
789
773
  this.set(_x, _y, _z, _w);
790
774
  }
@@ -798,7 +782,7 @@ class Quaternion {
798
782
  * @param {number} y angle in Y axis in radians
799
783
  * @param {number} z angle in Z axis in radians
800
784
  */
801
- fromEulerAnglesXYZ(x, y, z) {
785
+ fromEulerAnglesZXY(x, y, z) {
802
786
  const scaled_x = x * 0.5;
803
787
  const scaled_y = y * 0.5;
804
788
  const scaled_z = z * 0.5;
@@ -811,8 +795,8 @@ class Quaternion {
811
795
  const c2 = Math.cos(scaled_y);
812
796
  const c3 = Math.cos(scaled_z);
813
797
 
814
- const _x = s1 * c2 * c3 + c1 * s2 * s3;
815
- const _y = c1 * s2 * c3 - s1 * c2 * s3;
798
+ const _x = s1 * c2 * c3 - c1 * s2 * s3;
799
+ const _y = c1 * s2 * c3 + s1 * c2 * s3;
816
800
  const _z = c1 * c2 * s3 + s1 * s2 * c3;
817
801
  const _w = c1 * c2 * c3 - s1 * s2 * s3;
818
802
 
@@ -820,48 +804,93 @@ class Quaternion {
820
804
  }
821
805
 
822
806
  /**
823
- * Writes Pitch(Y), Yaw(Z), Roll(X) to a given vector
824
- * @source http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
825
- * @param {Vector3} result
807
+ * XYZ order
808
+ * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
809
+ * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
810
+ * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
811
+ * @param {number} x angle in X axis in radians
812
+ * @param {number} y angle in Y axis in radians
813
+ * @param {number} z angle in Z axis in radians
826
814
  */
827
- toEulerAngles(result) {
828
- const x = this.x;
829
- const y = this.y;
830
- const z = this.z;
831
- const w = this.w;
815
+ fromEulerAnglesZYX(x, y, z) {
816
+ const scaled_x = x * 0.5;
817
+ const scaled_y = y * 0.5;
818
+ const scaled_z = z * 0.5;
832
819
 
833
- const sqw = w * w;
834
- const sqx = x * x;
835
- const sqy = y * y;
836
- const sqz = z * z;
820
+ const s1 = Math.sin(scaled_x);
821
+ const s2 = Math.sin(scaled_y);
822
+ const s3 = Math.sin(scaled_z);
837
823
 
838
- const unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
824
+ const c1 = Math.cos(scaled_x);
825
+ const c2 = Math.cos(scaled_y);
826
+ const c3 = Math.cos(scaled_z);
839
827
 
840
- const test = x * w - y * z;
828
+ const _x = s1 * c2 * c3 - c1 * s2 * s3;
829
+ const _y = c1 * s2 * c3 + s1 * c2 * s3;
830
+ const _z = c1 * c2 * s3 - s1 * s2 * c3;
831
+ const _w = c1 * c2 * c3 + s1 * s2 * s3;
841
832
 
833
+ this.set(_x, _y, _z, _w);
834
+ }
842
835
 
843
- let yaw, pitch, roll;
836
+ /**
837
+ * XYZ order
838
+ * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
839
+ * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
840
+ * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
841
+ * @param {number} x angle in X axis in radians
842
+ * @param {number} y angle in Y axis in radians
843
+ * @param {number} z angle in Z axis in radians
844
+ */
845
+ fromEulerAnglesYZX(x, y, z) {
846
+ const scaled_x = x * 0.5;
847
+ const scaled_y = y * 0.5;
848
+ const scaled_z = z * 0.5;
844
849
 
845
- if (test > 0.4995 * unit) { // singularity at north pole
846
- yaw = 2 * Math.atan2(y, x);
847
- pitch = PI_HALF;
848
- roll = 0;
849
- } else if (test < -0.4995 * unit) { // singularity at south pole
850
- yaw = -2 * Math.atan2(y, x);
851
- pitch = -PI_HALF;
852
- roll = 0;
853
- } else {
854
- yaw = Math.atan2(2 * x * w + 2 * y * z, 1 - 2 * (sqz + sqw));
855
- pitch = Math.asin(2 * (x * z - w * y));
856
- roll = Math.atan2(2 * x * y - 2 * z * w, 1 - 2 * (sqy + sqz))
857
- }
850
+ const s1 = Math.sin(scaled_x);
851
+ const s2 = Math.sin(scaled_y);
852
+ const s3 = Math.sin(scaled_z);
858
853
 
859
- //normalize angles
860
- yaw = normalizeAngle(yaw);
861
- pitch = normalizeAngle(pitch);
862
- roll = normalizeAngle(roll);
854
+ const c1 = Math.cos(scaled_x);
855
+ const c2 = Math.cos(scaled_y);
856
+ const c3 = Math.cos(scaled_z);
857
+
858
+ const _x = s1 * c2 * c3 + c1 * s2 * s3;
859
+ const _y = c1 * s2 * c3 + s1 * c2 * s3;
860
+ const _z = c1 * c2 * s3 - s1 * s2 * c3;
861
+ const _w = c1 * c2 * c3 - s1 * s2 * s3;
862
+
863
+ this.set(_x, _y, _z, _w);
864
+ }
865
+
866
+ /**
867
+ * XYZ order
868
+ * @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
869
+ * @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
870
+ * @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
871
+ * @param {number} x angle in X axis in radians
872
+ * @param {number} y angle in Y axis in radians
873
+ * @param {number} z angle in Z axis in radians
874
+ */
875
+ fromEulerAnglesXZY(x, y, z) {
876
+ const scaled_x = x * 0.5;
877
+ const scaled_y = y * 0.5;
878
+ const scaled_z = z * 0.5;
879
+
880
+ const s1 = Math.sin(scaled_x);
881
+ const s2 = Math.sin(scaled_y);
882
+ const s3 = Math.sin(scaled_z);
883
+
884
+ const c1 = Math.cos(scaled_x);
885
+ const c2 = Math.cos(scaled_y);
886
+ const c3 = Math.cos(scaled_z);
887
+
888
+ const _x = s1 * c2 * c3 - c1 * s2 * s3;
889
+ const _y = c1 * s2 * c3 - s1 * c2 * s3;
890
+ const _z = c1 * c2 * s3 + s1 * s2 * c3;
891
+ const _w = c1 * c2 * c3 + s1 * s2 * s3;
863
892
 
864
- result.set(pitch, yaw, roll);
893
+ this.set(_x, _y, _z, _w);
865
894
  }
866
895
 
867
896
  /**
@@ -1152,6 +1181,7 @@ class Quaternion {
1152
1181
  this.set(x, y, z, w);
1153
1182
  }
1154
1183
 
1184
+
1155
1185
  /**
1156
1186
  * @see https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/quat.js
1157
1187
  * @param {Quaternion} other
@@ -1204,6 +1234,17 @@ class Quaternion {
1204
1234
  this.set(_x, _y, _z, _w);
1205
1235
  }
1206
1236
 
1237
+ /**
1238
+ * @see https://github.com/gareth-cross/quat/blob/master/include/quaternion.hpp
1239
+ * TODO implement
1240
+ * @param {Quaternion} a
1241
+ * @param {Quaternion} b
1242
+ * @param {number} t
1243
+ */
1244
+ quaternionsInterpolateRungeKutta4(a, b, t) {
1245
+ throw new Error('Not Implemented');
1246
+ }
1247
+
1207
1248
  /**
1208
1249
  *
1209
1250
  * @param {function} handler
@@ -1496,6 +1537,18 @@ class Quaternion {
1496
1537
  ;
1497
1538
  }
1498
1539
 
1540
+ /**
1541
+ *
1542
+ * @returns {number}
1543
+ */
1544
+ hash() {
1545
+ // fast and dumb hash, just spread bits a bit and XOR them
1546
+ return computeHashFloat(this.x)
1547
+ ^ (computeHashFloat(this.y) >> 2)
1548
+ ^ (computeHashFloat(this.z) >> 1)
1549
+ ^ (computeHashFloat(this.w) << 2);
1550
+ }
1551
+
1499
1552
  /**
1500
1553
  *
1501
1554
  * @param {Quaternion} other
@@ -1567,6 +1620,28 @@ class Quaternion {
1567
1620
 
1568
1621
  return result;
1569
1622
  }
1623
+
1624
+
1625
+ /**
1626
+ * Behaves similarly to Unity's Quaternion `RotateToward` method
1627
+ * @param {Quaternion} result
1628
+ * @param {Quaternion} from
1629
+ * @param {Quaternion} to
1630
+ * @param {number} max_delta
1631
+ */
1632
+ static rotateTowards(result, from, to, max_delta) {
1633
+ const angle = from.angleTo(to);
1634
+
1635
+ if (angle === 0) {
1636
+ result.copy(to);
1637
+ } else {
1638
+ // clamp to 1, to make sure we don't overshoot
1639
+ const t = min2(1, max_delta / angle);
1640
+
1641
+ from.slerp(to, t);
1642
+ }
1643
+
1644
+ }
1570
1645
  }
1571
1646
 
1572
1647
  /**
@@ -1585,6 +1660,10 @@ const axis = new Vector3();
1585
1660
 
1586
1661
  const tempvec3 = new Vector3();
1587
1662
 
1663
+ /**
1664
+ * Used in UINT32 packing
1665
+ * @type {number}
1666
+ */
1588
1667
  const K_CONST = 0.70710678118; // 1/sqrt(2)
1589
1668
 
1590
1669
  export default Quaternion;