@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
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { EngineHarness } from "../../../../engine/EngineHarness.js";
|
|
2
2
|
import { compute_delaunay_tetrahedral_mesh } from "./delaunay/compute_delaunay_tetrahedral_mesh.js";
|
|
3
|
-
import { LineBasicMaterial
|
|
4
|
-
import { BufferGeometry } from "three/src/core/BufferGeometry.js";
|
|
5
|
-
import { Float32BufferAttribute } from "three/src/core/BufferAttribute.js";
|
|
3
|
+
import { LineBasicMaterial } from "three";
|
|
6
4
|
import { ShadedGeometry } from "../../../../engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
|
|
7
5
|
import { DrawMode } from "../../../../engine/graphics/ecs/mesh-v2/DrawMode.js";
|
|
8
6
|
import EntityBuilder from "../../../../engine/ecs/EntityBuilder.js";
|
|
@@ -10,7 +8,11 @@ import { Transform } from "../../../../engine/ecs/transform/Transform.js";
|
|
|
10
8
|
import { ShadedGeometrySystem } from "../../../../engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
11
9
|
import { GizmoRenderingPlugin } from "../../../../engine/graphics/render/gizmo/GizmoRenderingPlugin.js";
|
|
12
10
|
import { Gizmo } from "../../../../engine/graphics/render/gizmo/Gizmo.js";
|
|
13
|
-
import {
|
|
11
|
+
import { build_tetrahedral_mesh_buffer_geometry } from "./build_tetrahedral_mesh_buffer_geometry.js";
|
|
12
|
+
import { seededRandom } from "../../../math/random/seededRandom.js";
|
|
13
|
+
import { randomFloatBetween } from "../../../math/random/randomFloatBetween.js";
|
|
14
|
+
import { delay } from "../../../process/delay.js";
|
|
15
|
+
import { TetrahedralMesh } from "./TetrahedralMesh.js";
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
*
|
|
@@ -26,45 +28,52 @@ async function main(engine) {
|
|
|
26
28
|
const offset = [7.5, 1, 7.5];
|
|
27
29
|
const scale = [.5, .5, .5];
|
|
28
30
|
|
|
29
|
-
const points = [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
31
|
+
const points = [];
|
|
32
|
+
|
|
33
|
+
// points.push(
|
|
34
|
+
// 0, 0, 0,
|
|
35
|
+
// 10, 0, 0,
|
|
36
|
+
// 10, 0, 10,
|
|
37
|
+
// 0, 0, 10,
|
|
38
|
+
//
|
|
39
|
+
// 0, 10, 0,
|
|
40
|
+
// 10, 10, 0,
|
|
41
|
+
// 10, 10, 10,
|
|
42
|
+
// 0, 10, 10,
|
|
43
|
+
// );
|
|
44
|
+
|
|
45
|
+
const random = seededRandom();
|
|
46
|
+
|
|
47
|
+
for (let i = 0; i < 600; i++) {
|
|
48
|
+
points.push(
|
|
49
|
+
randomFloatBetween(random, -100, 100),
|
|
50
|
+
randomFloatBetween(random, 0, 150),
|
|
51
|
+
randomFloatBetween(random, -100, 100),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
44
54
|
|
|
45
|
-
|
|
55
|
+
// make_justified_point_grid(new AABB3(-100, 0, -100, 100, 150, 100), 40, (x, y, z) => {
|
|
56
|
+
// points.push(x, y, z);
|
|
57
|
+
// });
|
|
46
58
|
|
|
47
|
-
|
|
59
|
+
await delay(1000);
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
61
|
+
const tetrahedra = new TetrahedralMesh();
|
|
62
|
+
// console.time('mesh build');
|
|
63
|
+
console.profile('mesh build');
|
|
64
|
+
compute_delaunay_tetrahedral_mesh(tetrahedra, points, points.length / 3);
|
|
65
|
+
console.profileEnd('mesh build');
|
|
66
|
+
// console.timeEnd('mesh build');
|
|
53
67
|
|
|
54
|
-
|
|
55
|
-
lines.push(a, c);
|
|
56
|
-
lines.push(a, d);
|
|
68
|
+
console.log(tetrahedra);
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
lines.push(c, d);
|
|
60
|
-
lines.push(b, d);
|
|
70
|
+
await delay(500);
|
|
61
71
|
|
|
62
|
-
|
|
72
|
+
const relocated_elements = tetrahedra.compact();
|
|
73
|
+
console.log(`Compaction relocated ${relocated_elements} elements`);
|
|
63
74
|
|
|
64
|
-
const geometry =
|
|
75
|
+
const geometry = build_tetrahedral_mesh_buffer_geometry(tetrahedra, points);
|
|
65
76
|
|
|
66
|
-
geometry.setIndex(new Uint32BufferAttribute(lines, 1, false));
|
|
67
|
-
geometry.setAttribute('position', new Float32BufferAttribute(points, 3, false));
|
|
68
77
|
|
|
69
78
|
|
|
70
79
|
new EntityBuilder()
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute signed volume of a tetrahedron with the last point at the origin
|
|
3
|
+
* @see "EFFICIENT FEATURE EXTRACTION FOR 2D/3D OBJECTS IN MESH REPRESENTATION" by Cha Zhang and Tsuhan Chen
|
|
4
|
+
* @param {number} ax
|
|
5
|
+
* @param {number} ay
|
|
6
|
+
* @param {number} az
|
|
7
|
+
* @param {number} bx
|
|
8
|
+
* @param {number} by
|
|
9
|
+
* @param {number} bz
|
|
10
|
+
* @param {number} cx
|
|
11
|
+
* @param {number} cy
|
|
12
|
+
* @param {number} cz
|
|
13
|
+
* @return {number}
|
|
14
|
+
*/
|
|
15
|
+
function triangle_compute_signed_volume(
|
|
16
|
+
ax, ay, az,
|
|
17
|
+
bx, by, bz,
|
|
18
|
+
cx, cy, cz
|
|
19
|
+
) {
|
|
20
|
+
|
|
21
|
+
const v321 = cx * by * az;
|
|
22
|
+
const v231 = bx * cy * az;
|
|
23
|
+
const v312 = cx * ay * bz;
|
|
24
|
+
const v132 = ax * cy * bz;
|
|
25
|
+
const v213 = bx * ay * cz;
|
|
26
|
+
const v123 = ax * by * cz;
|
|
27
|
+
|
|
28
|
+
return (1.0 / 6.0) * (-v321 + v231 + v312 - v132 - v213 + v123);
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @see https://en.wikipedia.org/wiki/Tetrahedron
|
|
35
|
+
*
|
|
36
|
+
* @param {ArrayLike<number>|number[]|Float32Array} points
|
|
37
|
+
* @param {number} a
|
|
38
|
+
* @param {number} b
|
|
39
|
+
* @param {number} c
|
|
40
|
+
* @param {number} d
|
|
41
|
+
* @returns {number}
|
|
42
|
+
*/
|
|
43
|
+
export function tetrahedron_compute_signed_volume(points, a, b, c, d) {
|
|
44
|
+
|
|
45
|
+
const a3 = a * 3;
|
|
46
|
+
const b3 = b * 3;
|
|
47
|
+
const c3 = c * 3;
|
|
48
|
+
const d3 = d * 3;
|
|
49
|
+
|
|
50
|
+
const ax = points[a3];
|
|
51
|
+
const ay = points[a3 + 1];
|
|
52
|
+
const az = points[a3 + 2];
|
|
53
|
+
|
|
54
|
+
const bx = points[b3];
|
|
55
|
+
const by = points[b3 + 1];
|
|
56
|
+
const bz = points[b3 + 2];
|
|
57
|
+
|
|
58
|
+
const cx = points[c3];
|
|
59
|
+
const cy = points[c3 + 1];
|
|
60
|
+
const cz = points[c3 + 2];
|
|
61
|
+
|
|
62
|
+
const dx = points[d3];
|
|
63
|
+
const dy = points[d3 + 1];
|
|
64
|
+
const dz = points[d3 + 2];
|
|
65
|
+
|
|
66
|
+
const adx = ax - dx;
|
|
67
|
+
const ady = ay - dy;
|
|
68
|
+
const adz = az - dz;
|
|
69
|
+
|
|
70
|
+
const bdx = bx - dx;
|
|
71
|
+
const bdy = by - dy;
|
|
72
|
+
const bdz = bz - dz;
|
|
73
|
+
|
|
74
|
+
const cdx = cx - dx;
|
|
75
|
+
const cdy = cy - dy;
|
|
76
|
+
const cdz = cz - dz;
|
|
77
|
+
|
|
78
|
+
return triangle_compute_signed_volume(
|
|
79
|
+
adx, ady, adz,
|
|
80
|
+
bdx, bdy, bdz,
|
|
81
|
+
cdx, cdy, cdz
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { tetrahedron_compute_signed_volume } from "./tetrahedron_compute_signed_volume.js";
|
|
2
|
+
|
|
3
|
+
test("0 volume", () => {
|
|
4
|
+
expect(tetrahedron_compute_signed_volume([
|
|
5
|
+
0, 0, 0
|
|
6
|
+
], 0, 0, 0, 0)).toBe(0);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
test("positive volume", () => {
|
|
10
|
+
|
|
11
|
+
expect(tetrahedron_compute_signed_volume([
|
|
12
|
+
1, 0, 1,
|
|
13
|
+
1, 0, 0,
|
|
14
|
+
0, 0, 0,
|
|
15
|
+
1, 1, 1
|
|
16
|
+
], 1, 2, 3, 0)).toBeGreaterThan(0);
|
|
17
|
+
|
|
18
|
+
expect(tetrahedron_compute_signed_volume([
|
|
19
|
+
0, 0, 0,
|
|
20
|
+
2, 0, 0,
|
|
21
|
+
0, 2, 0,
|
|
22
|
+
0, 0, 2
|
|
23
|
+
], 1, 2, 3, 0)).toBeGreaterThan(0);
|
|
24
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { tetrahedron_contains_point } from "./tetrahedron_contains_point.js";
|
|
2
|
+
|
|
3
|
+
test("basic containment", () => {
|
|
4
|
+
const tetrahedron = [
|
|
5
|
+
1, 0, 1,
|
|
6
|
+
1, 0, 0,
|
|
7
|
+
0, 0, 0,
|
|
8
|
+
1, 1, 1
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
expect(
|
|
12
|
+
tetrahedron_contains_point([
|
|
13
|
+
...tetrahedron,
|
|
14
|
+
//
|
|
15
|
+
0.5, 0.1, 0.5
|
|
16
|
+
], 0, 1, 2, 3, 4)
|
|
17
|
+
).toBe(true);
|
|
18
|
+
|
|
19
|
+
expect(
|
|
20
|
+
tetrahedron_contains_point([
|
|
21
|
+
...tetrahedron,
|
|
22
|
+
//
|
|
23
|
+
-1, 0, 0
|
|
24
|
+
], 0, 1, 2, 3, 4)
|
|
25
|
+
).toBe(false);
|
|
26
|
+
|
|
27
|
+
expect(
|
|
28
|
+
tetrahedron_contains_point([
|
|
29
|
+
...tetrahedron,
|
|
30
|
+
//
|
|
31
|
+
2, 0, 0
|
|
32
|
+
], 0, 1, 2, 3, 4)
|
|
33
|
+
).toBe(false);
|
|
34
|
+
|
|
35
|
+
expect(
|
|
36
|
+
tetrahedron_contains_point([
|
|
37
|
+
...tetrahedron,
|
|
38
|
+
//
|
|
39
|
+
0, -1, 0
|
|
40
|
+
], 0, 1, 2, 3, 4)
|
|
41
|
+
).toBe(false);
|
|
42
|
+
|
|
43
|
+
expect(
|
|
44
|
+
tetrahedron_contains_point([
|
|
45
|
+
...tetrahedron,
|
|
46
|
+
//
|
|
47
|
+
0, 2, 0
|
|
48
|
+
], 0, 1, 2, 3, 4)
|
|
49
|
+
).toBe(false);
|
|
50
|
+
|
|
51
|
+
expect(
|
|
52
|
+
tetrahedron_contains_point([
|
|
53
|
+
...tetrahedron,
|
|
54
|
+
//
|
|
55
|
+
0, 0, -1
|
|
56
|
+
], 0, 1, 2, 3, 4)
|
|
57
|
+
).toBe(false);
|
|
58
|
+
|
|
59
|
+
expect(
|
|
60
|
+
tetrahedron_contains_point([
|
|
61
|
+
...tetrahedron,
|
|
62
|
+
//
|
|
63
|
+
0, 0, 2
|
|
64
|
+
], 0, 1, 2, 3, 4)
|
|
65
|
+
).toBe(false);
|
|
66
|
+
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { tetrahedron_compute_signed_volume } from "./tetrahedron_compute_signed_volume.js";
|
|
2
|
+
import { noop } from "../../../function/Functions.js";
|
|
3
|
+
import { INVALID_NEIGHBOUR } from "./TetrahedralMesh.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param {TetrahedralMesh} mesh
|
|
8
|
+
* @param {ArrayLike<number>|number[]} points
|
|
9
|
+
* @param {number} tet
|
|
10
|
+
* @return {number}
|
|
11
|
+
*/
|
|
12
|
+
export function get_tetrahedron_volume(mesh, points, tet) {
|
|
13
|
+
|
|
14
|
+
const a = mesh.getVertexIndex(tet, 0);
|
|
15
|
+
const b = mesh.getVertexIndex(tet, 1);
|
|
16
|
+
const c = mesh.getVertexIndex(tet, 2);
|
|
17
|
+
const d = mesh.getVertexIndex(tet, 3);
|
|
18
|
+
|
|
19
|
+
return tetrahedron_compute_signed_volume(points, a, b, c, d);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param {TetrahedralMesh} mesh
|
|
25
|
+
* @param {number} tet
|
|
26
|
+
* @param {number} neighbour_id
|
|
27
|
+
* @param {function(string):*} consumer
|
|
28
|
+
* @return {boolean}
|
|
29
|
+
*/
|
|
30
|
+
export function validate_neighbour(mesh, tet, neighbour_id, consumer) {
|
|
31
|
+
let valid = true;
|
|
32
|
+
|
|
33
|
+
const neighbour = mesh.getNeighbour(tet, neighbour_id);
|
|
34
|
+
|
|
35
|
+
if (neighbour === INVALID_NEIGHBOUR) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// decode neighbour
|
|
40
|
+
const neighbour_tet = neighbour >> 2;
|
|
41
|
+
const neighbour_vertex_id = neighbour & 3;
|
|
42
|
+
|
|
43
|
+
if (!mesh.exists(neighbour_tet)) {
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
consumer(`Tetrahedron ${tet} Neighbour[${neighbour_id}] ${neighbour_tet} does not exist in the mesh`);
|
|
47
|
+
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const back_link = mesh.getNeighbour(neighbour_tet, neighbour_vertex_id);
|
|
52
|
+
|
|
53
|
+
if (back_link === INVALID_NEIGHBOUR) {
|
|
54
|
+
|
|
55
|
+
consumer(`Tetrahedron ${tet} Neighbour[${neighbour_id}] ${neighbour_tet} links back to invalid neighbour (no neighbour), expected ${tet} instead`);
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const back_link_tet = back_link >> 2;
|
|
60
|
+
const back_link_vertex_index = back_link & 3;
|
|
61
|
+
|
|
62
|
+
if (back_link_tet !== tet) {
|
|
63
|
+
valid = false;
|
|
64
|
+
|
|
65
|
+
consumer(`Tetrahedron ${tet} Neighbour[${neighbour_id}] ${neighbour_tet} links back to a different tet, expected ${tet}, got ${back_link_tet}`)
|
|
66
|
+
} else if (back_link_vertex_index !== neighbour_id) {
|
|
67
|
+
valid = false;
|
|
68
|
+
|
|
69
|
+
consumer(`Tetrahedron ${tet} Neighbour[${neighbour_id}] ${neighbour_tet} links back to a different vertex, expected ${neighbour_id}, got ${back_link_vertex_index}`);
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (let j = 0; j < 4; j++) {
|
|
74
|
+
const v = mesh.getVertexIndex(tet, j);
|
|
75
|
+
|
|
76
|
+
if (j === neighbour_id) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!mesh.tetContainsVertex(neighbour_tet, v)) {
|
|
81
|
+
valid = false;
|
|
82
|
+
|
|
83
|
+
consumer(`Tetrahedron ${tet} Neighbour[${neighbour_id}] ${neighbour_tet} does not share vertex ${v} with the tet`);
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return valid;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
*
|
|
94
|
+
* @param {TetrahedralMesh} mesh
|
|
95
|
+
* @param {number} tet
|
|
96
|
+
* @param {function(problem:string):*} consumer
|
|
97
|
+
*/
|
|
98
|
+
export function validate_tetrahedron_neighbourhood(mesh, tet, consumer = noop) {
|
|
99
|
+
let valid = true;
|
|
100
|
+
|
|
101
|
+
for (let i = 0; i < 4; i++) {
|
|
102
|
+
|
|
103
|
+
if (!validate_neighbour(mesh, tet, i, consumer)) {
|
|
104
|
+
valid = false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return valid;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
*
|
|
114
|
+
* @param {TetrahedralMesh} mesh
|
|
115
|
+
* @param {number} tet
|
|
116
|
+
* @returns {boolean}
|
|
117
|
+
*/
|
|
118
|
+
function is_tetrahedron_degenerate(mesh, tet) {
|
|
119
|
+
|
|
120
|
+
for (let i0 = 0; i0 < 4; i0++) {
|
|
121
|
+
const v0 = mesh.getVertexIndex(tet, i0);
|
|
122
|
+
for (let i1 = i0 + 1; i1 < 4; i1++) {
|
|
123
|
+
if (v0 === mesh.getVertexIndex(tet, i1)) {
|
|
124
|
+
// identical vertices
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* @param {TetrahedralMesh} mesh
|
|
136
|
+
* @param {ArrayLike<number>} points
|
|
137
|
+
* @param {(problem:string)=>*} [consumer]
|
|
138
|
+
* @returns {boolean}
|
|
139
|
+
*/
|
|
140
|
+
export function validate_tetrahedral_mesh(mesh, points, consumer = noop) {
|
|
141
|
+
let is_valid = true;
|
|
142
|
+
|
|
143
|
+
mesh.forEach((tet, mesh) => {
|
|
144
|
+
|
|
145
|
+
const volume = get_tetrahedron_volume(mesh, points, tet);
|
|
146
|
+
if (volume < 0) {
|
|
147
|
+
is_valid = false;
|
|
148
|
+
|
|
149
|
+
consumer(`Tetrahedron ${tet} has negative volume ${volume}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// check for degeneracy
|
|
153
|
+
if (is_tetrahedron_degenerate(mesh, tet)) {
|
|
154
|
+
is_valid = false;
|
|
155
|
+
consumer(`Tetrahedron ${tet} is degenerate (multiple vertices have the same index)`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!validate_tetrahedron_neighbourhood(mesh, tet, consumer)) {
|
|
159
|
+
is_valid = false;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
return is_valid;
|
|
166
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { max2 } from "../../../math/max2.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Created a grid of points to fill given bounds, spacing is used as upper-bound,
|
|
5
|
+
* actual spacing will be justified to provide even distanced along each dimension separately
|
|
6
|
+
* @param {AABB3} aabb3
|
|
7
|
+
* @param {number} spacing
|
|
8
|
+
* @param {function(x:number,y:number,z:number)} callback
|
|
9
|
+
*/
|
|
10
|
+
export function make_justified_point_grid(aabb3, spacing, callback) {
|
|
11
|
+
|
|
12
|
+
const steps_x = Math.ceil(aabb3.getExtentsX() / spacing);
|
|
13
|
+
const steps_y = Math.ceil(aabb3.getExtentsY() / spacing);
|
|
14
|
+
const steps_z = Math.ceil(aabb3.getExtentsZ() / spacing);
|
|
15
|
+
|
|
16
|
+
const spacing_x = aabb3.getExtentsX() / max2(1, steps_x - 1);
|
|
17
|
+
const spacing_y = aabb3.getExtentsY() / max2(1, steps_y - 1);
|
|
18
|
+
const spacing_z = aabb3.getExtentsZ() / max2(1, steps_z - 1);
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < steps_x; i++) {
|
|
21
|
+
for (let j = 0; j < steps_y; j++) {
|
|
22
|
+
for (let k = 0; k < steps_z; k++) {
|
|
23
|
+
const x = i * spacing_x + aabb3.x0;
|
|
24
|
+
const y = j * spacing_y + aabb3.y0;
|
|
25
|
+
const z = k * spacing_z + aabb3.z0;
|
|
26
|
+
|
|
27
|
+
callback(x, y, z);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/core/geom/Bezier.js
CHANGED
|
@@ -1,30 +1,3 @@
|
|
|
1
|
-
import Vector3 from "./Vector3.js";
|
|
2
|
-
|
|
3
|
-
export function Bezier() {
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
Bezier.computeQuadratic = (function () {
|
|
8
|
-
const a = new Vector3();
|
|
9
|
-
|
|
10
|
-
function computeQuadratic(p0, p1, p2, t, result) {
|
|
11
|
-
const minus = 1 - t;
|
|
12
|
-
const minus2 = minus * minus;
|
|
13
|
-
|
|
14
|
-
result.copy(p0).multiplyScalar(minus2);
|
|
15
|
-
|
|
16
|
-
a.copy(p1).multiplyScalar(minus * 2 * t);
|
|
17
|
-
result.add(a);
|
|
18
|
-
|
|
19
|
-
a.copy(p2).multiplyScalar(t * t);
|
|
20
|
-
result.add(a);
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return computeQuadratic;
|
|
25
|
-
})();
|
|
26
|
-
|
|
27
|
-
|
|
28
1
|
/**
|
|
29
2
|
*
|
|
30
3
|
* @param {Vector2} result
|
package/core/geom/Plane.js
CHANGED
|
@@ -40,13 +40,13 @@ export class Subspan {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* DxD square matrix, where D is number of dimensions
|
|
43
|
-
* @type {[]}
|
|
43
|
+
* @type {number[][]}
|
|
44
44
|
*/
|
|
45
45
|
this.Q = null;
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* DxD square matrix, where D is number of dimensions
|
|
49
|
-
* @type {[]}
|
|
49
|
+
* @type {number[][]}
|
|
50
50
|
*/
|
|
51
51
|
this.R = null;
|
|
52
52
|
|
package/core/geom/v3_lerp.js
CHANGED
|
@@ -11,7 +11,12 @@ import { lerp } from "../math/lerp.js";
|
|
|
11
11
|
* @param {number} b_z
|
|
12
12
|
* @param {number} fraction
|
|
13
13
|
*/
|
|
14
|
-
export function v3_lerp(
|
|
14
|
+
export function v3_lerp(
|
|
15
|
+
result,
|
|
16
|
+
a_x, a_y, a_z,
|
|
17
|
+
b_x, b_y, b_z,
|
|
18
|
+
fraction
|
|
19
|
+
) {
|
|
15
20
|
|
|
16
21
|
const x = lerp(a_x, b_x, fraction);
|
|
17
22
|
const y = lerp(a_y, b_y, fraction);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integer square root
|
|
3
|
+
*
|
|
4
|
+
* @author Jim Ulery (attributed on hextreme)
|
|
5
|
+
* @see https://en.wikipedia.org/wiki/Integer_square_root
|
|
6
|
+
* @see https://git.immc.ucl.ac.be/hextreme/hxt_seqdel/-/blob/master/src/hxt_tetrahedra.c#L54
|
|
7
|
+
*
|
|
8
|
+
* @param {number} input
|
|
9
|
+
* @returns {number}
|
|
10
|
+
*/
|
|
11
|
+
export function isqrt(input) {
|
|
12
|
+
let temp;
|
|
13
|
+
|
|
14
|
+
let g = 0;
|
|
15
|
+
let b = 0x8000;
|
|
16
|
+
let bshft = 15;
|
|
17
|
+
|
|
18
|
+
let val = input;
|
|
19
|
+
|
|
20
|
+
do {
|
|
21
|
+
if (val >= (temp = (((g << 1) + b) << bshft--))) {
|
|
22
|
+
g += b;
|
|
23
|
+
val -= temp;
|
|
24
|
+
}
|
|
25
|
+
} while (b >>= 1);
|
|
26
|
+
|
|
27
|
+
return g;
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { max2 } from "./max2.js";
|
|
2
|
+
|
|
3
|
+
test("0,0", () => {
|
|
4
|
+
expect(max2(0, 0)).toBe(0);
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test("0,1", () => {
|
|
8
|
+
expect(max2(0, 1)).toBe(1);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("1,0", () => {
|
|
12
|
+
expect(max2(1, 0)).toBe(1);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("-1,0", () => {
|
|
16
|
+
expect(max2(-1, 0)).toBe(0);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("0,-1", () => {
|
|
20
|
+
expect(max2(0, -1)).toBe(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("Infinity,-Infinity", () => {
|
|
24
|
+
expect(max2(Infinity, -Infinity)).toBe(Infinity);
|
|
25
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { min2 } from "./min2.js";
|
|
2
|
+
|
|
3
|
+
test("0,0", () => {
|
|
4
|
+
expect(min2(0, 0)).toBe(0);
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
test("0,1", () => {
|
|
8
|
+
expect(min2(0, 1)).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("1,0", () => {
|
|
12
|
+
expect(min2(1, 0)).toBe(0);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("-1,0", () => {
|
|
16
|
+
expect(min2(-1, 0)).toBe(-1);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("0,-1", () => {
|
|
20
|
+
expect(min2(0, -1)).toBe(-1);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("Infinity,-Infinity", () => {
|
|
24
|
+
expect(min2(Infinity, -Infinity)).toBe(-Infinity);
|
|
25
|
+
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { assert } from "../../../assert.js";
|
|
2
|
-
import { isArrayEqual } from "../../../collection/ArrayUtils.js";
|
|
3
2
|
import List from "../../../collection/list/List.js";
|
|
4
3
|
import { NodeInstancePortReference } from "./NodeInstancePortReference.js";
|
|
5
4
|
import { PortDirection } from "./PortDirection.js";
|
|
5
|
+
import { isArrayEqual } from "../../../collection/array/isArrayEqual.js";
|
|
6
6
|
|
|
7
7
|
export class NodeInstance {
|
|
8
8
|
constructor() {
|
|
@@ -27,14 +27,14 @@ export class NodeInstance {
|
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Internal instance data
|
|
30
|
-
* @type {
|
|
30
|
+
* @type {Array}
|
|
31
31
|
*/
|
|
32
32
|
this.parameters = [];
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* @transient
|
|
37
|
-
* @type {
|
|
37
|
+
* @type {Array}
|
|
38
38
|
*/
|
|
39
39
|
this.outputsValues = [];
|
|
40
40
|
|