@woosh/meep-engine 2.68.0 → 2.70.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 +1090 -1581
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +1090 -1581
- 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 +76 -52
- package/src/core/bvh2/binary/2/BinaryUint32BVH.spec.js +5 -7
- package/src/core/bvh2/binary/2/bvh32_query_user_data_overlaps_clipping_volume.js +94 -0
- package/src/core/bvh2/binary/2/bvh32_query_user_data_ray.js +17 -18
- package/src/core/bvh2/bvh3/query/BVHQueryIntersectsFrustum.js +4 -2
- package/src/core/geom/3d/aabb/AABB3.js +14 -14
- package/src/core/geom/3d/aabb/aabb3_array_intersects_clipping_volume_array.js +30 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_clipping_volume_array.js +51 -0
- package/src/core/geom/3d/cone/compute_bounding_cone_of_2_cones.js +3 -2
- package/src/core/geom/3d/frustum/{read_frustum_planes_to_array.js → read_three_planes_to_array.js} +5 -3
- 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 +106 -0
- package/src/core/geom/3d/triangle/triangle_intersects_clipping_volume.js +51 -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/primitives/numbers/computeHashFloat.js +2 -2
- package/src/engine/ecs/terrain/ecs/TerrainSystem.js +2 -2
- package/src/engine/ecs/terrain/ecs/makeTerrainWorkerProxy.js +1 -1
- package/src/engine/ecs/terrain/tiles/TerrainTile.js +9 -46
- package/src/engine/ecs/transform/Transform.js +8 -9
- package/src/engine/ecs/transform/TransformSerializationAdapter.js +18 -7
- package/src/engine/graphics/ecs/mesh/Mesh.js +11 -11
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +2 -2
- package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.js +79 -36
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_overlap_clipping_volume.js +88 -0
- package/src/engine/graphics/geometry/buffered/query/bvh32_geometry_raycast.js +108 -0
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_indexed_geometry.js +4 -30
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_from_unindexed_geometry.js +30 -0
- package/src/engine/graphics/geometry/bvh/buffered/bvh32_set_leaf_from_triangle.js +41 -0
- package/src/engine/graphics/render/forward_plus/LightManager.js +2 -2
- package/src/engine/graphics/render/forward_plus/query/query_bvh_frustum_from_texture.js +2 -2
- package/src/engine/graphics/render/view/CameraView.js +8 -8
- package/src/core/bvh2/binary/BinaryBVH.js +0 -281
- package/src/core/bvh2/binary/IndexedBinaryBVH.js +0 -407
- package/src/core/bvh2/binary/IndexedBinaryBVH.spec.js +0 -27
- package/src/core/bvh2/binary/IndexedBinaryBVHVisitor.js +0 -11
- package/src/core/bvh2/binary/NodeType.js +0 -8
- package/src/core/bvh2/binary/RayLeafIntersectionVisitor.js +0 -59
- package/src/core/geom/3d/aabb/aabb3_array_intersects_frustum_array.js +0 -20
- package/src/core/geom/3d/aabb/aabb3_intersects_frustum_array.js +0 -35
- package/src/engine/graphics/geometry/buffered/query/ClippingPlaneContainmentComputingVisitor.js +0 -195
- package/src/engine/graphics/geometry/buffered/query/GeometryVisitor.js +0 -87
- package/src/engine/graphics/geometry/buffered/query/RaycastNearestHitComputingVisitor.js +0 -206
- package/src/engine/graphics/geometry/bvh/buffered/BinaryBVHFromBufferGeometry.js +0 -123
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { aabb3_intersects_clipping_volume_array } from "./aabb3_intersects_clipping_volume_array.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {Float32Array|number[]} aabb
|
|
6
|
+
* @param {number} aabb_offset
|
|
7
|
+
* @param {Float32Array|number[]} planes
|
|
8
|
+
* @param {number} planes_offset
|
|
9
|
+
* @param {number} plane_count
|
|
10
|
+
* @return {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function aabb3_array_intersects_clipping_volume_array(
|
|
13
|
+
aabb, aabb_offset,
|
|
14
|
+
planes, planes_offset, plane_count
|
|
15
|
+
) {
|
|
16
|
+
|
|
17
|
+
const x0 = aabb[aabb_offset + 0];
|
|
18
|
+
const y0 = aabb[aabb_offset + 1];
|
|
19
|
+
const z0 = aabb[aabb_offset + 2];
|
|
20
|
+
const x1 = aabb[aabb_offset + 3];
|
|
21
|
+
const y1 = aabb[aabb_offset + 4];
|
|
22
|
+
const z1 = aabb[aabb_offset + 5];
|
|
23
|
+
|
|
24
|
+
return aabb3_intersects_clipping_volume_array(
|
|
25
|
+
x0, y0, z0,
|
|
26
|
+
x1, y1, z1,
|
|
27
|
+
planes, planes_offset, plane_count
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { assert } from "../../../assert.js";
|
|
2
|
+
import { aabb3_compute_distance_above_plane_max } from "./aabb3_compute_distance_above_plane_max.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tests whether AABB intersects a clipping volume defined by a set of planes
|
|
6
|
+
* Mainly useful for frustum checks
|
|
7
|
+
* @param {number} x0
|
|
8
|
+
* @param {number} y0
|
|
9
|
+
* @param {number} z0
|
|
10
|
+
* @param {number} x1
|
|
11
|
+
* @param {number} y1
|
|
12
|
+
* @param {number} z1
|
|
13
|
+
* @param {ArrayLike<number>|number[]|Float32Array|Float64Array} planes
|
|
14
|
+
* @param {number} planes_offset
|
|
15
|
+
* @param {number} plane_count
|
|
16
|
+
* @return {boolean}
|
|
17
|
+
*/
|
|
18
|
+
export function aabb3_intersects_clipping_volume_array(
|
|
19
|
+
x0, y0, z0,
|
|
20
|
+
x1, y1, z1,
|
|
21
|
+
planes, planes_offset, plane_count
|
|
22
|
+
) {
|
|
23
|
+
|
|
24
|
+
assert.isNonNegativeInteger(planes_offset, 'frustum_offset');
|
|
25
|
+
|
|
26
|
+
const limit = plane_count * 4;
|
|
27
|
+
|
|
28
|
+
for (let i = 0; i < limit; i += 4) {
|
|
29
|
+
|
|
30
|
+
const offset = planes_offset + i;
|
|
31
|
+
|
|
32
|
+
const plane_x = planes[offset];
|
|
33
|
+
const plane_y = planes[offset + 1];
|
|
34
|
+
const plane_z = planes[offset + 2];
|
|
35
|
+
const plane_w = planes[offset + 3];
|
|
36
|
+
|
|
37
|
+
const plane_distance = aabb3_compute_distance_above_plane_max(
|
|
38
|
+
plane_x, plane_y, plane_z, plane_w,
|
|
39
|
+
x0, y0, z0,
|
|
40
|
+
x1, y1, z1
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
if (plane_distance < 0) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
|
|
51
|
+
}
|
|
@@ -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
|
|
package/src/core/geom/3d/frustum/{read_frustum_planes_to_array.js → read_three_planes_to_array.js}
RENAMED
|
@@ -5,10 +5,12 @@ import { assert } from "../../../assert.js";
|
|
|
5
5
|
* @param {Plane[]} planes
|
|
6
6
|
* @param {ArrayLike<number>|number[]|Float32Array|Float64Array} array
|
|
7
7
|
*/
|
|
8
|
-
export function
|
|
9
|
-
|
|
8
|
+
export function read_three_planes_to_array(planes, array) {
|
|
9
|
+
const plane_count = planes.length;
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
assert.greaterThanOrEqual(array.length, plane_count * 4, 'target array is too small');
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i < plane_count; i++) {
|
|
12
14
|
const plane = planes[i];
|
|
13
15
|
|
|
14
16
|
const offset = i * 4;
|
|
@@ -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,106 @@
|
|
|
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 max = 0;
|
|
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
|
+
let v0, v1, v2, dropped;
|
|
50
|
+
|
|
51
|
+
//max will be dropped
|
|
52
|
+
if (max === 0) {
|
|
53
|
+
//dropping x
|
|
54
|
+
v0 = y;
|
|
55
|
+
v1 = z;
|
|
56
|
+
v2 = w;
|
|
57
|
+
|
|
58
|
+
dropped = x;
|
|
59
|
+
} else if (max === 1) {
|
|
60
|
+
//dropping y
|
|
61
|
+
v0 = x;
|
|
62
|
+
v1 = z;
|
|
63
|
+
v2 = w;
|
|
64
|
+
|
|
65
|
+
dropped = y;
|
|
66
|
+
} else if (max === 2) {
|
|
67
|
+
//dropping z
|
|
68
|
+
v0 = x;
|
|
69
|
+
v1 = y;
|
|
70
|
+
v2 = w;
|
|
71
|
+
|
|
72
|
+
dropped = z;
|
|
73
|
+
} else {
|
|
74
|
+
//dropping w
|
|
75
|
+
v0 = x;
|
|
76
|
+
v1 = y;
|
|
77
|
+
v2 = z;
|
|
78
|
+
|
|
79
|
+
dropped = w;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (dropped < 0) {
|
|
83
|
+
//reconstructing dropped value is only possible if it is positive, so we invert the quaternion to make dropped value positive
|
|
84
|
+
v0 = -v0;
|
|
85
|
+
v1 = -v1;
|
|
86
|
+
v2 = -v2;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const l = Math.sqrt(x * x + y * y + z * z + w * w);
|
|
90
|
+
const m = 511 / (l * Math.SQRT1_2);
|
|
91
|
+
|
|
92
|
+
//re-normalize the remaining components to 10 bit UINT value
|
|
93
|
+
const oV0 = Math.round(v0 * m + 511);
|
|
94
|
+
const oV1 = Math.round(v1 * m + 511);
|
|
95
|
+
const oV2 = Math.round(v2 * m + 511);
|
|
96
|
+
|
|
97
|
+
assert.ok(oV0 <= 1023 && oV0 >= 0, `expected 0 <= ov0 <= 1023, instead was '${oV0}'`);
|
|
98
|
+
assert.ok(oV1 <= 1023 && oV1 >= 0, `expected 0 <= ov1 <= 1023, instead was '${oV1}'`);
|
|
99
|
+
assert.ok(oV2 <= 1023 && oV2 >= 0, `expected 0 <= ov2 <= 1023, instead was '${oV2}'`);
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
return (max & 0x3)
|
|
103
|
+
| ((oV0 & 0x3FF) << 2)
|
|
104
|
+
| ((oV1 & 0x3FF) << 12)
|
|
105
|
+
| ((oV2 & 0x3FF) << 22);
|
|
106
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { computeTrianglePlaneSide } from "./computeTrianglePlaneSide.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {number[]|Float32Array} planes
|
|
5
|
+
* @param {number} planes_offset
|
|
6
|
+
* @param {number} plane_count
|
|
7
|
+
* @param {number} ax
|
|
8
|
+
* @param {number} ay
|
|
9
|
+
* @param {number} az
|
|
10
|
+
* @param {number} bx
|
|
11
|
+
* @param {number} by
|
|
12
|
+
* @param {number} bz
|
|
13
|
+
* @param {number} cx
|
|
14
|
+
* @param {number} cy
|
|
15
|
+
* @param {number} cz
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
export function triangle_intersects_clipping_volume(
|
|
19
|
+
planes, planes_offset, plane_count,
|
|
20
|
+
ax, ay, az,
|
|
21
|
+
bx, by, bz,
|
|
22
|
+
cx, cy, cz
|
|
23
|
+
) {
|
|
24
|
+
|
|
25
|
+
for (let j = 0; j < plane_count; j++) {
|
|
26
|
+
|
|
27
|
+
const plane_address = planes_offset + j * 4;
|
|
28
|
+
|
|
29
|
+
const plane_normal_x = planes[plane_address];
|
|
30
|
+
const plane_normal_y = planes[plane_address + 1];
|
|
31
|
+
const plane_normal_z = planes[plane_address + 2];
|
|
32
|
+
const plane_constant = planes[plane_address + 3];
|
|
33
|
+
|
|
34
|
+
const side = computeTrianglePlaneSide(
|
|
35
|
+
plane_normal_x,
|
|
36
|
+
plane_normal_y,
|
|
37
|
+
plane_normal_z,
|
|
38
|
+
plane_constant,
|
|
39
|
+
ax, ay, az,
|
|
40
|
+
bx, by, bz,
|
|
41
|
+
cx, cy, cz
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (side === -3) {
|
|
45
|
+
// fully outside
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
@@ -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
|
/**
|
package/src/core/geom/Vector2.js
CHANGED
|
@@ -546,11 +546,7 @@ class Vector2 {
|
|
|
546
546
|
const x = computeHashFloat(this.x);
|
|
547
547
|
const y = computeHashFloat(this.y);
|
|
548
548
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
hash |= 0; //convert to 32bit int
|
|
552
|
-
|
|
553
|
-
return hash;
|
|
549
|
+
return ((x << 5) - x) + y;
|
|
554
550
|
}
|
|
555
551
|
|
|
556
552
|
/**
|
|
@@ -561,8 +557,11 @@ class Vector2 {
|
|
|
561
557
|
const sin = Math.sin(angle);
|
|
562
558
|
const cos = Math.cos(angle);
|
|
563
559
|
|
|
564
|
-
const
|
|
565
|
-
const
|
|
560
|
+
const _x = this.x;
|
|
561
|
+
const _y = this.y;
|
|
562
|
+
|
|
563
|
+
const x = _x * cos - _y * sin
|
|
564
|
+
const y = _x * sin + _y * cos;
|
|
566
565
|
|
|
567
566
|
this.set(x, y);
|
|
568
567
|
}
|