@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
@@ -0,0 +1,251 @@
1
+ import { assert } from "../../../assert.js";
2
+ import { hash_mix2 } from "../../../math/hash/hash_mix2.js";
3
+ import { hash_mix3 } from "../../../math/hash/hash_mix3.js";
4
+ import { computeHashFloat } from "../../../primitives/numbers/computeHashFloat.js";
5
+ import { AbstractShape3D } from "./AbstractShape3D.js";
6
+ import { sdf3_plane, sdf3_plane_gradient } from "./sdf/sdf3_plane.js";
7
+
8
+ /**
9
+ * # An infinite half-space
10
+ *
11
+ * The solid is `{ p : n·p − offset ≤ 0 }` — everything on the far side of the
12
+ * boundary plane from the direction {@link normal} points in. So `normal` is
13
+ * the **outward** surface normal, exactly as it is for every other shape's
14
+ * signed-distance gradient, and `offset` is how far along it the boundary sits
15
+ * from the body's local origin.
16
+ *
17
+ * A ground plane is `normal = (0, 1, 0), offset = 0`: solid below, open above.
18
+ *
19
+ * ## Why a shape rather than a very large box
20
+ *
21
+ * A box standing in for a ground plane has to be large enough that nothing ever
22
+ * reaches its edge and thin enough that nothing tunnels through it, and those
23
+ * two requirements pull against each other in `Float32`. It also costs a
24
+ * six-face field evaluation where the honest answer is one dot product, and its
25
+ * gradient has creases that the thing it is standing in for does not.
26
+ *
27
+ * ## What it deliberately does not implement, and why that is the honest answer
28
+ *
29
+ * A half-space is convex and **unbounded**, and three of
30
+ * {@link AbstractShape3D}'s methods are only meaningful on a bounded set:
31
+ *
32
+ * - {@link support} — GJK's operand. `argmax(p·d)` over a half-space is at
33
+ * infinity for all but one direction, so a plane is not a GJK operand and
34
+ * pretending otherwise with a large finite point would silently produce wrong
35
+ * contact manifolds rather than a loud failure. Left unimplemented, which
36
+ * makes the base class's `Not Implemented` the answer.
37
+ * - {@link sample_random_point_in_volume} — the base class's rejection sampler
38
+ * needs a finite bounding box. There is no uniform distribution on an
39
+ * infinite volume.
40
+ * - {@link volume} and {@link surface_area} — both `Infinity`, stated rather
41
+ * than thrown, because a caller summing volumes gets an answer that is true.
42
+ *
43
+ * {@link compute_bounding_box} **does** answer, with `±Infinity` on the
44
+ * unbounded axes. That is what the set is. A consumer that cannot hold an
45
+ * infinite AABB — a BVH leaf, a broadphase grid — must not be handed a plane,
46
+ * and the cloth collider index that motivated this shape derives a plane's
47
+ * bounds from its normal rather than by projecting this box (`aabb3_matrix4_project`
48
+ * would multiply an infinity by a zero matrix element and get `NaN`).
49
+ *
50
+ * @author Alex Goldring
51
+ * @copyright Company Named Limited (c) 2026
52
+ */
53
+ export class PlaneShape3D extends AbstractShape3D {
54
+
55
+ /**
56
+ * Outward unit normal, x.
57
+ * @type {number}
58
+ */
59
+ normal_x = 0;
60
+
61
+ /**
62
+ * Outward unit normal, y.
63
+ * @type {number}
64
+ */
65
+ normal_y = 1;
66
+
67
+ /**
68
+ * Outward unit normal, z.
69
+ * @type {number}
70
+ */
71
+ normal_z = 0;
72
+
73
+ /**
74
+ * Distance from the local origin to the boundary plane, along
75
+ * {@link normal_x}/{@link normal_y}/{@link normal_z}.
76
+ * @type {number}
77
+ */
78
+ offset = 0;
79
+
80
+ /**
81
+ * @param {number} normal_x
82
+ * @param {number} normal_y
83
+ * @param {number} normal_z
84
+ * @param {number} [offset]
85
+ * @returns {PlaneShape3D}
86
+ */
87
+ static from(normal_x, normal_y, normal_z, offset = 0) {
88
+ assert.isNumber(normal_x, 'normal_x');
89
+ assert.isNumber(normal_y, 'normal_y');
90
+ assert.isNumber(normal_z, 'normal_z');
91
+ assert.isNumber(offset, 'offset');
92
+
93
+ const length = Math.sqrt(normal_x * normal_x + normal_y * normal_y + normal_z * normal_z);
94
+
95
+ assert.greaterThan(length, 0, 'plane normal length');
96
+
97
+ const r = new PlaneShape3D();
98
+
99
+ // Normalised on construction rather than trusted, because every method
100
+ // below reads the field as a *distance* field and an unnormalised
101
+ // normal makes all of them wrong by a scale rather than imprecise.
102
+ const inverse = 1 / length;
103
+
104
+ r.normal_x = normal_x * inverse;
105
+ r.normal_y = normal_y * inverse;
106
+ r.normal_z = normal_z * inverse;
107
+ r.offset = offset;
108
+
109
+ return r;
110
+ }
111
+
112
+ get volume() {
113
+ return Infinity;
114
+ }
115
+
116
+ get surface_area() {
117
+ return Infinity;
118
+ }
119
+
120
+ signed_distance_at_point(point) {
121
+ return sdf3_plane(
122
+ point[0], point[1], point[2],
123
+ this.normal_x, this.normal_y, this.normal_z, this.offset
124
+ );
125
+ }
126
+
127
+ signed_distance_gradient_at_point(result, point) {
128
+ return sdf3_plane_gradient(
129
+ result, 0,
130
+ point[0], point[1], point[2],
131
+ this.normal_x, this.normal_y, this.normal_z, this.offset
132
+ );
133
+ }
134
+
135
+ nearest_point_on_surface(result, reference) {
136
+ const distance = this.signed_distance_at_point(reference);
137
+
138
+ result[0] = reference[0] - this.normal_x * distance;
139
+ result[1] = reference[1] - this.normal_y * distance;
140
+ result[2] = reference[2] - this.normal_z * distance;
141
+ }
142
+
143
+ contains_point(point) {
144
+ return this.signed_distance_at_point(point) < 0;
145
+ }
146
+
147
+ /**
148
+ * The half-space's own bounds: finite on the one axis the normal is aligned
149
+ * with when it is axis-aligned, infinite everywhere else. See the class
150
+ * docblock for what a consumer is expected to do with that.
151
+ *
152
+ * @param {number[]|ArrayLike<number>|Float32Array|Float64Array} result
153
+ */
154
+ compute_bounding_box(result) {
155
+ result[0] = -Infinity;
156
+ result[1] = -Infinity;
157
+ result[2] = -Infinity;
158
+ result[3] = Infinity;
159
+ result[4] = Infinity;
160
+ result[5] = Infinity;
161
+
162
+ // A general normal makes every axis unbounded. An axis-aligned one — the
163
+ // overwhelmingly common case, and every ground plane — bounds exactly
164
+ // one of them, and saying so is what lets a caller cull against a floor.
165
+ if (this.normal_x === 1) { result[3] = this.offset; }
166
+ else if (this.normal_x === -1) { result[0] = -this.offset; }
167
+ else if (this.normal_y === 1) { result[4] = this.offset; }
168
+ else if (this.normal_y === -1) { result[1] = -this.offset; }
169
+ else if (this.normal_z === 1) { result[5] = this.offset; }
170
+ else if (this.normal_z === -1) { result[2] = -this.offset; }
171
+ }
172
+
173
+ /**
174
+ * Ray ↔ half-space, in the shape's local frame. A ray that starts inside
175
+ * the solid is already in contact and reports a hit at `t = 0` with the
176
+ * boundary normal, which is the convention every other shape here follows
177
+ * for an origin inside it.
178
+ *
179
+ * @param {Float32Array|number[]} hit
180
+ * @param {Ray3} ray
181
+ * @returns {boolean}
182
+ */
183
+ raycast(hit, ray) {
184
+ const nx = this.normal_x;
185
+ const ny = this.normal_y;
186
+ const nz = this.normal_z;
187
+
188
+ const distance = ray[0] * nx + ray[1] * ny + ray[2] * nz - this.offset;
189
+
190
+ const along = ray[3] * nx + ray[4] * ny + ray[5] * nz;
191
+
192
+ let t;
193
+
194
+ if (distance <= 0) {
195
+ t = 0;
196
+ } else if (along >= 0) {
197
+ // Outside and travelling away from — or exactly along — the plane.
198
+ return false;
199
+ } else {
200
+ t = -distance / along;
201
+
202
+ if (t > ray[6]) {
203
+ return false;
204
+ }
205
+ }
206
+
207
+ hit[0] = ray[0] + ray[3] * t;
208
+ hit[1] = ray[1] + ray[4] * t;
209
+ hit[2] = ray[2] + ray[5] * t;
210
+ hit[3] = nx;
211
+ hit[4] = ny;
212
+ hit[5] = nz;
213
+
214
+ return true;
215
+ }
216
+
217
+ equals(other) {
218
+ return super.equals(other)
219
+ && this.normal_x === other.normal_x
220
+ && this.normal_y === other.normal_y
221
+ && this.normal_z === other.normal_z
222
+ && this.offset === other.offset;
223
+ }
224
+
225
+ hash() {
226
+ return hash_mix2(
227
+ hash_mix3(
228
+ computeHashFloat(this.normal_x),
229
+ computeHashFloat(this.normal_y),
230
+ computeHashFloat(this.normal_z)
231
+ ),
232
+ computeHashFloat(this.offset)
233
+ );
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Fast type-check marker, following {@link SphereShape3D#isSphereShape3D}. A
239
+ * consumer that cannot hold an unbounded shape tests this rather than reaching
240
+ * for `instanceof` across a module boundary.
241
+ * @readonly
242
+ * @type {boolean}
243
+ */
244
+ PlaneShape3D.prototype.isPlaneShape3D = true;
245
+
246
+ /**
247
+ * The ground: solid below `y = 0`, open above it. Shared and immutable, in the
248
+ * same spirit as {@link UnitSphereShape3D}`.INSTANCE`.
249
+ * @type {PlaneShape3D}
250
+ */
251
+ PlaneShape3D.GROUND = PlaneShape3D.from(0, 1, 0, 0);
@@ -3,7 +3,7 @@ import { random_point_in_sphere } from "../../random/random_point_in_sphere.js";
3
3
  import { sphere_raycast } from "../sphere/sphere_raycast.js";
4
4
  import { v3_length } from "../../vec3/v3_length.js";
5
5
  import { AbstractShape3D } from "./AbstractShape3D.js";
6
- import { compute_signed_distance_gradient_by_sampling } from "./util/compute_signed_distance_gradient_by_sampling.js";
6
+ import { sdf3_sphere, sdf3_sphere_gradient } from "./sdf/sdf3_sphere.js";
7
7
 
8
8
  /**
9
9
  * Sphere of arbitrary `radius`, centred at the body's local origin.
@@ -98,11 +98,11 @@ export class SphereShape3D extends AbstractShape3D {
98
98
  }
99
99
 
100
100
  signed_distance_gradient_at_point(result, point) {
101
- return compute_signed_distance_gradient_by_sampling(result, this, point);
101
+ return sdf3_sphere_gradient(result, 0, point[0], point[1], point[2], this.radius);
102
102
  }
103
103
 
104
104
  signed_distance_at_point(point) {
105
- return v3_length(point[0], point[1], point[2]) - this.radius;
105
+ return sdf3_sphere(point[0], point[1], point[2], this.radius);
106
106
  }
107
107
 
108
108
  contains_point(point) {
@@ -1 +1 @@
1
- {"version":3,"file":"shape_to_type.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/shape_to_type.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,uDAFa,MAAM,CAoBlB"}
1
+ {"version":3,"file":"shape_to_type.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/shape_to_type.js"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,uDAFa,MAAM,CAsBlB"}
@@ -1,5 +1,6 @@
1
1
  import { CapsuleShape3D } from "../CapsuleShape3D.js";
2
2
  import { CylinderShape3D } from "../CylinderShape3D.js";
3
+ import { PlaneShape3D } from "../PlaneShape3D.js";
3
4
  import { SphereShape3D } from "../SphereShape3D.js";
4
5
  import { TransformedShape3D } from "../TransformedShape3D.js";
5
6
  import { UnionShape3D } from "../UnionShape3D.js";
@@ -25,6 +26,8 @@ export function shape_to_type(shape) {
25
26
  return 'capsule';
26
27
  } else if (shape instanceof CylinderShape3D) {
27
28
  return 'cylinder';
29
+ } else if (shape instanceof PlaneShape3D) {
30
+ return 'plane';
28
31
  } else {
29
32
  throw new Error('Unsupported shape');
30
33
  }
@@ -44,6 +44,19 @@ export namespace type_adapters {
44
44
  height: number;
45
45
  };
46
46
  }
47
+ namespace plane {
48
+ function read({ normal, offset }: {
49
+ normal: any;
50
+ offset: any;
51
+ }): PlaneShape3D;
52
+ /**
53
+ * @param {PlaneShape3D} object
54
+ */
55
+ function write(object: PlaneShape3D): {
56
+ normal: number[];
57
+ offset: number;
58
+ };
59
+ }
47
60
  namespace transform {
48
61
  function read({ transform, subject }: {
49
62
  transform: any;
@@ -75,6 +88,7 @@ import { UnitCubeShape3D } from "../UnitCubeShape3D.js";
75
88
  import { SphereShape3D } from "../SphereShape3D.js";
76
89
  import { CapsuleShape3D } from "../CapsuleShape3D.js";
77
90
  import { CylinderShape3D } from "../CylinderShape3D.js";
91
+ import { PlaneShape3D } from "../PlaneShape3D.js";
78
92
  import { TransformedShape3D } from "../TransformedShape3D.js";
79
93
  import { UnionShape3D } from "../UnionShape3D.js";
80
94
  //# sourceMappingURL=type_adapters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type_adapters.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/type_adapters.js"],"names":[],"mappings":";;QAYQ,iCAEC;QACD,qBAEC;;;QAGD;;0BAQC;QACD;;WAEG;QACH;;;;UAIC;;;QAGD;;;2BAEC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;;4BAEC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;;+BAIC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;yBAIC;QACD;;;WAGG;QACH;;UAIC;;;gCA9FuB,uBAAuB;8BAHzB,qBAAqB;+BAFpB,sBAAsB;gCACrB,uBAAuB;mCAEpB,0BAA0B;6BAChC,oBAAoB"}
1
+ {"version":3,"file":"type_adapters.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/json/type_adapters.js"],"names":[],"mappings":";;QAaQ,iCAEC;QACD,qBAEC;;;QAGD;;0BAQC;QACD;;WAEG;QACH;;;;UAIC;;;QAGD;;;2BAEC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;;4BAEC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;;yBAEC;QACD;;WAEG;QACH;;;UAKC;;;QAGD;;;+BAIC;QACD;;;WAGG;QACH;;;UAKC;;;QAGD;;yBAIC;QACD;;;WAGG;QACH;;UAIC;;;gCA5GuB,uBAAuB;8BAHzB,qBAAqB;+BAHpB,sBAAsB;gCACrB,uBAAuB;6BAC1B,oBAAoB;mCAEd,0BAA0B;6BAChC,oBAAoB"}
@@ -1,5 +1,6 @@
1
1
  import { CapsuleShape3D } from "../CapsuleShape3D.js";
2
2
  import { CylinderShape3D } from "../CylinderShape3D.js";
3
+ import { PlaneShape3D } from "../PlaneShape3D.js";
3
4
  import { SphereShape3D } from "../SphereShape3D.js";
4
5
  import { TransformedShape3D } from "../TransformedShape3D.js";
5
6
  import { UnionShape3D } from "../UnionShape3D.js";
@@ -66,6 +67,20 @@ export const type_adapters = {
66
67
  };
67
68
  }
68
69
  },
70
+ 'plane': {
71
+ read({ normal, offset }) {
72
+ return PlaneShape3D.from(normal[0], normal[1], normal[2], offset);
73
+ },
74
+ /**
75
+ * @param {PlaneShape3D} object
76
+ */
77
+ write(object) {
78
+ return {
79
+ normal: [object.normal_x, object.normal_y, object.normal_z],
80
+ offset: object.offset
81
+ };
82
+ }
83
+ },
69
84
  'transform': {
70
85
  read({ transform, subject }) {
71
86
  const subject_shape = shape_from_json(subject);
@@ -0,0 +1,51 @@
1
+ /**
2
+ * # Axis-aligned box — signed distance and its analytic gradient
3
+ *
4
+ * A box centred at the origin of its own frame, spanning `±half_extent` on each
5
+ * axis. Inigo Quilez's exact box field, with `q = |x| − h`:
6
+ *
7
+ * d(x) = ‖max(q, 0)‖ + min(max(qx, qy, qz), 0)
8
+ *
9
+ * The gradient has two regimes and that is the whole of the derivation:
10
+ *
11
+ * - **Outside** (some component of `q` is positive) the field is the distance
12
+ * to the nearest point on the box, so the gradient is the unit vector from
13
+ * that point — `sign(x) · max(q, 0)` normalised.
14
+ * - **Inside** (every component of `q` is negative) the field is
15
+ * `max(qx, qy, qz)`, a plain maximum, so the gradient is the signed unit axis
16
+ * of whichever component attains it — the nearest face.
17
+ *
18
+ * Inside a box the field is not differentiable on the medial surface, where two
19
+ * faces are equidistant. The maximum picks one, which is the standard answer
20
+ * and is what a caller wants: a consistent nearest face, not an average of two.
21
+ *
22
+ * @author Alex Goldring
23
+ * @copyright Company Named Limited (c) 2026
24
+ */
25
+ /**
26
+ * Signed distance from a point to a box's surface: negative inside.
27
+ *
28
+ * @param {number} x
29
+ * @param {number} y
30
+ * @param {number} z
31
+ * @param {number} half_x
32
+ * @param {number} half_y
33
+ * @param {number} half_z
34
+ * @returns {number}
35
+ */
36
+ export function sdf3_box(x: number, y: number, z: number, half_x: number, half_y: number, half_z: number): number;
37
+ /**
38
+ * Signed distance and the unit outward gradient, written to `out`.
39
+ *
40
+ * @param {Float32Array|Float64Array|number[]} out gradient destination
41
+ * @param {number} out_offset
42
+ * @param {number} x
43
+ * @param {number} y
44
+ * @param {number} z
45
+ * @param {number} half_x
46
+ * @param {number} half_y
47
+ * @param {number} half_z
48
+ * @returns {number} the signed distance
49
+ */
50
+ export function sdf3_box_gradient(out: Float32Array | Float64Array | number[], out_offset: number, x: number, y: number, z: number, half_x: number, half_y: number, half_z: number): number;
51
+ //# sourceMappingURL=sdf3_box.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdf3_box.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/sdf/sdf3_box.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;;;GAUG;AACH,4BARW,MAAM,KACN,MAAM,KACN,MAAM,UACN,MAAM,UACN,MAAM,UACN,MAAM,GACJ,MAAM,CAkBlB;AAED;;;;;;;;;;;;GAYG;AACH,uCAVW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,UACN,MAAM,UACN,MAAM,UACN,MAAM,GACJ,MAAM,CA6ClB"}
@@ -0,0 +1,113 @@
1
+ import { SDF3_EPSILON } from "./sdf3_degenerate_normal.js";
2
+
3
+ /**
4
+ * # Axis-aligned box — signed distance and its analytic gradient
5
+ *
6
+ * A box centred at the origin of its own frame, spanning `±half_extent` on each
7
+ * axis. Inigo Quilez's exact box field, with `q = |x| − h`:
8
+ *
9
+ * d(x) = ‖max(q, 0)‖ + min(max(qx, qy, qz), 0)
10
+ *
11
+ * The gradient has two regimes and that is the whole of the derivation:
12
+ *
13
+ * - **Outside** (some component of `q` is positive) the field is the distance
14
+ * to the nearest point on the box, so the gradient is the unit vector from
15
+ * that point — `sign(x) · max(q, 0)` normalised.
16
+ * - **Inside** (every component of `q` is negative) the field is
17
+ * `max(qx, qy, qz)`, a plain maximum, so the gradient is the signed unit axis
18
+ * of whichever component attains it — the nearest face.
19
+ *
20
+ * Inside a box the field is not differentiable on the medial surface, where two
21
+ * faces are equidistant. The maximum picks one, which is the standard answer
22
+ * and is what a caller wants: a consistent nearest face, not an average of two.
23
+ *
24
+ * @author Alex Goldring
25
+ * @copyright Company Named Limited (c) 2026
26
+ */
27
+
28
+ /**
29
+ * Signed distance from a point to a box's surface: negative inside.
30
+ *
31
+ * @param {number} x
32
+ * @param {number} y
33
+ * @param {number} z
34
+ * @param {number} half_x
35
+ * @param {number} half_y
36
+ * @param {number} half_z
37
+ * @returns {number}
38
+ */
39
+ export function sdf3_box(x, y, z, half_x, half_y, half_z) {
40
+ const qx = Math.abs(x) - half_x;
41
+ const qy = Math.abs(y) - half_y;
42
+ const qz = Math.abs(z) - half_z;
43
+
44
+ const ex = qx > 0 ? qx : 0;
45
+ const ey = qy > 0 ? qy : 0;
46
+ const ez = qz > 0 ? qz : 0;
47
+
48
+ let inner = qx > qy ? qx : qy;
49
+
50
+ if (qz > inner) {
51
+ inner = qz;
52
+ }
53
+
54
+ return Math.sqrt(ex * ex + ey * ey + ez * ez) + (inner < 0 ? inner : 0);
55
+ }
56
+
57
+ /**
58
+ * Signed distance and the unit outward gradient, written to `out`.
59
+ *
60
+ * @param {Float32Array|Float64Array|number[]} out gradient destination
61
+ * @param {number} out_offset
62
+ * @param {number} x
63
+ * @param {number} y
64
+ * @param {number} z
65
+ * @param {number} half_x
66
+ * @param {number} half_y
67
+ * @param {number} half_z
68
+ * @returns {number} the signed distance
69
+ */
70
+ export function sdf3_box_gradient(out, out_offset, x, y, z, half_x, half_y, half_z) {
71
+ const qx = Math.abs(x) - half_x;
72
+ const qy = Math.abs(y) - half_y;
73
+ const qz = Math.abs(z) - half_z;
74
+
75
+ const ex = qx > 0 ? qx : 0;
76
+ const ey = qy > 0 ? qy : 0;
77
+ const ez = qz > 0 ? qz : 0;
78
+
79
+ const outside = Math.sqrt(ex * ex + ey * ey + ez * ez);
80
+
81
+ if (outside > SDF3_EPSILON) {
82
+ const inverse = 1 / outside;
83
+
84
+ out[out_offset] = (x < 0 ? -ex : ex) * inverse;
85
+ out[out_offset + 1] = (y < 0 ? -ey : ey) * inverse;
86
+ out[out_offset + 2] = (z < 0 ? -ez : ez) * inverse;
87
+
88
+ return outside;
89
+ }
90
+
91
+ // Inside, or exactly on the surface. The field is `max(q)` and its gradient
92
+ // is the signed unit axis of the component that attains it — the nearest
93
+ // face, and the direction that leaves the box soonest.
94
+ out[out_offset] = 0;
95
+ out[out_offset + 1] = 0;
96
+ out[out_offset + 2] = 0;
97
+
98
+ if (qx >= qy && qx >= qz) {
99
+ out[out_offset] = x < 0 ? -1 : 1;
100
+
101
+ return qx;
102
+ }
103
+
104
+ if (qy >= qz) {
105
+ out[out_offset + 1] = y < 0 ? -1 : 1;
106
+
107
+ return qy;
108
+ }
109
+
110
+ out[out_offset + 2] = z < 0 ? -1 : 1;
111
+
112
+ return qz;
113
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * # Capsule — signed distance and its analytic gradient
3
+ *
4
+ * A capsule about the **Y axis** of its own frame: a segment of length
5
+ * `height` — so `±height/2` — swept by a sphere of `radius`. This is
6
+ * {@link CapsuleShape3D}'s parameterisation, and the total extent along Y is
7
+ * `height + 2·radius`.
8
+ *
9
+ * d(x) = ‖x − c(x)‖ − r, c(x) = (0, clamp(y, −h/2, +h/2), 0)
10
+ * ∇d(x) = (x − c(x))/‖x − c(x)‖
11
+ *
12
+ * The gradient is a sphere's gradient about the nearest point on the segment,
13
+ * which is the whole reason a capsule is cheap: collapsing Y onto the segment
14
+ * turns it into the sphere case, exactly once, with no branch on which cap.
15
+ *
16
+ * Degenerate on the segment itself, where the distance is zero and no direction
17
+ * is nearer than any other. See `sdf3_degenerate_normal.js`.
18
+ *
19
+ * @author Alex Goldring
20
+ * @copyright Company Named Limited (c) 2026
21
+ */
22
+ /**
23
+ * Signed distance from a point to a capsule's surface: negative inside.
24
+ *
25
+ * @param {number} x
26
+ * @param {number} y
27
+ * @param {number} z
28
+ * @param {number} radius
29
+ * @param {number} height length of the central segment — total extent is `height + 2·radius`
30
+ * @returns {number}
31
+ */
32
+ export function sdf3_capsule(x: number, y: number, z: number, radius: number, height: number): number;
33
+ /**
34
+ * Signed distance and the unit outward gradient, written to `out`.
35
+ *
36
+ * @param {Float32Array|Float64Array|number[]} out gradient destination
37
+ * @param {number} out_offset
38
+ * @param {number} x
39
+ * @param {number} y
40
+ * @param {number} z
41
+ * @param {number} radius
42
+ * @param {number} height
43
+ * @returns {number} the signed distance
44
+ */
45
+ export function sdf3_capsule_gradient(out: Float32Array | Float64Array | number[], out_offset: number, x: number, y: number, z: number, radius: number, height: number): number;
46
+ //# sourceMappingURL=sdf3_capsule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdf3_capsule.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/geom/3d/shape/sdf/sdf3_capsule.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;GASG;AACH,gCAPW,MAAM,KACN,MAAM,KACN,MAAM,UACN,MAAM,UACN,MAAM,GACJ,MAAM,CAQlB;AAED;;;;;;;;;;;GAWG;AACH,2CATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,UACN,MAAM,UACN,MAAM,GACJ,MAAM,CAwBlB"}
@@ -0,0 +1,82 @@
1
+ import {
2
+ SDF3_DEGENERATE_NORMAL_X,
3
+ SDF3_DEGENERATE_NORMAL_Y,
4
+ SDF3_DEGENERATE_NORMAL_Z,
5
+ SDF3_EPSILON
6
+ } from "./sdf3_degenerate_normal.js";
7
+
8
+ /**
9
+ * # Capsule — signed distance and its analytic gradient
10
+ *
11
+ * A capsule about the **Y axis** of its own frame: a segment of length
12
+ * `height` — so `±height/2` — swept by a sphere of `radius`. This is
13
+ * {@link CapsuleShape3D}'s parameterisation, and the total extent along Y is
14
+ * `height + 2·radius`.
15
+ *
16
+ * d(x) = ‖x − c(x)‖ − r, c(x) = (0, clamp(y, −h/2, +h/2), 0)
17
+ * ∇d(x) = (x − c(x))/‖x − c(x)‖
18
+ *
19
+ * The gradient is a sphere's gradient about the nearest point on the segment,
20
+ * which is the whole reason a capsule is cheap: collapsing Y onto the segment
21
+ * turns it into the sphere case, exactly once, with no branch on which cap.
22
+ *
23
+ * Degenerate on the segment itself, where the distance is zero and no direction
24
+ * is nearer than any other. See `sdf3_degenerate_normal.js`.
25
+ *
26
+ * @author Alex Goldring
27
+ * @copyright Company Named Limited (c) 2026
28
+ */
29
+
30
+ /**
31
+ * Signed distance from a point to a capsule's surface: negative inside.
32
+ *
33
+ * @param {number} x
34
+ * @param {number} y
35
+ * @param {number} z
36
+ * @param {number} radius
37
+ * @param {number} height length of the central segment — total extent is `height + 2·radius`
38
+ * @returns {number}
39
+ */
40
+ export function sdf3_capsule(x, y, z, radius, height) {
41
+ const half = height * 0.5;
42
+
43
+ const dy = y < -half ? y + half : (y > half ? y - half : 0);
44
+
45
+ return Math.sqrt(x * x + dy * dy + z * z) - radius;
46
+ }
47
+
48
+ /**
49
+ * Signed distance and the unit outward gradient, written to `out`.
50
+ *
51
+ * @param {Float32Array|Float64Array|number[]} out gradient destination
52
+ * @param {number} out_offset
53
+ * @param {number} x
54
+ * @param {number} y
55
+ * @param {number} z
56
+ * @param {number} radius
57
+ * @param {number} height
58
+ * @returns {number} the signed distance
59
+ */
60
+ export function sdf3_capsule_gradient(out, out_offset, x, y, z, radius, height) {
61
+ const half = height * 0.5;
62
+
63
+ const dy = y < -half ? y + half : (y > half ? y - half : 0);
64
+
65
+ const length = Math.sqrt(x * x + dy * dy + z * z);
66
+
67
+ if (length < SDF3_EPSILON) {
68
+ out[out_offset] = SDF3_DEGENERATE_NORMAL_X;
69
+ out[out_offset + 1] = SDF3_DEGENERATE_NORMAL_Y;
70
+ out[out_offset + 2] = SDF3_DEGENERATE_NORMAL_Z;
71
+
72
+ return -radius;
73
+ }
74
+
75
+ const inverse = 1 / length;
76
+
77
+ out[out_offset] = x * inverse;
78
+ out[out_offset + 1] = dy * inverse;
79
+ out[out_offset + 2] = z * inverse;
80
+
81
+ return length - radius;
82
+ }