@woosh/meep-engine 3.43.0 → 3.45.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/build/bundle-worker-terrain.js +1 -1
- package/editor/prototypeEditorShell.d.ts.map +1 -1
- package/editor/prototypeEditorShell.js +4 -2
- package/package.json +1 -1
- package/src/core/collection/array/array_sort_insertion_ascending.d.ts +19 -0
- package/src/core/collection/array/array_sort_insertion_ascending.d.ts.map +1 -0
- package/src/core/collection/array/array_sort_insertion_ascending.js +31 -0
- package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts +27 -0
- package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.d.ts.map +1 -0
- package/src/core/geom/3d/aabb/aabb3_array_round_outward_f32.js +39 -0
- package/src/core/geom/3d/aabb/aabb3_from_v3_array.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_from_v3_array.js +4 -1
- package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts +2 -2
- package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -1
- package/src/core/geom/3d/aabb/aabb3_transform_oriented.js +1 -1
- package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts +21 -0
- package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.d.ts.map +1 -0
- package/src/core/geom/3d/pose/pose3_apply_inverse_point_array.js +36 -0
- package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts +25 -0
- package/src/core/geom/3d/pose/pose3_apply_point_array.d.ts.map +1 -0
- package/src/core/geom/3d/pose/pose3_apply_point_array.js +40 -0
- package/src/core/geom/3d/pose/pose3_compose_array.d.ts +28 -0
- package/src/core/geom/3d/pose/pose3_compose_array.d.ts.map +1 -0
- package/src/core/geom/3d/pose/pose3_compose_array.js +41 -0
- package/src/core/geom/3d/pose/pose3_to_local_array.d.ts +29 -0
- package/src/core/geom/3d/pose/pose3_to_local_array.d.ts.map +1 -0
- package/src/core/geom/3d/pose/pose3_to_local_array.js +42 -0
- package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts +28 -0
- package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_clamp_angle_array.js +66 -0
- package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts +22 -0
- package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_left_array.js +30 -0
- package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts +23 -0
- package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_multiply_conjugate_right_array.js +31 -0
- package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts +26 -0
- package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.d.ts.map +1 -0
- package/src/core/geom/3d/triangle/tri3_compute_normal_area_weighted_array.js +46 -0
- package/src/core/geom/vec3/v3_distance_array.d.ts +11 -0
- package/src/core/geom/vec3/v3_distance_array.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_distance_array.js +19 -0
- package/src/core/geom/vec3/v3_normalize_array_checked.d.ts +23 -0
- package/src/core/geom/vec3/v3_normalize_array_checked.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_normalize_array_checked.js +49 -0
- package/src/core/geom/vec3/v3_reject_array.d.ts +15 -0
- package/src/core/geom/vec3/v3_reject_array.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_reject_array.js +32 -0
- package/src/core/graph/csr/csr_build_incidence.d.ts +26 -0
- package/src/core/graph/csr/csr_build_incidence.d.ts.map +1 -0
- package/src/core/graph/csr/csr_build_incidence.js +71 -0
- package/src/core/graph/csr/csr_graph_color_greedy.d.ts +25 -0
- package/src/core/graph/csr/csr_graph_color_greedy.d.ts.map +1 -0
- package/src/core/graph/csr/csr_graph_color_greedy.js +83 -0
- package/src/core/graph/csr/csr_graph_validate_coloring.d.ts +15 -0
- package/src/core/graph/csr/csr_graph_validate_coloring.d.ts.map +1 -0
- package/src/core/graph/csr/csr_graph_validate_coloring.js +33 -0
- package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts +26 -0
- package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.d.ts.map +1 -0
- package/src/core/math/linalg/matrix_symmetric_3x3_solve_ldlt.js +71 -0
- package/src/core/math/max2_exact.d.ts +15 -0
- package/src/core/math/max2_exact.d.ts.map +1 -0
- package/src/core/math/max2_exact.js +30 -0
- package/src/core/math/min2_exact.d.ts +20 -0
- package/src/core/math/min2_exact.d.ts.map +1 -0
- package/src/core/math/min2_exact.js +35 -0
- package/src/engine/Clock.d.ts +15 -0
- package/src/engine/Clock.d.ts.map +1 -1
- package/src/engine/Clock.js +29 -5
- package/src/engine/Engine.d.ts.map +1 -1
- package/src/engine/Engine.js +11 -19
- package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -1
- package/src/engine/ecs/ik/IKGoalSystem.js +3 -19
- package/src/engine/ecs/parent/parent_entity_model_of.d.ts +17 -0
- package/src/engine/ecs/parent/parent_entity_model_of.d.ts.map +1 -0
- package/src/engine/ecs/parent/parent_entity_model_of.js +26 -0
- package/src/engine/ecs/transform/t64_read_pose_array.d.ts +15 -0
- package/src/engine/ecs/transform/t64_read_pose_array.d.ts.map +1 -0
- package/src/engine/ecs/transform/t64_read_pose_array.js +24 -0
- package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts +57 -0
- package/src/engine/graphics/ecs/mesh-v2/MeshSkin.d.ts.map +1 -0
- package/src/engine/graphics/ecs/mesh-v2/MeshSkin.js +84 -0
- package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts +2 -0
- package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.d.ts.map +1 -1
- package/src/engine/graphics/geometry/geometry_construct_triangle_normal_area_weighted.js +10 -21
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +28 -13
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +107 -64
- package/src/engine/graphics3/AnimationSystem.d.ts +29 -15
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +112 -61
- package/src/engine/graphics3/MeshSkinSystem.d.ts +56 -0
- package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -0
- package/src/engine/graphics3/MeshSkinSystem.js +317 -0
- package/src/engine/graphics3/MeshSystem.d.ts +15 -35
- package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
- package/src/engine/graphics3/MeshSystem.js +21 -298
- package/src/engine/graphics3/RowChains.d.ts +76 -0
- package/src/engine/graphics3/RowChains.d.ts.map +1 -0
- package/src/engine/graphics3/RowChains.js +347 -0
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts +6 -0
- package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
- package/src/engine/graphics3/ShadedGeometrySystem.js +329 -309
- package/src/engine/graphics3/animation/AnimationClips.d.ts +56 -0
- package/src/engine/graphics3/animation/AnimationClips.d.ts.map +1 -0
- package/src/engine/graphics3/animation/AnimationClips.js +79 -0
- package/src/engine/graphics3/animation/ClipListPlayer.d.ts +13 -14
- package/src/engine/graphics3/animation/ClipListPlayer.d.ts.map +1 -1
- package/src/engine/graphics3/animation/ClipListPlayer.js +262 -263
- package/src/engine/graphics3/animation/write_clip_playback.d.ts +3 -3
- package/src/engine/graphics3/animation/write_clip_playback.js +4 -4
- package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts +5 -0
- package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
- package/src/engine/graphics3/pose/query_entity_node_world_pose.js +80 -75
- package/src/engine/graphics3/prefab/PrefabInstance.d.ts +4 -24
- package/src/engine/graphics3/prefab/PrefabInstance.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/PrefabInstance.js +60 -80
- package/src/engine/graphics3/prefab/prefab_instantiate.d.ts +16 -3
- package/src/engine/graphics3/prefab/prefab_instantiate.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/prefab_instantiate.js +49 -12
- package/src/engine/graphics3/prefab/prefab_place.d.ts +31 -17
- package/src/engine/graphics3/prefab/prefab_place.d.ts.map +1 -1
- package/src/engine/graphics3/prefab/prefab_place.js +175 -130
- package/src/engine/graphics3/register_clips.d.ts +93 -0
- package/src/engine/graphics3/register_clips.d.ts.map +1 -0
- package/src/engine/graphics3/register_clips.js +166 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +9 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
- package/src/engine/physics/broadphase/compute_fat_world_aabb.js +3 -1
- package/src/engine/physics/cloth/MEASUREMENTS.md +795 -0
- package/src/engine/physics/cloth/PLAN.md +349 -17
- package/src/engine/physics/cloth/build/ClothProxy.d.ts +113 -61
- package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -1
- package/src/engine/physics/cloth/build/ClothProxy.js +142 -77
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +44 -0
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -0
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +107 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +43 -30
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -1
- package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +371 -284
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts +62 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -0
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +275 -0
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +7 -0
- package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/ClothColliderIndex.js +85 -67
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +19 -101
- package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +2 -5
- package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_pack.js +7 -15
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +17 -62
- package/src/engine/physics/cloth/ecs/Cloth.d.ts +17 -9
- package/src/engine/physics/cloth/ecs/Cloth.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/Cloth.js +220 -212
- package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +0 -1
- package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +6 -19
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +1 -2
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +3 -12
- package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +6 -0
- package/src/engine/physics/cloth/ecs/ClothHold.d.ts +91 -0
- package/src/engine/physics/cloth/ecs/ClothHold.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothHold.js +103 -0
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +254 -48
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +277 -47
- package/src/engine/physics/cloth/ecs/ClothPin.d.ts +73 -0
- package/src/engine/physics/cloth/ecs/ClothPin.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothPin.js +92 -0
- package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts +36 -0
- package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/ClothPinSerializationAdapter.js +61 -0
- package/src/engine/physics/cloth/ecs/ClothRig.d.ts +23 -17
- package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothRig.js +29 -27
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +12 -14
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +20 -15
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts +57 -36
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +754 -207
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts +12 -13
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/WorkerClothSystem.js +20 -14
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +63 -11
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +297 -101
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts +9 -7
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +12 -10
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +3 -3
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +60 -120
- package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts +37 -0
- package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_geodesic.js +135 -0
- package/src/engine/physics/cloth/ecs/cloth_holds.d.ts +97 -0
- package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -0
- package/src/engine/physics/cloth/ecs/cloth_holds.js +583 -0
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +2 -2
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +168 -51
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +17 -22
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +55 -117
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +21 -6
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +51 -42
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +5 -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 +62 -50
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +65 -58
- package/src/engine/physics/cloth/playground/cloth_playground_build.d.ts.map +1 -1
- package/src/engine/physics/cloth/playground/cloth_playground_build.js +2 -3
- package/src/engine/physics/cloth/playground/collide_main.js +3 -29
- package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -1
- package/src/engine/physics/cloth/playground/garment_build.js +17 -5
- package/src/engine/physics/cloth/playground/garment_main.js +5 -20
- package/src/engine/physics/cloth/playground/main.js +6 -48
- package/src/engine/physics/cloth/playground/rig_build.d.ts.map +1 -1
- package/src/engine/physics/cloth/playground/rig_build.js +302 -296
- package/src/engine/physics/cloth/playground/rig_main.js +947 -955
- package/src/engine/physics/cloth/playground/wind_main.js +8 -7
- package/src/engine/physics/cloth/solver/ClothState.d.ts +45 -7
- package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +79 -83
- package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts +10 -8
- package/src/engine/physics/cloth/solver/cloth_color_particles.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_color_particles.js +30 -102
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +6 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +9 -3
- package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts +114 -0
- package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_hold_line.js +350 -0
- package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts +21 -0
- package/src/engine/physics/cloth/solver/cloth_kinetic_energy.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_kinetic_energy.js +45 -0
- package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts +32 -0
- package/src/engine/physics/cloth/solver/cloth_particle_coupling.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_particle_coupling.js +133 -0
- package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts +16 -0
- package/src/engine/physics/cloth/solver/cloth_particle_of_source.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_particle_of_source.js +19 -0
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +6 -2
- package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_self_find.js +19 -68
- package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +30 -65
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +24 -12
- package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_solver_constants.js +24 -12
- package/src/engine/physics/cloth/solver/cloth_step.d.ts +16 -0
- package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +189 -48
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts +1 -0
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +12 -6
- package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts +21 -0
- package/src/engine/physics/cloth/solver/cloth_stretch_residual.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_stretch_residual.js +54 -0
- package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts +15 -0
- package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_vertex_accumulator.js +28 -0
- package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts +30 -0
- package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.d.ts.map +1 -0
- package/src/engine/physics/cloth/solver/cloth_worst_tether_ratio.js +56 -0
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +3 -17
- package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_leash_row.js +353 -346
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +7 -5
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +7 -5
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts +2 -1
- package/src/engine/physics/cloth/wind/ClothFluidWind.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/ClothFluidWind.js +7 -25
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts +12 -10
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +60 -82
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/ContactProbeSystem.js +2 -18
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +9 -50
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts +24 -0
- package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/fluid_sample_domain_bounds.js +42 -0
- package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts +25 -0
- package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.d.ts.map +1 -0
- package/src/engine/physics/fluid/ecs/fluid_sample_velocity_world_mps.js +40 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -1
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +40 -90
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_contacts.js +3 -5
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +2 -14
- package/src/engine/physics/narrowphase/hull_sphere_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/hull_sphere_contact.js +2 -5
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +13 -32
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/sphere_box_contact.js +2 -5
- package/src/engine/simulation/Ticker.d.ts +13 -0
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +43 -8
- package/src/format/texture/basis/transcode/etc1s_to_astc.d.ts.map +1 -1
- package/src/format/texture/basis/transcode/etc1s_to_astc.js +2 -1
- package/src/shade/RENDERER_CONTRACT.md +8 -2
- package/src/shade/playground/image_decode_bench/main.js +2 -1
- package/src/shade/playground/mesh_row_ceiling/main.js +2 -1
- package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/diff_traced_against_rasterized.js +2 -1
- package/src/shade/playground/skinned_blas_refit/main.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/main.js +11 -19
- package/src/shade/playground/skinned_blas_refit/place_character.d.ts +6 -3
- package/src/shade/playground/skinned_blas_refit/place_character.d.ts.map +1 -1
- package/src/shade/playground/skinned_blas_refit/place_character.js +90 -90
- package/src/shade/playground/skinned_mesh_soup/main.d.ts.map +1 -1
- package/src/shade/playground/skinned_mesh_soup/main.js +502 -509
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.d.ts.map +1 -1
- package/src/shade/playground/skinned_mesh_soup/verify_clone_vertices.js +2 -1
- package/src/shade/playground/ssr_variance/statistics.d.ts.map +1 -1
- package/src/shade/playground/ssr_variance/statistics.js +2 -1
- package/src/shade/playground/texture_encode/README.md +129 -109
- package/src/shade/playground/texture_encode/main.d.ts.map +1 -1
- package/src/shade/playground/texture_encode/main.js +1431 -1430
- package/src/shade/playground/volumetrics_froxel/measure.d.ts.map +1 -1
- package/src/shade/playground/volumetrics_froxel/measure.js +2 -1
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +45 -14
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +316 -64
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts +5 -0
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.d.ts.map +1 -1
- package/src/shade/renderer/animation/skinning/GPUMeshSkinningContext.js +11 -1
- package/src/shade/renderer/buffer/table/gpu_database_check_links.d.ts.map +1 -1
- package/src/shade/renderer/buffer/table/gpu_database_check_links.js +2 -1
- package/src/shade/renderer/geometry/BoxGeometry.d.ts +1 -11
- package/src/shade/renderer/geometry/BoxGeometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/BoxGeometry.js +6 -13
- package/src/shade/renderer/geometry/CapsuleGeometry.d.ts +19 -0
- package/src/shade/renderer/geometry/CapsuleGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/CapsuleGeometry.js +24 -0
- package/src/shade/renderer/geometry/ConeGeometry.d.ts +20 -0
- package/src/shade/renderer/geometry/ConeGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/ConeGeometry.js +33 -0
- package/src/shade/renderer/geometry/CylinderGeometry.d.ts +21 -0
- package/src/shade/renderer/geometry/CylinderGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/CylinderGeometry.js +35 -0
- package/src/shade/renderer/geometry/PlaneGeometry.d.ts +17 -0
- package/src/shade/renderer/geometry/PlaneGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/PlaneGeometry.js +22 -0
- package/src/shade/renderer/geometry/TorusGeometry.d.ts +18 -0
- package/src/shade/renderer/geometry/TorusGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/TorusGeometry.js +23 -0
- package/src/shade/renderer/geometry/UVSphereGeometry.d.ts +21 -0
- package/src/shade/renderer/geometry/UVSphereGeometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/UVSphereGeometry.js +34 -0
- package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts +19 -0
- package/src/shade/renderer/geometry/primitives/make_capsule_geometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/primitives/make_capsule_geometry.js +205 -0
- package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts +21 -0
- package/src/shade/renderer/geometry/primitives/make_cone_geometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/primitives/make_cone_geometry.js +36 -0
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts +1 -1
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/primitives/make_cylinder_geometry.js +44 -9
- package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts +20 -0
- package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.d.ts.map +1 -0
- package/src/shade/renderer/geometry/primitives/make_uv_sphere_geometry.js +190 -0
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_group_step.js +3 -2
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_leaf_frontier.js +2 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_partition_into_groups.js +2 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_run_round.js +2 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/level/vgeo_try_repack.js +3 -2
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.js +2 -1
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.js +2 -1
- 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 +3 -2
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/graph_vgeo_expand_instances_to_meshlets.js +7 -2
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts +26 -8
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/graph_prefix_scan_csdldf.js +56 -39
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts +7 -0
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/shader_prefix_scan_csdldf.js +46 -4
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/prefix_sum/v1/test_prefix_sum.js +4 -2
- package/src/shade/renderer/gpu_primitive/sort/defs.d.ts +2 -2
- package/src/shade/renderer/gpu_primitive/sort/defs.js +79 -79
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.d.ts.map +1 -1
- package/src/shade/renderer/gpu_primitive/sort/graph_radix_sort.js +7 -3
- package/src/shade/renderer/particles/GPUParticleSystem.js +1 -1
- package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +4 -3
- package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
- package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +200 -194
- package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
- package/src/shade/renderer/particles/graph_particles.js +6 -2
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +3 -2
- package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -1
- package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +334 -329
- 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 +7 -2
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/mesh/graph_expand_meshes_to_meshlets.js +16 -4
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +2444 -2345
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_astc_encode_block_4x4_rgb.js +312 -310
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts +3 -3
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc1_encode_block.js +383 -375
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc6h_encode_block_mode11.js +349 -346
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts +58 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block.js +536 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts +21 -7
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc7_encode_block_mode6.js +291 -327
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts +25 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode1.js +99 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts +5 -3
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/chunk_bc7_pack_mode6.js +47 -71
- package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts +10 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.d.ts.map +1 -0
- package/src/shade/renderer/texture/encode/chunk_bc7_partition_2.js +50 -0
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts +4 -5
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.d.ts.map +1 -1
- package/src/shade/renderer/texture/encode/shader_texture_encode_bc7.js +7 -8
- package/src/shade/renderer/water/chunk_water_transport.d.ts.map +1 -1
- package/src/shade/renderer/water/chunk_water_transport.js +7 -5
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +1 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +8 -2
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts +3 -2
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.d.ts.map +1 -1
- package/src/shade/renderer/water/optics/chunk_water_receiver_downwelling.js +3 -2
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +3 -1
- package/src/shade/renderer/water/surface/GPUWaterSurface.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/GPUWaterSurface.js +3 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +11 -4
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.d.ts.map +1 -1
- package/src/shade/renderer/water/surface/particles/GPUWaterParticles.js +37 -20
- package/src/shade/wgsl/validate_wgsl_source.d.ts.map +1 -1
- package/src/shade/wgsl/validate_wgsl_source.js +74 -3
- package/src/engine/graphics3/register_instance_animation.d.ts +0 -114
- package/src/engine/graphics3/register_instance_animation.d.ts.map +0 -1
- package/src/engine/graphics3/register_instance_animation.js +0 -201
|
@@ -18,10 +18,15 @@ One solver over particles, driven by components:
|
|
|
18
18
|
- **`Cloth`** — the thing that simulates. Put it on an entity and that entity's transform subtree
|
|
19
19
|
becomes a simulated chain: a rope, a chain, a hanging sign, a mooring line.
|
|
20
20
|
- **`ClothRig`** — add it alongside `Cloth` and the particles are the **joints of a skinned model**
|
|
21
|
-
rather than the entity subtree. This is what makes a cape, a skirt, a banner on a character
|
|
21
|
+
rather than the entity subtree. This is what makes a cape, a skirt, a banner on a character — and,
|
|
22
|
+
built from triangles by `cloth_proxy_from_mesh`, a sheet: a flag, a curtain, a cloth thrown over a
|
|
23
|
+
table (§19.5).
|
|
22
24
|
- **`ClothCollider`** — the marker that opts an existing `(Collider, Transform64)` entity into being
|
|
23
25
|
something cloth collides with. This is the `RigidBody`-analogue: it says *this collider participates*,
|
|
24
26
|
and carries only what cloth needs that `Collider` does not already say.
|
|
27
|
+
- **`ClothPin`** — *M7.* Put it on any entity and that entity holds the particles it names. A cloth
|
|
28
|
+
has as many holders as name it — a rope its own top, a flag its pole, a cape both shoulders — and
|
|
29
|
+
none is a cloth that falls. §19.
|
|
25
30
|
|
|
26
31
|
That last component follows a pattern the engine already has twice. `AcousticBody` opts a collider
|
|
27
32
|
into the acoustic simulation and carries an `AcousticMaterial`; `FluidObstacle` opts a collider into
|
|
@@ -63,8 +68,10 @@ The design commitments, in priority order, because they conflict and the orderin
|
|
|
63
68
|
|
|
64
69
|
```js
|
|
65
70
|
// An entity hierarchy — rope, chain, hanging sign, a prop built out of entities.
|
|
66
|
-
// Cloth simulates the transform subtree of the entity it is on
|
|
71
|
+
// Cloth simulates the transform subtree of the entity it is on, that entity included.
|
|
72
|
+
// What holds it is a ClothPin: here the top holds its own particle, 0.
|
|
67
73
|
rope_top.add(Cloth.from(ClothDynamics.ROPE));
|
|
74
|
+
rope_top.add(ClothPin.from({ cloth: rope_top, particles: [0] }));
|
|
68
75
|
|
|
69
76
|
// A skinned model's garment — cape, skirt, banner, hair.
|
|
70
77
|
// Cloth simulates the JOINTS of the model instance this entity owns.
|
|
@@ -76,6 +83,12 @@ There is no mode enum and no discriminator field. **`Cloth` alone simulates the
|
|
|
76
83
|
`Cloth` + `ClothRig` simulates a skinned model's joints** — component presence doing the job an enum
|
|
77
84
|
would otherwise do badly. The solver is identical either way; only seeding and write-back differ.
|
|
78
85
|
|
|
86
|
+
**M7 note: what holds a cloth is not part of it.** Every sentence below that says "the anchor" meant
|
|
87
|
+
three things at once — the frame the cloth is simulated in, the particle it was pinned at, and what
|
|
88
|
+
its tethers measured from — and only the first is the `Cloth` entity's. The fixed set is now whatever
|
|
89
|
+
`ClothPin`s name (§19), any number of them, and the rest of the "anchor" sentences are read through
|
|
90
|
+
§19.
|
|
91
|
+
|
|
79
92
|
Those are two cases rather than one because **the engine has two hierarchies, and that is a decision
|
|
80
93
|
rather than an accident**. `shade_node_to_entity_composition` expands a loaded model into entities and
|
|
81
94
|
gives a `ShadedGeometry` to every node that draws — except a skinned one, which "is not expanded, and
|
|
@@ -113,6 +126,13 @@ Two rules keep the walk unambiguous:
|
|
|
113
126
|
With a `ClothRig`, the entity is instead the one that owns the skinned model instance, and the
|
|
114
127
|
subtree walk does not run at all — the particle set comes from the proxy's joint list (§3.2).
|
|
115
128
|
|
|
129
|
+
**M7 corrected "the anchor is the entity the component is on".** The entity is the cloth's **frame**:
|
|
130
|
+
what it is simulated in and what §7 P7's inertia is measured against. It is still particle 0 of the
|
|
131
|
+
walk — links run from it — but nothing pins it: a `ClothPin` on it does, `ClothPin.from({ cloth: e,
|
|
132
|
+
particles: [0] })`, and without one the rope falls while the entity, which cloth reads and never
|
|
133
|
+
writes, stays where it is. That is the price of there being no structural pin, paid in one line per
|
|
134
|
+
rope, and §19 has why it is the right one.
|
|
135
|
+
|
|
116
136
|
`blend` is the escape hatch for cinematics, LOD and "turn it off for this one shot". It is a lerp
|
|
117
137
|
between the animated pose and the simulated pose applied at write-back, not a solver parameter, so it
|
|
118
138
|
is free and always safe. **M1 note:** writing it wakes a sleeping cloth, because sleep skips the
|
|
@@ -124,7 +144,7 @@ effect at whatever later moment something else happened to wake it.
|
|
|
124
144
|
```js
|
|
125
145
|
export class ClothRig {
|
|
126
146
|
proxy = null; // ClothProxy — shared, immutable, built at import
|
|
127
|
-
skin =
|
|
147
|
+
skin = -1; // the entity whose MeshSkin the proxy's joint indices are into
|
|
128
148
|
}
|
|
129
149
|
```
|
|
130
150
|
|
|
@@ -132,7 +152,13 @@ A `ClothProxy` **object**, not a path. This is the convention the engine already
|
|
|
132
152
|
that points at a built, shared, immutable asset: `Collider#shape` holds an `AbstractShape3D` and is
|
|
133
153
|
documented as *not* serialised because shapes are shared assets the pipeline wires up;
|
|
134
154
|
`ParticleEffect` holds a `ParticleLayout` and a `ParticleProgram` the same way. `ClothRig` serialises
|
|
135
|
-
the proxy's identity and the skin
|
|
155
|
+
the proxy's identity and the skin's entity, and the asset pipeline resolves the rest.
|
|
156
|
+
|
|
157
|
+
**The skin is an entity's, named by entity** (2026-10-11). `skin` was an ordinal into the skins of
|
|
158
|
+
whatever `MeshSystem.instance_of` answered for the cloth's entity, which made a rig reachable only
|
|
159
|
+
through a loaded model. A skin is now a `MeshSkin` component on the mesh it deforms, and the rig
|
|
160
|
+
names that entity; a mesh built in code is rigged the same way as a loaded one. -1 means not named
|
|
161
|
+
yet, and waits like a model still loading.
|
|
136
162
|
|
|
137
163
|
**The proxy addresses joints by index, never by name.** The binding is resolved **once, at import**:
|
|
138
164
|
the builder turns authored bone names into integer indices into `Skin#joints`, and the runtime
|
|
@@ -223,7 +249,10 @@ reach of that position. Three things fall out of that and none of them need a kn
|
|
|
223
249
|
- **The profile is automatic.** A hem gets a long leash and a waistband gets a short one, because
|
|
224
250
|
that is what their geodesic depth says, not because someone painted it.
|
|
225
251
|
- **The fixed set falls out too.** A pinned particle has `d_geo = 0`, so `r_i = 0`, so the leash *is*
|
|
226
|
-
the pin. There is no separate attach constraint — one row covers both (§6).
|
|
252
|
+
the pin. There is no separate attach constraint — one row covers both (§6). *M7: not any more — a
|
|
253
|
+
held particle is kinematic, inverse mass zero, carried by its holder (§19); `d_geo` is its distance
|
|
254
|
+
to the nearest held particle along the fabric, and the animated position `s_i` is the rest pose hung
|
|
255
|
+
from that particle. The factor of two still holds exactly: `|s_i − x_p| = |r_i − r_p| ≤ d_geo`.*
|
|
227
256
|
- **There is no magic default.** The old formulation had a radius in metres with `0` meaning "derive
|
|
228
257
|
it from the mesh extent", which is the kind of overloaded sentinel that gets copied into a save file
|
|
229
258
|
and then means the wrong thing.
|
|
@@ -241,7 +270,7 @@ export class ClothCollider {
|
|
|
241
270
|
friction_scale = 1; // multiplies the entity's Collider#friction
|
|
242
271
|
layer = 1; // RigidBody semantics, and see below
|
|
243
272
|
mask = 0xFFFFFFFF;
|
|
244
|
-
flags = 0; // ClothColliderFlags
|
|
273
|
+
flags = 0; // ClothColliderFlags: none defined; bit 0 was Static, retired
|
|
245
274
|
}
|
|
246
275
|
```
|
|
247
276
|
|
|
@@ -295,6 +324,11 @@ engine/physics/cloth/
|
|
|
295
324
|
makeClothWorker.js the spawn expression, isolated because it needs import.meta
|
|
296
325
|
cloth_worker_protocol.js the command region: a count, then a block per cloth
|
|
297
326
|
ClothSerializationAdapter.js the component + its ClothDynamics, by value
|
|
327
|
+
ClothPin.js component: this entity holds these particles of that cloth (§19)
|
|
328
|
+
ClothPinSerializationAdapter.js the pin, with its cloth as a raw entity id
|
|
329
|
+
ClothHold.js one pin as the cloth sees it: offsets, the holder's pose
|
|
330
|
+
cloth_holds.js what holding decides: who is kinematic, tethers, the animated pose
|
|
331
|
+
cloth_geodesic.js distance along the fabric from a set of particles
|
|
298
332
|
ClothColliderSerializationAdapter.js five authored scalars, the same way
|
|
299
333
|
ClothRigSerializationAdapter.js NOT BUILT — §3.2's asset identity, and the proxy codec
|
|
300
334
|
collider/
|
|
@@ -485,6 +519,13 @@ iterate repeat `iterations` times:
|
|
|
485
519
|
H += k_c·(g gᵀ)
|
|
486
520
|
x_i += H⁻¹·f (3×3 LDLᵀ, capped at the shortest incident row)
|
|
487
521
|
|
|
522
|
+
last iteration only, when the held particles lie on one line (axis a through o):
|
|
523
|
+
for each free particle i: r_i = x_i − o, t_i = a × r_i
|
|
524
|
+
∇E_i, H_i = the vertex update's inertial term + leash, backstop, contact rows
|
|
525
|
+
g = Σ t_i·∇E_i
|
|
526
|
+
H = Σ t_iᵀ·H_i·t_i + max(0, Σ ∇E_i·(a(a·r_i) − r_i))
|
|
527
|
+
turn every free particle about the line by θ = −g/H
|
|
528
|
+
|
|
488
529
|
dual update, for each HARD constraint c:
|
|
489
530
|
λ_c ← clamp(k_c·C_c + λ_c, fmin_c, fmax_c)
|
|
490
531
|
k_c ← min(k_c + β·|C_c|, k_max·s_c)
|
|
@@ -563,6 +604,29 @@ non-positive-definite Hessian inside a second. A mechanism that costs, does not
|
|
|
563
604
|
the top of its own range is worse than its absence. `MEASUREMENTS.md` §21 keeps the grid so a future
|
|
564
605
|
attempt starts from the numbers.
|
|
565
606
|
|
|
607
|
+
**M7 added one block to the descent: the turn about a hold line** (`cloth_hold_line.js`). Every vertex
|
|
608
|
+
update is a 3×3 block, and a cloth whose held particles lie on one line has a motion no such block can
|
|
609
|
+
make — turning about the line as a rigid body. A vertex update moves one particle, so each adds
|
|
610
|
+
`x_i × m·Δx_i` of angular momentum about the line, and the step stopped at a fabric's iteration count
|
|
611
|
+
leaves a gradient along the turn. About a vertical line nothing restores it, and the warm start's
|
|
612
|
+
`α·γ = 0.25` means a cloth at rest re-solves three quarters of its weight every substep and is never a
|
|
613
|
+
fixed point: a flag on a pole turned for as long as it was run (§18).
|
|
614
|
+
|
|
615
|
+
So the turn gets its own block, in the listing above: one Newton step of `E` along it, in the last
|
|
616
|
+
iteration, after the sweep and before the dual update. Internal rows are invariant under the turn —
|
|
617
|
+
their ends turn together, or one of them is on the axis — so only the inertial term and the unary rows
|
|
618
|
+
enter. The last term of `H` is the path's own curvature, `d²x/dθ² = −r⊥`: near zero about a vertical
|
|
619
|
+
axis, the pendulum's gravity stiffness about a horizontal one, and added only where positive so the step
|
|
620
|
+
is never longer than the one without it. It is a descent step on the same energy, so §5.3 stands, and it
|
|
621
|
+
changes no row, multiplier or constant. It runs when the held particles lie on one line at that substep,
|
|
622
|
+
at two distinct points or more, to `2⁻¹⁶` of their largest coordinate. That is a runtime fact about the
|
|
623
|
+
holds, and the predict, which carries every held particle, lists them on its way.
|
|
624
|
+
|
|
625
|
+
What it does not cover: a single held point has three free turns and a cloth nothing holds has six, and
|
|
626
|
+
neither is handled. On a line gravity does restore it has slowed some sleeps and kept one cloth awake
|
|
627
|
+
(§18). Carrying the multiplier instead — AVBD's Eq. 18, or the reference code's post-stabilisation —
|
|
628
|
+
stops the turn too, and fails six to ten of the cloth gates. `MEASUREMENTS.md` §66.
|
|
629
|
+
|
|
566
630
|
### 5.3 Why the update never explodes
|
|
567
631
|
|
|
568
632
|
`H = (m/h²)·I + Σ_tension (fc/L)·(I − g gᵀ) + Σ_active k_c·(g gᵀ)`. The mass term is positive
|
|
@@ -611,10 +675,12 @@ bundles — the engine ships raw source, and a check moved out of `assert.*` sto
|
|
|
611
675
|
### 5.4 Colouring
|
|
612
676
|
|
|
613
677
|
The particle graph is coloured so no constraint touches two particles of the same colour, using the
|
|
614
|
-
|
|
615
|
-
`
|
|
616
|
-
the
|
|
617
|
-
|
|
678
|
+
greedy colouring in `core/graph/csr/csr_graph_color_greedy.js` and checked by
|
|
679
|
+
`csr_graph_validate_coloring.js`, over the deduplicated particle-coupling CSR that
|
|
680
|
+
`solver/cloth_particle_coupling.js` builds (the object `Graph` route was O(n²·degree): 134 ms → 3.5 ms
|
|
681
|
+
on a 64×64 sheet, same colours). Bending stencils span four particles, so the graph is the mesh graph plus
|
|
682
|
+
the bend diagonals — around 8–10 colours for typical garment topology. Colouring runs once, on that
|
|
683
|
+
CSR, and is baked into the `ClothProxy` as colour ranges over a permuted particle order;
|
|
618
684
|
for a chain it runs at link time on a graph of a few dozen nodes. Nothing colours per step and the
|
|
619
685
|
runtime never sees a graph object.
|
|
620
686
|
|
|
@@ -696,6 +762,15 @@ distinction between "pinned" and "loosely following" is a number rather than a b
|
|
|
696
762
|
`‖x − s‖` is undefined at `x = s`; the row is skipped below an epsilon, which is the standard guard and
|
|
697
763
|
is also exactly when it has nothing to do.)
|
|
698
764
|
|
|
765
|
+
**M7: and there still is none, but a pin is not a row either.** The anchor was pinned by inverse mass
|
|
766
|
+
zero all along, and that is what a hold is: a kinematic particle carried to where its holder puts it,
|
|
767
|
+
an equal share of the way at each substep (§19). Both leash rows now measure from a **particle** —
|
|
768
|
+
`ClothState#leash_source` and an offset, re-centred every substep after the held particles move —
|
|
769
|
+
because a centre written once a step sits a step behind a held particle that is moving, and a hard
|
|
770
|
+
row measured from a stale point fights the hold. The tether's centre is the nearest held particle,
|
|
771
|
+
not "the anchor"; a particle nothing holds has both rows at radius `Infinity`, skipped before any
|
|
772
|
+
arithmetic.
|
|
773
|
+
|
|
699
774
|
**Slack and tether are different questions, and a cape needs both.** Slack bounds distance to the
|
|
700
775
|
particle's *animated position*; the tether bounds distance to the *anchor*. Slack alone implies a
|
|
701
776
|
tether bound of `(1 + slack)·d_geo` — enough to stop a catastrophe, not enough to stop visible rubber —
|
|
@@ -1031,6 +1106,15 @@ cloth's own switches — a mode enum for two values is the discriminator field
|
|
|
1031
1106
|
frame anchored to the cloth's own entity the particles are already anchor-relative, so "apply the
|
|
1032
1107
|
delta" is doing nothing. The implementation is a `return`.
|
|
1033
1108
|
|
|
1109
|
+
**M7: a holder can jump too, and it is measured in the frame.** A rope tied to a ship that is moved
|
|
1110
|
+
across the map has a frame that did not move and a holder that did. The test is now the frame's jump
|
|
1111
|
+
in the world *or* any holder's jump in the frame, against the same threshold. `Reset` puts every
|
|
1112
|
+
particle on the animated pose hung from where the holders now are, held particles on their targets so
|
|
1113
|
+
the jump is taken between steps rather than dragged through one; `Keep` does nothing for the frame, as
|
|
1114
|
+
before, and for a holder applies that holder's own jump to what hangs from it. Measured: a hand holding
|
|
1115
|
+
a rope's top, moved a kilometre in one step, resets once and peaks under 5% of the velocity clamp
|
|
1116
|
+
(`cloth_pin.spec.js`).
|
|
1117
|
+
|
|
1034
1118
|
**P7 — Fast locomotion: whipping, lag, centrifugal spray.**
|
|
1035
1119
|
*Mechanism:* the simulation runs in a **local frame anchored to the cloth's own entity**, with
|
|
1036
1120
|
`ClothDynamics#inertia` controlling how much of the anchor's world motion the cloth is allowed to
|
|
@@ -1047,6 +1131,15 @@ against the cloth's own geometry so a 3 cm pendant and a 30 m mooring line get t
|
|
|
1047
1131
|
its range, which is what makes it a dial rather than a switch with a meaningless middle.
|
|
1048
1132
|
`MEASUREMENTS.md` §13.
|
|
1049
1133
|
|
|
1134
|
+
**M7: the frame is the only motion this softens.** A holder moving *relative to the frame* moves its
|
|
1135
|
+
particles in full — that is what holding means — so P7's limits protect a cloth whose holders ride its
|
|
1136
|
+
frame, which is every garment and every rope hung from its own top. A cloth held by something that
|
|
1137
|
+
moves independently — a banner between two characters — feels that motion unsoftened, and the frame
|
|
1138
|
+
it should ride is the author's choice, as Chaos Cloth's reference bone is. What bounds such a cloth is
|
|
1139
|
+
P1's clamp and P2's authority: measured, a hand dragging a rope at four times what one step can
|
|
1140
|
+
correct stays under the clamp every step and is back inside 1% of its tether within ten seconds of
|
|
1141
|
+
stopping (`cloth_pin.spec.js`).
|
|
1142
|
+
|
|
1050
1143
|
**P8 — Degenerate authoring.**
|
|
1051
1144
|
*Mechanism:* build-time validation, not runtime tolerance. The proxy builder welds duplicates, drops
|
|
1052
1145
|
zero-area triangles, and refuses non-manifold and inconsistently-wound configurations. The existing
|
|
@@ -1177,10 +1270,13 @@ it once at seed, in the bind pose, and the ceiling is two fifths of it. `MEASURE
|
|
|
1177
1270
|
"O(n) with a small constant" is right about the shape and optimistic about the constant: the pair
|
|
1178
1271
|
search is linear in particles with no term in the pair count, and it is **12% of a frame** at the
|
|
1179
1272
|
§17 workload, and most of everything self-collision costs. The rows themselves are nearly free.
|
|
1180
|
-
`MEASUREMENTS.md` §34. "The great majority of visible interpenetration" is 82% of it
|
|
1181
|
-
stiffness
|
|
1182
|
-
|
|
1183
|
-
|
|
1273
|
+
`MEASUREMENTS.md` §34. "The great majority of visible interpenetration" is 82% of it at the
|
|
1274
|
+
stiffness M4 shipped, `8·(m_eff/h²)`, which §32 chose on a folding sheet's crossing count.
|
|
1275
|
+
**Post-M7 corrected the stiffness to `2·(m_eff/h²)`.** §32's sheet showed no energy growth at 64×
|
|
1276
|
+
because its contacts come and go. A fold resting on a fold is a pair that carries weight, a spring
|
|
1277
|
+
that is on every step, and at 8 it never comes to rest (§18). 2 is the stiffest ratio that lets it,
|
|
1278
|
+
and it removes 63% to 71% of the folding sheet's crossings rather than 73% to 79%.
|
|
1279
|
+
`MEASUREMENTS.md` §32, §65.
|
|
1184
1280
|
|
|
1185
1281
|
*This tier cannot see cloth passing between particles.* A sheet thinner than its particle spacing can
|
|
1186
1282
|
still slip through itself. Stated, not hidden.
|
|
@@ -1517,9 +1613,16 @@ For a **rigged** garment, only steps 5–8 run, over the joint graph rather than
|
|
|
1517
1613
|
saying "this one is pinned". Several chains from one bone are one garment and are §3.1's coupled
|
|
1518
1614
|
solve; chains from *different* bones are refused, because there is then no single frame to
|
|
1519
1615
|
simulate in.
|
|
1616
|
+
|
|
1617
|
+
**M7 lifted the refusal, because the frame and the fixed set came apart.** The bones a garment
|
|
1618
|
+
hangs from are particles of the proxy that cloth reads and never writes (`ClothProxy#output`), with
|
|
1619
|
+
the links to their roots the first links of the fabric; the frame is the nearest skin joint above
|
|
1620
|
+
all of them (`ClothProxy#frame`); and the builder hands back one `ClothProxyGroup` per bone — the
|
|
1621
|
+
pin to add. A cape across both shoulders is one proxy, two pins, riding the chest
|
|
1622
|
+
(`cloth_rig.spec.js`).
|
|
1520
1623
|
6. Bake `d_geo` — geodesic distance from every particle to the fixed set. This one array drives the
|
|
1521
1624
|
tether row, the slack profile, and the pinning, so the three cannot disagree.
|
|
1522
|
-
7. Colour the particle graph (`
|
|
1625
|
+
7. Colour the particle graph (`csr_graph_color_greedy`, checked by `csr_graph_validate_coloring`), and permute
|
|
1523
1626
|
the particle order so each colour is a contiguous range.
|
|
1524
1627
|
8. Resolve joint **names to indices** into `Skin#joints`, using `SceneBundleInstance#nodes`. This is
|
|
1525
1628
|
the only place a name appears anywhere in the system.
|
|
@@ -1702,9 +1805,9 @@ What this design takes from the engine rather than building:
|
|
|
1702
1805
|
| Mesh topology, adjacency, bending stencils | `core/geom/3d/topology/struct/binary/` — `BinaryTopology`, `bt_edge_read_diamond`, `bt_edge_is_boundary`, `bt_collect_boundary_segments` |
|
|
1703
1806
|
| Proxy decimation | `bt_mesh_simplify_by_error`, `bt_mesh_compute_vertex_quadrics` |
|
|
1704
1807
|
| Mesh cleanup | `geometry_deduplicate_vertices` |
|
|
1705
|
-
| Graph colouring | `core/graph/
|
|
1808
|
+
| Graph colouring | `core/graph/csr/csr_graph_color_greedy.js`, `csr_graph_validate_coloring.js` |
|
|
1706
1809
|
| Collider shapes and their SDFs | `core/geom/3d/shape/*` — closed-form `signed_distance_at_point` on every primitive |
|
|
1707
|
-
| Collider AABBs, pose caching | `core/geom/3d/aabb/*`, `
|
|
1810
|
+
| Collider AABBs, pose caching | `core/geom/3d/aabb/*`, `aabb3_transform_oriented_array` |
|
|
1708
1811
|
| Collider ECS wiring | `Collider`, `ColliderFlags`, `ColliderObserverSystem` (as the pattern) |
|
|
1709
1812
|
| "Opt a collider into a second simulation" | `FluidObstacle` + `FluidObstacleSystem`, `AcousticBody` |
|
|
1710
1813
|
| Collider index shape | `AcousticOccluderIndex` + `OccluderBody` |
|
|
@@ -2361,6 +2464,45 @@ question it answers has become "does all the cloth in the scene fit in one worke
|
|
|
2361
2464
|
`MEASUREMENTS.md` §41. Re-measure the absolute column on a quiet machine, and check the process count
|
|
2362
2465
|
first.
|
|
2363
2466
|
|
|
2467
|
+
**M7 — attachment points. DONE, 2026-10-10.** `ClothPin`, `ClothHold`, `cloth_holds.js`,
|
|
2468
|
+
`cloth_geodesic.js`, `ClothPinSerializationAdapter`; the rows built from a particle graph rather than a
|
|
2469
|
+
parent array; held particles carried through the step (`ClothState#kinematic_target`) and leash rows
|
|
2470
|
+
measured from a particle (`leash_source`); the rig proxy's bones-to-hang-from and frame joint. There is
|
|
2471
|
+
no anchor: a cloth is held by whatever pins name it, from none up. §19 is the design.
|
|
2472
|
+
*Proofs, all green:* `cloth_held.spec.js` (five of six red against the previous solver),
|
|
2473
|
+
`cloth_pin.spec.js` (free fall, a rope held at its top, a rope bridge, letting go and catching mid-swing,
|
|
2474
|
+
a holder teleporting, a holder outrunning the cloth, holds pulled beyond the fabric, a pin before its
|
|
2475
|
+
cloth, lifecycle and refusals), `cloth_geodesic.spec.js`, the adapter's, a two-shoulder cape in
|
|
2476
|
+
`cloth_rig.spec.js`, and a worker parity run in which a second holder drags, lets go and takes hold
|
|
2477
|
+
again — bit-identical every step for 240. Cloth suite 327, slow 7, physics 1,861. *Cost:* +1.4% and
|
|
2478
|
+
+2.8% median a step on a 129- and a 1,025-particle rope rig, paired against the previous build in one
|
|
2479
|
+
process. *Equivalence:* a rope pinned at its own top under M7 and the same rope under the anchor differ
|
|
2480
|
+
by 1.9e-7 m after one step, and grow apart exactly as fast as two copies of the old build nudged 1e-7 m
|
|
2481
|
+
apart — chaos, not a change. `MEASUREMENTS.md` §62.
|
|
2482
|
+
|
|
2483
|
+
**M7, sheets. DONE, 2026-10-10.** `cloth_proxy_from_mesh`: a proxy from a skin with one joint per vertex
|
|
2484
|
+
and the triangles over them — a stretch row per edge, a hinge per interior edge, the authoring mistakes
|
|
2485
|
+
refused by name (§7 P8). `ClothProxy` carries its graph for both builders; hinge rows are built wherever
|
|
2486
|
+
a proxy has hinges, each stiffened as a ratio of its own inertia; a joint with triangles round it is
|
|
2487
|
+
turned by its surface rather than swung along a chain. §19.5 is the design.
|
|
2488
|
+
*Proofs, all green:* `cloth_proxy_from_mesh.spec.js`, and `cloth_sheet.spec.js` through `ClothSystem` —
|
|
2489
|
+
a flag held at its hoist by a pole, every library fabric swinging down from a held edge and coming to
|
|
2490
|
+
rest, a free sheet draped on a sphere with every joint turned onto its surface, and a cloth in two
|
|
2491
|
+
pieces of which only one is held. *Found:* a flag on a pole in still air turns about the pole, and the
|
|
2492
|
+
solver did it before holds existed (§18). `MEASUREMENTS.md` §63.
|
|
2493
|
+
*The stage's remaining scenes, later:* a sheet carried round by friction on a turning sphere, and a
|
|
2494
|
+
circle skirt that flares on a turning body and settles, both in `cloth_sheet.slow.spec.js`. The third, a
|
|
2495
|
+
pile of ribbons, found that a fold resting on a fold never comes to rest at the shipped self-collision
|
|
2496
|
+
stiffness (§18), and is kept as the proof a change to it needs. `MEASUREMENTS.md` §64.
|
|
2497
|
+
|
|
2498
|
+
**Post-M7 — a fold resting on a fold comes to rest. DONE, 2026-10-11.** `CLOTH_SELF_RATIO` goes from
|
|
2499
|
+
8 to 2 (§9, §18). *Proofs, red on 8 and green on 2:* in `cloth_sheet.slow.spec.js`, a pile of three
|
|
2500
|
+
silk ribbons fanned 60°, which sleeps with no crossing at any step and its order kept, and the circle
|
|
2501
|
+
skirt, asleep after its twirl; in `cloth_sheet.spec.js`, the sheet draped on a sphere, asleep. *Cost:*
|
|
2502
|
+
§32's folding sheet goes from 2.09 to 2.98 crossings a sample over 48 gusts, and the library bench
|
|
2503
|
+
does not move. The turning-sphere spec's 2° on where the sheet stops after the spin was one
|
|
2504
|
+
realisation and is now 10°. `MEASUREMENTS.md` §65.
|
|
2505
|
+
|
|
2364
2506
|
---
|
|
2365
2507
|
|
|
2366
2508
|
## 18. Risks and open questions
|
|
@@ -2506,6 +2648,11 @@ inextensibility, but the fixed set still has to come from the mesh boundary or f
|
|
|
2506
2648
|
neither is built. It belongs with the unrigged path, which is where a mesh first becomes a particle
|
|
2507
2649
|
set.
|
|
2508
2650
|
|
|
2651
|
+
**M7 closed half of this.** The fixed set is authored now, by `ClothPin` (§19), for every case: a
|
|
2652
|
+
flag's hoist is the vertices a pin on the pole names. **M7's sheets closed the mesh:**
|
|
2653
|
+
`cloth_proxy_from_mesh` builds the proxy from triangles (§19.5). What is left is a way to draw one
|
|
2654
|
+
(§19.6).
|
|
2655
|
+
|
|
2509
2656
|
**Open — LOD.** Distance-based particle-count reduction would need either multiple baked proxies per
|
|
2510
2657
|
garment or a runtime hierarchy. Culling (§12.1) covers the off-screen case; the far-but-visible case is
|
|
2511
2658
|
unaddressed.
|
|
@@ -2623,3 +2770,188 @@ whose rig was taken away kept driving the joints. Both edges are now watched by
|
|
|
2623
2770
|
`Cloth` + `ClothRig` inside `ClothWorld`, so the discriminator is read whenever it changes rather than
|
|
2624
2771
|
once. The **subtree** case above is untouched and stays open: an entity appearing under a live rope is
|
|
2625
2772
|
still a `reseed` the caller has to ask for.
|
|
2773
|
+
|
|
2774
|
+
**Open — M7: a seam between two holders that move apart.** The animated pose hangs each particle from
|
|
2775
|
+
its *nearest* held particle, so two holders moving relative to each other put a step in it where their
|
|
2776
|
+
regions meet. It binds only where the slack row does — past `2·slack·d_geo`, which at a seam is the
|
|
2777
|
+
widest radius the cloth has — and nothing measured has reached it. A geodesic-weighted blend of the
|
|
2778
|
+
holders' motions is the shape of a fix if a garment ever does.
|
|
2779
|
+
|
|
2780
|
+
**M7: a sheet held along a vertical line turned about it. — FIXED, by one more block of the descent.**
|
|
2781
|
+
A flag on a pole in still air did not hang still: it turned about the pole as a rigid body, ten degrees
|
|
2782
|
+
a second at rope's settings, for all 3,000 steps measured. A turn about a vertical hold line is the one
|
|
2783
|
+
motion nothing restores — gravity is parallel to it, and every row ends on the axis or is an equal and
|
|
2784
|
+
opposite pair — and AVBD stopped at a fabric's iteration count left a residual whose torque about that
|
|
2785
|
+
axis was not zero, so the step's fixed point was a steady turn rather than rest. `damping` balanced the
|
|
2786
|
+
torque rather than removing it: ten times the rate, a tenth of the speed. It was there with hard stretch
|
|
2787
|
+
rows and nothing else, and in the solver from before holds existed, digit for digit. A fabric with
|
|
2788
|
+
`slack < 1` came to rest only because its slack row caught the turn — a silk flag 123° round its pole,
|
|
2789
|
+
cotton 74° — and one at `slack = 1`, rope or chain, never did. `MEASUREMENTS.md` §63.
|
|
2790
|
+
|
|
2791
|
+
*The cause, measured.* A vertex update moves one particle, so each adds `x_i × m·Δx_i` of angular
|
|
2792
|
+
momentum about the line, and the step's change about the pole is exactly `h·Σ x × R`, `R` the energy
|
|
2793
|
+
gradient left when the iterations stop; the identity closes to four figures. The warm start keeps
|
|
2794
|
+
`α·γ = 0.25` of each hard multiplier, so a cloth at rest re-solves three quarters of its weight every
|
|
2795
|
+
substep and leaves that gradient every substep. Sweep order is not it: forward, backward and
|
|
2796
|
+
alternating each step all read −0.46 at 8 iterations.
|
|
2797
|
+
|
|
2798
|
+
*The fix* is the turn as a block of its own (§5.2, `cloth_hold_line.js`): one Newton step along it in
|
|
2799
|
+
the last iteration, whenever the held particles lie on one line. The bare flag reads 0 to four figures
|
|
2800
|
+
at every budget from 1 to 16 iterations, and every library fabric's flag sleeps: rope at step 416,
|
|
2801
|
+
chain at 250 and cotton at 336, where they never did. It costs 3–9% of a sheet's step, and nothing on a
|
|
2802
|
+
cloth held at one point, where it never runs. Carrying the multiplier instead — AVBD's Eq. 18, or the
|
|
2803
|
+
reference code's post-stabilisation — stops the turn too, fails six to ten of the 345 cloth gates, and
|
|
2804
|
+
diverges where its rows meet rows still on the old warm start. `MEASUREMENTS.md` §66.
|
|
2805
|
+
|
|
2806
|
+
*Still open, measured and not fixed:*
|
|
2807
|
+
- A single held point has three free turns and a cloth nothing holds has six; the block covers a line
|
|
2808
|
+
only. A sheet hung from one corner turns at no more than 0.004, and silk's is awake at step 3,000.
|
|
2809
|
+
- Where gravity does restore the turn, the block slows some sleeps: leather's lying sheet from 72 steps
|
|
2810
|
+
to 165, and rope and chain on a pole tilted 30° from 474 to 574 and 264 to 312. Why is not measured.
|
|
2811
|
+
- And in one case it keeps a cloth awake. Cotton held by its two top corners, after the hands see-saw
|
|
2812
|
+
for 900 steps and stop, never sleeps under the block, creeping 1.7 mm per 30 steps at step 8,000;
|
|
2813
|
+
before it, it slept at 1,378. Switched off at the stop it sleeps at 1,409, so it is the block's
|
|
2814
|
+
ongoing action: it takes out the leftover turn about the corner line rigidly, about 7e-7 rad a
|
|
2815
|
+
substep, and the sweeps put it back near a corner. Rope never sleeps after that see-saw in either
|
|
2816
|
+
build. Running the block only on hold lines near the vertical would remove this and the item above,
|
|
2817
|
+
at the price of a tolerance constant and a test against gravity; it was not done.
|
|
2818
|
+
- Far from the frame's origin the correction is smaller than the coordinates' rounding. A bare flag
|
|
2819
|
+
100 m out turns at −0.025 at step 500 and −0.136 at 3,000, against −0.18 to −0.23 before. `ClothSystem`
|
|
2820
|
+
steps a cloth in its own frame, where its coordinates are its own size.
|
|
2821
|
+
- After a one-kilometre teleport neither build sleeps within 2,400 steps, rope, silk, hair or chain. It
|
|
2822
|
+
was so before the block, and the cause is not measured.
|
|
2823
|
+
|
|
2824
|
+
**A fold resting on a fold never came to rest. — FIXED, `CLOTH_SELF_RATIO` 8 → 2, and the cost is
|
|
2825
|
+
measured.** §32 cleared `CLOTH_SELF_RATIO = 8` of adding energy on a folding sheet, whose
|
|
2826
|
+
contacts come and go. A self-collision pair that carries weight stays in contact, so a resting fold is
|
|
2827
|
+
a standing spring, which is the case M0's dissipative band was measured on. At 8 the step gains energy
|
|
2828
|
+
through it:
|
|
2829
|
+
- Two silk ribbons stacked parallel on a floor peak at 1.5 m/s after a 0.35 m/s drop, and never sleep.
|
|
2830
|
+
- Two crossed at 90°, dropped from gaps of 4 to 12 cm, sleep only from the 6 and 8 cm drops. From the
|
|
2831
|
+
others they creep 3 to 56 mm every five seconds.
|
|
2832
|
+
- Piles of three to six reach up to 5.7 m/s, 1.3 to 3.8 times what their drop gives them, and are
|
|
2833
|
+
left with 11 to 139 crossings. Every three-ribbon pile tried crosses.
|
|
2834
|
+
- §63's draped sheet stays awake on its sphere, with 14 to 18 pairs found every step.
|
|
2835
|
+
- A circle skirt stays awake after a twirl, with eight.
|
|
2836
|
+
|
|
2837
|
+
At ratio 1 all of them sleep. Averaging a particle's Jacobi share over its pairs is not the fix.
|
|
2838
|
+
*Fixed at 2*, the stiffest ratio at which cloth resting on itself reliably comes to rest. Of 225 ribbon
|
|
2839
|
+
piles in silk, cotton and hair, the 135 that land without passing through themselves all sleep but
|
|
2840
|
+
one, and so do the draped sheet and the skirt. At 4, five of 38 clean silk piles never do, and above
|
|
2841
|
+
2.25 the draped sheet's sleep is erratic. *What it costs* is §32's folding sheet: 2.09 → 2.98 crossings
|
|
2842
|
+
a sample over 48 gusts, where ratio 1 would cost 3.74. The library bench does not move. The proof is a
|
|
2843
|
+
three-ribbon pile fanned 60°, asserting no crossing at any step and the order kept. "No crossings at
|
|
2844
|
+
rest" is not enough, because a ribbon can land right through another and lie under it. *Still open,
|
|
2845
|
+
and not this:* piles land through themselves, 90 of 225 at 2, every one of them while landing. That is
|
|
2846
|
+
§35's missing travel term in the pair search. `MEASUREMENTS.md` §64, §65.
|
|
2847
|
+
|
|
2848
|
+
---
|
|
2849
|
+
|
|
2850
|
+
## 19. Attachment points
|
|
2851
|
+
|
|
2852
|
+
Written for M7, after an adversarial review of the first draft by three reviewers against the code;
|
|
2853
|
+
the review's findings are folded in below and listed in `MEASUREMENTS.md` §62.
|
|
2854
|
+
|
|
2855
|
+
### 19.1 The anchor was four jobs
|
|
2856
|
+
|
|
2857
|
+
Node 0 was the frame the cloth was simulated in, the one pinned particle, the point every tether
|
|
2858
|
+
measured from, and the root the rows were derived from. Only the first is a property of the entity the
|
|
2859
|
+
`Cloth` is on, and splitting the other three off is the whole design:
|
|
2860
|
+
|
|
2861
|
+
| Job | Now |
|
|
2862
|
+
|---|---|
|
|
2863
|
+
| Frame: the solve, gravity, colliders, wind, §7 P7 | The `Cloth` entity for a subtree; `ClothProxy#frame` for a rig |
|
|
2864
|
+
| The fixed set | Held particles: any number, each held by an entity carrying a `ClothPin` |
|
|
2865
|
+
| Tether centre and `d_geo` | The nearest held particle along the fabric |
|
|
2866
|
+
| Root of the rows | A particle graph — `ClothInstance#edge`, `#skip`, `#hinge` |
|
|
2867
|
+
|
|
2868
|
+
A cloth with no pins is the case where nothing is held, and it needs no code: every tether and slack
|
|
2869
|
+
row has radius `Infinity`.
|
|
2870
|
+
|
|
2871
|
+
### 19.2 `ClothPin`
|
|
2872
|
+
|
|
2873
|
+
On the holder, naming the cloth's entity and its particles by index — a proxy's particle order, or for
|
|
2874
|
+
a subtree the breadth-first walk, where 0 is the `Cloth` entity. Every field required; references fixed
|
|
2875
|
+
while attached; saved with its entity. A hold begins **where the particle is**: on a cloth's first step
|
|
2876
|
+
that is the rest pose, mid-run it is a grab. Removing the pin lets go, and the particle leaves at the
|
|
2877
|
+
speed its holder carried it. Destroying the cloth's entity removes the pins naming it (an entity id is
|
|
2878
|
+
reused). A particle two pins name goes to the lower holder; a holder the cloth itself moves is refused,
|
|
2879
|
+
once, by name.
|
|
2880
|
+
|
|
2881
|
+
The world keeps one `ClothHold` per pin **outside** the seeded instance: the offsets a hold takes are
|
|
2882
|
+
the hold's, so a re-seed does not move what is held. The observer only notices; everything a hold
|
|
2883
|
+
writes into a `ClothState` is written in `ClothWorld#advance`, the one window in which the main thread
|
|
2884
|
+
owns that state under both systems.
|
|
2885
|
+
|
|
2886
|
+
A holder's pose is read off its `Transform64` when the CPU owns it and evaluated exactly, under the
|
|
2887
|
+
clips of every model on its chain, when the GPU does; a holder whose chain is not complete yet holds
|
|
2888
|
+
where it last held.
|
|
2889
|
+
|
|
2890
|
+
### 19.3 What a hold does in the step
|
|
2891
|
+
|
|
2892
|
+
A held particle is kinematic: inverse mass zero, carried towards `kinematic_target` by an equal share
|
|
2893
|
+
of what remains at every substep, so it lands exactly at the last one and a target equal to the
|
|
2894
|
+
position moves nothing by a single bit. Chaos Cloth interpolates its kinematic particles the same way.
|
|
2895
|
+
Held particles are not carried by the frame's inertia; they belong to their holders.
|
|
2896
|
+
|
|
2897
|
+
**One tether per particle, to the nearest held particle.** Chaos tethers to the nearest of up to four
|
|
2898
|
+
kinematic islands; that is four hard rows per particle, three of them idle on every cloth with one
|
|
2899
|
+
hold, and two hard tethers to holders pulled apart are bounds no position satisfies. The fabric between
|
|
2900
|
+
two holders already carries everything a second tether would. The search is one Dijkstra over the
|
|
2901
|
+
fabric edges with every held particle a source, in double. A tether starts no tighter than where its
|
|
2902
|
+
particle already is and only ever comes in, so a hold taken mid-run does not snap the cloth onto it.
|
|
2903
|
+
|
|
2904
|
+
The **animated pose** is the rest pose hung from the nearest held particle and turned with its holder,
|
|
2905
|
+
`s_i = x_p + R_p·(r_i − r_p)`; it keeps §3.4's factor of two exact. When no holder has moved in the
|
|
2906
|
+
frame since the last step — every holder that rides its frame — nothing per step is recomputed.
|
|
2907
|
+
|
|
2908
|
+
`reach` is the largest `d_geo`, with a particle no hold reaches counted at its rest distance from the
|
|
2909
|
+
frame's origin.
|
|
2910
|
+
|
|
2911
|
+
### 19.4 The rig path
|
|
2912
|
+
|
|
2913
|
+
A rig proxy's particles are the garment's joints and the bones it hangs from; cloth writes the first
|
|
2914
|
+
and reads the second, each step, exactly, to express the garment's roots against. The builder finds
|
|
2915
|
+
the bones, the frame and the pins; the spawn code adds the pins. `Cloth` and `ClothRig` stay on the
|
|
2916
|
+
model's root, which is saved, rather than on a bone, which is not.
|
|
2917
|
+
|
|
2918
|
+
### 19.5 Sheets
|
|
2919
|
+
|
|
2920
|
+
A sheet is a skin with **one joint per vertex**, every one hanging straight off one root joint, and
|
|
2921
|
+
`cloth_proxy_from_mesh` builds its proxy from the triangles over them: a stretch row per edge, a hinge
|
|
2922
|
+
per interior edge — the shared edge, then each triangle's opposite wing, which is `cloth_bend_row`'s
|
|
2923
|
+
stencil — the root joint as the frame, and nothing pinned: a pin on a pole names the hoist. A triangle
|
|
2924
|
+
with no area, an edge three triangles share, joints under two roots and a name the skin lacks are
|
|
2925
|
+
refused by name. `ClothProxy` carries its graph (`edge`, `skip`, `hinge`, `triangle`) for both
|
|
2926
|
+
builders.
|
|
2927
|
+
|
|
2928
|
+
A hinge's stiffness is the skip row's rule over its own stencil, `bend ratio × (m / Σ w²) / h²`: a
|
|
2929
|
+
hinge across a sliver, whose cotangent weights are large, is softer per unit of `C` for exactly the
|
|
2930
|
+
reason its `C` is larger, and stays inside M0's dissipative band where a stiffness in newtons per metre
|
|
2931
|
+
would leave it.
|
|
2932
|
+
|
|
2933
|
+
A joint with triangles round it has no chain to swing along, and what its orientation is for is the
|
|
2934
|
+
normal it turns its vertex's normal by. It takes the swing carrying the area-weighted normal of its
|
|
2935
|
+
triangles in the animated pose onto the same in the simulated one, then the twist about that normal
|
|
2936
|
+
carrying one fixed neighbour's direction onto where it is now. A joint hanging straight off the frame is
|
|
2937
|
+
written in the frame.
|
|
2938
|
+
|
|
2939
|
+
### 19.6 Not done
|
|
2940
|
+
|
|
2941
|
+
- **Drawing a sheet: the route exists, nothing takes it yet.** A skin is a `MeshSkin` on the mesh it
|
|
2942
|
+
deforms and a rig names that entity (`38b2fe208`, `0e20799be`), so a sheet built in code needs no
|
|
2943
|
+
loaded asset: a mesh entity with `ShadedGeometry` and a `MeshSkin` naming the vertex joints, named
|
|
2944
|
+
by `ClothRig.from(proxy, mesh)`. Not built: a helper that makes that geometry, its skin and the
|
|
2945
|
+
joints from the triangles, and anything that shows a sheet drawn.
|
|
2946
|
+
- **The cost of a joint per vertex.** About 620 ns a joint a step, on the main thread, where
|
|
2947
|
+
`WorkerClothSystem` leaves it: 0.25 ms for a 400-particle sheet. `MEASUREMENTS.md` §63.
|
|
2948
|
+
- **Curved rest shapes.** The hinge stencil reads a curved rest as already bent (§18); a flag, a banner
|
|
2949
|
+
and a circle skirt cut flat are what it serves.
|
|
2950
|
+
- **Welding.** The builder takes a mesh that is already one joint per welded vertex.
|
|
2951
|
+
- **A sheet held at one point, or by two holders that see-saw.** The hold-line block that stopped a
|
|
2952
|
+
flag turning on its pole covers a line only, and after a see-saw it keeps a corner-held sheet awake
|
|
2953
|
+
(§18).
|
|
2954
|
+
- **A seam between holders that move apart** (§18).
|
|
2955
|
+
- **A pile landing through itself.** A fold resting on a fold comes to rest since the self-collision row
|
|
2956
|
+
went to 2 (§18). What is left is a pile passing through itself while it lands, which is §35's
|
|
2957
|
+
missing travel term in the pair search.
|