@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
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebuild every particle's contact slots against the packed collider table.
|
|
3
|
+
*
|
|
4
|
+
* The table is expected to be posed at the **end** of the step —
|
|
5
|
+
* {@link cloth_collider_pose_at} at `t = 1` — because that is where the
|
|
6
|
+
* colliders will be when the last substep runs, and a contact discovered
|
|
7
|
+
* against where a collider *was* is a contact behind the thing it is meant to
|
|
8
|
+
* stop. This function poses it there itself, so the caller cannot get it wrong,
|
|
9
|
+
* and leaves it there for the first substep to overwrite.
|
|
10
|
+
*
|
|
11
|
+
* @param {ClothState} state
|
|
12
|
+
* @param {Float32Array|Float64Array} table packed colliders, cloth-local
|
|
13
|
+
* @param {Int32Array} keys index handle per record in `table`
|
|
14
|
+
* @param {number} count records in `table`
|
|
15
|
+
* @returns {number} how many contact rows were created
|
|
16
|
+
*/
|
|
17
|
+
export function cloth_contact_find(state: ClothState, table: Float32Array | Float64Array, keys: Int32Array, count: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* # Finding the contacts, once per step
|
|
20
|
+
*
|
|
21
|
+
* Which particles are in contact with which colliders is decided **once per
|
|
22
|
+
* fixed step**, not per substep and not per iteration, and that is a design
|
|
23
|
+
* commitment rather than an optimisation. Three things fall out of it:
|
|
24
|
+
*
|
|
25
|
+
* - **The step is deterministic.** The set is built by one pass in a fixed
|
|
26
|
+
* order over a fixed table, so the same inputs produce the same rows in the
|
|
27
|
+
* same order — which is what §12's bit-parity gate between the main thread
|
|
28
|
+
* and the worker is going to be held to.
|
|
29
|
+
* - **A multiplier has something to be warm-started against.** A row that
|
|
30
|
+
* appeared and vanished within a step would have no history to carry, and a
|
|
31
|
+
* contact whose multiplier starts at zero every iteration is a contact that
|
|
32
|
+
* never becomes hard.
|
|
33
|
+
* - **The cost is bounded and known.** One broadphase pass per particle per
|
|
34
|
+
* step, against a table that has already been narrowed to the colliders
|
|
35
|
+
* overlapping this cloth.
|
|
36
|
+
*
|
|
37
|
+
* ## Speculative contacts, and the collider's own travel
|
|
38
|
+
*
|
|
39
|
+
* A row is created while the particle is still {@link CLOTH_CONTACT_MARGIN}
|
|
40
|
+
* radii clear of the surface, and stays inactive — clamped out, costing a field
|
|
41
|
+
* evaluation and nothing else — until it is actually touching. That is what
|
|
42
|
+
* makes a contact decided once per step safe: a particle approaching at speed
|
|
43
|
+
* has a row waiting for it, rather than arriving inside a collider that nothing
|
|
44
|
+
* is watching. Without the margin the discovery pass would have to run per
|
|
45
|
+
* substep, which is the cost this structure exists to avoid.
|
|
46
|
+
*
|
|
47
|
+
* **The margin has to include how far the collider moved**, and M2 got this
|
|
48
|
+
* wrong before it got it right. Discovery evaluates the field at the end-of-step
|
|
49
|
+
* pose; a collider that crossed the cloth *within* the step is nowhere near it
|
|
50
|
+
* by then, so a fixed margin finds nothing and the swept poses of §8.2 have no
|
|
51
|
+
* rows to act through. Measured on a capsule driven through a hanging sheet: at
|
|
52
|
+
* 20 m/s the pass produced **zero contact rows**, and the sheet was untouched —
|
|
53
|
+
* not tunnelled through so much as never noticed. Adding the collider's travel
|
|
54
|
+
* to the reach costs one subtraction per record per step and makes the whole
|
|
55
|
+
* range from 2 to 40 m/s behave the same way. `MEASUREMENTS.md` §20.
|
|
56
|
+
*
|
|
57
|
+
* That is also the honest boundary of P3's "swept collision": the *set* is
|
|
58
|
+
* swept by this margin, and the *poses* are swept by `cloth_collider_pose_at`.
|
|
59
|
+
* Both are translation-first — a collider spinning fast enough that a point on
|
|
60
|
+
* its surface travels more than its own radius within one substep is still
|
|
61
|
+
* missed, and more substeps is the answer to that.
|
|
62
|
+
*
|
|
63
|
+
* ## Warm-starting across the rebuild
|
|
64
|
+
*
|
|
65
|
+
* Slots are keyed on the collider's **handle in the index**, which is stable
|
|
66
|
+
* across a rebuild in a way the record index in the per-cloth table is not — the
|
|
67
|
+
* table is whatever this step's broadphase returned, in whatever order. A slot
|
|
68
|
+
* whose key survives keeps its multipliers and its friction anchor; one that
|
|
69
|
+
* does not starts cold. A collider that leaves the index takes its contacts
|
|
70
|
+
* with it, which is correct: the surface the multiplier described is gone.
|
|
71
|
+
*
|
|
72
|
+
* @author Alex Goldring
|
|
73
|
+
* @copyright Company Named Limited (c) 2026
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
76
|
+
* How far clear of a surface a contact row is still created, as a multiple of
|
|
77
|
+
* the contact offset (`thickness + inflation`).
|
|
78
|
+
*
|
|
79
|
+
* One, so a row exists from twice the offset inwards. At a garment's 8 mm that
|
|
80
|
+
* is 8 mm of warning, which at 60 Hz covers half a metre a second of approach
|
|
81
|
+
* before a substep can carry a particle past the discovery — and a cloth moving
|
|
82
|
+
* faster than that relative to a collider is one the velocity clamp of §7 P1 is
|
|
83
|
+
* already the bound on.
|
|
84
|
+
* @type {number}
|
|
85
|
+
*/
|
|
86
|
+
export const CLOTH_CONTACT_MARGIN: number;
|
|
87
|
+
//# sourceMappingURL=cloth_contact_find.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_contact_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_contact_find.js"],"names":[],"mappings":"AA8FA;;;;;;;;;;;;;;;GAeG;AACH,6DALW,YAAY,GAAC,YAAY,QACzB,UAAU,SACV,MAAM,GACJ,MAAM,CA4KlB;AAjQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AAEH;;;;;;;;;;GAUG;AACH,mCAFU,MAAM,CAEsB"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CCR_AABB_MAX_X,
|
|
3
|
+
CCR_AABB_MAX_Y,
|
|
4
|
+
CCR_AABB_MAX_Z,
|
|
5
|
+
CCR_AABB_MIN_X,
|
|
6
|
+
CCR_AABB_MIN_Y,
|
|
7
|
+
CCR_AABB_MIN_Z,
|
|
8
|
+
CCR_INFLATION,
|
|
9
|
+
CCR_PREV_TX,
|
|
10
|
+
CCR_PREV_TY,
|
|
11
|
+
CCR_PREV_TZ,
|
|
12
|
+
CCR_STRIDE,
|
|
13
|
+
CCR_TX,
|
|
14
|
+
CCR_TY,
|
|
15
|
+
CCR_TZ
|
|
16
|
+
} from "../collider/ClothColliderRecord.js";
|
|
17
|
+
import {
|
|
18
|
+
cloth_collider_pose_at,
|
|
19
|
+
cloth_collider_signed_distance,
|
|
20
|
+
cloth_collider_to_local
|
|
21
|
+
} from "../collider/cloth_collider_sdf.js";
|
|
22
|
+
import { CLOTH_CONTACT_SLOTS } from "./constraint/cloth_contact_row.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* # Finding the contacts, once per step
|
|
26
|
+
*
|
|
27
|
+
* Which particles are in contact with which colliders is decided **once per
|
|
28
|
+
* fixed step**, not per substep and not per iteration, and that is a design
|
|
29
|
+
* commitment rather than an optimisation. Three things fall out of it:
|
|
30
|
+
*
|
|
31
|
+
* - **The step is deterministic.** The set is built by one pass in a fixed
|
|
32
|
+
* order over a fixed table, so the same inputs produce the same rows in the
|
|
33
|
+
* same order — which is what §12's bit-parity gate between the main thread
|
|
34
|
+
* and the worker is going to be held to.
|
|
35
|
+
* - **A multiplier has something to be warm-started against.** A row that
|
|
36
|
+
* appeared and vanished within a step would have no history to carry, and a
|
|
37
|
+
* contact whose multiplier starts at zero every iteration is a contact that
|
|
38
|
+
* never becomes hard.
|
|
39
|
+
* - **The cost is bounded and known.** One broadphase pass per particle per
|
|
40
|
+
* step, against a table that has already been narrowed to the colliders
|
|
41
|
+
* overlapping this cloth.
|
|
42
|
+
*
|
|
43
|
+
* ## Speculative contacts, and the collider's own travel
|
|
44
|
+
*
|
|
45
|
+
* A row is created while the particle is still {@link CLOTH_CONTACT_MARGIN}
|
|
46
|
+
* radii clear of the surface, and stays inactive — clamped out, costing a field
|
|
47
|
+
* evaluation and nothing else — until it is actually touching. That is what
|
|
48
|
+
* makes a contact decided once per step safe: a particle approaching at speed
|
|
49
|
+
* has a row waiting for it, rather than arriving inside a collider that nothing
|
|
50
|
+
* is watching. Without the margin the discovery pass would have to run per
|
|
51
|
+
* substep, which is the cost this structure exists to avoid.
|
|
52
|
+
*
|
|
53
|
+
* **The margin has to include how far the collider moved**, and M2 got this
|
|
54
|
+
* wrong before it got it right. Discovery evaluates the field at the end-of-step
|
|
55
|
+
* pose; a collider that crossed the cloth *within* the step is nowhere near it
|
|
56
|
+
* by then, so a fixed margin finds nothing and the swept poses of §8.2 have no
|
|
57
|
+
* rows to act through. Measured on a capsule driven through a hanging sheet: at
|
|
58
|
+
* 20 m/s the pass produced **zero contact rows**, and the sheet was untouched —
|
|
59
|
+
* not tunnelled through so much as never noticed. Adding the collider's travel
|
|
60
|
+
* to the reach costs one subtraction per record per step and makes the whole
|
|
61
|
+
* range from 2 to 40 m/s behave the same way. `MEASUREMENTS.md` §20.
|
|
62
|
+
*
|
|
63
|
+
* That is also the honest boundary of P3's "swept collision": the *set* is
|
|
64
|
+
* swept by this margin, and the *poses* are swept by `cloth_collider_pose_at`.
|
|
65
|
+
* Both are translation-first — a collider spinning fast enough that a point on
|
|
66
|
+
* its surface travels more than its own radius within one substep is still
|
|
67
|
+
* missed, and more substeps is the answer to that.
|
|
68
|
+
*
|
|
69
|
+
* ## Warm-starting across the rebuild
|
|
70
|
+
*
|
|
71
|
+
* Slots are keyed on the collider's **handle in the index**, which is stable
|
|
72
|
+
* across a rebuild in a way the record index in the per-cloth table is not — the
|
|
73
|
+
* table is whatever this step's broadphase returned, in whatever order. A slot
|
|
74
|
+
* whose key survives keeps its multipliers and its friction anchor; one that
|
|
75
|
+
* does not starts cold. A collider that leaves the index takes its contacts
|
|
76
|
+
* with it, which is correct: the surface the multiplier described is gone.
|
|
77
|
+
*
|
|
78
|
+
* @author Alex Goldring
|
|
79
|
+
* @copyright Company Named Limited (c) 2026
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* How far clear of a surface a contact row is still created, as a multiple of
|
|
84
|
+
* the contact offset (`thickness + inflation`).
|
|
85
|
+
*
|
|
86
|
+
* One, so a row exists from twice the offset inwards. At a garment's 8 mm that
|
|
87
|
+
* is 8 mm of warning, which at 60 Hz covers half a metre a second of approach
|
|
88
|
+
* before a substep can carry a particle past the discovery — and a cloth moving
|
|
89
|
+
* faster than that relative to a collider is one the velocity clamp of §7 P1 is
|
|
90
|
+
* already the bound on.
|
|
91
|
+
* @type {number}
|
|
92
|
+
*/
|
|
93
|
+
export const CLOTH_CONTACT_MARGIN = 1;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Rebuild every particle's contact slots against the packed collider table.
|
|
97
|
+
*
|
|
98
|
+
* The table is expected to be posed at the **end** of the step —
|
|
99
|
+
* {@link cloth_collider_pose_at} at `t = 1` — because that is where the
|
|
100
|
+
* colliders will be when the last substep runs, and a contact discovered
|
|
101
|
+
* against where a collider *was* is a contact behind the thing it is meant to
|
|
102
|
+
* stop. This function poses it there itself, so the caller cannot get it wrong,
|
|
103
|
+
* and leaves it there for the first substep to overwrite.
|
|
104
|
+
*
|
|
105
|
+
* @param {ClothState} state
|
|
106
|
+
* @param {Float32Array|Float64Array} table packed colliders, cloth-local
|
|
107
|
+
* @param {Int32Array} keys index handle per record in `table`
|
|
108
|
+
* @param {number} count records in `table`
|
|
109
|
+
* @returns {number} how many contact rows were created
|
|
110
|
+
*/
|
|
111
|
+
export function cloth_contact_find(state, table, keys, count) {
|
|
112
|
+
const particle_count = state.particle_count;
|
|
113
|
+
|
|
114
|
+
const collider = state.contact_collider;
|
|
115
|
+
const key = state.contact_key;
|
|
116
|
+
const lambda = state.contact_lambda;
|
|
117
|
+
const penalty = state.contact_penalty;
|
|
118
|
+
const friction_lambda = state.contact_friction_lambda;
|
|
119
|
+
const friction_penalty = state.contact_friction_penalty;
|
|
120
|
+
const anchor = state.contact_anchor;
|
|
121
|
+
|
|
122
|
+
const position = state.position;
|
|
123
|
+
const mass_inverse = state.mass_inverse;
|
|
124
|
+
|
|
125
|
+
const radius = state.contact_radius;
|
|
126
|
+
|
|
127
|
+
if (count > TRAVEL.length) {
|
|
128
|
+
TRAVEL = new Float64Array(count);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (count === 0) {
|
|
132
|
+
// Nothing to collide against. Clearing is still necessary — last step's
|
|
133
|
+
// slots name records in a table that no longer exists.
|
|
134
|
+
collider.fill(-1);
|
|
135
|
+
key.fill(-1);
|
|
136
|
+
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
cloth_collider_pose_at(table, count, 1);
|
|
141
|
+
|
|
142
|
+
// How far each collider moved this step. A particle within this of the
|
|
143
|
+
// end-of-step surface is one the collider could have crossed on the way,
|
|
144
|
+
// and it needs a row before the substeps replay that crossing.
|
|
145
|
+
for (let record = 0; record < count; record++) {
|
|
146
|
+
const r = record * CCR_STRIDE;
|
|
147
|
+
|
|
148
|
+
TRAVEL[record] = Math.hypot(
|
|
149
|
+
table[r + CCR_TX] - table[r + CCR_PREV_TX],
|
|
150
|
+
table[r + CCR_TY] - table[r + CCR_PREV_TY],
|
|
151
|
+
table[r + CCR_TZ] - table[r + CCR_PREV_TZ]
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let created = 0;
|
|
156
|
+
|
|
157
|
+
for (let particle = 0; particle < particle_count; particle++) {
|
|
158
|
+
const base = particle * CLOTH_CONTACT_SLOTS;
|
|
159
|
+
|
|
160
|
+
// Remember what this particle had, then clear. The carry-over is a
|
|
161
|
+
// linear scan over at most four entries, which is why the slot count is
|
|
162
|
+
// small enough to make a scan the right structure.
|
|
163
|
+
for (let s = 0; s < CLOTH_CONTACT_SLOTS; s++) {
|
|
164
|
+
const slot = base + s;
|
|
165
|
+
|
|
166
|
+
PREVIOUS_KEY[s] = key[slot];
|
|
167
|
+
PREVIOUS_LAMBDA[s] = lambda[slot];
|
|
168
|
+
PREVIOUS_PENALTY[s] = penalty[slot];
|
|
169
|
+
PREVIOUS_FRICTION_LAMBDA[s] = friction_lambda[slot];
|
|
170
|
+
PREVIOUS_FRICTION_PENALTY[s] = friction_penalty[slot];
|
|
171
|
+
PREVIOUS_ANCHOR[s * 3] = anchor[slot * 3];
|
|
172
|
+
PREVIOUS_ANCHOR[s * 3 + 1] = anchor[slot * 3 + 1];
|
|
173
|
+
PREVIOUS_ANCHOR[s * 3 + 2] = anchor[slot * 3 + 2];
|
|
174
|
+
|
|
175
|
+
collider[slot] = -1;
|
|
176
|
+
key[slot] = -1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (mass_inverse[particle] === 0) {
|
|
180
|
+
// A pinned particle cannot be pushed anywhere, so a contact on it
|
|
181
|
+
// would be a row that assembles a force and throws it away.
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const p = particle * 3;
|
|
186
|
+
|
|
187
|
+
const x = position[p];
|
|
188
|
+
const y = position[p + 1];
|
|
189
|
+
const z = position[p + 2];
|
|
190
|
+
|
|
191
|
+
let found = 0;
|
|
192
|
+
|
|
193
|
+
for (let record = 0; record < count; record++) {
|
|
194
|
+
const r = record * CCR_STRIDE;
|
|
195
|
+
|
|
196
|
+
const reach = (radius + table[r + CCR_INFLATION]) * (1 + CLOTH_CONTACT_MARGIN) + TRAVEL[record];
|
|
197
|
+
|
|
198
|
+
if (x + reach < table[r + CCR_AABB_MIN_X] || x - reach > table[r + CCR_AABB_MAX_X]) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (y + reach < table[r + CCR_AABB_MIN_Y] || y - reach > table[r + CCR_AABB_MAX_Y]) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (z + reach < table[r + CCR_AABB_MIN_Z] || z - reach > table[r + CCR_AABB_MAX_Z]) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const distance = cloth_collider_signed_distance(NORMAL, 0, table, record, x, y, z);
|
|
211
|
+
|
|
212
|
+
if (distance > reach) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Insert, nearest first, into a list of at most CLOTH_CONTACT_SLOTS.
|
|
217
|
+
// The ones that fall off the end are the furthest from binding.
|
|
218
|
+
let at = found < CLOTH_CONTACT_SLOTS ? found : CLOTH_CONTACT_SLOTS - 1;
|
|
219
|
+
|
|
220
|
+
if (found === CLOTH_CONTACT_SLOTS && distance >= CANDIDATE_DISTANCE[at]) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
while (at > 0 && CANDIDATE_DISTANCE[at - 1] > distance) {
|
|
225
|
+
CANDIDATE_DISTANCE[at] = CANDIDATE_DISTANCE[at - 1];
|
|
226
|
+
CANDIDATE_RECORD[at] = CANDIDATE_RECORD[at - 1];
|
|
227
|
+
|
|
228
|
+
at--;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
CANDIDATE_DISTANCE[at] = distance;
|
|
232
|
+
CANDIDATE_RECORD[at] = record;
|
|
233
|
+
|
|
234
|
+
if (found < CLOTH_CONTACT_SLOTS) {
|
|
235
|
+
found++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
for (let s = 0; s < found; s++) {
|
|
240
|
+
const slot = base + s;
|
|
241
|
+
|
|
242
|
+
const record = CANDIDATE_RECORD[s];
|
|
243
|
+
const handle = keys[record];
|
|
244
|
+
|
|
245
|
+
collider[slot] = record;
|
|
246
|
+
key[slot] = handle;
|
|
247
|
+
|
|
248
|
+
let carried = -1;
|
|
249
|
+
|
|
250
|
+
for (let q = 0; q < CLOTH_CONTACT_SLOTS; q++) {
|
|
251
|
+
if (PREVIOUS_KEY[q] === handle) {
|
|
252
|
+
carried = q;
|
|
253
|
+
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (carried >= 0) {
|
|
259
|
+
lambda[slot] = PREVIOUS_LAMBDA[carried];
|
|
260
|
+
penalty[slot] = PREVIOUS_PENALTY[carried];
|
|
261
|
+
friction_lambda[slot] = PREVIOUS_FRICTION_LAMBDA[carried];
|
|
262
|
+
friction_penalty[slot] = PREVIOUS_FRICTION_PENALTY[carried];
|
|
263
|
+
anchor[slot * 3] = PREVIOUS_ANCHOR[carried * 3];
|
|
264
|
+
anchor[slot * 3 + 1] = PREVIOUS_ANCHOR[carried * 3 + 1];
|
|
265
|
+
anchor[slot * 3 + 2] = PREVIOUS_ANCHOR[carried * 3 + 2];
|
|
266
|
+
} else {
|
|
267
|
+
lambda[slot] = 0;
|
|
268
|
+
penalty[slot] = 0;
|
|
269
|
+
friction_lambda[slot] = 0;
|
|
270
|
+
friction_penalty[slot] = 0;
|
|
271
|
+
|
|
272
|
+
// A new contact sticks where the particle is now.
|
|
273
|
+
cloth_collider_to_local(anchor, slot * 3, table, record, x, y, z);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
created++;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return created;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* How far each collider moved this step, in the frame the table is expressed
|
|
285
|
+
* in. Grown and never shrunk; only `[0, count)` is meaningful.
|
|
286
|
+
* @type {Float64Array}
|
|
287
|
+
* @private
|
|
288
|
+
*/
|
|
289
|
+
let TRAVEL = new Float64Array(0);
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @type {Float64Array}
|
|
293
|
+
* @private
|
|
294
|
+
*/
|
|
295
|
+
const NORMAL = new Float64Array(3);
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @type {Float64Array}
|
|
299
|
+
* @private
|
|
300
|
+
*/
|
|
301
|
+
const CANDIDATE_DISTANCE = new Float64Array(CLOTH_CONTACT_SLOTS);
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* @type {Int32Array}
|
|
305
|
+
* @private
|
|
306
|
+
*/
|
|
307
|
+
const CANDIDATE_RECORD = new Int32Array(CLOTH_CONTACT_SLOTS);
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* @type {Int32Array}
|
|
311
|
+
* @private
|
|
312
|
+
*/
|
|
313
|
+
const PREVIOUS_KEY = new Int32Array(CLOTH_CONTACT_SLOTS);
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* @type {Float32Array}
|
|
317
|
+
* @private
|
|
318
|
+
*/
|
|
319
|
+
const PREVIOUS_LAMBDA = new Float32Array(CLOTH_CONTACT_SLOTS);
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* @type {Float32Array}
|
|
323
|
+
* @private
|
|
324
|
+
*/
|
|
325
|
+
const PREVIOUS_PENALTY = new Float32Array(CLOTH_CONTACT_SLOTS);
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @type {Float32Array}
|
|
329
|
+
* @private
|
|
330
|
+
*/
|
|
331
|
+
const PREVIOUS_FRICTION_LAMBDA = new Float32Array(CLOTH_CONTACT_SLOTS);
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* @type {Float32Array}
|
|
335
|
+
* @private
|
|
336
|
+
*/
|
|
337
|
+
const PREVIOUS_FRICTION_PENALTY = new Float32Array(CLOTH_CONTACT_SLOTS);
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @type {Float32Array}
|
|
341
|
+
* @private
|
|
342
|
+
*/
|
|
343
|
+
const PREVIOUS_ANCHOR = new Float32Array(CLOTH_CONTACT_SLOTS * 3);
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the exclusion lists from a state's persistent rows.
|
|
3
|
+
*
|
|
4
|
+
* @param {ClothState} state
|
|
5
|
+
* @returns {{offset: Int32Array, partner: Int32Array}} CSR, sorted within each particle
|
|
6
|
+
*/
|
|
7
|
+
export function cloth_self_exclusions(state: ClothState): {
|
|
8
|
+
offset: Int32Array;
|
|
9
|
+
partner: Int32Array;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The closest two particles get **without a row between them**, in whatever pose
|
|
13
|
+
* the state is in.
|
|
14
|
+
|
|
15
|
+
* This is the length that decides how wide a self-collision row may be written,
|
|
16
|
+
* and it has to be measured rather than assumed. On a triangulated sheet it is
|
|
17
|
+
* two hops — one hop is a stretch row, the mesh diagonal is a stretch row, and
|
|
18
|
+
* the two vertices across a diagonal are a bend stencil — so it comes out at
|
|
19
|
+
* twice the shortest row and the analytic answer and this one agree.
|
|
20
|
+
*
|
|
21
|
+
* **A rigged garment is not a sheet and the two do not agree.** Its proxy is a
|
|
22
|
+
* set of *strips*, and nothing connects one strip to the next: every pair across
|
|
23
|
+
* the gap between two strips is ungoverned, at whatever distance the artist
|
|
24
|
+
* placed the joints. That distance has nothing to do with the link length along
|
|
25
|
+
* a strip, which is what `shortest_row` measures. On the playground's cape they
|
|
26
|
+
* differ by a factor of two — 8.5 cm across the gap against the 16 cm a sheet's
|
|
27
|
+
* topology would predict — and a ceiling derived from the link length instead of
|
|
28
|
+
* measured left the settled cape with three permanently active pairs.
|
|
29
|
+
* `MEASUREMENTS.md` §37.
|
|
30
|
+
*
|
|
31
|
+
* Pinned particles are skipped, exactly as {@link cloth_self_find} skips them,
|
|
32
|
+
* so this measures the pairs the row can actually act on and nothing else.
|
|
33
|
+
*
|
|
34
|
+
* @param {ClothState} state
|
|
35
|
+
* @param {{offset: Int32Array, partner: Int32Array}} exclusions from {@link cloth_self_exclusions}
|
|
36
|
+
* @param {number} search only pairs closer than this are looked for; the walk is
|
|
37
|
+
* bounded by it, and a proxy with nothing that close gets `Infinity` — which is
|
|
38
|
+
* the right answer, because then no radius inside the bound can touch anything
|
|
39
|
+
* @returns {number} metres, or `Infinity`
|
|
40
|
+
*/
|
|
41
|
+
export function cloth_self_closest_free_pair(state: ClothState, exclusions: {
|
|
42
|
+
offset: Int32Array;
|
|
43
|
+
partner: Int32Array;
|
|
44
|
+
}, search: number): number;
|
|
45
|
+
/**
|
|
46
|
+
* Rebuild the pair list.
|
|
47
|
+
*
|
|
48
|
+
* @param {ClothState} state pairs written into `self_pair`, count into `self_count`
|
|
49
|
+
* @param {{offset: Int32Array, partner: Int32Array}} exclusions from {@link cloth_self_exclusions}
|
|
50
|
+
* @returns {number} how many pairs were found
|
|
51
|
+
*/
|
|
52
|
+
export function cloth_self_find(state: ClothState, exclusions: {
|
|
53
|
+
offset: Int32Array;
|
|
54
|
+
partner: Int32Array;
|
|
55
|
+
}): number;
|
|
56
|
+
/**
|
|
57
|
+
* # Finding the self-collision pairs, once per step
|
|
58
|
+
*
|
|
59
|
+
* A uniform hash grid over the particles in the cloth's own frame, then for each
|
|
60
|
+
* particle the ones near it that are not already governed by a row. Rebuilt
|
|
61
|
+
* whole every step, exactly like the contact set (`cloth_contact_find.js`) and
|
|
62
|
+
* for the same reasons: one pass in a fixed order, so the step is deterministic.
|
|
63
|
+
*
|
|
64
|
+
* ## Adjacent pairs are excluded, and "adjacent" means "shares a row"
|
|
65
|
+
*
|
|
66
|
+
* §9: "Pairs sharing a triangle or an edge are excluded, since they are already
|
|
67
|
+
* governed by stretch and bend rows and would otherwise fight them." The exact
|
|
68
|
+
* form of that here is **sharing any row at all** — a stretch row, a bend
|
|
69
|
+
* stencil, or a chain's skip row, which is a stretch row too. Two particles a
|
|
70
|
+
* stretch row already holds at 5 cm do not also need a repulsion telling them to
|
|
71
|
+
* be 8 mm apart, and a bend stencil's four particles are a fold the bend row is
|
|
72
|
+
* the model of.
|
|
73
|
+
*
|
|
74
|
+
* The exclusion set is built **once, at seed**, from the row tables the state
|
|
75
|
+
* already carries: `cloth_self_exclusions` walks them and produces a sorted CSR
|
|
76
|
+
* list per particle. Testing a candidate is then a short scan over a handful of
|
|
77
|
+
* neighbours, which at typical garment topology is 16.8 entries a particle
|
|
78
|
+
* (`MEASUREMENTS.md` §8) — small enough that a scan beats a hash.
|
|
79
|
+
*
|
|
80
|
+
* ## The cell is the row's own diameter, and that fixes the neighbourhood
|
|
81
|
+
*
|
|
82
|
+
* Two particles interact when they are closer than `2·self_radius`, so a cell of
|
|
83
|
+
* exactly that makes the 27-cell walk necessary and sufficient. A larger cell
|
|
84
|
+
* would visit more candidates for nothing; a smaller one would need a wider
|
|
85
|
+
* walk, which is the same candidates through more buckets.
|
|
86
|
+
*
|
|
87
|
+
* **That radius is the proxy's resolution rather than the fabric's thickness**,
|
|
88
|
+
* and `ClothState#self_radius` carries why.
|
|
89
|
+
*
|
|
90
|
+
* @author Alex Goldring
|
|
91
|
+
* @copyright Company Named Limited (c) 2026
|
|
92
|
+
*/
|
|
93
|
+
/**
|
|
94
|
+
* Pairs one particle may **originate**, before the rest are dropped.
|
|
95
|
+
*
|
|
96
|
+
* A particle in a fold has a few neighbours across the fold and a few along it;
|
|
97
|
+
* eight is generous for a garment and is what bounds the pair list so a cloth
|
|
98
|
+
* that crumples into a ball cannot allocate its way out of a frame budget. A
|
|
99
|
+
* particle at the limit keeps the eight it found first in grid order, which is
|
|
100
|
+
* arbitrary among equals — and they are equals, because every one of them is
|
|
101
|
+
* inside the same radius.
|
|
102
|
+
*
|
|
103
|
+
* **"Originate", not "is in".** The search emits a pair once, from its lower
|
|
104
|
+
* index, so this caps how many pairs a particle starts and not how many it ends
|
|
105
|
+
* up in: a particle can be the *higher* index of any number of them. What the
|
|
106
|
+
* cap does bound exactly — and the only thing `ClothState` needs it to — is the
|
|
107
|
+
* length of the whole list, at this many per particle, because every pair is
|
|
108
|
+
* charged to exactly one of its two ends.
|
|
109
|
+
* @type {number}
|
|
110
|
+
*/
|
|
111
|
+
export const CLOTH_SELF_PAIRS_PER_PARTICLE: number;
|
|
112
|
+
//# sourceMappingURL=cloth_self_find.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_self_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_self_find.js"],"names":[],"mappings":"AA4DA;;;;;GAKG;AACH,0DAFa;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,CA0DrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,4EANW;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,UACzC,MAAM,GAGJ,MAAM,CAoHlB;AAED;;;;;;GAMG;AACH,+DAHW;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,GACvC,MAAM,CAyJlB;AA1aD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,4CAFU,MAAM,CAE+B"}
|