@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,501 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CCR_FEATURE,
|
|
3
|
+
CCR_FRICTION,
|
|
4
|
+
CCR_INFLATION,
|
|
5
|
+
CCR_STRIDE
|
|
6
|
+
} from "../../collider/ClothColliderRecord.js";
|
|
7
|
+
import {
|
|
8
|
+
cloth_collider_from_local,
|
|
9
|
+
cloth_collider_signed_distance,
|
|
10
|
+
cloth_collider_to_local
|
|
11
|
+
} from "../../collider/cloth_collider_sdf.js";
|
|
12
|
+
import {
|
|
13
|
+
CVA_F_X,
|
|
14
|
+
CVA_F_Y,
|
|
15
|
+
CVA_F_Z,
|
|
16
|
+
CVA_H_XX,
|
|
17
|
+
CVA_H_XY,
|
|
18
|
+
CVA_H_XZ,
|
|
19
|
+
CVA_H_YY,
|
|
20
|
+
CVA_H_YZ,
|
|
21
|
+
CVA_H_ZZ,
|
|
22
|
+
CVA_TRUST
|
|
23
|
+
} from "../cloth_vertex_accumulator.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* # Contact — the collision row and its friction row, which are one contact
|
|
27
|
+
*
|
|
28
|
+
* §6's table has them as two rows and they are, but they are two rows of the
|
|
29
|
+
* *same thing*: friction's clamp is the collision row's own force, so a module
|
|
30
|
+
* that carried only one of them would have to reach into the other, and a
|
|
31
|
+
* contact that carried its normal multiplier in one table and its tangential
|
|
32
|
+
* one in another would have to keep two lifetimes in step. One module, one pair
|
|
33
|
+
* of slots, one lifetime.
|
|
34
|
+
*
|
|
35
|
+
* collision C = (r + inflation) − sdf_c(x) [0, +∞) hard
|
|
36
|
+
* g = −∇sdf_c(x)
|
|
37
|
+
*
|
|
38
|
+
* friction C = ‖P_t(x − a)‖ [0, μ·f_n) hard
|
|
39
|
+
* g = P_t(x − a)/‖P_t(x − a)‖
|
|
40
|
+
*
|
|
41
|
+
* where `a` is where the particle stuck to the collider, carried in the
|
|
42
|
+
* collider's own frame, and `P_t = I − n nᵀ` projects onto the contact's
|
|
43
|
+
* tangent plane.
|
|
44
|
+
*
|
|
45
|
+
* ## The collision row is hard, which §6's table does not say
|
|
46
|
+
*
|
|
47
|
+
* §6 gives it a stiffness `k_contact` and friction a `k_friction`, and M0's own
|
|
48
|
+
* rule — "a row is **hard** exactly when its stiffness is `Infinity`" — makes
|
|
49
|
+
* that a statement that both are soft penalties. They cannot be. A soft row
|
|
50
|
+
* above about `8·(m/h²)` makes the step *add* energy (`MEASUREMENTS.md` §6),
|
|
51
|
+
* and a contact soft enough to stay under that boundary is a contact cloth
|
|
52
|
+
* sinks through: measured at 2.3 cm of penetration into a 25 cm sphere for a
|
|
53
|
+
* cape that is 4 mm thick. Both rows are therefore hard, with the multiplier
|
|
54
|
+
* carrying the load and the penalty living in the measured band — and that is
|
|
55
|
+
* also what finally gives `β` something to do, because these are the first rows
|
|
56
|
+
* in the system that arrive and leave. `MEASUREMENTS.md` §17.
|
|
57
|
+
*
|
|
58
|
+
* ## The friction clamp is one-sided because `C` is a magnitude
|
|
59
|
+
*
|
|
60
|
+
* §6 writes friction's clamps as `±μ·f_n`, which is the *signed-slip*
|
|
61
|
+
* formulation — a row whose `C` is a displacement along a chosen tangent. This
|
|
62
|
+
* one measures the magnitude of the slip in the tangent plane and points its
|
|
63
|
+
* gradient along it, so `C ≥ 0` always and the negative half of that clamp
|
|
64
|
+
* names a force that pulls the particle further from where it stuck. The row is
|
|
65
|
+
* `[0, μ·f_n]`, which is the same physics: static friction while the force it
|
|
66
|
+
* needs is under the cap, sliding at exactly the cap once it is not.
|
|
67
|
+
*
|
|
68
|
+
* Writing it as a magnitude is what removes the tangent basis. A signed row
|
|
69
|
+
* needs two of them, chosen per contact, and any choice that is continuous
|
|
70
|
+
* frame to frame is a choice with state in it — which is exactly what §7 P4(a)
|
|
71
|
+
* exists to keep out of this system.
|
|
72
|
+
*
|
|
73
|
+
* ## Which force the friction cap reads
|
|
74
|
+
*
|
|
75
|
+
* The *current iteration's* normal force, not the previous iteration's
|
|
76
|
+
* multiplier. VBD uses the multiplier, which is one iteration stale and
|
|
77
|
+
* therefore exactly zero on a contact's first iteration — so at the one
|
|
78
|
+
* iteration per substep §5.1 says the solver must be usable at, friction would
|
|
79
|
+
* never act at all. The current force is already computed, already
|
|
80
|
+
* non-negative, and makes a cloth land on a slope and stay there at 1×1.
|
|
81
|
+
*
|
|
82
|
+
* @author Alex Goldring
|
|
83
|
+
* @copyright Company Named Limited (c) 2026
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Contact rows per particle.
|
|
88
|
+
*
|
|
89
|
+
* Four, because a particle in a garment's worst corner — an armpit, between two
|
|
90
|
+
* fingers — is inside three or four collider bounds at once and inside more
|
|
91
|
+
* than that only when a rig has redundant colliders, where the fifth is a
|
|
92
|
+
* duplicate of one of the first four. Slots are filled nearest-first, so the
|
|
93
|
+
* ones dropped are the ones furthest from binding.
|
|
94
|
+
*
|
|
95
|
+
* It is a compile-time constant rather than a field because it is a stride: the
|
|
96
|
+
* accumulation is a counted loop over `CLOTH_CONTACT_SLOTS` adjacent entries,
|
|
97
|
+
* and a per-cloth capacity would put a load and a multiply in the inner loop to
|
|
98
|
+
* buy a garment nothing.
|
|
99
|
+
* @type {number}
|
|
100
|
+
*/
|
|
101
|
+
export const CLOTH_CONTACT_SLOTS = 4;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Below this a tangential slip is treated as zero and the friction row is
|
|
105
|
+
* skipped: `‖·‖` is not differentiable there, and a particle that has not moved
|
|
106
|
+
* relative to the surface has nothing for friction to resist.
|
|
107
|
+
* @type {number}
|
|
108
|
+
*/
|
|
109
|
+
export const CLOTH_FRICTION_EPSILON = 1e-7;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Add every contact touching `particle` into the vertex accumulator.
|
|
113
|
+
*
|
|
114
|
+
* @param {Float64Array} accumulator
|
|
115
|
+
* @param {ClothState} state
|
|
116
|
+
* @param {number} particle
|
|
117
|
+
* @param {Float32Array|Float64Array} table packed colliders, cloth-local, posed
|
|
118
|
+
* at the substep in progress
|
|
119
|
+
*/
|
|
120
|
+
export function cloth_contact_accumulate(accumulator, state, particle, table) {
|
|
121
|
+
const collider = state.contact_collider;
|
|
122
|
+
|
|
123
|
+
const base = particle * CLOTH_CONTACT_SLOTS;
|
|
124
|
+
|
|
125
|
+
const position = state.position;
|
|
126
|
+
|
|
127
|
+
const self = particle * 3;
|
|
128
|
+
|
|
129
|
+
const x = position[self];
|
|
130
|
+
const y = position[self + 1];
|
|
131
|
+
const z = position[self + 2];
|
|
132
|
+
|
|
133
|
+
const radius = state.contact_radius;
|
|
134
|
+
|
|
135
|
+
const lambda = state.contact_lambda;
|
|
136
|
+
const penalty = state.contact_penalty;
|
|
137
|
+
const friction_lambda = state.contact_friction_lambda;
|
|
138
|
+
const friction_penalty = state.contact_friction_penalty;
|
|
139
|
+
const anchor = state.contact_anchor;
|
|
140
|
+
|
|
141
|
+
let f_x = accumulator[CVA_F_X];
|
|
142
|
+
let f_y = accumulator[CVA_F_Y];
|
|
143
|
+
let f_z = accumulator[CVA_F_Z];
|
|
144
|
+
|
|
145
|
+
let h_xx = accumulator[CVA_H_XX];
|
|
146
|
+
let h_yy = accumulator[CVA_H_YY];
|
|
147
|
+
let h_zz = accumulator[CVA_H_ZZ];
|
|
148
|
+
let h_xy = accumulator[CVA_H_XY];
|
|
149
|
+
let h_xz = accumulator[CVA_H_XZ];
|
|
150
|
+
let h_yz = accumulator[CVA_H_YZ];
|
|
151
|
+
|
|
152
|
+
let trust = accumulator[CVA_TRUST];
|
|
153
|
+
|
|
154
|
+
for (let s = 0; s < CLOTH_CONTACT_SLOTS; s++) {
|
|
155
|
+
const slot = base + s;
|
|
156
|
+
|
|
157
|
+
const record = collider[slot];
|
|
158
|
+
|
|
159
|
+
if (record < 0) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const r = record * CCR_STRIDE;
|
|
164
|
+
|
|
165
|
+
const distance = cloth_collider_signed_distance(NORMAL, 0, table, record, x, y, z);
|
|
166
|
+
|
|
167
|
+
const offset = radius + table[r + CCR_INFLATION];
|
|
168
|
+
|
|
169
|
+
const k = penalty[slot];
|
|
170
|
+
|
|
171
|
+
const force = k * (offset - distance) + lambda[slot];
|
|
172
|
+
|
|
173
|
+
if (force <= 0) {
|
|
174
|
+
// Not touching, and carrying no accumulated force. The row is
|
|
175
|
+
// clamped out — and while it is, the friction anchor follows the
|
|
176
|
+
// particle, so that when it *does* touch it sticks where it landed
|
|
177
|
+
// rather than being dragged back to wherever it last was.
|
|
178
|
+
cloth_collider_to_local(anchor, slot * 3, table, record, x, y, z);
|
|
179
|
+
|
|
180
|
+
friction_lambda[slot] = 0;
|
|
181
|
+
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const nx = NORMAL[0];
|
|
186
|
+
const ny = NORMAL[1];
|
|
187
|
+
const nz = NORMAL[2];
|
|
188
|
+
|
|
189
|
+
// `g = −n`, so `f -= fc·g` is `f += fc·n` — out of the collider.
|
|
190
|
+
f_x += force * nx;
|
|
191
|
+
f_y += force * ny;
|
|
192
|
+
f_z += force * nz;
|
|
193
|
+
|
|
194
|
+
// The row is active whenever it is not clamped out, and the clamp is
|
|
195
|
+
// one-sided at zero, so reaching here *is* `fc == fu` and the penalty
|
|
196
|
+
// curvature always goes in.
|
|
197
|
+
h_xx += k * nx * nx;
|
|
198
|
+
h_yy += k * ny * ny;
|
|
199
|
+
h_zz += k * nz * nz;
|
|
200
|
+
h_xy += k * nx * ny;
|
|
201
|
+
h_xz += k * nx * nz;
|
|
202
|
+
h_yz += k * ny * nz;
|
|
203
|
+
|
|
204
|
+
// Geometric stiffness, and there is none to keep. For a convex
|
|
205
|
+
// primitive `∇²sdf` is positive semidefinite outside the shape, so
|
|
206
|
+
// `fc·∂²C/∂x² = −fc·∇²sdf` is *negative* semidefinite — the half §5.3
|
|
207
|
+
// drops. A distance row's geometric term is the opposite sign because
|
|
208
|
+
// its `C` is written the opposite way round, which is the same trap §6's
|
|
209
|
+
// clamp gloss set for M1.
|
|
210
|
+
|
|
211
|
+
// The trust region, from the collider rather than from a constant: a
|
|
212
|
+
// surface normal describes a surface over the surface's own curvature
|
|
213
|
+
// radius and no further.
|
|
214
|
+
const feature = table[r + CCR_FEATURE];
|
|
215
|
+
|
|
216
|
+
if (feature < trust) {
|
|
217
|
+
trust = feature;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const friction = table[r + CCR_FRICTION];
|
|
221
|
+
|
|
222
|
+
if (friction <= 0) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
cloth_collider_from_local(
|
|
227
|
+
ANCHOR_WORLD, 0, table, record,
|
|
228
|
+
anchor[slot * 3], anchor[slot * 3 + 1], anchor[slot * 3 + 2]
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
const dx = x - ANCHOR_WORLD[0];
|
|
232
|
+
const dy = y - ANCHOR_WORLD[1];
|
|
233
|
+
const dz = z - ANCHOR_WORLD[2];
|
|
234
|
+
|
|
235
|
+
const along = dx * nx + dy * ny + dz * nz;
|
|
236
|
+
|
|
237
|
+
const tx = dx - along * nx;
|
|
238
|
+
const ty = dy - along * ny;
|
|
239
|
+
const tz = dz - along * nz;
|
|
240
|
+
|
|
241
|
+
const slip = Math.sqrt(tx * tx + ty * ty + tz * tz);
|
|
242
|
+
|
|
243
|
+
if (slip < CLOTH_FRICTION_EPSILON) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const kf = friction_penalty[slot];
|
|
248
|
+
|
|
249
|
+
const unclamped = kf * slip + friction_lambda[slot];
|
|
250
|
+
|
|
251
|
+
const cap = friction * force;
|
|
252
|
+
|
|
253
|
+
const tangential = unclamped < cap ? unclamped : cap;
|
|
254
|
+
|
|
255
|
+
const inverse = 1 / slip;
|
|
256
|
+
|
|
257
|
+
const gx = tx * inverse;
|
|
258
|
+
const gy = ty * inverse;
|
|
259
|
+
const gz = tz * inverse;
|
|
260
|
+
|
|
261
|
+
f_x -= tangential * gx;
|
|
262
|
+
f_y -= tangential * gy;
|
|
263
|
+
f_z -= tangential * gz;
|
|
264
|
+
|
|
265
|
+
if (unclamped <= cap) {
|
|
266
|
+
h_xx += kf * gx * gx;
|
|
267
|
+
h_yy += kf * gy * gy;
|
|
268
|
+
h_zz += kf * gz * gz;
|
|
269
|
+
h_xy += kf * gx * gy;
|
|
270
|
+
h_xz += kf * gx * gz;
|
|
271
|
+
h_yz += kf * gy * gz;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Geometric stiffness, `(fc/L)·(P − g gᵀ)` with `P = I − n nᵀ`. `g` lies
|
|
275
|
+
// in the tangent plane, so `P − g gᵀ` is the rank-one projector onto the
|
|
276
|
+
// other tangent direction — positive semidefinite, and kept whether or
|
|
277
|
+
// not the row is clamped, because a saturated row still swings as the
|
|
278
|
+
// slip direction rotates.
|
|
279
|
+
const scale = tangential * inverse;
|
|
280
|
+
|
|
281
|
+
h_xx += scale * (1 - nx * nx - gx * gx);
|
|
282
|
+
h_yy += scale * (1 - ny * ny - gy * gy);
|
|
283
|
+
h_zz += scale * (1 - nz * nz - gz * gz);
|
|
284
|
+
h_xy -= scale * (nx * ny + gx * gy);
|
|
285
|
+
h_xz -= scale * (nx * nz + gx * gz);
|
|
286
|
+
h_yz -= scale * (ny * nz + gy * gz);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
accumulator[CVA_F_X] = f_x;
|
|
290
|
+
accumulator[CVA_F_Y] = f_y;
|
|
291
|
+
accumulator[CVA_F_Z] = f_z;
|
|
292
|
+
|
|
293
|
+
accumulator[CVA_H_XX] = h_xx;
|
|
294
|
+
accumulator[CVA_H_YY] = h_yy;
|
|
295
|
+
accumulator[CVA_H_ZZ] = h_zz;
|
|
296
|
+
accumulator[CVA_H_XY] = h_xy;
|
|
297
|
+
accumulator[CVA_H_XZ] = h_xz;
|
|
298
|
+
accumulator[CVA_H_YZ] = h_yz;
|
|
299
|
+
|
|
300
|
+
accumulator[CVA_TRUST] = trust;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Warm start every occupied contact slot for a substep.
|
|
305
|
+
*
|
|
306
|
+
* A contact is where `β` finally means something. M0 chose `k_min = k_max`,
|
|
307
|
+
* which disables the ramp, and measured that it was as good as any ramped
|
|
308
|
+
* alternative — for *persistent* rows, which is all M0 and M1 had. A contact
|
|
309
|
+
* arrives: on the first substep it exists, its penalty starts at `k_min` and
|
|
310
|
+
* climbs by `β·|C|` per iteration, so a cape meeting a shoulder is pushed out
|
|
311
|
+
* over a few iterations instead of being shot off it in one.
|
|
312
|
+
*
|
|
313
|
+
* @param {ClothState} state
|
|
314
|
+
* @param {number} alpha
|
|
315
|
+
* @param {number} gamma
|
|
316
|
+
* @param {number} k_min_ratio
|
|
317
|
+
* @param {number} k_max_ratio
|
|
318
|
+
* @param {number} inverse_h_squared
|
|
319
|
+
*/
|
|
320
|
+
export function cloth_contact_warm_start(state, alpha, gamma, k_min_ratio, k_max_ratio, inverse_h_squared) {
|
|
321
|
+
const particle_count = state.particle_count;
|
|
322
|
+
|
|
323
|
+
const collider = state.contact_collider;
|
|
324
|
+
const mass_inverse = state.mass_inverse;
|
|
325
|
+
const lambda = state.contact_lambda;
|
|
326
|
+
const penalty = state.contact_penalty;
|
|
327
|
+
const friction_lambda = state.contact_friction_lambda;
|
|
328
|
+
const friction_penalty = state.contact_friction_penalty;
|
|
329
|
+
|
|
330
|
+
const decay = alpha * gamma;
|
|
331
|
+
|
|
332
|
+
for (let particle = 0; particle < particle_count; particle++) {
|
|
333
|
+
const compliance = mass_inverse[particle];
|
|
334
|
+
|
|
335
|
+
if (compliance === 0) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const scale = inverse_h_squared / compliance;
|
|
340
|
+
|
|
341
|
+
const lo = k_min_ratio * scale;
|
|
342
|
+
const hi = k_max_ratio * scale;
|
|
343
|
+
|
|
344
|
+
const base = particle * CLOTH_CONTACT_SLOTS;
|
|
345
|
+
|
|
346
|
+
for (let s = 0; s < CLOTH_CONTACT_SLOTS; s++) {
|
|
347
|
+
const slot = base + s;
|
|
348
|
+
|
|
349
|
+
if (collider[slot] < 0) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
lambda[slot] *= decay;
|
|
354
|
+
friction_lambda[slot] *= decay;
|
|
355
|
+
|
|
356
|
+
penalty[slot] = clamp_band(penalty[slot] * gamma, lo, hi);
|
|
357
|
+
friction_penalty[slot] = clamp_band(friction_penalty[slot] * gamma, lo, hi);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Dual update for every occupied contact slot.
|
|
364
|
+
*
|
|
365
|
+
* The constraint is re-evaluated here rather than cached from the accumulation,
|
|
366
|
+
* for the same reason every other row kind re-evaluates: the accumulation's `C`
|
|
367
|
+
* is measured *before* the vertex update it feeds, and a multiplier absorbing a
|
|
368
|
+
* violation that has already been corrected is a multiplier that overshoots on
|
|
369
|
+
* the next iteration. It costs a second field evaluation per contact per
|
|
370
|
+
* iteration and it is what makes the multiplier converge within the step.
|
|
371
|
+
*
|
|
372
|
+
* @param {ClothState} state
|
|
373
|
+
* @param {Float32Array|Float64Array} table
|
|
374
|
+
* @param {number} beta
|
|
375
|
+
* @param {number} k_max_ratio
|
|
376
|
+
* @param {number} inverse_h_squared
|
|
377
|
+
*/
|
|
378
|
+
export function cloth_contact_dual_update(state, table, beta, k_max_ratio, inverse_h_squared) {
|
|
379
|
+
const particle_count = state.particle_count;
|
|
380
|
+
|
|
381
|
+
const collider = state.contact_collider;
|
|
382
|
+
const mass_inverse = state.mass_inverse;
|
|
383
|
+
const position = state.position;
|
|
384
|
+
const lambda = state.contact_lambda;
|
|
385
|
+
const penalty = state.contact_penalty;
|
|
386
|
+
const friction_lambda = state.contact_friction_lambda;
|
|
387
|
+
const friction_penalty = state.contact_friction_penalty;
|
|
388
|
+
const anchor = state.contact_anchor;
|
|
389
|
+
|
|
390
|
+
const radius = state.contact_radius;
|
|
391
|
+
|
|
392
|
+
for (let particle = 0; particle < particle_count; particle++) {
|
|
393
|
+
const compliance = mass_inverse[particle];
|
|
394
|
+
|
|
395
|
+
if (compliance === 0) {
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const base = particle * CLOTH_CONTACT_SLOTS;
|
|
400
|
+
|
|
401
|
+
const self = particle * 3;
|
|
402
|
+
|
|
403
|
+
const x = position[self];
|
|
404
|
+
const y = position[self + 1];
|
|
405
|
+
const z = position[self + 2];
|
|
406
|
+
|
|
407
|
+
const k_max = k_max_ratio * inverse_h_squared / compliance;
|
|
408
|
+
|
|
409
|
+
for (let s = 0; s < CLOTH_CONTACT_SLOTS; s++) {
|
|
410
|
+
const slot = base + s;
|
|
411
|
+
|
|
412
|
+
const record = collider[slot];
|
|
413
|
+
|
|
414
|
+
if (record < 0) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const r = record * CCR_STRIDE;
|
|
419
|
+
|
|
420
|
+
const distance = cloth_collider_signed_distance(NORMAL, 0, table, record, x, y, z);
|
|
421
|
+
|
|
422
|
+
const c = radius + table[r + CCR_INFLATION] - distance;
|
|
423
|
+
|
|
424
|
+
const k = penalty[slot];
|
|
425
|
+
|
|
426
|
+
const next = k * c + lambda[slot];
|
|
427
|
+
|
|
428
|
+
const normal_force = next > 0 ? next : 0;
|
|
429
|
+
|
|
430
|
+
lambda[slot] = normal_force;
|
|
431
|
+
|
|
432
|
+
const ramped = k + beta * Math.abs(c);
|
|
433
|
+
|
|
434
|
+
penalty[slot] = ramped < k_max ? ramped : k_max;
|
|
435
|
+
|
|
436
|
+
const friction = table[r + CCR_FRICTION];
|
|
437
|
+
|
|
438
|
+
if (friction <= 0 || normal_force <= 0) {
|
|
439
|
+
friction_lambda[slot] = 0;
|
|
440
|
+
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
cloth_collider_from_local(
|
|
445
|
+
ANCHOR_WORLD, 0, table, record,
|
|
446
|
+
anchor[slot * 3], anchor[slot * 3 + 1], anchor[slot * 3 + 2]
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
const dx = x - ANCHOR_WORLD[0];
|
|
450
|
+
const dy = y - ANCHOR_WORLD[1];
|
|
451
|
+
const dz = z - ANCHOR_WORLD[2];
|
|
452
|
+
|
|
453
|
+
const along = dx * NORMAL[0] + dy * NORMAL[1] + dz * NORMAL[2];
|
|
454
|
+
|
|
455
|
+
const tx = dx - along * NORMAL[0];
|
|
456
|
+
const ty = dy - along * NORMAL[1];
|
|
457
|
+
const tz = dz - along * NORMAL[2];
|
|
458
|
+
|
|
459
|
+
const slip = Math.sqrt(tx * tx + ty * ty + tz * tz);
|
|
460
|
+
|
|
461
|
+
const kf = friction_penalty[slot];
|
|
462
|
+
|
|
463
|
+
const cap = friction * normal_force;
|
|
464
|
+
|
|
465
|
+
const unclamped = kf * slip + friction_lambda[slot];
|
|
466
|
+
|
|
467
|
+
friction_lambda[slot] = unclamped < cap ? (unclamped > 0 ? unclamped : 0) : cap;
|
|
468
|
+
|
|
469
|
+
const ramped_friction = kf + beta * slip;
|
|
470
|
+
|
|
471
|
+
friction_penalty[slot] = ramped_friction < k_max ? ramped_friction : k_max;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* @param {number} value
|
|
478
|
+
* @param {number} lo
|
|
479
|
+
* @param {number} hi
|
|
480
|
+
* @returns {number}
|
|
481
|
+
* @private
|
|
482
|
+
*/
|
|
483
|
+
function clamp_band(value, lo, hi) {
|
|
484
|
+
if (value < lo) {
|
|
485
|
+
return lo;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return value > hi ? hi : value;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* @type {Float64Array}
|
|
493
|
+
* @private
|
|
494
|
+
*/
|
|
495
|
+
const NORMAL = new Float64Array(3);
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* @type {Float64Array}
|
|
499
|
+
* @private
|
|
500
|
+
*/
|
|
501
|
+
const ANCHOR_WORLD = new Float64Array(3);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebuild the per-particle Jacobi scratch from the pair list.
|
|
3
|
+
*
|
|
4
|
+
* Called once per iteration, before the colour sweep, from the positions the
|
|
5
|
+
* previous iteration left. Every pair contributes to both of its particles.
|
|
6
|
+
*
|
|
7
|
+
* @param {ClothState} state
|
|
8
|
+
* @param {number} stiffness penalty, N/m — the same for every pair, because
|
|
9
|
+
* every pair has the same two free ends and therefore the same inertial scale
|
|
10
|
+
* @returns {number} how many pairs were in contact
|
|
11
|
+
*/
|
|
12
|
+
export function cloth_self_accumulate_scratch(state: ClothState, stiffness: number): number;
|
|
13
|
+
/**
|
|
14
|
+
* Add one particle's share of the Jacobi scratch into its vertex accumulator.
|
|
15
|
+
*
|
|
16
|
+
* @param {Float64Array} accumulator
|
|
17
|
+
* @param {ClothState} state
|
|
18
|
+
* @param {number} particle
|
|
19
|
+
*/
|
|
20
|
+
export function cloth_self_accumulate(accumulator: Float64Array, state: ClothState, particle: number): void;
|
|
21
|
+
/**
|
|
22
|
+
* # Self-collision — the row that keeps cloth off itself
|
|
23
|
+
*
|
|
24
|
+
* C(x) = ‖x_i − x_j‖ − (r_i + r_j)
|
|
25
|
+
* ∂C/∂x_i = (x_i − x_j)/‖x_i − x_j‖ = n
|
|
26
|
+
* ∂C/∂x_j = −n
|
|
27
|
+
* clamp (−∞, 0]
|
|
28
|
+
*
|
|
29
|
+
* **That clamp is right and it is the one place in §6's table where the negative
|
|
30
|
+
* half is the live one.** The rule is that `[0, +∞)` admits only forces that
|
|
31
|
+
* *reduce* `C` and `(−∞, 0]` only forces that *increase* it; this row is violated
|
|
32
|
+
* when the two particles are closer than their radii, which is `C < 0`, so what
|
|
33
|
+
* it needs is `C` increased. Under the solver's `f -= fc·g`, a negative `fc`
|
|
34
|
+
* pushes `i` along `+n` and `j` along `−n` — apart. Every distance row above it
|
|
35
|
+
* in the table bounds a distance from *above* and therefore takes the other
|
|
36
|
+
* half; this one bounds from below.
|
|
37
|
+
*
|
|
38
|
+
* ## It is applied Jacobi-style, and this is where §5.4 was right
|
|
39
|
+
*
|
|
40
|
+
* A collider contact is unary and needs none of §5.4's machinery (`MEASUREMENTS.md`
|
|
41
|
+
* §18). A self-collision row is a **pair**, and pairs are exactly what the
|
|
42
|
+
* colouring cannot pre-partition: two particles of the same colour can be
|
|
43
|
+
* neighbours in space and would then both move against each other inside one
|
|
44
|
+
* sweep, in an order that depends on how the sweep was split. So the pairs are
|
|
45
|
+
* accumulated once per iteration into a per-particle `(f, H)` scratch, from the
|
|
46
|
+
* positions at the start of that iteration, and every vertex update adds its own
|
|
47
|
+
* entry. The result is a step that is the same whatever order the colours were
|
|
48
|
+
* swept in, which is what §12's bit-parity gate is going to be held to.
|
|
49
|
+
*
|
|
50
|
+
* ## The row is soft, which the collision row could not be
|
|
51
|
+
*
|
|
52
|
+
* `MEASUREMENTS.md` §18 measured that a collider contact cannot be a soft
|
|
53
|
+
* penalty: the force it has to produce is an *arrested impact*, 376 N for a
|
|
54
|
+
* sheet arriving at 8 m/s, against the 4.6 N a soft row inside M0's dissipative
|
|
55
|
+
* band can deliver at one thickness of penetration.
|
|
56
|
+
*
|
|
57
|
+
* A self-collision row carries nothing of the kind. What it holds apart is cloth
|
|
58
|
+
* against cloth — grams, moving at the speed cloth moves relative to itself — and
|
|
59
|
+
* a penalty at the top of the band produces newtons per millimetre against a
|
|
60
|
+
* load of fractions of a newton. So it is a plain penalty with no multiplier, no
|
|
61
|
+
* warm start and no identity across steps, which is also what makes a pair list
|
|
62
|
+
* that is rebuilt from scratch every step affordable: there is nothing on a pair
|
|
63
|
+
* worth carrying. `MEASUREMENTS.md` §33.
|
|
64
|
+
*
|
|
65
|
+
* @author Alex Goldring
|
|
66
|
+
* @copyright Company Named Limited (c) 2026
|
|
67
|
+
*/
|
|
68
|
+
/**
|
|
69
|
+
* Below this a separation is treated as zero and the row is skipped: `‖·‖` is
|
|
70
|
+
* not differentiable there, and two particles at exactly the same place have no
|
|
71
|
+
* direction to be pushed apart along.
|
|
72
|
+
* @type {number}
|
|
73
|
+
*/
|
|
74
|
+
export const CLOTH_SELF_EPSILON: number;
|
|
75
|
+
//# sourceMappingURL=cloth_self_row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_self_row.d.ts","sourceRoot":"","sources":["../../../../../../../src/engine/physics/cloth/solver/constraint/cloth_self_row.js"],"names":[],"mappings":"AAoEA;;;;;;;;;;GAUG;AACH,4EAJW,MAAM,GAEJ,MAAM,CA4FlB;AAED;;;;;;GAMG;AACH,mDAJW,YAAY,+BAEZ,MAAM,QAyBhB;AA7LD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH;;;;;GAKG;AACH,iCAFU,MAAM,CAEuB"}
|