@woosh/meep-engine 2.139.0 → 2.140.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 (172) hide show
  1. package/package.json +1 -1
  2. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.d.ts +3 -3
  3. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.d.ts.map +1 -1
  4. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js +4 -4
  5. package/src/{engine/physics/broadphase/aabb_transform_oriented.d.ts → core/geom/3d/aabb/aabb3_transform_oriented.d.ts} +2 -2
  6. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -0
  7. package/src/{engine/physics/broadphase/aabb_transform_oriented.js → core/geom/3d/aabb/aabb3_transform_oriented.js} +1 -1
  8. package/src/core/geom/3d/quaternion/quat3_to_matrix3.d.ts +54 -0
  9. package/src/core/geom/3d/quaternion/quat3_to_matrix3.d.ts.map +1 -0
  10. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -0
  11. package/src/core/geom/3d/shape/AbstractShape3D.d.ts +24 -2
  12. package/src/core/geom/3d/shape/AbstractShape3D.d.ts.map +1 -1
  13. package/src/core/geom/3d/shape/AbstractShape3D.js +24 -1
  14. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +148 -0
  15. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -0
  16. package/src/core/geom/3d/shape/HeightMapShape3D.js +451 -0
  17. package/src/core/geom/3d/shape/MeshShape3D.d.ts +210 -0
  18. package/src/core/geom/3d/shape/MeshShape3D.d.ts.map +1 -0
  19. package/src/core/geom/3d/shape/MeshShape3D.js +593 -0
  20. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  21. package/src/core/geom/3d/shape/TransformedShape3D.js +46 -2
  22. package/src/core/geom/3d/shape/Triangle3D.d.ts +95 -0
  23. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -0
  24. package/src/core/geom/3d/shape/Triangle3D.js +318 -0
  25. package/src/core/geom/3d/shape/UnionShape3D.js +13 -0
  26. package/src/core/geom/3d/shape/shape_mesh_from_geometry.d.ts +30 -0
  27. package/src/core/geom/3d/shape/shape_mesh_from_geometry.d.ts.map +1 -0
  28. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +64 -0
  29. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +9 -11
  30. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.d.ts +28 -0
  31. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.d.ts.map +1 -0
  32. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -0
  33. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -1
  34. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +40 -18
  35. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +9 -5
  36. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -1
  37. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +38 -10
  38. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +14 -5
  39. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -1
  40. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +47 -5
  41. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +19 -0
  42. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
  43. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +75 -13
  44. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.d.ts +2 -2
  45. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.d.ts.map +1 -1
  46. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +1 -1
  47. package/src/core/geom/vec3/v3_dot_array_array.d.ts +3 -3
  48. package/src/core/geom/vec3/v3_dot_array_array.d.ts.map +1 -1
  49. package/src/core/geom/vec3/v3_dot_array_array.js +2 -2
  50. package/src/core/geom/vec3/v3_negate_array.d.ts +3 -3
  51. package/src/core/geom/vec3/v3_negate_array.d.ts.map +1 -1
  52. package/src/core/geom/vec3/v3_negate_array.js +2 -2
  53. package/src/core/geom/vec3/v3_quat3_apply.d.ts +29 -0
  54. package/src/core/geom/vec3/v3_quat3_apply.d.ts.map +1 -0
  55. package/src/core/geom/vec3/v3_quat3_apply.js +39 -0
  56. package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts +30 -0
  57. package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts.map +1 -0
  58. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +41 -0
  59. package/src/core/geom/vec3/v3_triple_cross_product.d.ts +32 -0
  60. package/src/core/geom/vec3/v3_triple_cross_product.d.ts.map +1 -0
  61. package/src/core/geom/vec3/v3_triple_cross_product.js +45 -0
  62. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +16 -3
  63. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  64. package/src/engine/control/first-person/FirstPersonPlayerController.js +211 -211
  65. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +72 -8
  66. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  67. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +37 -5
  68. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +101 -3
  69. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
  70. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +1789 -1416
  71. package/src/engine/control/first-person/TODO.md +173 -127
  72. package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -1
  73. package/src/engine/control/first-person/abilities/Slide.js +9 -1
  74. package/src/engine/control/first-person/prototype_first_person_controller.js +88 -2
  75. package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -1
  76. package/src/engine/control/first-person/test/buildTestPlayer.js +9 -1
  77. package/src/engine/graphics/geometry/CapsuleGeometry.d.ts +42 -0
  78. package/src/engine/graphics/geometry/CapsuleGeometry.d.ts.map +1 -0
  79. package/src/engine/graphics/geometry/CapsuleGeometry.js +171 -0
  80. package/src/engine/physics/BULLET_REVIEW.md +945 -0
  81. package/src/engine/physics/CANNON_REVIEW.md +1300 -0
  82. package/src/engine/physics/JOLT_REVIEW.md +913 -0
  83. package/src/engine/physics/PLAN.md +461 -236
  84. package/src/engine/physics/RAPIER_REVIEW.md +934 -0
  85. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -0
  86. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +2 -2
  87. package/src/engine/physics/contact/ManifoldStore.d.ts +83 -10
  88. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
  89. package/src/engine/physics/contact/ManifoldStore.js +608 -499
  90. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +2 -2
  91. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -1
  92. package/src/engine/physics/ecs/PhysicsSystem.d.ts +128 -20
  93. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  94. package/src/engine/physics/ecs/PhysicsSystem.js +1301 -1159
  95. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  96. package/src/engine/physics/fluid/FluidSimulator.js +2 -1
  97. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +28 -6
  98. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -1
  99. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +39 -17
  100. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts +6 -6
  101. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
  102. package/src/engine/physics/gjk/expanding_polytope_algorithm.js +68 -22
  103. package/src/engine/physics/gjk/gjk.d.ts +28 -2
  104. package/src/engine/physics/gjk/gjk.d.ts.map +1 -1
  105. package/src/engine/physics/gjk/gjk.js +421 -378
  106. package/src/engine/physics/gjk/minkowski_support.d.ts +37 -0
  107. package/src/engine/physics/gjk/minkowski_support.d.ts.map +1 -0
  108. package/src/engine/physics/gjk/minkowski_support.js +75 -0
  109. package/src/engine/physics/gjk/mpr.d.ts +56 -0
  110. package/src/engine/physics/gjk/mpr.d.ts.map +1 -0
  111. package/src/engine/physics/gjk/mpr.js +344 -0
  112. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +20 -5
  113. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  114. package/src/engine/physics/inertia/world_inverse_inertia.js +36 -38
  115. package/src/engine/physics/integration/integrate_position.d.ts +25 -7
  116. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -1
  117. package/src/engine/physics/integration/integrate_position.js +43 -12
  118. package/src/engine/physics/integration/integrate_velocity.d.ts +30 -0
  119. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -1
  120. package/src/engine/physics/integration/integrate_velocity.js +82 -1
  121. package/src/engine/physics/narrowphase/PosedShape.d.ts +0 -8
  122. package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -1
  123. package/src/engine/physics/narrowphase/PosedShape.js +28 -30
  124. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
  125. package/src/engine/physics/narrowphase/box_box_manifold.js +113 -17
  126. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts +30 -0
  127. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -0
  128. package/src/engine/physics/narrowphase/box_triangle_contact.js +811 -0
  129. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
  130. package/src/engine/physics/narrowphase/capsule_contacts.js +10 -56
  131. package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts +71 -0
  132. package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts.map +1 -0
  133. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +375 -0
  134. package/src/engine/physics/narrowphase/compute_penetration.d.ts +91 -0
  135. package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -0
  136. package/src/engine/physics/narrowphase/compute_penetration.js +396 -0
  137. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts +35 -0
  138. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts.map +1 -0
  139. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.js +80 -0
  140. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.d.ts +31 -0
  141. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.d.ts.map +1 -0
  142. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -0
  143. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +42 -0
  144. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -0
  145. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +204 -0
  146. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts +42 -0
  147. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -0
  148. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +94 -0
  149. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts +37 -0
  150. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts.map +1 -0
  151. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -0
  152. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +8 -2
  153. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  154. package/src/engine/physics/narrowphase/narrowphase_step.js +1422 -382
  155. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
  156. package/src/engine/physics/narrowphase/sphere_box_contact.js +16 -23
  157. package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts +48 -0
  158. package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts.map +1 -0
  159. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +143 -0
  160. package/src/engine/physics/queries/overlap_shape.d.ts +51 -0
  161. package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -0
  162. package/src/engine/physics/queries/overlap_shape.js +183 -0
  163. package/src/engine/physics/queries/shape_cast.d.ts +56 -0
  164. package/src/engine/physics/queries/shape_cast.d.ts.map +1 -0
  165. package/src/engine/physics/queries/shape_cast.js +387 -0
  166. package/src/engine/physics/solver/solve_contacts.d.ts +116 -30
  167. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
  168. package/src/engine/physics/solver/solve_contacts.js +641 -223
  169. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +0 -1
  170. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +0 -20
  171. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +0 -1
  172. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +0 -83
@@ -1,11 +1,11 @@
1
1
  import { assert } from "../../../assert.js";
2
+ import {
3
+ tetrahedral_mesh_build_vertex_to_tets_map
4
+ } from "./tetrahedral_mesh_build_vertex_to_tets_map.js";
2
5
  import { compute_tetrahedron_quality } from "./compute_tetrahedron_quality.js";
3
6
  import {
4
7
  tetrahedral_mesh_find_tets_around_edge
5
8
  } from "./tetrahedral_mesh_find_tets_around_edge.js";
6
- import {
7
- tetrahedral_mesh_find_tets_attached_to_vertex
8
- } from "./tetrahedral_mesh_find_tets_attached_to_vertex.js";
9
9
  import { tetrahedral_mesh_flip_23 } from "./tetrahedral_mesh_flip_23.js";
10
10
  import { tetrahedral_mesh_flip_32 } from "./tetrahedral_mesh_flip_32.js";
11
11
  import {
@@ -27,14 +27,12 @@ const FACE_VERTICES_BY_OPPOSITE = [
27
27
  [0, 1, 2],
28
28
  ];
29
29
 
30
- // Scratch for the 2-3 / 3-2 flip out-parameters and for collecting tets
31
- // during local quality re-evaluation. Module-level — the driver is not
32
- // re-entrant.
30
+ // Scratch for the 2-3 / 3-2 flip out-parameters. Module-level the driver
31
+ // is not re-entrant.
33
32
  const scratch_out_23 = new Uint32Array(3);
34
33
  const scratch_out_32 = new Uint32Array(2);
35
34
  const scratch_edge_ring = new Array(16);
36
35
  const scratch_ring_closed = [0];
37
- let scratch_local_tets = new Array(64);
38
36
 
39
37
  // The 6 unique vertex-pair (i, j) slots in a 4-vertex tet, enumerating
40
38
  // every edge once. Used to iterate the 6 edges of a candidate tet during
@@ -122,6 +120,13 @@ export function tetrahedral_mesh_improve_quality(mesh, points, options = {}) {
122
120
  // delete and re-introduce tet IDs underneath us.
123
121
  const live = mesh.getLive();
124
122
 
123
+ // Build a vertex->tets cache once per pass. Used by the boundary
124
+ // check (flip-invariant — safe to use for the whole pass) and by
125
+ // the local quality eval (filtered through mesh.exists; may miss
126
+ // newly-flipped tets which is fine: the live-snapshot iteration
127
+ // already misses them too, and they'll be picked up next pass).
128
+ const vertex_to_tets = tetrahedral_mesh_build_vertex_to_tets_map(mesh);
129
+
125
130
  for (let li = 0; li < live.length; li++) {
126
131
  const tet = live[li];
127
132
  if (!mesh.exists(tet)) continue;
@@ -134,19 +139,19 @@ export function tetrahedral_mesh_improve_quality(mesh, points, options = {}) {
134
139
  for (let i = 0; i < 4; i++) {
135
140
  if (!mesh.exists(tet)) break;
136
141
  const v_id = mesh.getVertexIndex(tet, i);
137
- if (tetrahedral_mesh_vertex_is_boundary(mesh, v_id)) continue;
142
+ if (tetrahedral_mesh_vertex_is_boundary(mesh, v_id, vertex_to_tets)) continue;
138
143
 
139
144
  const v3 = v_id * 3;
140
145
  const old_x = points[v3];
141
146
  const old_y = points[v3 + 1];
142
147
  const old_z = points[v3 + 2];
143
148
 
144
- const old_min = local_min_quality_around_vertex(mesh, points, v_id);
149
+ const old_min = local_min_quality_around_vertex(mesh, points, v_id, vertex_to_tets);
145
150
 
146
- const moved = tetrahedral_mesh_smooth_vertex(mesh, points, v_id, smoothing_weight);
151
+ const moved = tetrahedral_mesh_smooth_vertex(mesh, points, v_id, smoothing_weight, vertex_to_tets);
147
152
  if (!moved) continue;
148
153
 
149
- const new_min = local_min_quality_around_vertex(mesh, points, v_id);
154
+ const new_min = local_min_quality_around_vertex(mesh, points, v_id, vertex_to_tets);
150
155
  if (new_min > old_min) {
151
156
  stats.smoothings_committed++;
152
157
  any_improvement = true;
@@ -349,16 +354,33 @@ function scan_min_quality(mesh, points) {
349
354
  /**
350
355
  * Min quality across all tets containing `v_id`. Used to score the local
351
356
  * effect of moving (or undoing the move of) a single vertex.
357
+ *
358
+ * Reads the incident tets directly from the pass-level cache and filters
359
+ * out tets that have since been deleted. Cache entries whose vertex set
360
+ * no longer contains `v_id` (because a flip re-used the slot) are
361
+ * silently skipped — those tets are no longer part of `v_id`'s 1-ring
362
+ * anyway.
352
363
  */
353
- function local_min_quality_around_vertex(mesh, points, v_id) {
354
- if (scratch_local_tets.length < mesh.count) {
355
- scratch_local_tets = new Array(Math.max(mesh.count, scratch_local_tets.length * 2));
356
- }
357
- const n = tetrahedral_mesh_find_tets_attached_to_vertex(scratch_local_tets, 0, mesh, v_id);
364
+ function local_min_quality_around_vertex(mesh, points, v_id, vertex_to_tets) {
365
+ const tets = vertex_to_tets.get(v_id);
366
+ if (tets === undefined) return 1;
358
367
 
359
368
  let min_q = 1;
360
- for (let i = 0; i < n; i++) {
361
- const q = compute_tetrahedron_quality(mesh, points, scratch_local_tets[i]);
369
+ for (let i = 0; i < tets.length; i++) {
370
+ const tet = tets[i];
371
+ if (!mesh.exists(tet)) continue;
372
+ // Tet may have been re-used by a flip with a different vertex set;
373
+ // confirm v_id is still incident before counting it.
374
+ let still_incident = false;
375
+ for (let s = 0; s < 4; s++) {
376
+ if (mesh.getVertexIndex(tet, s) === v_id) {
377
+ still_incident = true;
378
+ break;
379
+ }
380
+ }
381
+ if (!still_incident) continue;
382
+
383
+ const q = compute_tetrahedron_quality(mesh, points, tet);
362
384
  if (q < min_q) min_q = q;
363
385
  }
364
386
  return min_q;
@@ -6,10 +6,13 @@
6
6
  * Mutates `points` in place. Does NOT touch the mesh topology.
7
7
  *
8
8
  * The 1-ring is computed by finding every tet that contains `vertex_id` and
9
- * collecting the OTHER 3 vertices of each tet, deduplicated. For typical
10
- * meshes this is fast; for very heavy use over many vertices in tight
11
- * loops, build a vertex-to-tet adjacency map once and call a lower-level
12
- * smoothing primitive instead.
9
+ * collecting the OTHER 3 vertices of each tet, deduplicated.
10
+ *
11
+ * If `vertex_to_tets_map` is provided (a `Map<vertex_id, tet_id[]>` from
12
+ * {@link tetrahedral_mesh_build_vertex_to_tets_map}), the incident-tet
13
+ * lookup runs in O(deg) instead of O(N). Entries pointing to deleted tets
14
+ * or to tets that no longer contain `vertex_id` (e.g. flipped) are
15
+ * silently filtered.
13
16
  *
14
17
  * Does NOT check whether the vertex sits on the mesh boundary — the caller
15
18
  * is responsible for skipping boundary vertices (via
@@ -25,7 +28,8 @@
25
28
  * @param {Float32Array|number[]} points flat (x,y,z) positions — mutated in place
26
29
  * @param {number} vertex_id
27
30
  * @param {number} [weight] move fraction, default 1.0
31
+ * @param {Map<number, number[]>} [vertex_to_tets_map] optional adjacency cache
28
32
  * @returns {boolean} true if `points` was modified
29
33
  */
30
- export function tetrahedral_mesh_smooth_vertex(mesh: TetrahedralMesh, points: Float32Array | number[], vertex_id: number, weight?: number): boolean;
34
+ export function tetrahedral_mesh_smooth_vertex(mesh: TetrahedralMesh, points: Float32Array | number[], vertex_id: number, weight?: number, vertex_to_tets_map?: Map<number, number[]>): boolean;
31
35
  //# sourceMappingURL=tetrahedral_mesh_smooth_vertex.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tetrahedral_mesh_smooth_vertex.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,8EALW,YAAY,GAAC,MAAM,EAAE,aACrB,MAAM,WACN,MAAM,GACJ,OAAO,CAyEnB"}
1
+ {"version":3,"file":"tetrahedral_mesh_smooth_vertex.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,8EANW,YAAY,GAAC,MAAM,EAAE,aACrB,MAAM,WACN,MAAM,uBACN,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC,GACnB,OAAO,CAiGnB"}
@@ -17,10 +17,13 @@ let scratch_neighbours = new Array(128);
17
17
  * Mutates `points` in place. Does NOT touch the mesh topology.
18
18
  *
19
19
  * The 1-ring is computed by finding every tet that contains `vertex_id` and
20
- * collecting the OTHER 3 vertices of each tet, deduplicated. For typical
21
- * meshes this is fast; for very heavy use over many vertices in tight
22
- * loops, build a vertex-to-tet adjacency map once and call a lower-level
23
- * smoothing primitive instead.
20
+ * collecting the OTHER 3 vertices of each tet, deduplicated.
21
+ *
22
+ * If `vertex_to_tets_map` is provided (a `Map<vertex_id, tet_id[]>` from
23
+ * {@link tetrahedral_mesh_build_vertex_to_tets_map}), the incident-tet
24
+ * lookup runs in O(deg) instead of O(N). Entries pointing to deleted tets
25
+ * or to tets that no longer contain `vertex_id` (e.g. flipped) are
26
+ * silently filtered.
24
27
  *
25
28
  * Does NOT check whether the vertex sits on the mesh boundary — the caller
26
29
  * is responsible for skipping boundary vertices (via
@@ -36,9 +39,10 @@ let scratch_neighbours = new Array(128);
36
39
  * @param {Float32Array|number[]} points flat (x,y,z) positions — mutated in place
37
40
  * @param {number} vertex_id
38
41
  * @param {number} [weight] move fraction, default 1.0
42
+ * @param {Map<number, number[]>} [vertex_to_tets_map] optional adjacency cache
39
43
  * @returns {boolean} true if `points` was modified
40
44
  */
41
- export function tetrahedral_mesh_smooth_vertex(mesh, points, vertex_id, weight = 1.0) {
45
+ export function tetrahedral_mesh_smooth_vertex(mesh, points, vertex_id, weight = 1.0, vertex_to_tets_map) {
42
46
  assert.defined(mesh, 'mesh');
43
47
  assert.defined(points, 'points');
44
48
  assert.isNonNegativeInteger(vertex_id, 'vertex_id');
@@ -47,12 +51,36 @@ export function tetrahedral_mesh_smooth_vertex(mesh, points, vertex_id, weight =
47
51
  if (weight === 0) return false;
48
52
 
49
53
  // 1. Find tets containing the vertex.
50
- if (scratch_tets.length < mesh.count) {
51
- scratch_tets = new Array(Math.max(mesh.count, scratch_tets.length * 2));
54
+ let tet_count;
55
+ if (vertex_to_tets_map !== undefined) {
56
+ const cached = vertex_to_tets_map.get(vertex_id);
57
+ if (cached === undefined) return false;
58
+ if (scratch_tets.length < cached.length) {
59
+ scratch_tets = new Array(Math.max(cached.length, scratch_tets.length * 2));
60
+ }
61
+ // Filter stale entries (deleted tets, or tets that no longer
62
+ // contain vertex_id because a flip re-used the slot).
63
+ tet_count = 0;
64
+ for (let i = 0; i < cached.length; i++) {
65
+ const tet = cached[i];
66
+ if (!mesh.exists(tet)) continue;
67
+ let still_incident = false;
68
+ for (let s = 0; s < 4; s++) {
69
+ if (mesh.getVertexIndex(tet, s) === vertex_id) {
70
+ still_incident = true;
71
+ break;
72
+ }
73
+ }
74
+ if (still_incident) scratch_tets[tet_count++] = tet;
75
+ }
76
+ } else {
77
+ if (scratch_tets.length < mesh.count) {
78
+ scratch_tets = new Array(Math.max(mesh.count, scratch_tets.length * 2));
79
+ }
80
+ tet_count = tetrahedral_mesh_find_tets_attached_to_vertex(
81
+ scratch_tets, 0, mesh, vertex_id
82
+ );
52
83
  }
53
- const tet_count = tetrahedral_mesh_find_tets_attached_to_vertex(
54
- scratch_tets, 0, mesh, vertex_id
55
- );
56
84
 
57
85
  if (tet_count === 0) return false;
58
86
 
@@ -8,15 +8,24 @@
8
8
  * external surface (which usually represents some geometric constraint
9
9
  * the caller wants preserved).
10
10
  *
11
- * Cost: O(N) over the live tets, same as
11
+ * Cost without `vertex_to_tets_map`: O(N) over the live tets, same as
12
12
  * {@link tetrahedral_mesh_find_tets_attached_to_vertex} which it shares
13
- * the same scan structure with. For repeated calls over many vertices,
14
- * caller should precompute a boundary bitset rather than calling this in
15
- * a loop.
13
+ * the same scan structure with.
14
+ *
15
+ * Cost with `vertex_to_tets_map`: O(deg(vertex)) — usually a small
16
+ * constant. For repeated calls over many vertices in a tight loop
17
+ * (e.g. a sliver-removal pass), build the map once via
18
+ * {@link tetrahedral_mesh_build_vertex_to_tets_map} and pass it in.
19
+ *
20
+ * Note: boundary status is invariant under interior 2-3 / 3-2 flips, so
21
+ * a once-per-pass cache stays valid for boundary queries even as the
22
+ * pass commits flips, as long as a freshly-snapshotted cache is built
23
+ * for each NEW pass.
16
24
  *
17
25
  * @param {TetrahedralMesh} mesh
18
26
  * @param {number} vertex_id
27
+ * @param {Map<number, number[]>} [vertex_to_tets_map] optional cache
19
28
  * @returns {boolean}
20
29
  */
21
- export function tetrahedral_mesh_vertex_is_boundary(mesh: TetrahedralMesh, vertex_id: number): boolean;
30
+ export function tetrahedral_mesh_vertex_is_boundary(mesh: TetrahedralMesh, vertex_id: number, vertex_to_tets_map?: Map<number, number[]>): boolean;
22
31
  //# sourceMappingURL=tetrahedral_mesh_vertex_is_boundary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tetrahedral_mesh_vertex_is_boundary.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,sFAHW,MAAM,GACJ,OAAO,CAiCnB"}
1
+ {"version":3,"file":"tetrahedral_mesh_vertex_is_boundary.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,sFAJW,MAAM,uBACN,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC,GACnB,OAAO,CAkEnB"}
@@ -11,20 +11,62 @@ import { INVALID_NEIGHBOUR } from "./TetrahedralMesh.js";
11
11
  * external surface (which usually represents some geometric constraint
12
12
  * the caller wants preserved).
13
13
  *
14
- * Cost: O(N) over the live tets, same as
14
+ * Cost without `vertex_to_tets_map`: O(N) over the live tets, same as
15
15
  * {@link tetrahedral_mesh_find_tets_attached_to_vertex} which it shares
16
- * the same scan structure with. For repeated calls over many vertices,
17
- * caller should precompute a boundary bitset rather than calling this in
18
- * a loop.
16
+ * the same scan structure with.
17
+ *
18
+ * Cost with `vertex_to_tets_map`: O(deg(vertex)) — usually a small
19
+ * constant. For repeated calls over many vertices in a tight loop
20
+ * (e.g. a sliver-removal pass), build the map once via
21
+ * {@link tetrahedral_mesh_build_vertex_to_tets_map} and pass it in.
22
+ *
23
+ * Note: boundary status is invariant under interior 2-3 / 3-2 flips, so
24
+ * a once-per-pass cache stays valid for boundary queries even as the
25
+ * pass commits flips, as long as a freshly-snapshotted cache is built
26
+ * for each NEW pass.
19
27
  *
20
28
  * @param {TetrahedralMesh} mesh
21
29
  * @param {number} vertex_id
30
+ * @param {Map<number, number[]>} [vertex_to_tets_map] optional cache
22
31
  * @returns {boolean}
23
32
  */
24
- export function tetrahedral_mesh_vertex_is_boundary(mesh, vertex_id) {
33
+ export function tetrahedral_mesh_vertex_is_boundary(mesh, vertex_id, vertex_to_tets_map) {
25
34
  assert.defined(mesh, 'mesh');
26
35
  assert.isNonNegativeInteger(vertex_id, 'vertex_id');
27
36
 
37
+ if (vertex_to_tets_map !== undefined) {
38
+ const tets = vertex_to_tets_map.get(vertex_id);
39
+ if (tets === undefined) return false;
40
+
41
+ for (let ti = 0; ti < tets.length; ti++) {
42
+ const tet = tets[ti];
43
+ // Tets in the cache may have been deleted since it was built.
44
+ if (!mesh.exists(tet)) continue;
45
+
46
+ // Find the slot of vertex_id in this tet — present by
47
+ // construction unless a flip re-used the tet ID with
48
+ // different vertices, in which case skip.
49
+ let v_slot = -1;
50
+ for (let i = 0; i < 4; i++) {
51
+ if (mesh.getVertexIndex(tet, i) === vertex_id) {
52
+ v_slot = i;
53
+ break;
54
+ }
55
+ }
56
+ if (v_slot < 0) continue;
57
+
58
+ // The 3 faces containing vertex_id are the ones NOT opposite v_slot.
59
+ for (let j = 0; j < 4; j++) {
60
+ if (j === v_slot) continue;
61
+ if (mesh.getNeighbour(tet, j) === INVALID_NEIGHBOUR) {
62
+ return true;
63
+ }
64
+ }
65
+ }
66
+ return false;
67
+ }
68
+
69
+ // Slow path: scan every live tet.
28
70
  let is_boundary = false;
29
71
 
30
72
  mesh.forEach((tet, m) => {
@@ -66,6 +66,17 @@ export class BinaryElementPool implements Iterable<number> {
66
66
  * @private
67
67
  */
68
68
  private __capacity;
69
+ /**
70
+ * Occupancy index: bit `id` is 1 when slot `id` is allocated, 0 when
71
+ * free. Lets {@link is_allocated} answer in O(1) instead of scanning
72
+ * {@link __free}. The {@link __free} stack remains the allocator; this
73
+ * is purely a membership accelerator kept in lockstep with it.
74
+ * `preventShrink` stops the bitset reallocating smaller when top slots
75
+ * are cleared — its capacity tracks the pool, not the live set.
76
+ * @type {BitSet}
77
+ * @private
78
+ */
79
+ private __occupancy;
69
80
  /**
70
81
  *
71
82
  * @param {ArrayBuffer} buffer
@@ -193,6 +204,14 @@ export class BinaryElementPool implements Iterable<number> {
193
204
  * @param {BinaryElementPool} other
194
205
  */
195
206
  copy(other: BinaryElementPool): void;
207
+ /**
208
+ * Rebuild the occupancy index from `__size` and the current free set:
209
+ * every id in `[0, size)` is allocated except those held in `__free`.
210
+ * Used after {@link copy}, where the data buffer and free set are adopted
211
+ * wholesale.
212
+ * @private
213
+ */
214
+ private __rebuild_occupancy_from_free;
196
215
  /**
197
216
  * Used for type checking
198
217
  * @readonly
@@ -1 +1 @@
1
- {"version":3,"file":"BinaryElementPool.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/geom/3d/topology/struct/binary/BinaryElementPool.js"],"names":[],"mappings":"AA2BA;;;GAGG;AACH,mDAFyB,MAAM;IA0B3B;;;;;OAKG;IACH,uBAJW,MAAM,qBACN,MAAM,sBACN,OAAO,EAkDjB;IA5ED;;;;OAIG;IACH,eAAY;IAEZ;;;;;OAKG;IACH,uBAAmB;IAEnB;;;;OAIG;IACH,eAAW;IAeP;;;;OAIG;IACH,oBAA4B;IAG5B;;;;OAIG;IACH,sBAA8F;IAC9F;;;;OAIG;IACH,qBAAsD;IACtD;;;;OAIG;IACH,sBAAwD;IACxD;;;;OAIG;IACH,uBAA0D;IAC1D,oBAAiD;IAEjD;;;;OAIG;IACH,mBAAkC;IAItC;;;;OAIG;IACH,wBAHW,WAAW,2BACX,MAAM,QAsBhB;IAED;;;OAGG;IACH,+BAEC;IAED;;;OAGG;IACH,wBAEC;IAED;;;;OAIG;IACH,mBAEC;IAED;;;OAGG;IACH,uBAEC;IAED;;;OAGG;IACH,uBAEC;IAGD;;;OAGG;IACH,+BAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;OAEG;IACH,aAEC;IAED;;;;OAIG;IACH,oBAHW,MAAM,GACL,MAAM,CAMjB;IAED;;;;;OAKG;IACH,iBAHW,MAAM,GACL,MAAM,CAIjB;IAED;;;;OAIG;IACH,iBAHW,MAAM,GACL,OAAO,CAsBlB;IAED;;;;OAIG;IACH,uBAwBC;IAED;;;;OAIG;IACH,wBAQC;IAED;;;OAGG;IACH,0BAFW,MAAM,QAMhB;IAGD;;;OAGG;IACH,YAFY,MAAM,CAqBjB;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACL,MAAM,CAcjB;IAED;;;;;OAKG;IACH,QAHW,MAAM,KACN,MAAM,QAiBhB;IAED;;;;OAIG;IACH,YAFW,MAAM,QAYhB;IAED;;OAEG;IACH,uBAEC;IAED;;;;;OAKG;IACH,mBAFW,MAAM,QAQhB;IAED;;;OAGG;IACH,cAGC;IAED;;;OAGG;IACH,YAFW,iBAAiB,QA0B3B;IAoBL;;;;OAIG;IACH,8BAFU,OAAO,CAE8B;IAvB3C;;;OAGG;IACH,qBAFY,UAAU,MAAM,CAAC,CAa5B;CACJ"}
1
+ {"version":3,"file":"BinaryElementPool.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/geom/3d/topology/struct/binary/BinaryElementPool.js"],"names":[],"mappings":"AA4BA;;;GAGG;AACH,mDAFyB,MAAM;IA0B3B;;;;;OAKG;IACH,uBAJW,MAAM,qBACN,MAAM,sBACN,OAAO,EA+DjB;IAzFD;;;;OAIG;IACH,eAAY;IAEZ;;;;;OAKG;IACH,uBAAmB;IAEnB;;;;OAIG;IACH,eAAW;IAeP;;;;OAIG;IACH,oBAA4B;IAG5B;;;;OAIG;IACH,sBAA8F;IAC9F;;;;OAIG;IACH,qBAAsD;IACtD;;;;OAIG;IACH,sBAAwD;IACxD;;;;OAIG;IACH,uBAA0D;IAC1D,oBAAiD;IAEjD;;;;OAIG;IACH,mBAAkC;IAElC;;;;;;;;;OASG;IACH,oBAA8C;IAKlD;;;;OAIG;IACH,wBAHW,WAAW,2BACX,MAAM,QA8BhB;IAED;;;OAGG;IACH,+BAEC;IAED;;;OAGG;IACH,wBAEC;IAED;;;;OAIG;IACH,mBAEC;IAED;;;OAGG;IACH,uBAEC;IAED;;;OAGG;IACH,uBAEC;IAGD;;;OAGG;IACH,+BAEC;IAED;;;OAGG;IACH,iCAEC;IAED;;OAEG;IACH,aAEC;IAED;;;;OAIG;IACH,oBAHW,MAAM,GACL,MAAM,CAMjB;IAED;;;;;OAKG;IACH,iBAHW,MAAM,GACL,MAAM,CAIjB;IAED;;;;OAIG;IACH,iBAHW,MAAM,GACL,OAAO,CAYlB;IAED;;;;OAIG;IACH,uBA2BC;IAED;;;;OAIG;IACH,wBAQC;IAED;;;OAGG;IACH,0BAFW,MAAM,QAMhB;IAGD;;;OAGG;IACH,YAFY,MAAM,CAyBjB;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACL,MAAM,CAmBjB;IAED;;;;;OAKG;IACH,QAHW,MAAM,KACN,MAAM,QAiBhB;IAED;;;;OAIG;IACH,YAFW,MAAM,QAchB;IAED;;OAEG;IACH,uBAOC;IAED;;;;;OAKG;IACH,mBAFW,MAAM,QAchB;IAED;;;OAGG;IACH,cAIC;IAED;;;OAGG;IACH,YAFW,iBAAiB,QA4B3B;IAED;;;;;;OAMG;IACH,sCAaC;IAoBL;;;;OAIG;IACH,8BAFU,OAAO,CAE8B;IAvB3C;;;OAGG;IACH,qBAFY,UAAU,MAAM,CAAC,CAa5B;CACJ"}
@@ -1,5 +1,6 @@
1
1
  import { assert } from "../../../../../assert.js";
2
2
  import { align_4 } from "../../../../../binary/align_4.js";
3
+ import { BitSet } from "../../../../../binary/BitSet.js";
3
4
  import { makeArrayBuffer } from "../../../../../binary/makeArrayBuffer.js";
4
5
  import { array_swap } from "../../../../../collection/array/array_swap.js";
5
6
  import { array_buffer_copy } from "../../../../../collection/array/typed/array_buffer_copy.js";
@@ -107,6 +108,19 @@ export class BinaryElementPool {
107
108
  */
108
109
  this.__capacity = initial_capacity;
109
110
 
111
+ /**
112
+ * Occupancy index: bit `id` is 1 when slot `id` is allocated, 0 when
113
+ * free. Lets {@link is_allocated} answer in O(1) instead of scanning
114
+ * {@link __free}. The {@link __free} stack remains the allocator; this
115
+ * is purely a membership accelerator kept in lockstep with it.
116
+ * `preventShrink` stops the bitset reallocating smaller when top slots
117
+ * are cleared — its capacity tracks the pool, not the live set.
118
+ * @type {BitSet}
119
+ * @private
120
+ */
121
+ this.__occupancy = new BitSet(this.__capacity);
122
+ this.__occupancy.preventShrink();
123
+
110
124
  }
111
125
 
112
126
  /**
@@ -134,6 +148,14 @@ export class BinaryElementPool {
134
148
  // drop free slots
135
149
  this.__free_pointer = 0;
136
150
  this.__size = allocated_record_count;
151
+
152
+ // Rebuild occupancy for the adopted buffer: the free set is dropped, so
153
+ // exactly [0, allocated_record_count) is allocated.
154
+ this.__occupancy = new BitSet(capacity);
155
+ this.__occupancy.preventShrink();
156
+ if (allocated_record_count > 0) {
157
+ this.__occupancy.setRange(0, allocated_record_count - 1);
158
+ }
137
159
  }
138
160
 
139
161
  /**
@@ -235,18 +257,8 @@ export class BinaryElementPool {
235
257
  return false;
236
258
  }
237
259
 
238
- const pointer = this.__free_pointer;
239
-
240
- for (let i = 0; i < pointer; i++) {
241
- const _id = this.__free[i];
242
-
243
- if (id === _id) {
244
- // found in unallocated set
245
- return false;
246
- }
247
- }
248
-
249
- return true;
260
+ // O(1) occupancy bit read.
261
+ return this.__occupancy.get(id);
250
262
  }
251
263
 
252
264
  /**
@@ -278,6 +290,9 @@ export class BinaryElementPool {
278
290
  typed_array_copy(old_data_uint8, this.__data_uint8);
279
291
 
280
292
  this.__capacity = new_capacity;
293
+
294
+ // The bitset self-manages capacity on set(); preventShrink keeps it from
295
+ // dropping below the used region on clears. Nothing to do here.
281
296
  }
282
297
 
283
298
  /**
@@ -314,7 +329,9 @@ export class BinaryElementPool {
314
329
  if (this.__free_pointer > 0) {
315
330
  // get unused slot
316
331
  this.__free_pointer--;
317
- return this.__free[this.__free_pointer];
332
+ const id = this.__free[this.__free_pointer];
333
+ this.__occupancy.set(id, true);
334
+ return id;
318
335
  }
319
336
 
320
337
  // allocate new
@@ -328,6 +345,8 @@ export class BinaryElementPool {
328
345
 
329
346
  // assert.greaterThan(this.__data_buffer.byteLength, result * this.__item_size, 'memory underflow');
330
347
 
348
+ this.__occupancy.set(result, true);
349
+
331
350
  return result;
332
351
  }
333
352
 
@@ -347,6 +366,11 @@ export class BinaryElementPool {
347
366
 
348
367
  // assert.greaterThanOrEqual(this.__data_buffer.byteLength, (offset + count) * this.__item_size, 'memory underflow');
349
368
 
369
+ // Mark the whole range allocated.
370
+ if (count > 0) {
371
+ this.__occupancy.setRange(offset, offset + count - 1);
372
+ }
373
+
350
374
  return offset;
351
375
  }
352
376
 
@@ -382,11 +406,13 @@ export class BinaryElementPool {
382
406
  if (id === this.__size - 1) {
383
407
  // releasing item at the end of the reserved region, don't have to push it into free set
384
408
  this.__size--;
409
+ this.__occupancy.set(id, false);
385
410
  } else if (id >= this.__size) {
386
411
  // do nothing, just throw it away
387
412
  // this should never happen
388
413
  } else {
389
414
  this.__free[this.__free_pointer++] = id;
415
+ this.__occupancy.set(id, false);
390
416
  }
391
417
  }
392
418
 
@@ -395,6 +421,11 @@ export class BinaryElementPool {
395
421
  */
396
422
  clear_free_set() {
397
423
  this.__free_pointer = 0;
424
+
425
+ // With the free set empty, every slot in [0, size) is allocated again.
426
+ if (this.__size > 0) {
427
+ this.__occupancy.setRange(0, this.__size - 1);
428
+ }
398
429
  }
399
430
 
400
431
  /**
@@ -409,6 +440,12 @@ export class BinaryElementPool {
409
440
 
410
441
  this.__size = new_size;
411
442
  this.__free_pointer = 0;
443
+
444
+ // Free set discarded: [0, new_size) is the live region with no holes.
445
+ this.__occupancy.reset();
446
+ if (new_size > 0) {
447
+ this.__occupancy.setRange(0, new_size - 1);
448
+ }
412
449
  }
413
450
 
414
451
  /**
@@ -418,6 +455,7 @@ export class BinaryElementPool {
418
455
  clear() {
419
456
  this.__size = 0;
420
457
  this.__free_pointer = 0;
458
+ this.__occupancy.reset();
421
459
  }
422
460
 
423
461
  /**
@@ -448,6 +486,30 @@ export class BinaryElementPool {
448
486
 
449
487
  this.__free_pointer = other.__free_pointer;
450
488
  this.__free = other.__free.slice();
489
+
490
+ this.__rebuild_occupancy_from_free();
491
+ }
492
+
493
+ /**
494
+ * Rebuild the occupancy index from `__size` and the current free set:
495
+ * every id in `[0, size)` is allocated except those held in `__free`.
496
+ * Used after {@link copy}, where the data buffer and free set are adopted
497
+ * wholesale.
498
+ * @private
499
+ */
500
+ __rebuild_occupancy_from_free() {
501
+ this.__occupancy = new BitSet(Math.max(this.__capacity, this.__size));
502
+ this.__occupancy.preventShrink();
503
+
504
+ if (this.__size > 0) {
505
+ this.__occupancy.setRange(0, this.__size - 1);
506
+ }
507
+
508
+ const free = this.__free;
509
+ const pointer = this.__free_pointer;
510
+ for (let i = 0; i < pointer; i++) {
511
+ this.__occupancy.set(free[i], false);
512
+ }
451
513
  }
452
514
 
453
515
  /**
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Compute face normal for a triangle
3
- * @param {number[]|Float32Array} result X,Y,Z normalized vector is written here
3
+ * @param {number[]|Float32Array|Float64Array} result X,Y,Z normalized vector is written here
4
4
  * @param {number} result_offset offset into result array where to start writing
5
5
  * @param {number} a_x
6
6
  * @param {number} a_y
@@ -12,5 +12,5 @@
12
12
  * @param {number} c_y
13
13
  * @param {number} c_z
14
14
  */
15
- export function v3_compute_triangle_normal(result: number[] | Float32Array, result_offset: number, a_x: number, a_y: number, a_z: number, b_x: number, b_y: number, b_z: number, c_x: number, c_y: number, c_z: number): void;
15
+ export function v3_compute_triangle_normal(result: number[] | Float32Array | Float64Array, result_offset: number, a_x: number, a_y: number, a_z: number, b_x: number, b_y: number, b_z: number, c_x: number, c_y: number, c_z: number): void;
16
16
  //# sourceMappingURL=v3_compute_triangle_normal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v3_compute_triangle_normal.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/triangle/v3_compute_triangle_normal.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,mDAZW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,QA0ChB"}
1
+ {"version":3,"file":"v3_compute_triangle_normal.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/triangle/v3_compute_triangle_normal.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,mDAZW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,QA0ChB"}
@@ -2,7 +2,7 @@ import { v3_length_sqr } from "../../vec3/v3_length_sqr.js";
2
2
 
3
3
  /**
4
4
  * Compute face normal for a triangle
5
- * @param {number[]|Float32Array} result X,Y,Z normalized vector is written here
5
+ * @param {number[]|Float32Array|Float64Array} result X,Y,Z normalized vector is written here
6
6
  * @param {number} result_offset offset into result array where to start writing
7
7
  * @param {number} a_x
8
8
  * @param {number} a_y
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  *
3
- * @param {number[]|Float32Array} a
3
+ * @param {number[]|Float32Array|Float64Array} a
4
4
  * @param {number} a_offset
5
- * @param {number[]|Float32Array} b
5
+ * @param {number[]|Float32Array|Float64Array} b
6
6
  * @param {number} b_offset
7
7
  * @returns {number}
8
8
  */
9
- export function v3_dot_array_array(a: number[] | Float32Array, a_offset: number, b: number[] | Float32Array, b_offset: number): number;
9
+ export function v3_dot_array_array(a: number[] | Float32Array | Float64Array, a_offset: number, b: number[] | Float32Array | Float64Array, b_offset: number): number;
10
10
  //# sourceMappingURL=v3_dot_array_array.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v3_dot_array_array.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_dot_array_array.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,sCANW,MAAM,EAAE,GAAC,YAAY,YACrB,MAAM,KACN,MAAM,EAAE,GAAC,YAAY,YACrB,MAAM,GACJ,MAAM,CAgBlB"}
1
+ {"version":3,"file":"v3_dot_array_array.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_dot_array_array.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,sCANW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,YAClC,MAAM,KACN,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,YAClC,MAAM,GACJ,MAAM,CAgBlB"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  *
3
- * @param {number[]|Float32Array} a
3
+ * @param {number[]|Float32Array|Float64Array} a
4
4
  * @param {number} a_offset
5
- * @param {number[]|Float32Array} b
5
+ * @param {number[]|Float32Array|Float64Array} b
6
6
  * @param {number} b_offset
7
7
  * @returns {number}
8
8
  */
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  *
3
- * @param {number[]|Float32Array} result
3
+ * @param {number[]|Float32Array|Float64Array} result
4
4
  * @param {number} result_offset
5
- * @param {number[]|Float32Array} input
5
+ * @param {number[]|Float32Array|Float64Array} input
6
6
  * @param {number} input_offset
7
7
  */
8
- export function v3_negate_array(result: number[] | Float32Array, result_offset: number, input: number[] | Float32Array, input_offset: number): void;
8
+ export function v3_negate_array(result: number[] | Float32Array | Float64Array, result_offset: number, input: number[] | Float32Array | Float64Array, input_offset: number): void;
9
9
  //# sourceMappingURL=v3_negate_array.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"v3_negate_array.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_negate_array.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wCALW,MAAM,EAAE,GAAC,YAAY,iBACrB,MAAM,SACN,MAAM,EAAE,GAAC,YAAY,gBACrB,MAAM,QAUhB"}
1
+ {"version":3,"file":"v3_negate_array.d.ts","sourceRoot":"","sources":["../../../../../src/core/geom/vec3/v3_negate_array.js"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wCALW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,MAAM,SACN,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,gBAClC,MAAM,QAUhB"}
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  *
3
- * @param {number[]|Float32Array} result
3
+ * @param {number[]|Float32Array|Float64Array} result
4
4
  * @param {number} result_offset
5
- * @param {number[]|Float32Array} input
5
+ * @param {number[]|Float32Array|Float64Array} input
6
6
  * @param {number} input_offset
7
7
  */
8
8
  export function v3_negate_array(result, result_offset, input, input_offset) {