@woosh/meep-engine 2.49.6 → 2.49.8
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/editor/enableEditor.js +1 -8
- package/package.json +1 -1
- package/samples/terrain/editor.js +2 -2
- package/src/core/cache/Cache.js +1 -1
- package/src/core/cache/LoadingCache.d.ts +2 -0
- package/src/core/cache/LoadingCache.js +45 -18
- package/src/core/collection/HashSet.js +1 -1
- package/src/core/collection/table/RowFirstTableSpec.js +110 -92
- package/src/core/collection/table/RowFirstTableSpec.spec.js +49 -0
- package/src/core/color/Color.d.ts +4 -2
- package/src/core/color/Color.js +7 -8
- package/src/core/color/Color.spec.js +93 -0
- package/src/core/color/hex2rgb.spec.js +10 -0
- package/src/core/color/rgb2hex.js +1 -1
- package/src/core/color/rgb2hex.spec.js +13 -0
- package/src/core/fsm/simple/SimpleStateMachine.spec.js +75 -0
- package/src/core/fsm/simple/SimpleStateMachineDescription.js +1 -1
- package/src/core/fsm/simple/SimpleStateMachineDescription.spec.js +32 -0
- package/src/core/geom/2d/Rectangle.spec.js +51 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_ray.spec.js +90 -0
- package/src/core/geom/3d/line/line3_compute_nearest_point_to_point.spec.js +61 -0
- package/src/core/geom/3d/morton/mortonEncode_magicbits.js +1 -34
- package/src/core/geom/3d/morton/split_by_2.js +17 -0
- package/src/core/geom/3d/morton/split_by_3.js +16 -0
- package/src/core/geom/3d/plane/computePlaneLineIntersection.js +6 -1
- package/src/core/geom/3d/sphere/sphere_intersects_ray.spec.js +11 -0
- package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.spec.js +8 -0
- package/src/core/geom/3d/topology/samples/sampleFloodFill.js +3 -3
- package/src/core/geom/3d/topology/struct/binary/io/OrderedEdge.js +1 -1
- package/src/core/geom/random/randomPointOnBox.spec.js +57 -0
- package/src/core/math/computeGreatestCommonDivisor.spec.js +9 -0
- package/src/core/math/statistics/computeStatisticalMean.spec.js +9 -0
- package/src/core/math/statistics/halton_sequence.spec.js +6 -1
- package/src/core/model/node-graph/node/Port.spec.js +10 -1
- package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.js +5 -8
- package/src/core/model/reactive/evaluation/MultiPredicateEvaluator.spec.js +41 -0
- package/src/core/model/reactive/trigger/BlackboardTrigger.js +5 -0
- package/src/core/model/reactive/trigger/BlackboardTrigger.spec.js +24 -0
- package/src/core/parser/simple/readBooleanToken.js +38 -0
- package/src/core/parser/simple/readHexToken.js +95 -0
- package/src/core/parser/simple/readHexToken.spec.js +21 -0
- package/src/core/parser/simple/readIdentifierToken.js +43 -0
- package/src/core/parser/simple/readIdentifierToken.spec.js +32 -0
- package/src/core/parser/simple/readLiteralToken.js +96 -0
- package/src/core/parser/simple/readNumberToken.js +73 -0
- package/src/core/parser/simple/readNumberToken.spec.js +17 -0
- package/src/core/parser/simple/readReferenceToken.js +48 -0
- package/src/core/parser/simple/readReferenceToken.spec.js +18 -0
- package/src/core/parser/simple/readStringToken.js +94 -0
- package/src/core/parser/simple/readStringToken.spec.js +57 -0
- package/src/core/parser/simple/{readUnsignedInteger.js → readUnsignedIntegerToken.js} +1 -1
- package/src/core/parser/simple/readUnsignedIntegerToken.spec.js +6 -0
- package/src/core/process/executor/ConcurrentExecutor.js +147 -234
- package/src/engine/Engine.d.ts +4 -2
- package/src/engine/Engine.js +62 -41
- package/src/engine/Engine.spec.js +11 -0
- package/src/engine/InputEngine.js +12 -0
- package/src/engine/graphics/GraphicsEngine.js +2 -13
- package/src/engine/graphics/ecs/compileAllMaterials.js +1 -1
- package/src/engine/graphics/ecs/mesh/createTaskWaitForMeshesToLoad.js +1 -1
- package/src/engine/graphics/impostors/octahedral/ImpostorBaker.js +1 -1
- package/src/engine/graphics/load_and_set_cubemap_v0.js +21 -0
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +3 -5
- package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +2 -4
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +1 -1
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +1 -1
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +2 -4
- package/src/engine/graphics/sh3/prototypeSH3Probe.js +4 -4
- package/src/engine/graphics/texture/sampler/copy_Sampler2D_channel_data.js +4 -3
- package/src/engine/graphics/texture/virtual/VirtualTexture.js +9 -0
- package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +5 -4
- package/src/engine/graphics/texture/virtual/tile/TileLoader.js +5 -0
- package/src/engine/input/devices/PointerDevice.spec.js +7 -0
- package/src/engine/intelligence/blackboard/Blackboard.d.ts +4 -0
- package/src/engine/intelligence/blackboard/Blackboard.js +11 -0
- package/src/engine/platform/InMemoryEnginePlatform.js +20 -0
- package/src/engine/save/Storage.d.ts +7 -7
- package/src/engine/save/storage/InMemoryStorage.js +34 -0
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +2 -2
- package/src/view/tooltip/gml/parser/readReferenceValueToken.js +2 -2
- package/src/core/parser/simple/SimpleParser.js +0 -464
- package/src/core/parser/simple/SimpleParser.spec.js +0 -105
- /package/src/core/collection/{IteratorUtils.js → collectIteratorValueToArray.js} +0 -0
- /package/src/core/color/{ColorUtils.js → parseColor.js} +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SimpleStateMachine } from "./SimpleStateMachine.js";
|
|
2
|
+
import { SimpleStateMachineDescription } from "./SimpleStateMachineDescription.js";
|
|
3
|
+
|
|
4
|
+
test("constructor does not throw", () => {
|
|
5
|
+
const description = new SimpleStateMachineDescription();
|
|
6
|
+
|
|
7
|
+
expect(() => new SimpleStateMachine(description)).not.toThrow();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
test("state entry event handler is fired as expected", () => {
|
|
12
|
+
|
|
13
|
+
const description = new SimpleStateMachineDescription();
|
|
14
|
+
|
|
15
|
+
const a = description.createState();
|
|
16
|
+
const b = description.createState();
|
|
17
|
+
|
|
18
|
+
description.createEdge(a, b);
|
|
19
|
+
|
|
20
|
+
const fsm = new SimpleStateMachine(description);
|
|
21
|
+
|
|
22
|
+
fsm.setState(a);
|
|
23
|
+
|
|
24
|
+
const entry_callback = jest.fn();
|
|
25
|
+
|
|
26
|
+
fsm.addEventHandlerStateEntry(b, entry_callback);
|
|
27
|
+
|
|
28
|
+
fsm.setState(b);
|
|
29
|
+
|
|
30
|
+
expect(entry_callback).toHaveBeenCalledTimes(1);
|
|
31
|
+
expect(entry_callback).toHaveBeenCalledWith(b, a);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("state exit event handler is fired as expected", () => {
|
|
35
|
+
|
|
36
|
+
const description = new SimpleStateMachineDescription();
|
|
37
|
+
|
|
38
|
+
const a = description.createState();
|
|
39
|
+
const b = description.createState();
|
|
40
|
+
|
|
41
|
+
description.createEdge(a, b);
|
|
42
|
+
|
|
43
|
+
const fsm = new SimpleStateMachine(description);
|
|
44
|
+
|
|
45
|
+
fsm.setState(a);
|
|
46
|
+
|
|
47
|
+
const entry_callback = jest.fn();
|
|
48
|
+
|
|
49
|
+
fsm.addEventHandlerStateExit(a, entry_callback);
|
|
50
|
+
|
|
51
|
+
fsm.setState(b);
|
|
52
|
+
|
|
53
|
+
expect(entry_callback).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(entry_callback).toHaveBeenCalledWith(a, b);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("'advance' moves us to the next state in the chain", () => {
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
const description = new SimpleStateMachineDescription();
|
|
61
|
+
|
|
62
|
+
const a = description.createState();
|
|
63
|
+
const b = description.createState();
|
|
64
|
+
|
|
65
|
+
description.createEdge(a, b);
|
|
66
|
+
|
|
67
|
+
const fsm = new SimpleStateMachine(description);
|
|
68
|
+
|
|
69
|
+
fsm.setState(a);
|
|
70
|
+
|
|
71
|
+
fsm.advance(0);
|
|
72
|
+
|
|
73
|
+
expect(fsm.getState()).toBe(b);
|
|
74
|
+
|
|
75
|
+
});
|
|
@@ -141,7 +141,7 @@ export class SimpleStateMachineDescription {
|
|
|
141
141
|
*
|
|
142
142
|
* @param {number} start
|
|
143
143
|
* @param {number} goal
|
|
144
|
-
* @returns {number[]}
|
|
144
|
+
* @returns {number[]|null}
|
|
145
145
|
*/
|
|
146
146
|
findPath(start, goal) {
|
|
147
147
|
assert.ok(this.stateExists(start), `start state ${start} doesn't exist`);
|
|
@@ -69,3 +69,35 @@ test('getIncomingStates', () => {
|
|
|
69
69
|
expect(smd.getIncomingStates(b)).toEqual([a]);
|
|
70
70
|
expect(smd.getIncomingStates(c)).toEqual([a]);
|
|
71
71
|
});
|
|
72
|
+
|
|
73
|
+
test('edgeExists', () => {
|
|
74
|
+
|
|
75
|
+
const smd = new SimpleStateMachineDescription();
|
|
76
|
+
|
|
77
|
+
const a = smd.createState();
|
|
78
|
+
const b = smd.createState();
|
|
79
|
+
|
|
80
|
+
expect(smd.edgeExists(a, b)).toBe(false);
|
|
81
|
+
expect(smd.edgeExists(b, a)).toBe(false);
|
|
82
|
+
|
|
83
|
+
smd.createEdge(a, b);
|
|
84
|
+
|
|
85
|
+
expect(smd.edgeExists(a, b)).toEqual(true);
|
|
86
|
+
expect(smd.edgeExists(b, a)).toEqual(false);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("findPath sanity check", () => {
|
|
90
|
+
|
|
91
|
+
const smd = new SimpleStateMachineDescription();
|
|
92
|
+
|
|
93
|
+
const a = smd.createState();
|
|
94
|
+
const b = smd.createState();
|
|
95
|
+
|
|
96
|
+
expect(smd.findPath(a, a)).toEqual([a]);
|
|
97
|
+
|
|
98
|
+
expect(smd.findPath(a, b)).toEqual(null);
|
|
99
|
+
|
|
100
|
+
smd.createEdge(a, b);
|
|
101
|
+
|
|
102
|
+
expect(smd.findPath(a, b)).toEqual([a, b]);
|
|
103
|
+
});
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import Rectangle from "./Rectangle.js";
|
|
2
|
+
import Vector2 from "../Vector2.js";
|
|
3
|
+
|
|
4
|
+
test("constructor", () => {
|
|
5
|
+
expect(() => new Rectangle()).not.toThrow();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("default constructor produces 0 size rectangle with valid position", () => {
|
|
9
|
+
const r = new Rectangle();
|
|
10
|
+
|
|
11
|
+
expect(r.size.x).toBe(0);
|
|
12
|
+
expect(r.size.y).toBe(0);
|
|
13
|
+
|
|
14
|
+
expect(r.position.x).not.toBeNaN();
|
|
15
|
+
expect(r.position.y).not.toBeNaN();
|
|
16
|
+
});
|
|
2
17
|
|
|
3
18
|
test("toArray works correctly", () => {
|
|
4
19
|
const v = new Rectangle(1, 2, 3, 4);
|
|
@@ -9,3 +24,39 @@ test("toArray works correctly", () => {
|
|
|
9
24
|
|
|
10
25
|
expect(actual).toEqual([1, 2, 3, 4]);
|
|
11
26
|
});
|
|
27
|
+
|
|
28
|
+
test("toJSON", () => {
|
|
29
|
+
const r = new Rectangle(1, 3, 7, 11);
|
|
30
|
+
|
|
31
|
+
expect(r.toJSON()).toEqual({
|
|
32
|
+
position: { x: 1, y: 3 },
|
|
33
|
+
size: { x: 7, y: 11 }
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("fromJSON", () => {
|
|
38
|
+
|
|
39
|
+
const r = new Rectangle();
|
|
40
|
+
|
|
41
|
+
r.fromJSON({
|
|
42
|
+
position: { x: 1, y: 3 },
|
|
43
|
+
size: { x: 7, y: 11 }
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
expect(r.position.x).toBe(1);
|
|
47
|
+
expect(r.position.y).toBe(3);
|
|
48
|
+
|
|
49
|
+
expect(r.size.x).toBe(7);
|
|
50
|
+
expect(r.size.y).toBe(11);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("computeCenter", () => {
|
|
54
|
+
const r = new Rectangle(1, 3, 7, 11);
|
|
55
|
+
|
|
56
|
+
const center = new Vector2();
|
|
57
|
+
|
|
58
|
+
r.computeCenter(center);
|
|
59
|
+
|
|
60
|
+
expect(center.x).toBe(4.5);
|
|
61
|
+
expect(center.y).toBe(8.5);
|
|
62
|
+
});
|
|
@@ -1,6 +1,96 @@
|
|
|
1
1
|
import { seededRandom } from "../../../math/random/seededRandom.js";
|
|
2
2
|
import { aabb3_intersects_ray } from "./aabb3_intersects_ray.js";
|
|
3
3
|
|
|
4
|
+
test("axis aligned ray on X", () => {
|
|
5
|
+
expect(aabb3_intersects_ray(
|
|
6
|
+
-0.5, -0.5, -0.5,
|
|
7
|
+
+0.5, +0.5, +0.5,
|
|
8
|
+
-1, 0, 0,
|
|
9
|
+
1, 0, 0
|
|
10
|
+
)).toBe(true);
|
|
11
|
+
|
|
12
|
+
expect(aabb3_intersects_ray(
|
|
13
|
+
-0.5, -0.5, -0.5,
|
|
14
|
+
+0.5, +0.5, +0.5,
|
|
15
|
+
-1, 0, 0,
|
|
16
|
+
-1, 0, 0
|
|
17
|
+
)).toBe(false);
|
|
18
|
+
|
|
19
|
+
expect(aabb3_intersects_ray(
|
|
20
|
+
-0.5, -0.5, -0.5,
|
|
21
|
+
+0.5, +0.5, +0.5,
|
|
22
|
+
1, 0, 0,
|
|
23
|
+
-1, 0, 0
|
|
24
|
+
)).toBe(true);
|
|
25
|
+
|
|
26
|
+
expect(aabb3_intersects_ray(
|
|
27
|
+
-0.5, -0.5, -0.5,
|
|
28
|
+
+0.5, +0.5, +0.5,
|
|
29
|
+
1, 0, 0,
|
|
30
|
+
1, 0, 0
|
|
31
|
+
)).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("axis aligned ray on Y", () => {
|
|
35
|
+
expect(aabb3_intersects_ray(
|
|
36
|
+
-0.5, -0.5, -0.5,
|
|
37
|
+
+0.5, +0.5, +0.5,
|
|
38
|
+
0, -1, 0,
|
|
39
|
+
0, 1, 0
|
|
40
|
+
)).toBe(true);
|
|
41
|
+
|
|
42
|
+
expect(aabb3_intersects_ray(
|
|
43
|
+
-0.5, -0.5, -0.5,
|
|
44
|
+
+0.5, +0.5, +0.5,
|
|
45
|
+
0, -1, 0,
|
|
46
|
+
0, -1, 0
|
|
47
|
+
)).toBe(false);
|
|
48
|
+
|
|
49
|
+
expect(aabb3_intersects_ray(
|
|
50
|
+
-0.5, -0.5, -0.5,
|
|
51
|
+
+0.5, +0.5, +0.5,
|
|
52
|
+
0, 1, 0,
|
|
53
|
+
0, -1, 0
|
|
54
|
+
)).toBe(true);
|
|
55
|
+
|
|
56
|
+
expect(aabb3_intersects_ray(
|
|
57
|
+
-0.5, -0.5, -0.5,
|
|
58
|
+
+0.5, +0.5, +0.5,
|
|
59
|
+
0, 1, 0,
|
|
60
|
+
0, 1, 0
|
|
61
|
+
)).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("axis aligned ray on Z", () => {
|
|
65
|
+
expect(aabb3_intersects_ray(
|
|
66
|
+
-0.5, -0.5, -0.5,
|
|
67
|
+
+0.5, +0.5, +0.5,
|
|
68
|
+
0, 0, -1,
|
|
69
|
+
0, 0, 1
|
|
70
|
+
)).toBe(true);
|
|
71
|
+
|
|
72
|
+
expect(aabb3_intersects_ray(
|
|
73
|
+
-0.5, -0.5, -0.5,
|
|
74
|
+
+0.5, +0.5, +0.5,
|
|
75
|
+
0, 0, -1,
|
|
76
|
+
0, 0, -1
|
|
77
|
+
)).toBe(false);
|
|
78
|
+
|
|
79
|
+
expect(aabb3_intersects_ray(
|
|
80
|
+
-0.5, -0.5, -0.5,
|
|
81
|
+
+0.5, +0.5, +0.5,
|
|
82
|
+
0, 0, 1,
|
|
83
|
+
0, 0, -1
|
|
84
|
+
)).toBe(true);
|
|
85
|
+
|
|
86
|
+
expect(aabb3_intersects_ray(
|
|
87
|
+
-0.5, -0.5, -0.5,
|
|
88
|
+
+0.5, +0.5, +0.5,
|
|
89
|
+
0, 0, 1,
|
|
90
|
+
0, 0, 1
|
|
91
|
+
)).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
4
94
|
test.skip("performance raycast", () => {
|
|
5
95
|
const rng = seededRandom(42);
|
|
6
96
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { line3_compute_nearest_point_to_point } from "./line3_compute_nearest_point_to_point.js";
|
|
2
|
+
|
|
3
|
+
test("aligned with the start of the line", () => {
|
|
4
|
+
const result = [];
|
|
5
|
+
|
|
6
|
+
line3_compute_nearest_point_to_point(result, 0,
|
|
7
|
+
1, 3, 7, 11, 13, 17,
|
|
8
|
+
1, 3, 7
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
expect(result).toEqual([1, 3, 7])
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("aligned with the end of the line", () => {
|
|
15
|
+
const result = [];
|
|
16
|
+
|
|
17
|
+
line3_compute_nearest_point_to_point(result, 0,
|
|
18
|
+
1, 3, 7, 11, 13, 17,
|
|
19
|
+
11, 13, 17
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
expect(result).toEqual([11, 13, 17])
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("ref point is on line past line ends", () => {
|
|
26
|
+
|
|
27
|
+
const result = [];
|
|
28
|
+
|
|
29
|
+
line3_compute_nearest_point_to_point(result, 0,
|
|
30
|
+
-1, 0, 0, 3, 0, 0,
|
|
31
|
+
-2, 0, 0
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(result).toEqual([-1, 0, 0])
|
|
35
|
+
|
|
36
|
+
line3_compute_nearest_point_to_point(result, 0,
|
|
37
|
+
-1, 0, 0, 3, 0, 0,
|
|
38
|
+
7, 0, 0
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
expect(result).toEqual([3, 0, 0])
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("ref point is on the line", () => {
|
|
45
|
+
|
|
46
|
+
const result = [];
|
|
47
|
+
|
|
48
|
+
line3_compute_nearest_point_to_point(result, 0,
|
|
49
|
+
-1, 0, 0, 3, 0, 0,
|
|
50
|
+
1, 0, 0
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
expect(result).toEqual([1, 0, 0])
|
|
54
|
+
|
|
55
|
+
line3_compute_nearest_point_to_point(result, 0,
|
|
56
|
+
-1, 0, 0, 3, 0, 0,
|
|
57
|
+
2, 0, 0
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
expect(result).toEqual([2, 0, 0])
|
|
61
|
+
});
|
|
@@ -1,37 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* method to separate bits from a given integer 3 positions apart
|
|
3
|
-
* we only look at the first 10 bits
|
|
4
|
-
*
|
|
5
|
-
* @example when input is ABC, output bits are A00B00C
|
|
6
|
-
* @param {number} a
|
|
7
|
-
* @returns {number}
|
|
8
|
-
*/
|
|
9
|
-
function split_by_3(a) {
|
|
10
|
-
let x = a;
|
|
11
|
-
x = (x | x << 16) & 0x30000ff;
|
|
12
|
-
x = (x | x << 8) & 0x0300f00f;
|
|
13
|
-
x = (x | x << 4) & 0x30c30c3;
|
|
14
|
-
x = (x | x << 2) & 0x9249249;
|
|
15
|
-
return x;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* method to separate bits from a given integer 2 positions apart
|
|
20
|
-
*
|
|
21
|
-
* @example when input is ABC, output bits are A00B00C
|
|
22
|
-
* @see https://github.com/Forceflow/libmorton/blob/234a443ca8e2c64f6385f1a9d6ee10a70d08a3fa/include/libmorton/morton2D.h#L99
|
|
23
|
-
* @param {number} a
|
|
24
|
-
* @returns {number}
|
|
25
|
-
*/
|
|
26
|
-
export function split_by_2(a) {
|
|
27
|
-
let x = a;
|
|
28
|
-
x = (x | x << 16) & 0x0000FFFF;
|
|
29
|
-
x = (x | x << 8) & 0x00FF00FF;
|
|
30
|
-
x = (x | x << 4) & 0x0F0F0F0F;
|
|
31
|
-
x = (x | x << 2) & 0x33333333;
|
|
32
|
-
x = (x | x << 1) & 0x55555555;
|
|
33
|
-
return x;
|
|
34
|
-
}
|
|
1
|
+
import { split_by_3 } from "./split_by_3.js";
|
|
35
2
|
|
|
36
3
|
/**
|
|
37
4
|
* Based on article and C++ source code:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* method to separate bits from a given integer 2 positions apart
|
|
3
|
+
*
|
|
4
|
+
* @example when input is ABC, output bits are A00B00C
|
|
5
|
+
* @see https://github.com/Forceflow/libmorton/blob/234a443ca8e2c64f6385f1a9d6ee10a70d08a3fa/include/libmorton/morton2D.h#L99
|
|
6
|
+
* @param {number} a
|
|
7
|
+
* @returns {number}
|
|
8
|
+
*/
|
|
9
|
+
export function split_by_2(a) {
|
|
10
|
+
let x = a;
|
|
11
|
+
x = (x | x << 16) & 0x0000FFFF;
|
|
12
|
+
x = (x | x << 8) & 0x00FF00FF;
|
|
13
|
+
x = (x | x << 4) & 0x0F0F0F0F;
|
|
14
|
+
x = (x | x << 2) & 0x33333333;
|
|
15
|
+
x = (x | x << 1) & 0x55555555;
|
|
16
|
+
return x;
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* method to separate bits from a given integer 3 positions apart
|
|
3
|
+
* we only look at the first 10 bits
|
|
4
|
+
*
|
|
5
|
+
* @example when input is ABC, output bits are A00B00C
|
|
6
|
+
* @param {number} a
|
|
7
|
+
* @returns {number}
|
|
8
|
+
*/
|
|
9
|
+
export function split_by_3(a) {
|
|
10
|
+
let x = a;
|
|
11
|
+
x = (x | x << 16) & 0x30000ff;
|
|
12
|
+
x = (x | x << 8) & 0x0300f00f;
|
|
13
|
+
x = (x | x << 4) & 0x30c30c3;
|
|
14
|
+
x = (x | x << 2) & 0x9249249;
|
|
15
|
+
return x;
|
|
16
|
+
}
|
|
@@ -15,7 +15,12 @@ import { v3_dot } from "../../v3_dot.js";
|
|
|
15
15
|
* @param {number} dist Plane distance
|
|
16
16
|
* @returns {boolean} true if intersection is found, false otherwise
|
|
17
17
|
*/
|
|
18
|
-
export function computePlaneLineIntersection(
|
|
18
|
+
export function computePlaneLineIntersection(
|
|
19
|
+
out,
|
|
20
|
+
originX, originY, originZ,
|
|
21
|
+
directionX, directionY, directionZ,
|
|
22
|
+
normalX, normalY, normalZ, dist
|
|
23
|
+
) {
|
|
19
24
|
const denom = v3_dot(directionX, directionY, directionZ, normalX, normalY, normalZ);
|
|
20
25
|
|
|
21
26
|
const p = v3_dot(normalX, normalY, normalZ, originX, originY, originZ) + dist;
|
|
@@ -47,3 +47,14 @@ test("ray from +Z to -Z intersects sphere", () => {
|
|
|
47
47
|
0, 0, -1
|
|
48
48
|
)).toBe(true);
|
|
49
49
|
});
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
// negative cases
|
|
53
|
+
|
|
54
|
+
test("ray from -X to -X", () => {
|
|
55
|
+
expect(sphere_intersects_ray(
|
|
56
|
+
0, 0, 0, 1,
|
|
57
|
+
-2, 0, 0,
|
|
58
|
+
-1, 0, 0
|
|
59
|
+
)).toBe(false);
|
|
60
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { sphere_radius_sqr_from_v3_array_transformed } from "./sphere_radius_sqr_from_v3_array_transformed.js";
|
|
2
|
+
import { MATRIX_4_IDENTITY } from "../matrix/MATRIX_4_IDENTITY.js";
|
|
3
|
+
|
|
4
|
+
test("base case", () => {
|
|
5
|
+
expect(sphere_radius_sqr_from_v3_array_transformed([0, 0, 0], 3, MATRIX_4_IDENTITY)).toBe(0);
|
|
6
|
+
expect(sphere_radius_sqr_from_v3_array_transformed([1, 0, 0], 3, MATRIX_4_IDENTITY)).toBe(1);
|
|
7
|
+
expect(sphere_radius_sqr_from_v3_array_transformed([-1, 0, 0], 3, MATRIX_4_IDENTITY)).toBe(1);
|
|
8
|
+
});
|
|
@@ -9,7 +9,7 @@ import { topo_mesh_to_three_buffer_geometry } from "../topo_mesh_to_three_buffer
|
|
|
9
9
|
import { three_buffer_geometry_to_topo_mesh } from "../three_buffer_geometry_to_topo_mesh.js";
|
|
10
10
|
import { mesh_flood_fill } from "../util/mesh_flood_fill.js";
|
|
11
11
|
import { compute_aabb_from_points } from "../../aabb/compute_aabb_from_points.js";
|
|
12
|
-
import { AABB3 } from "../../../../
|
|
12
|
+
import { AABB3 } from "../../../../geom/3d/aabb/AABB3.js";
|
|
13
13
|
import { mergeVertices } from "three/examples/jsm/utils/BufferGeometryUtils.js";
|
|
14
14
|
import { makeGeometryIndexed } from "../../../../../engine/graphics/geometry/buffered/makeGeometryIndexed.js";
|
|
15
15
|
import { v3_dot } from "../../../v3_dot.js";
|
|
@@ -23,10 +23,10 @@ import { SGMeshEvents } from "../../../../../engine/graphics/ecs/mesh-v2/aggrega
|
|
|
23
23
|
import { Color } from "../../../../color/Color.js";
|
|
24
24
|
import { seededRandom } from "../../../../math/random/seededRandom.js";
|
|
25
25
|
import { expandConnectivityByLocality } from "../expandConnectivityByLocality.js";
|
|
26
|
-
import { buildCubeURLs } from "../../../../../engine/graphics/texture/cubemap/buildCubeURLs.js";
|
|
27
26
|
import { EntityNode } from "../../../../../engine/ecs/parent/EntityNode.js";
|
|
28
27
|
import { TransformAttachmentSystem } from "../../../../../engine/ecs/transform-attachment/TransformAttachmentSystem.js";
|
|
29
28
|
import { make_ray_from_viewport_position } from "../../../../../engine/graphics/make_ray_from_viewport_position.js";
|
|
29
|
+
import { load_and_set_cubemap_v0 } from "../../../../../engine/graphics/load_and_set_cubemap_v0.js";
|
|
30
30
|
|
|
31
31
|
const harness = new EngineHarness();
|
|
32
32
|
|
|
@@ -98,7 +98,7 @@ async function main(engine) {
|
|
|
98
98
|
enableTerrain: false
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
engine.graphics
|
|
101
|
+
load_and_set_cubemap_v0(engine.graphics,'data/textures/cubemaps/hip_miramar/32/', '.png')
|
|
102
102
|
|
|
103
103
|
const path = 'data/models/sponza-pbr/gltf/sponza.glb';
|
|
104
104
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { randomPointOnBox } from "./randomPointOnBox.js";
|
|
2
|
+
|
|
3
|
+
function assert_point_on_box(sample) {
|
|
4
|
+
|
|
5
|
+
const x = sample[0];
|
|
6
|
+
const y = sample[1];
|
|
7
|
+
const z = sample[2];
|
|
8
|
+
|
|
9
|
+
function assert_range(v) {
|
|
10
|
+
expect(v).toBeGreaterThanOrEqual(-0.5);
|
|
11
|
+
expect(v).toBeLessThanOrEqual(0.5);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (Math.abs(x) === 0.5 && Math.abs(y) === 0.5) {
|
|
15
|
+
assert_range(z);
|
|
16
|
+
} else if (Math.abs(x) === 0.5 && Math.abs(z) === 0.5) {
|
|
17
|
+
assert_range(y);
|
|
18
|
+
} else if (Math.abs(y) === 0.5 && Math.abs(z) === 0.5) {
|
|
19
|
+
assert_range(x);
|
|
20
|
+
} else if (Math.abs(x) === 0.5) {
|
|
21
|
+
assert_range(y);
|
|
22
|
+
assert_range(z);
|
|
23
|
+
} else if (Math.abs(y) === 0.5) {
|
|
24
|
+
assert_range(x);
|
|
25
|
+
assert_range(z);
|
|
26
|
+
} else if (Math.abs(z) === 0.5) {
|
|
27
|
+
assert_range(y);
|
|
28
|
+
assert_range(x);
|
|
29
|
+
} else {
|
|
30
|
+
throw new Error(`Unexpected ${sample}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
test("samples are on box shell", () => {
|
|
36
|
+
function validate(sample_value) {
|
|
37
|
+
|
|
38
|
+
const sample = [];
|
|
39
|
+
|
|
40
|
+
randomPointOnBox(() => sample_value, sample, 0);
|
|
41
|
+
|
|
42
|
+
assert_point_on_box(sample);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
validate(0);
|
|
46
|
+
validate(1);
|
|
47
|
+
|
|
48
|
+
validate(0.1);
|
|
49
|
+
validate(0.2);
|
|
50
|
+
validate(0.3);
|
|
51
|
+
validate(0.4);
|
|
52
|
+
validate(0.5);
|
|
53
|
+
validate(0.6);
|
|
54
|
+
validate(0.7);
|
|
55
|
+
validate(0.8);
|
|
56
|
+
validate(0.9);
|
|
57
|
+
});
|
|
@@ -5,7 +5,12 @@ test("unique values in base 10", () => {
|
|
|
5
5
|
const values = [];
|
|
6
6
|
|
|
7
7
|
for (let i = 0; i < 10; i++) {
|
|
8
|
-
|
|
8
|
+
const v = halton_sequence(10, i);
|
|
9
|
+
|
|
10
|
+
expect(v).toBeGreaterThanOrEqual(0);
|
|
11
|
+
expect(v).toBeLessThanOrEqual(1);
|
|
12
|
+
|
|
13
|
+
values.push(v);
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
values.sort();
|
|
@@ -40,5 +40,14 @@ test("equality works as intended", () => {
|
|
|
40
40
|
b.id = a.id;
|
|
41
41
|
|
|
42
42
|
expect(b.equals(a)).toEqual(true);
|
|
43
|
-
|
|
43
|
+
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("toString on newly crated instance produces a valid string", () => {
|
|
47
|
+
const port = new Port();
|
|
48
|
+
|
|
49
|
+
const s = port.toString();
|
|
50
|
+
|
|
51
|
+
expect(typeof s).toBe('string');
|
|
52
|
+
expect(s.trim().length).toBeGreaterThan(0); // non-empty
|
|
44
53
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { assert } from "../../../assert.js";
|
|
2
2
|
import { BitSet } from "../../../binary/BitSet.js";
|
|
3
3
|
import { HashMap } from "../../../collection/HashMap.js";
|
|
4
|
-
import { returnZero } from "../../../function/Functions.js";
|
|
5
4
|
import { max2 } from "../../../math/max2.js";
|
|
6
5
|
import DataType from "../../../parser/simple/DataType.js";
|
|
7
6
|
|
|
@@ -95,15 +94,13 @@ class ExpressionNode {
|
|
|
95
94
|
|
|
96
95
|
/**
|
|
97
96
|
*
|
|
98
|
-
* @param {
|
|
99
|
-
* @
|
|
97
|
+
* @param {ReactiveExpression} exp
|
|
98
|
+
* @returns {number}
|
|
100
99
|
*/
|
|
101
|
-
function
|
|
102
|
-
return
|
|
100
|
+
function scoreByTreeSize(exp){
|
|
101
|
+
return exp.computeTreeSize();
|
|
103
102
|
}
|
|
104
103
|
|
|
105
|
-
const temp_array = [];
|
|
106
|
-
|
|
107
104
|
/**
|
|
108
105
|
* Evaluate given state against multiple predicates, order of evaluation is controlled by scoring function, highest score nodes are evaluated first
|
|
109
106
|
*/
|
|
@@ -112,7 +109,7 @@ export class MultiPredicateEvaluator {
|
|
|
112
109
|
*
|
|
113
110
|
* @param {function(ReactiveExpression):number} scoringFunction
|
|
114
111
|
*/
|
|
115
|
-
constructor(scoringFunction =
|
|
112
|
+
constructor(scoringFunction = scoreByTreeSize) {
|
|
116
113
|
/**
|
|
117
114
|
*
|
|
118
115
|
* @type {function(ReactiveExpression): number}
|
|
@@ -9,6 +9,47 @@ import { MultiPredicateEvaluator } from "./MultiPredicateEvaluator.js";
|
|
|
9
9
|
import { randomFromArray } from "../../../math/random/randomFromArray.js";
|
|
10
10
|
import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
|
|
11
11
|
import { randomIntegerBetween } from "../../../math/random/randomIntegerBetween.js";
|
|
12
|
+
import { ReactiveEquals } from "../model/comparative/ReactiveEquals.js";
|
|
13
|
+
|
|
14
|
+
test('constructor does not throw', () => {
|
|
15
|
+
expect(() => new MultiPredicateEvaluator()).not.toThrow();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test('build empty', () => {
|
|
19
|
+
const processor = new MultiPredicateEvaluator();
|
|
20
|
+
|
|
21
|
+
expect(() => processor.build([])).not.toThrow();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('match against empty list of predicates', () => {
|
|
25
|
+
|
|
26
|
+
const processor = new MultiPredicateEvaluator();
|
|
27
|
+
processor.build([]);
|
|
28
|
+
|
|
29
|
+
processor.initialize({});
|
|
30
|
+
|
|
31
|
+
expect(processor.next()).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('match against one predicate', () => {
|
|
35
|
+
|
|
36
|
+
const processor = new MultiPredicateEvaluator();
|
|
37
|
+
|
|
38
|
+
const predicate = ReactiveEquals.from(new ReactiveReference('a'), ReactiveLiteralNumber.from(7));
|
|
39
|
+
|
|
40
|
+
processor.build([predicate]);
|
|
41
|
+
|
|
42
|
+
processor.initialize({ a: 1 });
|
|
43
|
+
|
|
44
|
+
expect(processor.next()).toBeUndefined();
|
|
45
|
+
|
|
46
|
+
processor.finalize();
|
|
47
|
+
processor.initialize({ a: 7 });
|
|
48
|
+
|
|
49
|
+
expect(processor.next()).toBe(predicate);
|
|
50
|
+
expect(processor.next()).toBeUndefined();
|
|
51
|
+
|
|
52
|
+
});
|
|
12
53
|
|
|
13
54
|
test.skip('performance', () => {
|
|
14
55
|
const random = seededRandom(12319);
|