@woosh/meep-engine 2.60.1 → 2.62.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/meep.cjs +20244 -20262
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +20244 -20262
- package/package.json +1 -1
- package/src/core/binary/BitSet.js +1 -1
- package/src/core/bvh2/BinaryNode.js +16 -13
- package/src/core/bvh2/LeafNode.js +6 -3
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.js +81 -0
- package/src/core/geom/3d/aabb/AABB3.js +24 -36
- package/src/core/geom/3d/aabb/aabb3_array_compute_from_sphere.js +22 -0
- package/src/core/geom/3d/aabb/aabb3_array_intersects_sphere.js +22 -0
- package/src/core/geom/3d/aabb/aabb3_array_intersects_sphere_array.js +11 -0
- package/src/core/geom/3d/aabb/aabb3_signed_distance_to_aabb3.js +28 -0
- package/src/core/geom/3d/aabb/serializeAABB3Quantized16Uint.js +19 -10
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +30 -182
- package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.spec.js +27 -1
- package/src/core/geom/3d/tetrahedra/delaunay/Cavity.js +3 -4
- package/src/core/geom/ConicRay.js +16 -21
- package/src/core/geom/ConicRay.spec.js +24 -0
- package/src/core/geom/packing/miniball/Miniball.js +68 -117
- package/src/core/geom/packing/miniball/Miniball.spec.js +3 -3
- package/src/core/geom/packing/miniball/Subspan.js +47 -34
- package/src/core/geom/packing/miniball/miniball_compute_quality.js +64 -0
- package/src/core/math/bessel_3.js +1 -0
- package/src/core/math/random/randomBytes.js +2 -2
- package/src/core/math/sqr.js +8 -0
- package/src/core/model/node-graph/Connection.js +21 -23
- package/src/core/model/node-graph/DataType.js +16 -17
- package/src/core/model/node-graph/NodeGraph.js +49 -50
- package/src/core/model/node-graph/node/NodeDescription.js +42 -44
- package/src/core/model/node-graph/node/NodeInstance.js +59 -60
- package/src/core/model/node-graph/node/NodeInstancePortReference.js +27 -29
- package/src/core/model/node-graph/node/NodeRegistry.js +16 -18
- package/src/core/model/node-graph/node/Port.js +35 -37
- package/src/core/model/node-graph/node/parameter/NodeParameterDescription.js +27 -13
- package/src/core/path/computePathDirectory.spec.js +8 -0
- package/src/core/process/BaseProcess.d.ts +5 -0
- package/src/core/process/WatchDog.js +76 -75
- package/src/core/process/action/AsynchronousAction.js +24 -22
- package/src/core/process/executor/profile/Profile.js +34 -24
- package/src/core/process/executor/profile/TraceEvent.js +75 -75
- package/src/core/process/worker/OnDemandWorkerManager.js +27 -30
- package/src/core/process/worker/WorkerBuilder.js +149 -149
- package/src/core/process/worker/WorkerProxy.js +25 -21
- package/src/core/process/worker/extractTransferables.js +2 -2
- package/src/engine/Engine.js +58 -53
- package/src/engine/EngineConfiguration.d.ts +4 -4
- package/src/engine/ecs/EntityManager.js +517 -614
- package/src/engine/ecs/System.js +2 -2
- package/src/engine/ecs/foliage/ecs/Foliage2System.js +3 -0
- package/src/engine/ecs/foliage/ecs/InstancedMeshComponent.js +4 -1
- package/src/engine/ecs/foliage/ecs/convertInstancedMeshComponents2Entities.js +64 -0
- package/src/engine/ecs/foliage/ecs/{InstancedMeshUtils.js → optimizeIndividualMeshesEntitiesToInstances.js} +11 -70
- package/src/engine/ecs/transform/Transform.d.ts +7 -5
- package/src/engine/ecs/transform/Transform.js +30 -16
- package/src/engine/ecs/validateSystem.js +89 -0
- package/src/engine/graphics/GraphicsEngine.js +433 -483
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +42 -46
- package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +2 -2
- package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +49 -52
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +52 -56
- package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +20 -22
- package/src/engine/graphics/particles/ecs/ParticleEmitterSystem.js +43 -25
- package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +160 -180
- package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +37 -41
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +63 -67
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +46 -50
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +61 -65
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +48 -52
- package/src/engine/graphics/shadows/testShadowMapRendering.js +28 -32
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js +22 -20
- package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.js +10 -13
- package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +1 -1
- package/src/engine/plugin/EnginePluginManager.d.ts +6 -1
- package/src/engine/sound/dB2Volume.js +8 -0
- package/src/engine/sound/ecs/emitter/SoundEmitter.js +125 -99
- package/src/engine/sound/ecs/emitter/SoundEmitterComponentContext.js +4 -42
- package/src/engine/sound/ecs/emitter/SoundEmitterSystem.js +31 -121
- package/src/engine/sound/volume2dB.js +8 -0
- package/src/generation/theme/ThemeEngine.js +19 -53
- package/src/engine/ecs/components/ClingToHeightMap.js +0 -19
- package/src/engine/ecs/components/SynchronizePosition.js +0 -15
- package/src/engine/ecs/systems/ClingToHeightMapSystem.js +0 -170
- package/src/engine/ecs/systems/SynchronizePositionSystem.js +0 -43
- package/src/engine/graphics/geometry/bvh/buffered/BVHFromBufferGeometry.js +0 -133
package/package.json
CHANGED
|
@@ -457,7 +457,7 @@ BitSet.prototype.get = function (bitIndex) {
|
|
|
457
457
|
assert.isNonNegativeInteger(bitIndex, "bitIndex");
|
|
458
458
|
|
|
459
459
|
if (bitIndex >= this.__length) {
|
|
460
|
-
//bit is outside
|
|
460
|
+
//bit is outside the recorded region
|
|
461
461
|
return false;
|
|
462
462
|
}
|
|
463
463
|
|
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
6
|
+
import {assert} from "../assert.js";
|
|
7
|
+
import {arrayQuickSort} from "../collection/array/arrayQuickSort.js";
|
|
8
|
+
import {aabb3_box_surface_area_2} from "../geom/3d/aabb/aabb3_box_surface_area_2.js";
|
|
9
|
+
import {aabb3_combined_surface_area} from "../geom/3d/aabb/aabb3_combined_surface_area.js";
|
|
10
|
+
import {aabb3_intersects_aabb3} from "../geom/3d/aabb/aabb3_intersects_aabb3.js";
|
|
11
|
+
import {max2} from "../math/max2.js";
|
|
12
|
+
import {min2} from "../math/min2.js";
|
|
13
|
+
import {computeSampleStandardDeviation} from "../math/statistics/computeSampleStandardDeviation.js";
|
|
14
|
+
import {isLeaf, LeafNode} from "./LeafNode.js";
|
|
15
|
+
import {Node} from "./Node.js";
|
|
16
|
+
import {surfaceAreaHeuristic} from "./sah/surfaceAreaHeuristic.js";
|
|
17
|
+
import {BVHVisitor} from "./traversal/BVHVisitor.js";
|
|
18
|
+
import {traverseBinaryNodeUsingVisitor} from "./traversal/traverseBinaryNodeUsingVisitor.js";
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -36,6 +36,9 @@ let stackPointer = 0;
|
|
|
36
36
|
*/
|
|
37
37
|
const stack = [];
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated use {@link ExplicitBinaryBoundingVolumeHierarchy} instead
|
|
41
|
+
*/
|
|
39
42
|
export class BinaryNode extends Node {
|
|
40
43
|
constructor() {
|
|
41
44
|
super();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Created by Alex on 17/11/2014.
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import {deserializeAABB3} from "../geom/3d/aabb/deserializeAABB3.js";
|
|
5
|
+
import {serializeAABB3} from "../geom/3d/aabb/serializeAABB3.js";
|
|
6
|
+
import {Node} from "./Node.js";
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -15,6 +15,9 @@ function isLeaf(node) {
|
|
|
15
15
|
return node.isLeafNode;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated use {@link ExplicitBinaryBoundingVolumeHierarchy} and {@link EBBVHLeafProxy} respectively
|
|
20
|
+
*/
|
|
18
21
|
export class LeafNode extends Node {
|
|
19
22
|
/**
|
|
20
23
|
*
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {SCRATCH_UINT32_TRAVERSAL_STACK} from "../../../collection/SCRATCH_UINT32_TRAVERSAL_STACK.js";
|
|
2
|
+
import {aabb3_array_intersects_sphere_array} from "../../../geom/3d/aabb/aabb3_array_intersects_sphere_array.js";
|
|
3
|
+
import {NULL_NODE} from "../ExplicitBinaryBoundingVolumeHierarchy.js";
|
|
4
|
+
import {bvh_collect_user_data} from "./bvh_collect_user_data.js";
|
|
5
|
+
|
|
6
|
+
const stack = SCRATCH_UINT32_TRAVERSAL_STACK;
|
|
7
|
+
|
|
8
|
+
const scratch_aabb = new Float32Array(6);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param {number[]} result
|
|
13
|
+
* @param {number} result_offset
|
|
14
|
+
* @param {ExplicitBinaryBoundingVolumeHierarchy} bvh
|
|
15
|
+
* @param {number[]|Float32Array} sphere
|
|
16
|
+
*/
|
|
17
|
+
export function bvh_query_user_data_overlaps_sphere(
|
|
18
|
+
result,
|
|
19
|
+
result_offset,
|
|
20
|
+
bvh,
|
|
21
|
+
sphere
|
|
22
|
+
) {
|
|
23
|
+
const root = bvh.root;
|
|
24
|
+
|
|
25
|
+
if (root === NULL_NODE) {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
*
|
|
31
|
+
* @type {number}
|
|
32
|
+
*/
|
|
33
|
+
const stack_top = stack.pointer++;
|
|
34
|
+
|
|
35
|
+
stack[stack_top] = root;
|
|
36
|
+
|
|
37
|
+
let result_cursor = result_offset;
|
|
38
|
+
|
|
39
|
+
while (stack.pointer > stack_top) {
|
|
40
|
+
stack.pointer--;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @type {number}
|
|
45
|
+
*/
|
|
46
|
+
const node = stack[stack.pointer];
|
|
47
|
+
|
|
48
|
+
// test node against the ray
|
|
49
|
+
bvh.node_get_aabb(node, scratch_aabb);
|
|
50
|
+
const intersection = aabb3_array_intersects_sphere_array(scratch_aabb, sphere);
|
|
51
|
+
|
|
52
|
+
if (intersection === 0) {
|
|
53
|
+
// fully outside
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const node_is_leaf = bvh.node_is_leaf(node);
|
|
58
|
+
|
|
59
|
+
if (node_is_leaf) {
|
|
60
|
+
// leaf node
|
|
61
|
+
result[result_cursor++] = bvh.node_get_user_data(node);
|
|
62
|
+
|
|
63
|
+
} else if (intersection === 2) {
|
|
64
|
+
// fully inside, fast collection path
|
|
65
|
+
result_cursor += bvh_collect_user_data(result, result_cursor, bvh, node);
|
|
66
|
+
} else {
|
|
67
|
+
// partially inside
|
|
68
|
+
// read in-order
|
|
69
|
+
const child1 = bvh.node_get_child1(node);
|
|
70
|
+
const child2 = bvh.node_get_child2(node);
|
|
71
|
+
|
|
72
|
+
// write to stack in reverse order, so that fist child ends up being visited first
|
|
73
|
+
stack[stack.pointer++] = child1;
|
|
74
|
+
stack[stack.pointer++] = child2;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// drop stack frame
|
|
79
|
+
|
|
80
|
+
return result_cursor - result_offset;
|
|
81
|
+
}
|
|
@@ -3,22 +3,24 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { aabb3_compute_plane_side } from "./aabb3_compute_plane_side.js";
|
|
6
|
+
import {assert} from "../../../assert.js";
|
|
8
7
|
import computeMortonCode from "../morton/Morton.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
8
|
+
import {aabb3_array_intersects_point} from "./aabb3_array_intersects_point.js";
|
|
9
|
+
import {aabb3_build_corners} from "./aabb3_build_corners.js";
|
|
10
|
+
import {aabb3_compute_distance_above_plane_max} from "./aabb3_compute_distance_above_plane_max.js";
|
|
11
|
+
import {aabb3_compute_plane_side} from "./aabb3_compute_plane_side.js";
|
|
12
|
+
import {aabb3_compute_surface_area} from "./aabb3_compute_surface_area.js";
|
|
13
|
+
import {aabb3_intersects_frustum_array} from "./aabb3_intersects_frustum_array.js";
|
|
14
|
+
import {aabb3_intersects_frustum_degree} from "./aabb3_intersects_frustum_degree.js";
|
|
15
|
+
import {aabb3_intersects_line_segment} from "./aabb3_intersects_line_segment.js";
|
|
16
|
+
import {aabb3_intersects_ray} from "./aabb3_intersects_ray.js";
|
|
17
|
+
import {aabb3_matrix4_project} from "./aabb3_matrix4_project.js";
|
|
18
|
+
import {aabb3_signed_distance_sqr_to_point} from "./aabb3_signed_distance_sqr_to_point.js";
|
|
19
|
+
import {aabb3_signed_distance_to_aabb3} from "./aabb3_signed_distance_to_aabb3.js";
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Axis-Aligned bounding box in 3D
|
|
23
|
+
* NOTE: In cases where all you want is raw performance - prefer to use typed arrays instead along with `aabb3_` functions
|
|
22
24
|
*/
|
|
23
25
|
export class AABB3 {
|
|
24
26
|
/**
|
|
@@ -238,7 +240,12 @@ export class AABB3 {
|
|
|
238
240
|
* @returns {boolean}
|
|
239
241
|
*/
|
|
240
242
|
_equals(x0, y0, z0, x1, y1, z1) {
|
|
241
|
-
return this.x0 === x0
|
|
243
|
+
return this.x0 === x0
|
|
244
|
+
&& this.y0 === y0
|
|
245
|
+
&& this.z0 === z0
|
|
246
|
+
&& this.x1 === x1
|
|
247
|
+
&& this.y1 === y1
|
|
248
|
+
&& this.z1 === z1;
|
|
242
249
|
}
|
|
243
250
|
|
|
244
251
|
/**
|
|
@@ -332,28 +339,10 @@ export class AABB3 {
|
|
|
332
339
|
const _y1 = this.y1;
|
|
333
340
|
const _z1 = this.z1;
|
|
334
341
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const yp1 = y0 - _y1;
|
|
340
|
-
const zp0 = _z0 - z1;
|
|
341
|
-
const zp1 = z0 - _z1;
|
|
342
|
-
|
|
343
|
-
//calculate separation in each axis
|
|
344
|
-
const dx = Math.max(xp0, xp1);
|
|
345
|
-
const dy = Math.max(yp0, yp1);
|
|
346
|
-
const dz = Math.max(zp0, zp1);
|
|
347
|
-
|
|
348
|
-
//straight-line distance
|
|
349
|
-
let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
350
|
-
|
|
351
|
-
if (dx < 0 && dy < 0 && dz < 0) {
|
|
352
|
-
//penetration
|
|
353
|
-
return -distance;
|
|
354
|
-
} else {
|
|
355
|
-
return distance;
|
|
356
|
-
}
|
|
342
|
+
return aabb3_signed_distance_to_aabb3(
|
|
343
|
+
_x0, _y0, _z0, _x1, _y1, _z1,
|
|
344
|
+
x0, y0, z0, x1, y1, z1
|
|
345
|
+
);
|
|
357
346
|
}
|
|
358
347
|
|
|
359
348
|
/**
|
|
@@ -778,7 +767,6 @@ export class AABB3 {
|
|
|
778
767
|
}
|
|
779
768
|
|
|
780
769
|
/**
|
|
781
|
-
*
|
|
782
770
|
* @param {Plane[]} clippingPlanes
|
|
783
771
|
* @returns {boolean}
|
|
784
772
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number[]} output
|
|
4
|
+
* @param {number} output_offset
|
|
5
|
+
* @param {number} x
|
|
6
|
+
* @param {number} y
|
|
7
|
+
* @param {number} z
|
|
8
|
+
* @param {number} radius
|
|
9
|
+
*/
|
|
10
|
+
export function aabb3_array_compute_from_sphere(
|
|
11
|
+
output, output_offset,
|
|
12
|
+
x, y, z, radius
|
|
13
|
+
) {
|
|
14
|
+
|
|
15
|
+
output[output_offset] = x - radius;
|
|
16
|
+
output[output_offset + 1] = y - radius;
|
|
17
|
+
output[output_offset + 2] = z - radius;
|
|
18
|
+
output[output_offset + 3] = x + radius;
|
|
19
|
+
output[output_offset + 4] = y + radius;
|
|
20
|
+
output[output_offset + 5] = z + radius;
|
|
21
|
+
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {aabb3_signed_distance_sqr_to_point} from "./aabb3_signed_distance_sqr_to_point.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number[]} aabb
|
|
6
|
+
* @param {number} x
|
|
7
|
+
* @param {number} y
|
|
8
|
+
* @param {number} z
|
|
9
|
+
* @param {number} radius
|
|
10
|
+
* @returns {boolean}
|
|
11
|
+
*/
|
|
12
|
+
export function aabb3_array_intersects_sphere(aabb, x, y, z, radius) {
|
|
13
|
+
const distance_sqr = aabb3_signed_distance_sqr_to_point(
|
|
14
|
+
aabb[0], aabb[1], aabb[2],
|
|
15
|
+
aabb[3], aabb[4], aabb[5],
|
|
16
|
+
x, y, z
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const radius2 = radius * radius;
|
|
20
|
+
|
|
21
|
+
return distance_sqr <= radius2;
|
|
22
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {aabb3_array_intersects_sphere} from "./aabb3_array_intersects_sphere.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number[]|Float32Array} aabb
|
|
6
|
+
* @param {number[]|Float32Array} sphere [x,y,z, radius]
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
export function aabb3_array_intersects_sphere_array(aabb, sphere) {
|
|
10
|
+
return aabb3_array_intersects_sphere(aabb, sphere[0], sphere[1], sphere[2], sphere[3]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function aabb3_signed_distance_to_aabb3(
|
|
2
|
+
ax0,ay0,az0,ax1,ay1,az1,
|
|
3
|
+
bx0,by0,bz0, bx1,by1,bz1
|
|
4
|
+
){
|
|
5
|
+
|
|
6
|
+
//do projection
|
|
7
|
+
const xp0 = bx0 - ax1;
|
|
8
|
+
const xp1 = ax0 - bx1;
|
|
9
|
+
const yp0 = by0 - ay1;
|
|
10
|
+
const yp1 = ay0 - by1;
|
|
11
|
+
const zp0 = bz0 - az1;
|
|
12
|
+
const zp1 = az0 - bz1;
|
|
13
|
+
|
|
14
|
+
//calculate separation in each axis
|
|
15
|
+
const dx = Math.max(xp0, xp1);
|
|
16
|
+
const dy = Math.max(yp0, yp1);
|
|
17
|
+
const dz = Math.max(zp0, zp1);
|
|
18
|
+
|
|
19
|
+
//straight-line distance
|
|
20
|
+
let distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
21
|
+
|
|
22
|
+
if (dx < 0 && dy < 0 && dz < 0) {
|
|
23
|
+
//penetration
|
|
24
|
+
return -distance;
|
|
25
|
+
} else {
|
|
26
|
+
return distance;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -9,20 +9,29 @@
|
|
|
9
9
|
* @param {number} y1
|
|
10
10
|
* @param {number} z1
|
|
11
11
|
*/
|
|
12
|
-
export function serializeAABB3Quantized16Uint(
|
|
12
|
+
export function serializeAABB3Quantized16Uint(
|
|
13
|
+
buffer, box,
|
|
14
|
+
x0, y0, z0, x1, y1, z1
|
|
15
|
+
) {
|
|
16
|
+
|
|
13
17
|
//compute value ranges
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
18
|
+
const dx = x1 - x0;
|
|
19
|
+
const dy = y1 - y0;
|
|
20
|
+
const dz = z1 - z0;
|
|
21
|
+
|
|
22
|
+
// scale delta to Uin16 range, and avoid division by 0
|
|
23
|
+
const mx = dx > 0 ? 65535 / dx : 0;
|
|
24
|
+
const my = dy > 0 ? 65535 / dy : 0;
|
|
25
|
+
const mz = dz > 0 ? 65535 / dz : 0;
|
|
17
26
|
|
|
18
27
|
//quantize all values
|
|
19
|
-
const _x0 = ((
|
|
20
|
-
const _y0 = ((
|
|
21
|
-
const _z0 = ((
|
|
28
|
+
const _x0 = Math.floor((box.x0 - x0) * mx);
|
|
29
|
+
const _y0 = Math.floor((box.y0 - y0) * my);
|
|
30
|
+
const _z0 = Math.floor((box.z0 - z0) * mz);
|
|
22
31
|
|
|
23
|
-
const _x1 = ((
|
|
24
|
-
const _y1 = ((
|
|
25
|
-
const _z1 = ((
|
|
32
|
+
const _x1 = Math.ceil((box.x1 - x0) * mx);
|
|
33
|
+
const _y1 = Math.ceil((box.y1 - y0) * my);
|
|
34
|
+
const _z1 = Math.ceil((box.z1 - z0) * mz);
|
|
26
35
|
|
|
27
36
|
buffer.writeUint16(_x0);
|
|
28
37
|
buffer.writeUint16(_y0);
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { assert } from "../../../../assert.js";
|
|
1
|
+
import {mat3, vec3} from "gl-matrix";
|
|
2
|
+
import {assert} from "../../../../assert.js";
|
|
3
|
+
import {array_copy} from "../../../../collection/array/array_copy.js";
|
|
4
|
+
import {min2} from "../../../../math/min2.js";
|
|
6
5
|
|
|
7
6
|
/*
|
|
8
7
|
@see https://github.com/Bestmaker602/olacziy/blob/212b64ea5f1856b390cdf7629801243f76a4466d/libs/ibl/src/CubemapSH.cpp
|
|
9
8
|
*/
|
|
10
9
|
|
|
10
|
+
|
|
11
|
+
const F_PI = 3.14159265358979323846264338327950288;
|
|
12
|
+
const F_SQRT1_2 = 0.707106781186547524400844362104849039;
|
|
13
|
+
const M_SQRT_3 = 1.7320508076;
|
|
14
|
+
|
|
15
|
+
const M_SQRT_PI = 1.7724538509;
|
|
16
|
+
const M_SQRT_5 = 2.2360679775;
|
|
17
|
+
const M_SQRT_15 = 3.8729833462;
|
|
18
|
+
|
|
11
19
|
/**
|
|
12
20
|
*
|
|
13
21
|
* @param {number[]} M 5x5 matrix
|
|
14
22
|
* @param {number[]} x vec5
|
|
15
|
-
* @return {number[]}
|
|
23
|
+
* @return {number[]} vec5
|
|
16
24
|
*/
|
|
17
25
|
function multiply_5d(M, x) {
|
|
18
26
|
return [
|
|
@@ -24,51 +32,6 @@ function multiply_5d(M, x) {
|
|
|
24
32
|
];
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* returns n! / d!
|
|
30
|
-
* @param {number} n
|
|
31
|
-
* @param {number} d
|
|
32
|
-
* @return {number}
|
|
33
|
-
*/
|
|
34
|
-
function factorial(n, d = 1) {
|
|
35
|
-
let _d = max2(1, d);
|
|
36
|
-
let _n = max2(1, n);
|
|
37
|
-
|
|
38
|
-
let r = 1.0;
|
|
39
|
-
|
|
40
|
-
if (_n === _d) {
|
|
41
|
-
// intentionally left blank
|
|
42
|
-
} else if (_n > _d) {
|
|
43
|
-
for (; _n > _d; _n--) {
|
|
44
|
-
r *= _n;
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
for (; _d > _n; _d--) {
|
|
48
|
-
r *= _d;
|
|
49
|
-
}
|
|
50
|
-
r = 1.0 / r;
|
|
51
|
-
}
|
|
52
|
-
return r;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const F_PI = 3.14159265358979323846264338327950288;
|
|
56
|
-
const F_2_SQRTPI = 1.12837916709551257389615890312154517;
|
|
57
|
-
const F_SQRT2 = 1.41421356237309504880168872420969808;
|
|
58
|
-
const F_SQRT1_2 = 0.707106781186547524400844362104849039;
|
|
59
|
-
const M_SQRT_3 = 1.7320508076;
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* SH scaling factors
|
|
63
|
-
*/
|
|
64
|
-
function Kml(m, l) {
|
|
65
|
-
// returns sqrt((2*l + 1) / 4*pi) * sqrt( (l-|m|)! / (l+|m|)! )
|
|
66
|
-
|
|
67
|
-
m = m < 0 ? -m : m; // abs() is not constexpr
|
|
68
|
-
const K = (2 * l + 1) * factorial((l - m), (l + m));
|
|
69
|
-
return Math.sqrt(K) * (F_2_SQRTPI * 0.25);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
35
|
/**
|
|
73
36
|
* compute Index of spherical harmonics coefficient
|
|
74
37
|
* @param {number} m signed offset from zonal harmonic
|
|
@@ -79,127 +42,6 @@ function SHindex(m, l) {
|
|
|
79
42
|
return l * (l + 1) + m;
|
|
80
43
|
}
|
|
81
44
|
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
* @param {number[]} result
|
|
85
|
-
* @param {number} result_offset
|
|
86
|
-
* @param {number} numBands
|
|
87
|
-
*/
|
|
88
|
-
function Ki(result, result_offset, numBands) {
|
|
89
|
-
for (let l = 0; l < numBands; l++) {
|
|
90
|
-
result[SHindex(0, l) + result_offset] = Kml(0, l);
|
|
91
|
-
for (let m = 1; m <= l; m++) {
|
|
92
|
-
result[SHindex(m, l) + result_offset] =
|
|
93
|
-
result[SHindex(-m, l) + result_offset] = F_SQRT2 * Kml(m, l);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* < cos(theta) > SH coefficients pre-multiplied by 1 / K(0,l)
|
|
100
|
-
* @param {number} l
|
|
101
|
-
* @returns {number}
|
|
102
|
-
*/
|
|
103
|
-
function computeTruncatedCosSh(l) {
|
|
104
|
-
if (l === 0) {
|
|
105
|
-
return F_PI;
|
|
106
|
-
} else if (l === 1) {
|
|
107
|
-
return 2 * F_PI / 3;
|
|
108
|
-
} else if ((l & 1) !== 0) {
|
|
109
|
-
return 0;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const l_2 = l / 2;
|
|
113
|
-
const A0 = ((l_2 & 1) ? 1.0 : -1.0) / ((l + 2) * (l - 1));
|
|
114
|
-
const A1 = factorial(l, l_2) / (factorial(l_2) * (1 << l));
|
|
115
|
-
return 2 * F_PI * A0 * A1;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/*
|
|
119
|
-
* Calculates non-normalized SH bases, i.e.:
|
|
120
|
-
* m > 0, cos(m*phi) * P(m,l)
|
|
121
|
-
* m < 0, sin(|m|*phi) * P(|m|,l)
|
|
122
|
-
* m = 0, P(0,l)
|
|
123
|
-
*/
|
|
124
|
-
function computeShBasis(SHb, result_offset, numBands, sx, sy, sz) {
|
|
125
|
-
|
|
126
|
-
/*
|
|
127
|
-
* TODO: all the Legendre computation below is identical for all faces, so it
|
|
128
|
-
* might make sense to pre-compute it once. Also note that there is
|
|
129
|
-
* a fair amount of symmetry within a face (which we could take advantage of
|
|
130
|
-
* to reduce the pre-compute table).
|
|
131
|
-
*/
|
|
132
|
-
|
|
133
|
-
/*
|
|
134
|
-
* Below, we compute the associated Legendre polynomials using recursion.
|
|
135
|
-
* see: http://mathworld.wolfram.com/AssociatedLegendrePolynomial.html
|
|
136
|
-
*
|
|
137
|
-
* Note [0]: sz == cos(theta) ==> we only need to compute P(sz)
|
|
138
|
-
*
|
|
139
|
-
* Note [1]: We in fact compute P(sz) / sin(theta)^|m|, by removing
|
|
140
|
-
* the "sqrt(1 - sz*sz)" [i.e.: sin(theta)] factor from the recursion.
|
|
141
|
-
* This is later corrected in the ( cos(m*phi), sin(m*phi) ) recursion.
|
|
142
|
-
*/
|
|
143
|
-
|
|
144
|
-
// s = (x, y, z) = (sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta))
|
|
145
|
-
|
|
146
|
-
// handle m=0 separately, since it produces only one coefficient
|
|
147
|
-
let Pml_2 = 0;
|
|
148
|
-
let Pml_1 = 1;
|
|
149
|
-
SHb[result_offset + 0] = Pml_1;
|
|
150
|
-
for (let l = 1; l < numBands; l++) {
|
|
151
|
-
const Pml = ((2 * l - 1.0) * Pml_1 * sz - (l - 1.0) * Pml_2) / l;
|
|
152
|
-
Pml_2 = Pml_1;
|
|
153
|
-
Pml_1 = Pml;
|
|
154
|
-
SHb[result_offset + SHindex(0, l)] = Pml;
|
|
155
|
-
}
|
|
156
|
-
let Pmm = 1;
|
|
157
|
-
for (let m = 1; m < numBands; m++) {
|
|
158
|
-
Pmm = (1.0 - 2 * m) * Pmm; // See [1], divide by sqrt(1 - sz*sz);
|
|
159
|
-
Pml_2 = Pmm;
|
|
160
|
-
Pml_1 = (2 * m + 1.0) * Pmm * sz;
|
|
161
|
-
// l == m
|
|
162
|
-
SHb[result_offset + SHindex(-m, m)] = Pml_2;
|
|
163
|
-
SHb[result_offset + SHindex(m, m)] = Pml_2;
|
|
164
|
-
if (m + 1 < numBands) {
|
|
165
|
-
// l == m+1
|
|
166
|
-
SHb[result_offset + SHindex(-m, m + 1)] = Pml_1;
|
|
167
|
-
SHb[result_offset + SHindex(m, m + 1)] = Pml_1;
|
|
168
|
-
for (let l = m + 2; l < numBands; l++) {
|
|
169
|
-
const Pml = ((2 * l - 1.0) * Pml_1 * sz - (l + m - 1.0) * Pml_2) / (l - m);
|
|
170
|
-
Pml_2 = Pml_1;
|
|
171
|
-
Pml_1 = Pml;
|
|
172
|
-
SHb[result_offset + SHindex(-m, l)] = Pml;
|
|
173
|
-
SHb[result_offset + SHindex(m, l)] = Pml;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// At this point, SHb contains the associated Legendre polynomials divided
|
|
179
|
-
// by sin(theta)^|m|. Below we compute the SH basis.
|
|
180
|
-
//
|
|
181
|
-
// ( cos(m*phi), sin(m*phi) ) recursion:
|
|
182
|
-
// cos(m*phi + phi) == cos(m*phi)*cos(phi) - sin(m*phi)*sin(phi)
|
|
183
|
-
// sin(m*phi + phi) == sin(m*phi)*cos(phi) + cos(m*phi)*sin(phi)
|
|
184
|
-
// cos[m+1] == cos[m]*sx - sin[m]*sy
|
|
185
|
-
// sin[m+1] == sin[m]*sx + cos[m]*sy
|
|
186
|
-
//
|
|
187
|
-
// Note that (d.x, d.y) == (cos(phi), sin(phi)) * sin(theta), so the
|
|
188
|
-
// code below actually evaluates:
|
|
189
|
-
// (cos((m*phi), sin(m*phi)) * sin(theta)^|m|
|
|
190
|
-
let Cm = sx;
|
|
191
|
-
let Sm = sy;
|
|
192
|
-
for (let m = 1; m <= numBands; m++) {
|
|
193
|
-
for (let l = m; l < numBands; l++) {
|
|
194
|
-
SHb[result_offset + SHindex(-m, l)] *= Sm;
|
|
195
|
-
SHb[result_offset + SHindex(m, l)] *= Cm;
|
|
196
|
-
}
|
|
197
|
-
const Cm1 = Cm * sx - Sm * sy;
|
|
198
|
-
const Sm1 = Sm * sx + Cm * sy;
|
|
199
|
-
Cm = Cm1;
|
|
200
|
-
Sm = Sm1;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
45
|
|
|
204
46
|
/*
|
|
205
47
|
* utilities to rotate very low order spherical harmonics (up to 3rd band)
|
|
@@ -247,10 +89,10 @@ function rotateShericalHarmonicBand1(band1, M) {
|
|
|
247
89
|
/**
|
|
248
90
|
* This projects a vec3 to SH2/k space (i.e. we premultiply by 1/k)
|
|
249
91
|
* below can't be constexpr
|
|
250
|
-
* @return {number[]} vec5
|
|
251
92
|
* @param {number} x
|
|
252
93
|
* @param {number} y
|
|
253
94
|
* @param {number} z
|
|
95
|
+
* @return {number[]} vec5
|
|
254
96
|
*/
|
|
255
97
|
function project_v3_to_sh(x, y, z) {
|
|
256
98
|
return [
|
|
@@ -266,7 +108,7 @@ function project_v3_to_sh(x, y, z) {
|
|
|
266
108
|
*
|
|
267
109
|
* @param {number[]} band2 vec5
|
|
268
110
|
* @param {number[]} M mat3
|
|
269
|
-
* @return {
|
|
111
|
+
* @return {number[]} vec5
|
|
270
112
|
*/
|
|
271
113
|
function rotateShericalHarmonicBand2(band2, M) {
|
|
272
114
|
const n = F_SQRT1_2;
|
|
@@ -310,7 +152,7 @@ function rotateShericalHarmonicBand2(band2, M) {
|
|
|
310
152
|
return result;
|
|
311
153
|
}
|
|
312
154
|
|
|
313
|
-
|
|
155
|
+
/**
|
|
314
156
|
* SH from environment with high dynamic range (or high frequencies -- high dynamic range creates
|
|
315
157
|
* high frequencies) exhibit "ringing" and negative values when reconstructed.
|
|
316
158
|
* To mitigate this, we need to low-pass the input image -- or equivalently window the SH by
|
|
@@ -321,7 +163,9 @@ function rotateShericalHarmonicBand2(band2, M) {
|
|
|
321
163
|
* Deringing Spherical Harmonics
|
|
322
164
|
* by Peter-Pike Sloan
|
|
323
165
|
* https://www.ppsloan.org/publications/shdering.pdf
|
|
324
|
-
*
|
|
166
|
+
* @param {number} w
|
|
167
|
+
* @param {number} l
|
|
168
|
+
* @returns {number}
|
|
325
169
|
*/
|
|
326
170
|
function sincWindow(l, w) {
|
|
327
171
|
if (l === 0) {
|
|
@@ -379,10 +223,6 @@ function shmin(input_sh3) {
|
|
|
379
223
|
// See "Deringing Spherical Harmonics" by Peter-Pike Sloan
|
|
380
224
|
// https://www.ppsloan.org/publications/shdering.pdf
|
|
381
225
|
|
|
382
|
-
const M_SQRT_PI = 1.7724538509;
|
|
383
|
-
const M_SQRT_3 = 1.7320508076;
|
|
384
|
-
const M_SQRT_5 = 2.2360679775;
|
|
385
|
-
const M_SQRT_15 = 3.8729833462;
|
|
386
226
|
const A = [
|
|
387
227
|
1.0 / (2.0 * M_SQRT_PI), // 0: 0 0
|
|
388
228
|
-M_SQRT_3 / (2.0 * M_SQRT_PI), // 1: 1 -1
|
|
@@ -545,9 +385,13 @@ function windowing(f, cutoff, numBands) {
|
|
|
545
385
|
* @param {number} input_offset
|
|
546
386
|
* @param {number} numBands
|
|
547
387
|
* @param {number} channel_count
|
|
548
|
-
* @param {number} cutoff
|
|
388
|
+
* @param {number} [cutoff]
|
|
549
389
|
*/
|
|
550
|
-
function windowSH(
|
|
390
|
+
function windowSH(
|
|
391
|
+
output, output_offset,
|
|
392
|
+
input, input_offset,
|
|
393
|
+
numBands, channel_count, cutoff = 0
|
|
394
|
+
) {
|
|
551
395
|
assert.isNonNegativeInteger(channel_count, 'channel_count');
|
|
552
396
|
assert.greaterThan(channel_count, 0, 'channel_count must be greater than 0');
|
|
553
397
|
|
|
@@ -575,13 +419,17 @@ function windowSH(output, output_offset, input, input_offset, numBands, channel_
|
|
|
575
419
|
// find a cut-off band that works
|
|
576
420
|
let l = numBands;
|
|
577
421
|
let r = cutoff;
|
|
422
|
+
|
|
578
423
|
for (let i = 0; i < 16 && l + 0.1 < r; i++) {
|
|
424
|
+
|
|
579
425
|
const m = 0.5 * (l + r);
|
|
426
|
+
|
|
580
427
|
if (shmin(windowing(SH, m, numBands)) < 0) {
|
|
581
428
|
r = m;
|
|
582
429
|
} else {
|
|
583
430
|
l = m;
|
|
584
431
|
}
|
|
432
|
+
|
|
585
433
|
}
|
|
586
434
|
|
|
587
435
|
// record minimum cutoff
|