@woosh/meep-engine 2.156.0 → 2.158.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 (695) hide show
  1. package/README.md +1 -3
  2. package/editor/view/ecs/components/common/AutoCanvasView.js +100 -53
  3. package/editor/view/ecs/components/common/TextController.js +59 -0
  4. package/editor/view/node-graph/NodeGraphCamera.js +90 -0
  5. package/editor/view/node-graph/NodeGraphEditorView.js +121 -22
  6. package/editor/view/node-graph/NodeGraphSelection.js +89 -0
  7. package/editor/view/node-graph/NodeGraphView.js +669 -453
  8. package/editor/view/node-graph/NodeView.js +211 -135
  9. package/editor/view/node-graph/actions/ConnectionCreateAction.js +53 -0
  10. package/editor/view/node-graph/actions/ConnectionDeleteAction.js +36 -0
  11. package/editor/view/node-graph/actions/NodeDeleteAction.js +88 -0
  12. package/editor/view/node-graph/actions/NodeParameterSetAction.js +52 -0
  13. package/editor/view/node-graph/actions/NodesMoveAction.js +41 -0
  14. package/editor/view/node-graph/actions/SelectionSetAction.js +60 -0
  15. package/editor/view/node-graph/connection_wire_geometry.js +107 -0
  16. package/package.json +1 -1
  17. package/samples/generation/SampleGenerator0.js +8 -1
  18. package/src/core/binary/reinterpret_float32_as_uint32.d.ts +7 -0
  19. package/src/core/binary/reinterpret_float32_as_uint32.d.ts.map +1 -0
  20. package/src/core/binary/reinterpret_float32_as_uint32.js +13 -0
  21. package/src/core/binary/reinterpret_uint32_as_float32.d.ts +7 -0
  22. package/src/core/binary/reinterpret_uint32_as_float32.d.ts.map +1 -0
  23. package/src/core/binary/reinterpret_uint32_as_float32.js +14 -0
  24. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.d.ts.map +1 -1
  25. package/src/core/bvh2/bvh3/ebvh_build_for_geometry_incremental.js +1 -3
  26. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.d.ts +12 -0
  27. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.d.ts.map +1 -0
  28. package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_sphere.js +92 -0
  29. package/src/core/bvh8/BVH8.d.ts +127 -0
  30. package/src/core/bvh8/BVH8.d.ts.map +1 -0
  31. package/src/core/bvh8/BVH8.js +436 -0
  32. package/src/core/bvh8/NOTES.md +63 -0
  33. package/src/core/bvh8/build/BVH8Converter.d.ts +59 -0
  34. package/src/core/bvh8/build/BVH8Converter.d.ts.map +1 -0
  35. package/src/core/bvh8/build/BVH8Converter.js +588 -0
  36. package/src/core/bvh8/build/NodeProxy.d.ts +66 -0
  37. package/src/core/bvh8/build/NodeProxy.d.ts.map +1 -0
  38. package/src/core/bvh8/build/NodeProxy.js +308 -0
  39. package/src/core/bvh8/build/TriangleCluster.d.ts +29 -0
  40. package/src/core/bvh8/build/TriangleCluster.d.ts.map +1 -0
  41. package/src/core/bvh8/build/TriangleCluster.js +123 -0
  42. package/src/core/bvh8/build/aabb3_compute_merge_cost.d.ts +8 -0
  43. package/src/core/bvh8/build/aabb3_compute_merge_cost.d.ts.map +1 -0
  44. package/src/core/bvh8/build/aabb3_compute_merge_cost.js +29 -0
  45. package/src/core/bvh8/build/aabb3_from_triangle_by_index.d.ts +10 -0
  46. package/src/core/bvh8/build/aabb3_from_triangle_by_index.d.ts.map +1 -0
  47. package/src/core/bvh8/build/aabb3_from_triangle_by_index.js +18 -0
  48. package/src/core/bvh8/build/bvh8_build_for_geometry.d.ts +10 -0
  49. package/src/core/bvh8/build/bvh8_build_for_geometry.d.ts.map +1 -0
  50. package/src/core/bvh8/build/bvh8_build_for_geometry.js +303 -0
  51. package/src/core/bvh8/build/bvh8_from_proxy.d.ts +9 -0
  52. package/src/core/bvh8/build/bvh8_from_proxy.d.ts.map +1 -0
  53. package/src/core/bvh8/build/bvh8_from_proxy.js +256 -0
  54. package/src/core/bvh8/build/byte.d.ts +7 -0
  55. package/src/core/bvh8/build/byte.d.ts.map +1 -0
  56. package/src/core/bvh8/build/byte.js +10 -0
  57. package/src/core/bvh8/build/encode_bounds_e.d.ts +9 -0
  58. package/src/core/bvh8/build/encode_bounds_e.d.ts.map +1 -0
  59. package/src/core/bvh8/build/encode_bounds_e.js +12 -0
  60. package/src/core/bvh8/bvh8_convert_to_dot.d.ts +11 -0
  61. package/src/core/bvh8/bvh8_convert_to_dot.d.ts.map +1 -0
  62. package/src/core/bvh8/bvh8_convert_to_dot.js +133 -0
  63. package/src/core/bvh8/bvh8_count_primitives.d.ts +22 -0
  64. package/src/core/bvh8/bvh8_count_primitives.d.ts.map +1 -0
  65. package/src/core/bvh8/bvh8_count_primitives.js +98 -0
  66. package/src/core/bvh8/bvh8_geometry_validate.d.ts +16 -0
  67. package/src/core/bvh8/bvh8_geometry_validate.d.ts.map +1 -0
  68. package/src/core/bvh8/bvh8_geometry_validate.js +149 -0
  69. package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts +16 -0
  70. package/src/core/bvh8/bvh8_geometry_validate_indirect.d.ts.map +1 -0
  71. package/src/core/bvh8/bvh8_geometry_validate_indirect.js +177 -0
  72. package/src/core/bvh8/bvh8_get_node_bounds.d.ts +9 -0
  73. package/src/core/bvh8/bvh8_get_node_bounds.d.ts.map +1 -0
  74. package/src/core/bvh8/bvh8_get_node_bounds.js +35 -0
  75. package/src/core/bvh8/bvh8_get_node_child_bounds.d.ts +10 -0
  76. package/src/core/bvh8/bvh8_get_node_child_bounds.d.ts.map +1 -0
  77. package/src/core/bvh8/bvh8_get_node_child_bounds.js +53 -0
  78. package/src/core/bvh8/bvh8_node_child_surface_area.d.ts +9 -0
  79. package/src/core/bvh8/bvh8_node_child_surface_area.d.ts.map +1 -0
  80. package/src/core/bvh8/bvh8_node_child_surface_area.js +18 -0
  81. package/src/core/bvh8/bvh8_node_count_triangles.d.ts +8 -0
  82. package/src/core/bvh8/bvh8_node_count_triangles.d.ts.map +1 -0
  83. package/src/core/bvh8/bvh8_node_count_triangles.js +28 -0
  84. package/src/core/bvh8/bvh8_quality.d.ts +8 -0
  85. package/src/core/bvh8/bvh8_quality.d.ts.map +1 -0
  86. package/src/core/bvh8/bvh8_quality.js +73 -0
  87. package/src/core/bvh8/bvh8_validate_structure.d.ts +15 -0
  88. package/src/core/bvh8/bvh8_validate_structure.d.ts.map +1 -0
  89. package/src/core/bvh8/bvh8_validate_structure.js +87 -0
  90. package/src/core/collection/Uint32MinHeap.d.ts +56 -0
  91. package/src/core/collection/Uint32MinHeap.d.ts.map +1 -0
  92. package/src/core/collection/Uint32MinHeap.js +109 -0
  93. package/src/core/collection/list/FilteredListProjection.js +1 -1
  94. package/src/{engine/physics/island → core/collection/union-find}/union_find.d.ts +8 -5
  95. package/src/core/collection/union-find/union_find.d.ts.map +1 -0
  96. package/src/{engine/physics/island → core/collection/union-find}/union_find.js +8 -5
  97. package/src/core/dom/isImageBitmap.d.ts +7 -0
  98. package/src/core/dom/isImageBitmap.d.ts.map +1 -0
  99. package/src/core/dom/isImageBitmap.js +12 -0
  100. package/src/core/function/frameThrottle.d.ts +8 -0
  101. package/src/core/function/frameThrottle.d.ts.map +1 -0
  102. package/src/core/function/frameThrottle.js +23 -0
  103. package/src/{engine/physics/narrowphase/clip_against_axis_uv.d.ts → core/geom/2d/polygon/polygon2_clip_axis_halfplane.d.ts} +3 -3
  104. package/src/core/geom/2d/polygon/polygon2_clip_axis_halfplane.d.ts.map +1 -0
  105. package/src/{engine/physics/narrowphase/clip_against_axis_uv.js → core/geom/2d/polygon/polygon2_clip_axis_halfplane.js} +51 -51
  106. package/src/{engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts → core/geom/3d/aabb/aabb3_transform_oriented_inverse.d.ts} +9 -7
  107. package/src/core/geom/3d/aabb/aabb3_transform_oriented_inverse.d.ts.map +1 -0
  108. package/src/{engine/physics/narrowphase/decomposition/aabb_world_to_local.js → core/geom/3d/aabb/aabb3_transform_oriented_inverse.js} +9 -7
  109. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.d.ts +12 -0
  110. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.d.ts.map +1 -0
  111. package/src/core/geom/3d/aabb/compute_triangle_group_aabb3.js +46 -0
  112. package/src/core/geom/3d/box/box3_projected_half_extent.d.ts +28 -0
  113. package/src/core/geom/3d/box/box3_projected_half_extent.d.ts.map +1 -0
  114. package/src/core/geom/3d/box/box3_projected_half_extent.js +35 -0
  115. package/src/core/geom/3d/frustum/read_cluster_frustum_corners.js +1 -1
  116. package/src/core/geom/3d/frustum/read_frustum_corner.d.ts +9 -0
  117. package/src/core/geom/3d/frustum/read_frustum_corner.d.ts.map +1 -0
  118. package/src/core/geom/3d/frustum/read_frustum_corner.js +14 -0
  119. package/src/core/geom/3d/gjk/gjk.d.ts.map +1 -0
  120. package/src/{engine/physics → core/geom/3d}/gjk/gjk.js +430 -372
  121. package/src/{engine/physics → core/geom/3d}/gjk/gjk_epa_penetration.d.ts +8 -5
  122. package/src/core/geom/3d/gjk/gjk_epa_penetration.d.ts.map +1 -0
  123. package/src/{engine/physics → core/geom/3d}/gjk/gjk_epa_penetration.js +520 -544
  124. package/src/{engine/physics → core/geom/3d}/gjk/minkowski_support.d.ts +5 -4
  125. package/src/core/geom/3d/gjk/minkowski_support.d.ts.map +1 -0
  126. package/src/{engine/physics → core/geom/3d}/gjk/minkowski_support.js +71 -70
  127. package/src/{engine/physics → core/geom/3d}/gjk/mpr.d.ts +3 -3
  128. package/src/core/geom/3d/gjk/mpr.d.ts.map +1 -0
  129. package/src/{engine/physics → core/geom/3d}/gjk/mpr.js +368 -362
  130. package/src/{engine/physics/integration/quat_integrate.d.ts → core/geom/3d/quaternion/quat3_integrate.d.ts} +2 -2
  131. package/src/core/geom/3d/quaternion/quat3_integrate.d.ts.map +1 -0
  132. package/src/{engine/physics/integration/quat_integrate.js → core/geom/3d/quaternion/quat3_integrate.js} +1 -1
  133. package/src/{engine/physics/narrowphase/PosedShape.d.ts → core/geom/3d/shape/PosedShape3D.d.ts} +26 -8
  134. package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -0
  135. package/src/{engine/physics/narrowphase/PosedShape.js → core/geom/3d/shape/PosedShape3D.js} +60 -9
  136. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  137. package/src/core/geom/3d/shape/TransformedShape3D.js +15 -11
  138. package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts +1 -1
  139. package/src/core/geom/vec3/v3_quat3_apply_inverse.js +1 -1
  140. package/src/core/math/complex/complex_add.d.ts +1 -1
  141. package/src/core/math/complex/complex_add.d.ts.map +1 -1
  142. package/src/core/math/complex/complex_add.js +12 -3
  143. package/src/core/math/complex/complex_div.d.ts +1 -1
  144. package/src/core/math/complex/complex_div.d.ts.map +1 -1
  145. package/src/core/math/complex/complex_div.js +11 -4
  146. package/src/core/math/complex/complex_mul.d.ts +1 -1
  147. package/src/core/math/complex/complex_mul.d.ts.map +1 -1
  148. package/src/core/math/complex/complex_mul.js +10 -3
  149. package/src/core/math/complex/complex_sub.d.ts +1 -1
  150. package/src/core/math/complex/complex_sub.d.ts.map +1 -1
  151. package/src/core/math/complex/complex_sub.js +12 -3
  152. package/src/{engine/physics/fluid/solver/optimal_sor_omega.d.ts → core/math/linalg/sor_optimal_omega.d.ts} +4 -3
  153. package/src/core/math/linalg/sor_optimal_omega.d.ts.map +1 -0
  154. package/src/{engine/physics/fluid/solver/optimal_sor_omega.js → core/math/linalg/sor_optimal_omega.js} +4 -3
  155. package/src/core/math/lookup/ParameterLookupTable.d.ts +123 -0
  156. package/src/core/math/lookup/ParameterLookupTable.d.ts.map +1 -0
  157. package/src/core/math/lookup/ParameterLookupTable.js +495 -0
  158. package/src/core/math/lookup/ParameterLookupTableFlags.d.ts +5 -0
  159. package/src/core/math/lookup/ParameterLookupTableFlags.d.ts.map +1 -0
  160. package/src/core/math/lookup/ParameterLookupTableFlags.js +6 -0
  161. package/src/core/math/physics/kinematics/computeInterceptPoint.d.ts.map +1 -0
  162. package/src/{engine/physics → core/math/physics/kinematics}/computeInterceptPoint.js +79 -79
  163. package/src/core/math/physics/mie/ri_air.d.ts.map +1 -1
  164. package/src/core/math/physics/mie/ri_air.js +1 -3
  165. package/src/core/math/physics/mie/ri_ammonium_sulfate.d.ts.map +1 -1
  166. package/src/core/math/physics/mie/ri_ammonium_sulfate.js +1 -3
  167. package/src/core/math/physics/mie/ri_brine.d.ts.map +1 -1
  168. package/src/core/math/physics/mie/ri_brine.js +1 -3
  169. package/src/core/math/physics/mie/ri_dust.d.ts.map +1 -1
  170. package/src/core/math/physics/mie/ri_dust.js +1 -3
  171. package/src/core/math/physics/mie/ri_pollen.d.ts.map +1 -1
  172. package/src/core/math/physics/mie/ri_pollen.js +1 -3
  173. package/src/core/math/physics/mie/ri_smoke.d.ts.map +1 -1
  174. package/src/core/math/physics/mie/ri_smoke.js +1 -3
  175. package/src/core/math/physics/mie/ri_soot.d.ts.map +1 -1
  176. package/src/core/math/physics/mie/ri_soot.js +1 -3
  177. package/src/core/math/physics/mie/ri_water.d.ts.map +1 -1
  178. package/src/core/math/physics/mie/ri_water.js +1 -3
  179. package/src/core/math/random/random_pick_weighted_index.d.ts +10 -0
  180. package/src/core/math/random/random_pick_weighted_index.d.ts.map +1 -0
  181. package/src/core/math/random/random_pick_weighted_index.js +26 -0
  182. package/src/core/model/node-graph/NodeGraph.d.ts +9 -0
  183. package/src/core/model/node-graph/NodeGraph.d.ts.map +1 -1
  184. package/src/core/model/node-graph/NodeGraph.js +38 -0
  185. package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts +23 -0
  186. package/src/core/model/node-graph/visual/NodeGraphVisualData.d.ts.map +1 -1
  187. package/src/core/model/node-graph/visual/NodeGraphVisualData.js +54 -0
  188. package/src/core/path/convertPathToURL.d.ts +9 -0
  189. package/src/core/path/convertPathToURL.d.ts.map +1 -0
  190. package/src/core/path/convertPathToURL.js +107 -0
  191. package/src/core/process/worker/WorkerBuilder.js +1 -1
  192. package/src/core/process/worker/extractTransferables.js +1 -1
  193. package/src/engine/animation/curve/draw/build_tangent_editor.d.ts.map +1 -1
  194. package/src/engine/animation/curve/draw/build_tangent_editor.js +8 -1
  195. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.d.ts.map +1 -1
  196. package/src/engine/animation/curve/editor/createKeyframeDraggableAspect.js +11 -5
  197. package/src/engine/asset/Asset.d.ts.map +1 -1
  198. package/src/engine/asset/Asset.js +16 -6
  199. package/src/engine/asset/AssetManager.d.ts +61 -52
  200. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  201. package/src/engine/asset/AssetManager.js +1411 -1045
  202. package/src/engine/asset/AssetRequest.d.ts +1 -1
  203. package/src/engine/asset/AssetRequest.d.ts.map +1 -1
  204. package/src/engine/asset/AssetRequest.js +1 -1
  205. package/src/engine/asset/AssetRequestScope.d.ts.map +1 -1
  206. package/src/engine/asset/AssetRequestScope.js +7 -0
  207. package/src/engine/asset/PendingAsset.d.ts +32 -1
  208. package/src/engine/asset/PendingAsset.d.ts.map +1 -1
  209. package/src/engine/asset/PendingAsset.js +108 -61
  210. package/src/engine/asset/loaders/ArrayBufferLoader.js +2 -2
  211. package/src/engine/asset/loaders/AssetLoader.d.ts.map +1 -1
  212. package/src/engine/asset/loaders/AssetLoader.js +19 -2
  213. package/src/engine/asset/loaders/GLTFAssetLoader.d.ts.map +1 -1
  214. package/src/engine/asset/loaders/GLTFAssetLoader.js +123 -114
  215. package/src/engine/asset/loaders/JavascriptAssetLoader.d.ts +1 -1
  216. package/src/engine/asset/loaders/JavascriptAssetLoader.d.ts.map +1 -1
  217. package/src/engine/asset/loaders/JavascriptAssetLoader.js +31 -47
  218. package/src/engine/asset/loaders/JsonAssetLoader.js +1 -1
  219. package/src/engine/asset/loaders/SVGAssetLoader.js +2 -2
  220. package/src/engine/asset/loaders/SoundAssetLoader.js +1 -1
  221. package/src/engine/asset/loaders/TextAssetLoader.js +2 -2
  222. package/src/{core → engine/asset/loaders}/font/FontAsset.d.ts +1 -1
  223. package/src/engine/asset/loaders/font/FontAsset.d.ts.map +1 -0
  224. package/src/{core → engine/asset/loaders}/font/FontAsset.js +21 -21
  225. package/src/{core → engine/asset/loaders}/font/FontAssetLoader.d.ts +1 -1
  226. package/src/engine/asset/loaders/font/FontAssetLoader.d.ts.map +1 -0
  227. package/src/{core → engine/asset/loaders}/font/FontAssetLoader.js +20 -20
  228. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
  229. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
  230. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +11 -20
  231. package/src/engine/asset/loaders/texture/TextureAssetLoader.d.ts.map +1 -1
  232. package/src/engine/asset/loaders/texture/TextureAssetLoader.js +8 -2
  233. package/src/engine/asset/preloader/AssetPreloader.js +1 -1
  234. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts +1 -1
  235. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.d.ts.map +1 -1
  236. package/src/engine/ecs/sockets/serialization/AttachmentSocketsAssetLoader.js +19 -22
  237. package/src/engine/graphics/FrameThrottle.d.ts +1 -7
  238. package/src/engine/graphics/FrameThrottle.d.ts.map +1 -1
  239. package/src/engine/graphics/FrameThrottle.js +2 -24
  240. package/src/{core/geom/3d/shape/util → engine/graphics/debug}/shape_to_visual_entity.d.ts +1 -1
  241. package/src/engine/graphics/debug/shape_to_visual_entity.d.ts.map +1 -0
  242. package/src/{core/geom/3d/shape/util → engine/graphics/debug}/shape_to_visual_entity.js +159 -159
  243. package/src/{core/geom/3d/tetrahedra → engine/graphics/debug}/visualize_tetrahedral_mesh.d.ts +1 -1
  244. package/src/engine/graphics/debug/visualize_tetrahedral_mesh.d.ts.map +1 -0
  245. package/src/{core/geom/3d/tetrahedra → engine/graphics/debug}/visualize_tetrahedral_mesh.js +46 -46
  246. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.d.ts +1 -1
  247. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.d.ts.map +1 -1
  248. package/src/engine/graphics/ecs/animation/animator/graph/definition/serialization/AnimationGraphDefinitionAssetLoader.js +22 -32
  249. package/src/engine/graphics/ecs/trail2d/Trail2D.d.ts.map +1 -1
  250. package/src/engine/graphics/ecs/trail2d/Trail2D.js +21 -0
  251. package/src/engine/graphics/ecs/trail2d/Trail2DFlags.d.ts +1 -0
  252. package/src/engine/graphics/ecs/trail2d/Trail2DFlags.js +9 -1
  253. package/src/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.d.ts.map +1 -1
  254. package/src/engine/graphics/particles/particular/engine/emitter/serde/ParameterLookupTableSerializationAdapter.js +2 -76
  255. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.d.ts.map +1 -1
  256. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +2 -427
  257. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.d.ts +1 -4
  258. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.d.ts.map +1 -1
  259. package/src/engine/graphics/particles/particular/engine/parameter/ParameterLookupTableFlags.js +2 -6
  260. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +1 -1
  261. package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts +1 -8
  262. package/src/engine/graphics/render/forward_plus/read_frustum_corner.d.ts.map +1 -1
  263. package/src/engine/graphics/render/forward_plus/read_frustum_corner.js +2 -14
  264. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.d.ts +1 -11
  265. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.d.ts.map +1 -1
  266. package/src/engine/graphics/sh3/path_tracer/geometry/compute_triangle_group_aabb3.js +2 -46
  267. package/src/engine/graphics/sh3/prototypeSH3Probe.js +1 -1
  268. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts +27 -0
  269. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.d.ts.map +1 -0
  270. package/src/engine/graphics/texture/3d/scs3d_sample_linear3.js +81 -0
  271. package/src/engine/graphics/texture/isImageBitmap.d.ts +1 -6
  272. package/src/engine/graphics/texture/isImageBitmap.d.ts.map +1 -1
  273. package/src/engine/graphics/texture/isImageBitmap.js +2 -12
  274. package/src/{core/process/action → engine/intelligence/behavior/util}/AsynchronousDelayAction.d.ts +2 -2
  275. package/src/engine/intelligence/behavior/util/AsynchronousDelayAction.d.ts.map +1 -0
  276. package/src/{core/process/action → engine/intelligence/behavior/util}/AsynchronousDelayAction.js +55 -55
  277. package/src/engine/network/NetworkSession.d.ts +12 -1
  278. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  279. package/src/engine/network/NetworkSession.js +52 -1
  280. package/src/engine/network/README.md +45 -0
  281. package/src/engine/network/convertPathToURL.d.ts +1 -8
  282. package/src/engine/network/convertPathToURL.d.ts.map +1 -1
  283. package/src/engine/network/convertPathToURL.js +2 -107
  284. package/src/engine/network/core/quantize/quantize_float.d.ts.map +1 -1
  285. package/src/engine/network/core/quantize/quantize_float.js +7 -0
  286. package/src/engine/network/core/quantize/quantize_position.d.ts.map +1 -1
  287. package/src/engine/network/core/quantize/quantize_position.js +12 -1
  288. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  289. package/src/engine/network/orchestrator/NetworkPeer.js +15 -1
  290. package/src/engine/network/replication/Replicator.d.ts +8 -0
  291. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  292. package/src/engine/network/replication/Replicator.js +48 -0
  293. package/src/engine/network/transport/Channel.d.ts.map +1 -1
  294. package/src/engine/network/transport/Channel.js +46 -12
  295. package/src/engine/network/transport/ReliableCommandPipeline.d.ts +16 -0
  296. package/src/engine/network/transport/ReliableCommandPipeline.d.ts.map +1 -1
  297. package/src/engine/network/transport/ReliableCommandPipeline.js +29 -0
  298. package/src/engine/network/transport/adapters/NodeUDPTransport.d.ts.map +1 -1
  299. package/src/engine/network/transport/adapters/NodeUDPTransport.js +7 -1
  300. package/src/engine/network/transport/fragments/packet_size.d.ts +5 -5
  301. package/src/engine/network/transport/fragments/packet_size.d.ts.map +1 -1
  302. package/src/engine/network/transport/fragments/packet_size.js +5 -5
  303. package/src/engine/physics/BULLET_REVIEW.md +1 -1
  304. package/src/engine/physics/JOLT_REVIEW.md +2 -2
  305. package/src/engine/physics/PLAN.md +1094 -945
  306. package/src/engine/physics/RAPIER_REVIEW.md +2 -2
  307. package/src/engine/physics/body/BodyStorage.d.ts +2 -12
  308. package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
  309. package/src/engine/physics/body/BodyStorage.js +406 -452
  310. package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
  311. package/src/engine/physics/body/SolverBodyState.js +12 -3
  312. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +28 -3
  313. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
  314. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +60 -24
  315. package/src/engine/physics/broadphase/generate_pairs.d.ts +9 -5
  316. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  317. package/src/engine/physics/broadphase/generate_pairs.js +52 -37
  318. package/src/engine/physics/ccd/linear_sweep.d.ts +15 -5
  319. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
  320. package/src/engine/physics/ccd/linear_sweep.js +122 -40
  321. package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
  322. package/src/engine/physics/constraint/solve_constraints.js +830 -805
  323. package/src/engine/physics/contact/ManifoldStore.d.ts +91 -16
  324. package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
  325. package/src/engine/physics/contact/ManifoldStore.js +204 -60
  326. package/src/engine/physics/ecs/BodyKind.d.ts +7 -3
  327. package/src/engine/physics/ecs/BodyKind.d.ts.map +1 -1
  328. package/src/engine/physics/ecs/BodyKind.js +29 -25
  329. package/src/engine/physics/ecs/Collider.d.ts +7 -0
  330. package/src/engine/physics/ecs/Collider.d.ts.map +1 -1
  331. package/src/engine/physics/ecs/Collider.js +7 -0
  332. package/src/engine/physics/ecs/ColliderSerializationAdapter.js +1 -1
  333. package/src/engine/physics/ecs/PhysicsSystem.d.ts +110 -6
  334. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  335. package/src/engine/physics/ecs/PhysicsSystem.js +467 -45
  336. package/src/engine/physics/ecs/RigidBody.d.ts +20 -5
  337. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -1
  338. package/src/engine/physics/ecs/RigidBody.js +307 -286
  339. package/src/engine/physics/ecs/RigidBodyFlags.d.ts +6 -3
  340. package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -1
  341. package/src/engine/physics/ecs/RigidBodyFlags.js +31 -28
  342. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts +12 -4
  343. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -1
  344. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +19 -5
  345. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts +10 -0
  346. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.d.ts.map +1 -0
  347. package/src/engine/physics/ecs/RigidBodySerializationUpgrader_0_1.js +37 -0
  348. package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts +28 -0
  349. package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts.map +1 -0
  350. package/src/engine/physics/ecs/find_non_finite_physics_state.js +76 -0
  351. package/src/engine/physics/events/ContactEventBuffer.d.ts +11 -0
  352. package/src/engine/physics/events/ContactEventBuffer.d.ts.map +1 -1
  353. package/src/engine/physics/events/ContactEventBuffer.js +40 -0
  354. package/src/engine/physics/events/diff_manifolds.d.ts +30 -13
  355. package/src/engine/physics/events/diff_manifolds.d.ts.map +1 -1
  356. package/src/engine/physics/events/diff_manifolds.js +87 -50
  357. package/src/engine/physics/fluid/FluidField.d.ts +98 -26
  358. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  359. package/src/engine/physics/fluid/FluidField.js +684 -570
  360. package/src/engine/physics/fluid/FluidSimulator.d.ts +157 -6
  361. package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
  362. package/src/engine/physics/fluid/FluidSimulator.js +450 -83
  363. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +243 -0
  364. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +4 -3
  365. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts.map +1 -1
  366. package/src/engine/physics/fluid/ecs/FluidComponent.js +4 -3
  367. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts +72 -0
  368. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts.map +1 -0
  369. package/src/engine/physics/fluid/ecs/FluidObstacle.js +97 -0
  370. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +117 -0
  371. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts.map +1 -0
  372. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +348 -0
  373. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +3 -3
  374. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts +62 -12
  375. package/src/engine/physics/fluid/effector/GlobalFluidEffector.d.ts.map +1 -1
  376. package/src/engine/physics/fluid/effector/GlobalFluidEffector.js +135 -38
  377. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.d.ts.map +1 -1
  378. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +85 -38
  379. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +27 -8
  380. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts.map +1 -1
  381. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +171 -68
  382. package/src/engine/physics/fluid/prototype.js +25 -1
  383. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts +42 -0
  384. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.d.ts.map +1 -0
  385. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_scalar.js +136 -0
  386. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts +37 -0
  387. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.d.ts.map +1 -0
  388. package/src/engine/physics/fluid/solver/v3_grid_advect_maccormack_velocity.js +169 -0
  389. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts +36 -0
  390. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.d.ts.map +1 -0
  391. package/src/engine/physics/fluid/solver/v3_grid_advect_sl_velocity.js +100 -0
  392. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts +6 -0
  393. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.d.ts.map +1 -1
  394. package/src/engine/physics/fluid/solver/v3_grid_apply_advection_forward.js +6 -0
  395. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts +7 -2
  396. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.d.ts.map +1 -1
  397. package/src/engine/physics/fluid/solver/v3_grid_apply_diffusion.js +17 -12
  398. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.d.ts +42 -0
  399. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.d.ts.map +1 -0
  400. package/src/engine/physics/fluid/solver/v3_grid_apply_vorticity_confinement.js +131 -0
  401. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +32 -22
  402. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -1
  403. package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +43 -26
  404. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.d.ts +31 -0
  405. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.d.ts.map +1 -0
  406. package/src/engine/physics/fluid/solver/v3_grid_patch_edges_constant.js +77 -0
  407. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts +30 -0
  408. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.d.ts.map +1 -0
  409. package/src/engine/physics/fluid/solver/v3_grid_sample_scalar_masked.js +92 -0
  410. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +26 -19
  411. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -1
  412. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +46 -42
  413. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +38 -10
  414. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -1
  415. package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +158 -75
  416. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +22 -17
  417. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -1
  418. package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +108 -96
  419. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts +42 -0
  420. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.d.ts.map +1 -0
  421. package/src/engine/physics/fluid/solver/v3_mac_advect_maccormack_velocity.js +319 -0
  422. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts +53 -0
  423. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.d.ts.map +1 -0
  424. package/src/engine/physics/fluid/solver/v3_mac_advect_scalar.js +236 -0
  425. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts +46 -0
  426. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.d.ts.map +1 -0
  427. package/src/engine/physics/fluid/solver/v3_mac_advect_sl_velocity.js +217 -0
  428. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts +40 -0
  429. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.d.ts.map +1 -0
  430. package/src/engine/physics/fluid/solver/v3_mac_apply_vorticity_confinement.js +165 -0
  431. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.d.ts +44 -0
  432. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.d.ts.map +1 -0
  433. package/src/engine/physics/fluid/solver/v3_mac_clip_trace.js +95 -0
  434. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.d.ts +38 -0
  435. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.d.ts.map +1 -0
  436. package/src/engine/physics/fluid/solver/v3_mac_compute_divergence.js +77 -0
  437. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.d.ts +52 -0
  438. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.d.ts.map +1 -0
  439. package/src/engine/physics/fluid/solver/v3_mac_compute_face_solid.js +131 -0
  440. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.d.ts +38 -0
  441. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.d.ts.map +1 -0
  442. package/src/engine/physics/fluid/solver/v3_mac_subtract_pressure_gradient.js +104 -0
  443. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +30 -1
  444. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  445. package/src/engine/physics/inertia/world_inverse_inertia.js +160 -116
  446. package/src/engine/physics/integration/integrate_position.js +97 -97
  447. package/src/engine/physics/island/IslandBuilder.d.ts +49 -8
  448. package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -1
  449. package/src/engine/physics/island/IslandBuilder.js +93 -14
  450. package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
  451. package/src/engine/physics/narrowphase/box_box_manifold.js +683 -673
  452. package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
  453. package/src/engine/physics/narrowphase/box_triangle_contact.js +899 -749
  454. package/src/engine/physics/narrowphase/capsule_contacts.d.ts +27 -0
  455. package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
  456. package/src/engine/physics/narrowphase/capsule_contacts.js +624 -459
  457. package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts.map +1 -1
  458. package/src/engine/physics/narrowphase/capsule_triangle_contact.js +58 -38
  459. package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
  460. package/src/engine/physics/narrowphase/compute_penetration.js +369 -325
  461. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts +3 -1
  462. package/src/engine/physics/narrowphase/convex_convex_manifold.d.ts.map +1 -1
  463. package/src/engine/physics/narrowphase/convex_convex_manifold.js +568 -422
  464. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +6 -3
  465. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -1
  466. package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +66 -10
  467. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts +4 -1
  468. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
  469. package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +97 -94
  470. package/src/engine/physics/narrowphase/mesh_mesh_tet_manifold.js +117 -117
  471. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  472. package/src/engine/physics/narrowphase/narrowphase_step.js +1738 -1739
  473. package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts +14 -7
  474. package/src/engine/physics/narrowphase/reduce_manifold_contacts.d.ts.map +1 -1
  475. package/src/engine/physics/narrowphase/reduce_manifold_contacts.js +74 -69
  476. package/src/engine/physics/persistence/solver_caches.d.ts +20 -0
  477. package/src/engine/physics/persistence/solver_caches.d.ts.map +1 -0
  478. package/src/engine/physics/persistence/solver_caches.js +309 -0
  479. package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
  480. package/src/engine/physics/queries/overlap_shape.js +187 -184
  481. package/src/engine/physics/queries/raycast.d.ts +3 -2
  482. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  483. package/src/engine/physics/queries/raycast.js +37 -11
  484. package/src/engine/physics/queries/shape_cast.d.ts +18 -5
  485. package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
  486. package/src/engine/physics/queries/shape_cast.js +417 -393
  487. package/src/engine/physics/solver/solve_contacts.d.ts +22 -6
  488. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
  489. package/src/engine/physics/solver/solve_contacts.js +1482 -1338
  490. package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
  491. package/src/engine/physics/vehicle/RaycastVehicle.js +344 -339
  492. package/src/engine/ui/DraggableAspect.d.ts +12 -3
  493. package/src/engine/ui/DraggableAspect.d.ts.map +1 -1
  494. package/src/engine/ui/DraggableAspect.js +115 -83
  495. package/src/generation/COORDINATES.md +54 -0
  496. package/src/generation/GridTaskGroup.js +2 -2
  497. package/src/generation/REVIEW_01_ACTION_PLAN.md +628 -0
  498. package/src/generation/automata/CaveGeneratorCellularAutomata.d.ts +9 -1
  499. package/src/generation/automata/CaveGeneratorCellularAutomata.d.ts.map +1 -1
  500. package/src/generation/automata/CaveGeneratorCellularAutomata.js +79 -59
  501. package/src/generation/automata/CellularAutomata.d.ts +6 -3
  502. package/src/generation/automata/CellularAutomata.d.ts.map +1 -1
  503. package/src/generation/automata/CellularAutomata.js +22 -19
  504. package/src/generation/filtering/CellFilter.d.ts +17 -0
  505. package/src/generation/filtering/CellFilter.d.ts.map +1 -1
  506. package/src/generation/filtering/CellFilter.js +117 -77
  507. package/src/generation/filtering/CellFilterCellMatcher.d.ts.map +1 -1
  508. package/src/generation/filtering/CellFilterCellMatcher.js +2 -0
  509. package/src/generation/filtering/boolean/CellFilterLiteralBoolean.d.ts +5 -0
  510. package/src/generation/filtering/boolean/CellFilterLiteralBoolean.d.ts.map +1 -1
  511. package/src/generation/filtering/boolean/CellFilterLiteralBoolean.js +15 -0
  512. package/src/generation/filtering/core/CellFilterBinaryOperation.d.ts +0 -1
  513. package/src/generation/filtering/core/CellFilterBinaryOperation.d.ts.map +1 -1
  514. package/src/generation/filtering/core/CellFilterBinaryOperation.js +37 -50
  515. package/src/generation/filtering/core/CellFilterOperationTertiary.d.ts +0 -1
  516. package/src/generation/filtering/core/CellFilterOperationTertiary.d.ts.map +1 -1
  517. package/src/generation/filtering/core/CellFilterOperationTertiary.js +43 -59
  518. package/src/generation/filtering/core/CellFilterUnaryOperation.d.ts +0 -1
  519. package/src/generation/filtering/core/CellFilterUnaryOperation.d.ts.map +1 -1
  520. package/src/generation/filtering/core/CellFilterUnaryOperation.js +29 -33
  521. package/src/generation/filtering/numeric/CellFilterCache.d.ts +1 -0
  522. package/src/generation/filtering/numeric/CellFilterCache.d.ts.map +1 -1
  523. package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.d.ts +3 -2
  524. package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.d.ts.map +1 -1
  525. package/src/generation/filtering/numeric/complex/CellFilterAngleToNormal.js +9 -35
  526. package/src/generation/filtering/numeric/complex/CellFilterCurvature.d.ts +0 -1
  527. package/src/generation/filtering/numeric/complex/CellFilterCurvature.d.ts.map +1 -1
  528. package/src/generation/filtering/numeric/complex/CellFilterCurvature.js +19 -43
  529. package/src/generation/filtering/numeric/complex/CellFilterFXAA.d.ts +0 -1
  530. package/src/generation/filtering/numeric/complex/CellFilterFXAA.d.ts.map +1 -1
  531. package/src/generation/filtering/numeric/complex/CellFilterFXAA.js +2 -6
  532. package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.d.ts.map +1 -1
  533. package/src/generation/filtering/numeric/complex/CellFilterGaussianBlur.js +9 -12
  534. package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.d.ts.map +1 -1
  535. package/src/generation/filtering/numeric/complex/CellFilterSimplexNoise.js +2 -1
  536. package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts +0 -1
  537. package/src/generation/filtering/numeric/complex/CellFilterSobel.d.ts.map +1 -1
  538. package/src/generation/filtering/numeric/complex/CellFilterSobel.js +2 -6
  539. package/src/generation/filtering/numeric/math/CellFilterInverseLerp.d.ts +5 -4
  540. package/src/generation/filtering/numeric/math/CellFilterInverseLerp.d.ts.map +1 -1
  541. package/src/generation/filtering/numeric/math/CellFilterInverseLerp.js +5 -4
  542. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.d.ts +17 -0
  543. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.d.ts.map +1 -0
  544. package/src/generation/filtering/numeric/process/computeFilterSurfaceNormal.js +42 -0
  545. package/src/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.d.ts.map +1 -1
  546. package/src/generation/filtering/numeric/sampling/AbstractCellFilterSampleGridLayer.js +7 -1
  547. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.d.ts.map +1 -1
  548. package/src/generation/filtering/numeric/util/populateSampler2DFromCellFilter.js +7 -10
  549. package/src/generation/filtering/numeric/util/sampler_from_filter.d.ts.map +1 -1
  550. package/src/generation/filtering/numeric/util/sampler_from_filter.js +2 -1
  551. package/src/generation/grid/GridData.d.ts.map +1 -1
  552. package/src/generation/grid/GridData.js +14 -1
  553. package/src/generation/grid/actions/ContinuousGridCellAction.d.ts +10 -3
  554. package/src/generation/grid/actions/ContinuousGridCellAction.d.ts.map +1 -1
  555. package/src/generation/grid/actions/ContinuousGridCellAction.js +18 -3
  556. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.d.ts +11 -1
  557. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.d.ts.map +1 -1
  558. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainHeight.js +13 -3
  559. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.d.ts +1 -1
  560. package/src/generation/grid/actions/ContinuousGridCellActionSetTerrainObstacle.js +2 -2
  561. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts +1 -1
  562. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts.map +1 -1
  563. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.js +4 -6
  564. package/src/generation/grid/coords/grid_to_texel.d.ts +9 -0
  565. package/src/generation/grid/coords/grid_to_texel.d.ts.map +1 -0
  566. package/src/generation/grid/coords/grid_to_texel.js +10 -0
  567. package/src/generation/grid/coords/texel_to_grid.d.ts +9 -0
  568. package/src/generation/grid/coords/texel_to_grid.d.ts.map +1 -0
  569. package/src/generation/grid/coords/texel_to_grid.js +10 -0
  570. package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts +2 -2
  571. package/src/generation/grid/generation/GridTaskApplyActionToCells.d.ts.map +1 -1
  572. package/src/generation/grid/generation/GridTaskApplyActionToCells.js +10 -6
  573. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.d.ts.map +1 -1
  574. package/src/generation/grid/generation/GridTaskDensityMarkerDistribution.js +20 -21
  575. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.d.ts +7 -0
  576. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.d.ts.map +1 -1
  577. package/src/generation/grid/generation/GridTaskExecuteRuleTimes.js +18 -10
  578. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.d.ts.map +1 -1
  579. package/src/generation/grid/generation/discrete/GridTaskCellularAutomata.js +16 -7
  580. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts +5 -3
  581. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.d.ts.map +1 -1
  582. package/src/generation/grid/generation/discrete/GridTaskConnectRooms.js +26 -23
  583. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.d.ts.map +1 -1
  584. package/src/generation/grid/generation/discrete/layer/GridTaskBuildSourceDistanceMap.js +10 -1
  585. package/src/generation/grid/generation/grid/select/CellSupplierBestN.d.ts.map +1 -1
  586. package/src/generation/grid/generation/grid/select/CellSupplierBestN.js +4 -0
  587. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts +15 -8
  588. package/src/generation/grid/generation/road/GridTaskGenerateRoads.d.ts.map +1 -1
  589. package/src/generation/grid/generation/road/GridTaskGenerateRoads.js +89 -92
  590. package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
  591. package/src/generation/markers/GridActionRuleSet.js +10 -2
  592. package/src/generation/markers/GridCellActionPlaceMarker.d.ts +11 -0
  593. package/src/generation/markers/GridCellActionPlaceMarker.d.ts.map +1 -1
  594. package/src/generation/markers/GridCellActionPlaceMarker.js +20 -3
  595. package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts +3 -1
  596. package/src/generation/markers/GridCellActionPlaceMarkerGroup.d.ts.map +1 -1
  597. package/src/generation/markers/GridCellActionPlaceMarkerGroup.js +9 -2
  598. package/src/generation/markers/MarkerNode.d.ts +8 -3
  599. package/src/generation/markers/MarkerNode.d.ts.map +1 -1
  600. package/src/generation/markers/MarkerNode.js +12 -5
  601. package/src/generation/markers/actions/MarkerNodeActionEntityPlacement.js +1 -1
  602. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.d.ts +1 -1
  603. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.d.ts.map +1 -1
  604. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessor.js +1 -1
  605. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts +1 -1
  606. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts.map +1 -1
  607. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.js +1 -1
  608. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.d.ts +1 -1
  609. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.d.ts.map +1 -1
  610. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorRandomRotation.js +2 -2
  611. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.d.ts +1 -1
  612. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.d.ts.map +1 -1
  613. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorSequence.js +2 -2
  614. package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.d.ts.map +1 -1
  615. package/src/generation/markers/actions/probability/MarkerNodeActionSelectWeighted.js +6 -4
  616. package/src/generation/markers/actions/probability/MarkerNodeActionWeightedElement.d.ts.map +1 -1
  617. package/src/generation/markers/actions/probability/MarkerNodeActionWeightedElement.js +1 -3
  618. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.d.ts.map +1 -1
  619. package/src/generation/markers/actions/terrain/MarkerNodeActionPaintTerrain.js +12 -11
  620. package/src/generation/markers/matcher/MarkerNodeMatcherAnd.js +2 -2
  621. package/src/generation/markers/transform/MarkerNodeTransformer.d.ts +4 -1
  622. package/src/generation/markers/transform/MarkerNodeTransformer.d.ts.map +1 -1
  623. package/src/generation/markers/transform/MarkerNodeTransformer.js +4 -1
  624. package/src/generation/markers/transform/MarkerNodeTransformerAddPositionYFromFilter.d.ts.map +1 -1
  625. package/src/generation/markers/transform/MarkerNodeTransformerAddPositionYFromFilter.js +1 -3
  626. package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts +5 -0
  627. package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.d.ts.map +1 -1
  628. package/src/generation/markers/transform/MarkerNodeTransformerOffsetPosition.js +15 -0
  629. package/src/generation/markers/transform/MarkerNodeTransformerRecordProperty.d.ts.map +1 -1
  630. package/src/generation/markers/transform/MarkerNodeTransformerRecordProperty.js +1 -3
  631. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilter.d.ts.map +1 -1
  632. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilter.js +2 -4
  633. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.d.ts.map +1 -1
  634. package/src/generation/markers/transform/MarkerNodeTransformerYRotateByFilterGradient.js +1 -3
  635. package/src/generation/placement/GridCellPlacementRule.d.ts.map +1 -1
  636. package/src/generation/placement/GridCellPlacementRule.js +1 -3
  637. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.d.ts.map +1 -1
  638. package/src/generation/placement/action/GridCellActionWriteFilterToLayer.js +8 -10
  639. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.d.ts.map +1 -1
  640. package/src/generation/placement/action/random/weighted/CellActionSelectWeightedRandom.js +6 -4
  641. package/src/generation/placement/action/random/weighted/WeightedGridCellAction.d.ts.map +1 -1
  642. package/src/generation/placement/action/random/weighted/WeightedGridCellAction.js +1 -3
  643. package/src/generation/rules/CellMatcher.d.ts +3 -1
  644. package/src/generation/rules/CellMatcher.d.ts.map +1 -1
  645. package/src/generation/rules/CellMatcher.js +3 -1
  646. package/src/generation/rules/CellMatcherFromFilter.d.ts.map +1 -1
  647. package/src/generation/rules/CellMatcherFromFilter.js +1 -3
  648. package/src/generation/rules/CellMatcherLayerBitMaskTest.d.ts.map +1 -1
  649. package/src/generation/rules/CellMatcherLayerBitMaskTest.js +6 -20
  650. package/src/generation/test_support/executeTaskTreeSync.d.ts +9 -0
  651. package/src/generation/test_support/executeTaskTreeSync.d.ts.map +1 -0
  652. package/src/generation/test_support/executeTaskTreeSync.js +78 -0
  653. package/src/generation/theme/TerrainLayerRuleAggregator.d.ts +2 -1
  654. package/src/generation/theme/TerrainLayerRuleAggregator.d.ts.map +1 -1
  655. package/src/generation/theme/TerrainLayerRuleAggregator.js +9 -6
  656. package/src/generation/theme/Theme.d.ts +1 -1
  657. package/src/generation/theme/Theme.d.ts.map +1 -1
  658. package/src/generation/theme/Theme.js +2 -2
  659. package/src/generation/theme/ThemeEngine.d.ts +3 -3
  660. package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
  661. package/src/generation/theme/ThemeEngine.js +26 -16
  662. package/src/generation/theme/cell/CellProcessingRule.d.ts +3 -3
  663. package/src/generation/theme/cell/CellProcessingRule.d.ts.map +1 -1
  664. package/src/generation/theme/cell/CellProcessingRule.js +6 -10
  665. package/src/generation/theme/cell/CellProcessingRuleSet.d.ts +1 -1
  666. package/src/generation/theme/cell/CellProcessingRuleSet.d.ts.map +1 -1
  667. package/src/generation/theme/cell/CellProcessingRuleSet.js +2 -2
  668. package/src/view/common/ListView.js +1 -1
  669. package/src/view/elements/BottomLeftResizeHandleView.d.ts.map +1 -1
  670. package/src/view/elements/BottomLeftResizeHandleView.js +13 -5
  671. package/src/core/font/FontAsset.d.ts.map +0 -1
  672. package/src/core/font/FontAssetLoader.d.ts.map +0 -1
  673. package/src/core/geom/3d/shape/util/shape_to_visual_entity.d.ts.map +0 -1
  674. package/src/core/geom/3d/tetrahedra/visualize_tetrahedral_mesh.d.ts.map +0 -1
  675. package/src/core/process/action/AsynchronousDelayAction.d.ts.map +0 -1
  676. package/src/engine/physics/computeInterceptPoint.d.ts.map +0 -1
  677. package/src/engine/physics/fluid/solver/optimal_sor_omega.d.ts.map +0 -1
  678. package/src/engine/physics/gjk/gjk.d.ts.map +0 -1
  679. package/src/engine/physics/gjk/gjk_epa_penetration.d.ts.map +0 -1
  680. package/src/engine/physics/gjk/minkowski_support.d.ts.map +0 -1
  681. package/src/engine/physics/gjk/mpr.d.ts.map +0 -1
  682. package/src/engine/physics/integration/quat_integrate.d.ts.map +0 -1
  683. package/src/engine/physics/island/union_find.d.ts.map +0 -1
  684. package/src/engine/physics/narrowphase/PosedShape.d.ts.map +0 -1
  685. package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +0 -1
  686. package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts.map +0 -1
  687. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts +0 -21
  688. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.d.ts.map +0 -1
  689. package/src/generation/grid/generation/discrete/layer/GridTaskDistanceToMarkers.js +0 -68
  690. package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.d.ts +0 -10
  691. package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.d.ts.map +0 -1
  692. package/src/generation/grid/generation/grid/GridTaskGridAlignedNodeGenerator.js +0 -17
  693. /package/src/{engine/physics → core/geom/3d}/gjk/NOTES.md +0 -0
  694. /package/src/{engine/physics → core/geom/3d}/gjk/gjk.d.ts +0 -0
  695. /package/src/{engine/physics → core/math/physics/kinematics}/computeInterceptPoint.d.ts +0 -0
@@ -1,570 +1,684 @@
1
- import { assert } from "../../../core/assert.js";
2
- import { combine_hash } from "../../../core/collection/array/combine_hash.js";
3
- import { is_typed_array_equals } from "../../../core/collection/array/typed/is_typed_array_equals.js";
4
- import { sparse_typed_array_hash } from "../../../core/collection/array/typed/sparse_typed_array_hash.js";
5
- import { scs3d_sample_linear } from "../../graphics/texture/3d/scs3d_sample_linear.js";
6
- import { v3_grid_compute_solid_neighbour_mask } from "./solver/v3_grid_compute_solid_neighbour_mask.js";
7
- import { v3_grid_patch_edges_uniform } from "./solver/v3_grid_patch_edges_uniform.js";
8
- import { v3_grid_shift_in_place } from "./solver/v3_grid_shift_in_place.js";
9
-
10
- /**
11
- * Cell-centered 3D Eulerian grid for the fluid simulator.
12
- *
13
- * Holds three velocity components (x, y, z), an optional per-cell `solid` mask, and any
14
- * number of user-defined passive scalar attributes that get transported by the flow.
15
- *
16
- * Holds only state whose value carries information across step boundaries. The
17
- * simulator's transient working memory (per-step velocity snapshots, divergence,
18
- * diffusion / scalar ping-pong scratch) lives on the simulator. `pressure` is the
19
- * one exception: it's warm-started each step from the previous solve, so its value
20
- * is genuine cross-step state and belongs here.
21
- *
22
- * All typed array references are STABLE for the lifetime of the field. External
23
- * consumers can safely cache references returned from {@link getScalarData},
24
- * {@link velocity_x}, etc.
25
- *
26
- * @see "Real-Time Fluid Dynamics for Games" (Stam, 2003)
27
- * @see GDC 2019 talk "Wind Simulation in God of War" (Rupert Renard) for the wider
28
- * effector-driven design pattern this package is moving toward.
29
- */
30
- export class FluidField {
31
-
32
- /**
33
- * Grid dimensions in cells, `[x, y, z]`.
34
- * @type {[number, number, number]}
35
- */
36
- #resolution = [0, 0, 0];
37
-
38
- /**
39
- * Velocity X component, length = cell count. Cell-centered, indexed by
40
- * `z * res_x * res_y + y * res_x + x`.
41
- * @type {Float32Array|null}
42
- */
43
- velocity_x = null;
44
-
45
- /**
46
- * @type {Float32Array|null}
47
- */
48
- velocity_y = null;
49
-
50
- /**
51
- * @type {Float32Array|null}
52
- */
53
- velocity_z = null;
54
-
55
- /**
56
- * Per-cell solid flag. `0` = fluid, non-zero = solid (wall). Always allocated by
57
- * {@link build} (zero-filled — every cell defaults to fluid). The solver and every
58
- * effector read this unconditionally, so the array is part of the field's
59
- * uniform shape, not an optional add-on.
60
- * @type {Uint8Array|null}
61
- */
62
- solid = null;
63
-
64
- /**
65
- * Per-cell pre-baked neighbourhood mask consumed by the pressure SOR loop.
66
- * One byte per cell encoding which of the 6 cardinal neighbours are fluid:
67
- *
68
- * bit 0 (= 1) : -x neighbour is fluid (in-bounds AND non-solid)
69
- * bit 1 (= 2) : +x neighbour is fluid
70
- * bit 2 (= 4) : -y neighbour is fluid
71
- * bit 3 (= 8) : +y neighbour is fluid
72
- * bit 4 (= 16) : -z neighbour is fluid
73
- * bit 5 (= 32) : +z neighbour is fluid
74
- * bit 7 (= 128) : this cell is itself solid
75
- *
76
- * A solid cell encodes as `128` (bit 7 set, neighbour bits clear) and an
77
- * isolated fluid cell as `0`, so the SOR / PCG loops' `if ((mask & 63) === 0)
78
- * continue` skip handles both "this cell is solid" and "this fluid cell is
79
- * isolated" with a single comparison instead of one solid-self-check plus six
80
- * solid-neighbour-checks plus six boundary checks. Bit 7 additionally lets
81
- * {@link v3_grid_subtract_pressure_gradient} zero solid-cell velocity without
82
- * consulting the {@link solid} array.
83
- *
84
- * Computed once by {@link recomputeSolidNeighbourMask} after every solid-mask
85
- * mutation. The simulator runs that recompute at the top of every project()
86
- * call so callers never have to remember to invalidate it; the per-step cost
87
- * is one O(N) byte-pass against the bandwidth-bound SOR sweep that runs many
88
- * iterations per call.
89
- *
90
- * @type {Uint8Array|null}
91
- */
92
- solid_neighbour_mask = null;
93
-
94
- /**
95
- * Pressure field from the most recent projection. Owned by the field rather than
96
- * the simulator because the simulator warm-starts each solve from the previous
97
- * result step N+1 depends on the value step N wrote here. If this lived on the
98
- * simulator, replacing the simulator instance between steps would silently degrade
99
- * convergence at the same iteration count.
100
- *
101
- * Storage type is {@link Float32Array} by default, or {@link Float16Array} when
102
- * {@link half_precision_pressure} is enabled before build — see that field for
103
- * the bandwidth-vs-quality trade-off.
104
- *
105
- * Safe to read for debug visualisation. Don't mutate.
106
- * @type {Float32Array|Float16Array|null}
107
- */
108
- pressure = null;
109
-
110
- /**
111
- * Allocate {@link pressure} as {@link Float16Array} instead of {@link Float32Array}.
112
- *
113
- * **Currently slower in V8 — keep `false`.** The intent of this option is to
114
- * halve the memory bandwidth on the pressure SOR sweep (the simulator's
115
- * hottest, bandwidth-bound loop). On hardware with F16C the per-cell f16↔f32
116
- * conversion is ~1 cycle and the bandwidth saving wins. In V8 as of Node 24
117
- * the conversion path is not yet specialized each read of `pressure[i]`
118
- * goes through a slow generic Float16 unboxing routine, and the result is
119
- * the opposite of what you'd expect: bench at 64³ shows **49% slower** with
120
- * f16, at 128³ **28% slower** (see `bench: half_precision_pressure on/off`
121
- * in bench.spec.js). The bandwidth-savings story still holds in principle;
122
- * it'll likely become a real win once V8 adds inline support for
123
- * Float16Array access (the typed array landed in Node 24 / TC39 Stage 4 only
124
- * recently).
125
- *
126
- * Cost when it does win: Float16 has ~3 decimal digits of precision. The SOR
127
- * iterate rounds to f16 on every write, so iteration error can't fall below
128
- * ~10⁻³ relative. Bench currently shows max|div| within 8% of the f32
129
- * baseline at 64³ and 128³ — acceptable for visual sim but not for
130
- * quantitative pressure use.
131
- *
132
- * Must be set before {@link build}.
133
- *
134
- * The simulator's internal divergence scratch follows this type automatically
135
- * (re-allocated to match `pressure.constructor` on each project call).
136
- *
137
- * @type {boolean}
138
- */
139
- half_precision_pressure = false;
140
-
141
- /**
142
- * @type {{ name: string, data: Float32Array }[]}
143
- */
144
- #scalar_attributes = [];
145
-
146
- #built = false;
147
-
148
- /**
149
- * Set the grid dimensions in cells. Must be called before {@link build}; throws if
150
- * the field is already built.
151
- * @param {number} res_x positive integer
152
- * @param {number} res_y positive integer
153
- * @param {number} res_z positive integer
154
- */
155
- setResolution(res_x, res_y, res_z) {
156
- assert.notOk(this.#built, "resolution cannot be changed after build()");
157
- assert.isPositiveInteger(res_x, "res_x");
158
- assert.isPositiveInteger(res_y, "res_y");
159
- assert.isPositiveInteger(res_z, "res_z");
160
-
161
- this.#resolution[0] = res_x;
162
- this.#resolution[1] = res_y;
163
- this.#resolution[2] = res_z;
164
- }
165
-
166
- /**
167
- * @return {[number, number, number]} A reference to the internal resolution array.
168
- * Do not mutate.
169
- */
170
- getResolution() {
171
- return this.#resolution;
172
- }
173
-
174
- /**
175
- * @return {number} `res_x * res_y * res_z`. Zero until {@link setResolution} is
176
- * called.
177
- */
178
- cellCount() {
179
- return this.#resolution[0] * this.#resolution[1] * this.#resolution[2];
180
- }
181
-
182
- /**
183
- * Register a passive scalar attribute (density, temperature, dye, etc.) that will be
184
- * advected by the velocity field each step. Idempotent re-adding an existing name
185
- * returns the existing index.
186
- *
187
- * Must be called before {@link build}.
188
- *
189
- * @param {string} name
190
- * @return {number} index of the attribute (use with {@link setScalarAtIndex})
191
- */
192
- addScalar(name) {
193
- assert.notOk(this.#built, "addScalar cannot be called after build()");
194
- assert.isString(name, "name");
195
- assert.greaterThan(name.length, 0, "name must be non-empty");
196
-
197
- const existing = this.#scalar_attributes.findIndex(a => a.name === name);
198
- if (existing !== -1) {
199
- return existing;
200
- }
201
-
202
- const index = this.#scalar_attributes.length;
203
- this.#scalar_attributes.push({ name, data: null });
204
- return index;
205
- }
206
-
207
- /**
208
- * @param {string} name
209
- * @return {number} index the attribute was registered with, or -1 if not present.
210
- */
211
- scalarIndex(name) {
212
- return this.#scalar_attributes.findIndex(a => a.name === name);
213
- }
214
-
215
- /**
216
- * @param {string} name
217
- * @return {Float32Array|null} live buffer for the named scalar, or null if not
218
- * registered.
219
- */
220
- getScalarData(name) {
221
- const a = this.#scalar_attributes.find(a => a.name === name);
222
- return a === undefined ? null : a.data;
223
- }
224
-
225
- /**
226
- * @return {{ name: string, data: Float32Array }[]} Live reference; do not mutate.
227
- */
228
- getScalarAttributes() {
229
- return this.#scalar_attributes;
230
- }
231
-
232
- /**
233
- * Allocate all buffers. Must be called before any read/write. After this point,
234
- * resolution and attribute set are frozen.
235
- */
236
- build() {
237
- assert.notOk(this.#built, "build() called twice");
238
- assert.greaterThanOrEqual(this.#resolution[0], 1, "setResolution(...) must be called before build()");
239
-
240
- const cell_count = this.cellCount();
241
-
242
- this.velocity_x = new Float32Array(cell_count);
243
- this.velocity_y = new Float32Array(cell_count);
244
- this.velocity_z = new Float32Array(cell_count);
245
- this.solid = new Uint8Array(cell_count);
246
- this.solid_neighbour_mask = new Uint8Array(cell_count);
247
- const PressureCtor = this.half_precision_pressure ? Float16Array : Float32Array;
248
- this.pressure = new PressureCtor(cell_count);
249
-
250
- for (const attr of this.#scalar_attributes) {
251
- attr.data = new Float32Array(cell_count);
252
- }
253
-
254
- this.#built = true;
255
- }
256
-
257
- /**
258
- * Linear cell index for integer grid coordinates.
259
- * @param {number} x integer in [0, res_x)
260
- * @param {number} y integer in [0, res_y)
261
- * @param {number} z integer in [0, res_z)
262
- * @return {number} flat index `z * res_x * res_y + y * res_x + x`
263
- */
264
- cellIndex(x, y, z) {
265
- const res_x = this.#resolution[0];
266
- const res_y = this.#resolution[1];
267
- const res_z = this.#resolution[2];
268
- assert.greaterThanOrEqual(x, 0, "x");
269
- assert.lessThan(x, res_x, "x");
270
- assert.greaterThanOrEqual(y, 0, "y");
271
- assert.lessThan(y, res_y, "y");
272
- assert.greaterThanOrEqual(z, 0, "z");
273
- assert.lessThan(z, res_z, "z");
274
- return z * res_x * res_y + y * res_x + x;
275
- }
276
-
277
- /**
278
- * Set the velocity at an integer grid cell.
279
- * @param {number} x
280
- * @param {number} y
281
- * @param {number} z
282
- * @param {number} vx
283
- * @param {number} vy
284
- * @param {number} vz
285
- */
286
- setVelocityAt(x, y, z, vx, vy, vz) {
287
- const c = this.cellIndex(x, y, z);
288
- this.velocity_x[c] = vx;
289
- this.velocity_y[c] = vy;
290
- this.velocity_z[c] = vz;
291
- }
292
-
293
- /**
294
- * Add to the velocity at an integer grid cell (impulse).
295
- * @param {number} x
296
- * @param {number} y
297
- * @param {number} z
298
- * @param {number} dvx
299
- * @param {number} dvy
300
- * @param {number} dvz
301
- */
302
- addVelocityAt(x, y, z, dvx, dvy, dvz) {
303
- const c = this.cellIndex(x, y, z);
304
- this.velocity_x[c] += dvx;
305
- this.velocity_y[c] += dvy;
306
- this.velocity_z[c] += dvz;
307
- }
308
-
309
- /**
310
- * @param {number} attribute_index
311
- * @param {number} x
312
- * @param {number} y
313
- * @param {number} z
314
- * @param {number} value
315
- */
316
- setScalarAtIndex(attribute_index, x, y, z, value) {
317
- assert.greaterThanOrEqual(attribute_index, 0, "attribute_index");
318
- assert.lessThan(attribute_index, this.#scalar_attributes.length, "attribute_index");
319
- const c = this.cellIndex(x, y, z);
320
- this.#scalar_attributes[attribute_index].data[c] = value;
321
- }
322
-
323
- /**
324
- * Mark a cell as solid (wall) or fluid.
325
- * @param {number} x
326
- * @param {number} y
327
- * @param {number} z
328
- * @param {boolean} is_solid
329
- */
330
- setSolidAt(x, y, z, is_solid) {
331
- this.solid[this.cellIndex(x, y, z)] = is_solid ? 1 : 0;
332
- }
333
-
334
- /**
335
- * @param {number} x
336
- * @param {number} y
337
- * @param {number} z
338
- * @return {boolean} true if the cell is marked solid.
339
- */
340
- isSolidAt(x, y, z) {
341
- return this.solid[this.cellIndex(x, y, z)] !== 0;
342
- }
343
-
344
- /**
345
- * Sample velocity at a fractional grid position (positions outside the grid are
346
- * clamped). Writes into `out` and returns it.
347
- * @param {Float32Array|number[]} out Length-3 destination.
348
- * @param {number} x
349
- * @param {number} y
350
- * @param {number} z
351
- * @return {Float32Array|number[]} `out`, for chaining.
352
- */
353
- sampleVelocity(out, x, y, z) {
354
- const res_x = this.#resolution[0];
355
- const res_y = this.#resolution[1];
356
- const res_z = this.#resolution[2];
357
- out[0] = scs3d_sample_linear(this.velocity_x, res_x, res_y, res_z, x, y, z);
358
- out[1] = scs3d_sample_linear(this.velocity_y, res_x, res_y, res_z, x, y, z);
359
- out[2] = scs3d_sample_linear(this.velocity_z, res_x, res_y, res_z, x, y, z);
360
- return out;
361
- }
362
-
363
- /**
364
- * Sample a scalar attribute at a fractional grid position.
365
- * @param {string} name
366
- * @param {number} x
367
- * @param {number} y
368
- * @param {number} z
369
- * @return {number} trilinearly-interpolated value at `(x, y, z)`.
370
- */
371
- sampleScalar(name, x, y, z) {
372
- const data = this.getScalarData(name);
373
- assert.notNull(data, `scalar attribute '${name}'`);
374
- return scs3d_sample_linear(data, this.#resolution[0], this.#resolution[1], this.#resolution[2], x, y, z);
375
- }
376
-
377
- /**
378
- * Strict value equality. Two fields are equal iff they have the same resolution,
379
- * the same set of scalar attributes (matched by name AND index), and the same
380
- * buffer contents in `velocity_*`, `solid`, `pressure`, and each scalar. Pre-build
381
- * fields compare by resolution + attribute names only (their buffers are null).
382
- *
383
- * O(N) — walks every cell. Use {@link hash} for change-detection on hot paths.
384
- *
385
- * @param {FluidField} other
386
- * @return {boolean}
387
- */
388
- equals(other) {
389
- if (other === this) {
390
- return true;
391
- }
392
- if (!(other instanceof FluidField)) {
393
- return false;
394
- }
395
-
396
- if (this.#resolution[0] !== other.#resolution[0]
397
- || this.#resolution[1] !== other.#resolution[1]
398
- || this.#resolution[2] !== other.#resolution[2]) {
399
- return false;
400
- }
401
-
402
- if (this.#built !== other.#built) {
403
- return false;
404
- }
405
-
406
- const my_attrs = this.#scalar_attributes;
407
- const other_attrs = other.#scalar_attributes;
408
- if (my_attrs.length !== other_attrs.length) {
409
- return false;
410
- }
411
- for (let i = 0; i < my_attrs.length; i++) {
412
- if (my_attrs[i].name !== other_attrs[i].name) {
413
- return false;
414
- }
415
- }
416
-
417
- if (!this.#built) {
418
- // Buffers are null on both sides; resolution + names already matched.
419
- return true;
420
- }
421
-
422
- if (!is_typed_array_equals(this.velocity_x, other.velocity_x)
423
- || !is_typed_array_equals(this.velocity_y, other.velocity_y)
424
- || !is_typed_array_equals(this.velocity_z, other.velocity_z)) {
425
- return false;
426
- }
427
- if (!is_typed_array_equals(this.solid, other.solid)) {
428
- return false;
429
- }
430
- if (!is_typed_array_equals(this.pressure, other.pressure)) {
431
- return false;
432
- }
433
- for (let i = 0; i < my_attrs.length; i++) {
434
- if (!is_typed_array_equals(my_attrs[i].data, other_attrs[i].data)) {
435
- return false;
436
- }
437
- }
438
- return true;
439
- }
440
-
441
- /**
442
- * Fast hash suitable for change-detection. Combines the resolution and a *sparse*
443
- * sample of the velocity_x buffer {@link sparse_typed_array_hash} only inspects
444
- * the first ~1024 cells with stride enough to take ~31 samples, regardless of how
445
- * large the field is. The hash will catch most local edits to the velocity field
446
- * but is not a content-perfect fingerprint; for that, fall through to
447
- * {@link equals}.
448
- *
449
- * Constant-time relative to grid size in the common case.
450
- *
451
- * @return {number}
452
- */
453
- hash() {
454
- const velocity_sample = this.#built
455
- ? sparse_typed_array_hash(this.velocity_x, 0, this.velocity_x.length)
456
- : 0;
457
- return combine_hash(
458
- this.#resolution[0],
459
- this.#resolution[1],
460
- this.#resolution[2],
461
- this.#scalar_attributes.length,
462
- velocity_sample
463
- );
464
- }
465
-
466
- /**
467
- * Rebuild {@link solid_neighbour_mask} from the current {@link solid} buffer.
468
- *
469
- * O(N) one byte-write per cell, six byte-reads per cell. Called by the
470
- * simulator at the top of each project so callers never have to remember to
471
- * invalidate the mask after mutating solids; the cost is amortized across the
472
- * SOR sweep's many iterations.
473
- *
474
- * Encoding: see {@link solid_neighbour_mask}.
475
- */
476
- recomputeSolidNeighbourMask() {
477
- if (!this.#built) {
478
- return;
479
- }
480
- v3_grid_compute_solid_neighbour_mask(
481
- this.solid_neighbour_mask,
482
- this.solid,
483
- this.#resolution[0], this.#resolution[1], this.#resolution[2]
484
- );
485
- }
486
-
487
- /**
488
- * Translate the field's contents by `(shift_x, shift_y, shift_z)` grid cells —
489
- * called when the field's world-space origin moves, so the fluid data (anchored
490
- * to world space) follows. Every owned buffer (velocity_x/y/z, solid, pressure,
491
- * each scalar attribute) is shifted, then the newly-exposed edges are patched
492
- * via {@link v3_grid_patch_edges_uniform} (zero-gradient Neumann extrapolation —
493
- * "the field is locally uniform").
494
- *
495
- * Direction convention matches the primitive: positive shift means the grid's
496
- * world origin moved in that direction, so each cell takes the value previously
497
- * at its `+shift` neighbour.
498
- *
499
- * `(0, 0, 0)` is a no-op; |shift| ≥ res on any axis zero-fills (no valid source
500
- * left to replicate from). Pre-build fields (buffers null) are no-op'd.
501
- *
502
- * The solid mask is NOT migrated — it's cleared. Solids are out of scope for the
503
- * shift machinery: the contract is that the caller re-voxelizes scene geometry
504
- * and splats updated solid cells back into the field before the next simulation
505
- * tick. Migrating the existing mask would either lie about where the walls are
506
- * (if scene geometry moved) or produce double-bookkeeping problems if the caller
507
- * also re-voxelizes. Clearing keeps the contract obvious: "between a shift and
508
- * the next step, the field has no solids until you write them."
509
- *
510
- * @param {number} shift_x integer
511
- * @param {number} shift_y integer
512
- * @param {number} shift_z integer
513
- */
514
- shift(shift_x, shift_y, shift_z) {
515
- if (!this.#built) {
516
- return;
517
- }
518
- if (shift_x === 0 && shift_y === 0 && shift_z === 0) {
519
- return;
520
- }
521
-
522
- const rx = this.#resolution[0];
523
- const ry = this.#resolution[1];
524
- const rz = this.#resolution[2];
525
-
526
- // Velocity components.
527
- v3_grid_shift_in_place(this.velocity_x, rx, ry, rz, shift_x, shift_y, shift_z);
528
- v3_grid_patch_edges_uniform(this.velocity_x, rx, ry, rz, shift_x, shift_y, shift_z);
529
-
530
- v3_grid_shift_in_place(this.velocity_y, rx, ry, rz, shift_x, shift_y, shift_z);
531
- v3_grid_patch_edges_uniform(this.velocity_y, rx, ry, rz, shift_x, shift_y, shift_z);
532
-
533
- v3_grid_shift_in_place(this.velocity_z, rx, ry, rz, shift_x, shift_y, shift_z);
534
- v3_grid_patch_edges_uniform(this.velocity_z, rx, ry, rz, shift_x, shift_y, shift_z);
535
-
536
- // Solid mask — cleared, not migrated. Caller is expected to re-voxelize and
537
- // splat solids before the next simulation tick (see method docstring).
538
- // The derived neighbour mask is cleared too; the simulator's next project()
539
- // will repopulate it from the (potentially re-splatted) solid mask.
540
- this.solid.fill(0);
541
- this.solid_neighbour_mask.fill(0);
542
-
543
- // Pressure (warm-start state, carried across steps).
544
- v3_grid_shift_in_place(this.pressure, rx, ry, rz, shift_x, shift_y, shift_z);
545
- v3_grid_patch_edges_uniform(this.pressure, rx, ry, rz, shift_x, shift_y, shift_z);
546
-
547
- // Scalar attributes.
548
- for (let i = 0; i < this.#scalar_attributes.length; i++) {
549
- const data = this.#scalar_attributes[i].data;
550
- v3_grid_shift_in_place(data, rx, ry, rz, shift_x, shift_y, shift_z);
551
- v3_grid_patch_edges_uniform(data, rx, ry, rz, shift_x, shift_y, shift_z);
552
- }
553
- }
554
-
555
- /**
556
- * Zero velocity, pressure, and all scalar attributes. Solid mask is preserved.
557
- * Pressure is cleared to drop the warm-start (otherwise the next step's solve
558
- * begins from a stale solution that no longer matches the zero velocity).
559
- */
560
- clear() {
561
- assert.ok(this.#built, "build() must be called before clear()");
562
- this.velocity_x.fill(0);
563
- this.velocity_y.fill(0);
564
- this.velocity_z.fill(0);
565
- this.pressure.fill(0);
566
- for (const attr of this.#scalar_attributes) {
567
- attr.data.fill(0);
568
- }
569
- }
570
- }
1
+ import { assert } from "../../../core/assert.js";
2
+ import { combine_hash } from "../../../core/collection/array/combine_hash.js";
3
+ import { is_typed_array_equals } from "../../../core/collection/array/typed/is_typed_array_equals.js";
4
+ import { sparse_typed_array_hash } from "../../../core/collection/array/typed/sparse_typed_array_hash.js";
5
+ import { scs3d_sample_linear } from "../../graphics/texture/3d/scs3d_sample_linear.js";
6
+ import { v3_grid_compute_solid_neighbour_mask } from "./solver/v3_grid_compute_solid_neighbour_mask.js";
7
+ import { v3_grid_patch_edges_constant } from "./solver/v3_grid_patch_edges_constant.js";
8
+ import { v3_grid_patch_edges_uniform } from "./solver/v3_grid_patch_edges_uniform.js";
9
+ import { v3_grid_shift_in_place } from "./solver/v3_grid_shift_in_place.js";
10
+ import { v3_mac_compute_face_solid } from "./solver/v3_mac_compute_face_solid.js";
11
+
12
+ /**
13
+ * 3D Eulerian grid for the fluid simulator MAC (marker-and-cell) staggered
14
+ * layout: pressure, solids and scalars live at cell centers; each velocity
15
+ * component lives on the cell FACES normal to it (Harlow & Welch 1965).
16
+ *
17
+ * Staggering makes the discrete divergence and pressure gradient exact
18
+ * adjoints, so projection drives divergence to actual zero (no collocated
19
+ * operator-mismatch floor, no projection-invisible checkerboard modes) and
20
+ * solid boundaries pin the exact normal face velocity (true no-penetration).
21
+ *
22
+ * Holds three face-centered velocity components, a per-cell `solid` mask, and any
23
+ * number of user-defined cell-centered passive scalar attributes transported by
24
+ * the flow.
25
+ *
26
+ * Holds only state whose value carries information across step boundaries. The
27
+ * simulator's transient working memory (per-step velocity snapshots, divergence,
28
+ * diffusion / scalar ping-pong scratch) lives on the simulator. `pressure` is the
29
+ * one exception: it's warm-started each step from the previous solve, so its value
30
+ * is genuine cross-step state and belongs here.
31
+ *
32
+ * All typed array references are STABLE for the lifetime of the field. External
33
+ * consumers can safely cache references returned from {@link getScalarData},
34
+ * {@link velocity_x}, etc.
35
+ *
36
+ * @see "Real-Time Fluid Dynamics for Games" (Stam, 2003)
37
+ * @see GDC 2019 talk "Wind Simulation in God of War" (Rupert Renard) for the wider
38
+ * effector-driven design pattern this package is moving toward.
39
+ */
40
+ export class FluidField {
41
+
42
+ /**
43
+ * Grid dimensions in cells, `[x, y, z]`.
44
+ * @type {[number, number, number]}
45
+ */
46
+ #resolution = [0, 0, 0];
47
+
48
+ /**
49
+ * Velocity X component on x-faces. Length `(res_x+1) * res_y * res_z`,
50
+ * indexed by `z * (res_x+1) * res_y + y * (res_x+1) + x` with
51
+ * `x ∈ [0, res_x]`. Face `(x, y, z)` sits between cells `(x−1, y, z)` and
52
+ * `(x, y, z)` — at grid-space position `(x − 0.5, y, z)` in the
53
+ * cell-center coordinate frame.
54
+ * @type {Float32Array|null}
55
+ */
56
+ velocity_x = null;
57
+
58
+ /**
59
+ * Velocity Y component on y-faces. Length `res_x * (res_y+1) * res_z`,
60
+ * indexed by `z * res_x * (res_y+1) + y * res_x + x` with `y ∈ [0, res_y]`.
61
+ * @type {Float32Array|null}
62
+ */
63
+ velocity_y = null;
64
+
65
+ /**
66
+ * Velocity Z component on z-faces. Length `res_x * res_y * (res_z+1)`,
67
+ * indexed by `z * res_x * res_y + y * res_x + x` with `z ∈ [0, res_z]`
68
+ * (the face slice size equals the cell slice size).
69
+ * @type {Float32Array|null}
70
+ */
71
+ velocity_z = null;
72
+
73
+ /**
74
+ * Per-cell solid flag. `0` = fluid, non-zero = solid (wall). Always allocated by
75
+ * {@link build} (zero-filled — every cell defaults to fluid). The solver and every
76
+ * effector read this unconditionally, so the array is part of the field's
77
+ * uniform shape, not an optional add-on.
78
+ * @type {Uint8Array|null}
79
+ */
80
+ solid = null;
81
+
82
+ /**
83
+ * Per-cell pre-baked neighbourhood mask consumed by the pressure SOR loop.
84
+ * One byte per cell encoding which of the 6 cardinal neighbours are fluid:
85
+ *
86
+ * bit 0 (= 1) : -x neighbour is fluid (in-bounds AND non-solid)
87
+ * bit 1 (= 2) : +x neighbour is fluid
88
+ * bit 2 (= 4) : -y neighbour is fluid
89
+ * bit 3 (= 8) : +y neighbour is fluid
90
+ * bit 4 (= 16) : -z neighbour is fluid
91
+ * bit 5 (= 32) : +z neighbour is fluid
92
+ * bit 7 (= 128) : this cell is itself solid
93
+ *
94
+ * A solid cell encodes as `128` (bit 7 set, neighbour bits clear) and an
95
+ * isolated fluid cell as `0`, so the SOR / PCG loops' `if ((mask & 63) === 0)
96
+ * continue` skip handles both "this cell is solid" and "this fluid cell is
97
+ * isolated" with a single comparison instead of one solid-self-check plus six
98
+ * solid-neighbour-checks plus six boundary checks. Bit 7 additionally lets
99
+ * {@link v3_grid_subtract_pressure_gradient} zero solid-cell velocity without
100
+ * consulting the {@link solid} array.
101
+ *
102
+ * Computed once by {@link recomputeSolidNeighbourMask} after every solid-mask
103
+ * mutation. The simulator runs that recompute once per step (after effectors,
104
+ * which may splat solids) and at the top of every direct project() call, so
105
+ * callers never have to remember to invalidate it; the per-step cost is one
106
+ * O(N) byte-pass against the bandwidth-bound SOR sweep that runs many
107
+ * iterations per call. {@link shift} also refreshes it after migrating the
108
+ * solid mask.
109
+ *
110
+ * @type {Uint8Array|null}
111
+ */
112
+ solid_neighbour_mask = null;
113
+
114
+ /**
115
+ * Per-face "pinned" mask for x-faces: `1` where either adjacent cell is
116
+ * solid the face's normal velocity is a boundary condition (0 for
117
+ * static solids), not a degree of freedom. Same length and indexing as
118
+ * {@link velocity_x}. Baked by {@link recomputeSolidNeighbourMask} via
119
+ * {@link v3_mac_compute_face_solid}; domain-edge faces stay 0 (open).
120
+ * @type {Uint8Array|null}
121
+ */
122
+ face_solid_x = null;
123
+
124
+ /**
125
+ * y-face pinned mask — see {@link face_solid_x}.
126
+ * @type {Uint8Array|null}
127
+ */
128
+ face_solid_y = null;
129
+
130
+ /**
131
+ * z-face pinned mask — see {@link face_solid_x}.
132
+ * @type {Uint8Array|null}
133
+ */
134
+ face_solid_z = null;
135
+
136
+ /**
137
+ * Per-cell pressure-Laplacian diagonal, baked alongside
138
+ * {@link solid_neighbour_mask} by the same kernel pass:
139
+ *
140
+ * diag = (# fluid neighbours) + (# open faces)
141
+ *
142
+ * where an open face is one on the domain edge (out-of-bounds neighbour).
143
+ * The domain edge is an OPEN boundary — ghost pressure 0 — so flow can
144
+ * vent through it; solid faces are reflecting (Neumann) and drop out of
145
+ * the diagonal. A solid cell, or a fluid cell sealed on all six faces,
146
+ * has `diag = 0`, which is the solvers' single skip test. Sealed domains
147
+ * are built explicitly by lining the boundary with solid cells.
148
+ *
149
+ * Same freshness contract as {@link solid_neighbour_mask}.
150
+ *
151
+ * @type {Uint8Array|null}
152
+ */
153
+ pressure_diag = null;
154
+
155
+ /**
156
+ * Pressure field from the most recent projection. Owned by the field rather than
157
+ * the simulator because the simulator warm-starts each solve from the previous
158
+ * result — step N+1 depends on the value step N wrote here. If this lived on the
159
+ * simulator, replacing the simulator instance between steps would silently degrade
160
+ * convergence at the same iteration count.
161
+ *
162
+ * Storage type is {@link Float32Array} by default, or {@link Float16Array} when
163
+ * {@link half_precision_pressure} is enabled before build — see that field for
164
+ * the bandwidth-vs-quality trade-off.
165
+ *
166
+ * Safe to read for debug visualisation. Don't mutate.
167
+ * @type {Float32Array|Float16Array|null}
168
+ */
169
+ pressure = null;
170
+
171
+ /**
172
+ * Allocate {@link pressure} as {@link Float16Array} instead of {@link Float32Array}.
173
+ *
174
+ * **Currently slower in V8 — keep `false`.** The intent of this option is to
175
+ * halve the memory bandwidth on the pressure SOR sweep (the simulator's
176
+ * hottest, bandwidth-bound loop). On hardware with F16C the per-cell f16↔f32
177
+ * conversion is ~1 cycle and the bandwidth saving wins. In V8 as of Node 24
178
+ * the conversion path is not yet specialized — each read of `pressure[i]`
179
+ * goes through a slow generic Float16 unboxing routine, and the result is
180
+ * the opposite of what you'd expect: bench at 64³ shows **49% slower** with
181
+ * f16, at 128³ **28% slower** (see `bench: half_precision_pressure on/off`
182
+ * in bench.spec.js). The bandwidth-savings story still holds in principle;
183
+ * it'll likely become a real win once V8 adds inline support for
184
+ * Float16Array access (the typed array landed in Node 24 / TC39 Stage 4 only
185
+ * recently).
186
+ *
187
+ * Cost when it does win: Float16 has ~3 decimal digits of precision. The SOR
188
+ * iterate rounds to f16 on every write, so iteration error can't fall below
189
+ * ~10⁻³ relative. Bench currently shows max|div| within 8% of the f32
190
+ * baseline at 64³ and 128³ acceptable for visual sim but not for
191
+ * quantitative pressure use.
192
+ *
193
+ * Must be set before {@link build}.
194
+ *
195
+ * The simulator's internal divergence scratch follows this type automatically
196
+ * (re-allocated to match `pressure.constructor` on each project call).
197
+ *
198
+ * @type {boolean}
199
+ */
200
+ half_precision_pressure = false;
201
+
202
+ /**
203
+ * @type {{ name: string, data: Float32Array }[]}
204
+ */
205
+ #scalar_attributes = [];
206
+
207
+ #built = false;
208
+
209
+ /**
210
+ * Set the grid dimensions in cells. Must be called before {@link build}; throws if
211
+ * the field is already built.
212
+ * @param {number} res_x positive integer
213
+ * @param {number} res_y positive integer
214
+ * @param {number} res_z positive integer
215
+ */
216
+ setResolution(res_x, res_y, res_z) {
217
+ assert.notOk(this.#built, "resolution cannot be changed after build()");
218
+ assert.isPositiveInteger(res_x, "res_x");
219
+ assert.isPositiveInteger(res_y, "res_y");
220
+ assert.isPositiveInteger(res_z, "res_z");
221
+
222
+ this.#resolution[0] = res_x;
223
+ this.#resolution[1] = res_y;
224
+ this.#resolution[2] = res_z;
225
+ }
226
+
227
+ /**
228
+ * @return {[number, number, number]} A reference to the internal resolution array.
229
+ * Do not mutate.
230
+ */
231
+ getResolution() {
232
+ return this.#resolution;
233
+ }
234
+
235
+ /**
236
+ * @return {number} `res_x * res_y * res_z`. Zero until {@link setResolution} is
237
+ * called.
238
+ */
239
+ cellCount() {
240
+ return this.#resolution[0] * this.#resolution[1] * this.#resolution[2];
241
+ }
242
+
243
+ /**
244
+ * Register a passive scalar attribute (density, temperature, dye, etc.) that will be
245
+ * advected by the velocity field each step. Idempotent re-adding an existing name
246
+ * returns the existing index.
247
+ *
248
+ * Must be called before {@link build}.
249
+ *
250
+ * @param {string} name
251
+ * @return {number} index of the attribute (use with {@link setScalarAtIndex})
252
+ */
253
+ addScalar(name) {
254
+ assert.notOk(this.#built, "addScalar cannot be called after build()");
255
+ assert.isString(name, "name");
256
+ assert.greaterThan(name.length, 0, "name must be non-empty");
257
+
258
+ const existing = this.#scalar_attributes.findIndex(a => a.name === name);
259
+ if (existing !== -1) {
260
+ return existing;
261
+ }
262
+
263
+ const index = this.#scalar_attributes.length;
264
+ this.#scalar_attributes.push({ name, data: null });
265
+ return index;
266
+ }
267
+
268
+ /**
269
+ * @param {string} name
270
+ * @return {number} index the attribute was registered with, or -1 if not present.
271
+ */
272
+ scalarIndex(name) {
273
+ return this.#scalar_attributes.findIndex(a => a.name === name);
274
+ }
275
+
276
+ /**
277
+ * @param {string} name
278
+ * @return {Float32Array|null} live buffer for the named scalar, or null if not
279
+ * registered.
280
+ */
281
+ getScalarData(name) {
282
+ const a = this.#scalar_attributes.find(a => a.name === name);
283
+ return a === undefined ? null : a.data;
284
+ }
285
+
286
+ /**
287
+ * @return {{ name: string, data: Float32Array }[]} Live reference; do not mutate.
288
+ */
289
+ getScalarAttributes() {
290
+ return this.#scalar_attributes;
291
+ }
292
+
293
+ /**
294
+ * Allocate all buffers. Must be called before any read/write. After this point,
295
+ * resolution and attribute set are frozen.
296
+ */
297
+ build() {
298
+ assert.notOk(this.#built, "build() called twice");
299
+ assert.greaterThanOrEqual(this.#resolution[0], 1, "setResolution(...) must be called before build()");
300
+
301
+ const cell_count = this.cellCount();
302
+ const rx = this.#resolution[0];
303
+ const ry = this.#resolution[1];
304
+ const rz = this.#resolution[2];
305
+ const face_count_x = (rx + 1) * ry * rz;
306
+ const face_count_y = rx * (ry + 1) * rz;
307
+ const face_count_z = rx * ry * (rz + 1);
308
+
309
+ this.velocity_x = new Float32Array(face_count_x);
310
+ this.velocity_y = new Float32Array(face_count_y);
311
+ this.velocity_z = new Float32Array(face_count_z);
312
+ this.face_solid_x = new Uint8Array(face_count_x);
313
+ this.face_solid_y = new Uint8Array(face_count_y);
314
+ this.face_solid_z = new Uint8Array(face_count_z);
315
+ this.solid = new Uint8Array(cell_count);
316
+ this.solid_neighbour_mask = new Uint8Array(cell_count);
317
+ this.pressure_diag = new Uint8Array(cell_count);
318
+ const PressureCtor = this.half_precision_pressure ? Float16Array : Float32Array;
319
+ this.pressure = new PressureCtor(cell_count);
320
+
321
+ for (const attr of this.#scalar_attributes) {
322
+ attr.data = new Float32Array(cell_count);
323
+ }
324
+
325
+ this.#built = true;
326
+ }
327
+
328
+ /**
329
+ * Linear cell index for integer grid coordinates.
330
+ * @param {number} x integer in [0, res_x)
331
+ * @param {number} y integer in [0, res_y)
332
+ * @param {number} z integer in [0, res_z)
333
+ * @return {number} flat index `z * res_x * res_y + y * res_x + x`
334
+ */
335
+ cellIndex(x, y, z) {
336
+ const res_x = this.#resolution[0];
337
+ const res_y = this.#resolution[1];
338
+ const res_z = this.#resolution[2];
339
+ assert.greaterThanOrEqual(x, 0, "x");
340
+ assert.lessThan(x, res_x, "x");
341
+ assert.greaterThanOrEqual(y, 0, "y");
342
+ assert.lessThan(y, res_y, "y");
343
+ assert.greaterThanOrEqual(z, 0, "z");
344
+ assert.lessThan(z, res_z, "z");
345
+ return z * res_x * res_y + y * res_x + x;
346
+ }
347
+
348
+ /**
349
+ * Set the velocity of an integer grid cell: each component is written to
350
+ * BOTH faces of the cell along its axis, so sampling at the cell centre
351
+ * reads back exactly `(vx, vy, vz)`. Adjacent cells share faces — the
352
+ * later write wins on a shared face, exactly like overlapping
353
+ * cell-centered writes used to.
354
+ * @param {number} x
355
+ * @param {number} y
356
+ * @param {number} z
357
+ * @param {number} vx
358
+ * @param {number} vy
359
+ * @param {number} vz
360
+ */
361
+ setVelocityAt(x, y, z, vx, vy, vz) {
362
+ this.cellIndex(x, y, z); // asserts bounds
363
+ const rx = this.#resolution[0];
364
+ const ry = this.#resolution[1];
365
+ const sx = rx + 1;
366
+ const u = z * sx * ry + y * sx + x;
367
+ this.velocity_x[u] = vx;
368
+ this.velocity_x[u + 1] = vx;
369
+ const v = z * rx * (ry + 1) + y * rx + x;
370
+ this.velocity_y[v] = vy;
371
+ this.velocity_y[v + rx] = vy;
372
+ const w = z * rx * ry + y * rx + x;
373
+ this.velocity_z[w] = vz;
374
+ this.velocity_z[w + rx * ry] = vz;
375
+ }
376
+
377
+ /**
378
+ * Add to the velocity of an integer grid cell (impulse). Deposits each
379
+ * component onto BOTH faces of the cell along its axis; the centre-sampled
380
+ * velocity increases by exactly `(dvx, dvy, dvz)`.
381
+ * @param {number} x
382
+ * @param {number} y
383
+ * @param {number} z
384
+ * @param {number} dvx
385
+ * @param {number} dvy
386
+ * @param {number} dvz
387
+ */
388
+ addVelocityAt(x, y, z, dvx, dvy, dvz) {
389
+ this.cellIndex(x, y, z); // asserts bounds
390
+ const rx = this.#resolution[0];
391
+ const ry = this.#resolution[1];
392
+ const sx = rx + 1;
393
+ const u = z * sx * ry + y * sx + x;
394
+ this.velocity_x[u] += dvx;
395
+ this.velocity_x[u + 1] += dvx;
396
+ const v = z * rx * (ry + 1) + y * rx + x;
397
+ this.velocity_y[v] += dvy;
398
+ this.velocity_y[v + rx] += dvy;
399
+ const w = z * rx * ry + y * rx + x;
400
+ this.velocity_z[w] += dvz;
401
+ this.velocity_z[w + rx * ry] += dvz;
402
+ }
403
+
404
+ /**
405
+ * @param {number} attribute_index
406
+ * @param {number} x
407
+ * @param {number} y
408
+ * @param {number} z
409
+ * @param {number} value
410
+ */
411
+ setScalarAtIndex(attribute_index, x, y, z, value) {
412
+ assert.greaterThanOrEqual(attribute_index, 0, "attribute_index");
413
+ assert.lessThan(attribute_index, this.#scalar_attributes.length, "attribute_index");
414
+ const c = this.cellIndex(x, y, z);
415
+ this.#scalar_attributes[attribute_index].data[c] = value;
416
+ }
417
+
418
+ /**
419
+ * Mark a cell as solid (wall) or fluid.
420
+ * @param {number} x
421
+ * @param {number} y
422
+ * @param {number} z
423
+ * @param {boolean} is_solid
424
+ */
425
+ setSolidAt(x, y, z, is_solid) {
426
+ this.solid[this.cellIndex(x, y, z)] = is_solid ? 1 : 0;
427
+ }
428
+
429
+ /**
430
+ * @param {number} x
431
+ * @param {number} y
432
+ * @param {number} z
433
+ * @return {boolean} true if the cell is marked solid.
434
+ */
435
+ isSolidAt(x, y, z) {
436
+ return this.solid[this.cellIndex(x, y, z)] !== 0;
437
+ }
438
+
439
+ /**
440
+ * Sample velocity at a fractional grid position in CELL-CENTER coordinates
441
+ * (positions outside the grid are clamped). Each component is trilinearly
442
+ * interpolated on its own staggered face lattice x-face `i` sits at
443
+ * `x = i − 0.5`, so the component is sampled at `x + 0.5` in face-index
444
+ * space, and likewise per axis. Writes into `out` and returns it.
445
+ * @param {Float32Array|number[]} out Length-3 destination.
446
+ * @param {number} x
447
+ * @param {number} y
448
+ * @param {number} z
449
+ * @return {Float32Array|number[]} `out`, for chaining.
450
+ */
451
+ sampleVelocity(out, x, y, z) {
452
+ const res_x = this.#resolution[0];
453
+ const res_y = this.#resolution[1];
454
+ const res_z = this.#resolution[2];
455
+ out[0] = scs3d_sample_linear(this.velocity_x, res_x + 1, res_y, res_z, x + 0.5, y, z);
456
+ out[1] = scs3d_sample_linear(this.velocity_y, res_x, res_y + 1, res_z, x, y + 0.5, z);
457
+ out[2] = scs3d_sample_linear(this.velocity_z, res_x, res_y, res_z + 1, x, y, z + 0.5);
458
+ return out;
459
+ }
460
+
461
+ /**
462
+ * Sample a scalar attribute at a fractional grid position.
463
+ * @param {string} name
464
+ * @param {number} x
465
+ * @param {number} y
466
+ * @param {number} z
467
+ * @return {number} trilinearly-interpolated value at `(x, y, z)`.
468
+ */
469
+ sampleScalar(name, x, y, z) {
470
+ const data = this.getScalarData(name);
471
+ assert.notNull(data, `scalar attribute '${name}'`);
472
+ return scs3d_sample_linear(data, this.#resolution[0], this.#resolution[1], this.#resolution[2], x, y, z);
473
+ }
474
+
475
+ /**
476
+ * Strict value equality. Two fields are equal iff they have the same resolution,
477
+ * the same set of scalar attributes (matched by name AND index), and the same
478
+ * buffer contents in `velocity_*`, `solid`, `pressure`, and each scalar. Pre-build
479
+ * fields compare by resolution + attribute names only (their buffers are null).
480
+ *
481
+ * O(N) — walks every cell. Use {@link hash} for change-detection on hot paths.
482
+ *
483
+ * @param {FluidField} other
484
+ * @return {boolean}
485
+ */
486
+ equals(other) {
487
+ if (other === this) {
488
+ return true;
489
+ }
490
+ if (!(other instanceof FluidField)) {
491
+ return false;
492
+ }
493
+
494
+ if (this.#resolution[0] !== other.#resolution[0]
495
+ || this.#resolution[1] !== other.#resolution[1]
496
+ || this.#resolution[2] !== other.#resolution[2]) {
497
+ return false;
498
+ }
499
+
500
+ if (this.#built !== other.#built) {
501
+ return false;
502
+ }
503
+
504
+ const my_attrs = this.#scalar_attributes;
505
+ const other_attrs = other.#scalar_attributes;
506
+ if (my_attrs.length !== other_attrs.length) {
507
+ return false;
508
+ }
509
+ for (let i = 0; i < my_attrs.length; i++) {
510
+ if (my_attrs[i].name !== other_attrs[i].name) {
511
+ return false;
512
+ }
513
+ }
514
+
515
+ if (!this.#built) {
516
+ // Buffers are null on both sides; resolution + names already matched.
517
+ return true;
518
+ }
519
+
520
+ if (!is_typed_array_equals(this.velocity_x, other.velocity_x)
521
+ || !is_typed_array_equals(this.velocity_y, other.velocity_y)
522
+ || !is_typed_array_equals(this.velocity_z, other.velocity_z)) {
523
+ return false;
524
+ }
525
+ if (!is_typed_array_equals(this.solid, other.solid)) {
526
+ return false;
527
+ }
528
+ if (!is_typed_array_equals(this.pressure, other.pressure)) {
529
+ return false;
530
+ }
531
+ for (let i = 0; i < my_attrs.length; i++) {
532
+ if (!is_typed_array_equals(my_attrs[i].data, other_attrs[i].data)) {
533
+ return false;
534
+ }
535
+ }
536
+ return true;
537
+ }
538
+
539
+ /**
540
+ * Fast hash suitable for change-detection. Combines the resolution and a *sparse*
541
+ * sample of the velocity_x buffer — {@link sparse_typed_array_hash} only inspects
542
+ * the first ~1024 cells with stride enough to take ~31 samples, regardless of how
543
+ * large the field is. The hash will catch most local edits to the velocity field
544
+ * but is not a content-perfect fingerprint; for that, fall through to
545
+ * {@link equals}.
546
+ *
547
+ * Constant-time relative to grid size in the common case.
548
+ *
549
+ * @return {number}
550
+ */
551
+ hash() {
552
+ const velocity_sample = this.#built
553
+ ? sparse_typed_array_hash(this.velocity_x, 0, this.velocity_x.length)
554
+ : 0;
555
+ return combine_hash(
556
+ this.#resolution[0],
557
+ this.#resolution[1],
558
+ this.#resolution[2],
559
+ this.#scalar_attributes.length,
560
+ velocity_sample
561
+ );
562
+ }
563
+
564
+ /**
565
+ * Rebuild {@link solid_neighbour_mask} and {@link pressure_diag} from the
566
+ * current {@link solid} buffer.
567
+ *
568
+ * O(N) — two byte-writes per cell, six byte-reads per cell. Called by the
569
+ * simulator once per step and at the top of each direct project() call, so
570
+ * callers never have to remember to invalidate the mask after mutating
571
+ * solids; the cost is amortized across the SOR sweep's many iterations.
572
+ *
573
+ * Encoding: see {@link solid_neighbour_mask} and {@link pressure_diag}.
574
+ */
575
+ recomputeSolidNeighbourMask() {
576
+ if (!this.#built) {
577
+ return;
578
+ }
579
+ v3_grid_compute_solid_neighbour_mask(
580
+ this.solid_neighbour_mask,
581
+ this.pressure_diag,
582
+ this.solid,
583
+ this.#resolution[0], this.#resolution[1], this.#resolution[2]
584
+ );
585
+ v3_mac_compute_face_solid(
586
+ this.face_solid_x, this.face_solid_y, this.face_solid_z,
587
+ this.velocity_x, this.velocity_y, this.velocity_z,
588
+ this.solid,
589
+ this.#resolution[0], this.#resolution[1], this.#resolution[2]
590
+ );
591
+ }
592
+
593
+ /**
594
+ * Translate the field's contents by `(shift_x, shift_y, shift_z)` grid cells —
595
+ * called when the field's world-space origin moves, so the fluid data (anchored
596
+ * to world space) follows. Every owned buffer (velocity_x/y/z, solid, pressure,
597
+ * each scalar attribute) is shifted, then the newly-exposed edges are patched
598
+ * via {@link v3_grid_patch_edges_uniform} (zero-gradient Neumann extrapolation —
599
+ * "the field is locally uniform").
600
+ *
601
+ * Direction convention matches the primitive: positive shift means the grid's
602
+ * world origin moved in that direction, so each cell takes the value previously
603
+ * at its `+shift` neighbour.
604
+ *
605
+ * `(0, 0, 0)` is a no-op; |shift| ≥ res on any axis zero-fills (no valid source
606
+ * left to replicate from). Pre-build fields (buffers null) are no-op'd.
607
+ *
608
+ * The solid mask is migrated like every other buffer — solids are anchored to
609
+ * world space exactly like the fluid they bound, so a wall must stay where the
610
+ * world says it is when the grid hops a cell. Newly scrolled-in cells become
611
+ * fluid (`0`): the field knows nothing about un-simulated space, and "empty
612
+ * until a voxelizer says otherwise" is the only honest default. Callers that
613
+ * voxelize scene geometry can keep overwriting the mask each tick — the
614
+ * migrated values are then simply replaced. (Earlier behaviour cleared the
615
+ * whole mask on shift, which made every grid hop simulate one tick with no
616
+ * walls anywhere — fluid leaked through geometry until the caller re-splatted.)
617
+ *
618
+ * The derived {@link solid_neighbour_mask} is refreshed here too, so the field
619
+ * stays self-consistent for direct kernel users; the simulator's per-step
620
+ * refresh makes this redundant in the ECS path but shifts are rare (once per
621
+ * cell crossing) and the pass is one byte-write per cell.
622
+ *
623
+ * @param {number} shift_x integer
624
+ * @param {number} shift_y integer
625
+ * @param {number} shift_z integer
626
+ */
627
+ shift(shift_x, shift_y, shift_z) {
628
+ if (!this.#built) {
629
+ return;
630
+ }
631
+ if (shift_x === 0 && shift_y === 0 && shift_z === 0) {
632
+ return;
633
+ }
634
+
635
+ const rx = this.#resolution[0];
636
+ const ry = this.#resolution[1];
637
+ const rz = this.#resolution[2];
638
+
639
+ // Velocity components — each face grid shifts with its own dimensions.
640
+ // Faces ride along with the cells (face i sits between cells i−1 and
641
+ // i), so the integer cell shift applies unchanged on the face lattice.
642
+ v3_grid_shift_in_place(this.velocity_x, rx + 1, ry, rz, shift_x, shift_y, shift_z);
643
+ v3_grid_patch_edges_uniform(this.velocity_x, rx + 1, ry, rz, shift_x, shift_y, shift_z);
644
+
645
+ v3_grid_shift_in_place(this.velocity_y, rx, ry + 1, rz, shift_x, shift_y, shift_z);
646
+ v3_grid_patch_edges_uniform(this.velocity_y, rx, ry + 1, rz, shift_x, shift_y, shift_z);
647
+
648
+ v3_grid_shift_in_place(this.velocity_z, rx, ry, rz + 1, shift_x, shift_y, shift_z);
649
+ v3_grid_patch_edges_uniform(this.velocity_z, rx, ry, rz + 1, shift_x, shift_y, shift_z);
650
+
651
+ // Solid mask — world-anchored like the fluid; scrolled-in cells are fluid.
652
+ // recomputeSolidNeighbourMask refreshes every derived mask (cell + face).
653
+ v3_grid_shift_in_place(this.solid, rx, ry, rz, shift_x, shift_y, shift_z);
654
+ v3_grid_patch_edges_constant(this.solid, rx, ry, rz, shift_x, shift_y, shift_z, 0);
655
+ this.recomputeSolidNeighbourMask();
656
+
657
+ // Pressure (warm-start state, carried across steps).
658
+ v3_grid_shift_in_place(this.pressure, rx, ry, rz, shift_x, shift_y, shift_z);
659
+ v3_grid_patch_edges_uniform(this.pressure, rx, ry, rz, shift_x, shift_y, shift_z);
660
+
661
+ // Scalar attributes.
662
+ for (let i = 0; i < this.#scalar_attributes.length; i++) {
663
+ const data = this.#scalar_attributes[i].data;
664
+ v3_grid_shift_in_place(data, rx, ry, rz, shift_x, shift_y, shift_z);
665
+ v3_grid_patch_edges_uniform(data, rx, ry, rz, shift_x, shift_y, shift_z);
666
+ }
667
+ }
668
+
669
+ /**
670
+ * Zero velocity, pressure, and all scalar attributes. Solid mask is preserved.
671
+ * Pressure is cleared to drop the warm-start (otherwise the next step's solve
672
+ * begins from a stale solution that no longer matches the zero velocity).
673
+ */
674
+ clear() {
675
+ assert.ok(this.#built, "build() must be called before clear()");
676
+ this.velocity_x.fill(0);
677
+ this.velocity_y.fill(0);
678
+ this.velocity_z.fill(0);
679
+ this.pressure.fill(0);
680
+ for (const attr of this.#scalar_attributes) {
681
+ attr.data.fill(0);
682
+ }
683
+ }
684
+ }