@woosh/meep-engine 2.48.23 → 2.49.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/editor/tools/GridPaintTool.js +1 -1
- package/editor/tools/paint/TerrainPaintTool.js +1 -1
- package/editor/view/GridPickCoordinateView.js +1 -1
- package/package.json +1 -1
- package/src/core/UUID.js +2 -0
- package/src/core/assert.js +4 -1
- package/src/core/binary/ctz32.js +1 -1
- package/src/core/binary/operations/bitCount.spec.js +19 -0
- package/src/core/binary/uint82float.spec.js +7 -0
- package/src/core/bvh2/bvh3/EBBVHLeafProxy.js +3 -0
- package/src/core/bvh2/bvh3/query/compute_tight_near_far_clipping_planes.js +5 -4
- package/src/core/bvh2/transform/RotationOptimizer.spec.js +161 -155
- package/src/core/codegen/LineBuilder.js +12 -3
- package/src/core/codegen/LineBuilder.spec.js +7 -0
- package/src/core/collection/HashMap.js +486 -237
- package/src/core/collection/HashMap.spec.js +110 -1
- package/src/core/collection/array/{typedArrayToDataType.js → typed/typedArrayToDataType.js} +1 -1
- package/src/core/collection/array/weightedRandomFromArray.spec.js +20 -0
- package/src/core/debug/matchers/AnyOf.js +1 -2
- package/src/core/geom/2d/aabb/AABB2.spec.js +1 -1
- package/src/core/geom/2d/aabb/aabb2_compute_center_from_multiple.js +19 -0
- package/src/core/geom/2d/quad-tree/qt_collect_by_circle.js +3 -3
- package/src/core/geom/2d/quad-tree/qt_query_data_nearest_to_point.js +7 -9
- package/src/core/geom/3d/aabb/aabb3_compute_plane_side.js +17 -15
- package/src/core/geom/3d/aabb/aabb3_compute_plane_side.spec.js +25 -0
- package/src/core/geom/3d/aabb/aabb3_detailed_volume_intersection.js +1 -1
- package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +3 -0
- package/src/core/geom/3d/aabb/aabb3_from_v3_array.spec.js +32 -0
- package/src/core/geom/3d/aabb/aabb3_intersects_aabb3.spec.js +115 -0
- package/src/core/geom/3d/aabb/aabb3_raycast.js +6 -1
- package/src/core/geom/3d/aabb/serializeAABB3Encoded_v0.js +6 -6
- package/src/core/geom/3d/{CircleMath.js → compute_circle_bounding_box.js} +1 -1
- package/src/core/geom/3d/decompose_matrix_4_array.js +18 -19
- package/src/core/geom/3d/frustum/frustum3_computeNearestPointToPoint.js +1 -1
- package/src/{engine/graphics/ecs/mesh-v2 → core/geom/3d/matrix}/allocate_transform_m4.js +1 -1
- package/src/core/geom/3d/normal/hemioct/decode_hemioct_to_unit.js +26 -0
- package/src/core/geom/3d/normal/hemioct/encode_unit3_hemioct.js +0 -26
- package/src/core/geom/3d/normal/hemioct/unit_hemioct.spec.js +2 -1
- package/src/core/geom/3d/plane/computePlaneLineIntersection.js +51 -0
- package/src/core/geom/3d/plane/computePlanePlaneIntersection.js +77 -0
- package/src/core/geom/3d/plane/computePlaneRayIntersection.js +55 -0
- package/src/core/geom/3d/plane/plane3_computeLineSegmentIntersection.js +50 -0
- package/src/core/geom/3d/plane/planeRayIntersection.js +14 -0
- package/src/core/geom/3d/{tetrahedra/in_sphere_fast.js → sphere/in_sphere3d_fast.js} +1 -1
- package/src/core/geom/3d/{tetrahedra/in_sphere_robust.js → sphere/in_sphere3d_robust.js} +1 -1
- package/src/core/geom/3d/sphere/sphere_array_intersects_point.js +2 -2
- package/src/core/geom/3d/sphere/{sphereIntersectsPoint.js → sphere_intersects_point.js} +7 -4
- package/src/core/geom/3d/sphere/sphere_intersects_point.spec.js +134 -0
- package/src/core/geom/3d/sphere/sphere_intersects_ray.spec.js +49 -0
- package/src/core/geom/3d/sphere/sphere_radius_sqr_from_v3_array_transformed.js +11 -7
- package/src/core/geom/3d/tetrahedra/delaunay/{debug_validate_mesh.js → debug/debug_validate_mesh.js} +1 -1
- package/src/core/geom/3d/tetrahedra/delaunay/{push_boundary_with_validation.js → debug/push_boundary_with_validation.js} +1 -1
- package/src/core/geom/3d/tetrahedra/delaunay/{validate_cavity_boundary.js → debug/validate_cavity_boundary.js} +2 -2
- package/src/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +2 -2
- package/src/core/geom/3d/triangle/computeTriangleRayIntersection.js +0 -164
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentric.js +87 -0
- package/src/core/geom/3d/triangle/computeTriangleRayIntersectionBarycentricEdge.js +81 -0
- package/src/core/geom/{rayTriangleIntersection.js → 3d/triangle/rayTriangleIntersection.js} +2 -2
- package/src/core/geom/ConicRay.js +160 -152
- package/src/core/geom/Matrix4.js +2 -0
- package/src/core/geom/Quaternion.js +19 -1
- package/src/core/geom/packing/max-rect/MaxRectangles.js +4 -214
- package/src/core/geom/packing/max-rect/cost/costByBestShortSide.js +11 -0
- package/src/core/geom/packing/max-rect/cost/costByRemainingArea.js +14 -0
- package/src/core/geom/packing/max-rect/cutArea.js +79 -0
- package/src/core/geom/packing/max-rect/findBestContainer.js +58 -0
- package/src/core/geom/packing/max-rect/packOneBox.js +49 -0
- package/src/core/geom/v3_dot.js +1 -1
- package/src/core/graph/layout/CircleLayout.js +1 -1
- package/src/core/graph/layout/{BoxLayouter.js → box/BoxLayouter.js} +6 -50
- package/src/core/graph/layout/box/applyCentralGravityAABB2.js +29 -0
- package/src/core/json/resolvePath.spec.js +14 -0
- package/src/core/land/reactive/{compiler/ReactiveCompiler.spec.js → compileReactiveExpression.spec.js} +17 -17
- package/src/core/math/random/MersenneTwister.spec.js +19 -0
- package/src/core/math/random/randomGaussian.spec.js +9 -0
- package/src/core/math/statistics/computeStatisticalMean.js +2 -2
- package/src/core/model/reactive/model/arithmetic/ReactiveAdd.js +1 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveDivide.js +3 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveMultiply.js +1 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveNegate.js +3 -1
- package/src/core/model/reactive/model/arithmetic/ReactiveSubtract.js +1 -1
- package/src/core/model/reactive/model/comparative/ReactiveEquals.js +1 -1
- package/src/core/model/reactive/model/comparative/ReactiveGreaterThan.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveGreaterThanOrEqual.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveLessThan.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveLessThanOrEqual.js +3 -1
- package/src/core/model/reactive/model/comparative/ReactiveNotEquals.js +1 -1
- package/src/core/model/reactive/model/logic/ReactiveAnd.js +1 -1
- package/src/core/model/reactive/model/logic/ReactiveNot.js +3 -1
- package/src/core/model/reactive/model/logic/ReactiveOr.js +1 -1
- package/src/core/primitives/numbers/computeHashFloat.spec.js +7 -0
- package/src/core/process/task/util/iteratorTask.js +3 -1
- package/src/engine/animation/curve/AnimationCurve.js +34 -5
- package/src/engine/animation/curve/AnimationCurve.spec.js +100 -0
- package/src/engine/asset/AssetTransformer.js +1 -0
- package/src/engine/computeStridedIntegerArrayHash.js +4 -2
- package/src/engine/ecs/components/Renderable.d.ts +1 -1
- package/src/{ecs → engine/ecs}/grid/pick.js +4 -4
- package/src/engine/ecs/parent/entity_node_compute_bounding_box.js +1 -1
- package/src/engine/ecs/storage/binary/collection/BinaryCollectionSerializer.js +1 -18
- package/src/engine/ecs/systems/MotionSystem.js +7 -1
- package/src/engine/ecs/systems/SynchronizePositionSystem.js +8 -2
- package/src/engine/ecs/transform/Transform.js +1 -1
- package/src/engine/graphics/camera/makeScreenScissorFrustum.js +3 -3
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +13 -13
- package/src/engine/graphics/ecs/camera/Camera.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.js +1 -1
- package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +9 -0
- package/src/engine/graphics/geometry/MikkT/MikkTSpace.js +1 -1
- package/src/engine/graphics/geometry/MikkT/STSpace.js +1 -1
- package/src/engine/graphics/geometry/bvh/buffered/BVHGeometryRaycaster.js +1 -1
- package/src/engine/graphics/material/optimization/MaterialOptimizationContext.js +1 -1
- package/src/engine/graphics/particles/particular/engine/MovingBoundingBox.js +1 -1
- package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +1 -0
- package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
- package/src/engine/graphics/postprocess/threejs/postprocessing/TexturePass.js +2 -2
- package/src/engine/graphics/sh3/path_tracer/GeometryBVHBatched.js +2 -2
- package/src/engine/graphics/texture/sampler/Sampler2D.js +1 -1
- package/src/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js +1 -1
- package/src/engine/intelligence/behavior/Behavior.spec.js +15 -0
- package/src/engine/intelligence/mcts/MoveEdge.js +1 -1
- package/src/engine/reference/v1/ReferenceManager.js +3 -0
- package/src/engine/reference/v2/Reference.js +33 -37
- package/src/engine/sound/sopra/README.md +6 -0
- package/src/generation/automata/CaveGeneratorCellularAutomata.js +10 -7
- package/src/generation/automata/CaveGeneratorCellularAutomata.spec.js +12 -0
- package/src/generation/automata/CellularAutomata.js +5 -4
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +25 -9
- package/src/view/minimap/dom/MinimapCameraView.js +1 -1
- package/src/core/geom/Plane.js +0 -250
- package/src/core/land/reactive/ReactiveLexer.js +0 -158
- package/src/core/land/reactive/ReactiveLexer.ts +0 -181
- package/src/core/land/reactive/ReactiveListener.ts +0 -323
- package/src/core/land/reactive/ReactiveParser.js +0 -1573
- package/src/core/land/reactive/ReactiveParser.ts +0 -1776
- package/src/core/land/reactive/ReactiveVisitor.js +0 -1
- package/src/core/land/reactive/ReactiveVisitor.ts +0 -218
- package/src/core/land/reactive/compiler/ReactiveCompiler.js +0 -350
- package/src/core/land/reactive/compiler/ReactiveNearlyCompiler.js +0 -166
- package/src/core/land/reactive/compiler/ReactiveParser.js +0 -34
- package/src/core/land/reactive/nearley/ReactiveNearley.js +0 -187
- /package/src/{engine/graphics/ecs/mesh-v2 → core/geom/3d/vector}/allocate_v3.js +0 -0
|
@@ -12,7 +12,7 @@ import TopDownCameraControllerSystem
|
|
|
12
12
|
from "../../src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js";
|
|
13
13
|
import { hex2rgb } from "../../src/core/color/hex2rgb.js";
|
|
14
14
|
import { obtainTerrain } from "../../src/engine/ecs/terrain/util/obtainTerrain.js";
|
|
15
|
-
import { pick } from "../../src/ecs/grid/pick.js";
|
|
15
|
+
import { pick } from "../../src/engine/ecs/grid/pick.js";
|
|
16
16
|
|
|
17
17
|
class GridPaintTool extends Tool {
|
|
18
18
|
constructor() {
|
|
@@ -8,7 +8,7 @@ import ObservedString from "../../../src/core/model/ObservedString.js";
|
|
|
8
8
|
import { GameAssetType } from "../../../src/engine/asset/GameAssetType.js";
|
|
9
9
|
import Vector1 from "../../../src/core/geom/Vector1.js";
|
|
10
10
|
import { obtainTerrain } from "../../../src/engine/ecs/terrain/util/obtainTerrain.js";
|
|
11
|
-
import { pick } from "../../../src/ecs/grid/pick.js";
|
|
11
|
+
import { pick } from "../../../src/engine/ecs/grid/pick.js";
|
|
12
12
|
|
|
13
13
|
export class TerrainPaintTool extends Tool {
|
|
14
14
|
constructor() {
|
|
@@ -2,7 +2,7 @@ import View from "../../src/view/View.js";
|
|
|
2
2
|
import domify from "../../src/view/DOM.js";
|
|
3
3
|
import { PointerDevice } from "../../src/engine/input/devices/PointerDevice.js";
|
|
4
4
|
import { obtainTerrain } from "../../src/engine/ecs/terrain/util/obtainTerrain.js";
|
|
5
|
-
import { pick } from "../../src/ecs/grid/pick.js";
|
|
5
|
+
import { pick } from "../../src/engine/ecs/grid/pick.js";
|
|
6
6
|
|
|
7
7
|
class GridPickCoordinateView extends View {
|
|
8
8
|
/**
|
package/package.json
CHANGED
package/src/core/UUID.js
CHANGED
|
@@ -10,6 +10,8 @@ function replacer(c) {
|
|
|
10
10
|
const rx = /[xy]/g;
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
+
* Generates a variant 4 fully random UUID in string format
|
|
14
|
+
* NOTE: Prefer to use UUID component class instead as that implementation is more robust and has better entropy when it comes to randomness
|
|
13
15
|
* @returns {string}
|
|
14
16
|
*/
|
|
15
17
|
function uuid() {
|
package/src/core/assert.js
CHANGED
|
@@ -3,7 +3,10 @@ import { isTypedArray } from "./collection/array/typed/isTypedArray.js";
|
|
|
3
3
|
import { InMemoryDescriptor } from "./debug/InMemoryDescriptor.js";
|
|
4
4
|
|
|
5
5
|
function equal(a, b, m) {
|
|
6
|
-
|
|
6
|
+
if (a !== b) {
|
|
7
|
+
const message = m !== undefined ? m : `${a} !== ${b}`;
|
|
8
|
+
throw new Error(message);
|
|
9
|
+
}
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
function notEqual(a, b, m) {
|
package/src/core/binary/ctz32.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { bitCount } from "./bitCount.js";
|
|
2
|
+
|
|
3
|
+
test("no set bits", () => {
|
|
4
|
+
expect(bitCount(0)).toBe(0)
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test("1 set bit", () => {
|
|
8
|
+
|
|
9
|
+
for (let i = 0; i < 32; i++) {
|
|
10
|
+
expect(bitCount(1 << i)).toBe(1)
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("2 set bit together", () => {
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < 31; i++) {
|
|
17
|
+
expect(bitCount(0b11 << i)).toBe(2)
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -32,6 +32,7 @@ export class EBBVHLeafProxy {
|
|
|
32
32
|
* @param {number} data Must be a uint32
|
|
33
33
|
*/
|
|
34
34
|
link(tree, data) {
|
|
35
|
+
assert.equal(this.is_linked, false, 'already linked');
|
|
35
36
|
assert.defined(tree, 'tree');
|
|
36
37
|
assert.isNonNegativeInteger(data, 'data');
|
|
37
38
|
|
|
@@ -47,6 +48,8 @@ export class EBBVHLeafProxy {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
unlink() {
|
|
51
|
+
assert.equal(this.is_linked, true, 'not linked');
|
|
52
|
+
|
|
50
53
|
this.#tree.remove_leaf(this.#node_id);
|
|
51
54
|
this.#tree.release_node(this.#node_id);
|
|
52
55
|
|
|
@@ -27,7 +27,7 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
27
27
|
const root = bvh.root;
|
|
28
28
|
|
|
29
29
|
if (root === NULL_NODE) {
|
|
30
|
-
return
|
|
30
|
+
return false;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -67,8 +67,8 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
67
67
|
const _y1 = scratch_aabb[4];
|
|
68
68
|
const _z1 = scratch_aabb[5];
|
|
69
69
|
|
|
70
|
-
for (let
|
|
71
|
-
const plane_address =
|
|
70
|
+
for (let plane_index = 0; plane_index < 6; plane_index++) {
|
|
71
|
+
const plane_address = plane_index * 4;
|
|
72
72
|
|
|
73
73
|
//read out plane
|
|
74
74
|
const plane_normal_x = frustum[plane_address];
|
|
@@ -112,7 +112,7 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
112
112
|
continue node_loop;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
if ((constrained_planes_mask & (1 <<
|
|
115
|
+
if ((constrained_planes_mask & (1 << plane_index)) !== 0) {
|
|
116
116
|
// plane is constrained, we're done here
|
|
117
117
|
continue;
|
|
118
118
|
}
|
|
@@ -152,4 +152,5 @@ export function compute_tight_near_far_clipping_planes(result, result_offset, co
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
return true;
|
|
155
156
|
}
|
|
@@ -100,198 +100,204 @@ function pair(left, right) {
|
|
|
100
100
|
return node;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
test("empty node", () => {
|
|
104
|
-
const node = new BinaryNode();
|
|
105
|
-
node.setInfiniteBounds();
|
|
106
103
|
|
|
107
|
-
|
|
104
|
+
describe.skip("suite", () => {
|
|
108
105
|
|
|
109
|
-
expect(node.left).toBeNull();
|
|
110
|
-
expect(node.right).toBeNull();
|
|
111
|
-
});
|
|
112
106
|
|
|
113
|
-
test("
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
test("empty node", () => {
|
|
108
|
+
const node = new BinaryNode();
|
|
109
|
+
node.setInfiniteBounds();
|
|
116
110
|
|
|
117
|
-
|
|
111
|
+
optimize(node, 100);
|
|
118
112
|
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
expect(node.left).toBeNull();
|
|
114
|
+
expect(node.right).toBeNull();
|
|
115
|
+
});
|
|
121
116
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
test("does nothing on optimal 2 child tree", () => {
|
|
118
|
+
const a = leaf(0, 1, "hello");
|
|
119
|
+
const b = leaf(2, 3, "goodbye");
|
|
125
120
|
|
|
126
|
-
|
|
127
|
-
expect(root.left.parentNode).toEqual(root);
|
|
128
|
-
expect(root.right.parentNode).toEqual(root);
|
|
121
|
+
const root = pair(a, b);
|
|
129
122
|
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
const optimized = optimize(root, 100);
|
|
124
|
+
expect(optimized).toBe(0);
|
|
132
125
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const c = leaf(0, 1, "c");
|
|
137
|
-
const d = leaf(1, 2, "d");
|
|
126
|
+
//positions preserved
|
|
127
|
+
expect(root.left.object).toEqual(a.object);
|
|
128
|
+
expect(root.right.object).toEqual(b.object);
|
|
138
129
|
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
//parent node is root
|
|
131
|
+
expect(root.left.parentNode).toEqual(root);
|
|
132
|
+
expect(root.right.parentNode).toEqual(root);
|
|
141
133
|
|
|
142
|
-
|
|
134
|
+
expect(root).toBeValid();
|
|
135
|
+
});
|
|
143
136
|
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
test("does nothing on optimal depth 2 tree", () => {
|
|
138
|
+
const a = leaf(-2, -1, "a");
|
|
139
|
+
const b = leaf(-1, 0, "b");
|
|
140
|
+
const c = leaf(0, 1, "c");
|
|
141
|
+
const d = leaf(1, 2, "d");
|
|
146
142
|
|
|
147
|
-
|
|
143
|
+
const n0 = pair(a, b);
|
|
144
|
+
const n1 = pair(c, d);
|
|
148
145
|
|
|
149
|
-
|
|
150
|
-
expect(root.right).toBe(n1);
|
|
146
|
+
const root = pair(n0, n1);
|
|
151
147
|
|
|
152
|
-
|
|
153
|
-
|
|
148
|
+
const optimized = optimize(root, 100);
|
|
149
|
+
expect(optimized).toBe(0);
|
|
154
150
|
|
|
155
|
-
|
|
156
|
-
expect(n1.right).toBe(d);
|
|
151
|
+
expect(root.parentNode).toBeNull();
|
|
157
152
|
|
|
158
|
-
|
|
159
|
-
|
|
153
|
+
expect(root.left).toBe(n0);
|
|
154
|
+
expect(root.right).toBe(n1);
|
|
160
155
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const b = leaf(-1, 0, "b");
|
|
164
|
-
const c = leaf(0, 1, "c");
|
|
165
|
-
const d = leaf(1, 2, "d");
|
|
156
|
+
expect(n0.left).toBe(a);
|
|
157
|
+
expect(n0.right).toBe(b);
|
|
166
158
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
pair(c, d),
|
|
170
|
-
b
|
|
171
|
-
),
|
|
172
|
-
a
|
|
173
|
-
);
|
|
159
|
+
expect(n1.left).toBe(c);
|
|
160
|
+
expect(n1.right).toBe(d);
|
|
174
161
|
|
|
175
|
-
|
|
162
|
+
expect(root).toBeValid();
|
|
163
|
+
});
|
|
176
164
|
|
|
177
|
-
|
|
165
|
+
test("produces a valid tree from left-leaning tree with 4 leaves", () => {
|
|
166
|
+
const a = leaf(-2, -1, "a");
|
|
167
|
+
const b = leaf(-1, 0, "b");
|
|
168
|
+
const c = leaf(0, 1, "c");
|
|
169
|
+
const d = leaf(1, 2, "d");
|
|
178
170
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
171
|
+
const root = pair(
|
|
172
|
+
pair(
|
|
173
|
+
pair(c, d),
|
|
174
|
+
b
|
|
175
|
+
),
|
|
176
|
+
a
|
|
177
|
+
);
|
|
184
178
|
|
|
185
|
-
|
|
186
|
-
const a = leaf(-2, -1, "a");
|
|
187
|
-
const b = leaf(-1, 0, "b");
|
|
188
|
-
const c = leaf(0, 1, "c");
|
|
189
|
-
const d = leaf(1, 2, "d");
|
|
179
|
+
optimize(root, 100);
|
|
190
180
|
|
|
191
|
-
|
|
192
|
-
a,
|
|
193
|
-
pair(
|
|
194
|
-
b,
|
|
195
|
-
pair(c, d)
|
|
196
|
-
)
|
|
197
|
-
);
|
|
181
|
+
expect(root).toBeValid();
|
|
198
182
|
|
|
199
|
-
|
|
183
|
+
expect(root).toContainNode(a);
|
|
184
|
+
expect(root).toContainNode(b);
|
|
185
|
+
expect(root).toContainNode(c);
|
|
186
|
+
expect(root).toContainNode(d);
|
|
187
|
+
});
|
|
200
188
|
|
|
201
|
-
|
|
189
|
+
test("produces a valid tree from right-leaning tree with 4 leaves", () => {
|
|
190
|
+
const a = leaf(-2, -1, "a");
|
|
191
|
+
const b = leaf(-1, 0, "b");
|
|
192
|
+
const c = leaf(0, 1, "c");
|
|
193
|
+
const d = leaf(1, 2, "d");
|
|
202
194
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
195
|
+
const root = pair(
|
|
196
|
+
a,
|
|
197
|
+
pair(
|
|
198
|
+
b,
|
|
199
|
+
pair(c, d)
|
|
200
|
+
)
|
|
201
|
+
);
|
|
208
202
|
|
|
209
|
-
|
|
210
|
-
const random = seededRandom(42);
|
|
203
|
+
optimize(root, 100);
|
|
211
204
|
|
|
212
|
-
|
|
205
|
+
expect(root).toBeValid();
|
|
213
206
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
207
|
+
expect(root).toContainNode(a);
|
|
208
|
+
expect(root).toContainNode(b);
|
|
209
|
+
expect(root).toContainNode(c);
|
|
210
|
+
expect(root).toContainNode(d);
|
|
211
|
+
});
|
|
218
212
|
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
const z1 = z0 + random() * 5;
|
|
213
|
+
test("100 node random tree optimization does not degrade quality", () => {
|
|
214
|
+
const random = seededRandom(42);
|
|
222
215
|
|
|
223
|
-
nodes
|
|
224
|
-
}
|
|
216
|
+
const nodes = [];
|
|
225
217
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
218
|
+
for (let i = 0; i < 100; i++) {
|
|
219
|
+
const x0 = random() * 100;
|
|
220
|
+
const y0 = random() * 100;
|
|
221
|
+
const z0 = random() * 100;
|
|
222
|
+
|
|
223
|
+
const x1 = x0 + random() * 5;
|
|
224
|
+
const y1 = y0 + random() * 5;
|
|
225
|
+
const z1 = z0 + random() * 5;
|
|
231
226
|
|
|
232
|
-
|
|
227
|
+
nodes.push(new LeafNode(i, x0, y0, z0, x1, y1, z1));
|
|
228
|
+
}
|
|
233
229
|
|
|
234
|
-
|
|
230
|
+
while (nodes.length >= 2) {
|
|
231
|
+
const left = nodes.pop();
|
|
232
|
+
const right = nodes.pop();
|
|
233
|
+
nodes.unshift(pair(left, right));
|
|
234
|
+
}
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
const root = nodes[0];
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
const oldSAH = root.computeSAH();
|
|
239
239
|
|
|
240
|
-
|
|
240
|
+
optimize(root, 100);
|
|
241
241
|
|
|
242
|
-
|
|
243
|
-
expect(newSAH).toBeLessThanOrEqual(oldSAH);
|
|
244
|
-
});
|
|
242
|
+
expect(root).toBeValid();
|
|
245
243
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
244
|
+
const newSAH = root.computeSAH();
|
|
245
|
+
|
|
246
|
+
//at least not degraded
|
|
247
|
+
expect(newSAH).toBeLessThanOrEqual(oldSAH);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
test("case 0: 4 node tree optimization does not degrade quality", () => {
|
|
251
|
+
const ll = new LeafNode("ll",
|
|
252
|
+
76.06244471671744,
|
|
253
|
+
7.73902752171125,
|
|
254
|
+
1.925105413576489,
|
|
255
|
+
94.49883157197291,
|
|
256
|
+
50.63123012084361,
|
|
257
|
+
76.75841101302467
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const lr = new LeafNode("lr",
|
|
261
|
+
76.11310176957886,
|
|
262
|
+
58.65097077867176,
|
|
263
|
+
11.346076624795387,
|
|
264
|
+
97.55653706044541,
|
|
265
|
+
89.91247777413719,
|
|
266
|
+
90.73181902923352
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const rl = new LeafNode("rl",
|
|
270
|
+
32.4771196630536,
|
|
271
|
+
0.9366270797727339,
|
|
272
|
+
1.378434756588831,
|
|
273
|
+
66.71670340545461,
|
|
274
|
+
99.32784918828929,
|
|
275
|
+
97.52435446605432
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const rr = new LeafNode("rr",
|
|
279
|
+
1.124263022938976,
|
|
280
|
+
0.13232239543867763,
|
|
281
|
+
2.702786005283997,
|
|
282
|
+
31.51776058888572,
|
|
283
|
+
94.87720282424561,
|
|
284
|
+
101.03932220629758
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
const root = pair(pair(ll, lr), pair(rl, rr));
|
|
288
|
+
|
|
289
|
+
expect(root).toBeValid();
|
|
290
|
+
|
|
291
|
+
const oldSAH = root.computeSAH();
|
|
292
|
+
|
|
293
|
+
optimize(root, 1000);
|
|
294
|
+
|
|
295
|
+
expect(root).toBeValid();
|
|
296
|
+
|
|
297
|
+
const newSAH = root.computeSAH();
|
|
298
|
+
|
|
299
|
+
//at least not degraded
|
|
300
|
+
expect(newSAH).toBeLessThanOrEqual(oldSAH);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
})
|
|
@@ -16,6 +16,8 @@ class Line {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
const DEFAULT_INDENT_SPACES = 4;
|
|
20
|
+
|
|
19
21
|
/**
|
|
20
22
|
* Useful for creating formatted snippets of code
|
|
21
23
|
*/
|
|
@@ -35,7 +37,7 @@ class LineBuilder {
|
|
|
35
37
|
*
|
|
36
38
|
* @type {number}
|
|
37
39
|
*/
|
|
38
|
-
indentSpaces =
|
|
40
|
+
indentSpaces = DEFAULT_INDENT_SPACES;
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
*
|
|
@@ -82,8 +84,11 @@ class LineBuilder {
|
|
|
82
84
|
* @returns {LineBuilder}
|
|
83
85
|
*/
|
|
84
86
|
add(line_text) {
|
|
87
|
+
|
|
85
88
|
const line = new Line(line_text, this.indentation);
|
|
89
|
+
|
|
86
90
|
this.lines.push(line);
|
|
91
|
+
|
|
87
92
|
return this;
|
|
88
93
|
}
|
|
89
94
|
|
|
@@ -110,7 +115,7 @@ class LineBuilder {
|
|
|
110
115
|
clear() {
|
|
111
116
|
this.lines = [];
|
|
112
117
|
this.indentation = 0;
|
|
113
|
-
this.indentSpaces =
|
|
118
|
+
this.indentSpaces = DEFAULT_INDENT_SPACES;
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
/**
|
|
@@ -119,14 +124,16 @@ class LineBuilder {
|
|
|
119
124
|
*/
|
|
120
125
|
build() {
|
|
121
126
|
const result = [];
|
|
122
|
-
let i, j, l;
|
|
123
127
|
|
|
128
|
+
let i, j, l;
|
|
124
129
|
|
|
125
130
|
const lines = this.lines;
|
|
131
|
+
|
|
126
132
|
for (i = 0, l = lines.length; i < l; i++) {
|
|
127
133
|
const line = lines[i];
|
|
128
134
|
|
|
129
135
|
let indentString = '';
|
|
136
|
+
|
|
130
137
|
for (j = 0; j < line.indentation * this.indentSpaces; j++) {
|
|
131
138
|
indentString += ' ';
|
|
132
139
|
}
|
|
@@ -149,6 +156,8 @@ class LineBuilder {
|
|
|
149
156
|
|
|
150
157
|
const n = lines.length;
|
|
151
158
|
|
|
159
|
+
// TODO detect indent
|
|
160
|
+
|
|
152
161
|
for (let i = 0; i < n; i++) {
|
|
153
162
|
|
|
154
163
|
r.add(lines[i]);
|