@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,207 @@
|
|
|
1
|
+
import { assert } from "../assert.js";
|
|
2
|
+
import BinaryHeap from "../collection/heap/BinaryHeap.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Runs at most {@link max_concurrent} tasks at a time, highest priority first across everything
|
|
6
|
+
* submitted to it.
|
|
7
|
+
*
|
|
8
|
+
* The point of putting one of these between a caller and its work is almost never the cap on its
|
|
9
|
+
* own — a caller can count its own in-flight requests. It is that **one** gate shared by several
|
|
10
|
+
* callers orders their work against each other. Per-caller caps do not compose: the number a
|
|
11
|
+
* browser, a CDN or a disk cares about is the total, and a caller that knows about one file cannot
|
|
12
|
+
* see it. Neither can a per-caller queue say that the second caller's request matters more than the
|
|
13
|
+
* first caller's, however truthfully their priorities compare.
|
|
14
|
+
*
|
|
15
|
+
* Ties are broken arbitrarily. Two tasks submitted at the same priority are, by the only measure the
|
|
16
|
+
* gate has, equally worth running.
|
|
17
|
+
*
|
|
18
|
+
* Nothing here is a new idea in this engine, which is why it ended up here rather than inside any
|
|
19
|
+
* one of its callers. `AssetManager` has capped concurrent top-level loads on `load_concurrency` for the
|
|
20
|
+
* same stated reason — keeping network slots free for higher-priority requests — and orders its
|
|
21
|
+
* pending queue through `get_pending_asset_priority_score`, which negates the priority for exactly
|
|
22
|
+
* the reason this heap does: `BinaryHeap` pops the lowest score first. `VirtualTextureManager` caps
|
|
23
|
+
* `max_concurrent_loads` against `#loads_in_flight`. When the virtual-geometry residency layer
|
|
24
|
+
* wanted the cap a third time and wrote that same negation a second time, it stopped being a detail
|
|
25
|
+
* of any one caller. The other two keep their own queues anyway, deliberately, and each says why
|
|
26
|
+
* where its cap is declared; the three paragraphs below are those reasons.
|
|
27
|
+
*
|
|
28
|
+
* **Priority is read once, at {@link submit}.** A gate keyed on a number captured at submission is
|
|
29
|
+
* the wrong shape for work whose importance moves while it waits, or whose priorities were never on
|
|
30
|
+
* a common scale: `AssetRequestScope.final_priority` is a richer model than a bare number, but it
|
|
31
|
+
* propagates hierarchically from an asset's requesting scopes and so compares only inside one
|
|
32
|
+
* hierarchy. For either, keep a queue over live records and re-score it (see below).
|
|
33
|
+
*
|
|
34
|
+
* **A task must not wait on another submission to the same gate.** The parent holds a slot while the
|
|
35
|
+
* child waits for one, so at a full gate that is a deadlock, and the gate cannot detect it: it sees
|
|
36
|
+
* a task that has not settled. Work that nests needs the parent's slot to cover the child, which
|
|
37
|
+
* means dispatching the child over the cap — `AssetManager` does exactly that for the requests its
|
|
38
|
+
* loaders make while servicing a load, and keeps its own queue for it.
|
|
39
|
+
*
|
|
40
|
+
* **What it deliberately is not.** There is no cancellation, and no way to drop or re-order a
|
|
41
|
+
* submission once it is made: a queued entry holds a closure and the gate will eventually run it.
|
|
42
|
+
* A caller that wants to *discard* pending work — because the page stopped being on screen, or a
|
|
43
|
+
* coarser mip arrived instead — wants a queue of live records it can filter, drained on its own
|
|
44
|
+
* clock, not a gate that owns closures. `VirtualTextureManager` drops queued requests untouched for
|
|
45
|
+
* `queue_stale_window` frames; it is that second thing, and no worse for it.
|
|
46
|
+
*
|
|
47
|
+
* Nothing bounds how long a low-priority submission waits. A caller that keeps feeding the gate
|
|
48
|
+
* higher-priority work will starve it indefinitely, which is what a priority queue means and is
|
|
49
|
+
* fine for the admission gates named above — where a dropped want is re-derived next frame — and not
|
|
50
|
+
* fine for work that has to finish eventually.
|
|
51
|
+
*
|
|
52
|
+
* @author Alex Goldring
|
|
53
|
+
* @copyright Company Named Limited (c) 2026
|
|
54
|
+
*/
|
|
55
|
+
export class ConcurrencyGate {
|
|
56
|
+
/**
|
|
57
|
+
* @type {number}
|
|
58
|
+
*/
|
|
59
|
+
#max_concurrent;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @type {number}
|
|
63
|
+
*/
|
|
64
|
+
#in_flight = 0;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Waiting tasks, highest priority first — a min-heap on the negated priority.
|
|
68
|
+
* @type {BinaryHeap<{priority: number, task: function(): Promise<*>, resolve: function(*): void, reject: function(*): void}>}
|
|
69
|
+
*/
|
|
70
|
+
#queue = new BinaryHeap((entry) => -entry.priority);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @type {number}
|
|
74
|
+
*/
|
|
75
|
+
#admitted = 0;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @type {number}
|
|
79
|
+
*/
|
|
80
|
+
#peak_in_flight = 0;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param {number} max_concurrent how many tasks may be running at once
|
|
84
|
+
*/
|
|
85
|
+
constructor(max_concurrent) {
|
|
86
|
+
assert.isPositiveInteger(max_concurrent, 'max_concurrent');
|
|
87
|
+
|
|
88
|
+
this.#max_concurrent = max_concurrent;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @returns {number}
|
|
93
|
+
*/
|
|
94
|
+
get max_concurrent() {
|
|
95
|
+
return this.#max_concurrent;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Raising this starts whatever was already waiting. Lowering it starts nothing and stops
|
|
100
|
+
* nothing — tasks already running are left to finish, and the gate admits again once they have
|
|
101
|
+
* drained below the new value.
|
|
102
|
+
*
|
|
103
|
+
* @param {number} value
|
|
104
|
+
*/
|
|
105
|
+
set max_concurrent(value) {
|
|
106
|
+
assert.isPositiveInteger(value, 'max_concurrent');
|
|
107
|
+
|
|
108
|
+
this.#max_concurrent = value;
|
|
109
|
+
|
|
110
|
+
this.#pump();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @returns {number}
|
|
115
|
+
*/
|
|
116
|
+
get in_flight() {
|
|
117
|
+
return this.#in_flight;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @returns {number}
|
|
122
|
+
*/
|
|
123
|
+
get queued() {
|
|
124
|
+
return this.#queue.size();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* How many tasks this gate has started. Telemetry.
|
|
129
|
+
* @returns {number}
|
|
130
|
+
*/
|
|
131
|
+
get admitted() {
|
|
132
|
+
return this.#admitted;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* The most that were ever in flight at once — which should never exceed the cap that was in
|
|
137
|
+
* force when they started, and is here so that a test can say so rather than assume it.
|
|
138
|
+
* @returns {number}
|
|
139
|
+
*/
|
|
140
|
+
get peak_in_flight() {
|
|
141
|
+
return this.#peak_in_flight;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Run a task when there is room, highest priority first.
|
|
146
|
+
*
|
|
147
|
+
* The task is never invoked synchronously, even when the gate is empty: it runs from a
|
|
148
|
+
* microtask, so a task that throws on its first line is a rejected promise here rather than an
|
|
149
|
+
* exception thrown back at whoever called {@link submit}.
|
|
150
|
+
*
|
|
151
|
+
* @template T
|
|
152
|
+
* @param {number} priority higher runs sooner
|
|
153
|
+
* @param {function(): Promise<T>} task
|
|
154
|
+
* @returns {Promise<T>} whatever the task settled to, once it ran
|
|
155
|
+
*/
|
|
156
|
+
submit(priority, task) {
|
|
157
|
+
assert.isNumber(priority, 'priority');
|
|
158
|
+
assert.isFunction(task, 'task');
|
|
159
|
+
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
this.#queue.push({ priority, task, resolve, reject });
|
|
162
|
+
|
|
163
|
+
this.#pump();
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Start whatever fits.
|
|
169
|
+
*/
|
|
170
|
+
#pump() {
|
|
171
|
+
while (this.#in_flight < this.#max_concurrent && !this.#queue.isEmpty()) {
|
|
172
|
+
const entry = this.#queue.pop();
|
|
173
|
+
|
|
174
|
+
this.#in_flight++;
|
|
175
|
+
this.#admitted++;
|
|
176
|
+
|
|
177
|
+
if (this.#in_flight > this.#peak_in_flight) {
|
|
178
|
+
this.#peak_in_flight = this.#in_flight;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/*
|
|
182
|
+
Settled through two explicit branches rather than `.finally`, because `.finally` returns
|
|
183
|
+
a promise of its own and a rejection travelling through it with nothing attached is an
|
|
184
|
+
unhandled rejection — which at the scale a gate is reached for is not a warning in a
|
|
185
|
+
log, it is a process that stops.
|
|
186
|
+
*/
|
|
187
|
+
const settle = () => {
|
|
188
|
+
this.#in_flight--;
|
|
189
|
+
|
|
190
|
+
this.#pump();
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
Promise.resolve().then(() => entry.task()).then(
|
|
194
|
+
(value) => {
|
|
195
|
+
settle();
|
|
196
|
+
|
|
197
|
+
entry.resolve(value);
|
|
198
|
+
},
|
|
199
|
+
(error) => {
|
|
200
|
+
settle();
|
|
201
|
+
|
|
202
|
+
entry.reject(error);
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
@@ -32,6 +32,16 @@ export class AssetManager<CTX> {
|
|
|
32
32
|
* this can be useful to keep some network slots available for high-priority requests such as UI related ones.
|
|
33
33
|
* Nested requests (made by a loader while servicing another load) are dispatched immediately and never wait
|
|
34
34
|
* on this limit: their parent occupies a slot until they resolve, so queueing them would deadlock.
|
|
35
|
+
*
|
|
36
|
+
* Not a `core/process/ConcurrencyGate`, and the three reasons are each on their own decisive.
|
|
37
|
+
* That gate admits closures it owns and resolves one promise per task; a load here is dispatched
|
|
38
|
+
* by callback and settles exactly once, reached from several places. Its ordering key is read
|
|
39
|
+
* once, at submission; the key here is re-read live on every heap sift, because
|
|
40
|
+
* {@link AssetRequestScope#final_priority} walks the scope chain and a later request joining an
|
|
41
|
+
* already-queued asset re-scores it in place. And the nested-request bypass dispatches *over*
|
|
42
|
+
* this limit on purpose, which is the one thing a gate whose whole contract is "never more than
|
|
43
|
+
* N in flight" cannot express.
|
|
44
|
+
*
|
|
35
45
|
* @type {number}
|
|
36
46
|
*/
|
|
37
47
|
load_concurrency: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetManager.d.ts","sourceRoot":"","sources":["../../../../src/engine/asset/AssetManager.js"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH;
|
|
1
|
+
{"version":3,"file":"AssetManager.d.ts","sourceRoot":"","sources":["../../../../src/engine/asset/AssetManager.js"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH;IAsNI;;;;;;OAMG;IACH;QAJwB,OAAO,EAApB,GAAG;QACyB,QAAQ,EAApC,kBAAkB;OAW5B;IApOD;;;;OAIG;IACH,eAEG;IAEH;;;OAGG;IACH,aAFU,YAAY,gBAAgB,EAAE,YAAY,CAAC,CAER;IAuB7C;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAFU,MAAM,CAEY;IA4B5B;;;;;;OAMG;IACH,iBAAc;IAEd;;;OAGG;IACH,mBAFU,iBAAiB,CAEiB;IAuI5C,gBAWC;IAED;;;;;;OAMG;IACH,qBALW,OAAO,GAGN,QAAQ,IAAI,CAAC,CAgBxB;IA4ED;;;;;;;OAOG;IACH,yBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;OAKG;IACH,oCAFa,OAAO,CAOnB;IAED;;OAEG;IACH,cAEC;IAED,8BAEC;IAED;;;;;;;;OAQG;IACH;QALuC,KAAK,GAAjC,iBAAiB;QACC,UAAU,GAA5B,OAAO;QAC2C,QAAQ,GAA1D,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;QACrC,wCAAc,CAc1B;IAED;;;;;;;;;;OAUG;IACH;;;mCANgC,IAAI;kBACzB,CAAC,MAAM,KAAG,KAAK,IAAI;mBACnB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;qBACvC,OAAO;gBACP,iBAAiB;aA8D3B;IAED;;;;;;;OAOG;IACH,gBAJW,MAAM,QACN,MAAM,GACL,OAAO,CAKlB;IAGD;;;;;;;OAOG;IACH,eALW,MAAM,QACN,MAAM,GACJ,OAAO,CAOnB;IAED;;;;;;;OAOG;IACH,eAJW,MAAM,QACN,MAAM,GACL,OAAO,CAMlB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,uBAZW,MAAM,QACN,MAAM,sBACM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,iCAwE9D;IAED;;;;;;;;;;;OAWG;IACH,kBAJW,MAAM,QACN,MAAM,oBAoChB;IAgbD;;;;;;OAMG;IACH,sBAkCC;IAGD;;;;OAIG;IACH,uBAHW,MAAM,GACL,OAAO,CAIlB;IAED;;;;OAIG;IACH,sBAHW,MAAM,GACJ,wBAAY,SAAS,CAMjC;IAaD;;;;;;;;;;OAUG;IACH,+BALW,MAAM,qBAEJ,IAAI,CAqBhB;IAED;;;;;;OAMG;IACH,iCALW,MAAM,qBAEJ,OAAO,CAyBnB;IAED;;;;;;OAMG;IACH,6BAJW,MAAM,kCAEJ,QAAQ,OAAO,CAAC,CAU5B;IAED;;;;;OAKG;IACH,0BAJW,MAAM,iEAwChB;IAED;;;OAGG;IACH,uBAFW,MAAM,iBAkBhB;IAED;;;;;;;OAOG;IACH,6CAUC;IAED;;;;OAIG;IACH,2BAHW,MAAM,gBAchB;IAED;;;;OAIG;IACH,oBAHW,MAAM,GACL,gBAAgB,GAAC,SAAS,CAQrC;IAED;;;;;OAKG;IACH,mBAJW,MAAM,QACN,MAAM,QACN,MAAM,QAUhB;IAGL;;;OAGG;IACH,yBAFU,OAAO,CAEoB;;CANpC;;;4BAz4C2B,0CAA0C;iCAOrC,uBAAuB;6BAM3B,mBAAmB;kCAFd,6BAA6B;kCAD7B,wBAAwB;4BAE9B,0BAA0B;+BARvB,mDAAmD"}
|
|
@@ -101,6 +101,16 @@ export class AssetManager {
|
|
|
101
101
|
* this can be useful to keep some network slots available for high-priority requests such as UI related ones.
|
|
102
102
|
* Nested requests (made by a loader while servicing another load) are dispatched immediately and never wait
|
|
103
103
|
* on this limit: their parent occupies a slot until they resolve, so queueing them would deadlock.
|
|
104
|
+
*
|
|
105
|
+
* Not a `core/process/ConcurrencyGate`, and the three reasons are each on their own decisive.
|
|
106
|
+
* That gate admits closures it owns and resolves one promise per task; a load here is dispatched
|
|
107
|
+
* by callback and settles exactly once, reached from several places. Its ordering key is read
|
|
108
|
+
* once, at submission; the key here is re-read live on every heap sift, because
|
|
109
|
+
* {@link AssetRequestScope#final_priority} walks the scope chain and a later request joining an
|
|
110
|
+
* already-queued asset re-scores it in place. And the nested-request bypass dispatches *over*
|
|
111
|
+
* this limit on purpose, which is the one thing a gate whose whole contract is "never more than
|
|
112
|
+
* N in flight" cannot express.
|
|
113
|
+
*
|
|
104
114
|
* @type {number}
|
|
105
115
|
*/
|
|
106
116
|
load_concurrency = Infinity;
|
|
@@ -6,8 +6,14 @@ Date: 2026-07-30. Scope: `meep` graphics stack (three.js r136, WebGL2) as consum
|
|
|
6
6
|
Goal: when the browser drops the WebGL context, detect it, recover in place, and let the player continue —
|
|
7
7
|
no application restart, no reload, no lost session state.
|
|
8
8
|
|
|
9
|
-
**Status:
|
|
10
|
-
|
|
9
|
+
**Status: superseded, kept as the record.** Phases 0–3 were implemented and verified against the
|
|
10
|
+
renderer described here; that renderer — three.js r136 on WebGL2 — has since been removed from the
|
|
11
|
+
repo, and Shade (WebGPU) replaced it. Phases 4–6 (§11) will not be done as written: Shade does not
|
|
12
|
+
recover a lost device at all — `Renderer.on.contextRestored` is documented as never firing, and the
|
|
13
|
+
response to a loss is a message and a reload (`ShadeDeviceFailure.device_lost`) — so the in-place
|
|
14
|
+
recovery this document is about has no successor to port it to. Most links below point into a tree
|
|
15
|
+
that no longer holds these files. Claims are tagged **[src]** (read from three.js / meep source) or
|
|
16
|
+
**[measured]** (observed in the browser harness, §10).
|
|
11
17
|
|
|
12
18
|
---
|
|
13
19
|
|
|
@@ -110,18 +116,27 @@ produces the prefiltered radiance; `set_environment_texture` adds the skybox on
|
|
|
110
116
|
re-bakes and disposes the previous target. `load_and_set_cubemap_v0` now loads the source and hands it
|
|
111
117
|
over instead of baking behind the engine's back.
|
|
112
118
|
|
|
113
|
-
### 4.3 Raw GL handles and residency bookkeeping — library tier,
|
|
119
|
+
### 4.3 Raw GL handles and residency bookkeeping — library tier, since deleted
|
|
114
120
|
|
|
115
|
-
These
|
|
116
|
-
debt rather than shipping blockers (Phase 6)
|
|
121
|
+
These were `meep` public surface but were not reachable from `makeMirEngineConfig`, so they were
|
|
122
|
+
correctness debt rather than shipping blockers (Phase 6). Every one of them went with the WebGL
|
|
123
|
+
renderer, so the paths are recorded as they stood rather than linked:
|
|
117
124
|
|
|
118
|
-
| Subsystem | What breaks | File |
|
|
125
|
+
| Subsystem | What breaks | File, as of 2026-07-30 |
|
|
119
126
|
| --- | --- | --- |
|
|
120
|
-
| Virtual texture | page atlas written with `copyTextureToTexture`; CPU residency map still claims pages are valid → garbage tiles forever |
|
|
121
|
-
| `WebGLTextureAtlas` | same pattern |
|
|
122
|
-
| Node-based particles | raw `gl.createBuffer()` handles + cached `gl`, no invalidation |
|
|
123
|
-
| Hi-Z occlusion | readback of a lost target yields zeroes → whole-frame visibility misclassification |
|
|
124
|
-
| Impostors | baked atlases are GPU-only |
|
|
127
|
+
| Virtual texture | page atlas written with `copyTextureToTexture`; CPU residency map still claims pages are valid → garbage tiles forever | `src/engine/graphics/texture/virtual/VirtualTexturePage.js:389` |
|
|
128
|
+
| `WebGLTextureAtlas` | same pattern | `src/engine/graphics/texture/atlas/gpu/WebGLTextureAtlas.js:178` |
|
|
129
|
+
| Node-based particles | raw `gl.createBuffer()` handles + cached `gl`, no invalidation | `src/engine/graphics/particles/node-based/simulation/GLDataBuffer.js:48`, `TransformFeedback.js:414` |
|
|
130
|
+
| Hi-Z occlusion | readback of a lost target yields zeroes → whole-frame visibility misclassification | `src/engine/graphics/render/visibility/hiz/query/BatchOcclusionQuery.js:149` |
|
|
131
|
+
| Impostors | baked atlases are GPU-only | `src/engine/graphics/impostors/octahedral/ImpostorBaker.js` |
|
|
132
|
+
|
|
133
|
+
Virtual texturing is the one row with a live successor — `shade/renderer/texture/virtual/`
|
|
134
|
+
(`VirtualTextureManager` / `VTPageTable` / `VTPhysicalCache`), which keeps a CPU mirror of residency
|
|
135
|
+
just as the old stack did. The concern still does not carry over, because it is a *restore* hazard:
|
|
136
|
+
it needs a frame drawn after the device comes back, reading a residency map that outlived the loss.
|
|
137
|
+
Shade never draws that frame — `Renderer.on.contextRestored` is documented as never firing — and the
|
|
138
|
+
VT stack accordingly has no loss, restore or generation hook anywhere in it. There is nothing to
|
|
139
|
+
re-point this row at.
|
|
125
140
|
|
|
126
141
|
### 4.4 Secondary contexts — Phase 4
|
|
127
142
|
|
|
@@ -442,5 +457,7 @@ re-attach `viewport.el` / `graphics.domElement` / styles / size, and re-run fram
|
|
|
442
457
|
disposal of the old targets. The monitor already supports it — `attach()` resets the loss budget and returns
|
|
443
458
|
to `Live` while keeping the generation counter monotonic. Only worth building on evidence.
|
|
444
459
|
|
|
445
|
-
**Phase 6 (
|
|
446
|
-
|
|
460
|
+
**Phase 6 (closed) — library tier.** Not done, and will not be: every subsystem in §4.3 was deleted
|
|
461
|
+
along with the WebGL renderer. The only one with a successor is virtual texturing, and residency
|
|
462
|
+
invalidation does not carry over to it — Shade does not restore a lost device, so there is no frame in
|
|
463
|
+
which a stale residency map could be read (§4.3).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collect what every animation driver is playing on an entity, in the form the
|
|
3
|
+
* CPU pose evaluator takes.
|
|
4
|
+
*
|
|
5
|
+
* Both drivers are asked because either may be the one driving it — a combat
|
|
6
|
+
* unit runs a state machine, a building runs a clip list — and an entity has
|
|
7
|
+
* one of them, so the two sets do not overlap in practice. What they hand back
|
|
8
|
+
* is one entry per clip of the model, silent clips included, because that is
|
|
9
|
+
* what the GPU's accumulator is summing.
|
|
10
|
+
*
|
|
11
|
+
* A free function rather than a private helper of
|
|
12
|
+
* {@link query_entity_node_world_pose} because M3 gave it a second caller:
|
|
13
|
+
* cloth's rig path needs the anchor joint's world pose on the CPU for exactly
|
|
14
|
+
* the reason gameplay needs a socket's, and computing it from a different set
|
|
15
|
+
* of playbacks would put the garment somewhere the socket is not.
|
|
16
|
+
*
|
|
17
|
+
* @param {PosePlayback[]} target appended to; the caller owns its length
|
|
18
|
+
* @param {EntityManager} entity_manager
|
|
19
|
+
* @param {number} entity
|
|
20
|
+
* @returns {void}
|
|
21
|
+
*
|
|
22
|
+
* @author Alex Goldring
|
|
23
|
+
* @copyright Company Named Limited (c) 2026
|
|
24
|
+
*/
|
|
25
|
+
export function collect_entity_playbacks(target: PosePlayback[], entity_manager: EntityManager, entity: number): void;
|
|
26
|
+
//# sourceMappingURL=collect_entity_playbacks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect_entity_playbacks.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/pose/collect_entity_playbacks.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,iDARW,cAAc,yCAEd,MAAM,GACJ,IAAI,CAiBhB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AnimationGraphSystem } from "../AnimationGraphSystem.js";
|
|
2
|
+
import { AnimationSystem } from "../AnimationSystem.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Collect what every animation driver is playing on an entity, in the form the
|
|
6
|
+
* CPU pose evaluator takes.
|
|
7
|
+
*
|
|
8
|
+
* Both drivers are asked because either may be the one driving it — a combat
|
|
9
|
+
* unit runs a state machine, a building runs a clip list — and an entity has
|
|
10
|
+
* one of them, so the two sets do not overlap in practice. What they hand back
|
|
11
|
+
* is one entry per clip of the model, silent clips included, because that is
|
|
12
|
+
* what the GPU's accumulator is summing.
|
|
13
|
+
*
|
|
14
|
+
* A free function rather than a private helper of
|
|
15
|
+
* {@link query_entity_node_world_pose} because M3 gave it a second caller:
|
|
16
|
+
* cloth's rig path needs the anchor joint's world pose on the CPU for exactly
|
|
17
|
+
* the reason gameplay needs a socket's, and computing it from a different set
|
|
18
|
+
* of playbacks would put the garment somewhere the socket is not.
|
|
19
|
+
*
|
|
20
|
+
* @param {PosePlayback[]} target appended to; the caller owns its length
|
|
21
|
+
* @param {EntityManager} entity_manager
|
|
22
|
+
* @param {number} entity
|
|
23
|
+
* @returns {void}
|
|
24
|
+
*
|
|
25
|
+
* @author Alex Goldring
|
|
26
|
+
* @copyright Company Named Limited (c) 2026
|
|
27
|
+
*/
|
|
28
|
+
export function collect_entity_playbacks(target, entity_manager, entity) {
|
|
29
|
+
const graphs = entity_manager.getSystem(AnimationGraphSystem);
|
|
30
|
+
|
|
31
|
+
if (graphs !== null) {
|
|
32
|
+
graphs.write_pose_playbacks(target, entity);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const clips = entity_manager.getSystem(AnimationSystem);
|
|
36
|
+
|
|
37
|
+
if (clips !== null) {
|
|
38
|
+
clips.write_pose_playbacks(target, entity);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query_entity_node_world_pose.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/pose/query_entity_node_world_pose.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query_entity_node_world_pose.d.ts","sourceRoot":"","sources":["../../../../../src/engine/graphics3/pose/query_entity_node_world_pose.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,yGANW,MAAM,aACN,MAAM,GACJ,OAAO,CAwCnB"}
|
|
@@ -1,101 +1,74 @@
|
|
|
1
|
-
import { assert } from "../../../core/assert.js";
|
|
2
|
-
import { PosePlayback } from "../../../shade/renderer/animation/pose/PosePlayback.js";
|
|
3
|
-
import { pose_evaluate_world } from "../../../shade/renderer/animation/pose/pose_evaluate_world.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @param {
|
|
32
|
-
* @param {
|
|
33
|
-
* @param {
|
|
34
|
-
* @
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
assert.defined(
|
|
41
|
-
assert.
|
|
42
|
-
assert.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Collect what every animation driver is playing on the entity.
|
|
79
|
-
*
|
|
80
|
-
* Both are asked because either may be the one driving it — a combat unit runs a state machine, a
|
|
81
|
-
* building runs a clip list — and an entity has one of them, so the two sets do not overlap in
|
|
82
|
-
* practice. What they hand back is one entry per clip of the model, silent clips included, because
|
|
83
|
-
* that is what the GPU's accumulator is summing.
|
|
84
|
-
*
|
|
85
|
-
* @param {PosePlayback[]} target
|
|
86
|
-
* @param {EntityManager} entity_manager
|
|
87
|
-
* @param {number} entity
|
|
88
|
-
*/
|
|
89
|
-
function write_playbacks(target, entity_manager, entity) {
|
|
90
|
-
const graphs = entity_manager.getSystem(AnimationGraphSystem);
|
|
91
|
-
|
|
92
|
-
if (graphs !== null) {
|
|
93
|
-
graphs.write_pose_playbacks(target, entity);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const clips = entity_manager.getSystem(AnimationSystem);
|
|
97
|
-
|
|
98
|
-
if (clips !== null) {
|
|
99
|
-
clips.write_pose_playbacks(target, entity);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
2
|
+
import { PosePlayback } from "../../../shade/renderer/animation/pose/PosePlayback.js";
|
|
3
|
+
import { pose_evaluate_world } from "../../../shade/renderer/animation/pose/pose_evaluate_world.js";
|
|
4
|
+
import { MeshSystem } from "../MeshSystem.js";
|
|
5
|
+
import { collect_entity_playbacks } from "./collect_entity_playbacks.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The clip set handed to the evaluator, rebuilt per call from the systems' own entries. Nothing in
|
|
9
|
+
* here outlives the call — the query is on a per-frame path and allocates nothing.
|
|
10
|
+
*
|
|
11
|
+
* @type {PosePlayback[]}
|
|
12
|
+
*/
|
|
13
|
+
const PLAYBACKS = [];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Where a named part of an entity's model is, in world space.
|
|
17
|
+
*
|
|
18
|
+
* This is the question gameplay asks of an animated model and the only sanctioned way to ask it:
|
|
19
|
+
* where does this projectile leave from, where does that effect anchor, where does the floating UI
|
|
20
|
+
* hang. **The answer is computed, never read back** — GPU readback is a frame late and asynchronous,
|
|
21
|
+
* so an outcome that depended on it would depend on frame pacing, and determinism and replay would
|
|
22
|
+
* go with it: no GPU readback on a gameplay-affecting path.
|
|
23
|
+
*
|
|
24
|
+
* The pose is {@link pose_evaluate_world} over the clips the animation systems are driving: a pure
|
|
25
|
+
* function of (clip set, time, weights), off the same clock the renderer is written from, which is
|
|
26
|
+
* what keeps a socket on the mesh that is drawn.
|
|
27
|
+
*
|
|
28
|
+
* The result carries both its matrix and its components.
|
|
29
|
+
*
|
|
30
|
+
* @param {Transform64} result
|
|
31
|
+
* @param {EntityManager} entity_manager
|
|
32
|
+
* @param {number} entity
|
|
33
|
+
* @param {string} node_name name the asset gave the node — a bone, a socket's bone, an effector
|
|
34
|
+
* @returns {boolean} `false` when there is no such node to answer about: no mesh system is
|
|
35
|
+
* registered, the model has not loaded yet, the entity has none, or the name is not in it. None of
|
|
36
|
+
* the four is an error
|
|
37
|
+
*/
|
|
38
|
+
export function query_entity_node_world_pose(result, entity_manager, entity, node_name) {
|
|
39
|
+
assert.defined(result, 'result');
|
|
40
|
+
assert.defined(entity_manager, 'entity_manager');
|
|
41
|
+
assert.isNonNegativeInteger(entity, 'entity');
|
|
42
|
+
assert.isString(node_name, 'node_name');
|
|
43
|
+
|
|
44
|
+
const meshes = entity_manager.getSystem(MeshSystem);
|
|
45
|
+
|
|
46
|
+
if (meshes === null) {
|
|
47
|
+
// nothing draws models here, so nothing holds one to answer about
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const instance = meshes.instance_of(entity);
|
|
52
|
+
|
|
53
|
+
if (instance === null) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const node = instance.nodes.get(node_name);
|
|
58
|
+
|
|
59
|
+
if (node === undefined) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const playbacks = PLAYBACKS;
|
|
64
|
+
|
|
65
|
+
playbacks.length = 0;
|
|
66
|
+
|
|
67
|
+
collect_entity_playbacks(playbacks, entity_manager, entity);
|
|
68
|
+
|
|
69
|
+
pose_evaluate_world(result, node, playbacks);
|
|
70
|
+
|
|
71
|
+
playbacks.length = 0;
|
|
72
|
+
|
|
73
|
+
return true;
|
|
74
|
+
}
|