@woosh/meep-engine 2.43.1 → 2.43.4
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/binary/BinaryBuffer.js +13 -1
- package/core/binary/BitSet.js +2 -2
- package/core/bvh2/aabb3/aabb3_array_combine.js +2 -2
- package/core/collection/RingBuffer.js +4 -2
- package/core/collection/RingBuffer.spec.js +59 -0
- package/core/collection/array/ArrayIteratorRandom.js +1 -1
- package/core/collection/{ArrayUtils.spec.js → array/arrayPickBestElement.spec.js} +1 -1
- package/core/collection/array/arrayPickBestElements.js +51 -0
- package/core/collection/array/arrayPickMinElement.js +43 -0
- package/core/collection/array/arrayQuickSort.js +1 -1
- package/core/collection/array/arraySetSortingDiff.js +1 -1
- package/core/collection/array/arraySwapElements.js +12 -0
- package/core/collection/array/array_range_equal_strict.js +22 -0
- package/core/collection/array/groupArrayBy.js +42 -0
- package/core/collection/array/isArrayEqual.js +50 -0
- package/core/collection/array/randomMultipleFromArray.js +34 -0
- package/core/collection/array/randomizeArrayElementOrder.js +23 -0
- package/core/color/sRGB_to_linear.js +9 -4
- package/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +1 -1
- package/core/geom/3d/aabb/aabb3_build_frustum.js +1 -1
- package/core/geom/3d/aabb/compute_aabb_from_points.js +1 -1
- package/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +3 -1
- package/core/geom/3d/morton/v3_morton_encode_transformed.spec.js +20 -0
- package/core/geom/3d/plane/orient3d_fast.js +11 -10
- package/core/geom/3d/plane/orient3d_robust.js +41 -0
- package/core/geom/3d/plane/plane_computeConvex3PlaneIntersection.js +0 -23
- package/core/geom/3d/plane/plane_three_compute_convex3_plane_intersection.js +24 -0
- package/core/geom/3d/shape/UnionShape3D.js +1 -1
- package/core/geom/3d/sphere/harmonics/README.md +15 -0
- package/core/geom/3d/sphere/harmonics/sh3_add.js +21 -0
- package/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +618 -0
- package/core/geom/3d/sphere/harmonics/sh3_sample_by_direction.js +49 -0
- package/core/geom/3d/sphere/harmonics/sh3_sample_irradiance_by_direction.js +53 -0
- package/core/geom/3d/tetrahedra/README.md +10 -1
- package/core/geom/3d/tetrahedra/TetrahedralMesh.js +650 -0
- package/core/geom/3d/tetrahedra/TetrahedralMesh.spec.js +233 -0
- package/core/geom/3d/tetrahedra/build_tetrahedral_mesh_buffer_geometry.js +75 -0
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +2 -2
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.spec.js +4 -4
- package/core/geom/3d/tetrahedra/delaunay/Cavity.js +49 -7
- package/core/geom/3d/tetrahedra/delaunay/compute_delaunay_tetrahedral_mesh.js +51 -17
- package/core/geom/3d/tetrahedra/delaunay/debug_validate_mesh.js +19 -0
- package/core/geom/3d/tetrahedra/delaunay/fill_in_a_cavity.js +191 -0
- package/core/geom/3d/tetrahedra/delaunay/push_boundary_with_validation.js +27 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +59 -43
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.js +77 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_sub_determinant.spec.js +30 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_towards_containing_tetrahedron.js +58 -0
- package/core/geom/3d/tetrahedra/delaunay/validate_cavity_boundary.js +60 -0
- package/core/geom/3d/tetrahedra/{point_in_tetrahedron_circumsphere.js → in_sphere_fast.js} +11 -13
- package/core/geom/3d/tetrahedra/in_sphere_robust.js +53 -0
- package/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +44 -35
- package/core/geom/3d/tetrahedra/tetrahedron_compute_signed_volume.js +83 -0
- package/core/geom/3d/tetrahedra/tetrahedron_compute_signed_volume.spec.js +24 -0
- package/core/geom/3d/tetrahedra/tetrahedron_contains_point.spec.js +66 -0
- package/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.js +166 -0
- package/core/geom/3d/util/make_justified_point_grid.js +31 -0
- package/core/geom/Bezier.js +0 -27
- package/core/geom/Plane.js +0 -4
- package/core/geom/packing/miniball/Subspan.js +2 -2
- package/core/geom/v3_lerp.js +6 -1
- package/core/math/isqrt.js +28 -0
- package/core/math/isqrt.spec.js +9 -0
- package/core/math/max.spec.js +25 -0
- package/core/math/min2.spec.js +25 -0
- package/core/model/node-graph/node/NodeInstance.js +3 -3
- package/core/primitives/strings/prefixTree/PrefixTreeLeaf.js +1 -1
- package/core/process/delay.js +5 -0
- package/core/process/task/util/randomCountTask.js +1 -1
- package/editor/Editor.js +3 -0
- package/editor/ecs/component/editors/ecs/ParameterLookupTableEditor.js +195 -11
- package/editor/ecs/component/editors/ecs/ParameterTrackSetEditor.js +16 -0
- package/editor/ecs/component/editors/ecs/ParticleEmitterLayerEditor.js +4 -0
- package/editor/ecs/component/editors/primitive/ArrayEditor.js +1 -1
- package/editor/tools/v2/BlenderCameraOrientationGizmo.js +6 -0
- package/editor/view/ecs/components/common/AutoCanvasView.js +13 -25
- package/engine/EngineHarness.js +11 -5
- package/engine/asset/AssetManager.d.ts +5 -1
- package/engine/asset/AssetManager.js +50 -15
- package/engine/asset/AssetManager.spec.js +17 -11
- package/engine/asset/AssetRequest.js +57 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +22 -0
- package/engine/asset/loaders/AssetLoader.js +1 -1
- package/engine/ecs/System.js +1 -1
- package/engine/ecs/dynamic_actions/DynamicActorSystem.js +1 -1
- package/engine/ecs/terrain/ecs/TerrainSystem.js +7 -1
- package/engine/ecs/transform/copy_three_transform.js +15 -0
- package/engine/graphics/FrameRunner.js +5 -9
- package/engine/graphics/ecs/animation/animator/AnimationClipDefinition.js +1 -1
- package/engine/graphics/ecs/animation/animator/graph/definition/AnimationGraphDefinition.js +1 -1
- package/engine/graphics/ecs/camera/Camera.js +1 -10
- package/engine/graphics/ecs/camera/CameraSystem.js +8 -8
- package/engine/graphics/ecs/camera/ProjectionType.js +9 -0
- package/engine/graphics/ecs/camera/build_three_camera_object.js +3 -3
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +59 -4
- package/engine/graphics/ecs/light/Light.js +6 -1
- package/engine/graphics/ecs/light/LightSystem.d.ts +1 -1
- package/engine/graphics/ecs/mesh-v2/three_object_to_entity_composition.js +2 -17
- package/engine/graphics/geometry/VertexDataSpec.js +1 -1
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +2 -2
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +3 -3
- package/engine/graphics/micron/plugin/GLTFAssetTransformer.js +1 -1
- package/engine/graphics/micron/plugin/MicronRenderPlugin.js +3 -1
- package/engine/graphics/particles/node-based/codegen/modules/FunctionSignature.js +1 -1
- package/engine/graphics/render/forward_plus/LightManager.js +1 -1
- package/engine/graphics/render/forward_plus/LightManager.spec.js +4 -0
- package/engine/graphics/render/forward_plus/computeFrustumCorners.js +4 -2
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
- package/engine/graphics/render/layers/RenderLayerUtils.js +2 -2
- package/engine/graphics/sh3/LightProbeVolume.js +595 -0
- package/engine/graphics/sh3/SH3VisualisationMaterial.js +79 -0
- package/engine/graphics/sh3/prototypeSH3Probe.js +427 -0
- package/engine/graphics/sh3/visualise_probe.js +40 -0
- package/engine/graphics/shaders/DenoiseShader.js +1 -1
- package/engine/graphics/texture/atlas/AtlasPatch.js +11 -3
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +2 -2
- package/engine/graphics/texture/atlas/TextureAtlas.js +22 -4
- package/engine/graphics/texture/atlas/TextureAtlas.spec.js +22 -0
- package/engine/graphics/texture/sampler/Sampler2D.js +0 -64
- package/engine/graphics/texture/sampler/Sampler2D.spec.js +2 -1
- package/engine/graphics/texture/sampler/sampler2d_combine.js +67 -0
- package/engine/intelligence/behavior/ecs/BehaviorSystem.spec.js +0 -3
- package/engine/intelligence/blackboard/AbstractBlackboard.d.ts +1 -1
- package/engine/network/PriorityFetch.js +192 -0
- package/engine/simulation/DormandPrince.js +1 -1
- package/engine/ui/DraggableAspect.js +0 -1
- package/generation/grid/generation/road/GridTaskGenerateRoads.js +1 -1
- package/package.json +2 -1
- package/samples/terrain/from_image_2.js +127 -82
- package/view/elements/CanvasView.js +7 -1
- package/view/elements/image/HTMLElementCacheKey.js +1 -1
- package/view/util/DomSizeObserver.js +3 -5
- package/core/collection/ArrayUtils.js +0 -263
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_toward_cavity.js +0 -48
- package/core/geom/3d/tetrahedra/hxt/a.js +0 -524
- package/core/geom/3d/tetrahedra/hxt/hxt.js +0 -140
- package/core/geom/3d/tetrahedra/hxt/hxt.wasm +0 -0
- package/core/geom/3d/tetrahedra/tetrahedra_collection.js +0 -383
|
@@ -343,7 +343,7 @@ export class BinaryBuffer {
|
|
|
343
343
|
*
|
|
344
344
|
* @param {number} destination_offset starting index in the destination array
|
|
345
345
|
* @param {number} length number of elements to read
|
|
346
|
-
* @param {Uint32Array} destination
|
|
346
|
+
* @param {Uint32Array|number[]|ArrayLike<number>} destination
|
|
347
347
|
*/
|
|
348
348
|
readUint32Array(destination, destination_offset, length) {
|
|
349
349
|
for (let i = 0; i < length; i++) {
|
|
@@ -707,6 +707,18 @@ export class BinaryBuffer {
|
|
|
707
707
|
this.position = end;
|
|
708
708
|
}
|
|
709
709
|
|
|
710
|
+
/**
|
|
711
|
+
*
|
|
712
|
+
* @param {Uint32Array|number[]|ArrayLike<number>} source
|
|
713
|
+
* @param {number} source_offset
|
|
714
|
+
* @param {number} length
|
|
715
|
+
*/
|
|
716
|
+
writeUint32Array(source, source_offset, length) {
|
|
717
|
+
for (let i = 0; i < length; i++) {
|
|
718
|
+
this.writeUint32(source[source_offset + i]);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
710
722
|
/**
|
|
711
723
|
*
|
|
712
724
|
* @param {Uint8Array|Uint8ClampedArray} array
|
package/core/binary/BitSet.js
CHANGED
|
@@ -403,9 +403,9 @@ BitSet.prototype.set = function (bitIndex, value) {
|
|
|
403
403
|
|
|
404
404
|
if (bitIndex === this.__length - 1) {
|
|
405
405
|
// trim down set size potentially
|
|
406
|
-
const newLastSetBit = this.previousSetBit(bitIndex);
|
|
406
|
+
// const newLastSetBit = this.previousSetBit(bitIndex);
|
|
407
407
|
|
|
408
|
-
this.__setLength(
|
|
408
|
+
this.__setLength(bitIndex );
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
|
|
@@ -4,8 +4,8 @@ import { min2 } from "../../math/min2.js";
|
|
|
4
4
|
import { max2 } from "../../math/max2.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @param {ArrayLike<number>|number[]} result
|
|
7
|
+
* Merge bounds of two axis-aligned bounding boxes, the result is a box that tightly bounds inputs
|
|
8
|
+
* @param {ArrayLike<number>|number[]} result where resulting value is written to
|
|
9
9
|
* @param {ArrayLike<number>|number[]} a
|
|
10
10
|
* @param {ArrayLike<number>|number[]} b
|
|
11
11
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { assert } from "../assert.js";
|
|
2
|
+
import { min2 } from "../math/min2.js";
|
|
2
3
|
|
|
3
4
|
export class RingBuffer {
|
|
4
5
|
/**
|
|
@@ -12,7 +13,7 @@ export class RingBuffer {
|
|
|
12
13
|
assert.isNonNegativeInteger(size, 'size');
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* Capacity of the buffer, number of slots
|
|
16
17
|
* @type {number}
|
|
17
18
|
*/
|
|
18
19
|
this.size = size;
|
|
@@ -30,7 +31,7 @@ export class RingBuffer {
|
|
|
30
31
|
this.tail = 0;
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
+
* Number of used slots. Starts at 0, goes up to {@link #size}
|
|
34
35
|
* @type {number}
|
|
35
36
|
*/
|
|
36
37
|
this.count = 0;
|
|
@@ -51,6 +52,7 @@ export class RingBuffer {
|
|
|
51
52
|
|
|
52
53
|
this.data = array;
|
|
53
54
|
this.size = new_size;
|
|
55
|
+
this.count = min2(new_size, this.count);
|
|
54
56
|
|
|
55
57
|
this.clear();
|
|
56
58
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { RingBuffer } from "./RingBuffer.js";
|
|
2
|
+
|
|
3
|
+
test("constructor doesn't throw", () => {
|
|
4
|
+
expect(() => new RingBuffer(1)).not.toThrow();
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test("size set from constructor", () => {
|
|
8
|
+
const sut = new RingBuffer(7);
|
|
9
|
+
|
|
10
|
+
expect(sut.size).toBe(7);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("circular overwriting", () => {
|
|
14
|
+
const sut = new RingBuffer(2);
|
|
15
|
+
|
|
16
|
+
sut.push(3);
|
|
17
|
+
sut.push(7);
|
|
18
|
+
sut.push(11);
|
|
19
|
+
|
|
20
|
+
expect(sut.contains(3)).toBe(false);
|
|
21
|
+
expect(sut.contains(7)).toBe(true);
|
|
22
|
+
expect(sut.contains(11)).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("empty buffer count must be 0", () => {
|
|
26
|
+
const sut = new RingBuffer(1);
|
|
27
|
+
|
|
28
|
+
expect(sut.count).toBe(0);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("buffer count works as expected", () => {
|
|
32
|
+
const sut = new RingBuffer(2);
|
|
33
|
+
|
|
34
|
+
expect(sut.count).toBe(0);
|
|
35
|
+
|
|
36
|
+
sut.push(1);
|
|
37
|
+
|
|
38
|
+
expect(sut.count).toBe(1);
|
|
39
|
+
|
|
40
|
+
sut.push(3);
|
|
41
|
+
|
|
42
|
+
expect(sut.count).toBe(2);
|
|
43
|
+
|
|
44
|
+
sut.push(7);
|
|
45
|
+
|
|
46
|
+
expect(sut.count).toBe(2);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("resizing changes capacity", () => {
|
|
50
|
+
const sut = new RingBuffer(2);
|
|
51
|
+
|
|
52
|
+
sut.resize(1);
|
|
53
|
+
|
|
54
|
+
expect(sut.size).toBe(1);
|
|
55
|
+
|
|
56
|
+
sut.resize(3);
|
|
57
|
+
|
|
58
|
+
expect(sut.size).toBe(3);
|
|
59
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { seededRandom } from "../../math/random/seededRandom.js";
|
|
2
|
-
import { randomizeArrayElementOrder } from "../ArrayUtils.js";
|
|
3
2
|
import { AbstractArrayIterator } from "./AbstractArrayIterator.js";
|
|
3
|
+
import { randomizeArrayElementOrder } from "./randomizeArrayElementOrder.js";
|
|
4
4
|
|
|
5
5
|
export class ArrayIteratorRandom extends AbstractArrayIterator {
|
|
6
6
|
constructor() {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {T[]} array
|
|
6
|
+
* @param {function(T):number} scoreFunction
|
|
7
|
+
* @returns {T[]}
|
|
8
|
+
*/
|
|
9
|
+
export function arrayPickBestElements(array, scoreFunction) {
|
|
10
|
+
assert.notEqual(array, undefined, 'array is undefined');
|
|
11
|
+
assert.isArray(array, 'array');
|
|
12
|
+
|
|
13
|
+
assert.typeOf(scoreFunction, 'function', 'scoreFunction');
|
|
14
|
+
|
|
15
|
+
let bestScore;
|
|
16
|
+
|
|
17
|
+
const size = array.length;
|
|
18
|
+
|
|
19
|
+
if (size === 0) {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const first = array[0];
|
|
24
|
+
|
|
25
|
+
bestScore = scoreFunction(first);
|
|
26
|
+
|
|
27
|
+
assert.isNumber(bestScore, 'bestScore');
|
|
28
|
+
|
|
29
|
+
const result = [first];
|
|
30
|
+
|
|
31
|
+
for (let i = 1; i < size; i++) {
|
|
32
|
+
const el = array[i];
|
|
33
|
+
|
|
34
|
+
// compute score
|
|
35
|
+
const score = scoreFunction(el);
|
|
36
|
+
|
|
37
|
+
assert.isNumber(score, 'score');
|
|
38
|
+
|
|
39
|
+
if (score > bestScore) {
|
|
40
|
+
bestScore = score;
|
|
41
|
+
|
|
42
|
+
result.splice(0, result.length);
|
|
43
|
+
|
|
44
|
+
result.push(el);
|
|
45
|
+
} else if (score === bestScore) {
|
|
46
|
+
result.push(el);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { assert } from "../../assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template T
|
|
5
|
+
* @param {T[]} array
|
|
6
|
+
* @param {function(T):number} scoreFunction
|
|
7
|
+
* @returns {T}
|
|
8
|
+
*/
|
|
9
|
+
export function arrayPickMinElement(array, scoreFunction) {
|
|
10
|
+
assert.notEqual(array, undefined, 'array is undefined');
|
|
11
|
+
assert.typeOf(scoreFunction, 'function', 'scoreFunction');
|
|
12
|
+
|
|
13
|
+
let bestElement;
|
|
14
|
+
let bestScore;
|
|
15
|
+
|
|
16
|
+
const size = array.length;
|
|
17
|
+
|
|
18
|
+
if (size === 0) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
bestElement = array[0];
|
|
23
|
+
|
|
24
|
+
bestScore = scoreFunction(bestElement);
|
|
25
|
+
|
|
26
|
+
assert.typeOf(bestScore, 'number', 'bestScore');
|
|
27
|
+
|
|
28
|
+
for (let i = 1; i < size; i++) {
|
|
29
|
+
const el = array[i];
|
|
30
|
+
|
|
31
|
+
// compute score
|
|
32
|
+
const score = scoreFunction(el);
|
|
33
|
+
|
|
34
|
+
assert.typeOf(score, 'number', 'score');
|
|
35
|
+
|
|
36
|
+
if (score < bestScore) {
|
|
37
|
+
bestScore = score;
|
|
38
|
+
bestElement = el;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return bestElement;
|
|
43
|
+
}
|
|
@@ -3,7 +3,7 @@ import { assert } from "../../assert.js";
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Based on 2-way merge
|
|
6
|
+
* Based on 2-way merge algorithm from wiki: https://en.wikipedia.org/wiki/K-way_merge_algorithm
|
|
7
7
|
* @template T
|
|
8
8
|
* @param {T[]} a
|
|
9
9
|
* @param {T[]} b
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks that elements in supplied arrays are exactly equal within a certain range defined by a pair of offsets and element count (length)
|
|
3
|
+
* @template T
|
|
4
|
+
* @param {T[]} a
|
|
5
|
+
* @param {number} offset_a
|
|
6
|
+
* @param {T[]} b
|
|
7
|
+
* @param {number} offset_b
|
|
8
|
+
* @param {number} length
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/
|
|
11
|
+
export function array_range_equal_strict(a, offset_a, b, offset_b, length) {
|
|
12
|
+
|
|
13
|
+
for (let i = 0; i < length; i++) {
|
|
14
|
+
|
|
15
|
+
if (a[offset_a + i] !== b[offset_b + i]) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { returnZero } from "../../function/Functions.js";
|
|
2
|
+
import { HashMap } from "../HashMap.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @template T,K
|
|
6
|
+
* @param {T[]} array
|
|
7
|
+
* @param {function(T):K} groupingFunction
|
|
8
|
+
* @param keyHashFunction
|
|
9
|
+
* @returns {Map<K,T[]>}
|
|
10
|
+
*/
|
|
11
|
+
export function groupArrayBy(array, groupingFunction, keyHashFunction = returnZero) {
|
|
12
|
+
const result = new HashMap({
|
|
13
|
+
keyHashFunction,
|
|
14
|
+
keyEqualityFunction(a, b) {
|
|
15
|
+
if (a === b) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (typeof a === "object" && a !== null && typeof a.equals === "function") {
|
|
20
|
+
return a.equals(b);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < array.length; i++) {
|
|
28
|
+
const element = array[i];
|
|
29
|
+
|
|
30
|
+
const groupKey = groupingFunction(element);
|
|
31
|
+
|
|
32
|
+
const group = result.get(groupKey);
|
|
33
|
+
|
|
34
|
+
if (group === undefined) {
|
|
35
|
+
result.set(groupKey, [element]);
|
|
36
|
+
} else {
|
|
37
|
+
group.push(element);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T,R
|
|
3
|
+
* @param {T[]} first
|
|
4
|
+
* @param {R[]} second
|
|
5
|
+
* @return {boolean}
|
|
6
|
+
*/
|
|
7
|
+
export function isArrayEqual(first, second) {
|
|
8
|
+
|
|
9
|
+
const il = first.length;
|
|
10
|
+
|
|
11
|
+
if (il !== second.length) return false;
|
|
12
|
+
|
|
13
|
+
let i = 0;
|
|
14
|
+
|
|
15
|
+
for (; i < il; i++) {
|
|
16
|
+
|
|
17
|
+
const a = first[i];
|
|
18
|
+
const b = second[i];
|
|
19
|
+
|
|
20
|
+
if (a === b) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if (a === undefined) {
|
|
26
|
+
//a is undefined, and B is something else
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (a === null) {
|
|
31
|
+
//a is null and B is something else
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//try "equals" method
|
|
36
|
+
if (typeof a.equals === "function") {
|
|
37
|
+
|
|
38
|
+
if (!a.equals(b)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
} else {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return true;
|
|
49
|
+
|
|
50
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { randomizeArrayElementOrder } from "./randomizeArrayElementOrder.js";
|
|
2
|
+
import { min2 } from "../../math/min2.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pick multiple random items from an array
|
|
6
|
+
*
|
|
7
|
+
* @template T
|
|
8
|
+
* @param {function} random
|
|
9
|
+
* @param {T[]} source
|
|
10
|
+
* @param {T[]} target
|
|
11
|
+
* @param {number} count how many items to pick
|
|
12
|
+
* @returns {T}
|
|
13
|
+
*/
|
|
14
|
+
export function randomMultipleFromArray(random, source, target, count) {
|
|
15
|
+
|
|
16
|
+
const order = [];
|
|
17
|
+
|
|
18
|
+
const source_length = source.length;
|
|
19
|
+
for (let i = 0; i < source_length; i++) {
|
|
20
|
+
order[i] = i;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
randomizeArrayElementOrder(random, order);
|
|
24
|
+
|
|
25
|
+
const target_length = min2(source_length, count);
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < target_length; i++) {
|
|
28
|
+
const index = order[i];
|
|
29
|
+
const element = source[index];
|
|
30
|
+
target.push(element);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return target_length;
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { randomIntegerBetween } from "../../math/random/randomIntegerBetween.js";
|
|
2
|
+
import { arraySwapElements } from "./arraySwapElements.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @template T
|
|
6
|
+
* @param {function} random
|
|
7
|
+
* @param {T[]} array
|
|
8
|
+
*/
|
|
9
|
+
export function randomizeArrayElementOrder(random, array) {
|
|
10
|
+
const n = array.length;
|
|
11
|
+
|
|
12
|
+
const lastValidIndex = n - 1;
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < n; i++) {
|
|
15
|
+
const t = randomIntegerBetween(random, 0, lastValidIndex);
|
|
16
|
+
|
|
17
|
+
if (t === i) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
arraySwapElements(array, i, t);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @param {number} c
|
|
4
|
+
* @return {number|number}
|
|
5
|
+
*/
|
|
6
|
+
export function convert_channel_sRGB_to_linear(c) {
|
|
2
7
|
return (c < 0.04045) ? c * 0.0773993808 : Math.pow(c * 0.9478672986 + 0.0521327014, 2.4);
|
|
3
8
|
}
|
|
4
9
|
|
|
@@ -10,7 +15,7 @@ function convert(c) {
|
|
|
10
15
|
* @param {number} input_offset
|
|
11
16
|
*/
|
|
12
17
|
export function sRGB_to_linear(output, output_offset, input, input_offset) {
|
|
13
|
-
output[output_offset] =
|
|
14
|
-
output[output_offset + 1] =
|
|
15
|
-
output[output_offset + 2] =
|
|
18
|
+
output[output_offset] = convert_channel_sRGB_to_linear(input[input_offset]);
|
|
19
|
+
output[output_offset + 1] = convert_channel_sRGB_to_linear(input[input_offset + 1]);
|
|
20
|
+
output[output_offset + 2] = convert_channel_sRGB_to_linear(input[input_offset + 2]);
|
|
16
21
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { computePlanePlaneIntersection } from "../../Plane.js";
|
|
2
2
|
import Vector3 from "../../Vector3.js";
|
|
3
3
|
import { plane3_projectPoint } from "../plane/plane3_projectPoint.js";
|
|
4
|
-
import { plane_three_computeConvex3PlaneIntersection } from "../plane/plane_computeConvex3PlaneIntersection.js";
|
|
5
4
|
import { ray_computeNearestPointToPoint } from "../ray/ray_computeNearestPointToPoint.js";
|
|
6
5
|
import { v3_distance_above_plane } from "../../v3_distance_above_plane.js";
|
|
6
|
+
import {
|
|
7
|
+
plane_three_computeConvex3PlaneIntersection
|
|
8
|
+
} from "../plane/plane_three_compute_convex3_plane_intersection.js";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
*
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { v3_morton_encode_transformed } from "./v3_morton_encode_transformed.js";
|
|
2
|
+
import { MATRIX_4_IDENTITY } from "../matrix/MATRIX_4_IDENTITY.js";
|
|
3
|
+
|
|
4
|
+
test("valid number with identity transform", () => {
|
|
5
|
+
const v = v3_morton_encode_transformed(0, 0, 0, MATRIX_4_IDENTITY);
|
|
6
|
+
|
|
7
|
+
expect(typeof v).toBe('number');
|
|
8
|
+
expect(v).not.toBeNaN();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("different coordinates produce different hashes", () => {
|
|
12
|
+
expect(v3_morton_encode_transformed(1, 0, 0, MATRIX_4_IDENTITY))
|
|
13
|
+
.not.toEqual(v3_morton_encode_transformed(0, 0, 0, MATRIX_4_IDENTITY));
|
|
14
|
+
|
|
15
|
+
expect(v3_morton_encode_transformed(0, 1, 0, MATRIX_4_IDENTITY))
|
|
16
|
+
.not.toEqual(v3_morton_encode_transformed(0, 0, 0, MATRIX_4_IDENTITY));
|
|
17
|
+
|
|
18
|
+
expect(v3_morton_encode_transformed(0, 0, 1, MATRIX_4_IDENTITY))
|
|
19
|
+
.not.toEqual(v3_morton_encode_transformed(0, 0, 0, MATRIX_4_IDENTITY));
|
|
20
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Non-robust
|
|
3
|
+
*
|
|
2
4
|
* Return a positive value if the point pd lies below the
|
|
3
5
|
* plane passing through pa, pb, and pc; "below" is defined so
|
|
4
6
|
* that pa, pb, and pc appear in counterclockwise order when
|
|
@@ -24,24 +26,23 @@ export function orient3d_fast(points, a, b, c, d) {
|
|
|
24
26
|
const c3 = c * 3;
|
|
25
27
|
|
|
26
28
|
const d_x = points[d3];
|
|
27
|
-
|
|
28
|
-
const adx = points[a3] - d_x;
|
|
29
|
-
const bdx = points[b3] - d_x;
|
|
30
|
-
const cdx = points[c3] - d_x;
|
|
31
|
-
|
|
32
29
|
const d_y = points[d3 + 1];
|
|
30
|
+
const d_z = points[d3 + 2];
|
|
33
31
|
|
|
32
|
+
const adx = points[a3] - d_x;
|
|
34
33
|
const ady = points[a3 + 1] - d_y;
|
|
35
|
-
const
|
|
36
|
-
const cdy = points[c3 + 1] - d_y;
|
|
34
|
+
const adz = points[a3 + 2] - d_z;
|
|
37
35
|
|
|
38
|
-
const
|
|
36
|
+
const bdx = points[b3] - d_x;
|
|
37
|
+
const bdy = points[b3 + 1] - d_y;
|
|
38
|
+
const cdz = points[c3 + 2] - d_z;
|
|
39
39
|
|
|
40
|
-
const
|
|
40
|
+
const cdx = points[c3] - d_x;
|
|
41
|
+
const cdy = points[c3 + 1] - d_y;
|
|
41
42
|
const bdz = points[b3 + 2] - d_z;
|
|
42
|
-
const cdz = points[c3 + 2] - d_z;
|
|
43
43
|
|
|
44
44
|
return adx * (bdy * cdz - bdz * cdy)
|
|
45
45
|
+ bdx * (cdy * adz - cdz * ady)
|
|
46
46
|
+ cdx * (ady * bdz - adz * bdy);
|
|
47
47
|
}
|
|
48
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { orient3d } from "robust-predicates";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {number[]} points
|
|
6
|
+
* @param {number} a index of point a
|
|
7
|
+
* @param {number} b index of point b
|
|
8
|
+
* @param {number} c index of point c
|
|
9
|
+
* @param {number} d index of point d
|
|
10
|
+
* @returns {number}
|
|
11
|
+
*/
|
|
12
|
+
export function orient3d_robust(
|
|
13
|
+
points,
|
|
14
|
+
a, b, c, d
|
|
15
|
+
) {
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
const a3 = a * 3;
|
|
19
|
+
const b3 = b * 3;
|
|
20
|
+
const c3 = c * 3;
|
|
21
|
+
const d3 = d * 3;
|
|
22
|
+
|
|
23
|
+
const ax = points[a3];
|
|
24
|
+
const ay = points[a3 + 1];
|
|
25
|
+
const az = points[a3 + 2];
|
|
26
|
+
|
|
27
|
+
const bx = points[b3];
|
|
28
|
+
const by = points[b3 + 1];
|
|
29
|
+
const bz = points[b3 + 2];
|
|
30
|
+
|
|
31
|
+
const cx = points[c3];
|
|
32
|
+
const cy = points[c3 + 1];
|
|
33
|
+
const cz = points[c3 + 2];
|
|
34
|
+
|
|
35
|
+
const dx = points[d3];
|
|
36
|
+
const dy = points[d3 + 1];
|
|
37
|
+
const dz = points[d3 + 2];
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
return orient3d(ax, ay, az, bx, by, bz, cx, cy, cz, dx, dy, dz);
|
|
41
|
+
}
|
|
@@ -1,28 +1,5 @@
|
|
|
1
1
|
import { v3_dot } from "../../v3_dot.js";
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param {number[]} result
|
|
6
|
-
* @param {number} result_offset
|
|
7
|
-
* @param {Plane} a
|
|
8
|
-
* @param {Plane} b
|
|
9
|
-
* @param {Plane} c
|
|
10
|
-
* @returns {boolean}
|
|
11
|
-
*/
|
|
12
|
-
export function plane_three_computeConvex3PlaneIntersection(result, result_offset, a, b, c) {
|
|
13
|
-
const a_normal = a.normal;
|
|
14
|
-
const b_normal = b.normal;
|
|
15
|
-
const c_normal = c.normal;
|
|
16
|
-
|
|
17
|
-
return plane_computeConvex3PlaneIntersection(
|
|
18
|
-
result,
|
|
19
|
-
result_offset,
|
|
20
|
-
a_normal.x, a_normal.y, a_normal.z, a.constant,
|
|
21
|
-
b_normal.x, b_normal.y, b_normal.z, b.constant,
|
|
22
|
-
c_normal.x, c_normal.y, c_normal.z, c.constant,
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
3
|
/**
|
|
27
4
|
* Given 3 planes, compute point of their intersection.
|
|
28
5
|
* This only works when the planes are "convex", that is - no two planes are parallel.
|