@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.
Files changed (139) hide show
  1. package/core/binary/BitSet.js +4 -4
  2. package/core/binary/ctz32.js +40 -0
  3. package/core/collection/ObservedMap.js +61 -57
  4. package/core/collection/heap/FastBinaryHeap.js +7 -1
  5. package/core/collection/heap/Uint32Heap.js +19 -0
  6. package/core/collection/map/AsyncLoadingCache.js +3 -1
  7. package/core/geom/2d/compute_polygon_area_2d.js +32 -0
  8. package/core/geom/2d/compute_polygon_area_2d.spec.js +10 -0
  9. package/core/geom/2d/compute_triangle_area_2d.js +15 -0
  10. package/core/geom/2d/compute_triangle_area_2d.spec.js +9 -0
  11. package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.js +64 -0
  12. package/core/geom/2d/convex-hull/convex_hull_jarvis_2d.spec.js +33 -0
  13. package/core/geom/2d/convex-hull/convex_hull_monotone_2d.js +82 -0
  14. package/core/geom/2d/convex-hull/fixed_convex_hull_humus.js +135 -0
  15. package/core/geom/2d/convex-hull/fixed_convex_hull_relaxation.js +282 -0
  16. package/core/geom/2d/convex-hull/orientation3.js +444 -0
  17. package/core/geom/2d/convex-hull/orientation3_array.js +22 -0
  18. package/core/geom/2d/convex-hull/orientation3_v2.js +12 -0
  19. package/core/geom/2d/intersect_ray_2d.js +56 -0
  20. package/core/geom/2d/quad-tree/QuadTreeNode.js +0 -81
  21. package/core/geom/2d/quad-tree/qt_match_data_by_circle.js +70 -0
  22. package/core/geom/3d/matrix/m4_multiply_alphatensor.js +131 -0
  23. package/core/geom/3d/plane/orient3d_fast.js +2 -6
  24. package/core/geom/3d/tetrahedra/README.md +7 -0
  25. package/core/geom/3d/tetrahedra/compute_bounding_simplex_3d.js +3 -1
  26. package/core/geom/3d/tetrahedra/delaunay/Cavity.js +48 -0
  27. package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.js → delaunay/compute_delaunay_tetrahedral_mesh.js} +15 -7
  28. package/core/geom/3d/tetrahedra/{compute_delaunay_tetrahedral_mesh.spec.js → delaunay/compute_delaunay_tetrahedral_mesh.spec.js} +0 -0
  29. package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_compute_cavity.js +73 -0
  30. package/core/geom/3d/tetrahedra/delaunay/tetrahedral_mesh_walk_toward_cavity.js +48 -0
  31. package/core/geom/3d/tetrahedra/hxt/a.js +524 -0
  32. package/core/geom/3d/tetrahedra/hxt/hxt.js +140 -0
  33. package/core/geom/3d/tetrahedra/hxt/hxt.wasm +0 -0
  34. package/core/geom/3d/tetrahedra/point_in_tetrahedron_circumsphere.js +35 -20
  35. package/core/geom/3d/tetrahedra/prototypeTetrahedraBuilder.js +98 -0
  36. package/core/geom/3d/tetrahedra/tetrahedra_collection.js +60 -131
  37. package/core/geom/packing/{MaxRectangles.js → max-rect/MaxRectangles.js} +28 -124
  38. package/core/geom/packing/max-rect/removeRedundantBoxes.js +69 -0
  39. package/core/geom/packing/max-rect/removeRedundantBoxesArray.js +40 -0
  40. package/core/geom/v3_distance_above_plane.js +1 -1
  41. package/core/graph/layout/BoxLayouter.js +2 -88
  42. package/core/graph/layout/CircleLayout.js +2 -1
  43. package/core/graph/layout/box/forceIntoBox.js +45 -0
  44. package/core/graph/layout/box/pullBoxTowardsPoint.js +20 -0
  45. package/core/graph/layout/box/resolveAABB2Overlap.js +22 -0
  46. package/core/math/bessel_3.js +11 -0
  47. package/core/math/bessel_i0.js +26 -0
  48. package/core/process/executor/ConcurrentExecutor.spec.js +2 -1
  49. package/core/process/task/util/actionTask.js +19 -0
  50. package/core/process/task/util/countTask.js +62 -0
  51. package/core/process/task/util/delayTask.js +45 -0
  52. package/core/process/task/util/emptyTask.js +19 -0
  53. package/core/process/task/util/failingTask.js +17 -0
  54. package/core/process/task/util/futureTask.js +48 -0
  55. package/core/process/task/util/promiseTask.js +42 -0
  56. package/core/process/task/util/randomCountTask.js +64 -0
  57. package/core/process/task/util/wrapTaskIgnoreFailure.js +47 -0
  58. package/engine/Engine.js +8 -8
  59. package/engine/EngineBootstrapper.js +1 -1
  60. package/engine/asset/AssetManager.js +197 -53
  61. package/engine/asset/AssetRequest.js +32 -0
  62. package/engine/asset/loaders/ArrayBufferLoader.js +62 -50
  63. package/engine/asset/loaders/image/png/PNG.js +15 -1
  64. package/engine/asset/loaders/image/png/PNGReader.js +3 -2
  65. package/engine/ecs/foliage/ecs/InstancedMeshUtils.js +2 -1
  66. package/engine/ecs/storage/BinaryBufferDeSerializer.js +1 -1
  67. package/engine/ecs/storage/JSONDeSerializer.js +2 -1
  68. package/engine/ecs/terrain/ecs/splat/SplatMapOptimizer.js +2 -1
  69. package/engine/ecs/terrain/ecs/splat/SplatMapping.js +1 -1
  70. package/engine/graphics/camera/makeScreenScissorFrustum.js +1 -1
  71. package/engine/graphics/camera/testClippingPlaneComputation.js +4 -45
  72. package/engine/graphics/ecs/camera/FrustumProjector.js +6 -0
  73. package/engine/graphics/ecs/decal/v2/FPDecalSystem.js +5 -0
  74. package/engine/graphics/ecs/decal/v2/prototypeDecalSystem.js +23 -4
  75. package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +1 -1
  76. package/engine/graphics/ecs/mesh-v2/ShadedGeometry.js +11 -0
  77. package/engine/graphics/geometry/FULL_SCREEN_TRIANGLE_GEOMETRY.js +1 -2
  78. package/engine/graphics/impostors/octahedral/ImpostorBaker.js +5 -2
  79. package/engine/graphics/impostors/octahedral/ImpostorDescription.js +18 -0
  80. package/engine/graphics/impostors/octahedral/bake/prepare_bake_material.js +15 -0
  81. package/engine/graphics/impostors/octahedral/prototypeBaker.js +66 -79
  82. package/engine/graphics/impostors/octahedral/shader/ImpostorShaderWireframeV0.js +134 -0
  83. package/engine/graphics/impostors/octahedral/util/build_cutout_from_atlas_by_alpha.js +128 -0
  84. package/engine/graphics/impostors/octahedral/util/build_geometry_from_cutout_shape.js +32 -0
  85. package/engine/graphics/impostors/octahedral/util/load_mesh_for_bake.js +31 -0
  86. package/engine/graphics/impostors/octahedral/util/makeImpostorAtlasPreview.js +107 -0
  87. package/engine/graphics/material/manager/ManagedMaterial.js +4 -0
  88. package/engine/graphics/material/manager/MaterialManager.js +1 -0
  89. package/engine/graphics/material/optimization/MaterialOptimizationContext.js +7 -3
  90. package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +2 -2
  91. package/engine/graphics/render/forward_plus/plugin/ForwardPlusRenderingPlugin.js +0 -19
  92. package/engine/graphics/render/forward_plus/prototype/prototypeLightManager.js +2 -2
  93. package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +83 -27
  94. package/engine/graphics/shadows/ShadowMapRenderer.js +11 -4
  95. package/engine/graphics/texture/atlas/AbstractTextureAtlas.js +2 -1
  96. package/engine/graphics/texture/atlas/CachingTextureAtlas.js +208 -38
  97. package/engine/graphics/texture/atlas/TextureAtlas.js +31 -24
  98. package/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js +1 -1
  99. package/engine/graphics/texture/sampler/filter/box.js +16 -0
  100. package/engine/graphics/texture/sampler/filter/cubic2.js +32 -0
  101. package/engine/graphics/texture/sampler/filter/gaussian.js +16 -0
  102. package/engine/graphics/texture/sampler/filter/kaiser_1.js +19 -0
  103. package/engine/graphics/texture/sampler/filter/kaiser_bessel_window.js +19 -0
  104. package/engine/graphics/texture/sampler/filter/mitchell.js +55 -0
  105. package/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.js +109 -0
  106. package/engine/graphics/texture/sampler/filter/triangle.js +19 -0
  107. package/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +187 -86
  108. package/engine/graphics/texture/sampler/sampler2_d_scale_down_lanczos.js +77 -25
  109. package/engine/graphics/texture/sampler/search/make_edge_condition_channel_threshold.js +34 -0
  110. package/engine/graphics/texture/sampler/search/sampler2d_find_pixels.js +24 -0
  111. package/engine/graphics/texture/sprite/prototypeSpriteCutoutGeometry.js +212 -0
  112. package/engine/knowledge/database/StaticKnowledgeDataTable.js +1 -1
  113. package/engine/navigation/grid/AStar.js +1 -1
  114. package/engine/plugin/EnginePluginManager.js +28 -27
  115. package/engine/plugin/PluginReferenceContext.js +9 -0
  116. package/engine/scene/Scene.js +1 -1
  117. package/engine/scene/SerializedScene.js +1 -1
  118. package/engine/scene/transitionToScene.js +3 -1
  119. package/generation/example/main.js +1 -1
  120. package/generation/grid/generation/GridTaskApplyActionToCells.js +1 -1
  121. package/generation/grid/generation/GridTaskDensityMarkerDistribution.js +1 -1
  122. package/generation/grid/generation/GridTaskExecuteRuleTimes.js +1 -1
  123. package/generation/grid/generation/NoopGridTaskGenerator.js +1 -1
  124. package/generation/grid/generation/discrete/GridTaskCellularAutomata.js +2 -1
  125. package/generation/grid/generation/discrete/GridTaskConnectRooms.js +1 -1
  126. package/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +3 -2
  127. package/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +1 -1
  128. package/generation/grid/generation/grid/GridTaskAddNodesFixed.js +1 -1
  129. package/generation/grid/generation/road/GridTaskGenerateRoads.js +3 -2
  130. package/generation/grid/generation/util/buildDistanceMapToObjective.js +1 -1
  131. package/generation/markers/GridActionRuleSet.js +2 -1
  132. package/generation/placement/GridCellActionTransformNearbyMarkers.js +2 -4
  133. package/generation/theme/ThemeEngine.js +4 -1
  134. package/package.json +1 -1
  135. package/view/asset/AssetLoaderStatusView.js +5 -5
  136. package/view/minimap/gl/MinimapTerrainGL.js +1 -2
  137. package/view/renderModel.js +1 -1
  138. package/view/tooltip/TooltipView.js +5 -5
  139. 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
+ }
@@ -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(points, a, b, c, d, e) {
23
- const ex = points[e * 3];
24
- const ey = points[e * 3 + 1];
25
- const ez = points[e * 3 + 2];
26
-
27
- const aex = points[a * 3] - ex;
28
- const bex = points[b * 3] - ex;
29
- const cex = points[c * 3] - ex;
30
- const dex = points[d * 3] - ex;
31
-
32
- const aey = points[a * 3 + 1] - ey;
33
- const bey = points[b * 3 + 1] - ey;
34
- const cey = points[c * 3 + 1] - ey;
35
- const dey = points[d * 3 + 1] - ey;
36
-
37
- const aez = points[a * 3 + 2] - ez;
38
- const bez = points[b * 3 + 2] - ez;
39
- const cez = points[c * 3 + 2] - ez;
40
- const dez = points[d * 3 + 1] - ez;
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 :: uint
70
- * vertex_id_b :: uint
71
- * vertex_id_c :: uint
72
- * vertex_id_d :: uint
73
- * neighbour_a :: uint - neighbour tetrahedron, opposite to vertex A
74
- * neighbour_b :: uint - neighbour tetrahedron, opposite to vertex B
75
- * neighbour_c :: uint - neighbour tetrahedron, opposite to vertex C
76
- * neighbour_d :: uint - neighbour tetrahedron, opposite to vertex 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 TetrahedraCollection {
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 * i);
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 {Cavity} cavity
290
- * @param {number[]|Float32Array} points
291
- * @param {number} index
275
+ * @param {number} tet_index
276
+ * @param {number} point_index should be an integer between 0 and 3
277
+ * @returns {number}
292
278
  */
293
- computeCavity(cavity, points, index) {
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.computeCavity(SCRATCH_CAVITY, points, index);
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
  /**