@woosh/meep-engine 3.22.0 → 3.23.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 (267) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts +118 -0
  3. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts.map +1 -0
  4. package/src/core/geom/3d/hash-grid/PointHashGrid3.js +283 -0
  5. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -1
  6. package/src/core/geom/3d/shape/BoxShape3D.js +6 -17
  7. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  8. package/src/core/geom/3d/shape/CapsuleShape3D.js +3 -14
  9. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  10. package/src/core/geom/3d/shape/CylinderShape3D.js +3 -21
  11. package/src/core/geom/3d/shape/PlaneShape3D.d.ts +105 -0
  12. package/src/core/geom/3d/shape/PlaneShape3D.d.ts.map +1 -0
  13. package/src/core/geom/3d/shape/PlaneShape3D.js +251 -0
  14. package/src/core/geom/3d/shape/SphereShape3D.js +3 -3
  15. package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
  16. package/src/core/geom/3d/shape/json/shape_to_type.js +3 -0
  17. package/src/core/geom/3d/shape/json/type_adapters.d.ts +14 -0
  18. package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
  19. package/src/core/geom/3d/shape/json/type_adapters.js +15 -0
  20. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts +51 -0
  21. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts.map +1 -0
  22. package/src/core/geom/3d/shape/sdf/sdf3_box.js +113 -0
  23. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts +46 -0
  24. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts.map +1 -0
  25. package/src/core/geom/3d/shape/sdf/sdf3_capsule.js +82 -0
  26. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts +60 -0
  27. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts.map +1 -0
  28. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.js +126 -0
  29. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts +50 -0
  30. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts.map +1 -0
  31. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.js +53 -0
  32. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts +52 -0
  33. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts.map +1 -0
  34. package/src/core/geom/3d/shape/sdf/sdf3_plane.js +61 -0
  35. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts +41 -0
  36. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts.map +1 -0
  37. package/src/core/geom/3d/shape/sdf/sdf3_sphere.js +71 -0
  38. package/src/core/process/ConcurrencyGate.d.ts +103 -0
  39. package/src/core/process/ConcurrencyGate.d.ts.map +1 -0
  40. package/src/core/process/ConcurrencyGate.js +207 -0
  41. package/src/engine/asset/AssetManager.d.ts +10 -0
  42. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  43. package/src/engine/asset/AssetManager.js +10 -0
  44. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +30 -13
  45. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +26 -0
  46. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -0
  47. package/src/engine/graphics3/pose/collect_entity_playbacks.js +40 -0
  48. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  49. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +74 -101
  50. package/src/engine/physics/cloth/MEASUREMENTS.md +1287 -4
  51. package/src/engine/physics/cloth/PLAN.md +1967 -1581
  52. package/src/engine/physics/cloth/build/ClothProxy.d.ts +147 -0
  53. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -0
  54. package/src/engine/physics/cloth/build/ClothProxy.js +207 -0
  55. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +70 -0
  56. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -0
  57. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +256 -0
  58. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +176 -0
  59. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -0
  60. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +435 -0
  61. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts +12 -0
  62. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts.map +1 -0
  63. package/src/engine/physics/cloth/collider/ClothColliderKind.js +38 -0
  64. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts +120 -0
  65. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts.map +1 -0
  66. package/src/engine/physics/cloth/collider/ClothColliderRecord.js +137 -0
  67. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts +25 -0
  68. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -0
  69. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +190 -0
  70. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +44 -0
  71. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -0
  72. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +173 -0
  73. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +94 -0
  74. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -0
  75. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +275 -0
  76. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts +126 -0
  77. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts.map +1 -0
  78. package/src/engine/physics/cloth/ecs/ClothCollider.js +199 -0
  79. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +9 -0
  80. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts.map +1 -0
  81. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +32 -0
  82. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +114 -0
  83. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -0
  84. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +243 -0
  85. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +66 -57
  86. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +109 -1
  87. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  88. package/src/engine/physics/cloth/ecs/ClothInstance.js +479 -363
  89. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +95 -0
  90. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -0
  91. package/src/engine/physics/cloth/ecs/ClothRig.js +140 -0
  92. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +30 -1
  93. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  94. package/src/engine/physics/cloth/ecs/ClothSystem.js +1021 -773
  95. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +90 -0
  96. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -0
  97. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +374 -0
  98. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts +32 -3
  99. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.js +283 -254
  101. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +59 -0
  102. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -0
  103. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +328 -0
  104. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +13 -0
  105. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -0
  106. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +288 -0
  107. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +58 -0
  108. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -0
  109. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +199 -0
  110. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +8 -63
  111. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  112. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +317 -645
  113. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +61 -0
  114. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  115. package/src/engine/physics/cloth/ecs/cloth_write_back.js +212 -449
  116. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts +49 -0
  117. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -0
  118. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +115 -0
  119. package/src/engine/physics/cloth/playground/README.md +155 -1
  120. package/src/engine/physics/cloth/playground/collide.html +178 -0
  121. package/src/engine/physics/cloth/playground/collide_build.d.ts +95 -0
  122. package/src/engine/physics/cloth/playground/collide_build.d.ts.map +1 -0
  123. package/src/engine/physics/cloth/playground/collide_build.js +315 -0
  124. package/src/engine/physics/cloth/playground/collide_main.d.ts +2 -0
  125. package/src/engine/physics/cloth/playground/collide_main.d.ts.map +1 -0
  126. package/src/engine/physics/cloth/playground/collide_main.js +720 -0
  127. package/src/engine/physics/cloth/playground/garment.html +182 -0
  128. package/src/engine/physics/cloth/playground/garment_build.d.ts +78 -0
  129. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -0
  130. package/src/engine/physics/cloth/playground/garment_build.js +359 -0
  131. package/src/engine/physics/cloth/playground/garment_main.d.ts +2 -0
  132. package/src/engine/physics/cloth/playground/garment_main.d.ts.map +1 -0
  133. package/src/engine/physics/cloth/playground/garment_main.js +633 -0
  134. package/src/engine/physics/cloth/solver/ClothState.d.ts +208 -5
  135. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  136. package/src/engine/physics/cloth/solver/ClothState.js +302 -8
  137. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +87 -0
  138. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -0
  139. package/src/engine/physics/cloth/solver/cloth_contact_find.js +343 -0
  140. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +112 -0
  141. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -0
  142. package/src/engine/physics/cloth/solver/cloth_self_find.js +448 -0
  143. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts +4 -1
  144. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
  145. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +16 -1
  146. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +112 -5
  147. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +117 -6
  149. package/src/engine/physics/cloth/solver/cloth_step.d.ts +40 -9
  150. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/solver/cloth_step.js +122 -10
  152. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +95 -0
  153. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -0
  154. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +285 -0
  155. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +129 -0
  156. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -0
  157. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +501 -0
  158. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +75 -0
  159. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -0
  160. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +202 -0
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/shade/playground/vgeo_viewer/README.md +18 -0
  163. package/src/shade/playground/vgeo_viewer/main.js +87 -50
  164. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  165. package/src/shade/renderer/buffer/table/GPUDatabase.js +191 -62
  166. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts +94 -2
  167. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  168. package/src/shade/renderer/buffer/table/GPUTypedTable.js +414 -2
  169. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts +14 -0
  170. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts.map +1 -0
  171. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.js +13 -0
  172. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts +17 -0
  173. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts.map +1 -0
  174. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.js +116 -0
  175. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +9 -4
  176. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  177. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +843 -734
  178. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +12 -0
  179. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
  180. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +13 -0
  181. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +17 -0
  182. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  183. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +185 -30
  184. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +17 -0
  185. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +141 -24
  186. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +204 -64
  187. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +110 -10
  188. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +19 -0
  189. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +19 -6
  190. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  191. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +26 -7
  192. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +173 -14
  193. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  194. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +458 -51
  195. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +49 -13
  196. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  197. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +52 -14
  198. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts +20 -0
  199. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts.map +1 -0
  200. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.js +19 -0
  201. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts +27 -0
  202. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts.map +1 -0
  203. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.js +48 -0
  204. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts +29 -0
  205. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts.map +1 -0
  206. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.js +60 -0
  207. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +8 -1
  208. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  209. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +32 -2
  210. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +258 -0
  211. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +1 -0
  212. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +723 -0
  213. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +49 -0
  214. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +1 -0
  215. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +50 -0
  216. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  217. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  218. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts +3 -0
  219. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts.map +1 -1
  220. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.js +121 -21
  221. package/src/shade/renderer/texture/virtual/README.md +6 -4
  222. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  223. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +7 -0
  224. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.d.ts +3 -3
  225. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +3 -3
  226. package/src/engine/ecs/system/SystemExecutionPhase.d.ts +0 -9
  227. package/src/engine/ecs/system/SystemExecutionPhase.d.ts.map +0 -1
  228. package/src/engine/graphics/texture/virtual/NOTES.md +0 -128
  229. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts +0 -6
  230. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts.map +0 -1
  231. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.js +0 -5
  232. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts +0 -49
  233. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts.map +0 -1
  234. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.js +0 -264
  235. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts +0 -44
  236. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts.map +0 -1
  237. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.js +0 -228
  238. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts +0 -3
  239. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts.map +0 -1
  240. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.js +0 -73
  241. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts +0 -14
  242. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts.map +0 -1
  243. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.js +0 -85
  244. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts +0 -12
  245. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts.map +0 -1
  246. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.js +0 -63
  247. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts +0 -12
  248. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts.map +0 -1
  249. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.js +0 -243
  250. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts +0 -30
  251. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts.map +0 -1
  252. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.js +0 -39
  253. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts +0 -9
  254. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts.map +0 -1
  255. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.js +0 -24
  256. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts +0 -9
  257. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts.map +0 -1
  258. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.js +0 -26
  259. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts +0 -11
  260. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts.map +0 -1
  261. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.js +0 -12
  262. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts +0 -7
  263. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts.map +0 -1
  264. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.js +0 -16
  265. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts +0 -7
  266. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts.map +0 -1
  267. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.js +0 -35
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Advanced 3D game engine",
7
7
  "type": "module",
8
8
  "author": "Alexander Goldring",
9
- "version": "3.22.0",
9
+ "version": "3.23.0",
10
10
  "exports": {
11
11
  "./build/*": "./build/*",
12
12
  "./src/*": "./src/*",
@@ -0,0 +1,118 @@
1
+ /**
2
+ * # A uniform hash grid over points, rebuilt whole
3
+ *
4
+ * Bucket every point by the cell of a uniform grid it falls in, so that "what is
5
+ * near this point" is a walk over a handful of buckets instead of a scan over
6
+ * everything. The classic particle broadphase, and the structure a cloth's
7
+ * self-collision needs (§9, §14.2).
8
+ *
9
+ * ## What it takes from `SpatialHashGrid`, and where it deliberately differs
10
+ *
11
+ * §14.2 asks for this "modelled on `core/geom/2d/hash-grid/SpatialHashGrid.js`",
12
+ * and it takes the idea — uniform cells, hashed into a fixed bucket table — and
13
+ * not the structure, because the two answer different questions.
14
+ *
15
+ * `SpatialHashGrid` is a **persistent index of boxes**: an element carries an
16
+ * AABB, spans several cells, is allocated and freed individually, and lives in a
17
+ * singly-linked list per cell so that moving one element touches only that
18
+ * element. That is right for a world index whose contents change a few at a time
19
+ * and wrong for this: a cloth's particles *all* move every step, so every link
20
+ * would be relinked, and the pointer chase through a linked list is the worst
21
+ * possible access pattern for a loop that is going to visit every bucket anyway.
22
+ *
23
+ * This is instead a **counting sort, rebuilt whole**: two passes over the points
24
+ * to count and scatter, and a bucket is then a contiguous run of point indices.
25
+ * Rebuilding is O(n) with no allocation after the first sizing, and the walk is
26
+ * sequential. A point is a point rather than a box, so it lands in exactly one
27
+ * cell and nothing is emitted twice.
28
+ *
29
+ * ## Hash collisions are the caller's problem, and that is the trade
30
+ *
31
+ * The bucket table is a power of two and cell coordinates are hashed into it, so
32
+ * two distant cells can share a bucket and a query can hand back a point that is
33
+ * nowhere near. **Every caller has to check the actual distance**, which is not a
34
+ * cost because every caller was going to: a broadphase answers "maybe", and the
35
+ * narrow phase is a subtraction and a dot product.
36
+ *
37
+ * What the hash buys is that the grid needs no extent. A dense grid over a
38
+ * garment's bounds would have to be resized whenever the garment moved or grew,
39
+ * and a garment that teleports a kilometre would size it into the gigabytes.
40
+ *
41
+ * What a caller does **not** have to handle is a point arriving twice.
42
+ * `SpatialHashGrid` documents duplicate emission as the caller's problem because
43
+ * its elements are boxes and a box genuinely occupies several cells; here a point
44
+ * occupies one, and the only way it could be emitted twice is the 27-cell walk
45
+ * visiting one bucket more than once because two of those cells collided into it.
46
+ * {@link forEachNear} skips a bucket it has already visited, which is a scan over
47
+ * at most 27 numbers and removes the whole class.
48
+ *
49
+ * @author Alex Goldring
50
+ * @copyright Company Named Limited (c) 2026
51
+ */
52
+ export class PointHashGrid3 {
53
+ /**
54
+ * Side of one cell. Points closer than this are in the same cell or an
55
+ * adjacent one, which is what makes {@link forEachNear}'s 27-cell walk the
56
+ * whole of the broadphase.
57
+ * @type {number}
58
+ */
59
+ cell_size: number;
60
+ /**
61
+ * Points in the grid.
62
+ * @type {number}
63
+ */
64
+ count: number;
65
+ /**
66
+ * Start of each bucket in {@link point}, `bucket_count + 1` entries. Bucket
67
+ * `b` is `point[offset[b] .. offset[b + 1])`.
68
+ *
69
+ * Public because the inner loop that motivated this class walks buckets
70
+ * directly rather than through {@link forEachNear}, and a private field with
71
+ * an accessor in front of it would put a call in that loop.
72
+ * @type {Int32Array}
73
+ */
74
+ offset: Int32Array;
75
+ /**
76
+ * Point indices, bucket-major.
77
+ * @type {Int32Array}
78
+ */
79
+ point: Int32Array;
80
+ /**
81
+ * How many buckets the table has. A power of two, so hashing is a mask.
82
+ * @returns {number}
83
+ */
84
+ get bucketCount(): number;
85
+ /**
86
+ * Rebuild the grid from a flat position array.
87
+ *
88
+ * @param {Float32Array|Float64Array} position 3 per point
89
+ * @param {number} count points
90
+ * @param {number} cell_size metres
91
+ * @returns {void}
92
+ */
93
+ build(position: Float32Array | Float64Array, count: number, cell_size: number): void;
94
+ /**
95
+ * Call `visit(index)` for every point in the 27 cells around `(x, y, z)`.
96
+ *
97
+ * Points from other cells may be handed back — see the class docblock on
98
+ * hash collisions — and the visitor is expected to check the distance.
99
+ *
100
+ * @param {number} x
101
+ * @param {number} y
102
+ * @param {number} z
103
+ * @param {function(number): void} visit
104
+ * @returns {void}
105
+ */
106
+ forEachNear(x: number, y: number, z: number, visit: (arg0: number) => void): void;
107
+ /**
108
+ * The bucket a cell falls in. For a caller walking buckets itself.
109
+ *
110
+ * @param {number} cx cell coordinate
111
+ * @param {number} cy
112
+ * @param {number} cz
113
+ * @returns {number}
114
+ */
115
+ bucketOf(cx: number, cy: number, cz: number): number;
116
+ #private;
117
+ }
118
+ //# sourceMappingURL=PointHashGrid3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PointHashGrid3.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/hash-grid/PointHashGrid3.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH;IAEI;;;;;OAKG;IACH,WAFU,MAAM,CAEF;IAEd;;;OAGG;IACH,OAFU,MAAM,CAEN;IAEV;;;;;;;;OAQG;IACH,QAFU,UAAU,CAEO;IAE3B;;;OAGG;IACH,OAFU,UAAU,CAEM;IAQ1B;;;OAGG;IACH,0BAEC;IAED;;;;;;;OAOG;IACH,gBALW,YAAY,GAAC,YAAY,SACzB,MAAM,aACN,MAAM,GACJ,IAAI,CA0EhB;IAED;;;;;;;;;;;OAWG;IACH,eANW,MAAM,KACN,MAAM,KACN,MAAM,gBACG,MAAM,KAAG,IAAI,GACpB,IAAI,CAiDhB;IAED;;;;;;;OAOG;IACH,aALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAIlB;;CACJ"}
@@ -0,0 +1,283 @@
1
+ import { assert } from "../../../assert.js";
2
+
3
+ /**
4
+ * # A uniform hash grid over points, rebuilt whole
5
+ *
6
+ * Bucket every point by the cell of a uniform grid it falls in, so that "what is
7
+ * near this point" is a walk over a handful of buckets instead of a scan over
8
+ * everything. The classic particle broadphase, and the structure a cloth's
9
+ * self-collision needs (§9, §14.2).
10
+ *
11
+ * ## What it takes from `SpatialHashGrid`, and where it deliberately differs
12
+ *
13
+ * §14.2 asks for this "modelled on `core/geom/2d/hash-grid/SpatialHashGrid.js`",
14
+ * and it takes the idea — uniform cells, hashed into a fixed bucket table — and
15
+ * not the structure, because the two answer different questions.
16
+ *
17
+ * `SpatialHashGrid` is a **persistent index of boxes**: an element carries an
18
+ * AABB, spans several cells, is allocated and freed individually, and lives in a
19
+ * singly-linked list per cell so that moving one element touches only that
20
+ * element. That is right for a world index whose contents change a few at a time
21
+ * and wrong for this: a cloth's particles *all* move every step, so every link
22
+ * would be relinked, and the pointer chase through a linked list is the worst
23
+ * possible access pattern for a loop that is going to visit every bucket anyway.
24
+ *
25
+ * This is instead a **counting sort, rebuilt whole**: two passes over the points
26
+ * to count and scatter, and a bucket is then a contiguous run of point indices.
27
+ * Rebuilding is O(n) with no allocation after the first sizing, and the walk is
28
+ * sequential. A point is a point rather than a box, so it lands in exactly one
29
+ * cell and nothing is emitted twice.
30
+ *
31
+ * ## Hash collisions are the caller's problem, and that is the trade
32
+ *
33
+ * The bucket table is a power of two and cell coordinates are hashed into it, so
34
+ * two distant cells can share a bucket and a query can hand back a point that is
35
+ * nowhere near. **Every caller has to check the actual distance**, which is not a
36
+ * cost because every caller was going to: a broadphase answers "maybe", and the
37
+ * narrow phase is a subtraction and a dot product.
38
+ *
39
+ * What the hash buys is that the grid needs no extent. A dense grid over a
40
+ * garment's bounds would have to be resized whenever the garment moved or grew,
41
+ * and a garment that teleports a kilometre would size it into the gigabytes.
42
+ *
43
+ * What a caller does **not** have to handle is a point arriving twice.
44
+ * `SpatialHashGrid` documents duplicate emission as the caller's problem because
45
+ * its elements are boxes and a box genuinely occupies several cells; here a point
46
+ * occupies one, and the only way it could be emitted twice is the 27-cell walk
47
+ * visiting one bucket more than once because two of those cells collided into it.
48
+ * {@link forEachNear} skips a bucket it has already visited, which is a scan over
49
+ * at most 27 numbers and removes the whole class.
50
+ *
51
+ * @author Alex Goldring
52
+ * @copyright Company Named Limited (c) 2026
53
+ */
54
+ export class PointHashGrid3 {
55
+
56
+ /**
57
+ * Side of one cell. Points closer than this are in the same cell or an
58
+ * adjacent one, which is what makes {@link forEachNear}'s 27-cell walk the
59
+ * whole of the broadphase.
60
+ * @type {number}
61
+ */
62
+ cell_size = 1;
63
+
64
+ /**
65
+ * Points in the grid.
66
+ * @type {number}
67
+ */
68
+ count = 0;
69
+
70
+ /**
71
+ * Start of each bucket in {@link point}, `bucket_count + 1` entries. Bucket
72
+ * `b` is `point[offset[b] .. offset[b + 1])`.
73
+ *
74
+ * Public because the inner loop that motivated this class walks buckets
75
+ * directly rather than through {@link forEachNear}, and a private field with
76
+ * an accessor in front of it would put a call in that loop.
77
+ * @type {Int32Array}
78
+ */
79
+ offset = new Int32Array(1);
80
+
81
+ /**
82
+ * Point indices, bucket-major.
83
+ * @type {Int32Array}
84
+ */
85
+ point = new Int32Array(0);
86
+
87
+ /**
88
+ * @type {number}
89
+ * @private
90
+ */
91
+ #bucket_count = 0;
92
+
93
+ /**
94
+ * How many buckets the table has. A power of two, so hashing is a mask.
95
+ * @returns {number}
96
+ */
97
+ get bucketCount() {
98
+ return this.#bucket_count;
99
+ }
100
+
101
+ /**
102
+ * Rebuild the grid from a flat position array.
103
+ *
104
+ * @param {Float32Array|Float64Array} position 3 per point
105
+ * @param {number} count points
106
+ * @param {number} cell_size metres
107
+ * @returns {void}
108
+ */
109
+ build(position, count, cell_size) {
110
+ assert.isFinite(cell_size, 'cell_size');
111
+ assert.greaterThan(cell_size, 0, 'cell_size');
112
+
113
+ this.cell_size = cell_size;
114
+ this.count = count;
115
+
116
+ // One bucket per point, rounded up to a power of two, so the mean
117
+ // occupancy is about one and the table is never a rounding error next to
118
+ // the points it indexes.
119
+ let buckets = 16;
120
+
121
+ while (buckets < count) {
122
+ buckets *= 2;
123
+ }
124
+
125
+ if (buckets !== this.#bucket_count) {
126
+ this.#bucket_count = buckets;
127
+ this.offset = new Int32Array(buckets + 1);
128
+ } else {
129
+ this.offset.fill(0);
130
+ }
131
+
132
+ if (this.point.length < count) {
133
+ this.point = new Int32Array(count);
134
+ }
135
+
136
+ const offset = this.offset;
137
+ const mask = buckets - 1;
138
+
139
+ const inverse = 1 / cell_size;
140
+
141
+ for (let i = 0; i < count; i++) {
142
+ const p = i * 3;
143
+
144
+ const bucket = hash(
145
+ Math.floor(position[p] * inverse),
146
+ Math.floor(position[p + 1] * inverse),
147
+ Math.floor(position[p + 2] * inverse)
148
+ ) & mask;
149
+
150
+ offset[bucket + 1]++;
151
+ }
152
+
153
+ for (let b = 0; b < buckets; b++) {
154
+ offset[b + 1] += offset[b];
155
+ }
156
+
157
+ // The scatter needs a moving cursor per bucket, and the offsets are the
158
+ // starting cursors — so the pass below consumes them and the loop after
159
+ // it puts them back rather than keeping a second array of the same size.
160
+ const point = this.point;
161
+
162
+ for (let i = 0; i < count; i++) {
163
+ const p = i * 3;
164
+
165
+ const bucket = hash(
166
+ Math.floor(position[p] * inverse),
167
+ Math.floor(position[p + 1] * inverse),
168
+ Math.floor(position[p + 2] * inverse)
169
+ ) & mask;
170
+
171
+ point[offset[bucket]++] = i;
172
+ }
173
+
174
+ // Undo the cursor advance: `offset[b]` ran up to `offset[b + 1]`, so
175
+ // shifting the array back down by one restores the starts.
176
+ for (let b = buckets; b > 0; b--) {
177
+ offset[b] = offset[b - 1];
178
+ }
179
+
180
+ offset[0] = 0;
181
+ }
182
+
183
+ /**
184
+ * Call `visit(index)` for every point in the 27 cells around `(x, y, z)`.
185
+ *
186
+ * Points from other cells may be handed back — see the class docblock on
187
+ * hash collisions — and the visitor is expected to check the distance.
188
+ *
189
+ * @param {number} x
190
+ * @param {number} y
191
+ * @param {number} z
192
+ * @param {function(number): void} visit
193
+ * @returns {void}
194
+ */
195
+ forEachNear(x, y, z, visit) {
196
+ const inverse = 1 / this.cell_size;
197
+
198
+ const cx = Math.floor(x * inverse);
199
+ const cy = Math.floor(y * inverse);
200
+ const cz = Math.floor(z * inverse);
201
+
202
+ const mask = this.#bucket_count - 1;
203
+
204
+ const offset = this.offset;
205
+ const point = this.point;
206
+
207
+ let visited = 0;
208
+
209
+ for (let dz = -1; dz <= 1; dz++) {
210
+ for (let dy = -1; dy <= 1; dy++) {
211
+ for (let dx = -1; dx <= 1; dx++) {
212
+ const bucket = hash(cx + dx, cy + dy, cz + dz) & mask;
213
+
214
+ // Two of the 27 cells can hash to one bucket — most easily on
215
+ // a small table, where there are fewer buckets than cells in
216
+ // the neighbourhood — and visiting it twice would hand every
217
+ // point in it back twice.
218
+ let seen = false;
219
+
220
+ for (let i = 0; i < visited; i++) {
221
+ if (VISITED[i] === bucket) {
222
+ seen = true;
223
+
224
+ break;
225
+ }
226
+ }
227
+
228
+ if (seen) {
229
+ continue;
230
+ }
231
+
232
+ VISITED[visited++] = bucket;
233
+
234
+ const end = offset[bucket + 1];
235
+
236
+ for (let at = offset[bucket]; at < end; at++) {
237
+ visit(point[at]);
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ /**
245
+ * The bucket a cell falls in. For a caller walking buckets itself.
246
+ *
247
+ * @param {number} cx cell coordinate
248
+ * @param {number} cy
249
+ * @param {number} cz
250
+ * @returns {number}
251
+ */
252
+ bucketOf(cx, cy, cz) {
253
+ return hash(cx, cy, cz) & (this.#bucket_count - 1);
254
+ }
255
+ }
256
+
257
+ /**
258
+ * The buckets one {@link PointHashGrid3#forEachNear} has already visited — at
259
+ * most 27, so a linear scan is the whole of the de-duplication. Module scratch
260
+ * because a query allocates nothing, and safe because a query does not nest: the
261
+ * visitor is called with a point index and has no reason to start another walk.
262
+ * @type {Int32Array}
263
+ * @private
264
+ */
265
+ const VISITED = new Int32Array(27);
266
+
267
+ /**
268
+ * Teschner's spatial hash — three large primes, one exclusive-or, which is the
269
+ * one every particle system in the literature uses because it is cheap and its
270
+ * collisions are uncorrelated with the lattice.
271
+ *
272
+ * `Math.imul` rather than `*` because the products overflow 32 bits and JavaScript
273
+ * would carry them into doubles, losing the low bits that are the hash.
274
+ *
275
+ * @param {number} x cell coordinate, integer
276
+ * @param {number} y
277
+ * @param {number} z
278
+ * @returns {number} a non-negative int32
279
+ * @private
280
+ */
281
+ function hash(x, y, z) {
282
+ return (Math.imul(x, 73856093) ^ Math.imul(y, 19349663) ^ Math.imul(z, 83492791)) >>> 0;
283
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"BoxShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/BoxShape3D.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;GAYG;AACH;IAQI;;;;;;OAMG;IACH,gBALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,UAAU,CAMtB;IAED;;;;;;;OAOG;IACH,wBALW,MAAM,UACN,MAAM,SACN,MAAM,GACJ,UAAU,CAItB;IA9BD;;;;OAIG;IACH,uBAFU,OAAO,CAEyB;IAqC1C,wCAIC;IAED,4DAQC;IAED,qGAKC;IAED,qCAaC;IAED,mEAEC;IAED,6CAaC;IAED,oCAQC;IAED,kFAOC;IAED;;;OAGG;IACH,cAHW,UAAU,GACR,OAAO,CAInB;IAWL;;;;;;OAMG;IACH,uBAFU,OAAO,CAEgB;CAThC;gCAtJ+B,sBAAsB;oBAVlC,kBAAkB"}
1
+ {"version":3,"file":"BoxShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/BoxShape3D.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;GAYG;AACH;IAQI;;;;;;OAMG;IACH,gBALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,UAAU,CAMtB;IAED;;;;;;;OAOG;IACH,wBALW,MAAM,UACN,MAAM,SACN,MAAM,GACJ,UAAU,CAItB;IA9BD;;;;OAIG;IACH,uBAFU,OAAO,CAEyB;IAqC1C,wCAIC;IAED,4DAQC;IAED,qGAKC;IAED,qCAaC;IAED,mEAIC;IAED,6CAIC;IAED,oCAQC;IAED,kFAOC;IAED;;;OAGG;IACH,cAHW,UAAU,GACR,OAAO,CAInB;IAWL;;;;;;OAMG;IACH,uBAFU,OAAO,CAEgB;CAThC;gCA/I+B,sBAAsB;oBANlC,kBAAkB"}
@@ -1,16 +1,12 @@
1
1
  import { hash_mix3 } from "../../../math/hash/hash_mix3.js";
2
2
  import Vector3 from "../../Vector3.js";
3
- import { max2 } from "../../../math/max2.js";
4
- import { max3 } from "../../../math/max3.js";
5
- import { min2 } from "../../../math/min2.js";
6
3
  import { sign_not_zero } from "../../../math/sign_not_zero.js";
7
4
  import { computeHashFloat } from "../../../primitives/numbers/computeHashFloat.js";
8
5
  import { random_point_in_box } from "../../random/random_point_in_box.js";
9
- import { v3_length } from "../../vec3/v3_length.js";
10
6
  import { aabb3_closest_point_on_surface } from "../aabb/aabb3_closest_point_on_surface.js";
11
7
  import { box3_raycast } from "../box/box3_raycast.js";
12
8
  import { AbstractShape3D } from "./AbstractShape3D.js";
13
- import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
9
+ import { sdf3_box, sdf3_box_gradient } from "./sdf/sdf3_box.js";
14
10
 
15
11
  /**
16
12
  * Axis-aligned box of arbitrary half-extents, expressed in the body's local
@@ -107,22 +103,15 @@ export class BoxShape3D extends AbstractShape3D {
107
103
  }
108
104
 
109
105
  signed_distance_gradient_at_point(result, point) {
110
- return compute_signed_distance_gradient_by_sampling(result, this, point);
106
+ const h = this.half_extents;
107
+
108
+ return sdf3_box_gradient(result, 0, point[0], point[1], point[2], h.x, h.y, h.z);
111
109
  }
112
110
 
113
111
  signed_distance_at_point(point) {
114
- // SDF of an axis-aligned box centred at origin. Same closed form as
115
- // UnitCubeShape3D but parametrised by half_extents.
116
112
  const h = this.half_extents;
117
- const q_x = Math.abs(point[0]) - h.x;
118
- const q_y = Math.abs(point[1]) - h.y;
119
- const q_z = Math.abs(point[2]) - h.z;
120
-
121
- return v3_length(
122
- max2(q_x, 0),
123
- max2(q_y, 0),
124
- max2(q_z, 0)
125
- ) + min2(max3(q_x, q_y, q_z), 0);
113
+
114
+ return sdf3_box(point[0], point[1], point[2], h.x, h.y, h.z);
126
115
  }
127
116
 
128
117
  contains_point(point) {
@@ -1 +1 @@
1
- {"version":3,"file":"CapsuleShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/CapsuleShape3D.js"],"names":[],"mappings":"AAcA;;;;GAIG;AACH;IAaI;;;;OAIG;IACH,oBAJW,MAAM,UACN,MAAM,GACJ,cAAc,CAa1B;IA5BD;;;OAGG;IACH,QAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,QAFU,MAAM,CAEL;IAoCX,wCAUC;IAED,qCAgBC;IAED,6CAaC;IAED,mEAEC;IAED,oCAcC;IAED,4DA+BC;IAED,qGAUC;IAED,kFA+BC;IAED;;;OAGG;IACH,cAHW,cAAc,GACZ,OAAO,CAMnB;IAUL;;;;;;;;;OASG;IACH,2BAFU,OAAO,CAEwB;CAZxC;gCAxN+B,sBAAsB"}
1
+ {"version":3,"file":"CapsuleShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/CapsuleShape3D.js"],"names":[],"mappings":"AAcA;;;;GAIG;AACH;IAaI;;;;OAIG;IACH,oBAJW,MAAM,UACN,MAAM,GACJ,cAAc,CAa1B;IA5BD;;;OAGG;IACH,QAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,QAFU,MAAM,CAEL;IAoCX,wCAUC;IAED,qCAgBC;IAED,6CAEC;IAED,mEAEC;IAED,oCAcC;IAED,4DA+BC;IAED,qGAUC;IAED,kFA+BC;IAED;;;OAGG;IACH,cAHW,cAAc,GACZ,OAAO,CAMnB;IAUL;;;;;;;;;OASG;IACH,2BAFU,OAAO,CAEwB;CAZxC;gCA7M+B,sBAAsB"}
@@ -8,7 +8,7 @@ import { random_point_in_sphere } from "../../random/random_point_in_sphere.js";
8
8
  import { v3_length } from "../../vec3/v3_length.js";
9
9
  import { capsule_raycast } from "../capsule/capsule_raycast.js";
10
10
  import { AbstractShape3D } from "./AbstractShape3D.js";
11
- import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
11
+ import { sdf3_capsule, sdf3_capsule_gradient } from "./sdf/sdf3_capsule.js";
12
12
 
13
13
  const scratch_v3 = [0, 0, 0];
14
14
 
@@ -95,22 +95,11 @@ export class CapsuleShape3D extends AbstractShape3D {
95
95
  }
96
96
 
97
97
  signed_distance_at_point(point) {
98
- const px = point[0];
99
- const py = point[1];
100
- const pz = point[2];
101
-
102
- const half_h = this.height / 2;
103
-
104
- // collapse Y onto the central segment
105
- const y_seg = clamp(py, -half_h, half_h);
106
-
107
- const dy = py - y_seg;
108
-
109
- return v3_length(px, dy, pz) - this.radius;
98
+ return sdf3_capsule(point[0], point[1], point[2], this.radius, this.height);
110
99
  }
111
100
 
112
101
  signed_distance_gradient_at_point(result, point) {
113
- return compute_signed_distance_gradient_by_sampling(result, this, point);
102
+ return sdf3_capsule_gradient(result, 0, point[0], point[1], point[2], this.radius, this.height);
114
103
  }
115
104
 
116
105
  contains_point(point) {
@@ -1 +1 @@
1
- {"version":3,"file":"CylinderShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/CylinderShape3D.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;GAaG;AACH;IAcI;;;;OAIG;IACH,oBAJW,MAAM,UACN,MAAM,GACJ,eAAe,CAa3B;IA7BD;;;OAGG;IACH,QAFU,MAAM,CAEH;IAEb;;;;OAIG;IACH,QAFU,MAAM,CAEL;IA+BX,qCAkBC;IAED,wCAUC;IAED,qGAqBC;IAED,6CAoBC;IAED,mEAEC;IAED,oCASC;IAED,4DA0CC;IAED,kFAOC;IAED;;;OAGG;IACH,cAHW,eAAe,GACb,OAAO,CAMnB;IAUL;;;;;;;OAOG;IACH,4BAFU,OAAO,CAE0B;CAV1C;gCAhO+B,sBAAsB"}
1
+ {"version":3,"file":"CylinderShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/CylinderShape3D.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;GAaG;AACH;IAcI;;;;OAIG;IACH,oBAJW,MAAM,UACN,MAAM,GACJ,eAAe,CAa3B;IA7BD;;;OAGG;IACH,QAFU,MAAM,CAEH;IAEb;;;;OAIG;IACH,QAFU,MAAM,CAEL;IA+BX,qCAkBC;IAED,wCAUC;IAED,qGAqBC;IAED,6CAEC;IAED,mEAEC;IAED,oCASC;IAED,4DA0CC;IAED,kFAOC;IAED;;;OAGG;IACH,cAHW,eAAe,GACb,OAAO,CAMnB;IAUL;;;;;;;OAOG;IACH,4BAFU,OAAO,CAE0B;CAV1C;gCA9M+B,sBAAsB"}
@@ -6,7 +6,7 @@ import { computeHashFloat } from "../../../primitives/numbers/computeHashFloat.j
6
6
  import { random_point_in_circle } from "../../random/random_point_in_circle.js";
7
7
  import { AbstractShape3D } from "./AbstractShape3D.js";
8
8
  import { cylinder3_raycast } from "../cylinder/cylinder3_raycast.js";
9
- import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
9
+ import { sdf3_cylinder, sdf3_cylinder_gradient } from "./sdf/sdf3_cylinder.js";
10
10
 
11
11
  const scratch_v3 = [0, 0, 0];
12
12
 
@@ -123,29 +123,11 @@ export class CylinderShape3D extends AbstractShape3D {
123
123
  }
124
124
 
125
125
  signed_distance_at_point(point) {
126
- const px = point[0];
127
- const py = point[1];
128
- const pz = point[2];
129
-
130
- const half_h = this.height / 2;
131
-
132
- // Inigo Quilez capped-cylinder SDF, axis = Y. `d_radial` / `d_axial` are
133
- // the signed distances outside the infinite cylinder and the slab.
134
- const d_radial = Math.sqrt(px * px + pz * pz) - this.radius;
135
- const d_axial = Math.abs(py) - half_h;
136
-
137
- const ext_r = d_radial > 0 ? d_radial : 0;
138
- const ext_a = d_axial > 0 ? d_axial : 0;
139
- const outside = Math.sqrt(ext_r * ext_r + ext_a * ext_a);
140
-
141
- const m = d_radial > d_axial ? d_radial : d_axial;
142
- const inside = m < 0 ? m : 0;
143
-
144
- return outside + inside;
126
+ return sdf3_cylinder(point[0], point[1], point[2], this.radius, this.height);
145
127
  }
146
128
 
147
129
  signed_distance_gradient_at_point(result, point) {
148
- return compute_signed_distance_gradient_by_sampling(result, this, point);
130
+ return sdf3_cylinder_gradient(result, 0, point[0], point[1], point[2], this.radius, this.height);
149
131
  }
150
132
 
151
133
  contains_point(point) {
@@ -0,0 +1,105 @@
1
+ /**
2
+ * # An infinite half-space
3
+ *
4
+ * The solid is `{ p : n·p − offset ≤ 0 }` — everything on the far side of the
5
+ * boundary plane from the direction {@link normal} points in. So `normal` is
6
+ * the **outward** surface normal, exactly as it is for every other shape's
7
+ * signed-distance gradient, and `offset` is how far along it the boundary sits
8
+ * from the body's local origin.
9
+ *
10
+ * A ground plane is `normal = (0, 1, 0), offset = 0`: solid below, open above.
11
+ *
12
+ * ## Why a shape rather than a very large box
13
+ *
14
+ * A box standing in for a ground plane has to be large enough that nothing ever
15
+ * reaches its edge and thin enough that nothing tunnels through it, and those
16
+ * two requirements pull against each other in `Float32`. It also costs a
17
+ * six-face field evaluation where the honest answer is one dot product, and its
18
+ * gradient has creases that the thing it is standing in for does not.
19
+ *
20
+ * ## What it deliberately does not implement, and why that is the honest answer
21
+ *
22
+ * A half-space is convex and **unbounded**, and three of
23
+ * {@link AbstractShape3D}'s methods are only meaningful on a bounded set:
24
+ *
25
+ * - {@link support} — GJK's operand. `argmax(p·d)` over a half-space is at
26
+ * infinity for all but one direction, so a plane is not a GJK operand and
27
+ * pretending otherwise with a large finite point would silently produce wrong
28
+ * contact manifolds rather than a loud failure. Left unimplemented, which
29
+ * makes the base class's `Not Implemented` the answer.
30
+ * - {@link sample_random_point_in_volume} — the base class's rejection sampler
31
+ * needs a finite bounding box. There is no uniform distribution on an
32
+ * infinite volume.
33
+ * - {@link volume} and {@link surface_area} — both `Infinity`, stated rather
34
+ * than thrown, because a caller summing volumes gets an answer that is true.
35
+ *
36
+ * {@link compute_bounding_box} **does** answer, with `±Infinity` on the
37
+ * unbounded axes. That is what the set is. A consumer that cannot hold an
38
+ * infinite AABB — a BVH leaf, a broadphase grid — must not be handed a plane,
39
+ * and the cloth collider index that motivated this shape derives a plane's
40
+ * bounds from its normal rather than by projecting this box (`aabb3_matrix4_project`
41
+ * would multiply an infinity by a zero matrix element and get `NaN`).
42
+ *
43
+ * @author Alex Goldring
44
+ * @copyright Company Named Limited (c) 2026
45
+ */
46
+ export class PlaneShape3D extends AbstractShape3D {
47
+ /**
48
+ * @param {number} normal_x
49
+ * @param {number} normal_y
50
+ * @param {number} normal_z
51
+ * @param {number} [offset]
52
+ * @returns {PlaneShape3D}
53
+ */
54
+ static from(normal_x: number, normal_y: number, normal_z: number, offset?: number): PlaneShape3D;
55
+ /**
56
+ * Outward unit normal, x.
57
+ * @type {number}
58
+ */
59
+ normal_x: number;
60
+ /**
61
+ * Outward unit normal, y.
62
+ * @type {number}
63
+ */
64
+ normal_y: number;
65
+ /**
66
+ * Outward unit normal, z.
67
+ * @type {number}
68
+ */
69
+ normal_z: number;
70
+ /**
71
+ * Distance from the local origin to the boundary plane, along
72
+ * {@link normal_x}/{@link normal_y}/{@link normal_z}.
73
+ * @type {number}
74
+ */
75
+ offset: number;
76
+ signed_distance_at_point(point: any): number;
77
+ signed_distance_gradient_at_point(result: any, point: any): number;
78
+ nearest_point_on_surface(result: any, reference: any): void;
79
+ contains_point(point: any): boolean;
80
+ /**
81
+ * Ray ↔ half-space, in the shape's local frame. A ray that starts inside
82
+ * the solid is already in contact and reports a hit at `t = 0` with the
83
+ * boundary normal, which is the convention every other shape here follows
84
+ * for an origin inside it.
85
+ *
86
+ * @param {Float32Array|number[]} hit
87
+ * @param {Ray3} ray
88
+ * @returns {boolean}
89
+ */
90
+ raycast(hit: Float32Array | number[], ray: Ray3): boolean;
91
+ equals(other: any): boolean;
92
+ /**
93
+ * Fast type-check marker, following {@link SphereShape3D#isSphereShape3D}. A
94
+ * consumer that cannot hold an unbounded shape tests this rather than reaching
95
+ * for `instanceof` across a module boundary.
96
+ * @readonly
97
+ * @type {boolean}
98
+ */
99
+ readonly isPlaneShape3D: boolean;
100
+ }
101
+ export namespace PlaneShape3D {
102
+ let GROUND: PlaneShape3D;
103
+ }
104
+ import { AbstractShape3D } from "./AbstractShape3D.js";
105
+ //# sourceMappingURL=PlaneShape3D.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaneShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/PlaneShape3D.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH;IA2BI;;;;;;OAMG;IACH,sBANW,MAAM,YACN,MAAM,YACN,MAAM,WACN,MAAM,GACJ,YAAY,CAyBxB;IAvDD;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;;OAIG;IACH,QAFU,MAAM,CAEL;IA0CX,6CAKC;IAED,mEAMC;IAED,4DAMC;IAED,oCAEC;IA4BD;;;;;;;;;OASG;IACH,aAJW,YAAY,GAAC,MAAM,EAAE,cAEnB,OAAO,CAkCnB;IAED,4BAMC;IAcL;;;;;;OAMG;IACH,yBAFU,OAAO,CAEoB;CATpC;;gBAcS,YAAY;;gCApPU,sBAAsB"}