@woosh/meep-engine 2.138.20 → 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 (584) 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/core/collection/PairUint32Map.d.ts +100 -0
  6. package/src/core/collection/PairUint32Map.d.ts.map +1 -0
  7. package/src/core/collection/PairUint32Map.js +321 -0
  8. package/src/core/collection/Uint32Map.d.ts +119 -0
  9. package/src/core/collection/Uint32Map.d.ts.map +1 -0
  10. package/src/core/collection/Uint32Map.js +345 -0
  11. package/src/core/collection/array/array_shuffle.d.ts +10 -3
  12. package/src/core/collection/array/array_shuffle.d.ts.map +1 -1
  13. package/src/core/collection/array/array_shuffle.js +27 -22
  14. package/src/core/collection/heap/FibonacciHeap.d.ts +195 -0
  15. package/src/core/collection/heap/FibonacciHeap.d.ts.map +1 -0
  16. package/src/core/collection/heap/FibonacciHeap.js +586 -0
  17. package/src/core/collection/heap/Uint32Heap.js +1 -1
  18. package/src/core/collection/heap/Uint32Heap4.d.ts +169 -0
  19. package/src/core/collection/heap/Uint32Heap4.d.ts.map +1 -0
  20. package/src/core/collection/heap/Uint32Heap4.js +490 -0
  21. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts +30 -0
  22. package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -0
  23. package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +93 -0
  24. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts +27 -0
  25. package/src/core/geom/3d/line/line3_closest_points_segment_segment.d.ts.map +1 -0
  26. package/src/core/geom/3d/line/line3_closest_points_segment_segment.js +88 -0
  27. package/src/core/geom/3d/quaternion/quat3_to_matrix3.d.ts +54 -0
  28. package/src/core/geom/3d/quaternion/quat3_to_matrix3.d.ts.map +1 -0
  29. package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -0
  30. package/src/core/geom/3d/shape/AbstractShape3D.d.ts +24 -2
  31. package/src/core/geom/3d/shape/AbstractShape3D.d.ts.map +1 -1
  32. package/src/core/geom/3d/shape/AbstractShape3D.js +24 -1
  33. package/src/core/geom/3d/shape/BoxShape3D.d.ts +61 -0
  34. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -0
  35. package/src/core/geom/3d/shape/BoxShape3D.js +158 -0
  36. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts +11 -0
  37. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  38. package/src/core/geom/3d/shape/CapsuleShape3D.js +12 -0
  39. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +148 -0
  40. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -0
  41. package/src/core/geom/3d/shape/HeightMapShape3D.js +451 -0
  42. package/src/core/geom/3d/shape/MeshShape3D.d.ts +210 -0
  43. package/src/core/geom/3d/shape/MeshShape3D.d.ts.map +1 -0
  44. package/src/core/geom/3d/shape/MeshShape3D.js +593 -0
  45. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  46. package/src/core/geom/3d/shape/TransformedShape3D.js +46 -2
  47. package/src/core/geom/3d/shape/Triangle3D.d.ts +95 -0
  48. package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -0
  49. package/src/core/geom/3d/shape/Triangle3D.js +318 -0
  50. package/src/core/geom/3d/shape/UnionShape3D.js +13 -0
  51. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts +37 -9
  52. package/src/core/geom/3d/shape/UnitCubeShape3D.d.ts.map +1 -1
  53. package/src/core/geom/3d/shape/UnitCubeShape3D.js +45 -98
  54. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts +10 -0
  55. package/src/core/geom/3d/shape/UnitSphereShape3D.d.ts.map +1 -1
  56. package/src/core/geom/3d/shape/UnitSphereShape3D.js +11 -0
  57. package/src/core/geom/3d/shape/shape_mesh_from_geometry.d.ts +30 -0
  58. package/src/core/geom/3d/shape/shape_mesh_from_geometry.d.ts.map +1 -0
  59. package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +64 -0
  60. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts +61 -0
  61. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.d.ts.map +1 -0
  62. package/src/core/geom/3d/shape/util/shape3d_voxelize_to_grid.js +148 -0
  63. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts +39 -0
  64. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.d.ts.map +1 -0
  65. package/src/core/geom/3d/tetrahedra/compute_tetrahedral_mesh_from_surface.js +147 -0
  66. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts +15 -0
  67. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.d.ts.map +1 -0
  68. package/src/core/geom/3d/tetrahedra/compute_tetrahedron_quality.js +22 -0
  69. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts +2 -0
  70. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.d.ts.map +1 -0
  71. package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +671 -0
  72. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.d.ts +28 -0
  73. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.d.ts.map +1 -0
  74. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -0
  75. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts +26 -0
  76. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -0
  77. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.js +222 -0
  78. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts +34 -0
  79. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.d.ts.map +1 -0
  80. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_find_tets_around_edge.js +146 -0
  81. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts +36 -0
  82. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.d.ts.map +1 -0
  83. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_23.js +232 -0
  84. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts +33 -0
  85. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.d.ts.map +1 -0
  86. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_flip_32.js +255 -0
  87. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts +68 -0
  88. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -0
  89. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +387 -0
  90. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +35 -0
  91. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -0
  92. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +140 -0
  93. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +31 -0
  94. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -0
  95. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +97 -0
  96. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts +32 -0
  97. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.d.ts.map +1 -0
  98. package/src/core/geom/3d/tetrahedra/tetrahedron_compute_quality.js +66 -0
  99. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +41 -0
  100. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
  101. package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +124 -13
  102. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts +134 -0
  103. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.d.ts.map +1 -1
  104. package/src/core/geom/3d/topology/struct/binary/BinaryTopology.js +276 -3
  105. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +17 -0
  106. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -0
  107. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +135 -0
  108. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts +14 -0
  109. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.d.ts.map +1 -0
  110. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_compact.js +177 -0
  111. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.d.ts.map +1 -1
  112. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_face_decouple.js +20 -4
  113. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.d.ts.map +1 -1
  114. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_simplify.js +5 -3
  115. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.d.ts.map +1 -1
  116. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_create.js +9 -0
  117. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.d.ts.map +1 -1
  118. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_get_or_create.js +21 -45
  119. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.d.ts.map +1 -1
  120. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill.js +7 -1
  121. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts +8 -6
  122. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.d.ts.map +1 -1
  123. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_edge_kill_parallels.js +8 -6
  124. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts +22 -0
  125. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.d.ts.map +1 -0
  126. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_kill_short_edges.js +73 -0
  127. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.d.ts.map +1 -1
  128. package/src/core/geom/3d/topology/struct/binary/io/vertex/bt_vertex_replace.js +51 -1
  129. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts +10 -0
  130. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.d.ts.map +1 -0
  131. package/src/core/geom/3d/topology/struct/binary/query/bt_edge_get.js +42 -0
  132. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts +28 -0
  133. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.d.ts.map +1 -0
  134. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_sample_interior_grid_points.js +227 -0
  135. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts +13 -0
  136. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.d.ts.map +1 -0
  137. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_walk_boundary_loops.js +108 -0
  138. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts +11 -0
  139. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.d.ts.map +1 -0
  140. package/src/core/geom/3d/topology/struct/binary/query/bt_query_edge_is_boundary.js +20 -0
  141. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts +20 -0
  142. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.d.ts.map +1 -0
  143. package/src/core/geom/3d/triangle/triangle_mesh_compute_signed_volume.js +38 -0
  144. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.d.ts +2 -2
  145. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.d.ts.map +1 -1
  146. package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +1 -1
  147. package/src/core/geom/vec3/v3_dot_array_array.d.ts +3 -3
  148. package/src/core/geom/vec3/v3_dot_array_array.d.ts.map +1 -1
  149. package/src/core/geom/vec3/v3_dot_array_array.js +2 -2
  150. package/src/core/geom/vec3/v3_negate_array.d.ts +3 -3
  151. package/src/core/geom/vec3/v3_negate_array.d.ts.map +1 -1
  152. package/src/core/geom/vec3/v3_negate_array.js +2 -2
  153. package/src/core/geom/vec3/v3_quat3_apply.d.ts +29 -0
  154. package/src/core/geom/vec3/v3_quat3_apply.d.ts.map +1 -0
  155. package/src/core/geom/vec3/v3_quat3_apply.js +39 -0
  156. package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts +30 -0
  157. package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts.map +1 -0
  158. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +41 -0
  159. package/src/core/geom/vec3/v3_triple_cross_product.d.ts +32 -0
  160. package/src/core/geom/vec3/v3_triple_cross_product.d.ts.map +1 -0
  161. package/src/core/geom/vec3/v3_triple_cross_product.js +45 -0
  162. package/src/core/graph/csr/CSRGraph.d.ts +168 -0
  163. package/src/core/graph/csr/CSRGraph.d.ts.map +1 -0
  164. package/src/core/graph/csr/CSRGraph.js +319 -0
  165. package/src/core/graph/metis/cluster_mesh_metis.d.ts +12 -0
  166. package/src/core/graph/metis/cluster_mesh_metis.d.ts.map +1 -1
  167. package/src/core/graph/metis/cluster_mesh_metis.js +12 -0
  168. package/src/core/graph/metis/metis.d.ts +19 -0
  169. package/src/core/graph/metis/metis.d.ts.map +1 -1
  170. package/src/core/graph/metis/metis.js +20 -0
  171. package/src/core/graph/metis/metis_cluster_bs.d.ts +11 -0
  172. package/src/core/graph/metis/metis_cluster_bs.d.ts.map +1 -1
  173. package/src/core/graph/metis/metis_cluster_bs.js +11 -0
  174. package/src/core/graph/metis/metis_options.d.ts +17 -2
  175. package/src/core/graph/metis/metis_options.d.ts.map +1 -1
  176. package/src/core/graph/metis/metis_options.js +17 -2
  177. package/src/core/graph/metis/native/MetisGraph.d.ts +144 -0
  178. package/src/core/graph/metis/native/MetisGraph.d.ts.map +1 -0
  179. package/src/core/graph/metis/native/MetisGraph.js +212 -0
  180. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts +72 -0
  181. package/src/core/graph/metis/native/bisection/BisectionScratch.d.ts.map +1 -0
  182. package/src/core/graph/metis/native/bisection/BisectionScratch.js +101 -0
  183. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts +37 -0
  184. package/src/core/graph/metis/native/bisection/bisect_graph.d.ts.map +1 -0
  185. package/src/core/graph/metis/native/bisection/bisect_graph.js +100 -0
  186. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts +15 -0
  187. package/src/core/graph/metis/native/bisection/compute_2way_params.d.ts.map +1 -0
  188. package/src/core/graph/metis/native/bisection/compute_2way_params.js +84 -0
  189. package/src/core/graph/metis/native/bisection/fm_2way.d.ts +30 -0
  190. package/src/core/graph/metis/native/bisection/fm_2way.d.ts.map +1 -0
  191. package/src/core/graph/metis/native/bisection/fm_2way.js +290 -0
  192. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts +23 -0
  193. package/src/core/graph/metis/native/bisection/grow_bisection.d.ts.map +1 -0
  194. package/src/core/graph/metis/native/bisection/grow_bisection.js +137 -0
  195. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts +28 -0
  196. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -0
  197. package/src/core/graph/metis/native/bisection/split_graph_two_way.js +119 -0
  198. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts +20 -0
  199. package/src/core/graph/metis/native/coarsen/coarsen_graph.d.ts.map +1 -0
  200. package/src/core/graph/metis/native/coarsen/coarsen_graph.js +94 -0
  201. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts +24 -0
  202. package/src/core/graph/metis/native/coarsen/create_coarse_graph.d.ts.map +1 -0
  203. package/src/core/graph/metis/native/coarsen/create_coarse_graph.js +158 -0
  204. package/src/core/graph/metis/native/coarsen/match_shem.d.ts +41 -0
  205. package/src/core/graph/metis/native/coarsen/match_shem.d.ts.map +1 -0
  206. package/src/core/graph/metis/native/coarsen/match_shem.js +175 -0
  207. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts +24 -0
  208. package/src/core/graph/metis/native/initial/initial_kway_bfs.d.ts.map +1 -0
  209. package/src/core/graph/metis/native/initial/initial_kway_bfs.js +122 -0
  210. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts +29 -0
  211. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.d.ts.map +1 -0
  212. package/src/core/graph/metis/native/initial/initial_kway_recursive_bisection.js +170 -0
  213. package/src/core/graph/metis/native/metis_partition_kway.d.ts +41 -0
  214. package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -0
  215. package/src/core/graph/metis/native/metis_partition_kway.js +126 -0
  216. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts +62 -0
  217. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.d.ts.map +1 -0
  218. package/src/core/graph/metis/native/refine/IndexedFloatMaxHeap.js +261 -0
  219. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts +45 -0
  220. package/src/core/graph/metis/native/refine/RefinementScratch.d.ts.map +1 -0
  221. package/src/core/graph/metis/native/refine/RefinementScratch.js +53 -0
  222. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts +18 -0
  223. package/src/core/graph/metis/native/refine/compute_kway_params.d.ts.map +1 -0
  224. package/src/core/graph/metis/native/refine/compute_kway_params.js +138 -0
  225. package/src/core/graph/metis/native/refine/fm_kway.d.ts +63 -0
  226. package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -0
  227. package/src/core/graph/metis/native/refine/fm_kway.js +462 -0
  228. package/src/core/graph/metis/native/refine/project_kway.d.ts +22 -0
  229. package/src/core/graph/metis/native/refine/project_kway.d.ts.map +1 -0
  230. package/src/core/graph/metis/native/refine/project_kway.js +43 -0
  231. package/src/core/graph/metis/native/refine/refine_kway.d.ts +34 -0
  232. package/src/core/graph/metis/native/refine/refine_kway.d.ts.map +1 -0
  233. package/src/core/graph/metis/native/refine/refine_kway.js +43 -0
  234. package/src/core/math/linalg/eigen/matrix_householder_in_place.d.ts +2 -2
  235. package/src/core/math/linalg/eigen/matrix_householder_in_place.js +2 -2
  236. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts +6 -4
  237. package/src/core/math/linalg/eigen/matrix_qr_in_place.d.ts.map +1 -1
  238. package/src/core/math/linalg/eigen/matrix_qr_in_place.js +69 -23
  239. package/src/engine/EngineHarness.d.ts +3 -1
  240. package/src/engine/EngineHarness.d.ts.map +1 -1
  241. package/src/engine/EngineHarness.js +3 -0
  242. package/src/engine/control/first-person/DESIGN.md +30 -6
  243. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +563 -0
  244. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +115 -9
  245. package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
  246. package/src/engine/control/first-person/FirstPersonPlayerController.js +211 -176
  247. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +601 -8
  248. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
  249. package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +349 -8
  250. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +319 -23
  251. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
  252. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +1789 -799
  253. package/src/engine/control/first-person/TODO.md +173 -0
  254. package/src/engine/control/first-person/abilities/Ability.d.ts +101 -0
  255. package/src/engine/control/first-person/abilities/Ability.d.ts.map +1 -0
  256. package/src/engine/control/first-person/abilities/Ability.js +119 -0
  257. package/src/engine/control/first-person/abilities/AbilitySet.d.ts +86 -0
  258. package/src/engine/control/first-person/abilities/AbilitySet.d.ts.map +1 -0
  259. package/src/engine/control/first-person/abilities/AbilitySet.js +185 -0
  260. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +62 -0
  261. package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -0
  262. package/src/engine/control/first-person/abilities/LedgeGrab.js +199 -0
  263. package/src/engine/control/first-person/abilities/Mantle.d.ts +45 -0
  264. package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -0
  265. package/src/engine/control/first-person/abilities/Mantle.js +188 -0
  266. package/src/engine/control/first-person/abilities/Slide.d.ts +33 -0
  267. package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -0
  268. package/src/engine/control/first-person/abilities/Slide.js +166 -0
  269. package/src/engine/control/first-person/abilities/WallJump.d.ts +45 -0
  270. package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -0
  271. package/src/engine/control/first-person/abilities/WallJump.js +131 -0
  272. package/src/engine/control/first-person/abilities/WallRun.d.ts +44 -0
  273. package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -0
  274. package/src/engine/control/first-person/abilities/WallRun.js +180 -0
  275. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts +49 -0
  276. package/src/engine/control/first-person/composer/EyeOffsetStack.d.ts.map +1 -0
  277. package/src/engine/control/first-person/composer/EyeOffsetStack.js +60 -0
  278. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts +100 -0
  279. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.d.ts.map +1 -0
  280. package/src/engine/control/first-person/mastery/BreathRhythmEvaluator.js +133 -0
  281. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts +10 -0
  282. package/src/engine/control/first-person/mastery/DecisionPoint.d.ts.map +1 -0
  283. package/src/engine/control/first-person/mastery/DecisionPoint.js +30 -0
  284. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts +61 -0
  285. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.d.ts.map +1 -0
  286. package/src/engine/control/first-person/mastery/FootAsymmetryTurnEvaluator.js +109 -0
  287. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts +40 -0
  288. package/src/engine/control/first-person/mastery/MasteryEvaluator.d.ts.map +1 -0
  289. package/src/engine/control/first-person/mastery/MasteryEvaluator.js +45 -0
  290. package/src/engine/control/first-person/mastery/MasteryScore.d.ts +68 -0
  291. package/src/engine/control/first-person/mastery/MasteryScore.d.ts.map +1 -0
  292. package/src/engine/control/first-person/mastery/MasteryScore.js +100 -0
  293. package/src/engine/control/first-person/mastery/MasterySet.d.ts +60 -0
  294. package/src/engine/control/first-person/mastery/MasterySet.d.ts.map +1 -0
  295. package/src/engine/control/first-person/mastery/MasterySet.js +86 -0
  296. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts +58 -0
  297. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.d.ts.map +1 -0
  298. package/src/engine/control/first-person/mastery/SlideInitiationTimingEvaluator.js +83 -0
  299. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts +69 -0
  300. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.d.ts.map +1 -0
  301. package/src/engine/control/first-person/mastery/StrideTimingJumpEvaluator.js +109 -0
  302. package/src/engine/control/first-person/math/Spring.d.ts +56 -0
  303. package/src/engine/control/first-person/math/Spring.d.ts.map +1 -0
  304. package/src/engine/control/first-person/math/Spring.js +71 -0
  305. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts +26 -0
  306. package/src/engine/control/first-person/math/computeLRCBreathRate.d.ts.map +1 -0
  307. package/src/engine/control/first-person/math/computeLRCBreathRate.js +41 -0
  308. package/src/engine/control/first-person/math/computeMassRatios.d.ts +35 -0
  309. package/src/engine/control/first-person/math/computeMassRatios.d.ts.map +1 -0
  310. package/src/engine/control/first-person/math/computeMassRatios.js +44 -0
  311. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts +31 -1
  312. package/src/engine/control/first-person/pose/FirstPersonPose.d.ts.map +1 -1
  313. package/src/engine/control/first-person/pose/FirstPersonPose.js +49 -3
  314. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts +7 -0
  315. package/src/engine/control/first-person/pose/FirstPersonPosture.d.ts.map +1 -0
  316. package/src/engine/control/first-person/pose/FirstPersonPosture.js +27 -0
  317. package/src/engine/control/first-person/prototype_first_person_controller.js +637 -120
  318. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +58 -0
  319. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -0
  320. package/src/engine/control/first-person/sensors/FirstPersonSensors.js +77 -0
  321. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +80 -0
  322. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -0
  323. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +196 -0
  324. package/src/engine/control/first-person/test/buildTestPlayer.d.ts +20 -0
  325. package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -0
  326. package/src/engine/control/first-person/test/buildTestPlayer.js +36 -0
  327. package/src/engine/graphics/camera/testClippingPlaneComputation.js +0 -2
  328. package/src/engine/graphics/ecs/light/Light.d.ts.map +1 -1
  329. package/src/engine/graphics/ecs/light/Light.js +27 -0
  330. package/src/engine/graphics/ecs/light/LightSystem.js +1 -1
  331. package/src/engine/graphics/ecs/path/PathDisplaySystem.d.ts.map +1 -1
  332. package/src/engine/graphics/ecs/path/testPathDisplaySystem.js +0 -2
  333. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +0 -2
  334. package/src/engine/graphics/geometry/CapsuleGeometry.d.ts +42 -0
  335. package/src/engine/graphics/geometry/CapsuleGeometry.d.ts.map +1 -0
  336. package/src/engine/graphics/geometry/CapsuleGeometry.js +171 -0
  337. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +0 -2
  338. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +0 -2
  339. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +0 -2
  340. package/src/engine/navigation/grid/find_path_on_grid_astar.d.ts.map +1 -1
  341. package/src/engine/navigation/grid/find_path_on_grid_astar.js +11 -2
  342. package/src/engine/navigation/mesh/bt_mesh_face_find_path.d.ts.map +1 -1
  343. package/src/engine/navigation/mesh/bt_mesh_face_find_path.js +11 -1
  344. package/src/engine/physics/BULLET_REVIEW.md +945 -0
  345. package/src/engine/physics/CANNON_REVIEW.md +1300 -0
  346. package/src/engine/physics/JOLT_REVIEW.md +913 -0
  347. package/src/engine/physics/PLAN.md +461 -0
  348. package/src/engine/physics/RAPIER_REVIEW.md +934 -0
  349. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -0
  350. package/src/engine/physics/body/BodyStorage.d.ts +187 -0
  351. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -0
  352. package/src/engine/physics/body/BodyStorage.js +427 -0
  353. package/src/engine/physics/broadphase/PairList.d.ts +62 -0
  354. package/src/engine/physics/broadphase/PairList.d.ts.map +1 -0
  355. package/src/engine/physics/broadphase/PairList.js +97 -0
  356. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +16 -0
  357. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -0
  358. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +61 -0
  359. package/src/engine/physics/broadphase/generate_pairs.d.ts +38 -0
  360. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -0
  361. package/src/engine/physics/broadphase/generate_pairs.js +101 -0
  362. package/src/engine/physics/contact/ManifoldStore.d.ts +299 -0
  363. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -0
  364. package/src/engine/physics/contact/ManifoldStore.js +608 -0
  365. package/src/engine/physics/ecs/BodyKind.d.ts +23 -0
  366. package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -0
  367. package/src/engine/physics/ecs/BodyKind.js +24 -0
  368. package/src/engine/physics/ecs/Collider.d.ts +98 -0
  369. package/src/engine/physics/ecs/Collider.d.ts.map +1 -0
  370. package/src/engine/physics/ecs/Collider.js +136 -0
  371. package/src/engine/physics/ecs/ColliderFlags.d.ts +14 -0
  372. package/src/engine/physics/ecs/ColliderFlags.d.ts.map +1 -0
  373. package/src/engine/physics/ecs/ColliderFlags.js +15 -0
  374. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +58 -0
  375. package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -0
  376. package/src/engine/physics/ecs/ColliderObserverSystem.js +103 -0
  377. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts +25 -0
  378. package/src/engine/physics/ecs/ColliderSerializationAdapter.d.ts.map +1 -0
  379. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +37 -0
  380. package/src/engine/physics/ecs/PhysicsEvents.d.ts +15 -0
  381. package/src/engine/physics/ecs/PhysicsEvents.d.ts.map +1 -0
  382. package/src/engine/physics/ecs/PhysicsEvents.js +16 -0
  383. package/src/engine/physics/ecs/PhysicsSystem.d.ts +628 -0
  384. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -0
  385. package/src/engine/physics/ecs/PhysicsSystem.js +1301 -0
  386. package/src/engine/physics/ecs/RigidBody.d.ts +197 -0
  387. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -0
  388. package/src/engine/physics/ecs/RigidBody.js +240 -0
  389. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +21 -0
  390. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -0
  391. package/src/engine/physics/ecs/RigidBodyFlags.js +22 -0
  392. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +28 -0
  393. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -0
  394. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +81 -0
  395. package/src/engine/physics/ecs/SleepState.d.ts +11 -0
  396. package/src/engine/physics/ecs/SleepState.d.ts.map +1 -0
  397. package/src/engine/physics/ecs/SleepState.js +12 -0
  398. package/src/engine/physics/events/ContactEventBuffer.d.ts +46 -0
  399. package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -0
  400. package/src/engine/physics/events/ContactEventBuffer.js +83 -0
  401. package/src/engine/physics/events/diff_manifolds.d.ts +25 -0
  402. package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -0
  403. package/src/engine/physics/events/diff_manifolds.js +50 -0
  404. package/src/engine/physics/fluid/FluidField.d.ts +294 -16
  405. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  406. package/src/engine/physics/fluid/FluidField.js +510 -66
  407. package/src/engine/physics/fluid/FluidSimulator.d.ts +188 -5
  408. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  409. package/src/engine/physics/fluid/FluidSimulator.js +456 -95
  410. package/src/engine/physics/fluid/SliceVisualiser.d.ts +29 -6
  411. package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
  412. package/src/engine/physics/fluid/SliceVisualiser.js +190 -165
  413. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +154 -0
  414. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -0
  415. package/src/engine/physics/fluid/ecs/FluidComponent.js +238 -0
  416. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +45 -0
  417. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts.map +1 -0
  418. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +89 -0
  419. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +107 -0
  420. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts.map +1 -0
  421. package/src/engine/physics/fluid/ecs/FluidSystem.js +278 -0
  422. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +62 -1
  423. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
  424. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +81 -6
  425. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +17 -4
  426. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
  427. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +105 -12
  428. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts +43 -0
  429. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -0
  430. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +210 -0
  431. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +62 -1
  432. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  433. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +302 -8
  434. package/src/engine/physics/fluid/prototype.js +102 -91
  435. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts +33 -0
  436. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +1 -0
  437. package/src/engine/physics/fluid/solver/optimal_sor_omega.js +41 -0
  438. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +20 -5
  439. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
  440. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +60 -38
  441. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +25 -4
  442. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
  443. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +93 -73
  444. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts +23 -0
  445. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.d.ts.map +1 -0
  446. package/src/engine/physics/fluid/solver/v3_grid_apply_scalar_advection.js +60 -0
  447. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts +23 -0
  448. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.d.ts.map +1 -0
  449. package/src/engine/physics/fluid/solver/v3_grid_compute_divergence.js +68 -0
  450. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +30 -0
  451. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -0
  452. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +66 -0
  453. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts +26 -0
  454. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.d.ts.map +1 -0
  455. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_uniform.js +113 -0
  456. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts +30 -0
  457. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.d.ts.map +1 -0
  458. package/src/engine/physics/fluid/solver/v3_grid_shift_in_place.js +107 -0
  459. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +49 -0
  460. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -0
  461. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +126 -0
  462. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +93 -0
  463. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -0
  464. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +424 -0
  465. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +48 -0
  466. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -0
  467. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +92 -0
  468. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts +6 -6
  469. package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
  470. package/src/engine/physics/gjk/expanding_polytope_algorithm.js +76 -32
  471. package/src/engine/physics/gjk/gjk.d.ts +28 -2
  472. package/src/engine/physics/gjk/gjk.d.ts.map +1 -1
  473. package/src/engine/physics/gjk/gjk.js +421 -378
  474. package/src/engine/physics/gjk/minkowski_support.d.ts +37 -0
  475. package/src/engine/physics/gjk/minkowski_support.d.ts.map +1 -0
  476. package/src/engine/physics/gjk/minkowski_support.js +75 -0
  477. package/src/engine/physics/gjk/mpr.d.ts +56 -0
  478. package/src/engine/physics/gjk/mpr.d.ts.map +1 -0
  479. package/src/engine/physics/gjk/mpr.js +344 -0
  480. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +44 -0
  481. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -0
  482. package/src/engine/physics/inertia/world_inverse_inertia.js +77 -0
  483. package/src/engine/physics/integration/integrate_position.d.ts +34 -0
  484. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -0
  485. package/src/engine/physics/integration/integrate_position.js +79 -0
  486. package/src/engine/physics/integration/integrate_velocity.d.ts +55 -0
  487. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -0
  488. package/src/engine/physics/integration/integrate_velocity.js +160 -0
  489. package/src/engine/physics/integration/quat_integrate.d.ts +27 -0
  490. package/src/engine/physics/integration/quat_integrate.d.ts.map +1 -0
  491. package/src/engine/physics/integration/quat_integrate.js +62 -0
  492. package/src/engine/physics/island/IslandBuilder.d.ts +167 -0
  493. package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -0
  494. package/src/engine/physics/island/IslandBuilder.js +411 -0
  495. package/src/engine/physics/island/union_find.d.ts +51 -0
  496. package/src/engine/physics/island/union_find.d.ts.map +1 -0
  497. package/src/engine/physics/island/union_find.js +76 -0
  498. package/src/engine/physics/narrowphase/PosedShape.d.ts +51 -0
  499. package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -0
  500. package/src/engine/physics/narrowphase/PosedShape.js +108 -0
  501. package/src/engine/physics/narrowphase/box_box_manifold.d.ts +32 -0
  502. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -0
  503. package/src/engine/physics/narrowphase/box_box_manifold.js +639 -0
  504. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts +30 -0
  505. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -0
  506. package/src/engine/physics/narrowphase/box_triangle_contact.js +811 -0
  507. package/src/engine/physics/narrowphase/capsule_contacts.d.ts +122 -0
  508. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -0
  509. package/src/engine/physics/narrowphase/capsule_contacts.js +462 -0
  510. package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts +71 -0
  511. package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts.map +1 -0
  512. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +375 -0
  513. package/src/engine/physics/narrowphase/compute_penetration.d.ts +91 -0
  514. package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -0
  515. package/src/engine/physics/narrowphase/compute_penetration.js +396 -0
  516. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts +35 -0
  517. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts.map +1 -0
  518. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.js +80 -0
  519. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.d.ts +31 -0
  520. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.d.ts.map +1 -0
  521. package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -0
  522. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +42 -0
  523. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -0
  524. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +204 -0
  525. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts +42 -0
  526. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -0
  527. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +94 -0
  528. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts +37 -0
  529. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts.map +1 -0
  530. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -0
  531. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +17 -0
  532. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -0
  533. package/src/engine/physics/narrowphase/narrowphase_step.js +1422 -0
  534. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts +38 -0
  535. package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -0
  536. package/src/engine/physics/narrowphase/sphere_box_contact.js +123 -0
  537. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts +26 -0
  538. package/src/engine/physics/narrowphase/sphere_sphere_contact.d.ts.map +1 -0
  539. package/src/engine/physics/narrowphase/sphere_sphere_contact.js +51 -0
  540. package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts +48 -0
  541. package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts.map +1 -0
  542. package/src/engine/physics/narrowphase/sphere_triangle_contact.js +143 -0
  543. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +83 -0
  544. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -0
  545. package/src/engine/physics/queries/PhysicsSurfacePoint.js +100 -0
  546. package/src/engine/physics/queries/overlap_shape.d.ts +51 -0
  547. package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -0
  548. package/src/engine/physics/queries/overlap_shape.js +183 -0
  549. package/src/engine/physics/queries/raycast.d.ts +20 -0
  550. package/src/engine/physics/queries/raycast.d.ts.map +1 -0
  551. package/src/engine/physics/queries/raycast.js +249 -0
  552. package/src/engine/physics/queries/shape_cast.d.ts +56 -0
  553. package/src/engine/physics/queries/shape_cast.d.ts.map +1 -0
  554. package/src/engine/physics/queries/shape_cast.js +387 -0
  555. package/src/engine/physics/solver/friction_cone.d.ts +16 -0
  556. package/src/engine/physics/solver/friction_cone.d.ts.map +1 -0
  557. package/src/engine/physics/solver/friction_cone.js +37 -0
  558. package/src/engine/physics/solver/solve_contacts.d.ts +122 -0
  559. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -0
  560. package/src/engine/physics/solver/solve_contacts.js +1016 -0
  561. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts +0 -34
  562. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.d.ts.map +0 -1
  563. package/src/core/geom/3d/topology/struct/binary/io/edge/OrderedEdge.js +0 -66
  564. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts +0 -2
  565. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.d.ts.map +0 -1
  566. package/src/core/geom/3d/topology/struct/binary/io/edge/bt_mesh_calc_edges.js +0 -54
  567. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts +0 -2
  568. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.d.ts.map +0 -1
  569. package/src/core/geom/3d/topology/struct/binary/io/edge/get_or_create_edge_map.js +0 -26
  570. package/src/engine/ecs/components/Motion.d.ts +0 -21
  571. package/src/engine/ecs/components/Motion.d.ts.map +0 -1
  572. package/src/engine/ecs/components/Motion.js +0 -27
  573. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts +0 -20
  574. package/src/engine/ecs/components/MotionSerializationAdapter.d.ts.map +0 -1
  575. package/src/engine/ecs/components/MotionSerializationAdapter.js +0 -26
  576. package/src/engine/ecs/systems/MotionSystem.d.ts +0 -9
  577. package/src/engine/ecs/systems/MotionSystem.d.ts.map +0 -1
  578. package/src/engine/ecs/systems/MotionSystem.js +0 -29
  579. package/src/engine/physics/fluid/Fluid.d.ts +0 -26
  580. package/src/engine/physics/fluid/Fluid.d.ts.map +0 -1
  581. package/src/engine/physics/fluid/Fluid.js +0 -221
  582. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts +0 -7
  583. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.d.ts.map +0 -1
  584. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_reverse.js +0 -8
@@ -0,0 +1,1016 @@
1
+ import { BodyKind } from "../ecs/BodyKind.js";
2
+ import { ColliderFlags } from "../ecs/ColliderFlags.js";
3
+ import { CONTACT_STRIDE } from "../contact/ManifoldStore.js";
4
+ import { RigidBodyFlags } from "../ecs/RigidBodyFlags.js";
5
+ import { world_inverse_inertia_apply } from "../inertia/world_inverse_inertia.js";
6
+ import { v3_quat3_apply } from "../../../core/geom/vec3/v3_quat3_apply.js";
7
+ import { v3_quat3_apply_inverse } from "../../../core/geom/vec3/v3_quat3_apply_inverse.js";
8
+ import { friction_cone_clamp } from "./friction_cone.js";
9
+
10
+ /**
11
+ * # TGS split-impulse contact solver (staged)
12
+ *
13
+ * Temporal Gauss-Seidel with Catto-2018 split impulse. The solver runs as a
14
+ * sequence of stages driven by `PhysicsSystem.fixedUpdate`, which owns the
15
+ * substep loop (it has to — velocity/position integration spans every awake
16
+ * body, not just contacts):
17
+ *
18
+ * prepare_contacts(manifolds, system, h) // once per outer step
19
+ * for each substep:
20
+ * (system integrates gravity by h)
21
+ * refresh_contacts(manifolds, system) // re-derive geometry
22
+ * warm_start_contacts(manifolds, system) // replay impulse — per substep!
23
+ * solve_velocity(manifolds, system, iters) // non-penetration + friction
24
+ * solve_position(manifolds, system, pos_iters)
25
+ * (system integrates position by h, folding pseudo-velocity)
26
+ * apply_restitution(manifolds, system) // once, after the loop
27
+ *
28
+ * The three concerns are fully decoupled (Phases 1–2) and substepping
29
+ * (Phase 3) re-runs only the velocity + position solve per substep —
30
+ * narrowphase runs once per outer step. Each substep re-derives the
31
+ * current penetration analytically from the bodies' moved poses and the
32
+ * contact anchors captured at prepare time, so the position correction
33
+ * adapts as the stack settles (the mechanism behind TGS stack stability)
34
+ * without paying for narrowphase N times.
35
+ *
36
+ * Why staged module functions sharing module scratch, rather than one call:
37
+ * the substep loop interleaves solver stages with whole-body integration
38
+ * that lives in the system. The stages communicate through module-scoped
39
+ * scratch + `g_*` state set by `prepare_contacts`; they must be called in
40
+ * order, prepare first, within a single outer step. Single-threaded and
41
+ * deterministic, so the shared state is safe.
42
+ *
43
+ * Contacts from all islands are flattened into one scratch array. Islands
44
+ * are independent (they share no bodies), so a single flat Gauss-Seidel
45
+ * sweep gives the same result as per-island sweeps — the island partition
46
+ * is still built and used by the sleep test, just not needed here.
47
+ */
48
+
49
+ /**
50
+ * A pair is "sensor-only" when either body OR either body's primary
51
+ * collider carries the IsSensor flag. The manifold still exists (so
52
+ * Begin/Stay/End events fire from the manifold-diff pass) but no impulse
53
+ * is applied.
54
+ *
55
+ * @param {RigidBody} rbA
56
+ * @param {Collider} colA
57
+ * @param {RigidBody} rbB
58
+ * @param {Collider} colB
59
+ * @returns {boolean}
60
+ */
61
+ function pair_is_sensor(rbA, colA, rbB, colB) {
62
+ return (rbA.flags & RigidBodyFlags.IsSensor) !== 0
63
+ || (rbB.flags & RigidBodyFlags.IsSensor) !== 0
64
+ || (colA.flags & ColliderFlags.IsSensor) !== 0
65
+ || (colB.flags & ColliderFlags.IsSensor) !== 0;
66
+ }
67
+
68
+ /**
69
+ * Velocity-iteration count per substep. With substepping the per-substep
70
+ * count can be lower than a single-step PGS solver would need, because the
71
+ * outer loop revisits the contact set `substeps` times.
72
+ * @type {number}
73
+ */
74
+ const DEFAULT_VELOCITY_ITERATIONS = 10;
75
+
76
+ /**
77
+ * Position-iteration count per substep (split-impulse pseudo-velocity pass).
78
+ * @type {number}
79
+ */
80
+ const DEFAULT_POSITION_ITERATIONS = 2;
81
+
82
+ /**
83
+ * Penetration allowed without applying position correction. Eliminates
84
+ * micro-jitter at near-zero overlap.
85
+ * @type {number}
86
+ */
87
+ const PENETRATION_SLOP = 0.005;
88
+
89
+ /**
90
+ * SPOOK contact stiffness `k`. Effectively infinite for rigid-body
91
+ * contact: what the solver actually sees is the regularization
92
+ * `eps = 4 / (h² · k · (1 + 4d))`, negligible at `k = 1e12` but in place
93
+ * as a continuous compliance dial for future soft contacts. Lacoursière
94
+ * 2007; same formulation as cannon-es / AgX.
95
+ * @type {number}
96
+ */
97
+ const CONTACT_STIFFNESS = 1e12;
98
+
99
+ /**
100
+ * SPOOK contact relaxation `d`. Chosen so `a = 4 / (h(1 + 4d)) = 0.2 / h`,
101
+ * numerically matching the prior Baumgarte β = 0.2 gain. `4/(1+4d)=0.2` →
102
+ * `d = 4.75`. Note `h` here is the SUBSTEP size: position correction is
103
+ * applied per substep, so the gain is derived from the substep `dt`.
104
+ * @type {number}
105
+ */
106
+ const CONTACT_RELAXATION = 4.75;
107
+
108
+ /**
109
+ * Maximum magnitude of the position-correction velocity bias, in m/s.
110
+ * Belt-and-braces against inflated EPA depths (PLAN.md caveat) driving the
111
+ * bias to tens of m/s. Removed once closed-form triangle solvers land.
112
+ * @type {number}
113
+ */
114
+ const MAX_POSITION_BIAS = 3;
115
+
116
+ /**
117
+ * Velocity below which restitution is suppressed (no micro-bounce buzz on
118
+ * resting stacks).
119
+ * @type {number}
120
+ */
121
+ const RESTITUTION_VELOCITY_THRESHOLD = 1.0;
122
+
123
+ /**
124
+ * Per-contact pre-step scratch stride: 23 doubles.
125
+ * 0..2 : localWA (A's contact witness, in A's LOCAL frame — constant)
126
+ * 3..5 : localWB (B's contact witness, in B's LOCAL frame — constant)
127
+ * 6..8 : rA (lever from A's COM to the contact midpoint — refreshed)
128
+ * 9..11: rB (lever from B's COM to the contact midpoint — refreshed)
129
+ * 12..14: t1 (tangent 1, unit, world — constant)
130
+ * 15..17: t2 (tangent 2, unit, world — constant)
131
+ * 18 : m_eff_n
132
+ * 19 : m_eff_t1
133
+ * 20 : m_eff_t2
134
+ * 21 : rest_bias (restitution: `e · vn_approach`, ≤ 0; 0 if not bouncing)
135
+ * 22 : bias_position (depth-correction bias — refreshed each substep)
136
+ *
137
+ * `localWA` / `localWB` are the per-body contact witnesses expressed in body
138
+ * local frames at prepare time. Each substep, `refresh_contacts` rotates
139
+ * them back to world by the body's current pose to recover the moved contact
140
+ * points, re-derives the current penetration depth (anchored on the trusted
141
+ * prepare-time depth via a delta, so it's sign-robust), and rebuilds the
142
+ * impulse lever arms `rA` / `rB` and the position bias.
143
+ * @type {number}
144
+ */
145
+ const PRE_STRIDE = 23;
146
+
147
+ /** Per-contact index list — 4 uint32 per contact: slot, idx, idxA, idxB. */
148
+ const INDEX_STRIDE = 4;
149
+
150
+ /**
151
+ * Per-body pseudo-velocity stride: 3 linear + 3 angular doubles. Owned by
152
+ * PhysicsSystem (`system.__pseudo_velocity`); zeroed each substep before
153
+ * the position pass and folded into the pose by `integrate_position`.
154
+ * @type {number}
155
+ */
156
+ const PSEUDO_STRIDE = 6;
157
+
158
+ let scratch_pre = new Float64Array(64 * PRE_STRIDE);
159
+ let scratch_idx = new Uint32Array(64 * INDEX_STRIDE);
160
+ let scratch_mu = new Float64Array(64);
161
+ let scratch_pos_jn = new Float64Array(64);
162
+
163
+ /**
164
+ * Per-contact maximum normal impulse seen across the whole outer step's
165
+ * velocity solving (all substeps, all iterations). Reset in
166
+ * {@link prepare_contacts}, updated in {@link solve_velocity}, read by
167
+ * {@link apply_restitution}.
168
+ *
169
+ * Restitution must fire whenever a contact *was* compressive at some point
170
+ * in the step, even if its accumulated impulse later relaxes back to ~0 — a
171
+ * transient collision (ball bouncing, head-on hit) under per-substep
172
+ * warm-start ends the loop with `j_n ≈ 0` because there's no sustained load
173
+ * to hold the impulse up. Gating on this running max (Box2D-v3
174
+ * `maxNormalImpulse`) rather than the end-of-loop `j_n` is what makes
175
+ * bounces fire.
176
+ * @type {Float64Array}
177
+ */
178
+ let scratch_max_jn = new Float64Array(64);
179
+
180
+ /**
181
+ * Shared cross-stage state, set by {@link prepare_contacts} and read by the
182
+ * per-substep stages within the same outer step. Single-threaded, so plain
183
+ * module variables are safe.
184
+ */
185
+ let g_contact_count = 0;
186
+ let g_spook_a = 0;
187
+ let g_spook_eps = 0;
188
+
189
+ /** Scratch for re-deriving contact world points in {@link refresh_contacts}. */
190
+ const scratch_cp = new Float64Array(6);
191
+
192
+ function ensure_capacity(n) {
193
+ if (scratch_pre.length < n * PRE_STRIDE) {
194
+ scratch_pre = new Float64Array(n * PRE_STRIDE * 2);
195
+ }
196
+ if (scratch_idx.length < n * INDEX_STRIDE) {
197
+ scratch_idx = new Uint32Array(n * INDEX_STRIDE * 2);
198
+ }
199
+ if (scratch_mu.length < n) {
200
+ scratch_mu = new Float64Array(n * 2);
201
+ }
202
+ if (scratch_pos_jn.length < n) {
203
+ scratch_pos_jn = new Float64Array(n * 2);
204
+ }
205
+ if (scratch_max_jn.length < n) {
206
+ scratch_max_jn = new Float64Array(n * 2);
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Build an orthonormal tangent basis perpendicular to a unit normal.
212
+ *
213
+ * @param {Float64Array} out 6 floats: t1.xyz then t2.xyz
214
+ * @param {number} off
215
+ * @param {number} nx
216
+ * @param {number} ny
217
+ * @param {number} nz
218
+ */
219
+ function build_tangents(out, off, nx, ny, nz) {
220
+ const ax = nx < 0 ? -nx : nx;
221
+ const ay = ny < 0 ? -ny : ny;
222
+ const az = nz < 0 ? -nz : nz;
223
+
224
+ let rx, ry, rz;
225
+ if (ax <= ay && ax <= az) {
226
+ rx = 1; ry = 0; rz = 0;
227
+ } else if (ay <= az) {
228
+ rx = 0; ry = 1; rz = 0;
229
+ } else {
230
+ rx = 0; ry = 0; rz = 1;
231
+ }
232
+ let t1x = ny * rz - nz * ry;
233
+ let t1y = nz * rx - nx * rz;
234
+ let t1z = nx * ry - ny * rx;
235
+ const inv = 1 / Math.sqrt(t1x * t1x + t1y * t1y + t1z * t1z);
236
+ t1x *= inv; t1y *= inv; t1z *= inv;
237
+
238
+ const t2x = ny * t1z - nz * t1y;
239
+ const t2y = nz * t1x - nx * t1z;
240
+ const t2z = nx * t1y - ny * t1x;
241
+
242
+ out[off] = t1x; out[off + 1] = t1y; out[off + 2] = t1z;
243
+ out[off + 3] = t2x; out[off + 4] = t2y; out[off + 5] = t2z;
244
+ }
245
+
246
+ /**
247
+ * @param {RigidBody} rb
248
+ * @returns {number}
249
+ */
250
+ function inv_mass_of(rb) {
251
+ if (rb.kind !== BodyKind.Dynamic) return 0;
252
+ return rb.mass > 0 ? 1 / rb.mass : 0;
253
+ }
254
+
255
+ /**
256
+ * Combine two friction coefficients (geometric mean — Bullet / PhysX default).
257
+ * @param {number} a
258
+ * @param {number} b
259
+ * @returns {number}
260
+ */
261
+ function combine_friction(a, b) {
262
+ return Math.sqrt(a * b);
263
+ }
264
+
265
+ /**
266
+ * Combine two restitution coefficients (maximum — Unity / common default).
267
+ * @param {number} a
268
+ * @param {number} b
269
+ * @returns {number}
270
+ */
271
+ function combine_restitution(a, b) {
272
+ return a > b ? a : b;
273
+ }
274
+
275
+ const scratch_clamp = new Float64Array(2);
276
+ const scratch_inertia_a = new Float64Array(3);
277
+ const scratch_inertia_b = new Float64Array(3);
278
+
279
+ /**
280
+ * Apply an impulse `P` at body-relative offset `r` to persistent velocity
281
+ * (Δv = P/m, Δω = I⁻¹·(r × P)). Direct typed-array writes bypass
282
+ * {@link Vector3#set}'s observer dispatch (dead weight in the solver loop).
283
+ *
284
+ * @param {RigidBody} rb
285
+ * @param {Transform} transform
286
+ * @param {number} invM
287
+ * @param {number} rx @param {number} ry @param {number} rz
288
+ * @param {number} Px @param {number} Py @param {number} Pz
289
+ * @param {number} sign +1 for body A, -1 for body B
290
+ * @param {Float64Array} scratch_inertia
291
+ */
292
+ function apply_impulse_to_body(
293
+ rb, transform, invM,
294
+ rx, ry, rz,
295
+ Px, Py, Pz,
296
+ sign,
297
+ scratch_inertia
298
+ ) {
299
+ if (invM === 0) return;
300
+
301
+ const sPx = sign * Px;
302
+ const sPy = sign * Py;
303
+ const sPz = sign * Pz;
304
+
305
+ const lv = rb.linearVelocity;
306
+ lv[0] += sPx * invM;
307
+ lv[1] += sPy * invM;
308
+ lv[2] += sPz * invM;
309
+
310
+ const tx = ry * sPz - rz * sPy;
311
+ const ty = rz * sPx - rx * sPz;
312
+ const tz = rx * sPy - ry * sPx;
313
+
314
+ world_inverse_inertia_apply(scratch_inertia, 0, rb.inverseInertiaLocal, transform.rotation, tx, ty, tz);
315
+
316
+ const av = rb.angularVelocity;
317
+ av[0] += scratch_inertia[0];
318
+ av[1] += scratch_inertia[1];
319
+ av[2] += scratch_inertia[2];
320
+ }
321
+
322
+ /**
323
+ * Apply a position-pass impulse `P` at body-relative offset `r` to the
324
+ * body's pseudo-velocity (linear + angular) in the `pseudo_velocity` flat
325
+ * buffer. Mirrors {@link apply_impulse_to_body} but the result is consumed
326
+ * by `integrate_position` the same substep and never persists.
327
+ *
328
+ * @param {Float64Array} pseudo_velocity stride = {@link PSEUDO_STRIDE}
329
+ * @param {number} base offset = `body_index * PSEUDO_STRIDE`
330
+ * @param {RigidBody} rb @param {Transform} transform @param {number} invM
331
+ * @param {number} rx @param {number} ry @param {number} rz
332
+ * @param {number} Px @param {number} Py @param {number} Pz
333
+ * @param {number} sign +1 for body A, -1 for body B
334
+ * @param {Float64Array} scratch_inertia
335
+ */
336
+ function apply_impulse_to_pseudo(
337
+ pseudo_velocity, base,
338
+ rb, transform, invM,
339
+ rx, ry, rz,
340
+ Px, Py, Pz,
341
+ sign,
342
+ scratch_inertia
343
+ ) {
344
+ if (invM === 0) return;
345
+
346
+ const sPx = sign * Px;
347
+ const sPy = sign * Py;
348
+ const sPz = sign * Pz;
349
+
350
+ pseudo_velocity[base] += sPx * invM;
351
+ pseudo_velocity[base + 1] += sPy * invM;
352
+ pseudo_velocity[base + 2] += sPz * invM;
353
+
354
+ const tx = ry * sPz - rz * sPy;
355
+ const ty = rz * sPx - rx * sPz;
356
+ const tz = rx * sPy - ry * sPx;
357
+
358
+ world_inverse_inertia_apply(scratch_inertia, 0, rb.inverseInertiaLocal, transform.rotation, tx, ty, tz);
359
+
360
+ pseudo_velocity[base + 3] += scratch_inertia[0];
361
+ pseudo_velocity[base + 4] += scratch_inertia[1];
362
+ pseudo_velocity[base + 5] += scratch_inertia[2];
363
+ }
364
+
365
+ /**
366
+ * Quadratic-form contribution of one body to the constraint effective mass
367
+ * along a unit axis: `(r × axis)^T · I⁻¹_world · (r × axis)`.
368
+ *
369
+ * @param {RigidBody} rb @param {Transform} transform
370
+ * @param {number} rx @param {number} ry @param {number} rz
371
+ * @param {number} ax @param {number} ay @param {number} az
372
+ * @param {Float64Array} scratch_inertia
373
+ * @returns {number}
374
+ */
375
+ function angular_jacobian_contribution(
376
+ rb, transform,
377
+ rx, ry, rz,
378
+ ax, ay, az,
379
+ scratch_inertia
380
+ ) {
381
+ if (rb.kind !== BodyKind.Dynamic) return 0;
382
+ const ii = rb.inverseInertiaLocal;
383
+ if (ii.x === 0 && ii.y === 0 && ii.z === 0) return 0;
384
+
385
+ const rxax = ry * az - rz * ay;
386
+ const rxay = rz * ax - rx * az;
387
+ const rxaz = rx * ay - ry * ax;
388
+
389
+ world_inverse_inertia_apply(scratch_inertia, 0, ii, transform.rotation, rxax, rxay, rxaz);
390
+
391
+ return rxax * scratch_inertia[0]
392
+ + rxay * scratch_inertia[1]
393
+ + rxaz * scratch_inertia[2];
394
+ }
395
+
396
+ /**
397
+ * Flat count of all touched contacts across every island, plus the slot
398
+ * list to iterate. Islands are concatenated densely in `contact_data`;
399
+ * `contact_offsets[island_count]` is the end of the last island.
400
+ *
401
+ * @param {PhysicsSystem} system
402
+ * @returns {{slot_list: Uint32Array, total_slots: number}|null}
403
+ */
404
+ function island_slot_range(system) {
405
+ const islands = system.islands;
406
+ if (islands === undefined || islands === null) return null;
407
+ const island_count = islands.island_count;
408
+ if (island_count === 0) return null;
409
+ return {
410
+ slot_list: islands.contact_data,
411
+ total_slots: islands.contact_offsets[island_count],
412
+ };
413
+ }
414
+
415
+ /**
416
+ * Stage 1 — prepare the contact constraints for an outer step.
417
+ *
418
+ * Packs every touched, non-sensor contact into the flat scratch arrays:
419
+ * local-frame witness anchors, tangent basis, effective masses, friction,
420
+ * the restitution approach velocity, and the warm-start replay (applied
421
+ * once here, not per substep). Computes the SPOOK gains from the SUBSTEP
422
+ * size `dt_sub` because the position correction runs once per substep.
423
+ *
424
+ * @param {ManifoldStore} manifolds
425
+ * @param {PhysicsSystem} system
426
+ * @param {number} dt_sub substep size `dt / substeps`
427
+ * @returns {number} number of contacts prepared (also stored module-side)
428
+ */
429
+ export function prepare_contacts(manifolds, system, dt_sub) {
430
+ g_contact_count = 0;
431
+ if (dt_sub <= 0) return 0;
432
+
433
+ const range = island_slot_range(system);
434
+ if (range === null) return 0;
435
+ const slot_list = range.slot_list;
436
+ const total_slots = range.total_slots;
437
+
438
+ let contact_total = 0;
439
+ for (let i = 0; i < total_slots; i++) {
440
+ contact_total += manifolds.contact_count(slot_list[i]);
441
+ }
442
+ if (contact_total === 0) return 0;
443
+ ensure_capacity(contact_total);
444
+
445
+ const denom = 1 + 4 * CONTACT_RELAXATION;
446
+ g_spook_a = 4 / (dt_sub * denom);
447
+ g_spook_eps = 4 / (dt_sub * dt_sub * CONTACT_STIFFNESS * denom);
448
+
449
+ const data = manifolds.data_buffer;
450
+ const pre = scratch_pre;
451
+ const idx = scratch_idx;
452
+ const mus = scratch_mu;
453
+ const pos_jn = scratch_pos_jn;
454
+
455
+ let c = 0;
456
+ for (let i = 0; i < total_slots; i++) {
457
+ const slot = slot_list[i];
458
+ const idxA = system.__index_of(manifolds.bodyA(slot));
459
+ const idxB = system.__index_of(manifolds.bodyB(slot));
460
+ const rbA = system.__bodies[idxA];
461
+ const rbB = system.__bodies[idxB];
462
+ const trA = system.__transforms[idxA];
463
+ const trB = system.__transforms[idxB];
464
+ const colA = system.__primary_collider(idxA);
465
+ const colB = system.__primary_collider(idxB);
466
+ if (colA === null || colB === null) continue;
467
+ if (pair_is_sensor(rbA, colA, rbB, colB)) continue;
468
+
469
+ const invMA = inv_mass_of(rbA);
470
+ const invMB = inv_mass_of(rbB);
471
+
472
+ const cc = manifolds.contact_count(slot);
473
+ const slot_off = manifolds.slot_data_offset(slot);
474
+ const restitution_combined = combine_restitution(colA.restitution, colB.restitution);
475
+ const friction_combined = combine_friction(colA.friction, colB.friction);
476
+
477
+ const pAx = trA.position.x, pAy = trA.position.y, pAz = trA.position.z;
478
+ const pBx = trB.position.x, pBy = trB.position.y, pBz = trB.position.z;
479
+ const qA = trA.rotation, qB = trB.rotation;
480
+
481
+ for (let k = 0; k < cc; k++) {
482
+ const off = slot_off + k * CONTACT_STRIDE;
483
+
484
+ const wax = data[off], way = data[off + 1], waz = data[off + 2];
485
+ const wbx = data[off + 3], wby = data[off + 4], wbz = data[off + 5];
486
+ const nx = data[off + 6], ny = data[off + 7], nz = data[off + 8];
487
+
488
+ const px = (wax + wbx) * 0.5;
489
+ const py = (way + wby) * 0.5;
490
+ const pz = (waz + wbz) * 0.5;
491
+
492
+ const rax = px - pAx, ray = py - pAy, raz = pz - pAz;
493
+ const rbx = px - pBx, rby = py - pBy, rbz = pz - pBz;
494
+
495
+ const pre_off = c * PRE_STRIDE;
496
+
497
+ // Per-body witness anchors in LOCAL frame (constant across the
498
+ // outer step). localW = R⁻¹ · (witness − COM).
499
+ v3_quat3_apply_inverse(pre, pre_off, wax - pAx, way - pAy, waz - pAz, qA[0], qA[1], qA[2], qA[3]);
500
+ v3_quat3_apply_inverse(pre, pre_off + 3, wbx - pBx, wby - pBy, wbz - pBz, qB[0], qB[1], qB[2], qB[3]);
501
+
502
+ // Lever arms from COM to the contact midpoint (refreshed each
503
+ // substep; seeded here from prepare-time pose).
504
+ pre[pre_off + 6] = rax; pre[pre_off + 7] = ray; pre[pre_off + 8] = raz;
505
+ pre[pre_off + 9] = rbx; pre[pre_off + 10] = rby; pre[pre_off + 11] = rbz;
506
+
507
+ build_tangents(pre, pre_off + 12, nx, ny, nz);
508
+ const t1x = pre[pre_off + 12], t1y = pre[pre_off + 13], t1z = pre[pre_off + 14];
509
+ const t2x = pre[pre_off + 15], t2y = pre[pre_off + 16], t2z = pre[pre_off + 17];
510
+
511
+ const k_n = invMA + invMB
512
+ + angular_jacobian_contribution(rbA, trA, rax, ray, raz, nx, ny, nz, scratch_inertia_a)
513
+ + angular_jacobian_contribution(rbB, trB, rbx, rby, rbz, nx, ny, nz, scratch_inertia_b);
514
+ const k_t1 = invMA + invMB
515
+ + angular_jacobian_contribution(rbA, trA, rax, ray, raz, t1x, t1y, t1z, scratch_inertia_a)
516
+ + angular_jacobian_contribution(rbB, trB, rbx, rby, rbz, t1x, t1y, t1z, scratch_inertia_b);
517
+ const k_t2 = invMA + invMB
518
+ + angular_jacobian_contribution(rbA, trA, rax, ray, raz, t2x, t2y, t2z, scratch_inertia_a)
519
+ + angular_jacobian_contribution(rbB, trB, rbx, rby, rbz, t2x, t2y, t2z, scratch_inertia_b);
520
+
521
+ const k_n_eff = k_n + g_spook_eps;
522
+ pre[pre_off + 18] = k_n_eff > 0 ? 1 / k_n_eff : 0;
523
+ pre[pre_off + 19] = k_t1 > 0 ? 1 / k_t1 : 0;
524
+ pre[pre_off + 20] = k_t2 > 0 ? 1 / k_t2 : 0;
525
+
526
+ // Restitution approach velocity (captured once, this is the
527
+ // closing speed entering the step). n is B → A; vn < 0 closing.
528
+ const lvA = rbA.linearVelocity, avA = rbA.angularVelocity;
529
+ const lvB = rbB.linearVelocity, avB = rbB.angularVelocity;
530
+ const vAx_at = lvA[0] + avA[1] * raz - avA[2] * ray;
531
+ const vAy_at = lvA[1] + avA[2] * rax - avA[0] * raz;
532
+ const vAz_at = lvA[2] + avA[0] * ray - avA[1] * rax;
533
+ const vBx_at = lvB[0] + avB[1] * rbz - avB[2] * rby;
534
+ const vBy_at = lvB[1] + avB[2] * rbx - avB[0] * rbz;
535
+ const vBz_at = lvB[2] + avB[0] * rby - avB[1] * rbx;
536
+ const vn_pre = (vAx_at - vBx_at) * nx + (vAy_at - vBy_at) * ny + (vAz_at - vBz_at) * nz;
537
+
538
+ let rest_bias = 0;
539
+ if (vn_pre < -RESTITUTION_VELOCITY_THRESHOLD) {
540
+ rest_bias = restitution_combined * vn_pre;
541
+ }
542
+ pre[pre_off + 21] = rest_bias;
543
+ pre[pre_off + 22] = 0; // bias_position — filled by refresh_contacts
544
+
545
+ mus[c] = friction_combined;
546
+ pos_jn[c] = 0;
547
+ scratch_max_jn[c] = 0;
548
+
549
+ idx[c * INDEX_STRIDE] = slot;
550
+ idx[c * INDEX_STRIDE + 1] = k;
551
+ idx[c * INDEX_STRIDE + 2] = idxA;
552
+ idx[c * INDEX_STRIDE + 3] = idxB;
553
+
554
+ // Warm-start is NOT applied here: under TGS it must be replayed
555
+ // *every substep* (see warm_start_contacts) so that, per substep,
556
+ // the cached impulse balances exactly one substep of gravity.
557
+ // Applying the cached impulse once against a full frame of
558
+ // gravity (the non-substepped pattern) over-pushes resting
559
+ // contacts and jitters / explodes deep stacks.
560
+
561
+ c++;
562
+ }
563
+ }
564
+
565
+ g_contact_count = c;
566
+ return c;
567
+ }
568
+
569
+ /**
570
+ * Stage 1b (per substep) — warm-start: replay the cached accumulated
571
+ * impulses `(j_n, j_t1, j_t2)` onto persistent velocity using the current
572
+ * (refreshed) lever arms and tangents. Run once per substep, after
573
+ * {@link refresh_contacts} and before {@link solve_velocity}.
574
+ *
575
+ * Per-substep warm-start is the crux of stable TGS: the stored impulse is a
576
+ * per-substep quantity (≈ the impulse to counter one substep of gravity), so
577
+ * replaying it each substep balances that substep's `integrate_velocity_gravity`
578
+ * and a resting contact holds at zero velocity. `solve_velocity` then only
579
+ * has to correct the residual, which converges in a few iterations even for
580
+ * deep chains because each substep carries just `h` of gravity.
581
+ *
582
+ * @param {ManifoldStore} manifolds
583
+ * @param {PhysicsSystem} system
584
+ */
585
+ export function warm_start_contacts(manifolds, system) {
586
+ const count = g_contact_count;
587
+ if (count === 0) return;
588
+
589
+ const data = manifolds.data_buffer;
590
+ const pre = scratch_pre;
591
+ const idx = scratch_idx;
592
+
593
+ for (let ci = 0; ci < count; ci++) {
594
+ const slot = idx[ci * INDEX_STRIDE];
595
+ const cidx = idx[ci * INDEX_STRIDE + 1];
596
+ const idxA = idx[ci * INDEX_STRIDE + 2];
597
+ const idxB = idx[ci * INDEX_STRIDE + 3];
598
+ const rbA = system.__bodies[idxA];
599
+ const rbB = system.__bodies[idxB];
600
+ const trA = system.__transforms[idxA];
601
+ const trB = system.__transforms[idxB];
602
+ const invMA = inv_mass_of(rbA);
603
+ const invMB = inv_mass_of(rbB);
604
+
605
+ const pre_off = ci * PRE_STRIDE;
606
+ const rax = pre[pre_off + 6], ray = pre[pre_off + 7], raz = pre[pre_off + 8];
607
+ const rbx = pre[pre_off + 9], rby = pre[pre_off + 10], rbz = pre[pre_off + 11];
608
+ const t1x = pre[pre_off + 12], t1y = pre[pre_off + 13], t1z = pre[pre_off + 14];
609
+ const t2x = pre[pre_off + 15], t2y = pre[pre_off + 16], t2z = pre[pre_off + 17];
610
+
611
+ const slot_off = manifolds.slot_data_offset(slot);
612
+ const off = slot_off + cidx * CONTACT_STRIDE;
613
+ const nx = data[off + 6], ny = data[off + 7], nz = data[off + 8];
614
+
615
+ const j_n = data[off + 10];
616
+ const j_t1 = data[off + 11];
617
+ const j_t2 = data[off + 12];
618
+ const Px = nx * j_n + t1x * j_t1 + t2x * j_t2;
619
+ const Py = ny * j_n + t1y * j_t1 + t2y * j_t2;
620
+ const Pz = nz * j_n + t1z * j_t1 + t2z * j_t2;
621
+ apply_impulse_to_body(rbA, trA, invMA, rax, ray, raz, Px, Py, Pz, +1, scratch_inertia_a);
622
+ apply_impulse_to_body(rbB, trB, invMB, rbx, rby, rbz, Px, Py, Pz, -1, scratch_inertia_b);
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Stage 2 (per substep) — re-derive each contact's geometry from the
628
+ * bodies' current poses and the local witness anchors captured at prepare.
629
+ *
630
+ * For each contact:
631
+ * - rotate the stored local witnesses back to world by the current pose to
632
+ * get the moved contact points `cpA`, `cpB`;
633
+ * - current penetration `depth_now = depth0 − Δseparation`, where
634
+ * `Δseparation = (cpA − wA − (cpB − wB)) · n` is the change since prepare.
635
+ * Anchoring on the trusted prepare-time depth makes the sign convention
636
+ * irrelevant — only the analytic delta uses the anchors;
637
+ * - rebuild the impulse levers `rA`/`rB` from the moved midpoint;
638
+ * - recompute the position-correction bias from `depth_now`.
639
+ *
640
+ * The contact normal and tangents are held fixed for the outer step (valid
641
+ * for the small per-step rotation), so they are not recomputed here.
642
+ *
643
+ * @param {ManifoldStore} manifolds
644
+ * @param {PhysicsSystem} system
645
+ */
646
+ export function refresh_contacts(manifolds, system) {
647
+ const count = g_contact_count;
648
+ if (count === 0) return;
649
+
650
+ const data = manifolds.data_buffer;
651
+ const pre = scratch_pre;
652
+ const idx = scratch_idx;
653
+ const cp = scratch_cp;
654
+ const spook_a = g_spook_a;
655
+
656
+ for (let ci = 0; ci < count; ci++) {
657
+ const slot = idx[ci * INDEX_STRIDE];
658
+ const cidx = idx[ci * INDEX_STRIDE + 1];
659
+ const idxA = idx[ci * INDEX_STRIDE + 2];
660
+ const idxB = idx[ci * INDEX_STRIDE + 3];
661
+ const trA = system.__transforms[idxA];
662
+ const trB = system.__transforms[idxB];
663
+
664
+ const slot_off = manifolds.slot_data_offset(slot);
665
+ const off = slot_off + cidx * CONTACT_STRIDE;
666
+
667
+ const wax = data[off], way = data[off + 1], waz = data[off + 2];
668
+ const wbx = data[off + 3], wby = data[off + 4], wbz = data[off + 5];
669
+ const nx = data[off + 6], ny = data[off + 7], nz = data[off + 8];
670
+ const depth0 = data[off + 9];
671
+
672
+ const pre_off = ci * PRE_STRIDE;
673
+
674
+ const pAx = trA.position.x, pAy = trA.position.y, pAz = trA.position.z;
675
+ const pBx = trB.position.x, pBy = trB.position.y, pBz = trB.position.z;
676
+ const qA = trA.rotation, qB = trB.rotation;
677
+
678
+ // Current world contact points: COM + R · localWitness.
679
+ v3_quat3_apply(cp, 0, pre[pre_off], pre[pre_off + 1], pre[pre_off + 2], qA[0], qA[1], qA[2], qA[3]);
680
+ v3_quat3_apply(cp, 3, pre[pre_off + 3], pre[pre_off + 4], pre[pre_off + 5], qB[0], qB[1], qB[2], qB[3]);
681
+ const cpAx = pAx + cp[0], cpAy = pAy + cp[1], cpAz = pAz + cp[2];
682
+ const cpBx = pBx + cp[3], cpBy = pBy + cp[4], cpBz = pBz + cp[5];
683
+
684
+ // Penetration re-derived as a delta from the trusted prepare depth.
685
+ // Δsep = ((cpA − wA) − (cpB − wB)) · n.
686
+ const dsep = ((cpAx - wax) - (cpBx - wbx)) * nx
687
+ + ((cpAy - way) - (cpBy - wby)) * ny
688
+ + ((cpAz - waz) - (cpBz - wbz)) * nz;
689
+ const depth_now = depth0 - dsep;
690
+
691
+ // Impulse levers from each COM to the current contact midpoint.
692
+ const mx = (cpAx + cpBx) * 0.5;
693
+ const my = (cpAy + cpBy) * 0.5;
694
+ const mz = (cpAz + cpBz) * 0.5;
695
+ pre[pre_off + 6] = mx - pAx; pre[pre_off + 7] = my - pAy; pre[pre_off + 8] = mz - pAz;
696
+ pre[pre_off + 9] = mx - pBx; pre[pre_off + 10] = my - pBy; pre[pre_off + 11] = mz - pBz;
697
+
698
+ let bias_position = 0;
699
+ if (depth_now > PENETRATION_SLOP) {
700
+ bias_position = -spook_a * (depth_now - PENETRATION_SLOP);
701
+ if (bias_position < -MAX_POSITION_BIAS) bias_position = -MAX_POSITION_BIAS;
702
+ }
703
+ pre[pre_off + 22] = bias_position;
704
+ }
705
+ }
706
+
707
+ /**
708
+ * Stage 3 (per substep) — velocity iterations enforcing pure
709
+ * non-penetration (`vn → 0`) plus Coulomb-disk friction. No bias: depth
710
+ * correction is the position pass, restitution is the one-shot pass.
711
+ *
712
+ * @param {ManifoldStore} manifolds
713
+ * @param {PhysicsSystem} system
714
+ * @param {number} iters
715
+ */
716
+ export function solve_velocity(manifolds, system, iters) {
717
+ const contact_count = g_contact_count;
718
+ if (contact_count === 0) return;
719
+
720
+ const data = manifolds.data_buffer;
721
+ const pre = scratch_pre;
722
+ const idx = scratch_idx;
723
+ const mus = scratch_mu;
724
+
725
+ for (let iter = 0; iter < iters; iter++) {
726
+ for (let ci = 0; ci < contact_count; ci++) {
727
+ const slot = idx[ci * INDEX_STRIDE];
728
+ const cidx = idx[ci * INDEX_STRIDE + 1];
729
+ const idxA = idx[ci * INDEX_STRIDE + 2];
730
+ const idxB = idx[ci * INDEX_STRIDE + 3];
731
+ const rbA = system.__bodies[idxA];
732
+ const rbB = system.__bodies[idxB];
733
+ const trA = system.__transforms[idxA];
734
+ const trB = system.__transforms[idxB];
735
+ const invMA = inv_mass_of(rbA);
736
+ const invMB = inv_mass_of(rbB);
737
+
738
+ const pre_off = ci * PRE_STRIDE;
739
+ const rax = pre[pre_off + 6], ray = pre[pre_off + 7], raz = pre[pre_off + 8];
740
+ const rbx = pre[pre_off + 9], rby = pre[pre_off + 10], rbz = pre[pre_off + 11];
741
+ const t1x = pre[pre_off + 12], t1y = pre[pre_off + 13], t1z = pre[pre_off + 14];
742
+ const t2x = pre[pre_off + 15], t2y = pre[pre_off + 16], t2z = pre[pre_off + 17];
743
+ const m_eff_n = pre[pre_off + 18];
744
+ const m_eff_t1 = pre[pre_off + 19];
745
+ const m_eff_t2 = pre[pre_off + 20];
746
+
747
+ const slot_off = manifolds.slot_data_offset(slot);
748
+ const off = slot_off + cidx * CONTACT_STRIDE;
749
+ const nx = data[off + 6], ny = data[off + 7], nz = data[off + 8];
750
+
751
+ const lvA = rbA.linearVelocity, avA = rbA.angularVelocity;
752
+ const lvB = rbB.linearVelocity, avB = rbB.angularVelocity;
753
+
754
+ const vAx_at = lvA[0] + avA[1] * raz - avA[2] * ray;
755
+ const vAy_at = lvA[1] + avA[2] * rax - avA[0] * raz;
756
+ const vAz_at = lvA[2] + avA[0] * ray - avA[1] * rax;
757
+ const vBx_at = lvB[0] + avB[1] * rbz - avB[2] * rby;
758
+ const vBy_at = lvB[1] + avB[2] * rbx - avB[0] * rbz;
759
+ const vBz_at = lvB[2] + avB[0] * rby - avB[1] * rbx;
760
+ const dvx = vAx_at - vBx_at;
761
+ const dvy = vAy_at - vBy_at;
762
+ const dvz = vAz_at - vBz_at;
763
+
764
+ // --- Normal impulse (non-penetration: drive vn → 0) ---
765
+ const vn = dvx * nx + dvy * ny + dvz * nz;
766
+ const j_n_accum = data[off + 10];
767
+ const lambda_n = -m_eff_n * vn;
768
+ const sum_n = j_n_accum + lambda_n;
769
+ const new_j_n = sum_n > 0 ? sum_n : 0;
770
+ const delta_j_n = new_j_n - j_n_accum;
771
+ data[off + 10] = new_j_n;
772
+ if (new_j_n > scratch_max_jn[ci]) scratch_max_jn[ci] = new_j_n;
773
+
774
+ if (delta_j_n !== 0) {
775
+ const Pnx = nx * delta_j_n;
776
+ const Pny = ny * delta_j_n;
777
+ const Pnz = nz * delta_j_n;
778
+ apply_impulse_to_body(rbA, trA, invMA, rax, ray, raz, Pnx, Pny, Pnz, +1, scratch_inertia_a);
779
+ apply_impulse_to_body(rbB, trB, invMB, rbx, rby, rbz, Pnx, Pny, Pnz, -1, scratch_inertia_b);
780
+ }
781
+
782
+ // --- Friction impulse (Coulomb disk in tangent plane) ---
783
+ const vAx2 = lvA[0] + avA[1] * raz - avA[2] * ray;
784
+ const vAy2 = lvA[1] + avA[2] * rax - avA[0] * raz;
785
+ const vAz2 = lvA[2] + avA[0] * ray - avA[1] * rax;
786
+ const vBx2 = lvB[0] + avB[1] * rbz - avB[2] * rby;
787
+ const vBy2 = lvB[1] + avB[2] * rbx - avB[0] * rbz;
788
+ const vBz2 = lvB[2] + avB[0] * rby - avB[1] * rbx;
789
+ const dvx2 = vAx2 - vBx2;
790
+ const dvy2 = vAy2 - vBy2;
791
+ const dvz2 = vAz2 - vBz2;
792
+
793
+ const vt1 = dvx2 * t1x + dvy2 * t1y + dvz2 * t1z;
794
+ const vt2 = dvx2 * t2x + dvy2 * t2y + dvz2 * t2z;
795
+
796
+ const j_t1_accum = data[off + 11];
797
+ const j_t2_accum = data[off + 12];
798
+ const lambda_t1 = -m_eff_t1 * vt1;
799
+ const lambda_t2 = -m_eff_t2 * vt2;
800
+
801
+ const want_t1 = j_t1_accum + lambda_t1;
802
+ const want_t2 = j_t2_accum + lambda_t2;
803
+ const max_friction = mus[ci] * new_j_n;
804
+ friction_cone_clamp(scratch_clamp, 0, want_t1, want_t2, max_friction);
805
+ const new_j_t1 = scratch_clamp[0];
806
+ const new_j_t2 = scratch_clamp[1];
807
+ const delta_t1 = new_j_t1 - j_t1_accum;
808
+ const delta_t2 = new_j_t2 - j_t2_accum;
809
+ data[off + 11] = new_j_t1;
810
+ data[off + 12] = new_j_t2;
811
+
812
+ if (delta_t1 !== 0 || delta_t2 !== 0) {
813
+ const Ptx = t1x * delta_t1 + t2x * delta_t2;
814
+ const Pty = t1y * delta_t1 + t2y * delta_t2;
815
+ const Ptz = t1z * delta_t1 + t2z * delta_t2;
816
+ apply_impulse_to_body(rbA, trA, invMA, rax, ray, raz, Ptx, Pty, Ptz, +1, scratch_inertia_a);
817
+ apply_impulse_to_body(rbB, trB, invMB, rbx, rby, rbz, Ptx, Pty, Ptz, -1, scratch_inertia_b);
818
+ }
819
+ }
820
+ }
821
+ }
822
+
823
+ /**
824
+ * Stage 4 (once, after the substep loop) — one-shot restitution
825
+ * (Box2D-v3 `b2ApplyRestitution`, Catto 2018). Drives `vn → -e · vn_approach`
826
+ * exactly once per closing contact, gated on (a) the contact having been
827
+ * closing faster than the threshold at prepare, and (b) a compressive
828
+ * normal impulse having formed during the velocity solve. The added impulse
829
+ * accumulates into the same normal-impulse slot so it composes with
830
+ * warm-start next frame.
831
+ *
832
+ * @param {ManifoldStore} manifolds
833
+ * @param {PhysicsSystem} system
834
+ */
835
+ export function apply_restitution(manifolds, system) {
836
+ const contact_count = g_contact_count;
837
+ if (contact_count === 0) return;
838
+
839
+ const data = manifolds.data_buffer;
840
+ const pre = scratch_pre;
841
+ const idx = scratch_idx;
842
+
843
+ for (let ci = 0; ci < contact_count; ci++) {
844
+ const pre_off = ci * PRE_STRIDE;
845
+ const rest_bias = pre[pre_off + 21];
846
+ if (rest_bias === 0) continue;
847
+
848
+ const slot = idx[ci * INDEX_STRIDE];
849
+ const cidx = idx[ci * INDEX_STRIDE + 1];
850
+ // Gate on the running max normal impulse, not the end-of-loop value:
851
+ // a transient collision relaxes back to j_n ≈ 0 under per-substep
852
+ // warm-start, but it WAS compressive, so it should still bounce.
853
+ if (scratch_max_jn[ci] <= 0) continue;
854
+
855
+ const slot_off = manifolds.slot_data_offset(slot);
856
+ const off = slot_off + cidx * CONTACT_STRIDE;
857
+
858
+ const j_n_accum = data[off + 10];
859
+
860
+ const idxA = idx[ci * INDEX_STRIDE + 2];
861
+ const idxB = idx[ci * INDEX_STRIDE + 3];
862
+ const rbA = system.__bodies[idxA];
863
+ const rbB = system.__bodies[idxB];
864
+ const trA = system.__transforms[idxA];
865
+ const trB = system.__transforms[idxB];
866
+ const invMA = inv_mass_of(rbA);
867
+ const invMB = inv_mass_of(rbB);
868
+
869
+ const rax = pre[pre_off + 6], ray = pre[pre_off + 7], raz = pre[pre_off + 8];
870
+ const rbx = pre[pre_off + 9], rby = pre[pre_off + 10], rbz = pre[pre_off + 11];
871
+ const m_eff_n = pre[pre_off + 18];
872
+ const nx = data[off + 6], ny = data[off + 7], nz = data[off + 8];
873
+
874
+ const lvA = rbA.linearVelocity, avA = rbA.angularVelocity;
875
+ const lvB = rbB.linearVelocity, avB = rbB.angularVelocity;
876
+ const vAx_at = lvA[0] + avA[1] * raz - avA[2] * ray;
877
+ const vAy_at = lvA[1] + avA[2] * rax - avA[0] * raz;
878
+ const vAz_at = lvA[2] + avA[0] * ray - avA[1] * rax;
879
+ const vBx_at = lvB[0] + avB[1] * rbz - avB[2] * rby;
880
+ const vBy_at = lvB[1] + avB[2] * rbx - avB[0] * rbz;
881
+ const vBz_at = lvB[2] + avB[0] * rby - avB[1] * rbx;
882
+ const vn = (vAx_at - vBx_at) * nx + (vAy_at - vBy_at) * ny + (vAz_at - vBz_at) * nz;
883
+
884
+ const lambda = -m_eff_n * (vn + rest_bias);
885
+ const new_j_n = (j_n_accum + lambda) > 0 ? (j_n_accum + lambda) : 0;
886
+ const delta = new_j_n - j_n_accum;
887
+ data[off + 10] = new_j_n;
888
+
889
+ if (delta !== 0) {
890
+ const Px = nx * delta, Py = ny * delta, Pz = nz * delta;
891
+ apply_impulse_to_body(rbA, trA, invMA, rax, ray, raz, Px, Py, Pz, +1, scratch_inertia_a);
892
+ apply_impulse_to_body(rbB, trB, invMB, rbx, rby, rbz, Px, Py, Pz, -1, scratch_inertia_b);
893
+ }
894
+ }
895
+ }
896
+
897
+ /**
898
+ * Stage 5 (per substep) — split-impulse position correction. Normal-only
899
+ * (friction in the pseudo-velocity pass is ill-defined). Reads the per-body
900
+ * pseudo-velocity, applies a clamped normal impulse driven by the refreshed
901
+ * `bias_position`, and writes the increment back into the pseudo buffer. The
902
+ * pose integrator folds pseudo-velocity into `pos += v · dt` and discards it.
903
+ *
904
+ * The pseudo buffer must be zeroed by the caller before this stage each
905
+ * substep (it's a per-substep correction). The position accumulator
906
+ * `scratch_pos_jn` is likewise reset here per substep.
907
+ *
908
+ * @param {ManifoldStore} manifolds
909
+ * @param {PhysicsSystem} system
910
+ * @param {number} pos_iters
911
+ */
912
+ export function solve_position(manifolds, system, pos_iters) {
913
+ const contact_count = g_contact_count;
914
+ if (contact_count === 0) return;
915
+
916
+ const data = manifolds.data_buffer;
917
+ const pre = scratch_pre;
918
+ const idx = scratch_idx;
919
+ const pos_jn = scratch_pos_jn;
920
+ const pseudoVel = system.__pseudo_velocity;
921
+
922
+ // Reset the position-impulse accumulator for this substep.
923
+ for (let ci = 0; ci < contact_count; ci++) pos_jn[ci] = 0;
924
+
925
+ for (let iter = 0; iter < pos_iters; iter++) {
926
+ for (let ci = 0; ci < contact_count; ci++) {
927
+ const pre_off = ci * PRE_STRIDE;
928
+ const bias_p = pre[pre_off + 22];
929
+ if (bias_p === 0) continue;
930
+
931
+ const slot = idx[ci * INDEX_STRIDE];
932
+ const cidx = idx[ci * INDEX_STRIDE + 1];
933
+ const idxA = idx[ci * INDEX_STRIDE + 2];
934
+ const idxB = idx[ci * INDEX_STRIDE + 3];
935
+ const rbA = system.__bodies[idxA];
936
+ const rbB = system.__bodies[idxB];
937
+ const trA = system.__transforms[idxA];
938
+ const trB = system.__transforms[idxB];
939
+ const invMA = inv_mass_of(rbA);
940
+ const invMB = inv_mass_of(rbB);
941
+
942
+ const rax = pre[pre_off + 6], ray = pre[pre_off + 7], raz = pre[pre_off + 8];
943
+ const rbx = pre[pre_off + 9], rby = pre[pre_off + 10], rbz = pre[pre_off + 11];
944
+ const m_eff_n = pre[pre_off + 18];
945
+
946
+ const slot_off = manifolds.slot_data_offset(slot);
947
+ const off = slot_off + cidx * CONTACT_STRIDE;
948
+ const nx = data[off + 6], ny = data[off + 7], nz = data[off + 8];
949
+
950
+ const baseA = idxA * PSEUDO_STRIDE;
951
+ const baseB = idxB * PSEUDO_STRIDE;
952
+
953
+ const pslA_x = pseudoVel[baseA], pslA_y = pseudoVel[baseA + 1], pslA_z = pseudoVel[baseA + 2];
954
+ const psaA_x = pseudoVel[baseA + 3], psaA_y = pseudoVel[baseA + 4], psaA_z = pseudoVel[baseA + 5];
955
+ const pslB_x = pseudoVel[baseB], pslB_y = pseudoVel[baseB + 1], pslB_z = pseudoVel[baseB + 2];
956
+ const psaB_x = pseudoVel[baseB + 3], psaB_y = pseudoVel[baseB + 4], psaB_z = pseudoVel[baseB + 5];
957
+
958
+ const psvAx_at = pslA_x + psaA_y * raz - psaA_z * ray;
959
+ const psvAy_at = pslA_y + psaA_z * rax - psaA_x * raz;
960
+ const psvAz_at = pslA_z + psaA_x * ray - psaA_y * rax;
961
+ const psvBx_at = pslB_x + psaB_y * rbz - psaB_z * rby;
962
+ const psvBy_at = pslB_y + psaB_z * rbx - psaB_x * rbz;
963
+ const psvBz_at = pslB_z + psaB_x * rby - psaB_y * rbx;
964
+
965
+ const psdvx = psvAx_at - psvBx_at;
966
+ const psdvy = psvAy_at - psvBy_at;
967
+ const psdvz = psvAz_at - psvBz_at;
968
+ const psvn = psdvx * nx + psdvy * ny + psdvz * nz;
969
+
970
+ const jn_accum = pos_jn[ci];
971
+ const lambda = -m_eff_n * (psvn + bias_p);
972
+ const sum = jn_accum + lambda;
973
+ const new_jn = sum > 0 ? sum : 0;
974
+ const delta = new_jn - jn_accum;
975
+ pos_jn[ci] = new_jn;
976
+
977
+ if (delta !== 0) {
978
+ const Px = nx * delta;
979
+ const Py = ny * delta;
980
+ const Pz = nz * delta;
981
+ apply_impulse_to_pseudo(pseudoVel, baseA, rbA, trA, invMA, rax, ray, raz, Px, Py, Pz, +1, scratch_inertia_a);
982
+ apply_impulse_to_pseudo(pseudoVel, baseB, rbB, trB, invMB, rbx, rby, rbz, Px, Py, Pz, -1, scratch_inertia_b);
983
+ }
984
+ }
985
+ }
986
+ }
987
+
988
+ /**
989
+ * Convenience single-step driver: prepare → refresh → velocity →
990
+ * restitution → position, all at the full `dt` (one substep). Equivalent to
991
+ * the Phase-2 solver. The substepped path in `PhysicsSystem.fixedUpdate`
992
+ * calls the stages directly; this entry point exists for callers/tests that
993
+ * want a one-shot solve.
994
+ *
995
+ * The position pass writes `system.__pseudo_velocity`; the caller must zero
996
+ * that buffer before this call and fold it into the pose afterwards.
997
+ *
998
+ * @param {ManifoldStore} manifolds
999
+ * @param {PhysicsSystem} system
1000
+ * @param {number} dt
1001
+ * @param {number} [iters]
1002
+ * @param {number} [pos_iters]
1003
+ */
1004
+ export function solve_contacts(manifolds, system, dt,
1005
+ iters = DEFAULT_VELOCITY_ITERATIONS,
1006
+ pos_iters = DEFAULT_POSITION_ITERATIONS) {
1007
+ if (dt <= 0) return;
1008
+ if (prepare_contacts(manifolds, system, dt) === 0) return;
1009
+ refresh_contacts(manifolds, system);
1010
+ warm_start_contacts(manifolds, system);
1011
+ solve_velocity(manifolds, system, iters);
1012
+ apply_restitution(manifolds, system);
1013
+ solve_position(manifolds, system, pos_iters);
1014
+ }
1015
+
1016
+ export { DEFAULT_VELOCITY_ITERATIONS, DEFAULT_POSITION_ITERATIONS };