@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.
- package/package.json +1 -1
- package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts +118 -0
- package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts.map +1 -0
- package/src/core/geom/3d/hash-grid/PointHashGrid3.js +283 -0
- package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/BoxShape3D.js +6 -17
- package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CapsuleShape3D.js +3 -14
- package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/CylinderShape3D.js +3 -21
- package/src/core/geom/3d/shape/PlaneShape3D.d.ts +105 -0
- package/src/core/geom/3d/shape/PlaneShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/PlaneShape3D.js +251 -0
- package/src/core/geom/3d/shape/SphereShape3D.js +3 -3
- package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
- package/src/core/geom/3d/shape/json/shape_to_type.js +3 -0
- package/src/core/geom/3d/shape/json/type_adapters.d.ts +14 -0
- package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
- package/src/core/geom/3d/shape/json/type_adapters.js +15 -0
- package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts +51 -0
- package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts.map +1 -0
- package/src/core/geom/3d/shape/sdf/sdf3_box.js +113 -0
- package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts +46 -0
- package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts.map +1 -0
- package/src/core/geom/3d/shape/sdf/sdf3_capsule.js +82 -0
- package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts +60 -0
- package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts.map +1 -0
- package/src/core/geom/3d/shape/sdf/sdf3_cylinder.js +126 -0
- package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts +50 -0
- package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts.map +1 -0
- package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.js +53 -0
- package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts +52 -0
- package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts.map +1 -0
- package/src/core/geom/3d/shape/sdf/sdf3_plane.js +61 -0
- package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts +41 -0
- package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts.map +1 -0
- package/src/core/geom/3d/shape/sdf/sdf3_sphere.js +71 -0
- package/src/core/process/ConcurrencyGate.d.ts +103 -0
- package/src/core/process/ConcurrencyGate.d.ts.map +1 -0
- package/src/core/process/ConcurrencyGate.js +207 -0
- package/src/engine/asset/AssetManager.d.ts +10 -0
- package/src/engine/asset/AssetManager.d.ts.map +1 -1
- package/src/engine/asset/AssetManager.js +10 -0
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +30 -13
- package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +26 -0
- package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -0
- package/src/engine/graphics3/pose/collect_entity_playbacks.js +40 -0
- package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
- package/src/engine/graphics3/pose/query_entity_node_world_pose.js +74 -101
- package/src/engine/physics/cloth/MEASUREMENTS.md +1287 -4
- package/src/engine/physics/cloth/PLAN.md +1967 -1581
- package/src/engine/physics/cloth/build/ClothProxy.d.ts +147 -0
- package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -0
- package/src/engine/physics/cloth/build/ClothProxy.js +207 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +70 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +256 -0
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +176 -0
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -0
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +435 -0
- package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts +12 -0
- package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts.map +1 -0
- package/src/engine/physics/cloth/collider/ClothColliderKind.js +38 -0
- package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts +120 -0
- package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts.map +1 -0
- package/src/engine/physics/cloth/collider/ClothColliderRecord.js +137 -0
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts +25 -0
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -0
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +190 -0
- package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +44 -0
- package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -0
- package/src/engine/physics/cloth/collider/cloth_collider_pack.js +173 -0
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +94 -0
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -0
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +275 -0
- package/src/engine/physics/cloth/ecs/ClothCollider.d.ts +126 -0
- package/src/engine/physics/cloth/ecs/ClothCollider.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothCollider.js +199 -0
- package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +9 -0
- package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +32 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +114 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +243 -0
- package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +66 -57
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +109 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +479 -363
- package/src/engine/physics/cloth/ecs/ClothRig.d.ts +95 -0
- package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothRig.js +140 -0
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +30 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +1021 -773
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +90 -0
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +374 -0
- package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts +32 -3
- package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_library.js +283 -254
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +59 -0
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +328 -0
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +13 -0
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +288 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +58 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +199 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +8 -63
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +317 -645
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +61 -0
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +212 -449
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts +49 -0
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +115 -0
- package/src/engine/physics/cloth/playground/README.md +155 -1
- package/src/engine/physics/cloth/playground/collide.html +178 -0
- package/src/engine/physics/cloth/playground/collide_build.d.ts +95 -0
- package/src/engine/physics/cloth/playground/collide_build.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/collide_build.js +315 -0
- package/src/engine/physics/cloth/playground/collide_main.d.ts +2 -0
- package/src/engine/physics/cloth/playground/collide_main.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/collide_main.js +720 -0
- package/src/engine/physics/cloth/playground/garment.html +182 -0
- package/src/engine/physics/cloth/playground/garment_build.d.ts +78 -0
- package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/garment_build.js +359 -0
- package/src/engine/physics/cloth/playground/garment_main.d.ts +2 -0
- package/src/engine/physics/cloth/playground/garment_main.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/garment_main.js +633 -0
- package/src/engine/physics/cloth/solver/ClothState.d.ts +208 -5
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +302 -8
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +87 -0
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +343 -0
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +112 -0
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_self_find.js +448 -0
- package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts +4 -1
- package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +16 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +112 -5
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +117 -6
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +40 -9
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +122 -10
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +95 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +285 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +129 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +501 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +75 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +202 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/vgeo_viewer/README.md +18 -0
- package/src/shade/playground/vgeo_viewer/main.js +87 -50
- package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUDatabase.js +191 -62
- package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts +94 -2
- package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/GPUTypedTable.js +414 -2
- package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts +14 -0
- package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.js +13 -0
- package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts +17 -0
- package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts.map +1 -0
- package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.js +116 -0
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +9 -4
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +843 -734
- package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +12 -0
- package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
- package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +13 -0
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +17 -0
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +185 -30
- package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +17 -0
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +141 -24
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +204 -64
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +110 -10
- package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +19 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +19 -6
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +26 -7
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +173 -14
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +458 -51
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +49 -13
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +52 -14
- package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.js +19 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts +27 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.js +48 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts +29 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.js +60 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +8 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +32 -2
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +258 -0
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +723 -0
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +49 -0
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +50 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts +3 -0
- package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.js +121 -21
- package/src/shade/renderer/texture/virtual/README.md +6 -4
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
- package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +7 -0
- package/src/shade/renderer/texture/virtual/source/VTSourceTiled.d.ts +3 -3
- package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +3 -3
- package/src/engine/ecs/system/SystemExecutionPhase.d.ts +0 -9
- package/src/engine/ecs/system/SystemExecutionPhase.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/NOTES.md +0 -128
- package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts +0 -6
- package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.js +0 -5
- package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts +0 -49
- package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.js +0 -264
- package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts +0 -44
- package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/VirtualTextureUsage.js +0 -228
- package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts +0 -3
- package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.js +0 -73
- package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts +0 -14
- package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.js +0 -85
- package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts +0 -12
- package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/debug/UsageDebugView.js +0 -63
- package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts +0 -12
- package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.js +0 -243
- package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts +0 -30
- package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.js +0 -39
- package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts +0 -9
- package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/tile/compose_finger_print.js +0 -24
- package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts +0 -9
- package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/tile/compose_tile_address.js +0 -26
- package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts +0 -11
- package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.js +0 -12
- package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts +0 -7
- package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.js +0 -16
- package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts +0 -7
- package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts.map +0 -1
- package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.js +0 -35
package/package.json
CHANGED
|
@@ -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":"
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
118
|
-
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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,
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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"}
|