@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,140 +0,0 @@
|
|
|
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
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
import { tetrahedron_contains_point } from "./tetrahedron_contains_point.js";
|
|
2
|
-
import { assert } from "../../../assert.js";
|
|
3
|
-
import { BitSet } from "../../../binary/BitSet.js";
|
|
4
|
-
import { typed_array_copy } from "../../../collection/array/typed/typed_array_copy.js";
|
|
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";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Size in bytes of a single tetrahedron record
|
|
11
|
-
* @readonly
|
|
12
|
-
* @type {number}
|
|
13
|
-
*/
|
|
14
|
-
export const LAYOUT_TETRA_BYTE_SIZE = 9 * 4;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @readonly
|
|
18
|
-
* @type {number}
|
|
19
|
-
*/
|
|
20
|
-
export const INVALID_NEIGHBOUR = 0xFFFFFFFF;
|
|
21
|
-
|
|
22
|
-
const SCRATCH_CAVITY = new Cavity();
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Only keeps track of tetrahedra, actual point coordinates are stored outside. For most useful operations point coordinates are passed in
|
|
26
|
-
* Layout:
|
|
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
|
|
35
|
-
* sub_determinant :: float - ?
|
|
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])
|
|
40
|
-
*/
|
|
41
|
-
export class TetrahedralMesh {
|
|
42
|
-
constructor(initial_size) {
|
|
43
|
-
this.__buffer = new ArrayBuffer(initial_size * LAYOUT_TETRA_BYTE_SIZE);
|
|
44
|
-
|
|
45
|
-
this.__view = new DataView(this.__buffer);
|
|
46
|
-
|
|
47
|
-
this.__capacity = initial_size;
|
|
48
|
-
this.__length = 0;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Marks which indices are in use
|
|
53
|
-
* @type {BitSet}
|
|
54
|
-
* @private
|
|
55
|
-
*/
|
|
56
|
-
this.__occupancy = new BitSet();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
*
|
|
61
|
-
* @param {number} n
|
|
62
|
-
*/
|
|
63
|
-
setCapacity(n) {
|
|
64
|
-
if (n === this.__capacity) {
|
|
65
|
-
// do nothing
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (n < this.__length) {
|
|
70
|
-
throw new Error('Dropping information, not supported');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// allocate new buffer
|
|
74
|
-
const new_buffer = new ArrayBuffer(n * LAYOUT_TETRA_BYTE_SIZE);
|
|
75
|
-
|
|
76
|
-
// move data across from old buffer to the new one
|
|
77
|
-
const destination_uint8 = new Uint8Array(new_buffer);
|
|
78
|
-
const source_uint8 = new Uint8Array(this.__buffer);
|
|
79
|
-
|
|
80
|
-
typed_array_copy(source_uint8, destination_uint8);
|
|
81
|
-
|
|
82
|
-
// set new buffer
|
|
83
|
-
this.__buffer = new_buffer;
|
|
84
|
-
this.__view = new DataView(new_buffer);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
*
|
|
89
|
-
* @param {number} n
|
|
90
|
-
*/
|
|
91
|
-
ensureCapacity(n) {
|
|
92
|
-
|
|
93
|
-
const new_capacity = max3(
|
|
94
|
-
n,
|
|
95
|
-
this.__capacity * 1.2,
|
|
96
|
-
this.__capacity + 32
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
this.setCapacity(new_capacity);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
*
|
|
104
|
-
* @param {number} tetra_index
|
|
105
|
-
* @param {number} neighbour_index
|
|
106
|
-
* @returns {number}
|
|
107
|
-
*/
|
|
108
|
-
getNeighbour(tetra_index, neighbour_index) {
|
|
109
|
-
const tetra_address = LAYOUT_TETRA_BYTE_SIZE * tetra_index;
|
|
110
|
-
return this.__view.getUint32(tetra_address + (4 + neighbour_index) * 4);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
*
|
|
115
|
-
* @param {number} tetra_index
|
|
116
|
-
* @param {number} neighbour_index which neighbour to set (0..11)
|
|
117
|
-
* @param {number} neighbour index of the neighbour
|
|
118
|
-
*/
|
|
119
|
-
setNeighbour(tetra_index, neighbour_index, neighbour) {
|
|
120
|
-
const tetra_address = LAYOUT_TETRA_BYTE_SIZE * tetra_index;
|
|
121
|
-
return this.__view.setUint32(tetra_address + (4 + neighbour_index) * 4, neighbour);
|
|
122
|
-
}
|
|
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
|
-
|
|
142
|
-
/**
|
|
143
|
-
*
|
|
144
|
-
* @param {number[]|Float32Array} points
|
|
145
|
-
* @param {number} a
|
|
146
|
-
* @param {number} b
|
|
147
|
-
* @param {number} c
|
|
148
|
-
* @param {number} d
|
|
149
|
-
* @returns {number} index of the new tetra
|
|
150
|
-
*/
|
|
151
|
-
append(points, a, b, c, d) {
|
|
152
|
-
const tetra_index = this.__occupancy.nextClearBit(0);
|
|
153
|
-
const address = tetra_index * LAYOUT_TETRA_BYTE_SIZE;
|
|
154
|
-
|
|
155
|
-
if (tetra_index >= this.__capacity) {
|
|
156
|
-
// needs to be increased in size
|
|
157
|
-
this.ensureCapacity(tetra_index);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const view = this.__view;
|
|
161
|
-
|
|
162
|
-
view.setUint32(address, a);
|
|
163
|
-
view.setUint32(address + 4, b);
|
|
164
|
-
view.setUint32(address + 8, c);
|
|
165
|
-
view.setUint32(address + 12, d);
|
|
166
|
-
|
|
167
|
-
// set neighbours
|
|
168
|
-
view.setUint32(address + 16, INVALID_NEIGHBOUR);
|
|
169
|
-
view.setUint32(address + 20, INVALID_NEIGHBOUR);
|
|
170
|
-
view.setUint32(address + 24, INVALID_NEIGHBOUR);
|
|
171
|
-
view.setUint32(address + 28, INVALID_NEIGHBOUR);
|
|
172
|
-
|
|
173
|
-
//assert(this.validateLength());
|
|
174
|
-
|
|
175
|
-
this.__occupancy.set(tetra_index, true);
|
|
176
|
-
|
|
177
|
-
this.__length++;
|
|
178
|
-
|
|
179
|
-
// assert(this.validateLength());
|
|
180
|
-
|
|
181
|
-
return tetra_index;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Remove tetrahedron
|
|
186
|
-
* @param {number} tera_index
|
|
187
|
-
*/
|
|
188
|
-
remove(tera_index) {
|
|
189
|
-
|
|
190
|
-
// find neighbours and remove reference to self
|
|
191
|
-
for (let i = 0; i < 4; i++) {
|
|
192
|
-
const neighbour_encoded = this.getNeighbour(tera_index, i);
|
|
193
|
-
|
|
194
|
-
if (neighbour_encoded === INVALID_NEIGHBOUR) {
|
|
195
|
-
// no neighbour
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// get tetrahedra index and point index
|
|
200
|
-
const neighbour_index = neighbour_encoded >> 2;
|
|
201
|
-
const neighbour_point = neighbour_encoded & 4;
|
|
202
|
-
|
|
203
|
-
// clear reference to self
|
|
204
|
-
this.setNeighbour(neighbour_index, neighbour_point, INVALID_NEIGHBOUR);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
//assert(this.validateLength());
|
|
208
|
-
|
|
209
|
-
// mark as dead
|
|
210
|
-
this.__occupancy.clear(tera_index);
|
|
211
|
-
this.__length--;
|
|
212
|
-
|
|
213
|
-
//assert(this.validateLength());
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Remove tetrahedrons who's points touch the "super-tetrahedron's" points that was inserted originally
|
|
218
|
-
* These points are identified by an offset + count parameters
|
|
219
|
-
* @param {number[]|Float32Array} points
|
|
220
|
-
* @param {number} range_start
|
|
221
|
-
* @param {number} range_end
|
|
222
|
-
*/
|
|
223
|
-
removeTetrasConnectedToPoints(points, range_start, range_end) {
|
|
224
|
-
const data_view = this.__view;
|
|
225
|
-
|
|
226
|
-
let j = 0;
|
|
227
|
-
|
|
228
|
-
const occupancy = this.__occupancy;
|
|
229
|
-
for (let i = occupancy.nextSetBit(0); i !== -1; i = occupancy.nextSetBit(i + 1)) {
|
|
230
|
-
|
|
231
|
-
const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
|
|
232
|
-
|
|
233
|
-
for (j = 0; j < 4; j++) {
|
|
234
|
-
const point_index = data_view.getUint32(tet_address + 4 * j);
|
|
235
|
-
|
|
236
|
-
if (point_index >= range_start && point_index <= range_end) {
|
|
237
|
-
// point index is in range, tetra should be removed
|
|
238
|
-
this.remove(i);
|
|
239
|
-
break;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
*
|
|
247
|
-
* @param {number[]} points
|
|
248
|
-
* @param {number} index
|
|
249
|
-
* @returns {number} index of tetra or -1 if no containing tetra found
|
|
250
|
-
*/
|
|
251
|
-
findTetraContainingPoint(points, index) {
|
|
252
|
-
const data_view = this.__view;
|
|
253
|
-
|
|
254
|
-
// TODO improve this
|
|
255
|
-
const n = this.__length;
|
|
256
|
-
for (let i = 0; i < n; i++) {
|
|
257
|
-
|
|
258
|
-
const tet_address = i * LAYOUT_TETRA_BYTE_SIZE;
|
|
259
|
-
|
|
260
|
-
const a = data_view.getUint32(tet_address);
|
|
261
|
-
const b = data_view.getUint32(tet_address + 4);
|
|
262
|
-
const c = data_view.getUint32(tet_address + 8);
|
|
263
|
-
const d = data_view.getUint32(tet_address + 12);
|
|
264
|
-
|
|
265
|
-
if (tetrahedron_contains_point(points, a, b, c, d, index)) {
|
|
266
|
-
return i;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return -1;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
*
|
|
275
|
-
* @param {number} tet_index
|
|
276
|
-
* @param {number} point_index should be an integer between 0 and 3
|
|
277
|
-
* @returns {number}
|
|
278
|
-
*/
|
|
279
|
-
getCornerIndex(tet_index, point_index) {
|
|
280
|
-
return this.__view.getUint32(tet_index * LAYOUT_TETRA_BYTE_SIZE + point_index * 4);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
*
|
|
286
|
-
* @param {number[]|Float32Array} points
|
|
287
|
-
* @param {number} index
|
|
288
|
-
*/
|
|
289
|
-
insertPoint(points, index) {
|
|
290
|
-
const debug_length_initial = this.__length;
|
|
291
|
-
|
|
292
|
-
// Compute the cavity, that is the set of tetrahedra that need to be removed and rebuilt
|
|
293
|
-
tetrahedral_mesh_compute_cavity(this, SCRATCH_CAVITY, points, index);
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// identify cavity "edge" - the set of tetras that are neighbours of the tetras that form the cavity
|
|
297
|
-
const cavity_size = SCRATCH_CAVITY.size;
|
|
298
|
-
const cavity_indices = SCRATCH_CAVITY.indices;
|
|
299
|
-
|
|
300
|
-
for (let i = 0; i < cavity_size; i++) {
|
|
301
|
-
const data = this.__view;
|
|
302
|
-
|
|
303
|
-
const cavity_index = cavity_indices[i];
|
|
304
|
-
|
|
305
|
-
// take each side of the tetra
|
|
306
|
-
const tetra_address = cavity_index * LAYOUT_TETRA_BYTE_SIZE;
|
|
307
|
-
|
|
308
|
-
const a = data.getUint32(tetra_address);
|
|
309
|
-
const b = data.getUint32(tetra_address + 4);
|
|
310
|
-
const c = data.getUint32(tetra_address + 8);
|
|
311
|
-
const d = data.getUint32(tetra_address + 12);
|
|
312
|
-
|
|
313
|
-
// attempt to form 4 tetras using the sides of the cavity
|
|
314
|
-
const a_neighbour = data.getUint32(tetra_address + 16);
|
|
315
|
-
const a_neighbour_index = a_neighbour >> 2;
|
|
316
|
-
|
|
317
|
-
const b_neighbour = data.getUint32(tetra_address + 20);
|
|
318
|
-
const b_neighbour_index = b_neighbour >> 2;
|
|
319
|
-
|
|
320
|
-
const c_neighbour = data.getUint32(tetra_address + 24);
|
|
321
|
-
const c_neighbour_index = c_neighbour >> 2;
|
|
322
|
-
|
|
323
|
-
const d_neighbour = data.getUint32(tetra_address + 28);
|
|
324
|
-
const d_neighbour_index = d_neighbour >> 2;
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (a_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(a_neighbour_index) === 0) {
|
|
328
|
-
// ABC is a valid side
|
|
329
|
-
const tet = this.append(points, b, d, c, index);
|
|
330
|
-
// patch in neighbours
|
|
331
|
-
if (a_neighbour !== INVALID_NEIGHBOUR) {
|
|
332
|
-
this.setNeighbour(tet, 3, a_neighbour);
|
|
333
|
-
this.setNeighbour(a_neighbour_index, a_neighbour & 3, tet);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
if (b_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(b_neighbour_index) === 0) {
|
|
337
|
-
// ABC is a valid side
|
|
338
|
-
const tet = this.append(points, c, d, a, index);
|
|
339
|
-
if (b_neighbour !== INVALID_NEIGHBOUR) {
|
|
340
|
-
this.setNeighbour(tet, 3, b_neighbour);
|
|
341
|
-
this.setNeighbour(b_neighbour_index, b_neighbour & 3, tet);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
if (c_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(c_neighbour_index) === 0) {
|
|
345
|
-
// ABC is a valid side
|
|
346
|
-
const tet = this.append(points, d, b, a, index);
|
|
347
|
-
if (c_neighbour !== INVALID_NEIGHBOUR) {
|
|
348
|
-
this.setNeighbour(tet, 3, c_neighbour);
|
|
349
|
-
this.setNeighbour(c_neighbour_index, c_neighbour & 3, tet);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
if (d_neighbour === INVALID_NEIGHBOUR || cavity_indices.indexOf(d_neighbour_index) === 0) {
|
|
353
|
-
// ABC is a valid side
|
|
354
|
-
const tet = this.append(points, a, b, c, index);
|
|
355
|
-
if (d_neighbour !== INVALID_NEIGHBOUR) {
|
|
356
|
-
this.setNeighbour(tet, 3, d_neighbour);
|
|
357
|
-
this.setNeighbour(d_neighbour_index, d_neighbour & 3, tet);
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
// 3. remove the cavity tetrahedrons
|
|
364
|
-
for (let i = 0; i < cavity_size; i++) {
|
|
365
|
-
const cavity_index = cavity_indices[i];
|
|
366
|
-
|
|
367
|
-
// clear out cavity, connectivity was already patched in the previous step
|
|
368
|
-
this.__occupancy.set(cavity_index, false);
|
|
369
|
-
this.__length--;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
assert.greaterThan(this.__length, debug_length_initial, 'after insertion number of tetrahedra must grow, not shrink')
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* optimize tetrahedrons to reduce number of thin and long tetras
|
|
377
|
-
* @see https://gitlab.onelab.info/gmsh/gmsh/-/blob/master/contrib/hxt/tetMesh/src/HXTSPR.c
|
|
378
|
-
*/
|
|
379
|
-
optimize() {
|
|
380
|
-
|
|
381
|
-
throw new Error('Not Implemented');
|
|
382
|
-
}
|
|
383
|
-
}
|