@woosh/meep-engine 2.49.7 → 2.49.9
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/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/bessel_i0.spec.js +43 -0
- package/src/core/math/bessel_j0.js +30 -0
- package/src/core/math/hash/murmur3_32.spec.js +8 -0
- package/src/core/math/hash/squirrel3.spec.js +16 -0
- package/src/core/math/interval/NumericInterval.js +1 -0
- package/src/core/math/{bessel_i0.js → modified_bessel_i0.js} +5 -2
- package/src/core/math/noise/{create_noise_2d.js → create_simplex_noise_2d.js} +2 -2
- package/src/core/math/noise/create_simplex_noise_2d.spec.js +21 -0
- package/src/core/math/normalizeArrayVector.spec.js +15 -0
- package/src/core/math/physics/irradiance/interpolate_irradiance_linear.spec.js +20 -0
- package/src/core/math/physics/irradiance/interpolate_irradiance_lograrithmic.js +4 -4
- package/src/core/math/physics/irradiance/interpolate_irradiance_lograrithmic.spec.js +18 -0
- package/src/core/math/physics/irradiance/interpolate_irradiance_smith.js +1 -1
- package/src/core/math/physics/irradiance/interpolate_irradiance_smith.spec.js +20 -0
- package/src/core/math/random/seededRandomMersenneTwister.spec.js +10 -0
- package/src/core/math/spline/spline_bezier3.js +1 -1
- package/src/core/math/spline/spline_bezier3_bounds.js +2 -1
- package/src/core/math/spline/spline_bezier3_bounds.spec.js +37 -0
- package/src/core/math/statistics/computeSampleSize_Cochran.spec.js +12 -0
- package/src/core/math/statistics/computeStatisticalPartialMedian.js +4 -0
- package/src/core/math/statistics/computeStatisticalPartialMedian.spec.js +13 -0
- 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/achievements/Achievement.spec.js +21 -0
- package/src/engine/animation/curve/compression/prototypeCurveCompression.js +2 -2
- package/src/engine/animation/curve/compression/{animation_curve_to_float_array.js → sample_animation_curve_to_float_array.js} +10 -3
- package/src/engine/animation/curve/compression/sample_animation_curve_to_float_array.spec.js +29 -0
- package/src/engine/animation/curve/draw/build_curve_editor.js +3 -3
- package/src/engine/development/performance/RingBufferMetric.js +1 -1
- package/src/engine/ecs/animation/Animation.js +2 -180
- package/src/engine/ecs/animation/AnimationClip.js +132 -0
- package/src/engine/ecs/animation/AnimationClip.spec.js +5 -0
- package/src/engine/ecs/animation/AnimationClipFlag.js +7 -0
- package/src/engine/ecs/animation/AnimationFlags.js +8 -0
- package/src/engine/ecs/animation/AnimationSerializationAdapter.js +32 -0
- package/src/engine/ecs/systems/AnimationSystem.js +3 -1
- package/src/engine/graphics/GraphicsEngine.js +2 -13
- package/src/engine/graphics/camera/testClippingPlaneComputation.js +1 -1
- package/src/engine/graphics/ecs/animation/AnimationControllerSystem.js +2 -1
- package/src/engine/graphics/ecs/compileAllMaterials.js +1 -1
- package/src/engine/graphics/ecs/mesh/createTaskWaitForMeshesToLoad.js +1 -1
- package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +1 -1
- package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.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 +3 -5
- package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +2 -2
- package/src/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +1 -1
- package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +3 -5
- 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/sampler/filter/kaiser_1.js +8 -4
- package/src/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +2 -0
- 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/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/filtering/numeric/complex/CellFilterAngleToNormal.js +11 -4
- package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.spec.js +30 -0
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +18 -2
- package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.spec.js +17 -0
- package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +2 -2
- package/src/generation/grid/GridData.js +0 -60
- package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +2 -2
- /package/src/core/collection/{IteratorUtils.js → collectIteratorValueToArray.js} +0 -0
- /package/src/core/color/{ColorUtils.js → parseColor.js} +0 -0
- /package/src/engine/ecs/{animation → ik}/IKMath.js +0 -0
- /package/src/engine/ecs/{animation → ik}/IKProblem.js +0 -0
- /package/src/engine/ecs/{animation → ik}/IKSolver.js +0 -0
- /package/src/engine/ecs/{animation → ik}/InverseKinematics.js +0 -0
- /package/src/engine/ecs/{animation → ik}/InverseKinematicsSystem.js +0 -0
- /package/src/engine/ecs/{animation → ik}/OneBoneSurfaceAlignmentSolver.js +0 -0
- /package/src/engine/ecs/{animation → ik}/TwoBoneInverseKinematicsSolver.js +0 -0
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { bessel_j0 } from "./bessel_j0.js";
|
|
2
|
+
|
|
3
|
+
test("sanity", () => {
|
|
4
|
+
const v = bessel_j0(0);
|
|
5
|
+
|
|
6
|
+
expect(typeof v).toBe("number");
|
|
7
|
+
expect(v).not.toBeNaN();
|
|
8
|
+
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("sweep through low positive values", () => {
|
|
12
|
+
// https://www.wolframalpha.com/input?i=besselj%5B0%2Cx%5D
|
|
13
|
+
|
|
14
|
+
expect(bessel_j0(0)).toBeCloseTo(1, 1);
|
|
15
|
+
expect(bessel_j0(0.1)).toBeCloseTo(0.997, 1);
|
|
16
|
+
expect(bessel_j0(0.2)).toBeCloseTo(0.990, 1);
|
|
17
|
+
expect(bessel_j0(0.3)).toBeCloseTo(0.977, 1);
|
|
18
|
+
expect(bessel_j0(0.4)).toBeCloseTo(0.960, 1);
|
|
19
|
+
expect(bessel_j0(0.5)).toBeCloseTo(0.938, 1);
|
|
20
|
+
expect(bessel_j0(0.6)).toBeCloseTo(0.912, 1);
|
|
21
|
+
expect(bessel_j0(0.7)).toBeCloseTo(0.881, 1);
|
|
22
|
+
expect(bessel_j0(0.8)).toBeCloseTo(0.846, 1);
|
|
23
|
+
expect(bessel_j0(0.9)).toBeCloseTo(0.807, 1);
|
|
24
|
+
expect(bessel_j0(1)).toBeCloseTo(0.765, 1);
|
|
25
|
+
expect(bessel_j0(2)).toBeCloseTo(0.223, 1);
|
|
26
|
+
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("roots", () => {
|
|
30
|
+
|
|
31
|
+
expect(bessel_j0(2.40482555769577)).toBeCloseTo(0, 1);
|
|
32
|
+
expect(bessel_j0(-2.40482555769577)).toBeCloseTo(0, 1);
|
|
33
|
+
|
|
34
|
+
expect(bessel_j0(5.52007811028631)).toBeCloseTo(0, 1);
|
|
35
|
+
expect(bessel_j0(-5.52007811028631)).toBeCloseTo(0, 1);
|
|
36
|
+
|
|
37
|
+
expect(bessel_j0(8.65372791291101)).toBeCloseTo(0, 1);
|
|
38
|
+
expect(bessel_j0(-8.65372791291101)).toBeCloseTo(0, 1);
|
|
39
|
+
|
|
40
|
+
expect(bessel_j0(11.7915344390143)).toBeCloseTo(0, 1);
|
|
41
|
+
expect(bessel_j0(-11.7915344390143)).toBeCloseTo(0, 1);
|
|
42
|
+
|
|
43
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { assert } from "../assert.js";
|
|
2
|
+
|
|
3
|
+
const q = 0.7172491568;
|
|
4
|
+
const p0 = 0.6312725339;
|
|
5
|
+
const ps0 = 0.4308049446;
|
|
6
|
+
const p1 = 0.3500347951;
|
|
7
|
+
const ps1 = 0.4678202347;
|
|
8
|
+
const p2 = -0.06207747907;
|
|
9
|
+
const ps2 = 0.04253832927;
|
|
10
|
+
// const lamb4 = (lamb * lamb) * (lamb * lamb);
|
|
11
|
+
const lamb4 = 0.559840650625;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Bessel first order function of zeroth order
|
|
15
|
+
* @see https://link.springer.com/article/10.1007/s40314-020-01238-z
|
|
16
|
+
* @see https://www.shadertoy.com/view/Wt3czM
|
|
17
|
+
* @param {number} x
|
|
18
|
+
* @return {number}
|
|
19
|
+
*/
|
|
20
|
+
export function bessel_j0(x) {
|
|
21
|
+
assert.notNaN(x, 'x');
|
|
22
|
+
|
|
23
|
+
const xx = x * x;
|
|
24
|
+
|
|
25
|
+
const t0 = Math.sqrt(1.0 + lamb4 * xx);
|
|
26
|
+
const t1 = Math.sqrt(t0);
|
|
27
|
+
|
|
28
|
+
return xx === 0.0 ? 1.0 : 1.0 / (t1 * (1.0 + q * xx)) * ((p0 + p1 * xx + p2 * t0) * Math.cos(x) + ((ps0 + ps1 * xx) * t0 + ps2 * xx) * (Math.sin(x) / x));
|
|
29
|
+
|
|
30
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { squirrel3 } from "./squirrel3.js";
|
|
2
|
+
|
|
3
|
+
function expect_integer(v) {
|
|
4
|
+
|
|
5
|
+
expect(typeof v).toBe("number");
|
|
6
|
+
expect(Number.isInteger(v)).toBe(true);
|
|
7
|
+
expect(v).not.toBeNaN();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
test("sanity check", () => {
|
|
11
|
+
expect_integer(squirrel3(0));
|
|
12
|
+
expect_integer(squirrel3(1));
|
|
13
|
+
expect_integer(squirrel3(-1));
|
|
14
|
+
|
|
15
|
+
expect(squirrel3(0)).not.toEqual(squirrel3(1));
|
|
16
|
+
});
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { assert } from "../assert.js";
|
|
2
2
|
|
|
3
|
+
// const lamb = 0.865;
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
|
-
* Modified bessel function of the first kind
|
|
6
|
+
* Modified bessel function of the first kind zeroth order
|
|
5
7
|
* @see https://mathworld.wolfram.com/ModifiedBesselFunctionoftheFirstKind.html
|
|
6
8
|
* @see https://computergraphics.stackexchange.com/questions/6393/kaiser-windowed-sinc-filter-for-mip-mapping
|
|
7
9
|
* @see https://github.com/terifan/ImageResampler/blob/dbc212ce6aaa769bf3c9623cb6ead58ffd51d76c/src/org/terifan/image_resampler/FilterFactory.java
|
|
8
10
|
* @param {number} x
|
|
9
11
|
* @returns {number}
|
|
10
12
|
*/
|
|
11
|
-
export function
|
|
13
|
+
export function modified_bessel_i0(x) {
|
|
12
14
|
assert.notNaN(x, 'x');
|
|
13
15
|
|
|
14
16
|
let sum = 1.0;
|
|
@@ -24,3 +26,4 @@ export function bessel_i0(x) {
|
|
|
24
26
|
|
|
25
27
|
return sum;
|
|
26
28
|
}
|
|
29
|
+
|
|
@@ -58,9 +58,9 @@ const grad4 = /*#__PURE__*/ new Float64Array([0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1,
|
|
|
58
58
|
/**
|
|
59
59
|
* Creates a 2D noise function
|
|
60
60
|
* @param random the random function that will be used to build the permutation table
|
|
61
|
-
* @returns {function(x:number, y:number):number}
|
|
61
|
+
* @returns {function(x:number, y:number):number} producing values in range -1 .. 1
|
|
62
62
|
*/
|
|
63
|
-
export function
|
|
63
|
+
export function create_simplex_noise_2d(random = Math.random) {
|
|
64
64
|
// allocate continuous chunk of memory
|
|
65
65
|
const buffer = new ArrayBuffer(512 * 2);
|
|
66
66
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { create_simplex_noise_2d } from "./create_simplex_noise_2d.js";
|
|
2
|
+
|
|
3
|
+
test("sample 10 points in 0..1 range", () => {
|
|
4
|
+
const noise2d = create_simplex_noise_2d(() => 0);
|
|
5
|
+
|
|
6
|
+
const COUNT = 10;
|
|
7
|
+
for (let i = 0; i < COUNT; i++) {
|
|
8
|
+
const u = i / (COUNT - 1);
|
|
9
|
+
for (let j = 0; j < COUNT; j++) {
|
|
10
|
+
const v = j / (COUNT - 1);
|
|
11
|
+
|
|
12
|
+
const value = noise2d(u, v);
|
|
13
|
+
|
|
14
|
+
expect(typeof value).toBe('number');
|
|
15
|
+
expect(value).not.toBeNaN();
|
|
16
|
+
|
|
17
|
+
expect(value).toBeGreaterThanOrEqual(-1);
|
|
18
|
+
expect(value).toBeLessThanOrEqual(1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { normalizeArrayVector } from "./normalizeArrayVector.js";
|
|
2
|
+
|
|
3
|
+
test("1d vector normalization", () => {
|
|
4
|
+
const v = [7];
|
|
5
|
+
|
|
6
|
+
normalizeArrayVector(v, v, 1);
|
|
7
|
+
|
|
8
|
+
expect(v[0]).toBeCloseTo(1);
|
|
9
|
+
|
|
10
|
+
v[0] = -13;
|
|
11
|
+
|
|
12
|
+
normalizeArrayVector(v, v, 1);
|
|
13
|
+
|
|
14
|
+
expect(v[0]).toBeCloseTo(-1);
|
|
15
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { interpolate_irradiance_linear } from "./interpolate_irradiance_linear.js";
|
|
2
|
+
|
|
3
|
+
test("sanity check", () => {
|
|
4
|
+
|
|
5
|
+
expect(interpolate_irradiance_linear(3, 3, 3)).toBe(1);
|
|
6
|
+
|
|
7
|
+
expect(interpolate_irradiance_linear(3, 3, 7)).toBe(1);
|
|
8
|
+
|
|
9
|
+
expect(interpolate_irradiance_linear(7, 3, 7)).toBe(0);
|
|
10
|
+
|
|
11
|
+
expect(interpolate_irradiance_linear(0, 3, 7)).toBe(1);
|
|
12
|
+
|
|
13
|
+
expect(interpolate_irradiance_linear(11, 3, 7)).toBe(0);
|
|
14
|
+
|
|
15
|
+
const mid = interpolate_irradiance_linear(5, 3, 7);
|
|
16
|
+
|
|
17
|
+
expect(mid).toBeGreaterThan(0);
|
|
18
|
+
expect(mid).toBeLessThan(1);
|
|
19
|
+
|
|
20
|
+
});
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { inverseLerp } from "../../inverseLerp.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Approximates logarithmic decay, except it goes to 0 at max
|
|
5
|
+
* Estimation is done using a 5th degree polynomial
|
|
5
6
|
* @param {number} distance
|
|
6
7
|
* @param {number} min
|
|
7
8
|
* @param {number} max
|
|
8
9
|
* @return {number}
|
|
9
10
|
*/
|
|
10
11
|
export function interpolate_irradiance_lograrithmic(distance, min, max) {
|
|
11
|
-
if (distance >= max) {
|
|
12
|
-
return 0;
|
|
13
|
-
}
|
|
14
12
|
|
|
15
13
|
if (distance <= min) {
|
|
16
14
|
return 1;
|
|
15
|
+
} else if (distance >= max) {
|
|
16
|
+
return 0;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
const x = inverseLerp(min, max, distance);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { interpolate_irradiance_lograrithmic } from "./interpolate_irradiance_lograrithmic.js";
|
|
2
|
+
|
|
3
|
+
test("sanity check", () => {
|
|
4
|
+
expect(interpolate_irradiance_lograrithmic(3, 3, 3)).toBe(1);
|
|
5
|
+
|
|
6
|
+
expect(interpolate_irradiance_lograrithmic(3, 3, 7)).toBe(1);
|
|
7
|
+
|
|
8
|
+
expect(interpolate_irradiance_lograrithmic(7, 3, 7)).toBe(0);
|
|
9
|
+
|
|
10
|
+
expect(interpolate_irradiance_lograrithmic(0, 3, 7)).toBe(1);
|
|
11
|
+
|
|
12
|
+
expect(interpolate_irradiance_lograrithmic(11, 3, 7)).toBe(0);
|
|
13
|
+
|
|
14
|
+
const mid = interpolate_irradiance_lograrithmic(5, 3, 7);
|
|
15
|
+
|
|
16
|
+
expect(mid).toBeGreaterThan(0);
|
|
17
|
+
expect(mid).toBeLessThan(1);
|
|
18
|
+
});
|