@woosh/meep-engine 2.138.20 → 2.139.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 (491) hide show
  1. package/package.json +1 -1
  2. package/src/core/collection/PairUint32Map.d.ts +100 -0
  3. package/src/core/collection/PairUint32Map.d.ts.map +1 -0
  4. package/src/core/collection/PairUint32Map.js +321 -0
  5. package/src/core/collection/Uint32Map.d.ts +119 -0
  6. package/src/core/collection/Uint32Map.d.ts.map +1 -0
  7. package/src/core/collection/Uint32Map.js +345 -0
  8. package/src/core/collection/array/array_shuffle.d.ts +10 -3
  9. package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
  10. package/src/core/collection/array/array_shuffle.js +27 -22
  11. package/src/core/collection/heap/FibonacciHeap.d.ts +195 -0
  12. package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -0
  13. package/src/core/collection/heap/FibonacciHeap.js +586 -0
  14. package/src/core/collection/heap/Uint32Heap.js +1 -1
  15. package/src/core/collection/heap/Uint32Heap4.d.ts +169 -0
  16. package/src/core/collection/heap/Uint32Heap4.d.ts.map +1 -0
  17. package/src/core/collection/heap/Uint32Heap4.js +490 -0
  18. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts +27 -0
  19. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts.map +1 -0
  20. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +88 -0
  21. package/src/core/geom/3d/shape/BoxShape3D.d.ts +61 -0
  22. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -0
  23. package/src/core/geom/3d/shape/BoxShape3D.js +158 -0
  24. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +11 -0
  25. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  26. package/src/core/geom/3d/shape/CapsuleShape3D.js +12 -0
  27. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +37 -9
  28. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
  29. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -98
  30. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +10 -0
  31. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
  32. package/src/core/geom/3d/shape/UnitSphereShape3D.js +11 -0
  33. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts +61 -0
  34. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -0
  35. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +148 -0
  36. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts +39 -0
  37. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts.map +1 -0
  38. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +147 -0
  39. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts +15 -0
  40. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts.map +1 -0
  41. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +22 -0
  42. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts +2 -0
  43. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts.map +1 -0
  44. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +673 -0
  45. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts +26 -0
  46. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -0
  47. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +222 -0
  48. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts +34 -0
  49. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts.map +1 -0
  50. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -0
  51. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts +36 -0
  52. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts.map +1 -0
  53. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -0
  54. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts +33 -0
  55. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts.map +1 -0
  56. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -0
  57. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts +68 -0
  58. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -0
  59. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +365 -0
  60. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +31 -0
  61. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -0
  62. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +112 -0
  63. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +22 -0
  64. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -0
  65. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +55 -0
  66. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts +32 -0
  67. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts.map +1 -0
  68. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -0
  69. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +22 -0
  70. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
  71. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +49 -0
  72. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +134 -0
  73. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
  74. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +276 -3
  75. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +17 -0
  76. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -0
  77. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +135 -0
  78. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts +14 -0
  79. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts.map +1 -0
  80. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +177 -0
  81. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.d.ts.map +1 -1
  82. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +20 -4
  83. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
  84. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +5 -3
  85. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
  86. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +9 -0
  87. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.d.ts.map +1 -1
  88. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -45
  89. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.d.ts.map +1 -1
  90. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.js +7 -1
  91. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts +8 -6
  92. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts.map +1 -1
  93. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +8 -6
  94. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts +22 -0
  95. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts.map +1 -0
  96. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +73 -0
  97. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
  98. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +51 -1
  99. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts +10 -0
  100. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts.map +1 -0
  101. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -0
  102. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts +28 -0
  103. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -0
  104. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +227 -0
  105. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts +13 -0
  106. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts.map +1 -0
  107. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -0
  108. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts +11 -0
  109. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts.map +1 -0
  110. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +20 -0
  111. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts +20 -0
  112. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts.map +1 -0
  113. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +38 -0
  114. package/src/core/graph/csr/CSRGraph.d.ts +168 -0
  115. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -0
  116. package/src/core/graph/csr/CSRGraph.js +319 -0
  117. package/src/core/graph/metis/cluster_mesh_metis.d.ts +12 -0
  118. package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -1
  119. package/src/core/graph/metis/cluster_mesh_metis.js +12 -0
  120. package/src/core/graph/metis/metis.d.ts +19 -0
  121. package/src/core/graph/metis/metis.d.ts.map +1 -1
  122. package/src/core/graph/metis/metis.js +20 -0
  123. package/src/core/graph/metis/metis_cluster_bs.d.ts +11 -0
  124. package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -1
  125. package/src/core/graph/metis/metis_cluster_bs.js +11 -0
  126. package/src/core/graph/metis/metis_options.d.ts +17 -2
  127. package/src/core/graph/metis/metis_options.d.ts.map +1 -1
  128. package/src/core/graph/metis/metis_options.js +17 -2
  129. package/src/core/graph/metis/native/MetisGraph.d.ts +144 -0
  130. package/src/core/graph/metis/native/MetisGraph.d.ts.map +1 -0
  131. package/src/core/graph/metis/native/MetisGraph.js +212 -0
  132. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts +72 -0
  133. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts.map +1 -0
  134. package/src/core/graph/metis/native/bisection/BisectionScratch.js +101 -0
  135. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts +37 -0
  136. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts.map +1 -0
  137. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -0
  138. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts +15 -0
  139. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts.map +1 -0
  140. package/src/core/graph/metis/native/bisection/compute_2way_params.js +84 -0
  141. package/src/core/graph/metis/native/bisection/fm_2way.d.ts +30 -0
  142. package/src/core/graph/metis/native/bisection/fm_2way.d.ts.map +1 -0
  143. package/src/core/graph/metis/native/bisection/fm_2way.js +290 -0
  144. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts +23 -0
  145. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts.map +1 -0
  146. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -0
  147. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts +28 -0
  148. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -0
  149. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -0
  150. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts +20 -0
  151. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts.map +1 -0
  152. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -0
  153. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts +24 -0
  154. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts.map +1 -0
  155. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -0
  156. package/src/core/graph/metis/native/coarsen/match_shem.d.ts +41 -0
  157. package/src/core/graph/metis/native/coarsen/match_shem.d.ts.map +1 -0
  158. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -0
  159. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts +24 -0
  160. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts.map +1 -0
  161. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -0
  162. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts +29 -0
  163. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts.map +1 -0
  164. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -0
  165. package/src/core/graph/metis/native/metis_partition_kway.d.ts +41 -0
  166. package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -0
  167. package/src/core/graph/metis/native/metis_partition_kway.js +126 -0
  168. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts +62 -0
  169. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts.map +1 -0
  170. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.js +261 -0
  171. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts +45 -0
  172. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts.map +1 -0
  173. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -0
  174. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts +18 -0
  175. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -0
  176. package/src/core/graph/metis/native/refine/compute_kway_params.js +138 -0
  177. package/src/core/graph/metis/native/refine/fm_kway.d.ts +63 -0
  178. package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -0
  179. package/src/core/graph/metis/native/refine/fm_kway.js +462 -0
  180. package/src/core/graph/metis/native/refine/project_kway.d.ts +22 -0
  181. package/src/core/graph/metis/native/refine/project_kway.d.ts.map +1 -0
  182. package/src/core/graph/metis/native/refine/project_kway.js +43 -0
  183. package/src/core/graph/metis/native/refine/refine_kway.d.ts +34 -0
  184. package/src/core/graph/metis/native/refine/refine_kway.d.ts.map +1 -0
  185. package/src/core/graph/metis/native/refine/refine_kway.js +43 -0
  186. package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts +2 -2
  187. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +2 -2
  188. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +6 -4
  189. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -1
  190. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +69 -23
  191. package/src/engine/EngineHarness.d.ts +3 -1
  192. package/src/engine/EngineHarness.d.ts.map +1 -1
  193. package/src/engine/EngineHarness.js +3 -0
  194. package/src/engine/control/first-person/DESIGN.md +30 -6
  195. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -0
  196. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +102 -9
  197. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  198. package/src/engine/control/first-person/FirstPersonPlayerController.js +38 -3
  199. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +533 -4
  200. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  201. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +315 -6
  202. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +220 -22
  203. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
  204. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +858 -241
  205. package/src/engine/control/first-person/TODO.md +127 -0
  206. package/src/engine/control/first-person/abilities/Ability.d.ts +101 -0
  207. package/src/engine/control/first-person/abilities/Ability.d.ts.map +1 -0
  208. package/src/engine/control/first-person/abilities/Ability.js +119 -0
  209. package/src/engine/control/first-person/abilities/AbilitySet.d.ts +86 -0
  210. package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -0
  211. package/src/engine/control/first-person/abilities/AbilitySet.js +185 -0
  212. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +62 -0
  213. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -0
  214. package/src/engine/control/first-person/abilities/LedgeGrab.js +199 -0
  215. package/src/engine/control/first-person/abilities/Mantle.d.ts +45 -0
  216. package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -0
  217. package/src/engine/control/first-person/abilities/Mantle.js +188 -0
  218. package/src/engine/control/first-person/abilities/Slide.d.ts +33 -0
  219. package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -0
  220. package/src/engine/control/first-person/abilities/Slide.js +158 -0
  221. package/src/engine/control/first-person/abilities/WallJump.d.ts +45 -0
  222. package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -0
  223. package/src/engine/control/first-person/abilities/WallJump.js +131 -0
  224. package/src/engine/control/first-person/abilities/WallRun.d.ts +44 -0
  225. package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -0
  226. package/src/engine/control/first-person/abilities/WallRun.js +180 -0
  227. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts +49 -0
  228. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts.map +1 -0
  229. package/src/engine/control/first-person/composer/EyeOffsetStack.js +60 -0
  230. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts +100 -0
  231. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts.map +1 -0
  232. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.js +133 -0
  233. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts +10 -0
  234. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts.map +1 -0
  235. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -0
  236. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts +61 -0
  237. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts.map +1 -0
  238. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js +109 -0
  239. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts +40 -0
  240. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts.map +1 -0
  241. package/src/engine/control/first-person/mastery/MasteryEvaluator.js +45 -0
  242. package/src/engine/control/first-person/mastery/MasteryScore.d.ts +68 -0
  243. package/src/engine/control/first-person/mastery/MasteryScore.d.ts.map +1 -0
  244. package/src/engine/control/first-person/mastery/MasteryScore.js +100 -0
  245. package/src/engine/control/first-person/mastery/MasterySet.d.ts +60 -0
  246. package/src/engine/control/first-person/mastery/MasterySet.d.ts.map +1 -0
  247. package/src/engine/control/first-person/mastery/MasterySet.js +86 -0
  248. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +58 -0
  249. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -0
  250. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +83 -0
  251. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +69 -0
  252. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -0
  253. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +109 -0
  254. package/src/engine/control/first-person/math/Spring.d.ts +56 -0
  255. package/src/engine/control/first-person/math/Spring.d.ts.map +1 -0
  256. package/src/engine/control/first-person/math/Spring.js +71 -0
  257. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts +26 -0
  258. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts.map +1 -0
  259. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -0
  260. package/src/engine/control/first-person/math/computeMassRatios.d.ts +35 -0
  261. package/src/engine/control/first-person/math/computeMassRatios.d.ts.map +1 -0
  262. package/src/engine/control/first-person/math/computeMassRatios.js +44 -0
  263. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +31 -1
  264. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -1
  265. package/src/engine/control/first-person/pose/FirstPersonPose.js +49 -3
  266. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts +7 -0
  267. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts.map +1 -0
  268. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -0
  269. package/src/engine/control/first-person/prototype_first_person_controller.js +550 -119
  270. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +58 -0
  271. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -0
  272. package/src/engine/control/first-person/sensors/FirstPersonSensors.js +77 -0
  273. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +80 -0
  274. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -0
  275. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +196 -0
  276. package/src/engine/control/first-person/test/buildTestPlayer.d.ts +20 -0
  277. package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -0
  278. package/src/engine/control/first-person/test/buildTestPlayer.js +28 -0
  279. package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -2
  280. package/src/engine/graphics/ecs/light/Light.d.ts.map +1 -1
  281. package/src/engine/graphics/ecs/light/Light.js +27 -0
  282. package/src/engine/graphics/ecs/light/LightSystem.js +1 -1
  283. package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
  284. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
  285. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -2
  286. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
  287. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
  288. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
  289. package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
  290. package/src/engine/navigation/grid/find_path_on_grid_astar.js +11 -2
  291. package/src/engine/navigation/mesh/bt_mesh_face_find_path.d.ts.map +1 -1
  292. package/src/engine/navigation/mesh/bt_mesh_face_find_path.js +11 -1
  293. package/src/engine/physics/PLAN.md +236 -0
  294. package/src/engine/physics/body/BodyStorage.d.ts +187 -0
  295. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -0
  296. package/src/engine/physics/body/BodyStorage.js +427 -0
  297. package/src/engine/physics/broadphase/PairList.d.ts +62 -0
  298. package/src/engine/physics/broadphase/PairList.d.ts.map +1 -0
  299. package/src/engine/physics/broadphase/PairList.js +97 -0
  300. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts +30 -0
  301. package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +1 -0
  302. package/src/engine/physics/broadphase/aabb_transform_oriented.js +93 -0
  303. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +16 -0
  304. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -0
  305. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +61 -0
  306. package/src/engine/physics/broadphase/generate_pairs.d.ts +38 -0
  307. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -0
  308. package/src/engine/physics/broadphase/generate_pairs.js +101 -0
  309. package/src/engine/physics/contact/ManifoldStore.d.ts +226 -0
  310. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -0
  311. package/src/engine/physics/contact/ManifoldStore.js +499 -0
  312. package/src/engine/physics/ecs/BodyKind.d.ts +23 -0
  313. package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -0
  314. package/src/engine/physics/ecs/BodyKind.js +24 -0
  315. package/src/engine/physics/ecs/Collider.d.ts +98 -0
  316. package/src/engine/physics/ecs/Collider.d.ts.map +1 -0
  317. package/src/engine/physics/ecs/Collider.js +136 -0
  318. package/src/engine/physics/ecs/ColliderFlags.d.ts +14 -0
  319. package/src/engine/physics/ecs/ColliderFlags.d.ts.map +1 -0
  320. package/src/engine/physics/ecs/ColliderFlags.js +15 -0
  321. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +58 -0
  322. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -0
  323. package/src/engine/physics/ecs/ColliderObserverSystem.js +103 -0
  324. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts +25 -0
  325. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts.map +1 -0
  326. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -0
  327. package/src/engine/physics/ecs/PhysicsEvents.d.ts +15 -0
  328. package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -0
  329. package/src/engine/physics/ecs/PhysicsEvents.js +16 -0
  330. package/src/engine/physics/ecs/PhysicsSystem.d.ts +520 -0
  331. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -0
  332. package/src/engine/physics/ecs/PhysicsSystem.js +1159 -0
  333. package/src/engine/physics/ecs/RigidBody.d.ts +197 -0
  334. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -0
  335. package/src/engine/physics/ecs/RigidBody.js +240 -0
  336. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +21 -0
  337. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -0
  338. package/src/engine/physics/ecs/RigidBodyFlags.js +22 -0
  339. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +28 -0
  340. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -0
  341. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +81 -0
  342. package/src/engine/physics/ecs/SleepState.d.ts +11 -0
  343. package/src/engine/physics/ecs/SleepState.d.ts.map +1 -0
  344. package/src/engine/physics/ecs/SleepState.js +12 -0
  345. package/src/engine/physics/events/ContactEventBuffer.d.ts +46 -0
  346. package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -0
  347. package/src/engine/physics/events/ContactEventBuffer.js +83 -0
  348. package/src/engine/physics/events/diff_manifolds.d.ts +25 -0
  349. package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -0
  350. package/src/engine/physics/events/diff_manifolds.js +50 -0
  351. package/src/engine/physics/fluid/FluidField.d.ts +294 -16
  352. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  353. package/src/engine/physics/fluid/FluidField.js +510 -66
  354. package/src/engine/physics/fluid/FluidSimulator.d.ts +188 -5
  355. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  356. package/src/engine/physics/fluid/FluidSimulator.js +455 -95
  357. package/src/engine/physics/fluid/SliceVisualiser.d.ts +29 -6
  358. package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
  359. package/src/engine/physics/fluid/SliceVisualiser.js +190 -165
  360. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +154 -0
  361. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -0
  362. package/src/engine/physics/fluid/ecs/FluidComponent.js +238 -0
  363. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +45 -0
  364. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts.map +1 -0
  365. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -0
  366. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +107 -0
  367. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts.map +1 -0
  368. package/src/engine/physics/fluid/ecs/FluidSystem.js +278 -0
  369. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +62 -1
  370. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
  371. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -6
  372. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +17 -4
  373. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
  374. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +105 -12
  375. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts +43 -0
  376. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -0
  377. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +210 -0
  378. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +62 -1
  379. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  380. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +302 -8
  381. package/src/engine/physics/fluid/prototype.js +102 -91
  382. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts +33 -0
  383. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +1 -0
  384. package/src/engine/physics/fluid/solver/optimal_sor_omega.js +41 -0
  385. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +20 -5
  386. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
  387. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +60 -38
  388. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +25 -4
  389. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
  390. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +93 -73
  391. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts +23 -0
  392. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -0
  393. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +60 -0
  394. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts +23 -0
  395. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts.map +1 -0
  396. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.js +68 -0
  397. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +30 -0
  398. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -0
  399. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +66 -0
  400. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts +26 -0
  401. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts.map +1 -0
  402. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -0
  403. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts +30 -0
  404. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts.map +1 -0
  405. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -0
  406. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +49 -0
  407. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -0
  408. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +126 -0
  409. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +93 -0
  410. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -0
  411. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +424 -0
  412. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +20 -0
  413. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +1 -0
  414. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +83 -0
  415. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +26 -0
  416. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -0
  417. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +70 -0
  418. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
  419. package/src/engine/physics/gjk/expanding_polytope_algorithm.js +8 -10
  420. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +29 -0
  421. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -0
  422. package/src/engine/physics/inertia/world_inverse_inertia.js +79 -0
  423. package/src/engine/physics/integration/integrate_position.d.ts +16 -0
  424. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -0
  425. package/src/engine/physics/integration/integrate_position.js +48 -0
  426. package/src/engine/physics/integration/integrate_velocity.d.ts +25 -0
  427. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -0
  428. package/src/engine/physics/integration/integrate_velocity.js +79 -0
  429. package/src/engine/physics/integration/quat_integrate.d.ts +27 -0
  430. package/src/engine/physics/integration/quat_integrate.d.ts.map +1 -0
  431. package/src/engine/physics/integration/quat_integrate.js +62 -0
  432. package/src/engine/physics/island/IslandBuilder.d.ts +167 -0
  433. package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -0
  434. package/src/engine/physics/island/IslandBuilder.js +411 -0
  435. package/src/engine/physics/island/union_find.d.ts +51 -0
  436. package/src/engine/physics/island/union_find.d.ts.map +1 -0
  437. package/src/engine/physics/island/union_find.js +76 -0
  438. package/src/engine/physics/narrowphase/PosedShape.d.ts +59 -0
  439. package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -0
  440. package/src/engine/physics/narrowphase/PosedShape.js +110 -0
  441. package/src/engine/physics/narrowphase/box_box_manifold.d.ts +32 -0
  442. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -0
  443. package/src/engine/physics/narrowphase/box_box_manifold.js +543 -0
  444. package/src/engine/physics/narrowphase/capsule_contacts.d.ts +122 -0
  445. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -0
  446. package/src/engine/physics/narrowphase/capsule_contacts.js +508 -0
  447. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +11 -0
  448. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -0
  449. package/src/engine/physics/narrowphase/narrowphase_step.js +382 -0
  450. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts +38 -0
  451. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -0
  452. package/src/engine/physics/narrowphase/sphere_box_contact.js +130 -0
  453. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +26 -0
  454. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -0
  455. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +51 -0
  456. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +83 -0
  457. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -0
  458. package/src/engine/physics/queries/PhysicsSurfacePoint.js +100 -0
  459. package/src/engine/physics/queries/raycast.d.ts +20 -0
  460. package/src/engine/physics/queries/raycast.d.ts.map +1 -0
  461. package/src/engine/physics/queries/raycast.js +249 -0
  462. package/src/engine/physics/solver/friction_cone.d.ts +16 -0
  463. package/src/engine/physics/solver/friction_cone.d.ts.map +1 -0
  464. package/src/engine/physics/solver/friction_cone.js +37 -0
  465. package/src/engine/physics/solver/solve_contacts.d.ts +36 -0
  466. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -0
  467. package/src/engine/physics/solver/solve_contacts.js +598 -0
  468. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts +0 -34
  469. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts.map +0 -1
  470. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.js +0 -66
  471. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts +0 -2
  472. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts.map +0 -1
  473. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.js +0 -54
  474. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts +0 -2
  475. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts.map +0 -1
  476. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.js +0 -26
  477. package/src/engine/ecs/components/Motion.d.ts +0 -21
  478. package/src/engine/ecs/components/Motion.d.ts.map +0 -1
  479. package/src/engine/ecs/components/Motion.js +0 -27
  480. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts +0 -20
  481. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts.map +0 -1
  482. package/src/engine/ecs/components/MotionSerializationAdapter.js +0 -26
  483. package/src/engine/ecs/systems/MotionSystem.d.ts +0 -9
  484. package/src/engine/ecs/systems/MotionSystem.d.ts.map +0 -1
  485. package/src/engine/ecs/systems/MotionSystem.js +0 -29
  486. package/src/engine/physics/fluid/Fluid.d.ts +0 -26
  487. package/src/engine/physics/fluid/Fluid.d.ts.map +0 -1
  488. package/src/engine/physics/fluid/Fluid.js +0 -221
  489. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts +0 -7
  490. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts.map +0 -1
  491. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.js +0 -8
@@ -0,0 +1,673 @@
1
+ /**
2
+ * prototype_tetrahedrize_mesh.js
3
+ *
4
+ * Drag-and-drop a GLTF/GLB file. Every mesh inside the scene is converted to a
5
+ * BinaryTopology, tetrahedralized via `compute_tetrahedral_mesh_from_surface`,
6
+ * and rendered as a pile of slightly shrunken tetrahedra so the volumetric
7
+ * structure is visible. Each input geometry is shown in its own solid colour
8
+ * to make them easy to tell apart.
9
+ *
10
+ * This module is intentionally self-contained — no engine harness, no ECS,
11
+ * just bare three.js + the tetrahedralization pipeline.
12
+ *
13
+ * Reference prototypes:
14
+ * - prototypeTetrahedraBuilder.js (tet mesh creation patterns)
15
+ * - prototypeMeshSimplification.js (raw three.js bootstrap, drop-file handling style)
16
+ * - prototypeBinaryTopology.js (BinaryTopology construction from indexed geometry)
17
+ */
18
+
19
+ import {
20
+ AmbientLight,
21
+ BufferAttribute,
22
+ BufferGeometry,
23
+ DirectionalLight,
24
+ Float32BufferAttribute,
25
+ Group,
26
+ Mesh,
27
+ MeshStandardMaterial,
28
+ PerspectiveCamera,
29
+ Scene,
30
+ Vector3 as ThreeVector3,
31
+ WebGLRenderer
32
+ } from "three";
33
+ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
34
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
35
+ import { BinaryTopology } from "../topology/struct/binary/BinaryTopology.js";
36
+ import {
37
+ bt_mesh_from_indexed_geometry
38
+ } from "../topology/struct/binary/io/bt_mesh_from_indexed_geometry.js";
39
+ import {
40
+ triangle_mesh_compute_signed_volume
41
+ } from "../triangle/triangle_mesh_compute_signed_volume.js";
42
+ import { compute_tetrahedral_mesh_from_surface } from "./compute_tetrahedral_mesh_from_surface.js";
43
+ import { compute_tetrahedron_quality } from "./compute_tetrahedron_quality.js";
44
+ import { compute_tetrahedron_volume } from "./compute_tetrahedron_volume.js";
45
+ import { tetrahedral_mesh_improve_quality } from "./tetrahedral_mesh_improve_quality.js";
46
+ import { TetrahedralMesh } from "./TetrahedralMesh.js";
47
+
48
+ // Quality threshold below which we count a tet as a sliver. Matches the
49
+ // usual "shape is starting to hurt simulation conditioning" cutoff for the
50
+ // radius-ratio metric.
51
+ const SLIVER_QUALITY_THRESHOLD = 0.05;
52
+
53
+ // Sliver-removal driver config. Currently OFF by default because the
54
+ // driver isn't optimised for interactive use yet: on a 6,500-tet Suzanne
55
+ // (and similar) it takes ~50 seconds per pass, which would freeze the UI
56
+ // on every drop. The main hotspot is `tetrahedral_mesh_vertex_is_boundary`
57
+ // inside the smoothing pass — it scans every tet in the mesh per vertex.
58
+ // Builds a vertex→tet adjacency cache once per pass to replace it.
59
+ //
60
+ // When enabled, the driver halves the sliver count on Suzanne and
61
+ // commits ~200 3-2 flips; smoothing is a no-op on closed-surface meshes
62
+ // because every vertex is on the boundary. Toggle this to true if you
63
+ // want the BEFORE → AFTER numbers logged in the per-mesh console line.
64
+ const ENABLE_IMPROVE_QUALITY = false;
65
+ const IMPROVE_TARGET_QUALITY = 0.05; // sliver cutoff only — keep the workload small
66
+ const IMPROVE_MAX_PASSES = 1;
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Visual / behaviour tunables
70
+ // ---------------------------------------------------------------------------
71
+
72
+ const BACKGROUND_COLOR = 0x202428;
73
+ const EXPLODE_FACTOR = 0.88; // scale each tet toward its centroid; <1 reveals gaps
74
+ const COLOR_SATURATION = 0.62;
75
+ const COLOR_VALUE = 0.92;
76
+ const COLOR_HUE_STEP = 0.61803398875; // golden-ratio conjugate → good separation
77
+ const CAMERA_FIT_PADDING = 1.5;
78
+
79
+ // ---------------------------------------------------------------------------
80
+ // Colour helpers
81
+ // ---------------------------------------------------------------------------
82
+
83
+ /**
84
+ * Standard HSV → packed 0xRRGGBB conversion.
85
+ *
86
+ * @param {number} h hue in [0,1)
87
+ * @param {number} s saturation in [0,1]
88
+ * @param {number} v value in [0,1]
89
+ * @returns {number}
90
+ */
91
+ function hsv_to_rgb_hex(h, s, v) {
92
+ const i = Math.floor(h * 6);
93
+ const f = h * 6 - i;
94
+ const p = v * (1 - s);
95
+ const q = v * (1 - f * s);
96
+ const t = v * (1 - (1 - f) * s);
97
+
98
+ let r, g, b;
99
+ switch (i % 6) {
100
+ case 0: r = v; g = t; b = p; break;
101
+ case 1: r = q; g = v; b = p; break;
102
+ case 2: r = p; g = v; b = t; break;
103
+ case 3: r = p; g = q; b = v; break;
104
+ case 4: r = t; g = p; b = v; break;
105
+ case 5: r = v; g = p; b = q; break;
106
+ }
107
+
108
+ return (Math.round(r * 255) << 16) | (Math.round(g * 255) << 8) | Math.round(b * 255);
109
+ }
110
+
111
+ /**
112
+ * Pick a visually distinct colour for the i-th geometry. Golden-angle hue
113
+ * stepping spreads neighbouring indices far apart in colour space.
114
+ *
115
+ * @param {number} i
116
+ * @returns {number} 0xRRGGBB
117
+ */
118
+ function color_for_index(i) {
119
+ return hsv_to_rgb_hex((i * COLOR_HUE_STEP) % 1, COLOR_SATURATION, COLOR_VALUE);
120
+ }
121
+
122
+ // ---------------------------------------------------------------------------
123
+ // Exploded-tet geometry construction
124
+ // ---------------------------------------------------------------------------
125
+
126
+ /**
127
+ * Emit a single triangle as 3 positions + 3 (flat) normals into the output
128
+ * arrays at `write_offset`. The vertex order is chosen so the normal points
129
+ * away from `opposite` — guaranteeing outward-facing tet faces regardless of
130
+ * the Delaunay output's vertex winding.
131
+ *
132
+ * Returns the new write offset (always advances by 9).
133
+ */
134
+ function emit_face(positions, normals, write_offset, p0, p1, p2, opposite) {
135
+ const ex = p1[0] - p0[0], ey = p1[1] - p0[1], ez = p1[2] - p0[2];
136
+ const fx = p2[0] - p0[0], fy = p2[1] - p0[1], fz = p2[2] - p0[2];
137
+
138
+ let nx = ey * fz - ez * fy;
139
+ let ny = ez * fx - ex * fz;
140
+ let nz = ex * fy - ey * fx;
141
+
142
+ // If normal points toward the opposite vertex, flip the winding.
143
+ const dx = p0[0] - opposite[0], dy = p0[1] - opposite[1], dz = p0[2] - opposite[2];
144
+ if (nx * dx + ny * dy + nz * dz < 0) {
145
+ nx = -nx; ny = -ny; nz = -nz;
146
+ const tmp = p1; p1 = p2; p2 = tmp;
147
+ }
148
+
149
+ const len = Math.sqrt(nx * nx + ny * ny + nz * nz) || 1;
150
+ nx /= len; ny /= len; nz /= len;
151
+
152
+ positions[write_offset + 0] = p0[0]; positions[write_offset + 1] = p0[1]; positions[write_offset + 2] = p0[2];
153
+ positions[write_offset + 3] = p1[0]; positions[write_offset + 4] = p1[1]; positions[write_offset + 5] = p1[2];
154
+ positions[write_offset + 6] = p2[0]; positions[write_offset + 7] = p2[1]; positions[write_offset + 8] = p2[2];
155
+
156
+ for (let k = 0; k < 3; k++) {
157
+ normals[write_offset + k * 3 + 0] = nx;
158
+ normals[write_offset + k * 3 + 1] = ny;
159
+ normals[write_offset + k * 3 + 2] = nz;
160
+ }
161
+
162
+ return write_offset + 9;
163
+ }
164
+
165
+ /**
166
+ * Build a flat-shaded triangle geometry where each tetrahedron is rendered
167
+ * as four outward-facing triangles, with the tet's vertices contracted
168
+ * toward its centroid by `shrink`. The contraction creates visible gaps
169
+ * between adjacent tets so the volumetric tessellation is obvious.
170
+ *
171
+ * @param {TetrahedralMesh} tet_mesh
172
+ * @param {Float32Array|number[]} points flat (x,y,z) positions array
173
+ * @param {number} shrink (0,1] — 1 = touching tets, 0.85 = clear gaps
174
+ * @returns {BufferGeometry}
175
+ */
176
+ function build_exploded_tet_geometry(tet_mesh, points, shrink) {
177
+ const tet_count = tet_mesh.count;
178
+ const float_count = tet_count * 4 * 3 * 3; // 4 faces × 3 verts × xyz
179
+ const positions = new Float32Array(float_count);
180
+ const normals = new Float32Array(float_count);
181
+ const s = shrink;
182
+ const t = 1 - s;
183
+
184
+ let write = 0;
185
+
186
+ tet_mesh.forEach((tet) => {
187
+ const ai = tet_mesh.getVertexIndex(tet, 0);
188
+ const bi = tet_mesh.getVertexIndex(tet, 1);
189
+ const ci = tet_mesh.getVertexIndex(tet, 2);
190
+ const di = tet_mesh.getVertexIndex(tet, 3);
191
+
192
+ const ax = points[ai * 3], ay = points[ai * 3 + 1], az = points[ai * 3 + 2];
193
+ const bx = points[bi * 3], by = points[bi * 3 + 1], bz = points[bi * 3 + 2];
194
+ const cx = points[ci * 3], cy = points[ci * 3 + 1], cz = points[ci * 3 + 2];
195
+ const dx = points[di * 3], dy = points[di * 3 + 1], dz = points[di * 3 + 2];
196
+
197
+ const ccx = (ax + bx + cx + dx) * 0.25;
198
+ const ccy = (ay + by + cy + dy) * 0.25;
199
+ const ccz = (az + bz + cz + dz) * 0.25;
200
+
201
+ const A = [ax * s + ccx * t, ay * s + ccy * t, az * s + ccz * t];
202
+ const B = [bx * s + ccx * t, by * s + ccy * t, bz * s + ccz * t];
203
+ const C = [cx * s + ccx * t, cy * s + ccy * t, cz * s + ccz * t];
204
+ const D = [dx * s + ccx * t, dy * s + ccy * t, dz * s + ccz * t];
205
+
206
+ write = emit_face(positions, normals, write, B, C, D, A); // face opposite A
207
+ write = emit_face(positions, normals, write, A, D, C, B); // face opposite B
208
+ write = emit_face(positions, normals, write, A, B, D, C); // face opposite C
209
+ write = emit_face(positions, normals, write, A, C, B, D); // face opposite D
210
+ });
211
+
212
+ const geometry = new BufferGeometry();
213
+ geometry.setAttribute('position', new Float32BufferAttribute(positions, 3));
214
+ geometry.setAttribute('normal', new Float32BufferAttribute(normals, 3));
215
+ return geometry;
216
+ }
217
+
218
+ // ---------------------------------------------------------------------------
219
+ // Tetrahedralization pipeline for a single input geometry
220
+ // ---------------------------------------------------------------------------
221
+
222
+ /**
223
+ * Turn a three.js BufferGeometry (with its world matrix baked in) into a
224
+ * flat-shaded exploded-tet mesh plus measurement stats. Returns null if
225
+ * the input cannot be tetrahedralized.
226
+ *
227
+ * Stats included:
228
+ * - tet_count: number of live tets in the result
229
+ * - surface_volume: divergence-theorem volume of the input surface (the
230
+ * target we're trying to fill — caveat: only correct
231
+ * if the surface is properly closed and consistently
232
+ * wound. For meshes with holes / mixed winding the
233
+ * number is an approximation.)
234
+ * - tet_volume: sum of all tet volumes in the output
235
+ * - min_quality, avg_quality: radius-ratio quality (1 = regular tet,
236
+ * 0 = degenerate)
237
+ * - sliver_count: tets below SLIVER_QUALITY_THRESHOLD
238
+ *
239
+ * @param {BufferGeometry} input_geometry
240
+ * @returns {{
241
+ * geometry: BufferGeometry,
242
+ * tet_count: number,
243
+ * surface_volume: number,
244
+ * tet_volume: number,
245
+ * min_quality: number,
246
+ * avg_quality: number,
247
+ * sliver_count: number,
248
+ * } | null}
249
+ */
250
+ function tetrahedralize_geometry(input_geometry) {
251
+ const positions_attr = input_geometry.getAttribute('position');
252
+ if (!positions_attr || positions_attr.count < 3) return null;
253
+
254
+ // Pull out positions + indices, fabricating trivial indices if the input
255
+ // is non-indexed (every 3 vertices = 1 triangle).
256
+ const positions = Array.from(positions_attr.array);
257
+ let indices;
258
+ if (input_geometry.index) {
259
+ indices = Array.from(input_geometry.index.array);
260
+ } else {
261
+ const n = positions_attr.count;
262
+ indices = new Array(n);
263
+ for (let i = 0; i < n; i++) indices[i] = i;
264
+ }
265
+ if (indices.length < 3) return null;
266
+
267
+ // GLTF often duplicates positions at smoothing/UV splits — that's fine,
268
+ // compute_tetrahedral_mesh_from_surface merges coincident vertices via
269
+ // bt_merge_verts_by_distance internally before tetrahedralizing.
270
+ const surface = new BinaryTopology();
271
+ bt_mesh_from_indexed_geometry(surface, indices, positions);
272
+
273
+ const surface_volume = Math.abs(triangle_mesh_compute_signed_volume(positions, indices));
274
+
275
+ const tet_mesh = new TetrahedralMesh();
276
+ let tet_positions;
277
+ try {
278
+ tet_positions = compute_tetrahedral_mesh_from_surface(tet_mesh, surface);
279
+ } catch (e) {
280
+ console.warn('Tetrahedralization failed for one geometry:', e);
281
+ return null;
282
+ }
283
+
284
+ if (tet_mesh.count === 0) {
285
+ return null;
286
+ }
287
+
288
+ const stats_before = measure_tet_stats(tet_mesh, tet_positions);
289
+
290
+ // Sliver-removal driver: try Laplacian smoothing + 2-3 / 3-2 flips on
291
+ // every tet below IMPROVE_TARGET_QUALITY. Off by toggling the constant
292
+ // at top of file. Stats are captured before+after so the per-mesh
293
+ // console line shows whether the driver actually moved the needle.
294
+ let stats_after = stats_before;
295
+ let driver_stats = null;
296
+ let driver_ms = 0;
297
+ if (ENABLE_IMPROVE_QUALITY) {
298
+ const t = performance.now();
299
+ driver_stats = tetrahedral_mesh_improve_quality(tet_mesh, tet_positions, {
300
+ target_quality: IMPROVE_TARGET_QUALITY,
301
+ max_passes: IMPROVE_MAX_PASSES,
302
+ });
303
+ driver_ms = performance.now() - t;
304
+ stats_after = measure_tet_stats(tet_mesh, tet_positions);
305
+ }
306
+
307
+ const out_geom = build_exploded_tet_geometry(tet_mesh, tet_positions, EXPLODE_FACTOR);
308
+
309
+ return {
310
+ geometry: out_geom,
311
+ tet_count: tet_mesh.count,
312
+ surface_volume,
313
+ tet_volume: stats_after.tet_volume,
314
+ min_quality: stats_after.min_quality,
315
+ avg_quality: stats_after.avg_quality,
316
+ sliver_count: stats_after.sliver_count,
317
+ stats_before,
318
+ stats_after,
319
+ driver_stats,
320
+ driver_ms,
321
+ };
322
+ }
323
+
324
+ /**
325
+ * One pass over a tet mesh: total signed volume, min and average
326
+ * radius-ratio quality, count of tets below the sliver threshold.
327
+ *
328
+ * @param {TetrahedralMesh} tet_mesh
329
+ * @param {Float32Array|number[]} tet_positions
330
+ * @returns {{tet_volume: number, min_quality: number, avg_quality: number, sliver_count: number}}
331
+ */
332
+ function measure_tet_stats(tet_mesh, tet_positions) {
333
+ let tet_volume = 0;
334
+ let min_quality = 1;
335
+ let q_sum = 0;
336
+ let sliver_count = 0;
337
+ tet_mesh.forEach((tet, m) => {
338
+ tet_volume += compute_tetrahedron_volume(m, tet_positions, tet);
339
+ const q = compute_tetrahedron_quality(m, tet_positions, tet);
340
+ if (q < min_quality) min_quality = q;
341
+ q_sum += q;
342
+ if (q < SLIVER_QUALITY_THRESHOLD) sliver_count++;
343
+ });
344
+ const avg_quality = tet_mesh.count > 0 ? q_sum / tet_mesh.count : 0;
345
+ return { tet_volume, min_quality, avg_quality, sliver_count };
346
+ }
347
+
348
+ // ---------------------------------------------------------------------------
349
+ // Scene management
350
+ // ---------------------------------------------------------------------------
351
+
352
+ const scene = new Scene();
353
+ scene.background = null; // let CSS show through
354
+
355
+ const camera = new PerspectiveCamera(45, 1, 0.01, 10000);
356
+ camera.position.set(4, 4, 6);
357
+
358
+ const renderer = new WebGLRenderer({ antialias: true });
359
+ renderer.setPixelRatio(window.devicePixelRatio);
360
+ renderer.setClearColor(BACKGROUND_COLOR, 1);
361
+
362
+ document.body.style.margin = '0';
363
+ document.body.style.overflow = 'hidden';
364
+ document.body.style.background = `#${BACKGROUND_COLOR.toString(16).padStart(6, '0')}`;
365
+ document.body.appendChild(renderer.domElement);
366
+
367
+ scene.add(new AmbientLight(0xffffff, 0.45));
368
+ const key_light = new DirectionalLight(0xffffff, 0.9);
369
+ key_light.position.set(3, 5, 4);
370
+ scene.add(key_light);
371
+ const fill_light = new DirectionalLight(0xa0b8ff, 0.35);
372
+ fill_light.position.set(-4, -2, -3);
373
+ scene.add(fill_light);
374
+
375
+ const controls = new OrbitControls(camera, renderer.domElement);
376
+ controls.enableDamping = true;
377
+ controls.dampingFactor = 0.08;
378
+
379
+ const loaded_group = new Group();
380
+ scene.add(loaded_group);
381
+
382
+ function clear_loaded() {
383
+ while (loaded_group.children.length > 0) {
384
+ const child = loaded_group.children.pop();
385
+ if (child.geometry) child.geometry.dispose();
386
+ if (child.material) child.material.dispose();
387
+ }
388
+ }
389
+
390
+ function fit_camera_to(group) {
391
+ const min = new ThreeVector3(Infinity, Infinity, Infinity);
392
+ const max = new ThreeVector3(-Infinity, -Infinity, -Infinity);
393
+ const tmp = new ThreeVector3();
394
+
395
+ group.traverse((obj) => {
396
+ if (!obj.geometry) return;
397
+ const attr = obj.geometry.getAttribute('position');
398
+ if (!attr) return;
399
+ for (let i = 0; i < attr.count; i++) {
400
+ tmp.set(attr.getX(i), attr.getY(i), attr.getZ(i));
401
+ obj.localToWorld(tmp);
402
+ min.min(tmp);
403
+ max.max(tmp);
404
+ }
405
+ });
406
+
407
+ if (!isFinite(min.x)) return;
408
+
409
+ const center = min.clone().add(max).multiplyScalar(0.5);
410
+ const size = max.clone().sub(min);
411
+ const radius = size.length() * 0.5;
412
+ const dist = (radius / Math.sin((camera.fov * Math.PI / 180) / 2)) * CAMERA_FIT_PADDING;
413
+
414
+ const dir = new ThreeVector3(1, 0.6, 1.2).normalize();
415
+ camera.position.copy(center).add(dir.multiplyScalar(dist));
416
+ camera.near = Math.max(0.001, dist * 0.001);
417
+ camera.far = dist * 100;
418
+ camera.updateProjectionMatrix();
419
+
420
+ controls.target.copy(center);
421
+ controls.update();
422
+ }
423
+
424
+ // ---------------------------------------------------------------------------
425
+ // Drag & drop UI
426
+ // ---------------------------------------------------------------------------
427
+
428
+ const overlay = document.createElement('div');
429
+ Object.assign(overlay.style, {
430
+ position: 'fixed',
431
+ inset: '0',
432
+ display: 'flex',
433
+ flexDirection: 'column',
434
+ alignItems: 'center',
435
+ justifyContent: 'center',
436
+ color: 'rgba(255,255,255,0.55)',
437
+ fontFamily: 'system-ui, sans-serif',
438
+ fontSize: '20px',
439
+ pointerEvents: 'none',
440
+ transition: 'opacity 0.2s ease',
441
+ textAlign: 'center',
442
+ padding: '24px',
443
+ });
444
+ overlay.innerHTML = `
445
+ <div style="font-size:42px;margin-bottom:12px;">⬇</div>
446
+ <div>Drop a <b>.gltf</b> or <b>.glb</b> file anywhere</div>
447
+ <div style="font-size:14px;margin-top:8px;opacity:0.7;">
448
+ Each mesh inside will be tetrahedralized and shown in a distinct colour.
449
+ </div>
450
+ `;
451
+ document.body.appendChild(overlay);
452
+
453
+ const status_bar = document.createElement('div');
454
+ Object.assign(status_bar.style, {
455
+ position: 'fixed',
456
+ left: '12px',
457
+ bottom: '12px',
458
+ color: 'rgba(255,255,255,0.85)',
459
+ fontFamily: 'monospace',
460
+ fontSize: '13px',
461
+ background: 'rgba(0,0,0,0.4)',
462
+ padding: '6px 10px',
463
+ borderRadius: '4px',
464
+ pointerEvents: 'none',
465
+ whiteSpace: 'pre',
466
+ });
467
+ document.body.appendChild(status_bar);
468
+
469
+ function set_status(text) {
470
+ status_bar.textContent = text;
471
+ }
472
+
473
+ set_status('Ready. Drop a .gltf or .glb file.');
474
+
475
+ ['dragenter', 'dragover'].forEach((ev) => {
476
+ window.addEventListener(ev, (e) => {
477
+ e.preventDefault();
478
+ overlay.style.background = 'rgba(60,100,140,0.25)';
479
+ });
480
+ });
481
+ ['dragleave', 'drop'].forEach((ev) => {
482
+ window.addEventListener(ev, (e) => {
483
+ e.preventDefault();
484
+ overlay.style.background = '';
485
+ });
486
+ });
487
+
488
+ window.addEventListener('drop', (e) => {
489
+ const file = e.dataTransfer?.files?.[0];
490
+ if (!file) return;
491
+ handle_dropped_file(file);
492
+ });
493
+
494
+ const gltf_loader = new GLTFLoader();
495
+
496
+ /**
497
+ * @param {File} file
498
+ */
499
+ function handle_dropped_file(file) {
500
+ set_status(`Reading ${file.name}…`);
501
+
502
+ const reader = new FileReader();
503
+ reader.onload = () => {
504
+ const buffer = reader.result;
505
+ const is_glb = file.name.toLowerCase().endsWith('.glb');
506
+
507
+ // GLTFLoader.parse accepts an ArrayBuffer (for .glb) or a JSON string
508
+ // (for .gltf). For .gltf, the result.scenes won't include external
509
+ // .bin buffers — that's a known limitation of single-file drag-drop.
510
+ try {
511
+ let data;
512
+ if (is_glb) {
513
+ data = buffer;
514
+ } else {
515
+ data = new TextDecoder().decode(buffer);
516
+ }
517
+
518
+ gltf_loader.parse(
519
+ data,
520
+ '',
521
+ (gltf) => process_gltf(gltf, file.name),
522
+ (err) => {
523
+ console.error(err);
524
+ set_status(`Failed to parse ${file.name}: ${err?.message ?? err}`);
525
+ }
526
+ );
527
+ } catch (err) {
528
+ console.error(err);
529
+ set_status(`Failed to read ${file.name}: ${err.message}`);
530
+ }
531
+ };
532
+ reader.onerror = () => set_status(`Failed to read ${file.name}`);
533
+ reader.readAsArrayBuffer(file);
534
+ }
535
+
536
+ /**
537
+ * @param {{scene: import("three").Group}} gltf
538
+ * @param {string} file_name
539
+ */
540
+ function process_gltf(gltf, file_name) {
541
+ clear_loaded();
542
+ overlay.style.opacity = '0';
543
+
544
+ gltf.scene.updateWorldMatrix(true, true);
545
+
546
+ /** @type {Array<{name: string, geometry: BufferGeometry}>} */
547
+ const inputs = [];
548
+
549
+ gltf.scene.traverse((obj) => {
550
+ if (!obj.isMesh || !obj.geometry) return;
551
+ // Bake world transform so every geometry lives in the same coordinate frame.
552
+ const baked = obj.geometry.clone();
553
+ baked.applyMatrix4(obj.matrixWorld);
554
+ inputs.push({ name: obj.name || `mesh_${inputs.length}`, geometry: baked });
555
+ });
556
+
557
+ if (inputs.length === 0) {
558
+ set_status(`${file_name}: no meshes found.`);
559
+ overlay.style.opacity = '1';
560
+ return;
561
+ }
562
+
563
+ set_status(`${file_name}: tetrahedralizing ${inputs.length} mesh(es)…`);
564
+
565
+ let total_tets = 0;
566
+ let total_slivers = 0;
567
+ let total_surface_vol = 0;
568
+ let total_tet_vol = 0;
569
+ let global_min_quality = 1;
570
+ let q_sum_weighted = 0; // sum of avg_quality × tet_count, for a proper aggregate average
571
+ let succeeded = 0;
572
+ const t0 = performance.now();
573
+
574
+ inputs.forEach((input, i) => {
575
+ const color = color_for_index(i);
576
+
577
+ let result;
578
+ try {
579
+ result = tetrahedralize_geometry(input.geometry);
580
+ } catch (e) {
581
+ console.warn(`Tetrahedralization threw for "${input.name}":`, e);
582
+ return;
583
+ }
584
+ if (result === null) {
585
+ console.warn(`Tetrahedralization yielded no tets for "${input.name}".`);
586
+ return;
587
+ }
588
+
589
+ const material = new MeshStandardMaterial({
590
+ color,
591
+ flatShading: true,
592
+ roughness: 0.6,
593
+ metalness: 0.05,
594
+ });
595
+ const mesh = new Mesh(result.geometry, material);
596
+ mesh.name = input.name;
597
+ loaded_group.add(mesh);
598
+
599
+ succeeded += 1;
600
+ total_tets += result.tet_count;
601
+ total_slivers += result.sliver_count;
602
+ total_surface_vol += result.surface_volume;
603
+ total_tet_vol += result.tet_volume;
604
+ q_sum_weighted += result.avg_quality * result.tet_count;
605
+ if (result.min_quality < global_min_quality) global_min_quality = result.min_quality;
606
+
607
+ // Per-mesh details to the console. The line shows BEFORE → AFTER
608
+ // the improve-quality driver so we can immediately see whether it
609
+ // moved the needle on this specific mesh.
610
+ const gap_pct = result.surface_volume > 0
611
+ ? ((result.tet_volume - result.surface_volume) / result.surface_volume * 100).toFixed(2) + '%'
612
+ : 'n/a';
613
+ const before = result.stats_before;
614
+ const after = result.stats_after;
615
+ const driver_summary = result.driver_stats
616
+ ? ` (${result.driver_ms.toFixed(0)}ms; smooth=${result.driver_stats.smoothings_committed}, flip23=${result.driver_stats.flips_23_committed}, flip32=${result.driver_stats.flips_32_committed})`
617
+ : '';
618
+ // eslint-disable-next-line no-console
619
+ console.log(
620
+ `[${input.name}] tets=${result.tet_count} ` +
621
+ `surf_vol=${result.surface_volume.toFixed(4)} tet_vol=${result.tet_volume.toFixed(4)} gap=${gap_pct}\n` +
622
+ ` min_q: ${before.min_quality.toFixed(3)} → ${after.min_quality.toFixed(3)} ` +
623
+ `avg_q: ${before.avg_quality.toFixed(3)} → ${after.avg_quality.toFixed(3)} ` +
624
+ `slivers: ${before.sliver_count} → ${after.sliver_count}${driver_summary}`
625
+ );
626
+ });
627
+
628
+ const ms = (performance.now() - t0).toFixed(0);
629
+
630
+ if (succeeded === 0) {
631
+ set_status(`${file_name}: all ${inputs.length} mesh(es) failed to tetrahedralize. See console.`);
632
+ overlay.style.opacity = '1';
633
+ return;
634
+ }
635
+
636
+ fit_camera_to(loaded_group);
637
+
638
+ const aggregate_avg_q = total_tets > 0 ? q_sum_weighted / total_tets : 0;
639
+ const aggregate_gap = total_surface_vol > 0
640
+ ? ((total_tet_vol - total_surface_vol) / total_surface_vol * 100).toFixed(2) + '%'
641
+ : 'n/a';
642
+ const sliver_pct = total_tets > 0
643
+ ? (total_slivers / total_tets * 100).toFixed(1) + '%'
644
+ : '0%';
645
+
646
+ set_status(
647
+ `${file_name}\n` +
648
+ `meshes: ${succeeded}/${inputs.length} tets: ${total_tets.toLocaleString()} time: ${ms} ms\n` +
649
+ `vol: surf=${total_surface_vol.toFixed(4)} tet=${total_tet_vol.toFixed(4)} gap=${aggregate_gap}\n` +
650
+ `quality: min=${global_min_quality.toFixed(3)} avg=${aggregate_avg_q.toFixed(3)} slivers: ${total_slivers} (${sliver_pct})\n` +
651
+ `(drop another file to replace; per-mesh details in console)`
652
+ );
653
+ }
654
+
655
+ // ---------------------------------------------------------------------------
656
+ // Render loop & resize
657
+ // ---------------------------------------------------------------------------
658
+
659
+ function on_resize() {
660
+ const w = window.innerWidth;
661
+ const h = window.innerHeight;
662
+ renderer.setSize(w, h, false);
663
+ camera.aspect = w / h;
664
+ camera.updateProjectionMatrix();
665
+ }
666
+ window.addEventListener('resize', on_resize);
667
+ on_resize();
668
+
669
+ (function animate() {
670
+ requestAnimationFrame(animate);
671
+ controls.update();
672
+ renderer.render(scene, camera);
673
+ })();
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Carve a Delaunay tetrahedralization so only the tets inside the input
3
+ * surface remain. Operates on a TetrahedralMesh whose vertex IDs are aligned
4
+ * with the surface's vertex IDs — both index into the same flat positions
5
+ * array used by `compute_delaunay_tetrahedral_mesh`.
6
+ *
7
+ * Algorithm: build a BVH over the surface triangles, then for every tet,
8
+ * classify its centroid as inside or outside via parity ray-casting against
9
+ * the BVH. Exterior tets are disconnected and deleted.
10
+ *
11
+ * Pure ray-cast classification is intentional. A flood-fill optimisation over
12
+ * tet adjacency would be cheaper but is unsafe when the Delaunay's diagonals
13
+ * differ from the surface's (always the case for coarse meshes like a cube,
14
+ * common for finer meshes): leaked surface triangles let the fill cross from
15
+ * interior to exterior unchecked, deleting tets that should be kept.
16
+ *
17
+ * @param {TetrahedralMesh} tet_mesh mutated in place
18
+ * @param {ArrayLike<number>|Float32Array} positions same flat (x,y,z) array used in the Delaunay pass
19
+ * @param {BinaryTopology} surface watertight surface mesh defining inside/outside
20
+ * @returns {{deleted: number, kept: number}}
21
+ */
22
+ export function tetrahedral_mesh_carve_outside_surface(tet_mesh: TetrahedralMesh, positions: ArrayLike<number> | Float32Array, surface: BinaryTopology): {
23
+ deleted: number;
24
+ kept: number;
25
+ };
26
+ //# sourceMappingURL=tetrahedral_mesh_carve_outside_surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tetrahedral_mesh_carve_outside_surface.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js"],"names":[],"mappings":"AAoJA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,6FAJW,UAAU,MAAM,CAAC,GAAC,YAAY;aAElB,MAAM;UAAQ,MAAM;EAsD1C"}