@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,210 @@
|
|
|
1
|
+
import { FluidComponent } from "../../fluid/ecs/FluidComponent.js";
|
|
2
|
+
import { AbstractClothWind } from "./AbstractClothWind.js";
|
|
3
|
+
import { ClothAmbientWind } from "./ClothAmbientWind.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* # The air, read out of the fluid simulation that is already running
|
|
7
|
+
*
|
|
8
|
+
* §10's whole argument: this engine has a fluid simulator, `FluidObstacle`
|
|
9
|
+
* already voxelises physics colliders into it, so a character running past a
|
|
10
|
+
* cape gets a **wake** without anything cloth-specific being authored. This is
|
|
11
|
+
* the source that reads it — every enabled {@link FluidComponent} in the scene,
|
|
12
|
+
* sampled trilinearly where a particle actually is.
|
|
13
|
+
*
|
|
14
|
+
* Where no field reaches, {@link ambient} answers instead, so this is the one
|
|
15
|
+
* source a scene needs rather than a thing to switch between: a banner inside a
|
|
16
|
+
* wind tunnel volume reads the tunnel, the same banner carried outside reads the
|
|
17
|
+
* prevailing weather, and the cloth never learns which happened.
|
|
18
|
+
*
|
|
19
|
+
* ## Two units problems, and they are the reason this class exists at all
|
|
20
|
+
*
|
|
21
|
+
* A caller cannot simply forward `FluidComponent#sampleVelocityAtWorld`:
|
|
22
|
+
*
|
|
23
|
+
* - **Cells, not metres.** `FluidField#sampleVelocity` answers in *grid cells*
|
|
24
|
+
* per second and says so — it "does NOT rescale them, on the assumption that
|
|
25
|
+
* callers (vegetation sway, dust drift) interpret the field as a direction ×
|
|
26
|
+
* magnitude wind". Cloth's drag row is a relaxation toward a **velocity**, so
|
|
27
|
+
* the same wind voxelised at 0.25 m instead of 1 m would blow a garment four
|
|
28
|
+
* times as hard. The multiply by `cell_size` is here. `MEASUREMENTS.md` §45.
|
|
29
|
+
* - **Unbuilt fields read as null.** A `FluidComponent` exists from the moment
|
|
30
|
+
* the entity is spawned and its field's buffers arrive at `build()`. Sampling
|
|
31
|
+
* before that is a null dereference rather than a zero, so an unbuilt field is
|
|
32
|
+
* skipped exactly like a disabled one.
|
|
33
|
+
*
|
|
34
|
+
* ## The field list is rebuilt once a step, not once a cloth
|
|
35
|
+
*
|
|
36
|
+
* {@link begin} walks the dataset and caches each live field with its world
|
|
37
|
+
* box. Every cloth's {@link varies} and every particle's {@link sample} then
|
|
38
|
+
* read that cache, so a scene with twenty garments and one wind volume walks the
|
|
39
|
+
* dataset once. `FluidSystem` does the equivalent per field for its effectors
|
|
40
|
+
* and notes the same trade.
|
|
41
|
+
*
|
|
42
|
+
* ## What it does not do
|
|
43
|
+
*
|
|
44
|
+
* **It does not blend at a field's edge.** A point inside a field's box reads
|
|
45
|
+
* the field and a point outside reads the ambient, so a garment straddling the
|
|
46
|
+
* boundary sees a step in the air rather than a ramp. In a scene where the
|
|
47
|
+
* ambient is the far field the volume relaxes toward — `GlobalFluidEffector`'s
|
|
48
|
+
* `wind` — the step is small and mostly the disturbance the volume exists to
|
|
49
|
+
* carry; where it is not, it is visible, and the answer is a volume large enough
|
|
50
|
+
* to hold what moves through it. **Overlapping fields are resolved by order**,
|
|
51
|
+
* first match wins, which is the same arbitrary-but-deterministic rule
|
|
52
|
+
* `FluidSystem` applies when it steps them independently.
|
|
53
|
+
*
|
|
54
|
+
* @author Alex Goldring
|
|
55
|
+
* @copyright Company Named Limited (c) 2026
|
|
56
|
+
*/
|
|
57
|
+
export class ClothFluidWind extends AbstractClothWind {
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* What the air is where no field reaches. Present rather than optional
|
|
61
|
+
* because "outside every fluid volume" is most of the world.
|
|
62
|
+
* @type {ClothAmbientWind}
|
|
63
|
+
*/
|
|
64
|
+
ambient = new ClothAmbientWind();
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Live fields this step: the component and its world box, six words each.
|
|
68
|
+
* @type {FluidComponent[]}
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
__components = [];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @type {number[]}
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
__bounds = [];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @type {number}
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
__count = 0;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {number} time
|
|
87
|
+
* @param {EntityComponentDataset} ecd
|
|
88
|
+
* @returns {void}
|
|
89
|
+
*/
|
|
90
|
+
begin(time, ecd) {
|
|
91
|
+
this.ambient.begin(time, ecd);
|
|
92
|
+
|
|
93
|
+
const components = this.__components;
|
|
94
|
+
const bounds = this.__bounds;
|
|
95
|
+
|
|
96
|
+
let count = 0;
|
|
97
|
+
|
|
98
|
+
if (ecd !== null && ecd !== undefined) {
|
|
99
|
+
ecd.traverseComponents(FluidComponent, component => {
|
|
100
|
+
if (!component.enabled) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const field = component.field;
|
|
105
|
+
|
|
106
|
+
if (field.velocity_x === null) {
|
|
107
|
+
// Not built yet — `setResolution`/`build` has not run, so
|
|
108
|
+
// there are no buffers to sample.
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const resolution = field.getResolution();
|
|
113
|
+
|
|
114
|
+
const cell_size = component.cell_size;
|
|
115
|
+
|
|
116
|
+
const origin = component.origin;
|
|
117
|
+
|
|
118
|
+
const b = count * 6;
|
|
119
|
+
|
|
120
|
+
bounds[b] = origin[0];
|
|
121
|
+
bounds[b + 1] = origin[1];
|
|
122
|
+
bounds[b + 2] = origin[2];
|
|
123
|
+
bounds[b + 3] = origin[0] + resolution[0] * cell_size;
|
|
124
|
+
bounds[b + 4] = origin[1] + resolution[1] * cell_size;
|
|
125
|
+
bounds[b + 5] = origin[2] + resolution[2] * cell_size;
|
|
126
|
+
|
|
127
|
+
components[count] = component;
|
|
128
|
+
|
|
129
|
+
count++;
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Drop references to components that are no longer live, so a despawned
|
|
134
|
+
// fluid volume is not kept alive by this cache.
|
|
135
|
+
for (let i = count; i < components.length; i++) {
|
|
136
|
+
components[i] = null;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.__count = count;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param {number} min_x
|
|
144
|
+
* @param {number} min_y
|
|
145
|
+
* @param {number} min_z
|
|
146
|
+
* @param {number} max_x
|
|
147
|
+
* @param {number} max_y
|
|
148
|
+
* @param {number} max_z
|
|
149
|
+
* @returns {boolean} whether a fluid field reaches into this box — and so
|
|
150
|
+
* whether the caller has to sample per particle rather than once
|
|
151
|
+
*/
|
|
152
|
+
varies(min_x, min_y, min_z, max_x, max_y, max_z) {
|
|
153
|
+
const count = this.__count;
|
|
154
|
+
|
|
155
|
+
const bounds = this.__bounds;
|
|
156
|
+
|
|
157
|
+
for (let i = 0; i < count; i++) {
|
|
158
|
+
const b = i * 6;
|
|
159
|
+
|
|
160
|
+
if (max_x >= bounds[b]
|
|
161
|
+
&& max_y >= bounds[b + 1]
|
|
162
|
+
&& max_z >= bounds[b + 2]
|
|
163
|
+
&& min_x <= bounds[b + 3]
|
|
164
|
+
&& min_y <= bounds[b + 4]
|
|
165
|
+
&& min_z <= bounds[b + 5]) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @param {Float64Array|number[]} out
|
|
175
|
+
* @param {number} x
|
|
176
|
+
* @param {number} y
|
|
177
|
+
* @param {number} z
|
|
178
|
+
* @returns {Float64Array|number[]}
|
|
179
|
+
*/
|
|
180
|
+
sample(out, x, y, z) {
|
|
181
|
+
const count = this.__count;
|
|
182
|
+
|
|
183
|
+
const bounds = this.__bounds;
|
|
184
|
+
|
|
185
|
+
for (let i = 0; i < count; i++) {
|
|
186
|
+
const b = i * 6;
|
|
187
|
+
|
|
188
|
+
if (x < bounds[b] || x > bounds[b + 3]
|
|
189
|
+
|| y < bounds[b + 1] || y > bounds[b + 4]
|
|
190
|
+
|| z < bounds[b + 2] || z > bounds[b + 5]) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const component = this.__components[i];
|
|
195
|
+
|
|
196
|
+
component.sampleVelocityAtWorld(out, x, y, z);
|
|
197
|
+
|
|
198
|
+
// Cells per second to metres per second. See the header.
|
|
199
|
+
const cell_size = component.cell_size;
|
|
200
|
+
|
|
201
|
+
out[0] *= cell_size;
|
|
202
|
+
out[1] *= cell_size;
|
|
203
|
+
out[2] *= cell_size;
|
|
204
|
+
|
|
205
|
+
return out;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return this.ambient.sample(out, x, y, z);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # Reading the air into the cloth's own frame
|
|
3
|
+
*
|
|
4
|
+
* The one piece of §10 that has to run on the **main thread**, and the milestone's
|
|
5
|
+
* design decision. M5 moved every number the solver touches onto a worker; a
|
|
6
|
+
* fluid field is not one of those numbers. It is an ECS component holding a
|
|
7
|
+
* hundred thousand floats that the fluid solver rewrites every step, it may
|
|
8
|
+
* itself already live on a *different* worker (`WorkerFluidSystem`), and nothing
|
|
9
|
+
* about it is shaped like a cloth. Sending it across per step would cost more
|
|
10
|
+
* than the whole cloth step it was supposed to feed.
|
|
11
|
+
*
|
|
12
|
+
* So the split is the one §12 already draws — "arbitrary user-facing work —
|
|
13
|
+
* component reads, `Transform64` sync, index queries — stays on the main thread;
|
|
14
|
+
* the pure numeric step crosses" — applied once more. A field query is an index
|
|
15
|
+
* query. What crosses is the **answer**: one air velocity per particle, written
|
|
16
|
+
* into {@link ClothState#air_velocity}, which is a region of the cloth's own
|
|
17
|
+
* buffer and therefore already shared memory. Nothing is copied and nothing is
|
|
18
|
+
* marshalled; the main thread writes exactly where the worker reads. §39's "one
|
|
19
|
+
* buffer per cloth" is what makes that free.
|
|
20
|
+
*
|
|
21
|
+
* The **drag arithmetic** is not here, deliberately. It reads positions and
|
|
22
|
+
* velocities the state already holds, so it belongs with the rest of the
|
|
23
|
+
* arithmetic in `cloth_step_instance` — which keeps §40's property intact:
|
|
24
|
+
* neither system computes a step parameter of its own, the drag response crosses
|
|
25
|
+
* as one more word of the block, and the acceleration is built by the one
|
|
26
|
+
* function both systems call. `MEASUREMENTS.md` §45.
|
|
27
|
+
*
|
|
28
|
+
* ## Two costs, and only one of them scales
|
|
29
|
+
*
|
|
30
|
+
* A source that answers `varies() === false` — {@link ClothAmbientWind}, and
|
|
31
|
+
* {@link ClothFluidWind} anywhere its fields do not reach — is sampled **once**
|
|
32
|
+
* for the whole cloth. What is left is a bounds scan and a fill, both linear in
|
|
33
|
+
* particles with a handful of operations each, and both an order below a
|
|
34
|
+
* trilinear sample. That is the case §10 calls "no fluid field in range", and it
|
|
35
|
+
* is the common one. `MEASUREMENTS.md` §47 is what each costs.
|
|
36
|
+
*
|
|
37
|
+
* @author Alex Goldring
|
|
38
|
+
* @copyright Company Named Limited (c) 2026
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* Fill {@link ClothState#air_velocity} with the air each particle sits in,
|
|
42
|
+
* rotated into the cloth's local frame.
|
|
43
|
+
*
|
|
44
|
+
* @param {ClothState} state
|
|
45
|
+
* @param {AbstractClothWind} wind
|
|
46
|
+
* @param {Float64Array} anchor_translation the cloth frame's world origin
|
|
47
|
+
* @param {Float64Array} anchor_rotation the cloth frame's world rotation, xyzw
|
|
48
|
+
* @param {Float64Array} [centre] written with the world-space air at the cloth's
|
|
49
|
+
* own centre — what the sleep test compares against next step
|
|
50
|
+
* @returns {boolean} whether the source was sampled per particle
|
|
51
|
+
*/
|
|
52
|
+
export function cloth_sample_air(state: ClothState, wind: AbstractClothWind, anchor_translation: Float64Array, anchor_rotation: Float64Array, centre?: Float64Array): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the air at the cloth's centre has moved far enough since the last step
|
|
55
|
+
* that actually applied it to be worth waking for — §10's "sleep wakes on a wind
|
|
56
|
+
* change, so a settled banner does not sleep through a gust".
|
|
57
|
+
*
|
|
58
|
+
* The comparison is against the last **applied** air rather than the last
|
|
59
|
+
* sampled one, so a gust that arrives slowly still wakes the cloth: the
|
|
60
|
+
* difference accumulates instead of being reset by every step that declined to
|
|
61
|
+
* act on it.
|
|
62
|
+
*
|
|
63
|
+
* The threshold is the sleep test's own speed ratio, and that is deliberately
|
|
64
|
+
* conservative — the velocity a wind change of `Δu` actually produces in one
|
|
65
|
+
* step is `(1 − e^(−rate·dt))·facing·Δu`, a fraction of it, so this wakes on a
|
|
66
|
+
* change several times smaller than the one that would keep the cloth awake.
|
|
67
|
+
* Erring that way is the point: the failure §10 names is a banner sleeping
|
|
68
|
+
* through a gust, not one waking a few steps early.
|
|
69
|
+
*
|
|
70
|
+
* **Its limit, stated.** One point, at the cloth's centre. A wake that reaches
|
|
71
|
+
* only the hem of a sleeping banner and leaves its middle still will not wake
|
|
72
|
+
* it. The collider wake test next to it has no such gap because a collider's
|
|
73
|
+
* pose is seven exact numbers and a field is a continuum — the honest fix is
|
|
74
|
+
* more sample points, and the measurement is that one is enough for anything
|
|
75
|
+
* that crosses a garment rather than grazing it.
|
|
76
|
+
*
|
|
77
|
+
* @param {ClothState} state
|
|
78
|
+
* @param {AbstractClothWind} wind
|
|
79
|
+
* @param {Float64Array} anchor_translation
|
|
80
|
+
* @param {Float64Array} anchor_rotation
|
|
81
|
+
* @param {Float64Array} previous the air last applied to this cloth, world-space
|
|
82
|
+
* @param {number} threshold m/s
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
export function cloth_air_changed(state: ClothState, wind: AbstractClothWind, anchor_translation: Float64Array, anchor_rotation: Float64Array, previous: Float64Array, threshold: number): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* The cloth's world-space axis-aligned bounds.
|
|
88
|
+
*
|
|
89
|
+
* The particles are local, so this is the bounds of the **rotated** local box
|
|
90
|
+
* rather than the rotation of its bounds — the same eight-corner argument
|
|
91
|
+
* `cloth_gather_colliders` makes for its own query volume, and the same reason:
|
|
92
|
+
* a rotated box is not a box.
|
|
93
|
+
*
|
|
94
|
+
* @param {ClothState} state
|
|
95
|
+
* @param {Float64Array} anchor_translation
|
|
96
|
+
* @param {Float64Array} anchor_rotation
|
|
97
|
+
* @param {Float64Array} out six words, min then max
|
|
98
|
+
* @returns {void}
|
|
99
|
+
*/
|
|
100
|
+
export function cloth_air_bounds(state: ClothState, anchor_translation: Float64Array, anchor_rotation: Float64Array, out: Float64Array): void;
|
|
101
|
+
//# sourceMappingURL=cloth_sample_air.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_sample_air.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/wind/cloth_sample_air.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;;GAWG;AACH,iGANW,YAAY,mBACZ,YAAY,WACZ,YAAY,GAEV,OAAO,CA6EnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,kGANW,YAAY,mBACZ,YAAY,YACZ,YAAY,aACZ,MAAM,GACJ,OAAO,CAqBnB;AAED;;;;;;;;;;;;;GAaG;AACH,wEALW,YAAY,mBACZ,YAAY,OACZ,YAAY,GACV,IAAI,CAoEhB"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { v3_quaternion_apply } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
2
|
+
import { v3_quaternion_apply_inverse } from "../../../../core/geom/vec3/v3_quaternion_apply_inverse.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* # Reading the air into the cloth's own frame
|
|
6
|
+
*
|
|
7
|
+
* The one piece of §10 that has to run on the **main thread**, and the milestone's
|
|
8
|
+
* design decision. M5 moved every number the solver touches onto a worker; a
|
|
9
|
+
* fluid field is not one of those numbers. It is an ECS component holding a
|
|
10
|
+
* hundred thousand floats that the fluid solver rewrites every step, it may
|
|
11
|
+
* itself already live on a *different* worker (`WorkerFluidSystem`), and nothing
|
|
12
|
+
* about it is shaped like a cloth. Sending it across per step would cost more
|
|
13
|
+
* than the whole cloth step it was supposed to feed.
|
|
14
|
+
*
|
|
15
|
+
* So the split is the one §12 already draws — "arbitrary user-facing work —
|
|
16
|
+
* component reads, `Transform64` sync, index queries — stays on the main thread;
|
|
17
|
+
* the pure numeric step crosses" — applied once more. A field query is an index
|
|
18
|
+
* query. What crosses is the **answer**: one air velocity per particle, written
|
|
19
|
+
* into {@link ClothState#air_velocity}, which is a region of the cloth's own
|
|
20
|
+
* buffer and therefore already shared memory. Nothing is copied and nothing is
|
|
21
|
+
* marshalled; the main thread writes exactly where the worker reads. §39's "one
|
|
22
|
+
* buffer per cloth" is what makes that free.
|
|
23
|
+
*
|
|
24
|
+
* The **drag arithmetic** is not here, deliberately. It reads positions and
|
|
25
|
+
* velocities the state already holds, so it belongs with the rest of the
|
|
26
|
+
* arithmetic in `cloth_step_instance` — which keeps §40's property intact:
|
|
27
|
+
* neither system computes a step parameter of its own, the drag response crosses
|
|
28
|
+
* as one more word of the block, and the acceleration is built by the one
|
|
29
|
+
* function both systems call. `MEASUREMENTS.md` §45.
|
|
30
|
+
*
|
|
31
|
+
* ## Two costs, and only one of them scales
|
|
32
|
+
*
|
|
33
|
+
* A source that answers `varies() === false` — {@link ClothAmbientWind}, and
|
|
34
|
+
* {@link ClothFluidWind} anywhere its fields do not reach — is sampled **once**
|
|
35
|
+
* for the whole cloth. What is left is a bounds scan and a fill, both linear in
|
|
36
|
+
* particles with a handful of operations each, and both an order below a
|
|
37
|
+
* trilinear sample. That is the case §10 calls "no fluid field in range", and it
|
|
38
|
+
* is the common one. `MEASUREMENTS.md` §47 is what each costs.
|
|
39
|
+
*
|
|
40
|
+
* @author Alex Goldring
|
|
41
|
+
* @copyright Company Named Limited (c) 2026
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Fill {@link ClothState#air_velocity} with the air each particle sits in,
|
|
46
|
+
* rotated into the cloth's local frame.
|
|
47
|
+
*
|
|
48
|
+
* @param {ClothState} state
|
|
49
|
+
* @param {AbstractClothWind} wind
|
|
50
|
+
* @param {Float64Array} anchor_translation the cloth frame's world origin
|
|
51
|
+
* @param {Float64Array} anchor_rotation the cloth frame's world rotation, xyzw
|
|
52
|
+
* @param {Float64Array} [centre] written with the world-space air at the cloth's
|
|
53
|
+
* own centre — what the sleep test compares against next step
|
|
54
|
+
* @returns {boolean} whether the source was sampled per particle
|
|
55
|
+
*/
|
|
56
|
+
export function cloth_sample_air(state, wind, anchor_translation, anchor_rotation, centre = undefined) {
|
|
57
|
+
const particle_count = state.particle_count;
|
|
58
|
+
|
|
59
|
+
const air = state.air_velocity;
|
|
60
|
+
|
|
61
|
+
if (particle_count === 0) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const position = state.position;
|
|
66
|
+
|
|
67
|
+
const anchor_x = anchor_translation[0];
|
|
68
|
+
const anchor_y = anchor_translation[1];
|
|
69
|
+
const anchor_z = anchor_translation[2];
|
|
70
|
+
|
|
71
|
+
const qx = anchor_rotation[0];
|
|
72
|
+
const qy = anchor_rotation[1];
|
|
73
|
+
const qz = anchor_rotation[2];
|
|
74
|
+
const qw = anchor_rotation[3];
|
|
75
|
+
|
|
76
|
+
cloth_air_bounds(state, anchor_translation, anchor_rotation, BOUNDS);
|
|
77
|
+
|
|
78
|
+
const varies = wind.varies(BOUNDS[0], BOUNDS[1], BOUNDS[2], BOUNDS[3], BOUNDS[4], BOUNDS[5]);
|
|
79
|
+
|
|
80
|
+
// The cloth's own centre: where a uniform source is read, and where the
|
|
81
|
+
// sleep test asks whether the air has changed.
|
|
82
|
+
wind.sample(
|
|
83
|
+
SAMPLE,
|
|
84
|
+
(BOUNDS[0] + BOUNDS[3]) * 0.5,
|
|
85
|
+
(BOUNDS[1] + BOUNDS[4]) * 0.5,
|
|
86
|
+
(BOUNDS[2] + BOUNDS[5]) * 0.5
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
if (centre !== undefined) {
|
|
90
|
+
centre[0] = SAMPLE[0];
|
|
91
|
+
centre[1] = SAMPLE[1];
|
|
92
|
+
centre[2] = SAMPLE[2];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!varies) {
|
|
96
|
+
// One vector for the whole cloth. `varies() === false` is a promise
|
|
97
|
+
// rather than a hint, so this is exact rather than an approximation the
|
|
98
|
+
// caller opted into.
|
|
99
|
+
v3_quaternion_apply_inverse(LOCAL, 0, SAMPLE[0], SAMPLE[1], SAMPLE[2], qx, qy, qz, qw);
|
|
100
|
+
|
|
101
|
+
const local_x = LOCAL[0];
|
|
102
|
+
const local_y = LOCAL[1];
|
|
103
|
+
const local_z = LOCAL[2];
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < particle_count; i++) {
|
|
106
|
+
const p = i * 3;
|
|
107
|
+
|
|
108
|
+
air[p] = local_x;
|
|
109
|
+
air[p + 1] = local_y;
|
|
110
|
+
air[p + 2] = local_z;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (let i = 0; i < particle_count; i++) {
|
|
117
|
+
const p = i * 3;
|
|
118
|
+
|
|
119
|
+
v3_quaternion_apply(WORLD, 0, position[p], position[p + 1], position[p + 2], qx, qy, qz, qw);
|
|
120
|
+
|
|
121
|
+
wind.sample(SAMPLE, WORLD[0] + anchor_x, WORLD[1] + anchor_y, WORLD[2] + anchor_z);
|
|
122
|
+
|
|
123
|
+
v3_quaternion_apply_inverse(LOCAL, 0, SAMPLE[0], SAMPLE[1], SAMPLE[2], qx, qy, qz, qw);
|
|
124
|
+
|
|
125
|
+
air[p] = LOCAL[0];
|
|
126
|
+
air[p + 1] = LOCAL[1];
|
|
127
|
+
air[p + 2] = LOCAL[2];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Whether the air at the cloth's centre has moved far enough since the last step
|
|
135
|
+
* that actually applied it to be worth waking for — §10's "sleep wakes on a wind
|
|
136
|
+
* change, so a settled banner does not sleep through a gust".
|
|
137
|
+
*
|
|
138
|
+
* The comparison is against the last **applied** air rather than the last
|
|
139
|
+
* sampled one, so a gust that arrives slowly still wakes the cloth: the
|
|
140
|
+
* difference accumulates instead of being reset by every step that declined to
|
|
141
|
+
* act on it.
|
|
142
|
+
*
|
|
143
|
+
* The threshold is the sleep test's own speed ratio, and that is deliberately
|
|
144
|
+
* conservative — the velocity a wind change of `Δu` actually produces in one
|
|
145
|
+
* step is `(1 − e^(−rate·dt))·facing·Δu`, a fraction of it, so this wakes on a
|
|
146
|
+
* change several times smaller than the one that would keep the cloth awake.
|
|
147
|
+
* Erring that way is the point: the failure §10 names is a banner sleeping
|
|
148
|
+
* through a gust, not one waking a few steps early.
|
|
149
|
+
*
|
|
150
|
+
* **Its limit, stated.** One point, at the cloth's centre. A wake that reaches
|
|
151
|
+
* only the hem of a sleeping banner and leaves its middle still will not wake
|
|
152
|
+
* it. The collider wake test next to it has no such gap because a collider's
|
|
153
|
+
* pose is seven exact numbers and a field is a continuum — the honest fix is
|
|
154
|
+
* more sample points, and the measurement is that one is enough for anything
|
|
155
|
+
* that crosses a garment rather than grazing it.
|
|
156
|
+
*
|
|
157
|
+
* @param {ClothState} state
|
|
158
|
+
* @param {AbstractClothWind} wind
|
|
159
|
+
* @param {Float64Array} anchor_translation
|
|
160
|
+
* @param {Float64Array} anchor_rotation
|
|
161
|
+
* @param {Float64Array} previous the air last applied to this cloth, world-space
|
|
162
|
+
* @param {number} threshold m/s
|
|
163
|
+
* @returns {boolean}
|
|
164
|
+
*/
|
|
165
|
+
export function cloth_air_changed(state, wind, anchor_translation, anchor_rotation, previous, threshold) {
|
|
166
|
+
if (state.particle_count === 0) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
cloth_air_bounds(state, anchor_translation, anchor_rotation, BOUNDS);
|
|
171
|
+
|
|
172
|
+
wind.sample(
|
|
173
|
+
SAMPLE,
|
|
174
|
+
(BOUNDS[0] + BOUNDS[3]) * 0.5,
|
|
175
|
+
(BOUNDS[1] + BOUNDS[4]) * 0.5,
|
|
176
|
+
(BOUNDS[2] + BOUNDS[5]) * 0.5
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const dx = SAMPLE[0] - previous[0];
|
|
180
|
+
const dy = SAMPLE[1] - previous[1];
|
|
181
|
+
const dz = SAMPLE[2] - previous[2];
|
|
182
|
+
|
|
183
|
+
return dx * dx + dy * dy + dz * dz > threshold * threshold;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* The cloth's world-space axis-aligned bounds.
|
|
188
|
+
*
|
|
189
|
+
* The particles are local, so this is the bounds of the **rotated** local box
|
|
190
|
+
* rather than the rotation of its bounds — the same eight-corner argument
|
|
191
|
+
* `cloth_gather_colliders` makes for its own query volume, and the same reason:
|
|
192
|
+
* a rotated box is not a box.
|
|
193
|
+
*
|
|
194
|
+
* @param {ClothState} state
|
|
195
|
+
* @param {Float64Array} anchor_translation
|
|
196
|
+
* @param {Float64Array} anchor_rotation
|
|
197
|
+
* @param {Float64Array} out six words, min then max
|
|
198
|
+
* @returns {void}
|
|
199
|
+
*/
|
|
200
|
+
export function cloth_air_bounds(state, anchor_translation, anchor_rotation, out) {
|
|
201
|
+
const particle_count = state.particle_count;
|
|
202
|
+
|
|
203
|
+
const position = state.position;
|
|
204
|
+
|
|
205
|
+
let min_x = Infinity;
|
|
206
|
+
let min_y = Infinity;
|
|
207
|
+
let min_z = Infinity;
|
|
208
|
+
let max_x = -Infinity;
|
|
209
|
+
let max_y = -Infinity;
|
|
210
|
+
let max_z = -Infinity;
|
|
211
|
+
|
|
212
|
+
for (let i = 0; i < particle_count; i++) {
|
|
213
|
+
const p = i * 3;
|
|
214
|
+
|
|
215
|
+
const x = position[p];
|
|
216
|
+
const y = position[p + 1];
|
|
217
|
+
const z = position[p + 2];
|
|
218
|
+
|
|
219
|
+
if (x < min_x) { min_x = x; }
|
|
220
|
+
if (y < min_y) { min_y = y; }
|
|
221
|
+
if (z < min_z) { min_z = z; }
|
|
222
|
+
if (x > max_x) { max_x = x; }
|
|
223
|
+
if (y > max_y) { max_y = y; }
|
|
224
|
+
if (z > max_z) { max_z = z; }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const qx = anchor_rotation[0];
|
|
228
|
+
const qy = anchor_rotation[1];
|
|
229
|
+
const qz = anchor_rotation[2];
|
|
230
|
+
const qw = anchor_rotation[3];
|
|
231
|
+
|
|
232
|
+
let world_min_x = Infinity;
|
|
233
|
+
let world_min_y = Infinity;
|
|
234
|
+
let world_min_z = Infinity;
|
|
235
|
+
let world_max_x = -Infinity;
|
|
236
|
+
let world_max_y = -Infinity;
|
|
237
|
+
let world_max_z = -Infinity;
|
|
238
|
+
|
|
239
|
+
for (let corner = 0; corner < 8; corner++) {
|
|
240
|
+
v3_quaternion_apply(
|
|
241
|
+
WORLD, 0,
|
|
242
|
+
(corner & 1) === 0 ? min_x : max_x,
|
|
243
|
+
(corner & 2) === 0 ? min_y : max_y,
|
|
244
|
+
(corner & 4) === 0 ? min_z : max_z,
|
|
245
|
+
qx, qy, qz, qw
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const x = WORLD[0] + anchor_translation[0];
|
|
249
|
+
const y = WORLD[1] + anchor_translation[1];
|
|
250
|
+
const z = WORLD[2] + anchor_translation[2];
|
|
251
|
+
|
|
252
|
+
if (x < world_min_x) { world_min_x = x; }
|
|
253
|
+
if (y < world_min_y) { world_min_y = y; }
|
|
254
|
+
if (z < world_min_z) { world_min_z = z; }
|
|
255
|
+
if (x > world_max_x) { world_max_x = x; }
|
|
256
|
+
if (y > world_max_y) { world_max_y = y; }
|
|
257
|
+
if (z > world_max_z) { world_max_z = z; }
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
out[0] = world_min_x;
|
|
261
|
+
out[1] = world_min_y;
|
|
262
|
+
out[2] = world_min_z;
|
|
263
|
+
out[3] = world_max_x;
|
|
264
|
+
out[4] = world_max_y;
|
|
265
|
+
out[5] = world_max_z;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @type {Float64Array}
|
|
270
|
+
* @private
|
|
271
|
+
*/
|
|
272
|
+
const BOUNDS = new Float64Array(6);
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @type {Float64Array}
|
|
276
|
+
* @private
|
|
277
|
+
*/
|
|
278
|
+
const WORLD = new Float64Array(3);
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* @type {Float64Array}
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
const LOCAL = new Float64Array(3);
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* @type {Float64Array}
|
|
288
|
+
* @private
|
|
289
|
+
*/
|
|
290
|
+
const SAMPLE = new Float64Array(3);
|
|
@@ -64,11 +64,11 @@ export class FluidObstacleSystem extends System<any> {
|
|
|
64
64
|
/**
|
|
65
65
|
* @param {FluidComponent} fluid
|
|
66
66
|
*/
|
|
67
|
-
static "__#
|
|
67
|
+
static "__#396@#refresh_masks"(fluid: FluidComponent): void;
|
|
68
68
|
/**
|
|
69
69
|
* @param {FluidComponent} fluid
|
|
70
70
|
*/
|
|
71
|
-
static "__#
|
|
71
|
+
static "__#396@#clear_field"(fluid: FluidComponent): void;
|
|
72
72
|
/**
|
|
73
73
|
* Mark every cell of `fluid` whose centre lies within `inflation` of the
|
|
74
74
|
* posed shape as solid. Iteration is clipped to the shape's world AABB
|
|
@@ -80,7 +80,7 @@ export class FluidObstacleSystem extends System<any> {
|
|
|
80
80
|
* @param {number} inflation world-units SDF threshold
|
|
81
81
|
* @param {Float64Array} point length-3 scratch
|
|
82
82
|
*/
|
|
83
|
-
static "__#
|
|
83
|
+
static "__#396@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
|
|
84
84
|
/**
|
|
85
85
|
* Write the obstacle's translation velocity onto every face of every cell
|
|
86
86
|
* it voxelized — the moving-wall boundary condition. Runs AFTER the mask
|
|
@@ -100,7 +100,7 @@ export class FluidObstacleSystem extends System<any> {
|
|
|
100
100
|
* @param {number} wvy
|
|
101
101
|
* @param {number} wvz
|
|
102
102
|
*/
|
|
103
|
-
static "__#
|
|
103
|
+
static "__#396@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
|
|
104
104
|
constructor();
|
|
105
105
|
dependencies: (typeof FluidObstacle)[];
|
|
106
106
|
components_used: (ResourceAccessSpecification<typeof Transform64> | ResourceAccessSpecification<typeof RigidBody> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof FluidComponent> | ResourceAccessSpecification<typeof FluidObstacle>)[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"texture_copy.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/mock/texture_copy.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"texture_copy.d.ts","sourceRoot":"","sources":["../../../../../src/shade/device/mock/texture_copy.js"],"names":[],"mappings":"AA6MA;;;;;;;;;;;;;GAaG;AACH;IAP0C,cAAc;IACf,aAAa;IACZ,mBAAmB;IACpB,kBAAkB;IAC9B,IAAI;IACpB,MAAM,GAAC,IAAI,CA4DvB;AAiED;;;;;GAKG;AACH,uHAHW,MAAM,GACJ,IAAI,CA8BhB;;;;;;UA5Fa,WAAW;;;;YACX,MAAM;gBACN,MAAM;kBACN,MAAM"}
|
|
@@ -104,6 +104,34 @@ function texture_endpoint_refusal(info, role, required_usage, required_usage_nam
|
|
|
104
104
|
return `${role} copySize.height (${extent.height}) is not a multiple of the ${format.block_height}-texel block height of ${texture.format}`;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
/*
|
|
108
|
+
WebGPU's rule for `copyTextureToBuffer`/`copyBufferToTexture`/`writeTexture`: "if the
|
|
109
|
+
GPUTexture.format is a depth-or-stencil format or GPUTexture.sampleCount is more than 1, the
|
|
110
|
+
subresource size is equal to size". A depth buffer is copied whole or not at all — there is no
|
|
111
|
+
reading one texel of one, and the one-pixel read that looks like the obvious way to pick an
|
|
112
|
+
entity off the frame's depth is the thing this forbids. The restriction comes from D3D12, so
|
|
113
|
+
it is enforced everywhere rather than being a Windows-only surprise.
|
|
114
|
+
|
|
115
|
+
Only the two axes a region is named in: this does not also require a layered copy to take every
|
|
116
|
+
layer, which WebGPU's definition of a subresource's size does.
|
|
117
|
+
*/
|
|
118
|
+
const depth_or_stencil = !format.aspects.includes("all");
|
|
119
|
+
|
|
120
|
+
if (depth_or_stencil || texture.sampleCount > 1) {
|
|
121
|
+
const full_width = texture.mip_width(mip);
|
|
122
|
+
const full_height = texture.mip_height(mip);
|
|
123
|
+
|
|
124
|
+
if (origin.x !== 0 || origin.y !== 0 || extent.width !== full_width || extent.height !== full_height) {
|
|
125
|
+
const why = depth_or_stencil
|
|
126
|
+
? `is ${texture.format}, a depth-or-stencil format`
|
|
127
|
+
: `has sampleCount ${texture.sampleCount}`;
|
|
128
|
+
|
|
129
|
+
return `${role} texture '${texture.label}' ${why}, so a copy must cover the whole`
|
|
130
|
+
+ ` subresource; mip ${mip} is ${full_width}x${full_height} and the region asked for`
|
|
131
|
+
+ ` is ${extent.width}x${extent.height} at (${origin.x}, ${origin.y})`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
107
135
|
return null;
|
|
108
136
|
}
|
|
109
137
|
|