@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,173 @@
|
|
|
1
|
+
import { BoxShape3D } from "../../../../core/geom/3d/shape/BoxShape3D.js";
|
|
2
|
+
import { CapsuleShape3D } from "../../../../core/geom/3d/shape/CapsuleShape3D.js";
|
|
3
|
+
import { CylinderShape3D } from "../../../../core/geom/3d/shape/CylinderShape3D.js";
|
|
4
|
+
import { PlaneShape3D } from "../../../../core/geom/3d/shape/PlaneShape3D.js";
|
|
5
|
+
import { SphereShape3D } from "../../../../core/geom/3d/shape/SphereShape3D.js";
|
|
6
|
+
import { ClothColliderKind } from "./ClothColliderKind.js";
|
|
7
|
+
import {
|
|
8
|
+
CCR_FEATURE,
|
|
9
|
+
CCR_KIND,
|
|
10
|
+
CCR_PARAM_0,
|
|
11
|
+
CCR_PARAM_1,
|
|
12
|
+
CCR_PARAM_2,
|
|
13
|
+
CCR_PARAM_3
|
|
14
|
+
} from "./ClothColliderRecord.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* # `AbstractShape3D` → a packed record's geometry
|
|
18
|
+
*
|
|
19
|
+
* The one place a cloth collider is a shape object rather than a row of floats.
|
|
20
|
+
* It runs when a `ClothCollider` is linked or its shape changes, never per step
|
|
21
|
+
* and never per particle.
|
|
22
|
+
*
|
|
23
|
+
* `instanceof` rather than the prototype markers the physics narrowphase uses,
|
|
24
|
+
* because this needs to distinguish *five* kinds rather than short-circuit one,
|
|
25
|
+
* and because a marker per kind would be five new fields on `core` shapes for
|
|
26
|
+
* one consumer's benefit. The ordering matters in one place and is commented
|
|
27
|
+
* where it does.
|
|
28
|
+
*
|
|
29
|
+
* @author Alex Goldring
|
|
30
|
+
* @copyright Company Named Limited (c) 2026
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Write a shape's kind, parameters and feature size into a record.
|
|
35
|
+
*
|
|
36
|
+
* @param {Float32Array|Float64Array} table
|
|
37
|
+
* @param {number} record record index, not a slot offset
|
|
38
|
+
* @param {AbstractShape3D} shape in its canonical local frame
|
|
39
|
+
* @param {number} stride
|
|
40
|
+
* @returns {boolean} `false` if the shape is not one cloth can collide against,
|
|
41
|
+
* in which case nothing was written
|
|
42
|
+
*/
|
|
43
|
+
export function cloth_collider_pack(table, record, shape, stride) {
|
|
44
|
+
const r = record * stride;
|
|
45
|
+
|
|
46
|
+
if (shape instanceof SphereShape3D) {
|
|
47
|
+
// Covers UnitSphereShape3D, which is a SphereShape3D of radius 1.
|
|
48
|
+
const radius = shape.radius;
|
|
49
|
+
|
|
50
|
+
table[r + CCR_KIND] = ClothColliderKind.Sphere;
|
|
51
|
+
table[r + CCR_PARAM_0] = radius;
|
|
52
|
+
table[r + CCR_PARAM_1] = 0;
|
|
53
|
+
table[r + CCR_PARAM_2] = 0;
|
|
54
|
+
table[r + CCR_PARAM_3] = 0;
|
|
55
|
+
table[r + CCR_FEATURE] = radius;
|
|
56
|
+
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (shape instanceof CapsuleShape3D) {
|
|
61
|
+
const radius = shape.radius;
|
|
62
|
+
|
|
63
|
+
table[r + CCR_KIND] = ClothColliderKind.Capsule;
|
|
64
|
+
table[r + CCR_PARAM_0] = radius;
|
|
65
|
+
table[r + CCR_PARAM_1] = shape.height;
|
|
66
|
+
table[r + CCR_PARAM_2] = 0;
|
|
67
|
+
table[r + CCR_PARAM_3] = 0;
|
|
68
|
+
|
|
69
|
+
// A capsule's tightest curvature is its cap, which is its own radius.
|
|
70
|
+
table[r + CCR_FEATURE] = radius;
|
|
71
|
+
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (shape instanceof BoxShape3D) {
|
|
76
|
+
// Covers UnitCubeShape3D, which is a BoxShape3D pinned to 0.5.
|
|
77
|
+
const h = shape.half_extents;
|
|
78
|
+
|
|
79
|
+
table[r + CCR_KIND] = ClothColliderKind.Box;
|
|
80
|
+
table[r + CCR_PARAM_0] = h.x;
|
|
81
|
+
table[r + CCR_PARAM_1] = h.y;
|
|
82
|
+
table[r + CCR_PARAM_2] = h.z;
|
|
83
|
+
table[r + CCR_PARAM_3] = 0;
|
|
84
|
+
|
|
85
|
+
// A box has no curvature; its edges are creases, and the distance over
|
|
86
|
+
// which "the nearest face's normal" describes the surface is how far
|
|
87
|
+
// the nearest face extends — its smallest half-extent, conservatively.
|
|
88
|
+
table[r + CCR_FEATURE] = Math.min(h.x, Math.min(h.y, h.z));
|
|
89
|
+
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (shape instanceof CylinderShape3D) {
|
|
94
|
+
const radius = shape.radius;
|
|
95
|
+
|
|
96
|
+
table[r + CCR_KIND] = ClothColliderKind.Cylinder;
|
|
97
|
+
table[r + CCR_PARAM_0] = radius;
|
|
98
|
+
table[r + CCR_PARAM_1] = shape.height;
|
|
99
|
+
table[r + CCR_PARAM_2] = 0;
|
|
100
|
+
table[r + CCR_PARAM_3] = 0;
|
|
101
|
+
table[r + CCR_FEATURE] = Math.min(radius, shape.height * 0.5);
|
|
102
|
+
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (shape instanceof PlaneShape3D) {
|
|
107
|
+
table[r + CCR_KIND] = ClothColliderKind.Plane;
|
|
108
|
+
table[r + CCR_PARAM_0] = shape.normal_x;
|
|
109
|
+
table[r + CCR_PARAM_1] = shape.normal_y;
|
|
110
|
+
table[r + CCR_PARAM_2] = shape.normal_z;
|
|
111
|
+
table[r + CCR_PARAM_3] = shape.offset;
|
|
112
|
+
|
|
113
|
+
// A plane is flat everywhere, so its normal describes it at any
|
|
114
|
+
// distance and it never narrows a trust region.
|
|
115
|
+
table[r + CCR_FEATURE] = Infinity;
|
|
116
|
+
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The AABB of a packed shape in its own local frame, ignoring pose.
|
|
125
|
+
*
|
|
126
|
+
* Written here rather than taken from `AbstractShape3D#compute_bounding_box`
|
|
127
|
+
* because a plane's box is `±Infinity` on its unbounded axes and the caller
|
|
128
|
+
* transforms this one — `0 · Infinity` is `NaN`, so an unbounded local box
|
|
129
|
+
* cannot go through a pose. {@link cloth_collider_local_bounds} therefore
|
|
130
|
+
* refuses a plane and the index bounds one directly from its world normal.
|
|
131
|
+
*
|
|
132
|
+
* @param {Float64Array|number[]} out `[x0, y0, z0, x1, y1, z1]`
|
|
133
|
+
* @param {Float32Array|Float64Array} table
|
|
134
|
+
* @param {number} record
|
|
135
|
+
* @param {number} stride
|
|
136
|
+
* @returns {boolean} `false` for an unbounded kind, in which case `out` is untouched
|
|
137
|
+
*/
|
|
138
|
+
export function cloth_collider_local_bounds(out, table, record, stride) {
|
|
139
|
+
const r = record * stride;
|
|
140
|
+
|
|
141
|
+
const kind = table[r + CCR_KIND];
|
|
142
|
+
|
|
143
|
+
let hx;
|
|
144
|
+
let hy;
|
|
145
|
+
let hz;
|
|
146
|
+
|
|
147
|
+
if (kind === ClothColliderKind.Sphere) {
|
|
148
|
+
hx = hy = hz = table[r + CCR_PARAM_0];
|
|
149
|
+
} else if (kind === ClothColliderKind.Capsule) {
|
|
150
|
+
const radius = table[r + CCR_PARAM_0];
|
|
151
|
+
|
|
152
|
+
hx = hz = radius;
|
|
153
|
+
hy = radius + table[r + CCR_PARAM_1] * 0.5;
|
|
154
|
+
} else if (kind === ClothColliderKind.Box) {
|
|
155
|
+
hx = table[r + CCR_PARAM_0];
|
|
156
|
+
hy = table[r + CCR_PARAM_1];
|
|
157
|
+
hz = table[r + CCR_PARAM_2];
|
|
158
|
+
} else if (kind === ClothColliderKind.Cylinder) {
|
|
159
|
+
hx = hz = table[r + CCR_PARAM_0];
|
|
160
|
+
hy = table[r + CCR_PARAM_1] * 0.5;
|
|
161
|
+
} else {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
out[0] = -hx;
|
|
166
|
+
out[1] = -hy;
|
|
167
|
+
out[2] = -hz;
|
|
168
|
+
out[3] = hx;
|
|
169
|
+
out[4] = hy;
|
|
170
|
+
out[5] = hz;
|
|
171
|
+
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # Evaluating a packed collider
|
|
3
|
+
*
|
|
4
|
+
* Two functions, and between them they are the whole of §8.2. One writes a
|
|
5
|
+
* collider's pose interpolated to a substep; the other evaluates its signed
|
|
6
|
+
* distance and gradient at a point, in the frame the table is expressed in.
|
|
7
|
+
*
|
|
8
|
+
* The evaluation is: bring the point into the collider's local frame with the
|
|
9
|
+
* inverse of the interpolated pose, evaluate the closed-form field there, and
|
|
10
|
+
* rotate the gradient back. That is three steps and no matrix — a rigid pose
|
|
11
|
+
* inverts by conjugating its quaternion and subtracting its translation, which
|
|
12
|
+
* costs less than storing an inverse and is exact rather than cached.
|
|
13
|
+
*
|
|
14
|
+
* The fields themselves live in `core/geom/3d/shape/sdf/` as free functions
|
|
15
|
+
* over scalars, so this dispatch and {@link SphereShape3D} and the rest are
|
|
16
|
+
* calling one implementation (§14.1). Before M2 those shapes fell back to
|
|
17
|
+
* `compute_signed_distance_gradient_by_sampling` — four field evaluations and a
|
|
18
|
+
* normalise, for shapes whose gradients are two lines of algebra.
|
|
19
|
+
*
|
|
20
|
+
* @author Alex Goldring
|
|
21
|
+
* @copyright Company Named Limited (c) 2026
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Write every collider's pose interpolated to fraction `t` of the step into its
|
|
25
|
+
* own record. `t = 0` is the previous step's pose and `t = 1` is this one's.
|
|
26
|
+
*
|
|
27
|
+
* **This is the whole of "swept collision", and it is swept in translation and
|
|
28
|
+
* rotation but not in the *contact set*.** Which particles are in contact is
|
|
29
|
+
* decided once per step; where those colliders are is decided once per substep.
|
|
30
|
+
* The limit §7 P3 states — a collider spinning fast enough that a point on its
|
|
31
|
+
* surface travels more than its own radius within one substep can still be
|
|
32
|
+
* missed — is a limit on the second of those, and more substeps is the answer
|
|
33
|
+
* to it.
|
|
34
|
+
*
|
|
35
|
+
* The rotation is an `nlerp` rather than a `slerp`: it is not constant angular
|
|
36
|
+
* velocity, and over the fraction of a fixed step it is indistinguishable from
|
|
37
|
+
* one — the two differ by under a thousandth of a degree at the half-radian per
|
|
38
|
+
* step `CLOTH_ANCHOR_ROTATION_LIMIT` already treats as a spin.
|
|
39
|
+
*
|
|
40
|
+
* @param {Float32Array|Float64Array} table
|
|
41
|
+
* @param {number} count records in `table`
|
|
42
|
+
* @param {number} t `[0, 1]`
|
|
43
|
+
* @returns {void}
|
|
44
|
+
*/
|
|
45
|
+
export function cloth_collider_pose_at(table: Float32Array | Float64Array, count: number, t: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* Signed distance from a point to one packed collider's surface, with the unit
|
|
48
|
+
* outward gradient written into `gradient` at `gradient_offset`.
|
|
49
|
+
*
|
|
50
|
+
* The point and the gradient are both in the frame `table` is expressed in.
|
|
51
|
+
*
|
|
52
|
+
* @param {Float32Array|Float64Array|number[]} gradient
|
|
53
|
+
* @param {number} gradient_offset
|
|
54
|
+
* @param {Float32Array|Float64Array} table
|
|
55
|
+
* @param {number} record record index, not a slot offset
|
|
56
|
+
* @param {number} x
|
|
57
|
+
* @param {number} y
|
|
58
|
+
* @param {number} z
|
|
59
|
+
* @returns {number} the signed distance
|
|
60
|
+
*/
|
|
61
|
+
export function cloth_collider_signed_distance(gradient: Float32Array | Float64Array | number[], gradient_offset: number, table: Float32Array | Float64Array, record: number, x: number, y: number, z: number): number;
|
|
62
|
+
/**
|
|
63
|
+
* Bring a point expressed in a collider's own local frame out into the frame
|
|
64
|
+
* the table is expressed in, using the interpolated pose. This is the inverse
|
|
65
|
+
* of the localisation above, and it is what carries a friction anchor with a
|
|
66
|
+
* moving collider (§8.3): the anchor is stored where the collider will always
|
|
67
|
+
* agree it is, and read back wherever the collider has moved to.
|
|
68
|
+
*
|
|
69
|
+
* @param {Float32Array|Float64Array|number[]} out
|
|
70
|
+
* @param {number} out_offset
|
|
71
|
+
* @param {Float32Array|Float64Array} table
|
|
72
|
+
* @param {number} record
|
|
73
|
+
* @param {number} x local
|
|
74
|
+
* @param {number} y local
|
|
75
|
+
* @param {number} z local
|
|
76
|
+
* @returns {void}
|
|
77
|
+
*/
|
|
78
|
+
export function cloth_collider_from_local(out: Float32Array | Float64Array | number[], out_offset: number, table: Float32Array | Float64Array, record: number, x: number, y: number, z: number): void;
|
|
79
|
+
/**
|
|
80
|
+
* Bring a point out of the table's frame into a collider's own local frame,
|
|
81
|
+
* using the interpolated pose. The anchoring half of
|
|
82
|
+
* {@link cloth_collider_from_local}.
|
|
83
|
+
*
|
|
84
|
+
* @param {Float32Array|Float64Array|number[]} out
|
|
85
|
+
* @param {number} out_offset
|
|
86
|
+
* @param {Float32Array|Float64Array} table
|
|
87
|
+
* @param {number} record
|
|
88
|
+
* @param {number} x
|
|
89
|
+
* @param {number} y
|
|
90
|
+
* @param {number} z
|
|
91
|
+
* @returns {void}
|
|
92
|
+
*/
|
|
93
|
+
export function cloth_collider_to_local(out: Float32Array | Float64Array | number[], out_offset: number, table: Float32Array | Float64Array, record: number, x: number, y: number, z: number): void;
|
|
94
|
+
//# sourceMappingURL=cloth_collider_sdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_collider_sdf.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_sdf.js"],"names":[],"mappings":"AAsCA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8CALW,YAAY,GAAC,YAAY,SACzB,MAAM,KACN,MAAM,GACJ,IAAI,CAiDhB;AAED;;;;;;;;;;;;;;GAcG;AACH,yDATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,mBAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,MAAM,CA4DlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,+CATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,IAAI,CAchB;AAED;;;;;;;;;;;;;GAaG;AACH,6CATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,IAAI,CAahB"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { sdf3_box_gradient } from "../../../../core/geom/3d/shape/sdf/sdf3_box.js";
|
|
2
|
+
import { sdf3_capsule_gradient } from "../../../../core/geom/3d/shape/sdf/sdf3_capsule.js";
|
|
3
|
+
import { sdf3_cylinder_gradient } from "../../../../core/geom/3d/shape/sdf/sdf3_cylinder.js";
|
|
4
|
+
import { sdf3_plane_gradient } from "../../../../core/geom/3d/shape/sdf/sdf3_plane.js";
|
|
5
|
+
import { sdf3_sphere_gradient } from "../../../../core/geom/3d/shape/sdf/sdf3_sphere.js";
|
|
6
|
+
import { v3_quaternion_apply } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
7
|
+
import { v3_quaternion_apply_inverse } from "../../../../core/geom/vec3/v3_quaternion_apply_inverse.js";
|
|
8
|
+
import {
|
|
9
|
+
CCR_INTERP_QW,
|
|
10
|
+
CCR_INTERP_QX,
|
|
11
|
+
CCR_INTERP_QY,
|
|
12
|
+
CCR_INTERP_QZ,
|
|
13
|
+
CCR_INTERP_TX,
|
|
14
|
+
CCR_INTERP_TY,
|
|
15
|
+
CCR_INTERP_TZ,
|
|
16
|
+
CCR_KIND,
|
|
17
|
+
CCR_PARAM_0,
|
|
18
|
+
CCR_PARAM_1,
|
|
19
|
+
CCR_PARAM_2,
|
|
20
|
+
CCR_PARAM_3,
|
|
21
|
+
CCR_PREV_QW,
|
|
22
|
+
CCR_PREV_QX,
|
|
23
|
+
CCR_PREV_QY,
|
|
24
|
+
CCR_PREV_QZ,
|
|
25
|
+
CCR_PREV_TX,
|
|
26
|
+
CCR_PREV_TY,
|
|
27
|
+
CCR_PREV_TZ,
|
|
28
|
+
CCR_QW,
|
|
29
|
+
CCR_QX,
|
|
30
|
+
CCR_QY,
|
|
31
|
+
CCR_QZ,
|
|
32
|
+
CCR_STRIDE,
|
|
33
|
+
CCR_TX,
|
|
34
|
+
CCR_TY,
|
|
35
|
+
CCR_TZ
|
|
36
|
+
} from "./ClothColliderRecord.js";
|
|
37
|
+
import { ClothColliderKind } from "./ClothColliderKind.js";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* # Evaluating a packed collider
|
|
41
|
+
*
|
|
42
|
+
* Two functions, and between them they are the whole of §8.2. One writes a
|
|
43
|
+
* collider's pose interpolated to a substep; the other evaluates its signed
|
|
44
|
+
* distance and gradient at a point, in the frame the table is expressed in.
|
|
45
|
+
*
|
|
46
|
+
* The evaluation is: bring the point into the collider's local frame with the
|
|
47
|
+
* inverse of the interpolated pose, evaluate the closed-form field there, and
|
|
48
|
+
* rotate the gradient back. That is three steps and no matrix — a rigid pose
|
|
49
|
+
* inverts by conjugating its quaternion and subtracting its translation, which
|
|
50
|
+
* costs less than storing an inverse and is exact rather than cached.
|
|
51
|
+
*
|
|
52
|
+
* The fields themselves live in `core/geom/3d/shape/sdf/` as free functions
|
|
53
|
+
* over scalars, so this dispatch and {@link SphereShape3D} and the rest are
|
|
54
|
+
* calling one implementation (§14.1). Before M2 those shapes fell back to
|
|
55
|
+
* `compute_signed_distance_gradient_by_sampling` — four field evaluations and a
|
|
56
|
+
* normalise, for shapes whose gradients are two lines of algebra.
|
|
57
|
+
*
|
|
58
|
+
* @author Alex Goldring
|
|
59
|
+
* @copyright Company Named Limited (c) 2026
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Write every collider's pose interpolated to fraction `t` of the step into its
|
|
64
|
+
* own record. `t = 0` is the previous step's pose and `t = 1` is this one's.
|
|
65
|
+
*
|
|
66
|
+
* **This is the whole of "swept collision", and it is swept in translation and
|
|
67
|
+
* rotation but not in the *contact set*.** Which particles are in contact is
|
|
68
|
+
* decided once per step; where those colliders are is decided once per substep.
|
|
69
|
+
* The limit §7 P3 states — a collider spinning fast enough that a point on its
|
|
70
|
+
* surface travels more than its own radius within one substep can still be
|
|
71
|
+
* missed — is a limit on the second of those, and more substeps is the answer
|
|
72
|
+
* to it.
|
|
73
|
+
*
|
|
74
|
+
* The rotation is an `nlerp` rather than a `slerp`: it is not constant angular
|
|
75
|
+
* velocity, and over the fraction of a fixed step it is indistinguishable from
|
|
76
|
+
* one — the two differ by under a thousandth of a degree at the half-radian per
|
|
77
|
+
* step `CLOTH_ANCHOR_ROTATION_LIMIT` already treats as a spin.
|
|
78
|
+
*
|
|
79
|
+
* @param {Float32Array|Float64Array} table
|
|
80
|
+
* @param {number} count records in `table`
|
|
81
|
+
* @param {number} t `[0, 1]`
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*/
|
|
84
|
+
export function cloth_collider_pose_at(table, count, t) {
|
|
85
|
+
const s = 1 - t;
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < count; i++) {
|
|
88
|
+
const r = i * CCR_STRIDE;
|
|
89
|
+
|
|
90
|
+
table[r + CCR_INTERP_TX] = s * table[r + CCR_PREV_TX] + t * table[r + CCR_TX];
|
|
91
|
+
table[r + CCR_INTERP_TY] = s * table[r + CCR_PREV_TY] + t * table[r + CCR_TY];
|
|
92
|
+
table[r + CCR_INTERP_TZ] = s * table[r + CCR_PREV_TZ] + t * table[r + CCR_TZ];
|
|
93
|
+
|
|
94
|
+
const ax = table[r + CCR_PREV_QX];
|
|
95
|
+
const ay = table[r + CCR_PREV_QY];
|
|
96
|
+
const az = table[r + CCR_PREV_QZ];
|
|
97
|
+
const aw = table[r + CCR_PREV_QW];
|
|
98
|
+
|
|
99
|
+
let bx = table[r + CCR_QX];
|
|
100
|
+
let by = table[r + CCR_QY];
|
|
101
|
+
let bz = table[r + CCR_QZ];
|
|
102
|
+
let bw = table[r + CCR_QW];
|
|
103
|
+
|
|
104
|
+
// `q` and `−q` are one rotation, so the pair has to be brought onto the
|
|
105
|
+
// same hemisphere or the interpolation takes the long way round — which
|
|
106
|
+
// for a collider is a bone that spins through the character.
|
|
107
|
+
if (ax * bx + ay * by + az * bz + aw * bw < 0) {
|
|
108
|
+
bx = -bx;
|
|
109
|
+
by = -by;
|
|
110
|
+
bz = -bz;
|
|
111
|
+
bw = -bw;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const qx = s * ax + t * bx;
|
|
115
|
+
const qy = s * ay + t * by;
|
|
116
|
+
const qz = s * az + t * bz;
|
|
117
|
+
const qw = s * aw + t * bw;
|
|
118
|
+
|
|
119
|
+
const length = Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw);
|
|
120
|
+
|
|
121
|
+
// Two opposed quaternions cancel exactly, which the hemisphere fix
|
|
122
|
+
// above makes impossible; the guard is for a record whose poses were
|
|
123
|
+
// never written rather than for a rotation.
|
|
124
|
+
const inverse = length > 0 ? 1 / length : 0;
|
|
125
|
+
|
|
126
|
+
table[r + CCR_INTERP_QX] = qx * inverse;
|
|
127
|
+
table[r + CCR_INTERP_QY] = qy * inverse;
|
|
128
|
+
table[r + CCR_INTERP_QZ] = qz * inverse;
|
|
129
|
+
table[r + CCR_INTERP_QW] = length > 0 ? qw * inverse : 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Signed distance from a point to one packed collider's surface, with the unit
|
|
135
|
+
* outward gradient written into `gradient` at `gradient_offset`.
|
|
136
|
+
*
|
|
137
|
+
* The point and the gradient are both in the frame `table` is expressed in.
|
|
138
|
+
*
|
|
139
|
+
* @param {Float32Array|Float64Array|number[]} gradient
|
|
140
|
+
* @param {number} gradient_offset
|
|
141
|
+
* @param {Float32Array|Float64Array} table
|
|
142
|
+
* @param {number} record record index, not a slot offset
|
|
143
|
+
* @param {number} x
|
|
144
|
+
* @param {number} y
|
|
145
|
+
* @param {number} z
|
|
146
|
+
* @returns {number} the signed distance
|
|
147
|
+
*/
|
|
148
|
+
export function cloth_collider_signed_distance(gradient, gradient_offset, table, record, x, y, z) {
|
|
149
|
+
const r = record * CCR_STRIDE;
|
|
150
|
+
|
|
151
|
+
const qx = table[r + CCR_INTERP_QX];
|
|
152
|
+
const qy = table[r + CCR_INTERP_QY];
|
|
153
|
+
const qz = table[r + CCR_INTERP_QZ];
|
|
154
|
+
const qw = table[r + CCR_INTERP_QW];
|
|
155
|
+
|
|
156
|
+
v3_quaternion_apply_inverse(
|
|
157
|
+
LOCAL_POINT, 0,
|
|
158
|
+
x - table[r + CCR_INTERP_TX],
|
|
159
|
+
y - table[r + CCR_INTERP_TY],
|
|
160
|
+
z - table[r + CCR_INTERP_TZ],
|
|
161
|
+
qx, qy, qz, qw
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const lx = LOCAL_POINT[0];
|
|
165
|
+
const ly = LOCAL_POINT[1];
|
|
166
|
+
const lz = LOCAL_POINT[2];
|
|
167
|
+
|
|
168
|
+
const kind = table[r + CCR_KIND];
|
|
169
|
+
|
|
170
|
+
let distance;
|
|
171
|
+
|
|
172
|
+
if (kind === ClothColliderKind.Sphere) {
|
|
173
|
+
distance = sdf3_sphere_gradient(LOCAL_GRADIENT, 0, lx, ly, lz, table[r + CCR_PARAM_0]);
|
|
174
|
+
} else if (kind === ClothColliderKind.Capsule) {
|
|
175
|
+
distance = sdf3_capsule_gradient(
|
|
176
|
+
LOCAL_GRADIENT, 0, lx, ly, lz,
|
|
177
|
+
table[r + CCR_PARAM_0], table[r + CCR_PARAM_1]
|
|
178
|
+
);
|
|
179
|
+
} else if (kind === ClothColliderKind.Box) {
|
|
180
|
+
distance = sdf3_box_gradient(
|
|
181
|
+
LOCAL_GRADIENT, 0, lx, ly, lz,
|
|
182
|
+
table[r + CCR_PARAM_0], table[r + CCR_PARAM_1], table[r + CCR_PARAM_2]
|
|
183
|
+
);
|
|
184
|
+
} else if (kind === ClothColliderKind.Cylinder) {
|
|
185
|
+
distance = sdf3_cylinder_gradient(
|
|
186
|
+
LOCAL_GRADIENT, 0, lx, ly, lz,
|
|
187
|
+
table[r + CCR_PARAM_0], table[r + CCR_PARAM_1]
|
|
188
|
+
);
|
|
189
|
+
} else {
|
|
190
|
+
distance = sdf3_plane_gradient(
|
|
191
|
+
LOCAL_GRADIENT, 0, lx, ly, lz,
|
|
192
|
+
table[r + CCR_PARAM_0], table[r + CCR_PARAM_1], table[r + CCR_PARAM_2],
|
|
193
|
+
table[r + CCR_PARAM_3]
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// The gradient is a direction, so it takes the rotation and not the
|
|
198
|
+
// translation.
|
|
199
|
+
v3_quaternion_apply(
|
|
200
|
+
gradient, gradient_offset,
|
|
201
|
+
LOCAL_GRADIENT[0], LOCAL_GRADIENT[1], LOCAL_GRADIENT[2],
|
|
202
|
+
qx, qy, qz, qw
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
return distance;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Bring a point expressed in a collider's own local frame out into the frame
|
|
210
|
+
* the table is expressed in, using the interpolated pose. This is the inverse
|
|
211
|
+
* of the localisation above, and it is what carries a friction anchor with a
|
|
212
|
+
* moving collider (§8.3): the anchor is stored where the collider will always
|
|
213
|
+
* agree it is, and read back wherever the collider has moved to.
|
|
214
|
+
*
|
|
215
|
+
* @param {Float32Array|Float64Array|number[]} out
|
|
216
|
+
* @param {number} out_offset
|
|
217
|
+
* @param {Float32Array|Float64Array} table
|
|
218
|
+
* @param {number} record
|
|
219
|
+
* @param {number} x local
|
|
220
|
+
* @param {number} y local
|
|
221
|
+
* @param {number} z local
|
|
222
|
+
* @returns {void}
|
|
223
|
+
*/
|
|
224
|
+
export function cloth_collider_from_local(out, out_offset, table, record, x, y, z) {
|
|
225
|
+
const r = record * CCR_STRIDE;
|
|
226
|
+
|
|
227
|
+
v3_quaternion_apply(
|
|
228
|
+
out, out_offset, x, y, z,
|
|
229
|
+
table[r + CCR_INTERP_QX], table[r + CCR_INTERP_QY],
|
|
230
|
+
table[r + CCR_INTERP_QZ], table[r + CCR_INTERP_QW]
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
out[out_offset] += table[r + CCR_INTERP_TX];
|
|
234
|
+
out[out_offset + 1] += table[r + CCR_INTERP_TY];
|
|
235
|
+
out[out_offset + 2] += table[r + CCR_INTERP_TZ];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Bring a point out of the table's frame into a collider's own local frame,
|
|
240
|
+
* using the interpolated pose. The anchoring half of
|
|
241
|
+
* {@link cloth_collider_from_local}.
|
|
242
|
+
*
|
|
243
|
+
* @param {Float32Array|Float64Array|number[]} out
|
|
244
|
+
* @param {number} out_offset
|
|
245
|
+
* @param {Float32Array|Float64Array} table
|
|
246
|
+
* @param {number} record
|
|
247
|
+
* @param {number} x
|
|
248
|
+
* @param {number} y
|
|
249
|
+
* @param {number} z
|
|
250
|
+
* @returns {void}
|
|
251
|
+
*/
|
|
252
|
+
export function cloth_collider_to_local(out, out_offset, table, record, x, y, z) {
|
|
253
|
+
const r = record * CCR_STRIDE;
|
|
254
|
+
|
|
255
|
+
v3_quaternion_apply_inverse(
|
|
256
|
+
out, out_offset,
|
|
257
|
+
x - table[r + CCR_INTERP_TX],
|
|
258
|
+
y - table[r + CCR_INTERP_TY],
|
|
259
|
+
z - table[r + CCR_INTERP_TZ],
|
|
260
|
+
table[r + CCR_INTERP_QX], table[r + CCR_INTERP_QY],
|
|
261
|
+
table[r + CCR_INTERP_QZ], table[r + CCR_INTERP_QW]
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @type {Float64Array}
|
|
267
|
+
* @private
|
|
268
|
+
*/
|
|
269
|
+
const LOCAL_GRADIENT = new Float64Array(3);
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @type {Float64Array}
|
|
273
|
+
* @private
|
|
274
|
+
*/
|
|
275
|
+
const LOCAL_POINT = new Float64Array(3);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # The marker that opts a collider into cloth
|
|
3
|
+
*
|
|
4
|
+
* Put this beside an existing `(Collider, Transform64)` and cloth collides
|
|
5
|
+
* against it. That is the whole of the component's job, and it is the third
|
|
6
|
+
* instance of a pattern the engine already has twice: `AcousticBody` opts a
|
|
7
|
+
* collider into the acoustic simulation and carries an `AcousticMaterial`,
|
|
8
|
+
* `FluidObstacle` opts a collider into the fluid simulation and carries an
|
|
9
|
+
* inflation radius. This should read as a sibling of those two rather than as a
|
|
10
|
+
* new invention.
|
|
11
|
+
*
|
|
12
|
+
* Everything not here is read from components the entity already has: geometry
|
|
13
|
+
* and friction from `Collider`, pose from `Transform64`.
|
|
14
|
+
*
|
|
15
|
+
* ## No `RigidBody` required
|
|
16
|
+
*
|
|
17
|
+
* A deliberate divergence from `FluidObstacle`, which requires one because it
|
|
18
|
+
* needs a wall velocity. Cloth's colliders are overwhelmingly character bones —
|
|
19
|
+
* ordinary entities in a `TransformAttachment` hierarchy — and making each of
|
|
20
|
+
* them a physics body to be seen by cloth would tax the common case. Collider
|
|
21
|
+
* velocity is derived from the pose delta between fixed steps, which the index
|
|
22
|
+
* caches anyway for swept collision (§8.2). A world prop that *does* carry a
|
|
23
|
+
* `RigidBody` adds a `ClothCollider` the same way and lands in the same index;
|
|
24
|
+
* the two cases are not distinguished.
|
|
25
|
+
*
|
|
26
|
+
* ## Layer and mask, which §3.5 did not have
|
|
27
|
+
*
|
|
28
|
+
* §3.5 gives this component three fields and says layer filtering comes "from
|
|
29
|
+
* the `Cloth` side". It cannot: `Cloth#mask` is a mask *of collider layers*,
|
|
30
|
+
* and with no `RigidBody` required there is nowhere else for a collider's layer
|
|
31
|
+
* to live. So the pair is here, with `RigidBody`'s own semantics — a cloth and
|
|
32
|
+
* a collider interact when each is in the other's mask — which is what
|
|
33
|
+
* `Cloth.js` already says it means by "`RigidBody` semantics".
|
|
34
|
+
*
|
|
35
|
+
* @author Alex Goldring
|
|
36
|
+
* @copyright Company Named Limited (c) 2026
|
|
37
|
+
*/
|
|
38
|
+
export class ClothCollider {
|
|
39
|
+
/**
|
|
40
|
+
* @param {object} [spec]
|
|
41
|
+
* @param {number} [spec.inflation]
|
|
42
|
+
* @param {number} [spec.friction_scale]
|
|
43
|
+
* @param {number} [spec.layer]
|
|
44
|
+
* @param {number} [spec.mask]
|
|
45
|
+
* @param {number} [spec.flags]
|
|
46
|
+
* @returns {ClothCollider}
|
|
47
|
+
*/
|
|
48
|
+
static from(spec?: {
|
|
49
|
+
inflation?: number;
|
|
50
|
+
friction_scale?: number;
|
|
51
|
+
layer?: number;
|
|
52
|
+
mask?: number;
|
|
53
|
+
flags?: number;
|
|
54
|
+
}): ClothCollider;
|
|
55
|
+
/**
|
|
56
|
+
* Extra thickness in metres, on top of `ClothDynamics#thickness`.
|
|
57
|
+
*
|
|
58
|
+
* The contact row holds cloth at `thickness + inflation` from the surface,
|
|
59
|
+
* so this is how a garment is kept off a body it would otherwise graze —
|
|
60
|
+
* the same idea as `FluidObstacle#inflation`, and useful for the same
|
|
61
|
+
* reason: a collider that approximates a limb loosely wants the cloth held
|
|
62
|
+
* a little further out than the approximation.
|
|
63
|
+
* @type {number}
|
|
64
|
+
*/
|
|
65
|
+
inflation: number;
|
|
66
|
+
/**
|
|
67
|
+
* Multiplies the entity's `Collider#friction` before it is combined with
|
|
68
|
+
* the cloth's own. `0` makes the surface frictionless to cloth without
|
|
69
|
+
* making it frictionless to rigid bodies, which is the case this exists
|
|
70
|
+
* for: a character's collision capsules are tuned for footing, and a cape
|
|
71
|
+
* that grips them the same way reads as glued.
|
|
72
|
+
* @type {number}
|
|
73
|
+
*/
|
|
74
|
+
friction_scale: number;
|
|
75
|
+
/**
|
|
76
|
+
* Collision layer this collider belongs to, `RigidBody` semantics.
|
|
77
|
+
* @type {number}
|
|
78
|
+
*/
|
|
79
|
+
layer: number;
|
|
80
|
+
/**
|
|
81
|
+
* Which `Cloth` layers this collider acts on.
|
|
82
|
+
* @type {number}
|
|
83
|
+
*/
|
|
84
|
+
mask: number;
|
|
85
|
+
/**
|
|
86
|
+
* @see ClothColliderFlags
|
|
87
|
+
* @type {number}
|
|
88
|
+
*/
|
|
89
|
+
flags: number;
|
|
90
|
+
/**
|
|
91
|
+
* @param {number|ClothColliderFlags} flag
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
getFlag(flag: number | ClothColliderFlags): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* @param {ClothCollider} other
|
|
97
|
+
* @returns {boolean}
|
|
98
|
+
*/
|
|
99
|
+
equals(other: ClothCollider): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* @returns {number}
|
|
102
|
+
*/
|
|
103
|
+
hash(): number;
|
|
104
|
+
toJSON(): {
|
|
105
|
+
inflation: number;
|
|
106
|
+
friction_scale: number;
|
|
107
|
+
layer: number;
|
|
108
|
+
mask: number;
|
|
109
|
+
flags: number;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* @param {object} json
|
|
113
|
+
*/
|
|
114
|
+
fromJSON({ inflation, friction_scale, layer, mask, flags }: object): void;
|
|
115
|
+
toString(): string;
|
|
116
|
+
/**
|
|
117
|
+
* @readonly
|
|
118
|
+
* @type {boolean}
|
|
119
|
+
*/
|
|
120
|
+
readonly isClothCollider: boolean;
|
|
121
|
+
}
|
|
122
|
+
export namespace ClothCollider {
|
|
123
|
+
let typeName: string;
|
|
124
|
+
}
|
|
125
|
+
import { ClothColliderFlags } from "./ClothColliderFlags.js";
|
|
126
|
+
//# sourceMappingURL=ClothCollider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClothCollider.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothCollider.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH;IA0CI;;;;;;;;OAQG;IACH;QAPyB,SAAS,GAAvB,MAAM;QACQ,cAAc,GAA5B,MAAM;QACQ,KAAK,GAAnB,MAAM;QACQ,IAAI,GAAlB,MAAM;QACQ,KAAK,GAAnB,MAAM;QACJ,aAAa,CA0BzB;IAzED;;;;;;;;;OASG;IACH,WAFU,MAAM,CAEF;IAEd;;;;;;;OAOG;IACH,gBAFU,MAAM,CAEG;IAEnB;;;OAGG;IACH,OAFU,MAAM,CAEN;IAEV;;;OAGG;IACH,MAFU,MAAM,CAEE;IAElB;;;OAGG;IACH,OAFU,MAAM,CAEgB;IAqChC;;;OAGG;IACH,cAHW,MAAM,GAAC,kBAAkB,GACvB,OAAO,CAInB;IAED;;;OAGG;IACH,cAHW,aAAa,GACX,OAAO,CAgBnB;IAED;;OAEG;IACH,QAFa,MAAM,CAUlB;IAED;;;;;;MAQC;IAED;;OAEG;IACH,4DAFW,MAAM,QAchB;IAED,mBAEC;IAGL;;;OAGG;IACH,0BAFU,OAAO,CAEsB;CANtC;;;;mCA3LkC,yBAAyB"}
|