@woosh/meep-engine 2.69.0 → 2.71.0
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/build/bundle-worker-image-decoder.js +1 -1
- package/build/bundle-worker-terrain.js +1 -1
- package/build/meep.cjs +498 -429
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +498 -429
- package/package.json +1 -1
- package/src/core/__module.js +1 -0
- package/src/core/binary/BinaryBuffer.js +37 -31
- package/src/core/bvh2/binary/2/BinaryUint32BVH.js +21 -24
- package/src/core/bvh2/binary/2/BinaryUint32BVH.spec.js +2 -4
- package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +3 -2
- package/src/core/geom/3d/morton/v3_morton_encode_bounded.js +34 -0
- package/src/core/geom/3d/morton/v3_morton_encode_transformed.js +2 -1
- package/src/core/geom/3d/quaternion/quat3_createFromAxisAngle.js +11 -0
- package/src/core/geom/3d/quaternion/quat_decode_from_uint32.js +53 -0
- package/src/core/geom/3d/quaternion/quat_encode_to_uint32.js +105 -0
- package/src/core/geom/Quaternion.js +8 -142
- package/src/core/geom/Vector2.js +6 -7
- package/src/core/geom/Vector3.js +15 -82
- package/src/core/geom/vec3/v3_binary_equality_decode.js +44 -0
- package/src/core/geom/vec3/v3_binary_equality_encode.js +47 -0
- package/src/core/math/remap.js +5 -1
- package/src/core/math/statistics/computeStatisticalPartialMedian.js +1 -1
- package/src/core/primitives/numbers/computeHashFloat.js +2 -2
- package/src/core/process/task/Task.js +53 -34
- package/src/engine/achievements/AchievementManager.js +19 -19
- package/src/engine/animation/curve/compression/prototypeCurveCompression.js +6 -6
- package/src/engine/animation/curve/draw/build_plot_entity_from_array.js +11 -6
- package/src/engine/ecs/dynamic_actions/DynamicActor.js +5 -10
- package/src/engine/ecs/dynamic_actions/DynamicActorSystem.js +82 -89
- package/src/engine/ecs/dynamic_actions/RuleExecution.js +10 -12
- package/src/engine/ecs/gui/GUIElement.js +44 -61
- package/src/engine/ecs/gui/GUIElementSystem.js +26 -24
- package/src/engine/ecs/gui/hud/HeadsUpDisplay.js +12 -15
- package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +15 -15
- package/src/engine/ecs/gui/parallax/GuiElementParallax.js +3 -3
- package/src/engine/ecs/gui/parallax/GuiElementParallaxSystem.js +2 -2
- package/src/engine/ecs/gui/position/ViewportPosition.js +5 -50
- package/src/engine/ecs/gui/position/ViewportPositionSerializationAdapter.js +42 -0
- package/src/engine/ecs/transform/Transform.js +8 -9
- package/src/engine/ecs/transform/TransformSerializationAdapter.js +20 -14
- package/src/engine/graphics/ecs/mesh/Mesh.js +11 -11
- package/src/engine/graphics/impostors/octahedral/prototypeBaker.js +20 -20
- package/src/engine/graphics/texture/sprite/prototypeSpriteCutoutGeometry.js +12 -12
- package/src/engine/navigation/ecs/components/PathSerializationAdapter.js +1 -4
- package/src/core/binary/ValidatingBitSetWrapper.js +0 -81
- package/src/core/binary/jsonToStringToByteArray.js +0 -27
- package/src/engine/ecs/components/AreaOfEffect.js +0 -12
- package/src/engine/ecs/components/Mortality.js +0 -27
- package/src/engine/ecs/systems/AreaOfEffectSystem.js +0 -48
package/package.json
CHANGED
package/src/core/__module.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { assert } from "../assert.js";
|
|
6
6
|
import { array_copy } from "../collection/array/array_copy.js";
|
|
7
|
+
import { typed_array_copy } from "../collection/array/typed/typed_array_copy.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
*
|
|
@@ -142,8 +143,7 @@ export class BinaryBuffer {
|
|
|
142
143
|
const newData = new Uint8Array(capacity);
|
|
143
144
|
|
|
144
145
|
//copy old data
|
|
145
|
-
|
|
146
|
-
newData.set(oldData.subarray(0, copyLength), 0);
|
|
146
|
+
typed_array_copy(oldData, newData);
|
|
147
147
|
|
|
148
148
|
this.data = newData.buffer;
|
|
149
149
|
this.__data_uint8 = newData;
|
|
@@ -152,15 +152,24 @@ export class BinaryBuffer {
|
|
|
152
152
|
this.capacity = capacity;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @param {number} min_capacity
|
|
158
|
+
*/
|
|
159
|
+
ensureCapacity(min_capacity) {
|
|
160
|
+
const existing_capacity = this.capacity;
|
|
161
|
+
|
|
162
|
+
if (existing_capacity >= min_capacity) {
|
|
163
|
+
return;
|
|
163
164
|
}
|
|
165
|
+
|
|
166
|
+
const new_capacity = Math.ceil(Math.max(
|
|
167
|
+
min_capacity,
|
|
168
|
+
existing_capacity * this.__growFactor,
|
|
169
|
+
existing_capacity + MIN_GROWTH_STEP
|
|
170
|
+
));
|
|
171
|
+
|
|
172
|
+
this.setCapacity(new_capacity);
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
readFloat32() {
|
|
@@ -825,16 +834,14 @@ export class BinaryBuffer {
|
|
|
825
834
|
//mark non-NULL
|
|
826
835
|
this.writeUint32(len);
|
|
827
836
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
let at = startPosition; // output position
|
|
831
|
-
|
|
832
|
-
let tlen = Math.max(32, len + (len >> 1) + 7); // 1.5x size
|
|
837
|
+
let cursor = this.position; // output position
|
|
833
838
|
|
|
834
|
-
|
|
839
|
+
const expected_byte_size = Math.max(32, len + (len >> 1) + 7); // 1.5x size
|
|
835
840
|
|
|
836
|
-
|
|
841
|
+
this.ensureCapacity(expected_byte_size + cursor);
|
|
837
842
|
|
|
843
|
+
let target = this.__data_uint8;
|
|
844
|
+
let capacity = this.capacity;
|
|
838
845
|
|
|
839
846
|
while (pos < len) {
|
|
840
847
|
let value = string.charCodeAt(pos++);
|
|
@@ -853,37 +860,36 @@ export class BinaryBuffer {
|
|
|
853
860
|
}
|
|
854
861
|
|
|
855
862
|
// expand the buffer if we couldn't write 4 bytes
|
|
856
|
-
if (
|
|
857
|
-
tlen += 8; // minimum extra
|
|
858
|
-
tlen *= (1.0 + (pos / len) * 2); // take 2x the remaining
|
|
859
|
-
tlen = (tlen >> 3) << 3; // 8 byte offset
|
|
863
|
+
if (cursor + 4 > capacity) {
|
|
860
864
|
|
|
861
|
-
this.ensureCapacity(
|
|
865
|
+
this.ensureCapacity(cursor + 4);
|
|
862
866
|
|
|
867
|
+
// rebind variables
|
|
868
|
+
capacity = this.capacity;
|
|
863
869
|
target = this.__data_uint8;
|
|
864
870
|
}
|
|
865
871
|
|
|
866
872
|
if ((value & 0xffffff80) === 0) { // 1-byte
|
|
867
|
-
target[
|
|
873
|
+
target[cursor++] = value; // ASCII
|
|
868
874
|
continue;
|
|
869
875
|
} else if ((value & 0xfffff800) === 0) { // 2-byte
|
|
870
|
-
target[
|
|
876
|
+
target[cursor++] = ((value >> 6) & 0x1f) | 0xc0;
|
|
871
877
|
} else if ((value & 0xffff0000) === 0) { // 3-byte
|
|
872
|
-
target[
|
|
873
|
-
target[
|
|
878
|
+
target[cursor++] = ((value >> 12) & 0x0f) | 0xe0;
|
|
879
|
+
target[cursor++] = ((value >> 6) & 0x3f) | 0x80;
|
|
874
880
|
} else if ((value & 0xffe00000) === 0) { // 4-byte
|
|
875
|
-
target[
|
|
876
|
-
target[
|
|
877
|
-
target[
|
|
881
|
+
target[cursor++] = ((value >> 18) & 0x07) | 0xf0;
|
|
882
|
+
target[cursor++] = ((value >> 12) & 0x3f) | 0x80;
|
|
883
|
+
target[cursor++] = ((value >> 6) & 0x3f) | 0x80;
|
|
878
884
|
} else {
|
|
879
885
|
// FIXME: do we care
|
|
880
886
|
continue;
|
|
881
887
|
}
|
|
882
888
|
|
|
883
|
-
target[
|
|
889
|
+
target[cursor++] = (value & 0x3f) | 0x80;
|
|
884
890
|
}
|
|
885
891
|
|
|
886
|
-
this.position =
|
|
892
|
+
this.position = cursor;
|
|
887
893
|
}
|
|
888
894
|
|
|
889
895
|
/**
|
|
@@ -2,10 +2,11 @@ import { assert } from "../../../assert.js";
|
|
|
2
2
|
import { ceilPowerOfTwo } from "../../../binary/operations/ceilPowerOfTwo.js";
|
|
3
3
|
import { array_copy } from "../../../collection/array/array_copy.js";
|
|
4
4
|
import { array_swap } from "../../../collection/array/array_swap.js";
|
|
5
|
+
import { SCRATCH_UINT32_TRAVERSAL_STACK } from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
|
|
5
6
|
import { aabb3_array_combine } from "../../../geom/3d/aabb/aabb3_array_combine.js";
|
|
6
7
|
import { aabb3_array_set } from "../../../geom/3d/aabb/aabb3_array_set.js";
|
|
7
8
|
import { aabb3_compute_half_surface_area } from "../../../geom/3d/aabb/aabb3_compute_half_surface_area.js";
|
|
8
|
-
import {
|
|
9
|
+
import { v3_morton_encode_bounded } from "../../../geom/3d/morton/v3_morton_encode_bounded.js";
|
|
9
10
|
import { max2 } from "../../../math/max2.js";
|
|
10
11
|
import { max3 } from "../../../math/max3.js";
|
|
11
12
|
import { min2 } from "../../../math/min2.js";
|
|
@@ -54,10 +55,10 @@ function copy_box_zero_size(data, destination, source) {
|
|
|
54
55
|
* Assumes data will be normalized to 0...1 value range
|
|
55
56
|
* @param {Float32Array} data
|
|
56
57
|
* @param {number} address
|
|
57
|
-
* @param {number[]}
|
|
58
|
+
* @param {number[]} bounds
|
|
58
59
|
* @returns {number}
|
|
59
60
|
*/
|
|
60
|
-
function build_morton(data, address,
|
|
61
|
+
function build_morton(data, address, bounds) {
|
|
61
62
|
|
|
62
63
|
const x0 = data[address];
|
|
63
64
|
const y0 = data[address + 1];
|
|
@@ -66,17 +67,15 @@ function build_morton(data, address, matrix) {
|
|
|
66
67
|
const y1 = data[address + 4];
|
|
67
68
|
const z1 = data[address + 5];
|
|
68
69
|
|
|
69
|
-
const cx = (x0 + x1)
|
|
70
|
-
const cy = (y0 + y1)
|
|
71
|
-
const cz = (z0 + z1)
|
|
70
|
+
const cx = (x0 + x1) * 0.5;
|
|
71
|
+
const cy = (y0 + y1) * 0.5;
|
|
72
|
+
const cz = (z0 + z1) * 0.5;
|
|
72
73
|
|
|
73
|
-
return
|
|
74
|
-
// return v3_morton_encode_transformed(cx, cy, cz, matrix);
|
|
74
|
+
return v3_morton_encode_bounded(cx, cy, cz, bounds);
|
|
75
75
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
const
|
|
79
|
-
const stack = [];
|
|
78
|
+
const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
|
|
80
79
|
|
|
81
80
|
export class BinaryUint32BVH {
|
|
82
81
|
/**
|
|
@@ -307,17 +306,15 @@ export class BinaryUint32BVH {
|
|
|
307
306
|
* @private
|
|
308
307
|
*/
|
|
309
308
|
__compute_bounds_area_of_3_boxes(a, b, c) {
|
|
310
|
-
this.
|
|
311
|
-
this.readBounds(b, scratch_box_0, 6);
|
|
312
|
-
this.readBounds(c, scratch_box_0, 12);
|
|
309
|
+
const float32 = this.__data_float32;
|
|
313
310
|
|
|
314
|
-
const x0 = min3(
|
|
315
|
-
const y0 = min3(
|
|
316
|
-
const z0 = min3(
|
|
311
|
+
const x0 = min3(float32[a + 0], float32[b + 0], float32[c + 0]);
|
|
312
|
+
const y0 = min3(float32[a + 1], float32[b + 1], float32[c + 1]);
|
|
313
|
+
const z0 = min3(float32[a + 2], float32[b + 2], float32[c + 2]);
|
|
317
314
|
|
|
318
|
-
const x1 = max3(
|
|
319
|
-
const y1 = max3(
|
|
320
|
-
const z1 = max3(
|
|
315
|
+
const x1 = max3(float32[a + 3], float32[b + 3], float32[c + 3]);
|
|
316
|
+
const y1 = max3(float32[a + 4], float32[b + 4], float32[c + 4]);
|
|
317
|
+
const z1 = max3(float32[a + 5], float32[b + 5], float32[c + 5]);
|
|
321
318
|
|
|
322
319
|
return aabb3_compute_half_surface_area(x0, y0, z0, x1, y1, z1);
|
|
323
320
|
}
|
|
@@ -369,9 +366,9 @@ export class BinaryUint32BVH {
|
|
|
369
366
|
|
|
370
367
|
/**
|
|
371
368
|
* Sort leaf nodes according to their morton codes
|
|
372
|
-
* @param {number[]}
|
|
369
|
+
* @param {number[]} bounds
|
|
373
370
|
*/
|
|
374
|
-
sort_morton(
|
|
371
|
+
sort_morton(bounds) {
|
|
375
372
|
|
|
376
373
|
const leaf_block_address = this.__node_count_binary * BVH_BINARY_NODE_SIZE;
|
|
377
374
|
|
|
@@ -401,15 +398,15 @@ export class BinaryUint32BVH {
|
|
|
401
398
|
|
|
402
399
|
const pivot_address = pivotIndex * BVH_LEAF_NODE_SIZE + leaf_block_address;
|
|
403
400
|
|
|
404
|
-
const pivot = build_morton(data, pivot_address,
|
|
401
|
+
const pivot = build_morton(data, pivot_address, bounds);
|
|
405
402
|
|
|
406
403
|
/* partition */
|
|
407
404
|
while (i <= j) {
|
|
408
|
-
while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address,
|
|
405
|
+
while (build_morton(data, i * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) < pivot) {
|
|
409
406
|
i++;
|
|
410
407
|
}
|
|
411
408
|
|
|
412
|
-
while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address,
|
|
409
|
+
while (build_morton(data, j * BVH_LEAF_NODE_SIZE + leaf_block_address, bounds) > pivot) {
|
|
413
410
|
j--;
|
|
414
411
|
}
|
|
415
412
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
//
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
import Vector3 from "../../Vector3.js";
|
|
5
|
-
import Quaternion, { quat3_createFromAxisAngle } from "../../Quaternion.js";
|
|
6
4
|
import { max2 } from "../../../math/max2.js";
|
|
5
|
+
import Quaternion from "../../Quaternion.js";
|
|
6
|
+
import Vector3 from "../../Vector3.js";
|
|
7
|
+
import { quat3_createFromAxisAngle } from "../quaternion/quat3_createFromAxisAngle.js";
|
|
7
8
|
|
|
8
9
|
const tangent = new Vector3();
|
|
9
10
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { mortonEncode_magicbits } from "./mortonEncode_magicbits.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {number} x
|
|
5
|
+
* @param {number} y
|
|
6
|
+
* @param {number} z
|
|
7
|
+
* @param {number[]} bounds
|
|
8
|
+
* @returns {number}
|
|
9
|
+
*/
|
|
10
|
+
export function v3_morton_encode_bounded(x, y, z, bounds) {
|
|
11
|
+
|
|
12
|
+
const bounds_x0 = bounds[0];
|
|
13
|
+
const bounds_y0 = bounds[1];
|
|
14
|
+
const bounds_z0 = bounds[2];
|
|
15
|
+
|
|
16
|
+
const bounds_x1 = bounds[3];
|
|
17
|
+
const bounds_y1 = bounds[4];
|
|
18
|
+
const bounds_z1 = bounds[5];
|
|
19
|
+
|
|
20
|
+
const bounds_span_x = bounds_x1 - bounds_x0;
|
|
21
|
+
const bounds_span_y = bounds_y1 - bounds_y0;
|
|
22
|
+
const bounds_span_z = bounds_z1 - bounds_z0;
|
|
23
|
+
|
|
24
|
+
// scale to 10 bits
|
|
25
|
+
const ndc_x = 1023 * (x - bounds_x0) / bounds_span_x;
|
|
26
|
+
const ndc_y = 1023 * (y - bounds_y0) / bounds_span_y;
|
|
27
|
+
const ndc_z = 1023 * (z - bounds_z0) / bounds_span_z;
|
|
28
|
+
|
|
29
|
+
return mortonEncode_magicbits(
|
|
30
|
+
Math.round(ndc_x),
|
|
31
|
+
Math.round(ndc_y),
|
|
32
|
+
Math.round(ndc_z)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { mortonEncode_magicbits } from "./mortonEncode_magicbits.js";
|
|
2
1
|
import { clamp } from "../../../math/clamp.js";
|
|
2
|
+
import { mortonEncode_magicbits } from "./mortonEncode_magicbits.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Assumes that coordinates will be mapped to -1..1 range after transform
|
|
@@ -35,3 +35,4 @@ export function v3_morton_encode_transformed(x, y, z, matrix) {
|
|
|
35
35
|
Math.round(pz)
|
|
36
36
|
);
|
|
37
37
|
}
|
|
38
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* just in case you need that function also
|
|
3
|
+
* @param {Vector3} axis
|
|
4
|
+
* @param {number} angle
|
|
5
|
+
* @param {Quaternion} result
|
|
6
|
+
*/
|
|
7
|
+
export function quat3_createFromAxisAngle(axis, angle, result) {
|
|
8
|
+
const halfAngle = angle * .5;
|
|
9
|
+
const s = Math.sin(halfAngle);
|
|
10
|
+
result.set(axis.x * s, axis.y * s, axis.z * s, Math.cos(halfAngle));
|
|
11
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const K = Math.SQRT1_2 / 511;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Based on GDC talk from Bungie on destiny, compressing quaternions for animation
|
|
5
|
+
* @param {number[]} output
|
|
6
|
+
* @param {number} output_offset
|
|
7
|
+
* @param {number} value
|
|
8
|
+
*/
|
|
9
|
+
export function quat_decode_from_uint32(output, output_offset, value) {
|
|
10
|
+
//read components
|
|
11
|
+
const max = value & 0x3;
|
|
12
|
+
|
|
13
|
+
const iv0 = (value >> 2) & 0x3FF;
|
|
14
|
+
const iv1 = (value >> 12) & 0x3FF;
|
|
15
|
+
const iv2 = (value >> 22) & 0x3FF;
|
|
16
|
+
|
|
17
|
+
//scale components back to quaternion range
|
|
18
|
+
const v0 = iv0 * K - Math.SQRT1_2;
|
|
19
|
+
const v1 = iv1 * K - Math.SQRT1_2;
|
|
20
|
+
const v2 = iv2 * K - Math.SQRT1_2;
|
|
21
|
+
|
|
22
|
+
//restore dropped component using quaternion identity: x^2 + y^2 + z^2 + w^2 = 1
|
|
23
|
+
const dropped_2 = 1 - v0 * v0 - v1 * v1 - v2 * v2;
|
|
24
|
+
const dropped = Math.sqrt(dropped_2);
|
|
25
|
+
|
|
26
|
+
let x, y, z, w;
|
|
27
|
+
if (max === 0) {
|
|
28
|
+
x = dropped
|
|
29
|
+
y = v0
|
|
30
|
+
z = v1
|
|
31
|
+
w = v2
|
|
32
|
+
} else if (max === 1) {
|
|
33
|
+
x = v0
|
|
34
|
+
y = dropped
|
|
35
|
+
z = v1
|
|
36
|
+
w = v2
|
|
37
|
+
} else if (max === 2) {
|
|
38
|
+
x = v0
|
|
39
|
+
y = v1
|
|
40
|
+
z = dropped
|
|
41
|
+
w = v2
|
|
42
|
+
} else {
|
|
43
|
+
x = v0
|
|
44
|
+
y = v1
|
|
45
|
+
z = v2
|
|
46
|
+
w = dropped
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
output[output_offset] = x;
|
|
50
|
+
output[output_offset + 1] = y;
|
|
51
|
+
output[output_offset + 2] = z;
|
|
52
|
+
output[output_offset + 3] = w;
|
|
53
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { assert } from "../../../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Based on GDC talk from Bungie on destiny, compressing quaternions for animation
|
|
5
|
+
* @param {number} x
|
|
6
|
+
* @param {number} y
|
|
7
|
+
* @param {number} z
|
|
8
|
+
* @param {number} w
|
|
9
|
+
* @returns {number}
|
|
10
|
+
*/
|
|
11
|
+
export function quat_encode_to_uint32(x, y, z, w) {
|
|
12
|
+
|
|
13
|
+
const absX = Math.abs(x);
|
|
14
|
+
const absY = Math.abs(y);
|
|
15
|
+
const absZ = Math.abs(z);
|
|
16
|
+
const absW = Math.abs(w);
|
|
17
|
+
|
|
18
|
+
let v0, v1, v2, dropped, max;
|
|
19
|
+
|
|
20
|
+
//pick max component
|
|
21
|
+
if (absY > absX) {
|
|
22
|
+
if (absY > absZ) {
|
|
23
|
+
if (absY > absW) {
|
|
24
|
+
//absY is max
|
|
25
|
+
max = 1;
|
|
26
|
+
} else {
|
|
27
|
+
//absW is max
|
|
28
|
+
max = 3;
|
|
29
|
+
}
|
|
30
|
+
} else if (absZ > absW) {
|
|
31
|
+
//absZ is max
|
|
32
|
+
max = 2;
|
|
33
|
+
} else {
|
|
34
|
+
//absW is max
|
|
35
|
+
max = 3;
|
|
36
|
+
}
|
|
37
|
+
} else if (absX > absZ) {
|
|
38
|
+
if (absX > absW) {
|
|
39
|
+
max = 0;
|
|
40
|
+
} else {
|
|
41
|
+
max = 3;
|
|
42
|
+
}
|
|
43
|
+
} else if (absZ > absW) {
|
|
44
|
+
max = 2;
|
|
45
|
+
} else {
|
|
46
|
+
max = 3;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
//max will be dropped
|
|
51
|
+
if (max === 0) {
|
|
52
|
+
//dropping x
|
|
53
|
+
v0 = y;
|
|
54
|
+
v1 = z;
|
|
55
|
+
v2 = w;
|
|
56
|
+
|
|
57
|
+
dropped = x;
|
|
58
|
+
} else if (max === 1) {
|
|
59
|
+
//dropping y
|
|
60
|
+
v0 = x;
|
|
61
|
+
v1 = z;
|
|
62
|
+
v2 = w;
|
|
63
|
+
|
|
64
|
+
dropped = y;
|
|
65
|
+
} else if (max === 2) {
|
|
66
|
+
//dropping z
|
|
67
|
+
v0 = x;
|
|
68
|
+
v1 = y;
|
|
69
|
+
v2 = w;
|
|
70
|
+
|
|
71
|
+
dropped = z;
|
|
72
|
+
} else {
|
|
73
|
+
//dropping w
|
|
74
|
+
v0 = x;
|
|
75
|
+
v1 = y;
|
|
76
|
+
v2 = z;
|
|
77
|
+
|
|
78
|
+
dropped = w;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (dropped < 0) {
|
|
82
|
+
//reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
|
|
83
|
+
v0 = -v0;
|
|
84
|
+
v1 = -v1;
|
|
85
|
+
v2 = -v2;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const l = Math.hypot(v0, v1, v2, dropped);
|
|
89
|
+
const m = 511 / (l * Math.SQRT1_2);
|
|
90
|
+
|
|
91
|
+
//re-normalize the remaining components to 10 bit UINT value
|
|
92
|
+
const oV0 = Math.round(v0 * m + 511);
|
|
93
|
+
const oV1 = Math.round(v1 * m + 511);
|
|
94
|
+
const oV2 = Math.round(v2 * m + 511);
|
|
95
|
+
|
|
96
|
+
assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
|
|
97
|
+
assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
|
|
98
|
+
assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
return (max & 0x3)
|
|
102
|
+
| ((oV0 & 0x3FF) << 2)
|
|
103
|
+
| ((oV1 & 0x3FF) << 12)
|
|
104
|
+
| ((oV2 & 0x3FF) << 22);
|
|
105
|
+
}
|
|
@@ -6,31 +6,21 @@
|
|
|
6
6
|
import { assert } from "../assert.js";
|
|
7
7
|
import Signal from "../events/signal/Signal.js";
|
|
8
8
|
import { clamp } from "../math/clamp.js";
|
|
9
|
+
import { EPSILON } from "../math/EPSILON.js";
|
|
10
|
+
import { epsilonEquals } from "../math/epsilonEquals.js";
|
|
9
11
|
import { lerp } from "../math/lerp.js";
|
|
10
|
-
import Vector3 from "./Vector3.js";
|
|
11
|
-
import { v3_dot } from "./vec3/v3_dot.js";
|
|
12
12
|
import { min2 } from "../math/min2.js";
|
|
13
13
|
import { computeHashFloat } from "../primitives/numbers/computeHashFloat.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
14
|
+
import { quat_decode_from_uint32 } from "./3d/quaternion/quat_decode_from_uint32.js";
|
|
15
|
+
import { quat_encode_to_uint32 } from "./3d/quaternion/quat_encode_to_uint32.js";
|
|
16
|
+
import { v3_dot } from "./vec3/v3_dot.js";
|
|
17
|
+
import Vector3 from "./Vector3.js";
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
const forward = new Vector3();
|
|
19
21
|
const up = new Vector3();
|
|
20
22
|
const right = new Vector3();
|
|
21
23
|
|
|
22
|
-
/**
|
|
23
|
-
* just in case you need that function also
|
|
24
|
-
* @param {Vector3} axis
|
|
25
|
-
* @param {number} angle
|
|
26
|
-
* @param {Quaternion} result
|
|
27
|
-
*/
|
|
28
|
-
export function quat3_createFromAxisAngle(axis, angle, result) {
|
|
29
|
-
const halfAngle = angle * .5;
|
|
30
|
-
const s = Math.sin(halfAngle);
|
|
31
|
-
result.set(axis.x * s, axis.y * s, axis.z * s, Math.cos(halfAngle));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
24
|
class Quaternion {
|
|
35
25
|
/**
|
|
36
26
|
*
|
|
@@ -1453,31 +1443,7 @@ class Quaternion {
|
|
|
1453
1443
|
* @param {number} value
|
|
1454
1444
|
*/
|
|
1455
1445
|
decodeFromUint32(value) {
|
|
1456
|
-
|
|
1457
|
-
const max = value & 0x3;
|
|
1458
|
-
|
|
1459
|
-
const iv0 = (value >> 2) & 0x3FF;
|
|
1460
|
-
const iv1 = (value >> 12) & 0x3FF;
|
|
1461
|
-
const iv2 = (value >> 22) & 0x3FF;
|
|
1462
|
-
|
|
1463
|
-
//scale components back to quaternion range
|
|
1464
|
-
const v0 = (iv0 / 511 - 1) * K_CONST;
|
|
1465
|
-
const v1 = (iv1 / 511 - 1) * K_CONST;
|
|
1466
|
-
const v2 = (iv2 / 511 - 1) * K_CONST;
|
|
1467
|
-
|
|
1468
|
-
//restore dropped component using quaternion identity: x^2 + y^2 + z^2 + w^2 = 1
|
|
1469
|
-
const dropped_2 = 1 - v0 * v0 - v1 * v1 - v2 * v2;
|
|
1470
|
-
const dropped = Math.sqrt(dropped_2);
|
|
1471
|
-
|
|
1472
|
-
if (max === 0) {
|
|
1473
|
-
this.set(dropped, v0, v1, v2);
|
|
1474
|
-
} else if (max === 1) {
|
|
1475
|
-
this.set(v0, dropped, v1, v2);
|
|
1476
|
-
} else if (max === 2) {
|
|
1477
|
-
this.set(v0, v1, dropped, v2);
|
|
1478
|
-
} else {
|
|
1479
|
-
this.set(v0, v1, v2, dropped);
|
|
1480
|
-
}
|
|
1446
|
+
quat_decode_from_uint32(this, 0, value);
|
|
1481
1447
|
}
|
|
1482
1448
|
|
|
1483
1449
|
/**
|
|
@@ -1485,107 +1451,7 @@ class Quaternion {
|
|
|
1485
1451
|
* @returns {number}
|
|
1486
1452
|
*/
|
|
1487
1453
|
encodeToUint32() {
|
|
1488
|
-
|
|
1489
|
-
const y = this.y;
|
|
1490
|
-
const z = this.z;
|
|
1491
|
-
const w = this.w;
|
|
1492
|
-
|
|
1493
|
-
const absX = Math.abs(x);
|
|
1494
|
-
const absY = Math.abs(y);
|
|
1495
|
-
const absZ = Math.abs(z);
|
|
1496
|
-
const absW = Math.abs(w);
|
|
1497
|
-
|
|
1498
|
-
let max = 0;
|
|
1499
|
-
|
|
1500
|
-
//pick max component
|
|
1501
|
-
if (absY > absX) {
|
|
1502
|
-
if (absY > absZ) {
|
|
1503
|
-
if (absY > absW) {
|
|
1504
|
-
//absY is max
|
|
1505
|
-
max = 1;
|
|
1506
|
-
} else {
|
|
1507
|
-
//absW is max
|
|
1508
|
-
max = 3;
|
|
1509
|
-
}
|
|
1510
|
-
} else if (absZ > absW) {
|
|
1511
|
-
//absZ is max
|
|
1512
|
-
max = 2;
|
|
1513
|
-
} else {
|
|
1514
|
-
//absW is max
|
|
1515
|
-
max = 3;
|
|
1516
|
-
}
|
|
1517
|
-
} else if (absX > absZ) {
|
|
1518
|
-
if (absX > absW) {
|
|
1519
|
-
max = 0;
|
|
1520
|
-
} else {
|
|
1521
|
-
max = 3;
|
|
1522
|
-
}
|
|
1523
|
-
} else if (absZ > absW) {
|
|
1524
|
-
max = 2;
|
|
1525
|
-
} else {
|
|
1526
|
-
max = 3;
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
let v0, v1, v2, dropped;
|
|
1530
|
-
|
|
1531
|
-
//max will be dropped
|
|
1532
|
-
if (max === 0) {
|
|
1533
|
-
//dropping x
|
|
1534
|
-
v0 = y;
|
|
1535
|
-
v1 = z;
|
|
1536
|
-
v2 = w;
|
|
1537
|
-
|
|
1538
|
-
dropped = x;
|
|
1539
|
-
} else if (max === 1) {
|
|
1540
|
-
//dropping y
|
|
1541
|
-
v0 = x;
|
|
1542
|
-
v1 = z;
|
|
1543
|
-
v2 = w;
|
|
1544
|
-
|
|
1545
|
-
dropped = y;
|
|
1546
|
-
} else if (max === 2) {
|
|
1547
|
-
//dropping z
|
|
1548
|
-
v0 = x;
|
|
1549
|
-
v1 = y;
|
|
1550
|
-
v2 = w;
|
|
1551
|
-
|
|
1552
|
-
dropped = z;
|
|
1553
|
-
} else {
|
|
1554
|
-
//dropping w
|
|
1555
|
-
v0 = x;
|
|
1556
|
-
v1 = y;
|
|
1557
|
-
v2 = z;
|
|
1558
|
-
|
|
1559
|
-
dropped = w;
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
if (dropped < 0) {
|
|
1563
|
-
//reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
|
|
1564
|
-
v0 = -v0;
|
|
1565
|
-
v1 = -v1;
|
|
1566
|
-
v2 = -v2;
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
const l = Math.sqrt(x * x + y * y + z * z + w * w);
|
|
1570
|
-
const m = 1 / (l * K_CONST);
|
|
1571
|
-
|
|
1572
|
-
//re-normalize the remaining components to 10 bit UINT value
|
|
1573
|
-
const oV0 = Math.round((v0 * m + 1) * 511);
|
|
1574
|
-
const oV1 = Math.round((v1 * m + 1) * 511);
|
|
1575
|
-
const oV2 = Math.round((v2 * m + 1) * 511);
|
|
1576
|
-
|
|
1577
|
-
assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
|
|
1578
|
-
assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
|
|
1579
|
-
assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
const result = (max & 0x3)
|
|
1583
|
-
| ((oV0 & 0x3FF) << 2)
|
|
1584
|
-
| ((oV1 & 0x3FF) << 12)
|
|
1585
|
-
| ((oV2 & 0x3FF) << 22)
|
|
1586
|
-
;
|
|
1587
|
-
|
|
1588
|
-
return result;
|
|
1454
|
+
return quat_encode_to_uint32(this.x, this.y, this.z, this.w);
|
|
1589
1455
|
}
|
|
1590
1456
|
|
|
1591
1457
|
/**
|