@woosh/meep-engine 3.24.0 → 3.25.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/engine/graphics3/PickingSystem.d.ts +3 -3
- package/src/engine/graphics3/PickingSystem.d.ts.map +1 -1
- package/src/engine/graphics3/PickingSystem.js +52 -55
- package/src/engine/graphics3/shader_picking_gather.d.ts +40 -0
- package/src/engine/graphics3/shader_picking_gather.d.ts.map +1 -0
- package/src/engine/graphics3/shader_picking_gather.js +120 -0
- package/src/engine/physics/cloth/MEASUREMENTS.md +1050 -0
- package/src/engine/physics/cloth/PLAN.md +411 -49
- package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts +52 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothColliderSerializationAdapter.js +70 -0
- package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts +12 -3
- package/src/engine/physics/cloth/ecs/ClothDynamics.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothDynamics.js +340 -331
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +36 -22
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +38 -23
- package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts +84 -0
- package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothSerializationAdapter.js +141 -0
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +51 -82
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +81 -869
- package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts +48 -0
- package/src/engine/physics/cloth/ecs/ClothWorkerCore.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothWorkerCore.js +107 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +286 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.js +1104 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +182 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +562 -0
- package/src/engine/physics/cloth/ecs/cloth.worker.d.ts +2 -0
- package/src/engine/physics/cloth/ecs/cloth.worker.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth.worker.js +12 -0
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +2 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +58 -0
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +341 -271
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +20 -2
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +39 -15
- package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts +29 -0
- package/src/engine/physics/cloth/ecs/cloth_worker_protocol.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_worker_protocol.js +78 -0
- package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts +17 -0
- package/src/engine/physics/cloth/ecs/makeClothWorker.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/makeClothWorker.js +18 -0
- package/src/engine/physics/cloth/playground/README.md +73 -2
- package/src/engine/physics/cloth/playground/wind.html +166 -0
- package/src/engine/physics/cloth/playground/wind_build.d.ts +81 -0
- package/src/engine/physics/cloth/playground/wind_build.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/wind_build.js +141 -0
- package/src/engine/physics/cloth/playground/wind_main.d.ts +2 -0
- package/src/engine/physics/cloth/playground/wind_main.d.ts.map +1 -0
- package/src/engine/physics/cloth/playground/wind_main.js +681 -0
- package/src/engine/physics/cloth/solver/ClothState.d.ts +134 -79
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +273 -12
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +33 -0
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +34 -0
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +21 -2
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +173 -4
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +40 -0
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +284 -0
- package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts +107 -0
- package/src/engine/physics/cloth/solver/cloth_wind_accelerate.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_wind_accelerate.js +263 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +88 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.js +100 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +85 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.js +182 -0
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +79 -0
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/ClothFluidWind.js +210 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +101 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +290 -0
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/device/mock/texture_copy.d.ts.map +1 -1
- package/src/shade/device/mock/texture_copy.js +28 -0
- package/src/shade/playground/vgeo_runtime/README.md +94 -0
- package/src/shade/playground/vgeo_runtime/index.html +62 -0
- package/src/shade/playground/vgeo_runtime/main.d.ts +2 -0
- package/src/shade/playground/vgeo_runtime/main.d.ts.map +1 -0
- package/src/shade/playground/vgeo_runtime/main.js +399 -0
- package/src/shade/playground/vgeo_viewer/sample_asset.js +1 -1
- package/src/shade/renderer/camera/Camera.d.ts +14 -0
- package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
- package/src/shade/renderer/camera/Camera.js +7 -1
- package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GEOMETRY_METADATA_STRUCT.js +16 -1
- package/src/shade/renderer/geometry/GPUGeometryManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryManager.js +29 -9
- package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts +10 -0
- package/src/shade/renderer/geometry/GPUGeometryMetadata.d.ts.map +1 -1
- package/src/shade/renderer/geometry/GPUGeometryMetadata.js +13 -0
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +46 -18
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +70 -22
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +97 -19
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +12 -2
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +14 -3
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts +2 -2
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/vgeo_assemble_pages.js +124 -6
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts +22 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/build/vgeo_page_node_count.js +53 -0
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts +8 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/VGeoWriteOptions.js +8 -1
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/header/VGEO_FEATURE_IGNORABLE_BOUNDED_PAGES.js +15 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts +54 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/format/page/VGEO_DEFAULT_PAGE_SIZE.js +53 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +13 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +14 -2
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +100 -0
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +113 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +5 -0
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +108 -0
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +23 -0
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +40 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts +228 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryPool.js +932 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +176 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +425 -0
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +241 -0
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +574 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts +120 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +674 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts +287 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VGeoRuntimeTables.js +976 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +42 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +96 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts +16 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_FLAG_CULL.js +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_PARAMS_STRUCT.js +83 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/VGEO_CUT_WORKGROUP_SIZE.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +160 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_collect.js +255 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_queue_prepare.js +80 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +144 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts +3 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +530 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts +39 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/cut/vgeo_cut_feedback_layout.js +54 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts +41 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_if_enabled.js +56 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts +49 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +328 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_OFFSET.js +51 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CLUSTER_ROW_WORDS.js +12 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT.js +99 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_CUT_STAT_COUNT.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_FEEDBACK_OFFSET.js +27 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_NONE.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_OFFSET.js +35 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GEOMETRY_ROW_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_FLAG_SELECTABLE.js +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_OFFSET.js +36 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_GROUP_ROW_WORDS.js +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_OFFSET.js +54 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_INSTANCE_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_LEAF_BIT.js +10 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts +7 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_OFFSET.js +30 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NODE_ROW_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_NO_CHILD_PAGE.js +12 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts +14 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_NONE.js +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts +11 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_OFFSET.js +61 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_PAGE_ROW_WORDS.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts +13 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_ITEM_WORDS.js +12 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts +9 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_QUEUE_TARGET_GROUP_BIT.js +8 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts +20 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/layout/VGEO_WANT_WORDS.js +19 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts +23 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +70 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts +18 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_block_words.js +25 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts +35 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_page_slot_words.js +41 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts +32 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_write_page_block.js +138 -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/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.js +9 -0
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +12 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +12 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +10 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +18 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
- package/src/shade/renderer/scene/GPUSceneContext.js +647 -594
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +22 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts +35 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.d.ts.map +1 -0
- package/src/shade/renderer/shader/chunk/geometry/mat3/chunk_mat3_singular_values.js +91 -0
- package/src/engine/graphics3/instantiate_scene_bundle.d.ts +0 -54
- package/src/engine/graphics3/instantiate_scene_bundle.d.ts.map +0 -1
- package/src/engine/graphics3/shade_node_to_entity_composition.d.ts +0 -39
- package/src/engine/graphics3/shade_node_to_entity_composition.d.ts.map +0 -1
- package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts +0 -35
- package/src/shade/renderer/animation/compute_skin_world_bounds.d.ts.map +0 -1
- package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts +0 -96
- package/src/shade/renderer/animation/compute_skinned_mesh_clip_bounding_sphere.d.ts.map +0 -1
- package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts +0 -20
- package/src/shade/renderer/animation/pose/pose_evaluate_world.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_bind_transform.d.ts +0 -25
- package/src/shade/renderer/animation/skin_bind_transform.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_frame_defect.d.ts +0 -34
- package/src/shade/renderer/animation/skin_frame_defect.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_joint_matrix.d.ts +0 -24
- package/src/shade/renderer/animation/skin_joint_matrix.d.ts.map +0 -1
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts +0 -70
- package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +0 -1
- package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts +0 -96
- package/src/shade/renderer/buffer/table/GPUReadbackStagingRing.d.ts.map +0 -1
- package/src/shade/renderer/scene/InstanceBatch.d.ts +0 -92
- package/src/shade/renderer/scene/InstanceBatch.d.ts.map +0 -1
- package/src/shade/renderer/scene/Mesh.d.ts +0 -55
- package/src/shade/renderer/scene/Mesh.d.ts.map +0 -1
- package/src/shade/renderer/scene/Node3D.d.ts +0 -159
- package/src/shade/renderer/scene/Node3D.d.ts.map +0 -1
- package/src/shade/renderer/scene/Node3DDirtyList.d.ts +0 -59
- package/src/shade/renderer/scene/Node3DDirtyList.d.ts.map +0 -1
- package/src/shade/renderer/scene/SceneNodeBinding.d.ts +0 -52
- package/src/shade/renderer/scene/SceneNodeBinding.d.ts.map +0 -1
- package/src/shade/renderer/scene/SkinnedMesh.d.ts +0 -27
- package/src/shade/renderer/scene/SkinnedMesh.d.ts.map +0 -1
- package/src/shade/renderer/scene/TransformAuthority.d.ts +0 -19
- package/src/shade/renderer/scene/TransformAuthority.d.ts.map +0 -1
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
import { ResourceAccessKind } from "../../../../core/model/ResourceAccessKind.js";
|
|
2
|
+
import { ResourceAccessSpecification } from "../../../../core/model/ResourceAccessSpecification.js";
|
|
3
|
+
import { WorkerSystem } from "../../../ecs/async/WorkerSystem.js";
|
|
4
|
+
import {
|
|
5
|
+
TransformAttachment
|
|
6
|
+
} from "../../../ecs/transform-attachment/TransformAttachment.js";
|
|
7
|
+
import { Transform64 } from "../../../ecs/transform/Transform64.js";
|
|
8
|
+
import { ClothStepParam } from "../solver/cloth_step_instance.js";
|
|
9
|
+
import { Cloth } from "./Cloth.js";
|
|
10
|
+
import { ClothCollider } from "./ClothCollider.js";
|
|
11
|
+
import { ClothExclude } from "./ClothExclude.js";
|
|
12
|
+
import { ClothRig } from "./ClothRig.js";
|
|
13
|
+
import { ClothWorld } from "./ClothWorld.js";
|
|
14
|
+
import {
|
|
15
|
+
ClothCommand,
|
|
16
|
+
cloth_command_offset,
|
|
17
|
+
cloth_command_word_count
|
|
18
|
+
} from "./cloth_worker_protocol.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Default ceiling on simultaneously stepped cloths. Sizes the command region,
|
|
22
|
+
* which is allocated once at startup and cannot grow.
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
const DEFAULT_MAX_CLOTH_COUNT = 32;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Drop-in alternative to {@link ClothSystem} that runs the solve on a worker
|
|
29
|
+
* thread.
|
|
30
|
+
*
|
|
31
|
+
* ## What moves, and what does not
|
|
32
|
+
*
|
|
33
|
+
* A cloth's fixed step is "work that needs the world" followed by "arithmetic
|
|
34
|
+
* over typed arrays", and `MEASUREMENTS.md` §7 puts 69% of the frame in the
|
|
35
|
+
* stretch rows alone — so the split is where §12 drew it:
|
|
36
|
+
*
|
|
37
|
+
* - **main thread**: seeding, the anchor's pose, the local-frame carry, the
|
|
38
|
+
* leash centres, the collider broadphase, the sleep test and the write-back.
|
|
39
|
+
* All of it reads components, walks hierarchies or queries an index, and
|
|
40
|
+
* none of it is where the time goes.
|
|
41
|
+
* - **worker**: `cloth_step_instance(state, exclusions, params, offset)` — the
|
|
42
|
+
* damping, the contact search, the self-collision pair search, the solve and
|
|
43
|
+
* the velocity clamp.
|
|
44
|
+
*
|
|
45
|
+
* Both sides call {@link ClothWorld}, and both hand `cloth_step_instance` the
|
|
46
|
+
* *same* `Float64` parameter block — {@link ClothSystem} in a private scratch
|
|
47
|
+
* array, this one in a slice of the shared command region. Identical code over
|
|
48
|
+
* identical data in an identical order, so results are bit-for-bit equal to
|
|
49
|
+
* {@link ClothSystem}'s (`WorkerClothSystem.spec.js` holds that as a standing
|
|
50
|
+
* gate).
|
|
51
|
+
*
|
|
52
|
+
* Nothing is copied. A cloth's `ClothState` lives in a {@link SharedArrayBuffer}
|
|
53
|
+
* and the worker steps it in place; a completed step is published by advancing a
|
|
54
|
+
* single atomic.
|
|
55
|
+
*
|
|
56
|
+
* ## Using it
|
|
57
|
+
*
|
|
58
|
+
* ```js
|
|
59
|
+
* entityManager.addSystem(new WorkerClothSystem({ worker_factory: makeClothWorker }));
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* There is no per-component opt-in, unlike {@link WorkerFluidSystem}'s
|
|
63
|
+
* `field.shared_memory`: a cloth's state does not exist until the cloth seeds,
|
|
64
|
+
* and seeding is this system's own work, so it simply builds them shared.
|
|
65
|
+
*
|
|
66
|
+
* Requires a cross-origin isolated page (`Cross-Origin-Opener-Policy:
|
|
67
|
+
* same-origin` + `Cross-Origin-Embedder-Policy: require-corp`) — without it
|
|
68
|
+
* `SharedArrayBuffer` does not exist and startup throws.
|
|
69
|
+
*
|
|
70
|
+
* ## Ownership — the one behavioural difference
|
|
71
|
+
*
|
|
72
|
+
* {@link ClothSystem} leaves every cloth consistent at all times. Here a cloth's
|
|
73
|
+
* `ClothState` is **owned by the worker** from the moment this system's
|
|
74
|
+
* `fixedUpdate` dispatches until the next tick joins the result. Concretely:
|
|
75
|
+
*
|
|
76
|
+
* - The `Transform64`/`Node3D` poses this system writes are *not* affected:
|
|
77
|
+
* the write-back happens at join, on this thread, inside the fixed pass. A
|
|
78
|
+
* renderer reading a cloth's transforms reads them exactly as it always did.
|
|
79
|
+
* - What must not be read outside the fixed pass is `ClothInstance#state` —
|
|
80
|
+
* particle positions, velocities, the contact slots. Nothing in the engine
|
|
81
|
+
* does; the playgrounds' diagnostics run inside the fixed pass.
|
|
82
|
+
* - {@link ClothColliderSystem} is refreshed from inside this system's own
|
|
83
|
+
* `collect`, as it is under {@link ClothSystem}, so the index is never read
|
|
84
|
+
* while a step is in flight.
|
|
85
|
+
*
|
|
86
|
+
* Two further differences from {@link ClothSystem}:
|
|
87
|
+
*
|
|
88
|
+
* - Results lag by one tick: the pose written at tick `T` is step `T - 1`'s.
|
|
89
|
+
* The *sequence* of states is unchanged — it is observed one tick later.
|
|
90
|
+
* - A newly seeded cloth is not stepped until the worker acknowledges its
|
|
91
|
+
* registration (a cold-plane round trip, so at least one tick and in
|
|
92
|
+
* practice a few). Until then it is not advanced either — not stepped, not
|
|
93
|
+
* carried across anchor motion, not written back — which is what keeps the
|
|
94
|
+
* step *sequence* identical to {@link ClothSystem}'s rather than merely
|
|
95
|
+
* similar. A garment therefore holds its bind pose for a few ticks after it
|
|
96
|
+
* spawns, and a re-seed does the same, because a re-seed builds a new buffer
|
|
97
|
+
* and the worker has to be told about it.
|
|
98
|
+
*
|
|
99
|
+
* @author Alex Goldring
|
|
100
|
+
* @copyright Company Named Limited (c) 2026
|
|
101
|
+
*/
|
|
102
|
+
export class WorkerClothSystem extends WorkerSystem {
|
|
103
|
+
|
|
104
|
+
dependencies = [Cloth, Transform64];
|
|
105
|
+
|
|
106
|
+
components_used = [
|
|
107
|
+
ResourceAccessSpecification.from(Cloth, ResourceAccessKind.Read),
|
|
108
|
+
ResourceAccessSpecification.from(Transform64, ResourceAccessKind.Read | ResourceAccessKind.Write),
|
|
109
|
+
ResourceAccessSpecification.from(TransformAttachment, ResourceAccessKind.Read | ResourceAccessKind.Write),
|
|
110
|
+
ResourceAccessSpecification.from(ClothExclude, ResourceAccessKind.Read),
|
|
111
|
+
ResourceAccessSpecification.from(ClothCollider, ResourceAccessKind.Read),
|
|
112
|
+
ResourceAccessSpecification.from(ClothRig, ResourceAccessKind.Read)
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The cloths, and everything about stepping one that is not arithmetic.
|
|
117
|
+
* Shared with {@link ClothSystem}, which is what makes the two systems one
|
|
118
|
+
* implementation.
|
|
119
|
+
* @type {ClothWorld}
|
|
120
|
+
*/
|
|
121
|
+
world = new ClothWorld();
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @type {(() => Worker)|null}
|
|
125
|
+
*/
|
|
126
|
+
#worker_factory = null;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @type {number}
|
|
130
|
+
*/
|
|
131
|
+
#max_cloth_count = DEFAULT_MAX_CLOTH_COUNT;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The cold-plane message that announced each registered cloth, the state it
|
|
135
|
+
* announced, and whether the worker has acknowledged it.
|
|
136
|
+
*
|
|
137
|
+
* Keyed by instance, and carrying the `ClothState` rather than trusting the
|
|
138
|
+
* instance still to hold it: a re-seed replaces the state with a new buffer,
|
|
139
|
+
* and the registration the worker holds then names memory nobody writes to
|
|
140
|
+
* any more. Comparing identity is how that is noticed without a dirty flag.
|
|
141
|
+
* @type {Map<ClothInstance, {id: number, sequence: number, state: ClothState, acknowledged: boolean}>}
|
|
142
|
+
*/
|
|
143
|
+
#registrations = new Map();
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Cloths announced but not yet acknowledged.
|
|
147
|
+
* @type {ClothInstance[]}
|
|
148
|
+
*/
|
|
149
|
+
#pending = [];
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Cloths dispatched at the tick now in flight, in nomination order — the
|
|
153
|
+
* ones {@link apply} will finish.
|
|
154
|
+
* @type {ClothInstance[]}
|
|
155
|
+
*/
|
|
156
|
+
#dispatched = [];
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @type {number}
|
|
160
|
+
*/
|
|
161
|
+
#next_cloth_id = 1;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Latches the max_cloth_count overflow report so a persistent
|
|
165
|
+
* misconfiguration warns once instead of once per tick.
|
|
166
|
+
* @type {boolean}
|
|
167
|
+
*/
|
|
168
|
+
#cloth_overflow_reported = false;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* @param {object} options
|
|
172
|
+
* @param {() => Worker} options.worker_factory spawns the worker. Supplied
|
|
173
|
+
* rather than hard-coded because the spawn expression needs
|
|
174
|
+
* `import.meta.url`, which cannot be parsed by the CommonJS transform
|
|
175
|
+
* the test runner uses — see `makeClothWorker.js`.
|
|
176
|
+
* @param {number} [options.max_cloth_count] ceiling on simultaneously
|
|
177
|
+
* stepped cloths; sizes the fixed command region.
|
|
178
|
+
*/
|
|
179
|
+
constructor({ worker_factory, max_cloth_count = DEFAULT_MAX_CLOTH_COUNT } = {}) {
|
|
180
|
+
super();
|
|
181
|
+
|
|
182
|
+
this.#worker_factory = worker_factory;
|
|
183
|
+
this.#max_cloth_count = max_cloth_count;
|
|
184
|
+
|
|
185
|
+
this.world.shared_state = true;
|
|
186
|
+
|
|
187
|
+
this.command_word_count = cloth_command_word_count(max_cloth_count);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* World gravity, m/s². Rotated into each cloth's local frame per step.
|
|
192
|
+
* @returns {Float64Array}
|
|
193
|
+
*/
|
|
194
|
+
get gravity() {
|
|
195
|
+
return this.world.gravity;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @param {Float64Array} value
|
|
200
|
+
*/
|
|
201
|
+
set gravity(value) {
|
|
202
|
+
this.world.gravity = value;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Where the air comes from — see {@link ClothWorld#wind}. Sampled on **this**
|
|
207
|
+
* thread even under the worker, because a fluid field cannot cross and its
|
|
208
|
+
* answer can: `cloth_sample_air.js` is the argument, and it lands in a region
|
|
209
|
+
* of the cloth's own shared buffer.
|
|
210
|
+
* @returns {AbstractClothWind|null}
|
|
211
|
+
*/
|
|
212
|
+
get wind() {
|
|
213
|
+
return this.world.wind;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @param {AbstractClothWind|null} value
|
|
218
|
+
*/
|
|
219
|
+
set wind(value) {
|
|
220
|
+
this.world.wind = value;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @returns {ClothInstance[]}
|
|
225
|
+
*/
|
|
226
|
+
get instances() {
|
|
227
|
+
return this.world.instances;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @returns {{instance_of: function(number): (PrefabInstance|null)}|null}
|
|
232
|
+
*/
|
|
233
|
+
get models() {
|
|
234
|
+
return this.world.models;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @param {{instance_of: function(number): (PrefabInstance|null)}|null} value
|
|
239
|
+
*/
|
|
240
|
+
set models(value) {
|
|
241
|
+
this.world.models = value;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @returns {Worker}
|
|
246
|
+
*/
|
|
247
|
+
createWorker() {
|
|
248
|
+
if (typeof this.#worker_factory !== "function") {
|
|
249
|
+
throw new Error(
|
|
250
|
+
"WorkerClothSystem requires a worker factory:"
|
|
251
|
+
+ " new WorkerClothSystem({ worker_factory: makeClothWorker })"
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return this.#worker_factory();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {EntityManager} entityManager
|
|
260
|
+
* @returns {Promise<void>}
|
|
261
|
+
*/
|
|
262
|
+
async startup(entityManager) {
|
|
263
|
+
this.world.attach(entityManager);
|
|
264
|
+
|
|
265
|
+
await super.startup(entityManager);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @param {EntityManager} entityManager
|
|
270
|
+
* @returns {Promise<void>}
|
|
271
|
+
*/
|
|
272
|
+
async shutdown(entityManager) {
|
|
273
|
+
await super.shutdown(entityManager);
|
|
274
|
+
|
|
275
|
+
this.#registrations.clear();
|
|
276
|
+
this.#pending.length = 0;
|
|
277
|
+
this.#dispatched.length = 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @param {Cloth} cloth
|
|
282
|
+
* @param {Transform64} transform
|
|
283
|
+
* @param {number} entity
|
|
284
|
+
*/
|
|
285
|
+
link(cloth, transform, entity) {
|
|
286
|
+
this.world.link(cloth, transform, entity);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* @param {Cloth} cloth
|
|
291
|
+
* @param {Transform64} transform
|
|
292
|
+
* @param {number} entity
|
|
293
|
+
*/
|
|
294
|
+
unlink(cloth, transform, entity) {
|
|
295
|
+
const instance = this.world.unlink(entity);
|
|
296
|
+
|
|
297
|
+
if (instance !== undefined) {
|
|
298
|
+
this.#retire(instance);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Throw away a cloth's binding so the next step walks its subtree again.
|
|
304
|
+
* @param {number} entity
|
|
305
|
+
* @returns {void}
|
|
306
|
+
*/
|
|
307
|
+
reseed(entity) {
|
|
308
|
+
this.world.reseed(entity);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Wake a sleeping cloth.
|
|
313
|
+
* @param {number} entity
|
|
314
|
+
* @returns {void}
|
|
315
|
+
*/
|
|
316
|
+
wake(entity) {
|
|
317
|
+
this.world.wake(entity);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @param {number} entity
|
|
322
|
+
* @returns {ClothInstance|undefined}
|
|
323
|
+
*/
|
|
324
|
+
instanceOf(entity) {
|
|
325
|
+
return this.world.instanceOf(entity);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @returns {boolean} whether cloth *particle state* may currently be read
|
|
330
|
+
* from the main thread. False while a step is in flight. The poses
|
|
331
|
+
* on the scene are always readable — they are written at join.
|
|
332
|
+
*/
|
|
333
|
+
get is_state_readable() {
|
|
334
|
+
return !this.is_step_in_flight;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* @param {Float64Array} command
|
|
339
|
+
* @param {number} tick
|
|
340
|
+
* @param {number} time_delta_seconds
|
|
341
|
+
* @returns {boolean}
|
|
342
|
+
*/
|
|
343
|
+
collect(command, tick, time_delta_seconds) {
|
|
344
|
+
const em = this.entityManager;
|
|
345
|
+
|
|
346
|
+
if (em === null) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const ecd = em.dataset;
|
|
351
|
+
|
|
352
|
+
if (ecd === null || ecd === undefined) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
this.#promote_acknowledged_cloths();
|
|
357
|
+
|
|
358
|
+
const world = this.world;
|
|
359
|
+
|
|
360
|
+
world.begin(ecd, time_delta_seconds);
|
|
361
|
+
|
|
362
|
+
const instances = world.instances;
|
|
363
|
+
|
|
364
|
+
const max_cloth_count = this.#max_cloth_count;
|
|
365
|
+
|
|
366
|
+
const dispatched = this.#dispatched;
|
|
367
|
+
|
|
368
|
+
dispatched.length = 0;
|
|
369
|
+
|
|
370
|
+
let cloth_count = 0;
|
|
371
|
+
|
|
372
|
+
for (let i = 0; i < instances.length; i++) {
|
|
373
|
+
const instance = instances[i];
|
|
374
|
+
|
|
375
|
+
if (!world.ensure_seeded(instance, ecd, time_delta_seconds)) {
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const registration = this.#registrations.get(instance);
|
|
380
|
+
|
|
381
|
+
if (registration === undefined || registration.state !== instance.state) {
|
|
382
|
+
// Either the cloth has just seeded, or a re-seed built it a new
|
|
383
|
+
// buffer. Announce the current one and wait — nominating memory
|
|
384
|
+
// the worker has not attached to is a protocol error, and
|
|
385
|
+
// advancing the cloth without stepping it would put its step
|
|
386
|
+
// sequence out of step with ClothSystem's for the rest of the
|
|
387
|
+
// run.
|
|
388
|
+
this.#register(instance);
|
|
389
|
+
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (!registration.acknowledged) {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (cloth_count === max_cloth_count) {
|
|
398
|
+
if (!this.#cloth_overflow_reported) {
|
|
399
|
+
this.#cloth_overflow_reported = true;
|
|
400
|
+
|
|
401
|
+
console.error(
|
|
402
|
+
`WorkerClothSystem: more live cloths than max_cloth_count (${max_cloth_count});`
|
|
403
|
+
+ ` the remainder will not be simulated. Raise max_cloth_count in the constructor.`
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const offset = cloth_command_offset(cloth_count);
|
|
411
|
+
|
|
412
|
+
if (!world.advance(instance, time_delta_seconds, command, offset)) {
|
|
413
|
+
// Asleep. §7 P5: not stepped, not written back, and costing
|
|
414
|
+
// nothing but its absence from this list.
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
command[offset + ClothStepParam.ID] = registration.id;
|
|
419
|
+
|
|
420
|
+
dispatched.push(instance);
|
|
421
|
+
|
|
422
|
+
cloth_count++;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (cloth_count === 0) {
|
|
426
|
+
// Nothing to do. Skipping the dispatch also keeps the fixed-step
|
|
427
|
+
// gate open, since there is no result to wait for.
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
command[ClothCommand.CLOTH_COUNT] = cloth_count;
|
|
432
|
+
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* The worker stepped each nominated cloth in place, so joining is the sleep
|
|
438
|
+
* test and the write-back — the half of `ClothSystem`'s loop that needs the
|
|
439
|
+
* scene rather than the arithmetic.
|
|
440
|
+
*
|
|
441
|
+
* @param {number} tick
|
|
442
|
+
*/
|
|
443
|
+
apply(tick) {
|
|
444
|
+
const ecd = this.entityManager.dataset;
|
|
445
|
+
|
|
446
|
+
if (ecd === null || ecd === undefined) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const dispatched = this.#dispatched;
|
|
451
|
+
|
|
452
|
+
const world = this.world;
|
|
453
|
+
|
|
454
|
+
for (let i = 0; i < dispatched.length; i++) {
|
|
455
|
+
const instance = dispatched[i];
|
|
456
|
+
|
|
457
|
+
if (!this.#registrations.has(instance)) {
|
|
458
|
+
// Unlinked between dispatch and join. Its entity is gone, so
|
|
459
|
+
// there is nothing to write the pose onto.
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
world.finish(instance, ecd);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
dispatched.length = 0;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Announce a cloth's current `ClothState` to the worker, retiring whatever
|
|
471
|
+
* it was registered with before.
|
|
472
|
+
*
|
|
473
|
+
* @param {ClothInstance} instance
|
|
474
|
+
* @private
|
|
475
|
+
*/
|
|
476
|
+
#register(instance) {
|
|
477
|
+
const state = instance.state;
|
|
478
|
+
|
|
479
|
+
if (!state.isSharedMemory()) {
|
|
480
|
+
// Not an assert: asserts are stripped from a production build, and a
|
|
481
|
+
// non-shared buffer does not fail loudly on its own — `postMessage`
|
|
482
|
+
// structured-clones it, both threads get a private copy of a cloth,
|
|
483
|
+
// and each simulates a garment the other cannot see. A cloth built
|
|
484
|
+
// through this system is always shared (`ClothWorld#shared_state`),
|
|
485
|
+
// so reaching here means someone handed it a world that is not.
|
|
486
|
+
throw new Error(
|
|
487
|
+
`WorkerClothSystem: the ClothState of entity ${instance.entity} is not shared-memory backed,`
|
|
488
|
+
+ ` so the worker would step a copy of it. Build the world with shared_state set, or use`
|
|
489
|
+
+ ` ClothSystem, which is the same solver on this thread.`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
this.#retire(instance);
|
|
494
|
+
|
|
495
|
+
const id = this.#next_cloth_id++;
|
|
496
|
+
|
|
497
|
+
const sequence = this.postToWorker({
|
|
498
|
+
type: "add_cloth",
|
|
499
|
+
id,
|
|
500
|
+
state: state.getSharedDescriptor(),
|
|
501
|
+
self_exclusions: instance.self_exclusions
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
this.#registrations.set(instance, { id, sequence, state, acknowledged: false });
|
|
505
|
+
this.#pending.push(instance);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Drop a cloth's registration, telling the worker to forget it.
|
|
510
|
+
*
|
|
511
|
+
* @param {ClothInstance} instance
|
|
512
|
+
* @private
|
|
513
|
+
*/
|
|
514
|
+
#retire(instance) {
|
|
515
|
+
const registration = this.#registrations.get(instance);
|
|
516
|
+
|
|
517
|
+
if (registration === undefined) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
this.#registrations.delete(instance);
|
|
522
|
+
|
|
523
|
+
const pending_index = this.#pending.indexOf(instance);
|
|
524
|
+
|
|
525
|
+
if (pending_index !== -1) {
|
|
526
|
+
this.#pending.splice(pending_index, 1);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Safe even mid-step: the worker may still be stepping this cloth, and
|
|
530
|
+
// will simply finish. It is dropped from the next dispatch regardless of
|
|
531
|
+
// when the message lands, and the shared buffer outlives both sides'
|
|
532
|
+
// references.
|
|
533
|
+
this.postToWorker({ type: "remove_cloth", id: registration.id });
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Move cloths whose registration message the worker has consumed into the
|
|
538
|
+
* dispatchable set. Until then the worker has no view of their memory and
|
|
539
|
+
* nominating them would be a protocol error.
|
|
540
|
+
*
|
|
541
|
+
* @private
|
|
542
|
+
*/
|
|
543
|
+
#promote_acknowledged_cloths() {
|
|
544
|
+
let write = 0;
|
|
545
|
+
|
|
546
|
+
for (let i = 0; i < this.#pending.length; i++) {
|
|
547
|
+
const instance = this.#pending[i];
|
|
548
|
+
|
|
549
|
+
const registration = this.#registrations.get(instance);
|
|
550
|
+
|
|
551
|
+
if (registration !== undefined && this.isMessageHandled(registration.sequence)) {
|
|
552
|
+
registration.acknowledged = true;
|
|
553
|
+
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
this.#pending[write++] = instance;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
this.#pending.length = write;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth.worker.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth.worker.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { SystemWorkerHost } from "../../../ecs/async/SystemWorkerHost.js";
|
|
2
|
+
import { ClothWorkerCore } from "./ClothWorkerCore.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Worker entry point for {@link WorkerClothSystem}.
|
|
6
|
+
*
|
|
7
|
+
* A real module worker rather than a generated blob, so the solver it pulls in
|
|
8
|
+
* is the ordinary `cloth_step_instance` — same source, same bundler treatment,
|
|
9
|
+
* same source maps — which is what makes bit-parity with the main-thread
|
|
10
|
+
* {@link ClothSystem} a property of the build rather than a coincidence.
|
|
11
|
+
*/
|
|
12
|
+
SystemWorkerHost.serve(new ClothWorkerCore());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_build_rows.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_build_rows.js"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH,+DAFa,IAAI,CAyBhB;AAID;;;;;;;GAOG;AACH,8DAHW,MAAM,GACJ,IAAI,
|
|
1
|
+
{"version":3,"file":"cloth_build_rows.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_build_rows.js"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH,+DAFa,IAAI,CAyBhB;AAID;;;;;;;GAOG;AACH,8DAHW,MAAM,GACJ,IAAI,CA6LhB;AAWD;;;;;;;;;;;;;;;;GAgBG;AACH,kEAHW,MAAM,GACJ,IAAI,CAoChB;AAED;;;;;;;;;;;GAWG;AACH,iGAFa,OAAO,CAkBnB;AAjXD;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,kCAFU,MAAM,CAEwB;AAIxC;;;;;;;;;;;;;;;;GAgBG;AACH,gCAFU,MAAM,CAEmB"}
|
|
@@ -249,7 +249,8 @@ export function cloth_build_rows(instance, dt) {
|
|
|
249
249
|
stretch_force_min: Float32Array.from(stretch_force_min),
|
|
250
250
|
stretch_force_max: Float32Array.from(stretch_force_max),
|
|
251
251
|
leash_particle: Int32Array.from(leash_particle),
|
|
252
|
-
leash_radius: Float32Array.from(leash_radius)
|
|
252
|
+
leash_radius: Float32Array.from(leash_radius),
|
|
253
|
+
shared: instance.shared_state
|
|
253
254
|
});
|
|
254
255
|
|
|
255
256
|
const particle_of_node = new Int32Array(node_count);
|
|
@@ -31,6 +31,36 @@ export function cloth_bend_ratio(bend: number): number;
|
|
|
31
31
|
* @returns {number}
|
|
32
32
|
*/
|
|
33
33
|
export function cloth_velocity_limit(shortest_row: number, substeps: number, iterations: number, dt: number): number;
|
|
34
|
+
/**
|
|
35
|
+
* §10's aerodynamic coupling as the **per-step response** the step multiplies
|
|
36
|
+
* the relative flow by, 1/s.
|
|
37
|
+
*
|
|
38
|
+
* Not a rate, and the difference is a stability argument rather than a
|
|
39
|
+
* convenience. The step holds one acceleration for the whole fixed step, so an
|
|
40
|
+
* explicit `rate·(u − v)` changes the velocity by `rate·dt·(u − v)` — which
|
|
41
|
+
* overshoots the air once `rate·dt > 1` and diverges past 2. §1's first
|
|
42
|
+
* commitment is "not at 5 fps", which is a `dt` of 0.2 s and a rate of 10.
|
|
43
|
+
*
|
|
44
|
+
* The exact solution of the same linear ODE has no such boundary:
|
|
45
|
+
*
|
|
46
|
+
* Δv = (1 − e^(−rate·dt))·(u − v)
|
|
47
|
+
*
|
|
48
|
+
* closes a fraction of the gap that is strictly below one for every `rate` and
|
|
49
|
+
* every `dt`, so the drag can never push a particle past the air it is
|
|
50
|
+
* relaxing toward. Dividing by `dt` turns it back into the acceleration the
|
|
51
|
+
* solver wants, and the exponential is evaluated **once per cloth per step** on
|
|
52
|
+
* the main thread rather than per particle.
|
|
53
|
+
*
|
|
54
|
+
* It is also the same step `GlobalFluidEffector` takes for the air itself —
|
|
55
|
+
* both are relaxations toward a velocity, and a cloth and the air around it
|
|
56
|
+
* reaching their common answer by the same arithmetic is a symmetry worth
|
|
57
|
+
* having.
|
|
58
|
+
*
|
|
59
|
+
* @param {number} drag `[0, 1]`
|
|
60
|
+
* @param {number} dt fixed step, seconds
|
|
61
|
+
* @returns {number} 1/s; `0` when there is no coupling at all
|
|
62
|
+
*/
|
|
63
|
+
export function cloth_drag_response(drag: number, dt: number): number;
|
|
34
64
|
/**
|
|
35
65
|
* Fraction of a particle's velocity surviving one fixed step. §7 P5, and see
|
|
36
66
|
* {@link ClothDynamics#damping} for why this is a correctness mechanism rather
|
|
@@ -218,6 +248,34 @@ export const CLOTH_TELEPORT_FLOOR: number;
|
|
|
218
248
|
* @type {number}
|
|
219
249
|
*/
|
|
220
250
|
export const CLOTH_STABILISE_STEPS: number;
|
|
251
|
+
/**
|
|
252
|
+
* Aerodynamic relaxation rate at `drag = 1`, per second (§10).
|
|
253
|
+
*
|
|
254
|
+
* ## Linear, not log
|
|
255
|
+
*
|
|
256
|
+
* `bend` is log-mapped because a stiffness spans decades and an author needs
|
|
257
|
+
* the whole range to be useful. Drag does not: the library's own entries run
|
|
258
|
+
* from leather at 0.05 to silk at 0.45, a factor of nine, and a linear map is
|
|
259
|
+
* the one that keeps that factor of nine meaning a factor of nine. It is also
|
|
260
|
+
* exactly zero at zero without a special case, which a log map cannot be.
|
|
261
|
+
*
|
|
262
|
+
* ## Sixty, because that is "the cloth goes where the air goes"
|
|
263
|
+
*
|
|
264
|
+
* The rate is a reciprocal time constant, so what `drag = 1` has to mean is a
|
|
265
|
+
* cloth with no aerodynamic memory at all — one that takes the air's velocity
|
|
266
|
+
* within a step. At 60 Hz, a rate of 60 closes 63% of the gap to the air every
|
|
267
|
+
* step and has a time constant of 17 ms, which is that. The library then reads:
|
|
268
|
+
* silk 27/s (37 ms), hair 18/s, cotton 12/s (83 ms), rope 7.2/s, denim 4.8/s
|
|
269
|
+
* (0.21 s), leather and chain 3/s (0.33 s) — a light banner that answers a gust
|
|
270
|
+
* within a couple of frames and an armour skirt that takes a third of a second
|
|
271
|
+
* to notice one, which is the ordering the fabrics already claimed.
|
|
272
|
+
*
|
|
273
|
+
* Raising it further buys nothing: {@link cloth_drag_response} saturates at
|
|
274
|
+
* `1/dt` by construction, so past about `1/dt` the whole range compresses into
|
|
275
|
+
* "the cloth is a streamer". `MEASUREMENTS.md` §48.
|
|
276
|
+
* @type {number}
|
|
277
|
+
*/
|
|
278
|
+
export const CLOTH_DRAG_RATE_MAX: number;
|
|
221
279
|
/**
|
|
222
280
|
* Speed below which a particle counts as still, as a fraction of the cloth's
|
|
223
281
|
* reach per second. A metre-long rope sleeps once nothing on it is moving
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_dynamics_map.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_dynamics_map.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_dynamics_map.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_dynamics_map.js"],"names":[],"mappings":"AA0OA;;;;;;;;GAQG;AACH,gDAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;;;;;;GAQG;AACH,uCAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;GAWG;AACH,mDAPW,MAAM,YAEN,MAAM,cACN,MAAM,MACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,0CAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;;GAQG;AACH,kDAJW,MAAM,MACN,MAAM,GACJ,MAAM,CAQlB;AApVD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;GAKG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;GAWG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,mCAFU,MAAM,CAEyB;AAEzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,+CAFU,MAAM,CAEkC;AAElD;;;;;;;;GAQG;AACH,iCAFU,MAAM,CAEqB;AAErC;;;;;;;;;;;;;GAaG;AACH,wCAFU,MAAM,CAE6B;AAE7C;;;;;;;;GAQG;AACH,0CAFU,MAAM,CAE+B;AAE/C;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;;GAQG;AACH,mCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH,oCAFU,MAAM,CAEwB;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,kCAFU,MAAM,CAEsB;AAEtC;;;;;GAKG;AACH,sCAFU,MAAM,CAE4B;AAE5C;;;;;GAKG;AACH,gCAFU,MAAM,CAEoB"}
|