@woosh/meep-engine 2.42.7 → 2.43.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/core/binary/BitSet.js +4 -4
- package/core/binary/ctz32.js +40 -0
- package/core/collection/ObservedMap.js +61 -57
- package/core/collection/heap/FastBinaryHeap.js +7 -1
- package/core/collection/heap/Uint32Heap.js +19 -0
- package/core/collection/map/AsyncLoadingCache.js +3 -1
- package/core/geom/2d/compute_polygon_area_2d.js +32 -0
- package/core/geom/2d/compute_polygon_area_2d.spec.js +10 -0
- package/core/geom/2d/compute_triangle_area_2d.js +15 -0
- package/core/geom/2d/compute_triangle_area_2d.spec.js +9 -0
- package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.js +64 -0
- package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.spec.js +33 -0
- package/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +82 -0
- package/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +135 -0
- package/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +282 -0
- package/core/geom/2d/convex-hull/orientation3.js +444 -0
- package/core/geom/2d/convex-hull/orientation3_array.js +22 -0
- package/core/geom/2d/convex-hull/orientation3_v2.js +12 -0
- package/core/geom/2d/intersect_ray_2d.js +56 -0
- package/core/geom/2d/quad-tree/QuadTreeNode.js +0 -81
- package/core/geom/2d/quad-tree/qt_match_data_by_circle.js +70 -0
- package/core/geom/3d/matrix/m4_multiply_alphatensor.js +131 -0
- package/core/geom/3d/plane/orient3d_fast.js +2 -6
- package/core/geom/3d/tetrahedra/README.md +7 -0
- package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +3 -1
- package/core/geom/3d/tetrahedra/delaunay/Cavity.js +48 -0
- package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.js → delaunay/compute_delaunay_tetrahedral_mesh.js} +15 -7
- package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.spec.js → delaunay/compute_delaunay_tetrahedral_mesh.spec.js} +0 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +73 -0
- package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_toward_cavity.js +48 -0
- package/core/geom/3d/tetrahedra/hxt/a.js +524 -0
- package/core/geom/3d/tetrahedra/hxt/hxt.js +140 -0
- package/core/geom/3d/tetrahedra/hxt/hxt.wasm +0 -0
- package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +35 -20
- package/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +98 -0
- package/core/geom/3d/tetrahedra/tetrahedra_collection.js +60 -131
- package/core/geom/packing/{MaxRectangles.js → max-rect/MaxRectangles.js} +28 -124
- package/core/geom/packing/max-rect/removeRedundantBoxes.js +69 -0
- package/core/geom/packing/max-rect/removeRedundantBoxesArray.js +40 -0
- package/core/geom/v3_distance_above_plane.js +1 -1
- package/core/graph/layout/BoxLayouter.js +2 -88
- package/core/graph/layout/CircleLayout.js +2 -1
- package/core/graph/layout/box/forceIntoBox.js +45 -0
- package/core/graph/layout/box/pullBoxTowardsPoint.js +20 -0
- package/core/graph/layout/box/resolveAABB2Overlap.js +22 -0
- package/core/math/bessel_3.js +11 -0
- package/core/math/bessel_i0.js +26 -0
- package/core/process/executor/ConcurrentExecutor.spec.js +2 -1
- package/core/process/task/util/actionTask.js +19 -0
- package/core/process/task/util/countTask.js +62 -0
- package/core/process/task/util/delayTask.js +45 -0
- package/core/process/task/util/emptyTask.js +19 -0
- package/core/process/task/util/failingTask.js +17 -0
- package/core/process/task/util/futureTask.js +48 -0
- package/core/process/task/util/promiseTask.js +42 -0
- package/core/process/task/util/randomCountTask.js +64 -0
- package/core/process/task/util/wrapTaskIgnoreFailure.js +47 -0
- package/engine/Engine.js +8 -8
- package/engine/EngineBootstrapper.js +1 -1
- package/engine/asset/AssetManager.js +197 -53
- package/engine/asset/AssetRequest.js +32 -0
- package/engine/asset/loaders/ArrayBufferLoader.js +62 -50
- package/engine/asset/loaders/image/png/PNG.js +15 -1
- package/engine/asset/loaders/image/png/PNGReader.js +3 -2
- package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -1
- package/engine/ecs/storage/BinaryBufferDeSerializer.js +1 -1
- package/engine/ecs/storage/JSONDeSerializer.js +2 -1
- package/engine/ecs/terrain/ecs/splat/SplatMapOptimizer.js +2 -1
- package/engine/ecs/terrain/ecs/splat/SplatMapping.js +1 -1
- package/engine/graphics/camera/makeScreenScissorFrustum.js +1 -1
- package/engine/graphics/camera/testClippingPlaneComputation.js +4 -45
- package/engine/graphics/ecs/camera/FrustumProjector.js +6 -0
- package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +5 -0
- package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +23 -4
- package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +1 -1
- package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +11 -0
- package/engine/graphics/geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js +1 -2
- package/engine/graphics/impostors/octahedral/ImpostorBaker.js +5 -2
- package/engine/graphics/impostors/octahedral/ImpostorDescription.js +18 -0
- package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +15 -0
- package/engine/graphics/impostors/octahedral/prototypeBaker.js +66 -79
- package/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js +134 -0
- package/engine/graphics/impostors/octahedral/util/build_cutout_from_atlas_by_alpha.js +128 -0
- package/engine/graphics/impostors/octahedral/util/build_geometry_from_cutout_shape.js +32 -0
- package/engine/graphics/impostors/octahedral/util/load_mesh_for_bake.js +31 -0
- package/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.js +107 -0
- package/engine/graphics/material/manager/ManagedMaterial.js +4 -0
- package/engine/graphics/material/manager/MaterialManager.js +1 -0
- package/engine/graphics/material/optimization/MaterialOptimizationContext.js +7 -3
- package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +2 -2
- package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +0 -19
- package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +83 -27
- package/engine/graphics/shadows/ShadowMapRenderer.js +11 -4
- package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +2 -1
- package/engine/graphics/texture/atlas/CachingTextureAtlas.js +208 -38
- package/engine/graphics/texture/atlas/TextureAtlas.js +31 -24
- package/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +1 -1
- package/engine/graphics/texture/sampler/filter/box.js +16 -0
- package/engine/graphics/texture/sampler/filter/cubic2.js +32 -0
- package/engine/graphics/texture/sampler/filter/gaussian.js +16 -0
- package/engine/graphics/texture/sampler/filter/kaiser_1.js +19 -0
- package/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +19 -0
- package/engine/graphics/texture/sampler/filter/mitchell.js +55 -0
- package/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.js +109 -0
- package/engine/graphics/texture/sampler/filter/triangle.js +19 -0
- package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +187 -86
- package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +77 -25
- package/engine/graphics/texture/sampler/search/make_edge_condition_channel_threshold.js +34 -0
- package/engine/graphics/texture/sampler/search/sampler2d_find_pixels.js +24 -0
- package/engine/graphics/texture/sprite/prototypeSpriteCutoutGeometry.js +212 -0
- package/engine/knowledge/database/StaticKnowledgeDataTable.js +1 -1
- package/engine/navigation/grid/AStar.js +1 -1
- package/engine/plugin/EnginePluginManager.js +28 -27
- package/engine/plugin/PluginReferenceContext.js +9 -0
- package/engine/scene/Scene.js +1 -1
- package/engine/scene/SerializedScene.js +1 -1
- package/engine/scene/transitionToScene.js +3 -1
- package/generation/example/main.js +1 -1
- package/generation/grid/generation/GridTaskApplyActionToCells.js +1 -1
- package/generation/grid/generation/GridTaskDensityMarkerDistribution.js +1 -1
- package/generation/grid/generation/GridTaskExecuteRuleTimes.js +1 -1
- package/generation/grid/generation/NoopGridTaskGenerator.js +1 -1
- package/generation/grid/generation/discrete/GridTaskCellularAutomata.js +2 -1
- package/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
- package/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +3 -2
- package/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +1 -1
- package/generation/grid/generation/grid/GridTaskAddNodesFixed.js +1 -1
- package/generation/grid/generation/road/GridTaskGenerateRoads.js +3 -2
- package/generation/grid/generation/util/buildDistanceMapToObjective.js +1 -1
- package/generation/markers/GridActionRuleSet.js +2 -1
- package/generation/placement/GridCellActionTransformNearbyMarkers.js +2 -4
- package/generation/theme/ThemeEngine.js +4 -1
- package/package.json +1 -1
- package/view/asset/AssetLoaderStatusView.js +5 -5
- package/view/minimap/gl/MinimapTerrainGL.js +1 -2
- package/view/renderModel.js +1 -1
- package/view/tooltip/TooltipView.js +5 -5
- package/core/process/task/TaskUtils.js +0 -352
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import hxt_wasm from "./hxt.wasm";
|
|
2
|
+
import { min2 } from "../../../../math/min2.js";
|
|
3
|
+
import { max2 } from "../../../../math/max2.js";
|
|
4
|
+
|
|
5
|
+
var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
|
|
6
|
+
|
|
7
|
+
function updateGlobalBufferAndViews(buf) {
|
|
8
|
+
buffer = buf;
|
|
9
|
+
HEAP8 = new Int8Array(buf);
|
|
10
|
+
HEAP16 = new Int16Array(buf);
|
|
11
|
+
HEAP32 = new Int32Array(buf);
|
|
12
|
+
HEAPU8 = new Uint8Array(buf);
|
|
13
|
+
HEAPU16 = new Uint16Array(buf);
|
|
14
|
+
HEAPU32 = new Uint32Array(buf);
|
|
15
|
+
HEAPF32 = new Float32Array(buf);
|
|
16
|
+
HEAPF64 = new Float64Array(buf)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let instance;
|
|
20
|
+
|
|
21
|
+
function emscripten_realloc_buffer(size) {
|
|
22
|
+
try {
|
|
23
|
+
wasmMemory.grow(size - buffer.byteLength + 65535 >>> 16);
|
|
24
|
+
updateGlobalBufferAndViews(wasmMemory.buffer);
|
|
25
|
+
return 1
|
|
26
|
+
} catch (e) {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function _emscripten_resize_heap(requestedSize) {
|
|
31
|
+
var oldSize = HEAPU8.length;
|
|
32
|
+
requestedSize = requestedSize >>> 0;
|
|
33
|
+
var maxHeapSize = getHeapMax();
|
|
34
|
+
if (requestedSize > maxHeapSize) {
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
let alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
|
|
38
|
+
for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
|
|
39
|
+
var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
|
|
40
|
+
overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
|
|
41
|
+
var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
|
|
42
|
+
var replacement = emscripten_realloc_buffer(newSize);
|
|
43
|
+
if (replacement) {
|
|
44
|
+
return true
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function _emscripten_memcpy_big(dest, src, num) {
|
|
51
|
+
HEAPU8.copyWithin(dest, src, src + num)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function _fd_close(fd) {
|
|
55
|
+
return 52
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
|
|
59
|
+
return 70
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function _fd_write(fd, iov, iovcnt, pnum) {
|
|
63
|
+
var num = 0;
|
|
64
|
+
for (var i = 0; i < iovcnt; i++) {
|
|
65
|
+
var ptr = HEAPU32[iov >> 2];
|
|
66
|
+
var len = HEAPU32[iov + 4 >> 2];
|
|
67
|
+
iov += 8;
|
|
68
|
+
for (var j = 0; j < len; j++) {
|
|
69
|
+
printChar(fd, HEAPU8[ptr + j])
|
|
70
|
+
}
|
|
71
|
+
num += len
|
|
72
|
+
}
|
|
73
|
+
HEAPU32[pnum >> 2] = num;
|
|
74
|
+
return 0
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
var asmLibraryArg = {
|
|
78
|
+
"e": _emscripten_memcpy_big,
|
|
79
|
+
"b": _emscripten_resize_heap,
|
|
80
|
+
"d": _fd_close,
|
|
81
|
+
"a": _fd_seek,
|
|
82
|
+
"c": _fd_write
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
*
|
|
87
|
+
* @param {number[]} _points
|
|
88
|
+
* @param {number} n
|
|
89
|
+
* @return {Promise<void>}
|
|
90
|
+
*/
|
|
91
|
+
export async function hxt(_points, n) {
|
|
92
|
+
|
|
93
|
+
if (instance === undefined) {
|
|
94
|
+
var info = { "a": asmLibraryArg };
|
|
95
|
+
|
|
96
|
+
updateGlobalBufferAndViews(new ArrayBuffer(4 * 1024 * 1024));
|
|
97
|
+
|
|
98
|
+
const response = await fetch(hxt_wasm);
|
|
99
|
+
const bytes = await response.arrayBuffer();
|
|
100
|
+
|
|
101
|
+
const module = await WebAssembly.instantiate(bytes, info);
|
|
102
|
+
|
|
103
|
+
instance = module.instance;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
|
|
108
|
+
double* points, // x0, y0, z0, x1,y1,z1, ...
|
|
109
|
+
uint32_t point_count, // number of points in the input buffer
|
|
110
|
+
double* bbox, //6 floats: min_x, min_y, min_z, max_x, max_y, max_z
|
|
111
|
+
LinkedTetrahedron* output
|
|
112
|
+
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
const points = new Float64Array(_points);
|
|
116
|
+
|
|
117
|
+
const bbox = new Float64Array(6);
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < n; i++) {
|
|
120
|
+
|
|
121
|
+
const x = points[i * 3];
|
|
122
|
+
const y = points[i * 3 + 1];
|
|
123
|
+
const z = points[i * 3 + 2];
|
|
124
|
+
|
|
125
|
+
bbox[0] = min2(x, bbox[0]);
|
|
126
|
+
bbox[1] = min2(y, bbox[1]);
|
|
127
|
+
bbox[2] = min2(z, bbox[2]);
|
|
128
|
+
|
|
129
|
+
bbox[3] = max2(x, bbox[3]);
|
|
130
|
+
bbox[4] = max2(y, bbox[4]);
|
|
131
|
+
bbox[5] = max2(z, bbox[5]);
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const output_tets = new Uint8Array(10 * 1024 * 1024);
|
|
136
|
+
|
|
137
|
+
const out_tet_count = instance.exports["h"](points, n, bbox, output_tets);
|
|
138
|
+
|
|
139
|
+
console.log(out_tet_count);
|
|
140
|
+
}
|
|
Binary file
|
|
@@ -16,38 +16,52 @@
|
|
|
16
16
|
* @param {number} b tetrahedral point index
|
|
17
17
|
* @param {number} c tetrahedral point index
|
|
18
18
|
* @param {number} d tetrahedral point index
|
|
19
|
-
* @param {number} e reference point index
|
|
19
|
+
* @param {number} e reference point index that we are testing against the tetrahedron
|
|
20
20
|
* @returns {number}
|
|
21
21
|
*/
|
|
22
|
-
export function point_in_tetrahedron_circumsphere(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
22
|
+
export function point_in_tetrahedron_circumsphere(
|
|
23
|
+
points,
|
|
24
|
+
a, b, c, d, e
|
|
25
|
+
) {
|
|
26
|
+
|
|
27
|
+
const a3 = a * 3;
|
|
28
|
+
const b3 = b * 3;
|
|
29
|
+
const c3 = c * 3;
|
|
30
|
+
const d3 = d * 3;
|
|
31
|
+
const e3 = e * 3;
|
|
32
|
+
|
|
33
|
+
const ex = points[e3];
|
|
34
|
+
const ey = points[e3 + 1];
|
|
35
|
+
const ez = points[e3 + 2];
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const aex = points[a3] - ex;
|
|
39
|
+
const bex = points[b3] - ex;
|
|
40
|
+
const cex = points[c3] - ex;
|
|
41
|
+
const dex = points[d3] - ex;
|
|
42
|
+
|
|
43
|
+
const aey = points[a3 + 1] - ey;
|
|
44
|
+
const bey = points[b3 + 1] - ey;
|
|
45
|
+
const cey = points[c3 + 1] - ey;
|
|
46
|
+
const dey = points[d3 + 1] - ey;
|
|
47
|
+
|
|
48
|
+
const aez = points[a3 + 2] - ez;
|
|
49
|
+
const bez = points[b3 + 2] - ez;
|
|
50
|
+
const cez = points[c3 + 2] - ez;
|
|
51
|
+
const dez = points[d3 + 2] - ez;
|
|
41
52
|
|
|
42
53
|
const aexbey = aex * bey;
|
|
43
54
|
const bexaey = bex * aey;
|
|
44
55
|
const ab = aexbey - bexaey;
|
|
56
|
+
|
|
45
57
|
const bexcey = bex * cey;
|
|
46
58
|
const cexbey = cex * bey;
|
|
47
59
|
const bc = bexcey - cexbey;
|
|
60
|
+
|
|
48
61
|
const cexdey = cex * dey;
|
|
49
62
|
const dexcey = dex * cey;
|
|
50
63
|
const cd = cexdey - dexcey;
|
|
64
|
+
|
|
51
65
|
const dexaey = dex * aey;
|
|
52
66
|
const aexdey = aex * dey;
|
|
53
67
|
const da = dexaey - aexdey;
|
|
@@ -55,6 +69,7 @@ export function point_in_tetrahedron_circumsphere(points, a, b, c, d, e) {
|
|
|
55
69
|
const aexcey = aex * cey;
|
|
56
70
|
const cexaey = cex * aey;
|
|
57
71
|
const ac = aexcey - cexaey;
|
|
72
|
+
|
|
58
73
|
const bexdey = bex * dey;
|
|
59
74
|
const dexbey = dex * bey;
|
|
60
75
|
const bd = bexdey - dexbey;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../../engine/EngineHarness.js";
|
|
2
|
+
import { compute_delaunay_tetrahedral_mesh } from "./delaunay/compute_delaunay_tetrahedral_mesh.js";
|
|
3
|
+
import { LineBasicMaterial, Uint32BufferAttribute } from "three";
|
|
4
|
+
import { BufferGeometry } from "three/src/core/BufferGeometry.js";
|
|
5
|
+
import { Float32BufferAttribute } from "three/src/core/BufferAttribute.js";
|
|
6
|
+
import { ShadedGeometry } from "../../../../engine/graphics/ecs/mesh-v2/ShadedGeometry.js";
|
|
7
|
+
import { DrawMode } from "../../../../engine/graphics/ecs/mesh-v2/DrawMode.js";
|
|
8
|
+
import EntityBuilder from "../../../../engine/ecs/EntityBuilder.js";
|
|
9
|
+
import { Transform } from "../../../../engine/ecs/transform/Transform.js";
|
|
10
|
+
import { ShadedGeometrySystem } from "../../../../engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js";
|
|
11
|
+
import { GizmoRenderingPlugin } from "../../../../engine/graphics/render/gizmo/GizmoRenderingPlugin.js";
|
|
12
|
+
import { Gizmo } from "../../../../engine/graphics/render/gizmo/Gizmo.js";
|
|
13
|
+
import { LAYOUT_TETRA_BYTE_SIZE } from "./tetrahedra_collection.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {Engine} engine
|
|
18
|
+
* @return {Promise<void>}
|
|
19
|
+
*/
|
|
20
|
+
async function main(engine) {
|
|
21
|
+
await EngineHarness.buildBasics({
|
|
22
|
+
engine,
|
|
23
|
+
enableWater: false
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const offset = [7.5, 1, 7.5];
|
|
27
|
+
const scale = [.5, .5, .5];
|
|
28
|
+
|
|
29
|
+
const points = [
|
|
30
|
+
0, 0, 0,
|
|
31
|
+
10, 0, 0,
|
|
32
|
+
10, 0, 10,
|
|
33
|
+
0, 0, 10,
|
|
34
|
+
|
|
35
|
+
0, 10, 0,
|
|
36
|
+
10, 10, 0,
|
|
37
|
+
10, 10, 10,
|
|
38
|
+
0, 10, 10,
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const tetrahedra = compute_delaunay_tetrahedral_mesh(points, points.length / 3);
|
|
42
|
+
|
|
43
|
+
const lines = [];
|
|
44
|
+
|
|
45
|
+
for (let i = tetrahedra.__occupancy.nextSetBit(0); i !== -1; i = tetrahedra.__occupancy.nextSetBit(i + 1)) {
|
|
46
|
+
|
|
47
|
+
const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
|
|
48
|
+
|
|
49
|
+
const a = tetrahedra.__view.getUint32(tet_address);
|
|
50
|
+
const b = tetrahedra.__view.getUint32(tet_address + 4);
|
|
51
|
+
const c = tetrahedra.__view.getUint32(tet_address + 8);
|
|
52
|
+
const d = tetrahedra.__view.getUint32(tet_address + 12);
|
|
53
|
+
|
|
54
|
+
lines.push(a, b);
|
|
55
|
+
lines.push(a, c);
|
|
56
|
+
lines.push(a, d);
|
|
57
|
+
|
|
58
|
+
lines.push(b, c);
|
|
59
|
+
lines.push(c, d);
|
|
60
|
+
lines.push(b, d);
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const geometry = new BufferGeometry();
|
|
65
|
+
|
|
66
|
+
geometry.setIndex(new Uint32BufferAttribute(lines, 1, false));
|
|
67
|
+
geometry.setAttribute('position', new Float32BufferAttribute(points, 3, false));
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
new EntityBuilder()
|
|
71
|
+
.add(ShadedGeometry.from(geometry, new LineBasicMaterial({ color: 0xFF0000 }), DrawMode.LineSegments))
|
|
72
|
+
.add(Transform.fromJSON({
|
|
73
|
+
position: { x: offset[0], y: offset[1], z: offset[2] },
|
|
74
|
+
scale: { x: scale[0], y: scale[1], z: scale[2] },
|
|
75
|
+
}))
|
|
76
|
+
.build(engine.entityManager.dataset);
|
|
77
|
+
|
|
78
|
+
engine.graphics.on.preRender.add(() => {
|
|
79
|
+
|
|
80
|
+
Gizmo.color = [1, 1, 1, 1];
|
|
81
|
+
|
|
82
|
+
for (let i = 0; i < points.length; i += 3) {
|
|
83
|
+
|
|
84
|
+
Gizmo.draw_solid_sphere([
|
|
85
|
+
points[i] * scale[0] + offset[0],
|
|
86
|
+
points[i + 1] * scale[1] + offset[1],
|
|
87
|
+
points[i + 2] * scale[2] + offset[2]
|
|
88
|
+
], 0.1);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
new EngineHarness().initialize({
|
|
94
|
+
configuration(config, engine) {
|
|
95
|
+
config.addSystem(new ShadedGeometrySystem(engine));
|
|
96
|
+
config.addPlugin(GizmoRenderingPlugin);
|
|
97
|
+
}
|
|
98
|
+
}).then(main);
|
|
@@ -1,83 +1,44 @@
|
|
|
1
1
|
import { tetrahedron_contains_point } from "./tetrahedron_contains_point.js";
|
|
2
2
|
import { assert } from "../../../assert.js";
|
|
3
|
-
import { point_in_tetrahedron_circumsphere } from "./point_in_tetrahedron_circumsphere.js";
|
|
4
3
|
import { BitSet } from "../../../binary/BitSet.js";
|
|
5
4
|
import { typed_array_copy } from "../../../collection/array/typed/typed_array_copy.js";
|
|
6
5
|
import { max3 } from "../../../math/max3.js";
|
|
6
|
+
import { Cavity } from "./delaunay/Cavity.js";
|
|
7
|
+
import { tetrahedral_mesh_compute_cavity } from "./delaunay/tetrahedral_mesh_compute_cavity.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
10
|
+
* Size in bytes of a single tetrahedron record
|
|
9
11
|
* @readonly
|
|
10
12
|
* @type {number}
|
|
11
13
|
*/
|
|
12
|
-
const LAYOUT_TETRA_BYTE_SIZE = 9 * 4;
|
|
14
|
+
export const LAYOUT_TETRA_BYTE_SIZE = 9 * 4;
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
17
|
* @readonly
|
|
16
18
|
* @type {number}
|
|
17
19
|
*/
|
|
18
|
-
const INVALID_NEIGHBOUR = 0xFFFFFFFF;
|
|
19
|
-
|
|
20
|
-
class Cavity {
|
|
21
|
-
constructor() {
|
|
22
|
-
this.indices = [];
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* @type {number}
|
|
27
|
-
*/
|
|
28
|
-
this.size = 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
update() {
|
|
32
|
-
// compute in/out state for each side of each tetra
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
37
|
-
* @param {number} i
|
|
38
|
-
*/
|
|
39
|
-
push(i) {
|
|
40
|
-
this.indices[this.size++] = i;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
*
|
|
45
|
-
* @param {number} i
|
|
46
|
-
* @returns {boolean}
|
|
47
|
-
*/
|
|
48
|
-
includes(i) {
|
|
49
|
-
const n = this.size;
|
|
50
|
-
for (let j = 0; j < n; j++) {
|
|
51
|
-
if (this.indices[j] === i) {
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
reset() {
|
|
60
|
-
this.size = 0;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
20
|
+
export const INVALID_NEIGHBOUR = 0xFFFFFFFF;
|
|
63
21
|
|
|
64
22
|
const SCRATCH_CAVITY = new Cavity();
|
|
65
23
|
|
|
66
24
|
/**
|
|
67
|
-
*
|
|
25
|
+
* Only keeps track of tetrahedra, actual point coordinates are stored outside. For most useful operations point coordinates are passed in
|
|
68
26
|
* Layout:
|
|
69
|
-
* vertex_id_a ::
|
|
70
|
-
* vertex_id_b ::
|
|
71
|
-
* vertex_id_c ::
|
|
72
|
-
* vertex_id_d ::
|
|
73
|
-
* neighbour_a ::
|
|
74
|
-
* neighbour_b ::
|
|
75
|
-
* neighbour_c ::
|
|
76
|
-
* neighbour_d ::
|
|
27
|
+
* vertex_id_a :: uint32
|
|
28
|
+
* vertex_id_b :: uint32
|
|
29
|
+
* vertex_id_c :: uint32
|
|
30
|
+
* vertex_id_d :: uint32
|
|
31
|
+
* neighbour_a :: uint32 - neighbour tetrahedron, opposite to vertex A
|
|
32
|
+
* neighbour_b :: uint32 - neighbour tetrahedron, opposite to vertex B
|
|
33
|
+
* neighbour_c :: uint32 - neighbour tetrahedron, opposite to vertex C
|
|
34
|
+
* neighbour_d :: uint32 - neighbour tetrahedron, opposite to vertex D
|
|
77
35
|
* sub_determinant :: float - ?
|
|
78
36
|
* Layout is similar to [1], but is interleaved for better cache locality
|
|
37
|
+
*
|
|
38
|
+
* @see [1] 2018 "One machine, one minute, three billion tetrahedra" by Célestin Marot, Jeanne Pellerin and Jean-François Remacle
|
|
39
|
+
* @see https://git.immc.ucl.ac.be/hextreme/hxt_seqdel (C source code for [1])
|
|
79
40
|
*/
|
|
80
|
-
export class
|
|
41
|
+
export class TetrahedralMesh {
|
|
81
42
|
constructor(initial_size) {
|
|
82
43
|
this.__buffer = new ArrayBuffer(initial_size * LAYOUT_TETRA_BYTE_SIZE);
|
|
83
44
|
|
|
@@ -160,6 +121,24 @@ export class TetrahedraCollection {
|
|
|
160
121
|
return this.__view.setUint32(tetra_address + (4 + neighbour_index) * 4, neighbour);
|
|
161
122
|
}
|
|
162
123
|
|
|
124
|
+
validateLength() {
|
|
125
|
+
return this.countOccupancy() === this.__length;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Counts number of occupied(used) elements in the pool
|
|
130
|
+
* Should be the same as __length
|
|
131
|
+
* @return {number}
|
|
132
|
+
*/
|
|
133
|
+
countOccupancy() {
|
|
134
|
+
let r = 0;
|
|
135
|
+
for (let i = this.__occupancy.nextSetBit(0); i !== -1; i = this.__occupancy.nextSetBit(i + 1)) {
|
|
136
|
+
r++;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return r;
|
|
140
|
+
}
|
|
141
|
+
|
|
163
142
|
/**
|
|
164
143
|
*
|
|
165
144
|
* @param {number[]|Float32Array} points
|
|
@@ -191,10 +170,14 @@ export class TetrahedraCollection {
|
|
|
191
170
|
view.setUint32(address + 24, INVALID_NEIGHBOUR);
|
|
192
171
|
view.setUint32(address + 28, INVALID_NEIGHBOUR);
|
|
193
172
|
|
|
173
|
+
//assert(this.validateLength());
|
|
174
|
+
|
|
194
175
|
this.__occupancy.set(tetra_index, true);
|
|
195
176
|
|
|
196
177
|
this.__length++;
|
|
197
178
|
|
|
179
|
+
// assert(this.validateLength());
|
|
180
|
+
|
|
198
181
|
return tetra_index;
|
|
199
182
|
}
|
|
200
183
|
|
|
@@ -221,9 +204,13 @@ export class TetrahedraCollection {
|
|
|
221
204
|
this.setNeighbour(neighbour_index, neighbour_point, INVALID_NEIGHBOUR);
|
|
222
205
|
}
|
|
223
206
|
|
|
207
|
+
//assert(this.validateLength());
|
|
208
|
+
|
|
224
209
|
// mark as dead
|
|
225
210
|
this.__occupancy.clear(tera_index);
|
|
226
211
|
this.__length--;
|
|
212
|
+
|
|
213
|
+
//assert(this.validateLength());
|
|
227
214
|
}
|
|
228
215
|
|
|
229
216
|
/**
|
|
@@ -236,16 +223,15 @@ export class TetrahedraCollection {
|
|
|
236
223
|
removeTetrasConnectedToPoints(points, range_start, range_end) {
|
|
237
224
|
const data_view = this.__view;
|
|
238
225
|
|
|
239
|
-
let i = 0;
|
|
240
226
|
let j = 0;
|
|
241
227
|
|
|
242
228
|
const occupancy = this.__occupancy;
|
|
243
|
-
for (i = occupancy.nextSetBit(0); i !== -1; i = occupancy.nextSetBit(i + 1)) {
|
|
229
|
+
for (let i = occupancy.nextSetBit(0); i !== -1; i = occupancy.nextSetBit(i + 1)) {
|
|
244
230
|
|
|
245
231
|
const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
|
|
246
232
|
|
|
247
233
|
for (j = 0; j < 4; j++) {
|
|
248
|
-
const point_index = data_view.getUint32(tet_address + 4 *
|
|
234
|
+
const point_index = data_view.getUint32(tet_address + 4 * j);
|
|
249
235
|
|
|
250
236
|
if (point_index >= range_start && point_index <= range_end) {
|
|
251
237
|
// point index is in range, tetra should be removed
|
|
@@ -286,94 +272,34 @@ export class TetrahedraCollection {
|
|
|
286
272
|
|
|
287
273
|
/**
|
|
288
274
|
*
|
|
289
|
-
* @param {
|
|
290
|
-
* @param {number
|
|
291
|
-
* @
|
|
275
|
+
* @param {number} tet_index
|
|
276
|
+
* @param {number} point_index should be an integer between 0 and 3
|
|
277
|
+
* @returns {number}
|
|
292
278
|
*/
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
// 1.identify tetrahedron that contains this point
|
|
296
|
-
const containing_tetra = this.findTetraContainingPoint(points, index);
|
|
297
|
-
|
|
298
|
-
assert.isNonNegativeInteger(containing_tetra, 'containing_tetra');
|
|
299
|
-
|
|
300
|
-
cavity.reset();
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
*
|
|
304
|
-
* @type {number[]}
|
|
305
|
-
*/
|
|
306
|
-
const open_set = [
|
|
307
|
-
containing_tetra
|
|
308
|
-
];
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
*
|
|
312
|
-
* @type {number[]}
|
|
313
|
-
*/
|
|
314
|
-
const closed_set = [];
|
|
315
|
-
|
|
316
|
-
const data_view = this.__view;
|
|
317
|
-
|
|
318
|
-
// 2. find the Delaunay "cavity", a set of tetrahedrons who's circumsphere overlarlaps the point
|
|
319
|
-
// perform breadth-first expansion on the containing tetra to identify the cavity
|
|
320
|
-
while (open_set.length > 0) {
|
|
321
|
-
const tetra = open_set.pop();
|
|
322
|
-
cavity.push(tetra);
|
|
323
|
-
closed_set.push(tetra);
|
|
324
|
-
|
|
325
|
-
// get neighbours
|
|
326
|
-
for (let i = 0; i < 4; i++) {
|
|
327
|
-
const neighbour_encoded = this.getNeighbour(tetra, i);
|
|
328
|
-
const neighbour_tetra_index = neighbour_encoded >> 2;
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
(neighbour_encoded === INVALID_NEIGHBOUR) // no neighbour
|
|
332
|
-
|| closed_set.includes(neighbour_tetra_index) // already visited
|
|
333
|
-
|| open_set.includes(neighbour_tetra_index) // already in open set
|
|
334
|
-
) {
|
|
335
|
-
|
|
336
|
-
continue;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const neighbour_address = neighbour_tetra_index * LAYOUT_TETRA_BYTE_SIZE;
|
|
340
|
-
|
|
341
|
-
const a = data_view.getUint32(neighbour_address);
|
|
342
|
-
const b = data_view.getUint32(neighbour_address + 4);
|
|
343
|
-
const c = data_view.getUint32(neighbour_address + 8);
|
|
344
|
-
const d = data_view.getUint32(neighbour_address + 12);
|
|
345
|
-
|
|
346
|
-
// check neighbour
|
|
347
|
-
const is_in_sphere = point_in_tetrahedron_circumsphere(points, a, b, c, d, index);
|
|
348
|
-
|
|
349
|
-
if (is_in_sphere) {
|
|
350
|
-
open_set.push(neighbour_tetra_index);
|
|
351
|
-
} else {
|
|
352
|
-
// move directly to closed set
|
|
353
|
-
closed_set.push(neighbour_tetra_index);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
358
|
-
}
|
|
279
|
+
getCornerIndex(tet_index, point_index) {
|
|
280
|
+
return this.__view.getUint32(tet_index * LAYOUT_TETRA_BYTE_SIZE + point_index * 4);
|
|
359
281
|
}
|
|
360
282
|
|
|
283
|
+
|
|
361
284
|
/**
|
|
362
285
|
*
|
|
363
286
|
* @param {number[]|Float32Array} points
|
|
364
287
|
* @param {number} index
|
|
365
288
|
*/
|
|
366
289
|
insertPoint(points, index) {
|
|
290
|
+
const debug_length_initial = this.__length;
|
|
291
|
+
|
|
367
292
|
// Compute the cavity, that is the set of tetrahedra that need to be removed and rebuilt
|
|
368
|
-
this
|
|
293
|
+
tetrahedral_mesh_compute_cavity(this, SCRATCH_CAVITY, points, index);
|
|
369
294
|
|
|
370
295
|
|
|
371
296
|
// identify cavity "edge" - the set of tetras that are neighbours of the tetras that form the cavity
|
|
372
297
|
const cavity_size = SCRATCH_CAVITY.size;
|
|
373
298
|
const cavity_indices = SCRATCH_CAVITY.indices;
|
|
374
|
-
const data = this.__view;
|
|
375
299
|
|
|
376
300
|
for (let i = 0; i < cavity_size; i++) {
|
|
301
|
+
const data = this.__view;
|
|
302
|
+
|
|
377
303
|
const cavity_index = cavity_indices[i];
|
|
378
304
|
|
|
379
305
|
// take each side of the tetra
|
|
@@ -440,7 +366,10 @@ export class TetrahedraCollection {
|
|
|
440
366
|
|
|
441
367
|
// clear out cavity, connectivity was already patched in the previous step
|
|
442
368
|
this.__occupancy.set(cavity_index, false);
|
|
369
|
+
this.__length--;
|
|
443
370
|
}
|
|
371
|
+
|
|
372
|
+
assert.greaterThan(this.__length, debug_length_initial, 'after insertion number of tetrahedra must grow, not shrink')
|
|
444
373
|
}
|
|
445
374
|
|
|
446
375
|
/**
|