@woosh/meep-engine 2.37.18 → 2.37.19
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.
- package/core/assert.js +1 -1
- package/core/collection/array/typed/isTypedArray.js +20 -0
- package/core/collection/array/typedArrayToDataType.js +1 -0
- package/core/collection/table/RowFirstTable.js +34 -0
- package/core/collection/table/RowFirstTable.spec.js +59 -1
- package/core/color/Color.js +14 -0
- package/core/color/rgb2hex.js +1 -1
- package/core/events/signal/Signal.spec.js +16 -0
- package/core/geom/Quaternion.d.ts +5 -0
- package/core/geom/Quaternion.js +152 -137
- package/core/geom/Quaternion.spec.js +47 -2
- package/core/geom/Vector3.schema.json +16 -0
- package/core/json/JsonUtils.js +2 -20
- package/core/model/ObservedEnum.js +8 -0
- package/editor/Editor.js +97 -1
- package/editor/actions/concrete/PatchTerrainHeightAction.js +1 -1
- package/editor/ecs/component/FieldDescriptor.js +34 -0
- package/editor/ecs/component/FieldValueAdapter.js +20 -0
- package/editor/ecs/component/TypeEditor.js +33 -0
- package/editor/ecs/component/TypeSchema.d.ts +38 -0
- package/editor/ecs/component/createFieldEditor.js +90 -0
- package/editor/ecs/component/createObjectEditor.js +242 -60
- package/editor/ecs/component/editors/ColorEditor.js +39 -0
- package/editor/ecs/component/editors/HTMLElementEditor.js +17 -0
- package/editor/ecs/component/editors/ImagePathEditor.js +50 -0
- package/editor/ecs/component/editors/NumericIntervalEditor.js +86 -0
- package/editor/ecs/component/editors/ObservedBooleanEditor.js +13 -0
- package/editor/ecs/component/editors/ObservedEnumEditor.js +32 -0
- package/editor/ecs/component/editors/ObservedIntegerEditor.js +43 -0
- package/editor/ecs/component/editors/ObservedStringEditor.js +51 -0
- package/editor/ecs/component/editors/Sampler2DEditor.js +60 -0
- package/editor/ecs/component/editors/collection/ListEditor.js +83 -0
- package/editor/ecs/component/editors/common/BitFlagsEditor.js +80 -0
- package/editor/ecs/component/editors/common/EnumEditor.js +41 -0
- package/editor/ecs/component/editors/common/makeV3_editor.js +85 -0
- package/editor/ecs/component/editors/common/noEditor.js +9 -0
- package/editor/ecs/component/editors/ecs/GridObstacleEditor.js +17 -0
- package/editor/ecs/component/editors/ecs/MinimapMarkerEditor.js +16 -0
- package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +44 -0
- package/editor/ecs/component/editors/ecs/ParameterTrackEditor.js +17 -0
- package/editor/ecs/component/editors/ecs/ParticleEmitterEditor.js +58 -0
- package/editor/ecs/component/editors/ecs/ParticleEmitterLayerEditor.js +54 -0
- package/editor/ecs/component/editors/ecs/SimulationStepDefinitionEditor.js +21 -0
- package/editor/ecs/component/editors/ecs/Trail2DEditor.js +33 -0
- package/editor/ecs/component/editors/ecs/TransformEditor.js +23 -0
- package/editor/ecs/component/editors/ecs/terrain/SplatMappingEditor.js +21 -0
- package/editor/ecs/component/editors/ecs/terrain/TerrainEditor.js +42 -0
- package/editor/ecs/component/editors/ecs/terrain/TerrainLayerEditor.js +18 -0
- package/editor/ecs/component/editors/ecs/terrain/TerrainLayersEditor.js +22 -0
- package/editor/ecs/component/editors/ecs/terrain/TerrainOverlayEditor.js +20 -0
- package/editor/ecs/component/editors/geom/QuaternionEditor.js +56 -0
- package/editor/ecs/component/editors/geom/Vector1Editor.js +57 -0
- package/editor/ecs/component/editors/geom/Vector2Editor.js +11 -0
- package/editor/ecs/component/editors/geom/Vector3Editor.js +13 -0
- package/editor/ecs/component/editors/geom/Vector4Editor.js +12 -0
- package/editor/ecs/component/editors/primitive/ArrayEditor.js +46 -0
- package/editor/ecs/component/editors/primitive/BooleanEditor.js +27 -0
- package/editor/ecs/component/editors/primitive/FunctionEditor.js +25 -0
- package/editor/ecs/component/editors/primitive/NumberEditor.js +60 -0
- package/editor/ecs/component/editors/primitive/ObjectEditor.js +12 -0
- package/editor/ecs/component/editors/primitive/StringEditor.js +31 -0
- package/editor/ecs/component/editors/three/BufferGeometryEditor.js +28 -0
- package/editor/ecs/component/editors/three/MaterialEditor.js +27 -0
- package/editor/ecs/component/editors/three/MeshEditor.js +35 -0
- package/editor/ecs/component/editors/three/TextureEditor.js +32 -0
- package/editor/ecs/component/findNearestRegisteredType.js +59 -0
- package/editor/ecs/component/prototypeObjectEditor.js +379 -0
- package/editor/view/EditorView.js +1 -1
- package/editor/view/ecs/ComponentControlView.js +2 -30
- package/editor/view/ecs/EntityEditor.js +61 -139
- package/editor/view/ecs/components/GridObstacleController.js +4 -4
- package/editor/view/ecs/components/TerrainController.js +1 -1
- package/editor/view/ecs/components/common/NumberController.js +19 -7
- package/engine/animation/keyed2/AnimationTrack.js +1 -1
- package/engine/ecs/components/TagEditor.js +15 -0
- package/engine/ecs/terrain/ecs/Terrain.js +23 -42
- package/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
- package/engine/ecs/terrain/ecs/layers/TerrainLayer.js +1 -1
- package/engine/ecs/terrain/util/loadVisibleTerrainTiles.js +1 -1
- package/engine/ecs/transform/Transform.editor.schema.json +16 -0
- package/engine/graphics/ecs/highlight/HighlightEditor.js +17 -0
- package/engine/graphics/ecs/mesh/MeshEditor.js +28 -0
- package/engine/graphics/ecs/mesh-v2/aggregate/prototypeSGMesh.js +3 -3
- package/engine/graphics/micron/render/instanced/shader/shader_rewrite_standard.js +15 -15
- package/engine/graphics/particles/particular/engine/ParticularEngine.js +5 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +16 -0
- package/engine/graphics/util/ScaleObject3ToBox.js +14 -1
- package/engine/graphics/util/makeMeshPreviewScene.js +2 -1
- package/engine/grid/components/GridObstacle.js +0 -44
- package/engine/grid/components/GridObstacleSerializationAdapter.js +46 -0
- package/engine/navigation/ecs/components/Path.d.ts +2 -0
- package/engine/navigation/ecs/components/Path.js +6 -1
- package/generation/example/SampleGenerator0.js +33 -29
- package/generation/example/generators/interactive/mir_generator_place_buff_objects.js +7 -6
- package/generation/example/generators/mir_generator_place_bases.js +7 -3
- package/generation/example/generators/mir_generator_place_road_decorators.js +3 -3
- package/generation/example/generators/mir_generator_place_starting_point.js +3 -2
- package/generation/markers/GridCellActionPlaceMarker.js +9 -3
- package/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +1 -1
- package/generation/placement/GridCellPlacementRule.js +22 -23
- package/generation/theme/ThemeEngine.js +1 -1
- package/package.json +1 -1
- package/samples/terrain/main.js +1 -1
- package/view/View.js +23 -1
- package/view/common/LabelView.js +1 -1
- package/view/compose3x3transform.js +32 -8
- package/view/controller/dat/DatGuiUtils.js +1 -1
- package/view/elements/DropDownSelectionView.js +11 -3
- package/view/elements/image/ImageView.js +3 -1
- package/core/model/ObservedReal.js +0 -55
- package/editor/ecs/component/ObjectEditor.js +0 -0
package/core/assert.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isTypedArray } from "./json/JsonUtils.js";
|
|
2
1
|
import { isArrayEqualStrict } from "./collection/array/isArrayEqualStrict.js";
|
|
2
|
+
import { isTypedArray } from "./collection/array/typed/isTypedArray.js";
|
|
3
3
|
|
|
4
4
|
function equal(a, b, m) {
|
|
5
5
|
assert(a === b, m) // eslint-disable-line eqeqeq
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param o
|
|
4
|
+
* @returns {boolean}
|
|
5
|
+
*/
|
|
6
|
+
function isTypedArray(o) {
|
|
7
|
+
return (
|
|
8
|
+
o instanceof Int8Array ||
|
|
9
|
+
o instanceof Uint8Array ||
|
|
10
|
+
o instanceof Uint8ClampedArray ||
|
|
11
|
+
o instanceof Int16Array ||
|
|
12
|
+
o instanceof Uint16Array ||
|
|
13
|
+
o instanceof Int32Array ||
|
|
14
|
+
o instanceof Uint32Array ||
|
|
15
|
+
o instanceof Float32Array ||
|
|
16
|
+
o instanceof Float64Array
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { isTypedArray };
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { assert } from "../../assert.js";
|
|
7
7
|
import Signal from "../../events/signal/Signal.js";
|
|
8
8
|
import { max2 } from "../../math/max2.js";
|
|
9
|
+
import { array_copy } from "../array/copyArray.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
*
|
|
@@ -414,6 +415,39 @@ RowFirstTable.prototype.setRow = function (index, record) {
|
|
|
414
415
|
this.writeRowMethod(this.dataView, this.bytesPerRecord * index, record);
|
|
415
416
|
}
|
|
416
417
|
|
|
418
|
+
/**
|
|
419
|
+
* Reverse order of rows, row-0 will end up at and previously last row will become the first row etc.
|
|
420
|
+
*/
|
|
421
|
+
RowFirstTable.prototype.reverse_rows = function () {
|
|
422
|
+
const bpr = this.bytesPerRecord;
|
|
423
|
+
const copy_buffer = new Uint8Array(bpr);
|
|
424
|
+
|
|
425
|
+
const buffer = this.data;
|
|
426
|
+
const wrapper = new Uint8Array(buffer);
|
|
427
|
+
|
|
428
|
+
const length = this.length;
|
|
429
|
+
|
|
430
|
+
if (length <= 1) {
|
|
431
|
+
// need at least 2 rows for reversal to make any change
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const last_row_index = length - 1;
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
const traversal_limit = last_row_index >>> 1;
|
|
439
|
+
for (let i = 0; i <= traversal_limit; i++) {
|
|
440
|
+
const address = i * bpr;
|
|
441
|
+
array_copy(wrapper, address, copy_buffer, 0, bpr);
|
|
442
|
+
|
|
443
|
+
const swap_index = last_row_index - i;
|
|
444
|
+
const swap_address = swap_index * bpr;
|
|
445
|
+
|
|
446
|
+
wrapper.copyWithin(address, swap_address, swap_address + bpr)
|
|
447
|
+
wrapper.set(copy_buffer, swap_address);
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
417
451
|
/**
|
|
418
452
|
* clear out all the data and free memory
|
|
419
453
|
*/
|
|
@@ -223,7 +223,65 @@ test('copy', () => {
|
|
|
223
223
|
a.addRow([-11.3, 13]);
|
|
224
224
|
|
|
225
225
|
const b = new RowFirstTable(spec);
|
|
226
|
-
b.copy(a);
|
|
226
|
+
b.copy(a);
|
|
227
227
|
|
|
228
228
|
|
|
229
229
|
});
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
test('reverse_rows 3 rows (odd number)', () => {
|
|
233
|
+
|
|
234
|
+
const spec = new RowFirstTableSpec([DataType.Uint8]);
|
|
235
|
+
|
|
236
|
+
const a = new RowFirstTable(spec);
|
|
237
|
+
a.addRow([1]);
|
|
238
|
+
a.addRow([2]);
|
|
239
|
+
a.addRow([3]);
|
|
240
|
+
|
|
241
|
+
a.reverse_rows();
|
|
242
|
+
|
|
243
|
+
expect(a.readCellValue(0, 0)).toBeCloseTo(3);
|
|
244
|
+
expect(a.readCellValue(1, 0)).toBeCloseTo(2);
|
|
245
|
+
expect(a.readCellValue(2, 0)).toBeCloseTo(1);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('reverse_rows 2 rows', () => {
|
|
249
|
+
|
|
250
|
+
const spec = new RowFirstTableSpec([DataType.Float64, DataType.Uint8]);
|
|
251
|
+
|
|
252
|
+
const a = new RowFirstTable(spec);
|
|
253
|
+
a.addRow([3.1, 7]);
|
|
254
|
+
a.addRow([-11.3, 13]);
|
|
255
|
+
|
|
256
|
+
a.reverse_rows();
|
|
257
|
+
|
|
258
|
+
expect(a.readCellValue(1, 0)).toBeCloseTo(3.1);
|
|
259
|
+
expect(a.readCellValue(1, 1)).toBeCloseTo(7);
|
|
260
|
+
|
|
261
|
+
expect(a.readCellValue(0, 0)).toBeCloseTo(-11.3);
|
|
262
|
+
expect(a.readCellValue(0, 1)).toBeCloseTo(13);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test('reverse_rows 1 row', () => {
|
|
266
|
+
|
|
267
|
+
const spec = new RowFirstTableSpec([DataType.Float64, DataType.Uint8]);
|
|
268
|
+
|
|
269
|
+
const a = new RowFirstTable(spec);
|
|
270
|
+
|
|
271
|
+
a.addRow([3.1, 7]);
|
|
272
|
+
a.reverse_rows();
|
|
273
|
+
|
|
274
|
+
expect(a.readCellValue(0, 0)).toBeCloseTo(3.1);
|
|
275
|
+
expect(a.readCellValue(0, 1)).toBeCloseTo(7);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('reverse_rows empty', () => {
|
|
279
|
+
|
|
280
|
+
const spec = new RowFirstTableSpec([DataType.Float64, DataType.Uint8]);
|
|
281
|
+
|
|
282
|
+
const a = new RowFirstTable(spec);
|
|
283
|
+
|
|
284
|
+
a.reverse_rows();
|
|
285
|
+
|
|
286
|
+
expect(a.length).toBe(0);
|
|
287
|
+
});
|
package/core/color/Color.js
CHANGED
|
@@ -9,6 +9,7 @@ import { computeHashFloat } from "../math/hash/computeHashFloat.js";
|
|
|
9
9
|
import { rgb2hsv } from "./rgb2hsv.js";
|
|
10
10
|
import { rgb2uint24 } from "./rgb2uint24.js";
|
|
11
11
|
import { clamp01 } from "../math/clamp01.js";
|
|
12
|
+
import { rgb2hex } from "./rgb2hex.js";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @class
|
|
@@ -346,6 +347,19 @@ export class Color {
|
|
|
346
347
|
this.setRGB(r / 255, g / 255, b / 255);
|
|
347
348
|
}
|
|
348
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Returns color in CSS hex color format
|
|
352
|
+
* @example #FF0000
|
|
353
|
+
* @returns {string}
|
|
354
|
+
*/
|
|
355
|
+
toHex() {
|
|
356
|
+
return '#' + rgb2hex(
|
|
357
|
+
Math.round(this.r),
|
|
358
|
+
Math.round(this.g),
|
|
359
|
+
Math.round(this.b)
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
349
363
|
/**
|
|
350
364
|
*
|
|
351
365
|
* @param {Color} other
|
package/core/color/rgb2hex.js
CHANGED
|
@@ -147,3 +147,19 @@ test("handler context is properly setup during dispatch", () => {
|
|
|
147
147
|
|
|
148
148
|
expect(handler).toHaveBeenCalled();
|
|
149
149
|
});
|
|
150
|
+
|
|
151
|
+
test("handlers should be executed in the order in which they are added", () => {
|
|
152
|
+
const signal = new Signal();
|
|
153
|
+
|
|
154
|
+
const marks = [];
|
|
155
|
+
|
|
156
|
+
const write_1 = jest.fn(() => marks.push(1));
|
|
157
|
+
const write_2 = jest.fn(() => marks.push(2));
|
|
158
|
+
|
|
159
|
+
signal.add(write_1);
|
|
160
|
+
signal.add(write_2);
|
|
161
|
+
|
|
162
|
+
signal.send0();
|
|
163
|
+
|
|
164
|
+
expect(marks).toEqual([1, 2]);
|
|
165
|
+
});
|
|
@@ -24,4 +24,9 @@ export default class Quaternion {
|
|
|
24
24
|
setFromRotationMatrix(m: Matrix4): void
|
|
25
25
|
|
|
26
26
|
decodeFromUint32(uint: number): void
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
toEulerAnglesXYZ(v3: { set(x: number, y: number, z: number): any }): void
|
|
30
|
+
|
|
31
|
+
fromEulerAnglesXYZ(x: number, y: number, z: number): void
|
|
27
32
|
}
|
package/core/geom/Quaternion.js
CHANGED
|
@@ -7,9 +7,8 @@ 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
|
|
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";
|
|
15
14
|
|
|
@@ -503,84 +502,33 @@ class Quaternion {
|
|
|
503
502
|
|
|
504
503
|
// http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
505
504
|
|
|
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
505
|
if (order === 'XYZ') {
|
|
522
506
|
|
|
523
|
-
|
|
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
|
-
);
|
|
507
|
+
this.fromEulerAnglesXYZ(x, y, z);
|
|
529
508
|
|
|
530
509
|
} else if (order === 'YXZ') {
|
|
531
510
|
|
|
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
|
-
// );
|
|
511
|
+
this.fromEulerAnglesYXZ(x, y, z);
|
|
546
512
|
|
|
547
513
|
} else if (order === 'ZXY') {
|
|
548
514
|
|
|
549
|
-
|
|
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
|
-
);
|
|
515
|
+
this.fromEulerAnglesZXY(x, y, z);
|
|
555
516
|
|
|
556
517
|
} else if (order === 'ZYX') {
|
|
557
518
|
|
|
558
|
-
|
|
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
|
-
);
|
|
519
|
+
this.fromEulerAnglesZYX(x, y, z);
|
|
564
520
|
|
|
565
521
|
} else if (order === 'YZX') {
|
|
566
522
|
|
|
567
|
-
|
|
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
|
-
);
|
|
523
|
+
this.fromEulerAnglesYZX(x, y, z);
|
|
573
524
|
|
|
574
525
|
} else if (order === 'XZY') {
|
|
575
526
|
|
|
576
|
-
|
|
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
|
-
);
|
|
527
|
+
this.fromEulerAnglesXZY(x, y, z);
|
|
582
528
|
|
|
583
529
|
}
|
|
530
|
+
|
|
531
|
+
return this;
|
|
584
532
|
}
|
|
585
533
|
|
|
586
534
|
/**
|
|
@@ -599,9 +547,9 @@ class Quaternion {
|
|
|
599
547
|
const y2 = y * y;
|
|
600
548
|
const z2 = z * z;
|
|
601
549
|
|
|
602
|
-
const psi = Math.atan2(
|
|
550
|
+
const psi = Math.atan2(2 * (x * w - y * z), (w2 - x2 - y2 + z2));
|
|
603
551
|
const theta = Math.asin(2 * (x * z + y * w));
|
|
604
|
-
const phi = Math.atan2(
|
|
552
|
+
const phi = Math.atan2(2 * (z * w - x * y), (w2 + x2 - y2 - z2));
|
|
605
553
|
|
|
606
554
|
result.set(psi, theta, phi);
|
|
607
555
|
}
|
|
@@ -727,64 +675,75 @@ class Quaternion {
|
|
|
727
675
|
}
|
|
728
676
|
|
|
729
677
|
/**
|
|
730
|
-
*
|
|
731
|
-
* @
|
|
678
|
+
* XYZ order
|
|
679
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
680
|
+
* @param {number} x angle in X axis in radians
|
|
681
|
+
* @param {number} y angle in Y axis in radians
|
|
682
|
+
* @param {number} z angle in Z axis in radians
|
|
732
683
|
*/
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
const z = this.z;
|
|
737
|
-
const w = this.w;
|
|
684
|
+
fromEulerAngles(x, y, z) {
|
|
685
|
+
return this.fromEulerAnglesXYZ(x, y, z);
|
|
686
|
+
}
|
|
738
687
|
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
688
|
+
/**
|
|
689
|
+
* XYZ order
|
|
690
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
691
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
692
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
693
|
+
* @param {number} x angle in X axis in radians
|
|
694
|
+
* @param {number} y angle in Y axis in radians
|
|
695
|
+
* @param {number} z angle in Z axis in radians
|
|
696
|
+
*/
|
|
697
|
+
fromEulerAnglesXYZ(x, y, z) {
|
|
698
|
+
const half_x = x * 0.5;
|
|
699
|
+
const half_y = y * 0.5;
|
|
700
|
+
const half_z = z * 0.5;
|
|
742
701
|
|
|
743
|
-
|
|
744
|
-
const
|
|
745
|
-
const cosr_cosp = +1.0 - 2.0 * (xx + yy);
|
|
746
|
-
const roll = Math.atan2(sinr_cosp, cosr_cosp);
|
|
702
|
+
const sin = Math.sin;
|
|
703
|
+
const cos = Math.cos;
|
|
747
704
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
const
|
|
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
|
-
}
|
|
705
|
+
const s1 = sin(half_x);
|
|
706
|
+
const s2 = sin(half_y);
|
|
707
|
+
const s3 = sin(half_z);
|
|
756
708
|
|
|
757
|
-
|
|
758
|
-
const
|
|
759
|
-
const
|
|
760
|
-
|
|
709
|
+
const c1 = cos(half_x);
|
|
710
|
+
const c2 = cos(half_y);
|
|
711
|
+
const c3 = cos(half_z);
|
|
712
|
+
|
|
713
|
+
const _x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
714
|
+
const _y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
715
|
+
const _z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
716
|
+
const _w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
761
717
|
|
|
762
|
-
|
|
718
|
+
this.set(_x, _y, _z, _w);
|
|
763
719
|
}
|
|
764
720
|
|
|
765
721
|
/**
|
|
766
722
|
* XYZ order
|
|
767
723
|
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
724
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
725
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
768
726
|
* @param {number} x angle in X axis in radians
|
|
769
727
|
* @param {number} y angle in Y axis in radians
|
|
770
728
|
* @param {number} z angle in Z axis in radians
|
|
771
729
|
*/
|
|
772
|
-
|
|
730
|
+
fromEulerAnglesYXZ(x, y, z) {
|
|
773
731
|
const scaled_x = x * 0.5;
|
|
774
732
|
const scaled_y = y * 0.5;
|
|
775
733
|
const scaled_z = z * 0.5;
|
|
776
734
|
|
|
777
|
-
const
|
|
778
|
-
const
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
const
|
|
782
|
-
const
|
|
735
|
+
const s1 = Math.sin(scaled_x);
|
|
736
|
+
const s2 = Math.sin(scaled_y);
|
|
737
|
+
const s3 = Math.sin(scaled_z);
|
|
738
|
+
|
|
739
|
+
const c1 = Math.cos(scaled_x);
|
|
740
|
+
const c2 = Math.cos(scaled_y);
|
|
741
|
+
const c3 = Math.cos(scaled_z);
|
|
783
742
|
|
|
784
|
-
const _x =
|
|
785
|
-
const _y =
|
|
786
|
-
const _z =
|
|
787
|
-
const _w =
|
|
743
|
+
const _x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
744
|
+
const _y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
745
|
+
const _z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
746
|
+
const _w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
788
747
|
|
|
789
748
|
this.set(_x, _y, _z, _w);
|
|
790
749
|
}
|
|
@@ -798,7 +757,7 @@ class Quaternion {
|
|
|
798
757
|
* @param {number} y angle in Y axis in radians
|
|
799
758
|
* @param {number} z angle in Z axis in radians
|
|
800
759
|
*/
|
|
801
|
-
|
|
760
|
+
fromEulerAnglesZXY(x, y, z) {
|
|
802
761
|
const scaled_x = x * 0.5;
|
|
803
762
|
const scaled_y = y * 0.5;
|
|
804
763
|
const scaled_z = z * 0.5;
|
|
@@ -811,8 +770,8 @@ class Quaternion {
|
|
|
811
770
|
const c2 = Math.cos(scaled_y);
|
|
812
771
|
const c3 = Math.cos(scaled_z);
|
|
813
772
|
|
|
814
|
-
const _x = s1 * c2 * c3
|
|
815
|
-
const _y = c1 * s2 * c3
|
|
773
|
+
const _x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
774
|
+
const _y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
816
775
|
const _z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
817
776
|
const _w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
818
777
|
|
|
@@ -820,48 +779,93 @@ class Quaternion {
|
|
|
820
779
|
}
|
|
821
780
|
|
|
822
781
|
/**
|
|
823
|
-
*
|
|
824
|
-
* @source
|
|
825
|
-
* @
|
|
782
|
+
* XYZ order
|
|
783
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
784
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
785
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
786
|
+
* @param {number} x angle in X axis in radians
|
|
787
|
+
* @param {number} y angle in Y axis in radians
|
|
788
|
+
* @param {number} z angle in Z axis in radians
|
|
826
789
|
*/
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
const
|
|
830
|
-
const
|
|
831
|
-
const w = this.w;
|
|
790
|
+
fromEulerAnglesZYX(x, y, z) {
|
|
791
|
+
const scaled_x = x * 0.5;
|
|
792
|
+
const scaled_y = y * 0.5;
|
|
793
|
+
const scaled_z = z * 0.5;
|
|
832
794
|
|
|
833
|
-
const
|
|
834
|
-
const
|
|
835
|
-
const
|
|
836
|
-
const sqz = z * z;
|
|
795
|
+
const s1 = Math.sin(scaled_x);
|
|
796
|
+
const s2 = Math.sin(scaled_y);
|
|
797
|
+
const s3 = Math.sin(scaled_z);
|
|
837
798
|
|
|
838
|
-
const
|
|
799
|
+
const c1 = Math.cos(scaled_x);
|
|
800
|
+
const c2 = Math.cos(scaled_y);
|
|
801
|
+
const c3 = Math.cos(scaled_z);
|
|
839
802
|
|
|
840
|
-
const
|
|
803
|
+
const _x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
804
|
+
const _y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
805
|
+
const _z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
806
|
+
const _w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
841
807
|
|
|
808
|
+
this.set(_x, _y, _z, _w);
|
|
809
|
+
}
|
|
842
810
|
|
|
843
|
-
|
|
811
|
+
/**
|
|
812
|
+
* XYZ order
|
|
813
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
814
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
815
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
816
|
+
* @param {number} x angle in X axis in radians
|
|
817
|
+
* @param {number} y angle in Y axis in radians
|
|
818
|
+
* @param {number} z angle in Z axis in radians
|
|
819
|
+
*/
|
|
820
|
+
fromEulerAnglesYZX(x, y, z) {
|
|
821
|
+
const scaled_x = x * 0.5;
|
|
822
|
+
const scaled_y = y * 0.5;
|
|
823
|
+
const scaled_z = z * 0.5;
|
|
844
824
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
825
|
+
const s1 = Math.sin(scaled_x);
|
|
826
|
+
const s2 = Math.sin(scaled_y);
|
|
827
|
+
const s3 = Math.sin(scaled_z);
|
|
828
|
+
|
|
829
|
+
const c1 = Math.cos(scaled_x);
|
|
830
|
+
const c2 = Math.cos(scaled_y);
|
|
831
|
+
const c3 = Math.cos(scaled_z);
|
|
832
|
+
|
|
833
|
+
const _x = s1 * c2 * c3 + c1 * s2 * s3;
|
|
834
|
+
const _y = c1 * s2 * c3 + s1 * c2 * s3;
|
|
835
|
+
const _z = c1 * c2 * s3 - s1 * s2 * c3;
|
|
836
|
+
const _w = c1 * c2 * c3 - s1 * s2 * s3;
|
|
837
|
+
|
|
838
|
+
this.set(_x, _y, _z, _w);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* XYZ order
|
|
843
|
+
* @source: https://stackoverflow.com/questions/12088610/conversion-between-euler-quaternion-like-in-unity3d-engine
|
|
844
|
+
* @see http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
|
|
845
|
+
* @see https://github.com/mrdoob/three.js/blob/510705cde208b165fd87946b0f8504a1cd6dbe83/src/math/Quaternion.js#L206
|
|
846
|
+
* @param {number} x angle in X axis in radians
|
|
847
|
+
* @param {number} y angle in Y axis in radians
|
|
848
|
+
* @param {number} z angle in Z axis in radians
|
|
849
|
+
*/
|
|
850
|
+
fromEulerAnglesXZY(x, y, z) {
|
|
851
|
+
const scaled_x = x * 0.5;
|
|
852
|
+
const scaled_y = y * 0.5;
|
|
853
|
+
const scaled_z = z * 0.5;
|
|
854
|
+
|
|
855
|
+
const s1 = Math.sin(scaled_x);
|
|
856
|
+
const s2 = Math.sin(scaled_y);
|
|
857
|
+
const s3 = Math.sin(scaled_z);
|
|
858
|
+
|
|
859
|
+
const c1 = Math.cos(scaled_x);
|
|
860
|
+
const c2 = Math.cos(scaled_y);
|
|
861
|
+
const c3 = Math.cos(scaled_z);
|
|
858
862
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
+
const _x = s1 * c2 * c3 - c1 * s2 * s3;
|
|
864
|
+
const _y = c1 * s2 * c3 - s1 * c2 * s3;
|
|
865
|
+
const _z = c1 * c2 * s3 + s1 * s2 * c3;
|
|
866
|
+
const _w = c1 * c2 * c3 + s1 * s2 * s3;
|
|
863
867
|
|
|
864
|
-
|
|
868
|
+
this.set(_x, _y, _z, _w);
|
|
865
869
|
}
|
|
866
870
|
|
|
867
871
|
/**
|
|
@@ -1204,6 +1208,17 @@ class Quaternion {
|
|
|
1204
1208
|
this.set(_x, _y, _z, _w);
|
|
1205
1209
|
}
|
|
1206
1210
|
|
|
1211
|
+
/**
|
|
1212
|
+
* @see https://github.com/gareth-cross/quat/blob/master/include/quaternion.hpp
|
|
1213
|
+
* TODO implement
|
|
1214
|
+
* @param {Quaternion} a
|
|
1215
|
+
* @param {Quaternion} b
|
|
1216
|
+
* @param {number} t
|
|
1217
|
+
*/
|
|
1218
|
+
quaternionsInterpolateRungeKutta4(a, b, t) {
|
|
1219
|
+
throw new Error('Not Implemented');
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1207
1222
|
/**
|
|
1208
1223
|
*
|
|
1209
1224
|
* @param {function} handler
|
|
@@ -162,8 +162,8 @@ test('to/from euler YXZ consistency', () => {
|
|
|
162
162
|
|
|
163
163
|
const u = new Vector3();
|
|
164
164
|
|
|
165
|
-
r.
|
|
166
|
-
r.
|
|
165
|
+
r.fromEulerAnglesXYZ(x, y, z);
|
|
166
|
+
r.toEulerAnglesXYZ(u);
|
|
167
167
|
|
|
168
168
|
expect(u.x).toBeCloseTo(x);
|
|
169
169
|
expect(u.y).toBeCloseTo(y);
|
|
@@ -177,4 +177,49 @@ test('to/from euler YXZ consistency', () => {
|
|
|
177
177
|
check(1, 0, 1);
|
|
178
178
|
check(1, 1, 0);
|
|
179
179
|
check(1, 1, 1);
|
|
180
|
+
|
|
181
|
+
check(0, 0, -1);
|
|
182
|
+
check(0, -1, 0);
|
|
183
|
+
check(0, -1, -1);
|
|
184
|
+
check(-1, 0, 0);
|
|
185
|
+
check(-1, 0, -1);
|
|
186
|
+
check(-1, -1, 0);
|
|
187
|
+
check(-1, -1, -1);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* See https://www.andre-gaschler.com/rotationconverter/
|
|
193
|
+
*/
|
|
194
|
+
test('toEulerAnglesXYZ', () => {
|
|
195
|
+
|
|
196
|
+
function check(quat, euler) {
|
|
197
|
+
|
|
198
|
+
const q = new Quaternion(...quat);
|
|
199
|
+
|
|
200
|
+
const r = new Vector3();
|
|
201
|
+
q.toEulerAnglesXYZ(r)
|
|
202
|
+
|
|
203
|
+
expect(r.x).toBeCloseTo(euler[0]);
|
|
204
|
+
expect(r.y).toBeCloseTo(euler[1]);
|
|
205
|
+
expect(r.z).toBeCloseTo(euler[2]);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
check([0.4794255, 0, 0, 0.8775826], [1, 0, 0]);
|
|
210
|
+
check([0, 0.4794255, 0, 0.8775826], [0, 1, 0]);
|
|
211
|
+
check([0, 0, 0.4794255, 0.8775826], [0, 0, 1]);
|
|
212
|
+
|
|
213
|
+
check([0.4207355, 0.4207355, 0.2298488, 0.7701512], [1, 1, 0]);
|
|
214
|
+
check([0.2298488, 0.4207355, 0.4207355, 0.7701512], [0, 1, 1]);
|
|
215
|
+
check([0.4207355, -0.2298488, 0.4207355, 0.7701512], [1, 0, 1]);
|
|
216
|
+
|
|
217
|
+
check([0.5709415, 0.1675188, 0.5709415, 0.5656758], [1, 1, 1]);
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
check([-0.4794255, 0, 0, 0.8775826], [-1, 0, 0]);
|
|
221
|
+
check([0, -0.4794255, 0, 0.8775826], [0, -1, 0]);
|
|
222
|
+
check([0, 0, -0.4794255, 0.8775826], [0, 0, -1]);
|
|
223
|
+
|
|
224
|
+
|
|
180
225
|
});
|