@woosh/meep-engine 3.24.0 → 3.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +59 -0
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +285 -0
- package/src/core/geom/3d/shape/PosedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/PosedShape3D.js +57 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +102 -0
- package/src/core/geom/3d/shape/UnionShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/UnionShape3D.js +64 -0
- 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 +1632 -0
- package/src/engine/physics/cloth/PLAN.md +738 -95
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +84 -17
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +451 -42
- 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 +101 -29
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +110 -31
- 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 +71 -81
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +135 -856
- 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 +323 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothWorld.js +1248 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +192 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +578 -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 +85 -3
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +366 -271
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +95 -12
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +170 -27
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +19 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +249 -201
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +62 -1
- 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/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +18 -10
- 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/collide_main.js +1 -1
- 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_contact_find.d.ts +29 -8
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +37 -9
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +45 -2
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +46 -2
- 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/solver/constraint/cloth_backstop_row.d.ts +9 -2
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +9 -2
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts +102 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/AbstractClothWind.js +114 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts +87 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.d.ts.map +1 -0
- package/src/engine/physics/cloth/wind/ClothAmbientWind.js +185 -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 +213 -0
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +106 -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 +297 -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
|
@@ -1,271 +1,366 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* # Normalised coordinates → row parameters
|
|
3
|
-
*
|
|
4
|
-
* {@link ClothDynamics}' stiffnesses are coordinates in `[0, 1]`, and this is
|
|
5
|
-
* the whole of what they mean. It is one module rather than methods on the
|
|
6
|
-
* value object because the mapping is *measured* — every constant below has a
|
|
7
|
-
* number in `MEASUREMENTS.md` behind it — and a measured mapping deserves to be
|
|
8
|
-
* readable on its own and specced on its own.
|
|
9
|
-
*
|
|
10
|
-
* ## Why neither stiffness maps to newtons per metre
|
|
11
|
-
*
|
|
12
|
-
* M0's central finding: a **soft** row — a plain penalty — is dissipative only
|
|
13
|
-
* while its stiffness stays below about `8·(m/h²)`, and above that boundary the
|
|
14
|
-
* step *adds* energy and the cloth sustains a limit cycle forever. More
|
|
15
|
-
* iterations and more substeps shrink it; neither removes it
|
|
16
|
-
* (`MEASUREMENTS.md` §6). And that boundary is not a stiffness: it is a
|
|
17
|
-
* multiple of the row's own inertial scale, which moved across five decades of
|
|
18
|
-
* particle mass in §4's sweep without the answer changing.
|
|
19
|
-
*
|
|
20
|
-
* Two consequences, one for each stiffness:
|
|
21
|
-
*
|
|
22
|
-
* - **`stretch` cannot be a penalty at all.** Real fabric wants a stretch
|
|
23
|
-
* stiffness far above that boundary — for a half-gram particle at 60 Hz × 2
|
|
24
|
-
* substeps it sits near 60 N/m, a rubber band — so the stretch row is hard
|
|
25
|
-
* (`Infinity`, augmented Lagrangian), and what `stretch` actually selects is
|
|
26
|
-
* {@link cloth_strain_allowance}: how far the fabric may extend before the
|
|
27
|
-
* strain-limit row of §6 stops it.
|
|
28
|
-
* - **`bend` maps to a ratio.** A bend row is soft and must stay inside the
|
|
29
|
-
* dissipative band, so its stiffness is expressed as a multiple of
|
|
30
|
-
* `m_eff/dt²` — the row's own inertial scale at the **fixed** step rather
|
|
31
|
-
* than the substep. Two things fall out of that choice and both are wanted:
|
|
32
|
-
* the fabric's look is invariant to how heavy the author made the particles
|
|
33
|
-
* (which is what a normalised `[0, 1]` knob should mean), and the row is
|
|
34
|
-
* inside the band at *any* substep count, since `k/(m/h²) = ratio/substeps²`
|
|
35
|
-
* and `substeps ≥ 1`. A stiffness in newtons per metre has neither property.
|
|
36
|
-
*
|
|
37
|
-
* @author Alex Goldring
|
|
38
|
-
* @copyright Company Named Limited (c) 2026
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Strain a fabric at `stretch = 0` may carry: a quarter of its own length, a
|
|
43
|
-
* loose knit. Chosen as the loosest thing that still reads as fabric rather
|
|
44
|
-
* than as elastic.
|
|
45
|
-
* @type {number}
|
|
46
|
-
*/
|
|
47
|
-
export const CLOTH_STRAIN_MAX = 0.25;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Strain a fabric at `stretch = 1` may carry: a tenth of a per cent, which is
|
|
51
|
-
* a chain. Below this the strain-limit row is asking for more precision than a
|
|
52
|
-
* `Float32` position over a garment-sized coordinate resolves.
|
|
53
|
-
* @type {number}
|
|
54
|
-
*/
|
|
55
|
-
export const CLOTH_STRAIN_MIN = 1e-3;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Bend stiffness at `bend = 1`, as a multiple of the row's `m_eff/dt²`.
|
|
59
|
-
*
|
|
60
|
-
* It is 8 because that is the top of the dissipative band M0 measured
|
|
61
|
-
* (`MEASUREMENTS.md` §4 and §6) and a bend row is soft. The consequence, stated
|
|
62
|
-
* rather than hidden: **bending saturates**. A fabric stiffer than this cannot
|
|
63
|
-
* be expressed as a soft row that also comes to rest, and asking for one is
|
|
64
|
-
* asking for the limit cycle §7 P5 exists to prevent. If a garment ever needs
|
|
65
|
-
* more, the answer is a hard bend row with a multiplier, not a bigger number
|
|
66
|
-
* here.
|
|
67
|
-
* @type {number}
|
|
68
|
-
*/
|
|
69
|
-
export const CLOTH_BEND_RATIO_MAX = 8;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Bend stiffness just above `bend = 0`, as a multiple of `m_eff/dt²`. Four
|
|
73
|
-
* orders of magnitude below the ceiling, which is what makes the log map
|
|
74
|
-
* useful across the whole range instead of spending most of it near zero.
|
|
75
|
-
* @type {number}
|
|
76
|
-
*/
|
|
77
|
-
export const CLOTH_BEND_RATIO_MIN = 1e-3;
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* How many times its own **correction authority** a particle may travel in one
|
|
81
|
-
* fixed step before the velocity clamp of §7 P1 catches it.
|
|
82
|
-
*
|
|
83
|
-
* ## Not `thickness`, and the measurement is why
|
|
84
|
-
*
|
|
85
|
-
* §7 P1 asks for a clamp "derived from `thickness` and `h`", and that turns out
|
|
86
|
-
* to be the wrong length scale for this job. `thickness` is a **contact**
|
|
87
|
-
* radius: a clamp built from it is a tunnelling bound, and a tunnelling bound
|
|
88
|
-
* sits *below* ordinary cloth speeds rather than above them. Silk is 4 mm
|
|
89
|
-
* thick, so at 60 Hz "a particle may not cross its own radius in a step" is
|
|
90
|
-
* 0.24 m/s — and M1 measured a rope behind a 9 m/s sprinter reaching 13 m/s
|
|
91
|
-
* (§7 P7). Any multiple large enough to stop the clamp being a *behaviour* for
|
|
92
|
-
* silk is large enough to make it meaningless for leather, because the two
|
|
93
|
-
* thicknesses differ by 5× and their speeds do not.
|
|
94
|
-
*
|
|
95
|
-
* ## What the scale actually is
|
|
96
|
-
*
|
|
97
|
-
* The solver has a measurable ability to pull a particle back, and it is not
|
|
98
|
-
* unlimited: the trust region caps each vertex update at the **shortest row
|
|
99
|
-
* incident on that particle** (§5.3), so one fixed step can move a particle at
|
|
100
|
-
* most `shortest_row · substeps · iterations`. M1 measured what happens past
|
|
101
|
-
* it — a 30-link chain kicked at 16 m/s at 1 substep × 1 iteration stretches to
|
|
102
|
-
* **17× its own reach** before recovering, against 1.02× when it is dropped
|
|
103
|
-
* under gravity, and 2.6× for the same kick at 2×4. The tether row is not what
|
|
104
|
-
* failed there; the tether row was never given a chance to act.
|
|
105
|
-
*
|
|
106
|
-
* So the clamp is a multiple of exactly that quantity, which makes it a bound
|
|
107
|
-
* on *the solver being asked to do more than it can*, and makes it scale with
|
|
108
|
-
* the budget the fabric bought and the mesh it is built on rather than with a
|
|
109
|
-
* contact radius it does not use until M2.
|
|
110
|
-
*
|
|
111
|
-
* Four, because one would bind: a coat on a sprinting character carries several
|
|
112
|
-
* metres a second of anchor-relative velocity, and a clamp that engages there
|
|
113
|
-
* is a behaviour rather than a backstop. Four leaves every library entry an
|
|
114
|
-
* order of magnitude of headroom over its measured peak and still bounds the
|
|
115
|
-
* absurd cases in a handful of steps.
|
|
116
|
-
* @type {number}
|
|
117
|
-
*/
|
|
118
|
-
export const CLOTH_VELOCITY_CORRECTION_MARGIN = 4;
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Velocity decay rate at `damping = 1`, per second.
|
|
122
|
-
*
|
|
123
|
-
* `damping` maps to an exponential decay rather than a per-step multiplier so
|
|
124
|
-
* that the same value means the same thing at any fixed rate. At the default
|
|
125
|
-
* `damping = 0.15` the time constant is a third of a second, which is a cape
|
|
126
|
-
* that stops swinging without looking like it is under water.
|
|
127
|
-
* @type {number}
|
|
128
|
-
*/
|
|
129
|
-
export const CLOTH_DAMPING_RATE = 20;
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* How far a cloth's anchor may carry it in one fixed step, as a multiple of the
|
|
133
|
-
* cloth's own reach. Motion above this is felt as though it were exactly this,
|
|
134
|
-
* which is what "anchor speed limit" means in §7 P7.
|
|
135
|
-
*
|
|
136
|
-
* Expressing it as a fraction of reach rather than in metres per second is what
|
|
137
|
-
* makes it work for a 3 cm pendant and a 30 m mooring line at the same time: a
|
|
138
|
-
* cloth is whipped by motion large *compared to itself*, and the reach is the
|
|
139
|
-
* only length scale the cloth carries. Half a reach per step is 30 reaches a
|
|
140
|
-
* second at 60 Hz, which no character locomotion comes near — §7 P7's own
|
|
141
|
-
* profile peaks two orders below it — and which a lift, a lurching vehicle or a
|
|
142
|
-
* badly-keyed cut does exceed.
|
|
143
|
-
* @type {number}
|
|
144
|
-
*/
|
|
145
|
-
export const CLOTH_ANCHOR_TRAVEL_REACH = 0.5;
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* How far a cloth's anchor may rotate in one fixed step, radians. Rotation
|
|
149
|
-
* above this is felt as though it were exactly this.
|
|
150
|
-
*
|
|
151
|
-
* Unlike the travel limit this has no length scale to hang off — an angle is
|
|
152
|
-
* already dimensionless — so it is a plain number. Half a radian per step is
|
|
153
|
-
* about 1,700 degrees a second, which is a spin rather than a turn.
|
|
154
|
-
* @type {number}
|
|
155
|
-
*/
|
|
156
|
-
export const CLOTH_ANCHOR_ROTATION_LIMIT = 0.5;
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Anchor displacement in one fixed step, as a multiple of the cloth's reach,
|
|
160
|
-
* above which the motion is a **teleport** rather than locomotion (§7 P6).
|
|
161
|
-
*
|
|
162
|
-
* Four reaches in one step is 240 reaches a second: for a 1 m rope that is
|
|
163
|
-
* 240 m/s, well past anything the world moves at and well short of the values a
|
|
164
|
-
* cut or a level load produces.
|
|
165
|
-
* @type {number}
|
|
166
|
-
*/
|
|
167
|
-
export const CLOTH_TELEPORT_REACH = 4;
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Absolute floor on the teleport threshold, metres per fixed step.
|
|
171
|
-
*
|
|
172
|
-
* The reach multiple alone would make a small cloth absurdly twitchy — a 3 cm
|
|
173
|
-
* pendant would call 7 m/s a teleport, which is a brisk walk. This floor is
|
|
174
|
-
* 2 metres in a sixtieth of a second, so nothing under 120 m/s is a teleport
|
|
175
|
-
* whatever size the cloth is.
|
|
176
|
-
* @type {number}
|
|
177
|
-
*/
|
|
178
|
-
export const CLOTH_TELEPORT_FLOOR = 2;
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Length of the stabilisation window after a teleport reset, in fixed steps.
|
|
182
|
-
*
|
|
183
|
-
* The velocity limit ramps linearly from zero back to its full value across it,
|
|
184
|
-
* so a re-seeded cloth cannot leave the animated pose faster than the window
|
|
185
|
-
* allows however wrong its first solve is. A third of a second at 60 Hz.
|
|
186
|
-
* @type {number}
|
|
187
|
-
*/
|
|
188
|
-
export const CLOTH_STABILISE_STEPS = 20;
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* @
|
|
213
|
-
*
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
|
|
247
|
-
*
|
|
248
|
-
* @
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* @
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
1
|
+
/**
|
|
2
|
+
* # Normalised coordinates → row parameters
|
|
3
|
+
*
|
|
4
|
+
* {@link ClothDynamics}' stiffnesses are coordinates in `[0, 1]`, and this is
|
|
5
|
+
* the whole of what they mean. It is one module rather than methods on the
|
|
6
|
+
* value object because the mapping is *measured* — every constant below has a
|
|
7
|
+
* number in `MEASUREMENTS.md` behind it — and a measured mapping deserves to be
|
|
8
|
+
* readable on its own and specced on its own.
|
|
9
|
+
*
|
|
10
|
+
* ## Why neither stiffness maps to newtons per metre
|
|
11
|
+
*
|
|
12
|
+
* M0's central finding: a **soft** row — a plain penalty — is dissipative only
|
|
13
|
+
* while its stiffness stays below about `8·(m/h²)`, and above that boundary the
|
|
14
|
+
* step *adds* energy and the cloth sustains a limit cycle forever. More
|
|
15
|
+
* iterations and more substeps shrink it; neither removes it
|
|
16
|
+
* (`MEASUREMENTS.md` §6). And that boundary is not a stiffness: it is a
|
|
17
|
+
* multiple of the row's own inertial scale, which moved across five decades of
|
|
18
|
+
* particle mass in §4's sweep without the answer changing.
|
|
19
|
+
*
|
|
20
|
+
* Two consequences, one for each stiffness:
|
|
21
|
+
*
|
|
22
|
+
* - **`stretch` cannot be a penalty at all.** Real fabric wants a stretch
|
|
23
|
+
* stiffness far above that boundary — for a half-gram particle at 60 Hz × 2
|
|
24
|
+
* substeps it sits near 60 N/m, a rubber band — so the stretch row is hard
|
|
25
|
+
* (`Infinity`, augmented Lagrangian), and what `stretch` actually selects is
|
|
26
|
+
* {@link cloth_strain_allowance}: how far the fabric may extend before the
|
|
27
|
+
* strain-limit row of §6 stops it.
|
|
28
|
+
* - **`bend` maps to a ratio.** A bend row is soft and must stay inside the
|
|
29
|
+
* dissipative band, so its stiffness is expressed as a multiple of
|
|
30
|
+
* `m_eff/dt²` — the row's own inertial scale at the **fixed** step rather
|
|
31
|
+
* than the substep. Two things fall out of that choice and both are wanted:
|
|
32
|
+
* the fabric's look is invariant to how heavy the author made the particles
|
|
33
|
+
* (which is what a normalised `[0, 1]` knob should mean), and the row is
|
|
34
|
+
* inside the band at *any* substep count, since `k/(m/h²) = ratio/substeps²`
|
|
35
|
+
* and `substeps ≥ 1`. A stiffness in newtons per metre has neither property.
|
|
36
|
+
*
|
|
37
|
+
* @author Alex Goldring
|
|
38
|
+
* @copyright Company Named Limited (c) 2026
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Strain a fabric at `stretch = 0` may carry: a quarter of its own length, a
|
|
43
|
+
* loose knit. Chosen as the loosest thing that still reads as fabric rather
|
|
44
|
+
* than as elastic.
|
|
45
|
+
* @type {number}
|
|
46
|
+
*/
|
|
47
|
+
export const CLOTH_STRAIN_MAX = 0.25;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Strain a fabric at `stretch = 1` may carry: a tenth of a per cent, which is
|
|
51
|
+
* a chain. Below this the strain-limit row is asking for more precision than a
|
|
52
|
+
* `Float32` position over a garment-sized coordinate resolves.
|
|
53
|
+
* @type {number}
|
|
54
|
+
*/
|
|
55
|
+
export const CLOTH_STRAIN_MIN = 1e-3;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Bend stiffness at `bend = 1`, as a multiple of the row's `m_eff/dt²`.
|
|
59
|
+
*
|
|
60
|
+
* It is 8 because that is the top of the dissipative band M0 measured
|
|
61
|
+
* (`MEASUREMENTS.md` §4 and §6) and a bend row is soft. The consequence, stated
|
|
62
|
+
* rather than hidden: **bending saturates**. A fabric stiffer than this cannot
|
|
63
|
+
* be expressed as a soft row that also comes to rest, and asking for one is
|
|
64
|
+
* asking for the limit cycle §7 P5 exists to prevent. If a garment ever needs
|
|
65
|
+
* more, the answer is a hard bend row with a multiplier, not a bigger number
|
|
66
|
+
* here.
|
|
67
|
+
* @type {number}
|
|
68
|
+
*/
|
|
69
|
+
export const CLOTH_BEND_RATIO_MAX = 8;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Bend stiffness just above `bend = 0`, as a multiple of `m_eff/dt²`. Four
|
|
73
|
+
* orders of magnitude below the ceiling, which is what makes the log map
|
|
74
|
+
* useful across the whole range instead of spending most of it near zero.
|
|
75
|
+
* @type {number}
|
|
76
|
+
*/
|
|
77
|
+
export const CLOTH_BEND_RATIO_MIN = 1e-3;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* How many times its own **correction authority** a particle may travel in one
|
|
81
|
+
* fixed step before the velocity clamp of §7 P1 catches it.
|
|
82
|
+
*
|
|
83
|
+
* ## Not `thickness`, and the measurement is why
|
|
84
|
+
*
|
|
85
|
+
* §7 P1 asks for a clamp "derived from `thickness` and `h`", and that turns out
|
|
86
|
+
* to be the wrong length scale for this job. `thickness` is a **contact**
|
|
87
|
+
* radius: a clamp built from it is a tunnelling bound, and a tunnelling bound
|
|
88
|
+
* sits *below* ordinary cloth speeds rather than above them. Silk is 4 mm
|
|
89
|
+
* thick, so at 60 Hz "a particle may not cross its own radius in a step" is
|
|
90
|
+
* 0.24 m/s — and M1 measured a rope behind a 9 m/s sprinter reaching 13 m/s
|
|
91
|
+
* (§7 P7). Any multiple large enough to stop the clamp being a *behaviour* for
|
|
92
|
+
* silk is large enough to make it meaningless for leather, because the two
|
|
93
|
+
* thicknesses differ by 5× and their speeds do not.
|
|
94
|
+
*
|
|
95
|
+
* ## What the scale actually is
|
|
96
|
+
*
|
|
97
|
+
* The solver has a measurable ability to pull a particle back, and it is not
|
|
98
|
+
* unlimited: the trust region caps each vertex update at the **shortest row
|
|
99
|
+
* incident on that particle** (§5.3), so one fixed step can move a particle at
|
|
100
|
+
* most `shortest_row · substeps · iterations`. M1 measured what happens past
|
|
101
|
+
* it — a 30-link chain kicked at 16 m/s at 1 substep × 1 iteration stretches to
|
|
102
|
+
* **17× its own reach** before recovering, against 1.02× when it is dropped
|
|
103
|
+
* under gravity, and 2.6× for the same kick at 2×4. The tether row is not what
|
|
104
|
+
* failed there; the tether row was never given a chance to act.
|
|
105
|
+
*
|
|
106
|
+
* So the clamp is a multiple of exactly that quantity, which makes it a bound
|
|
107
|
+
* on *the solver being asked to do more than it can*, and makes it scale with
|
|
108
|
+
* the budget the fabric bought and the mesh it is built on rather than with a
|
|
109
|
+
* contact radius it does not use until M2.
|
|
110
|
+
*
|
|
111
|
+
* Four, because one would bind: a coat on a sprinting character carries several
|
|
112
|
+
* metres a second of anchor-relative velocity, and a clamp that engages there
|
|
113
|
+
* is a behaviour rather than a backstop. Four leaves every library entry an
|
|
114
|
+
* order of magnitude of headroom over its measured peak and still bounds the
|
|
115
|
+
* absurd cases in a handful of steps.
|
|
116
|
+
* @type {number}
|
|
117
|
+
*/
|
|
118
|
+
export const CLOTH_VELOCITY_CORRECTION_MARGIN = 4;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Velocity decay rate at `damping = 1`, per second.
|
|
122
|
+
*
|
|
123
|
+
* `damping` maps to an exponential decay rather than a per-step multiplier so
|
|
124
|
+
* that the same value means the same thing at any fixed rate. At the default
|
|
125
|
+
* `damping = 0.15` the time constant is a third of a second, which is a cape
|
|
126
|
+
* that stops swinging without looking like it is under water.
|
|
127
|
+
* @type {number}
|
|
128
|
+
*/
|
|
129
|
+
export const CLOTH_DAMPING_RATE = 20;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* How far a cloth's anchor may carry it in one fixed step, as a multiple of the
|
|
133
|
+
* cloth's own reach. Motion above this is felt as though it were exactly this,
|
|
134
|
+
* which is what "anchor speed limit" means in §7 P7.
|
|
135
|
+
*
|
|
136
|
+
* Expressing it as a fraction of reach rather than in metres per second is what
|
|
137
|
+
* makes it work for a 3 cm pendant and a 30 m mooring line at the same time: a
|
|
138
|
+
* cloth is whipped by motion large *compared to itself*, and the reach is the
|
|
139
|
+
* only length scale the cloth carries. Half a reach per step is 30 reaches a
|
|
140
|
+
* second at 60 Hz, which no character locomotion comes near — §7 P7's own
|
|
141
|
+
* profile peaks two orders below it — and which a lift, a lurching vehicle or a
|
|
142
|
+
* badly-keyed cut does exceed.
|
|
143
|
+
* @type {number}
|
|
144
|
+
*/
|
|
145
|
+
export const CLOTH_ANCHOR_TRAVEL_REACH = 0.5;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* How far a cloth's anchor may rotate in one fixed step, radians. Rotation
|
|
149
|
+
* above this is felt as though it were exactly this.
|
|
150
|
+
*
|
|
151
|
+
* Unlike the travel limit this has no length scale to hang off — an angle is
|
|
152
|
+
* already dimensionless — so it is a plain number. Half a radian per step is
|
|
153
|
+
* about 1,700 degrees a second, which is a spin rather than a turn.
|
|
154
|
+
* @type {number}
|
|
155
|
+
*/
|
|
156
|
+
export const CLOTH_ANCHOR_ROTATION_LIMIT = 0.5;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Anchor displacement in one fixed step, as a multiple of the cloth's reach,
|
|
160
|
+
* above which the motion is a **teleport** rather than locomotion (§7 P6).
|
|
161
|
+
*
|
|
162
|
+
* Four reaches in one step is 240 reaches a second: for a 1 m rope that is
|
|
163
|
+
* 240 m/s, well past anything the world moves at and well short of the values a
|
|
164
|
+
* cut or a level load produces.
|
|
165
|
+
* @type {number}
|
|
166
|
+
*/
|
|
167
|
+
export const CLOTH_TELEPORT_REACH = 4;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Absolute floor on the teleport threshold, metres per fixed step.
|
|
171
|
+
*
|
|
172
|
+
* The reach multiple alone would make a small cloth absurdly twitchy — a 3 cm
|
|
173
|
+
* pendant would call 7 m/s a teleport, which is a brisk walk. This floor is
|
|
174
|
+
* 2 metres in a sixtieth of a second, so nothing under 120 m/s is a teleport
|
|
175
|
+
* whatever size the cloth is.
|
|
176
|
+
* @type {number}
|
|
177
|
+
*/
|
|
178
|
+
export const CLOTH_TELEPORT_FLOOR = 2;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Length of the stabilisation window after a teleport reset, in fixed steps.
|
|
182
|
+
*
|
|
183
|
+
* The velocity limit ramps linearly from zero back to its full value across it,
|
|
184
|
+
* so a re-seeded cloth cannot leave the animated pose faster than the window
|
|
185
|
+
* allows however wrong its first solve is. A third of a second at 60 Hz.
|
|
186
|
+
* @type {number}
|
|
187
|
+
*/
|
|
188
|
+
export const CLOTH_STABILISE_STEPS = 20;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Aerodynamic relaxation rate at `drag = 1`, per second (§10).
|
|
192
|
+
*
|
|
193
|
+
* ## Linear, not log
|
|
194
|
+
*
|
|
195
|
+
* `bend` is log-mapped because a stiffness spans decades and an author needs
|
|
196
|
+
* the whole range to be useful. Drag does not: the library's own entries run
|
|
197
|
+
* from leather at 0.05 to silk at 0.45, a factor of nine, and a linear map is
|
|
198
|
+
* the one that keeps that factor of nine meaning a factor of nine. It is also
|
|
199
|
+
* exactly zero at zero without a special case, which a log map cannot be.
|
|
200
|
+
*
|
|
201
|
+
* ## Sixty, because that is "the cloth goes where the air goes"
|
|
202
|
+
*
|
|
203
|
+
* The rate is a reciprocal time constant, so what `drag = 1` has to mean is a
|
|
204
|
+
* cloth with no aerodynamic memory at all — one that takes the air's velocity
|
|
205
|
+
* within a step. At 60 Hz, a rate of 60 closes 63% of the gap to the air every
|
|
206
|
+
* step and has a time constant of 17 ms, which is that. The library then reads:
|
|
207
|
+
* silk 27/s (37 ms), hair 18/s, cotton 12/s (83 ms), rope 7.2/s, denim 4.8/s
|
|
208
|
+
* (0.21 s), leather and chain 3/s (0.33 s) — a light banner that answers a gust
|
|
209
|
+
* within a couple of frames and an armour skirt that takes a third of a second
|
|
210
|
+
* to notice one, which is the ordering the fabrics already claimed.
|
|
211
|
+
*
|
|
212
|
+
* Raising it further buys nothing: {@link cloth_drag_response} saturates at
|
|
213
|
+
* `1/dt` by construction, so past about `1/dt` the whole range compresses into
|
|
214
|
+
* "the cloth is a streamer". `MEASUREMENTS.md` §48.
|
|
215
|
+
* @type {number}
|
|
216
|
+
*/
|
|
217
|
+
export const CLOTH_DRAG_RATE_MAX = 60;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Speed below which the air counts as unchanged, as a fraction of the cloth's
|
|
221
|
+
* reach per second — §10's wake test, which asks whether a gust has arrived.
|
|
222
|
+
*
|
|
223
|
+
* This was the sleep test's own threshold until the sleep test stopped reading
|
|
224
|
+
* a speed; see {@link CLOTH_SLEEP_DISPLACEMENT_RATIO} for why.
|
|
225
|
+
* @type {number}
|
|
226
|
+
*/
|
|
227
|
+
export const CLOTH_SLEEP_SPEED_RATIO = 1e-3;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* How far a particle may travel from the window's anchor and still count as
|
|
231
|
+
* still, as a fraction of the cloth's reach (§7 P5).
|
|
232
|
+
*
|
|
233
|
+
* **Displacement rather than speed, and a contact is why.** A cloth resting on
|
|
234
|
+
* a collider carries contact rows whose penalty `γ = 1` never decays, and the
|
|
235
|
+
* configuration it settles into is a *bounded limit cycle* rather than a rest
|
|
236
|
+
* state: measured on an 8-link rope on a floor, a tenth of a millimetre of
|
|
237
|
+
* travel per step — invisible — at a peak particle speed of 1.5e-2 m/s, which
|
|
238
|
+
* is eighteen times what the old speed threshold allowed. An instantaneous
|
|
239
|
+
* speed cannot tell a cloth vibrating in place apart from one going somewhere;
|
|
240
|
+
* the distance it has covered since the window opened can, and that is what
|
|
241
|
+
* §7 P5's own text has always described.
|
|
242
|
+
*
|
|
243
|
+
* `5e-4` rather than {@link CLOTH_SLEEP_SPEED_RATIO}'s `1e-3` so the gate is no
|
|
244
|
+
* *looser* than the speed test it replaces: over the {@link CLOTH_SLEEP_STEPS}
|
|
245
|
+
* window at the engine's 60 Hz fixed step, half a thousandth of a reach is the
|
|
246
|
+
* same millimetre a second. Every library entry on a floor or a sphere sleeps
|
|
247
|
+
* inside 961 steps at this value. `MEASUREMENTS.md` §53.
|
|
248
|
+
* @type {number}
|
|
249
|
+
*/
|
|
250
|
+
export const CLOTH_SLEEP_DISPLACEMENT_RATIO = 5e-4;
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* How many consecutive still steps put a cloth to sleep (§7 P5). Half a second
|
|
254
|
+
* at 60 Hz, which is long enough that a cloth pausing at the top of a swing
|
|
255
|
+
* does not sleep through the way down.
|
|
256
|
+
* @type {number}
|
|
257
|
+
*/
|
|
258
|
+
export const CLOTH_SLEEP_STEPS = 30;
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Fabric extension allowance for a normalised `stretch`, as a fraction of rest
|
|
262
|
+
* length. Log-mapped between {@link CLOTH_STRAIN_MAX} and
|
|
263
|
+
* {@link CLOTH_STRAIN_MIN}, so equal steps in `stretch` are equal ratios in
|
|
264
|
+
* strain and `0.9` is not four orders of magnitude away from `0.7`.
|
|
265
|
+
*
|
|
266
|
+
* @param {number} stretch `[0, 1]`
|
|
267
|
+
* @returns {number} strain, `L_max = L₀·(1 + ε)`
|
|
268
|
+
*/
|
|
269
|
+
export function cloth_strain_allowance(stretch) {
|
|
270
|
+
const t = stretch < 0 ? 0 : (stretch > 1 ? 1 : stretch);
|
|
271
|
+
|
|
272
|
+
return CLOTH_STRAIN_MAX * Math.pow(CLOTH_STRAIN_MIN / CLOTH_STRAIN_MAX, t);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Bend row stiffness for a normalised `bend`, as a multiple of the row's own
|
|
277
|
+
* `m_eff/dt²`. Log-mapped, and **exactly zero at `bend = 0`** — a log map
|
|
278
|
+
* cannot reach zero, and "no bending resistance at all" is a state a chain is
|
|
279
|
+
* actually in rather than a limit it approaches.
|
|
280
|
+
*
|
|
281
|
+
* @param {number} bend `[0, 1]`
|
|
282
|
+
* @returns {number} ratio of `m_eff/dt²`
|
|
283
|
+
*/
|
|
284
|
+
export function cloth_bend_ratio(bend) {
|
|
285
|
+
if (bend <= 0) {
|
|
286
|
+
return 0;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const t = bend > 1 ? 1 : bend;
|
|
290
|
+
|
|
291
|
+
return CLOTH_BEND_RATIO_MIN * Math.pow(CLOTH_BEND_RATIO_MAX / CLOTH_BEND_RATIO_MIN, t);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Largest speed a particle may carry, metres per second. §7 P1, and see
|
|
296
|
+
* {@link CLOTH_VELOCITY_CORRECTION_MARGIN} for why this is built out of the
|
|
297
|
+
* mesh and the budget rather than out of `thickness`.
|
|
298
|
+
*
|
|
299
|
+
* @param {number} shortest_row metres — the shortest row in the cloth, which
|
|
300
|
+
is what the trust region caps a vertex update at
|
|
301
|
+
* @param {number} substeps
|
|
302
|
+
* @param {number} iterations
|
|
303
|
+
* @param {number} dt fixed step, seconds
|
|
304
|
+
* @returns {number}
|
|
305
|
+
*/
|
|
306
|
+
export function cloth_velocity_limit(shortest_row, substeps, iterations, dt) {
|
|
307
|
+
return CLOTH_VELOCITY_CORRECTION_MARGIN * shortest_row * substeps * iterations / dt;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* §10's aerodynamic coupling as the **per-step response** the step multiplies
|
|
312
|
+
* the relative flow by, 1/s.
|
|
313
|
+
*
|
|
314
|
+
* Not a rate, and the difference is a stability argument rather than a
|
|
315
|
+
* convenience. The step holds one acceleration for the whole fixed step, so an
|
|
316
|
+
* explicit `rate·(u − v)` changes the velocity by `rate·dt·(u − v)` — which
|
|
317
|
+
* overshoots the air once `rate·dt > 1` and diverges past 2. §1's first
|
|
318
|
+
* commitment is "not at 5 fps", which is a `dt` of 0.2 s and a rate of 10.
|
|
319
|
+
*
|
|
320
|
+
* The exact solution of the same linear ODE has no such boundary:
|
|
321
|
+
*
|
|
322
|
+
* Δv = (1 − e^(−rate·dt))·(u − v)
|
|
323
|
+
*
|
|
324
|
+
* closes a fraction of the gap that is strictly below one for every `rate` and
|
|
325
|
+
* every `dt`, so the drag can never push a particle past the air it is
|
|
326
|
+
* relaxing toward. Dividing by `dt` turns it back into the acceleration the
|
|
327
|
+
* solver wants, and the exponential is evaluated **once per cloth per step** on
|
|
328
|
+
* the main thread rather than per particle.
|
|
329
|
+
*
|
|
330
|
+
* It is also the same step `GlobalFluidEffector` takes for the air itself —
|
|
331
|
+
* both are relaxations toward a velocity, and a cloth and the air around it
|
|
332
|
+
* reaching their common answer by the same arithmetic is a symmetry worth
|
|
333
|
+
* having.
|
|
334
|
+
*
|
|
335
|
+
* @param {number} drag `[0, 1]`
|
|
336
|
+
* @param {number} dt fixed step, seconds
|
|
337
|
+
* @returns {number} 1/s; `0` when there is no coupling at all
|
|
338
|
+
*/
|
|
339
|
+
export function cloth_drag_response(drag, dt) {
|
|
340
|
+
if (drag <= 0 || dt <= 0) {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const rate = CLOTH_DRAG_RATE_MAX * (drag > 1 ? 1 : drag);
|
|
345
|
+
|
|
346
|
+
// `-expm1(-x)` is `1 - exp(-x)` without the cancellation at small `x`, and
|
|
347
|
+
// small `x` is every fabric below silk at a 60 Hz step.
|
|
348
|
+
return -Math.expm1(-rate * dt) / dt;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Fraction of a particle's velocity surviving one fixed step. §7 P5, and see
|
|
353
|
+
* {@link ClothDynamics#damping} for why this is a correctness mechanism rather
|
|
354
|
+
* than a taste control.
|
|
355
|
+
*
|
|
356
|
+
* @param {number} damping `[0, 1]`
|
|
357
|
+
* @param {number} dt fixed step, seconds
|
|
358
|
+
* @returns {number} `[0, 1]`
|
|
359
|
+
*/
|
|
360
|
+
export function cloth_velocity_retention(damping, dt) {
|
|
361
|
+
if (damping <= 0) {
|
|
362
|
+
return 1;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return Math.exp(-CLOTH_DAMPING_RATE * (damping > 1 ? 1 : damping) * dt);
|
|
366
|
+
}
|