@woosh/meep-engine 3.40.0 → 3.41.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/quaternion/swing_twist_clamp.d.ts +24 -0
- package/src/core/geom/3d/quaternion/swing_twist_clamp.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_clamp.js +62 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.d.ts +15 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.js +36 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.d.ts +39 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.js +85 -0
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.d.ts +11 -6
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.js +27 -13
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts +25 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +166 -0
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts +5 -3
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.js +5 -3
- package/src/engine/animation/curve/AnimationCurve.d.ts +3 -0
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +6 -1
- package/src/engine/ecs/EntityManager.d.ts +9 -1
- package/src/engine/ecs/EntityManager.d.ts.map +1 -1
- package/src/engine/ecs/EntityManager.js +26 -27
- package/src/engine/ecs/gpu/GPUStateAuthority.d.ts +20 -0
- package/src/engine/ecs/gpu/GPUStateAuthority.d.ts.map +1 -1
- package/src/engine/ecs/gpu/GPUStateAuthority.js +21 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.d.ts +13 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.js +12 -0
- package/src/engine/ecs/gpu/gpu_authority_grant.d.ts +6 -0
- package/src/engine/ecs/gpu/gpu_authority_grant.d.ts.map +1 -1
- package/src/engine/ecs/gpu/gpu_authority_grant.js +7 -1
- package/src/engine/ecs/gpu/gpu_authority_held.d.ts +14 -0
- package/src/engine/ecs/gpu/gpu_authority_held.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_held.js +23 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.d.ts +23 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.js +41 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.d.ts +14 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.js +32 -0
- package/src/engine/ecs/ik/IKGoal.d.ts +59 -0
- package/src/engine/ecs/ik/IKGoal.d.ts.map +1 -0
- package/src/engine/ecs/ik/IKGoal.js +83 -0
- package/src/engine/ecs/ik/IKGoalSystem.d.ts +75 -0
- package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -0
- package/src/engine/ecs/ik/IKGoalSystem.js +1456 -0
- package/src/engine/ecs/ik/PLAN.md +179 -0
- package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
- package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
- package/src/engine/ecs/storage/BinaryBufferSerializer.d.ts.map +1 -1
- package/src/engine/ecs/storage/BinaryBufferSerializer.js +4 -5
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +7 -3
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +1 -2
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.d.ts +33 -0
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.d.ts.map +1 -0
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.js +282 -0
- package/src/engine/ecs/transform/T64WorldCache.js +139 -139
- package/src/engine/ecs/transform/t64_evaluate_local.d.ts +25 -0
- package/src/engine/ecs/transform/t64_evaluate_local.d.ts.map +1 -0
- package/src/engine/ecs/transform/t64_evaluate_local.js +35 -0
- package/src/engine/ecs/transform/t64_evaluate_world.d.ts +5 -3
- package/src/engine/ecs/transform/t64_evaluate_world.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_evaluate_world.js +128 -126
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +2 -0
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +337 -329
- package/src/engine/graphics3/AnimationSystem.d.ts +2 -0
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +360 -352
- package/src/engine/physics/cloth/MEASUREMENTS.md +130 -0
- package/src/engine/physics/cloth/PLAN.md +16 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +5 -6
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +5 -6
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +4 -7
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +4 -7
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +4 -3
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +4 -3
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +10 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +24 -24
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +46 -43
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +1 -1
- package/src/engine/physics/constraint/solve_constraints.d.ts +0 -35
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +1 -83
- package/src/engine/physics/ecs/ContactProbe.d.ts +73 -0
- package/src/engine/physics/ecs/ContactProbe.d.ts.map +1 -0
- package/src/engine/physics/ecs/ContactProbe.js +103 -0
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts +44 -0
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/ContactProbeSystem.js +397 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +1 -1
- package/src/engine/physics/fluid/ecs/FluidComponent.js +1 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.d.ts +205 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.js +245 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.d.ts +21 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.js +63 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts +33 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +874 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.d.ts +27 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.js +77 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.d.ts +36 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.js +97 -0
- package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts +33 -11
- package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts.map +1 -1
- package/src/engine/physics/inverse_kinematics/two_joint_ik.js +158 -67
- package/src/shade/renderer/animation/ANIMATION_TRACK_BINDING_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/animation/ANIMATION_TRACK_BINDING_STRUCT.js +10 -1
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +10 -4
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +251 -23
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts +12 -4
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts.map +1 -1
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.js +12 -4
- package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
- package/src/shade/renderer/animation/chunk_pose_accumulator.js +14 -1
- package/src/shade/renderer/animation/pose/PoseChannelIndex.d.ts +78 -0
- package/src/shade/renderer/animation/pose/PoseChannelIndex.d.ts.map +1 -0
- package/src/shade/renderer/animation/pose/PoseChannelIndex.js +274 -0
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts +40 -3
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/PosePlayback.js +77 -3
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts +21 -3
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/pose_evaluate_local.js +79 -11
- package/src/shade/renderer/animation/shader_animation_apply.js +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts +3 -2
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.js +187 -176
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.d.ts +3 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.js +5 -2
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts +4 -0
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.js +6 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.d.ts +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.js +135 -73
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.d.ts +7 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.js +29 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.d.ts +19 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.js +167 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.d.ts +25 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.js +124 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.d.ts +19 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.js +48 -0
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +17 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +29 -3
- package/src/engine/ecs/ik/IKConstraint.d.ts +0 -52
- package/src/engine/ecs/ik/IKConstraint.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKConstraint.js +0 -95
- package/src/engine/ecs/ik/IKProblem.d.ts +0 -45
- package/src/engine/ecs/ik/IKProblem.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKProblem.js +0 -58
- package/src/engine/ecs/ik/IKSolver.d.ts +0 -8
- package/src/engine/ecs/ik/IKSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKSolver.js +0 -9
- package/src/engine/ecs/ik/InverseKinematics.d.ts +0 -48
- package/src/engine/ecs/ik/InverseKinematics.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematics.js +0 -119
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.d.ts +0 -19
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.js +0 -72
- package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts +0 -54
- package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematicsSystem.js +0 -212
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts +0 -8
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +0 -153
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts +0 -5
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +0 -120
- package/src/engine/ecs/ik/ik_bone_chain.d.ts +0 -64
- package/src/engine/ecs/ik/ik_bone_chain.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_bone_chain.js +0 -142
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts +0 -42
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_probe_terrain_contact.js +0 -123
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +0 -18
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.js +0 -32
|
@@ -3984,3 +3984,133 @@ colliding readings have a median of 0.90 and the twelve idle ones 0.95.
|
|
|
3984
3984
|
|
|
3985
3985
|
**No library entry is re-sized.** Its bench cannot see a collider (§58), and a
|
|
3986
3986
|
garment on a body is the colliding half of the tables above.
|
|
3987
|
+
|
|
3988
|
+
## 61. A rig's joints were claimed with a bit the GPU never reads, by two parties at once
|
|
3989
|
+
|
|
3990
|
+
Found reading code in the 2026-10-05 IK design review, and measured here before
|
|
3991
|
+
anything changed. Every reading below is a spec that registers a real clip
|
|
3992
|
+
through `GPUAnimationManager` on a `SoftwareGPUDevice` scene over the garment's
|
|
3993
|
+
own dataset (`cloth_rig.spec.js`), or runs the real apply pass under the WGSL
|
|
3994
|
+
emulator (`shader_animation_apply.spec.js`). The specs it replaced granted the
|
|
3995
|
+
bit by hand on joints no clip bound, so none of this was visible to them.
|
|
3996
|
+
|
|
3997
|
+
```
|
|
3998
|
+
what before after
|
|
3999
|
+
clip unregistered while cloth held it, bit 2 (GPU), and a CPU write of bit 0; the row holds
|
|
4000
|
+
then the garment removed (0.25, -0.5, 0.125) left the row at (0.25, -0.5, 0.125)
|
|
4001
|
+
0.0020000000949949026, for good
|
|
4002
|
+
rig re-seeded while seeded, then removed bit 0 with the clip still bound bit 2
|
|
4003
|
+
clip binding a joint cloth already holds bit 2; the row stayed 0.0020000000949949026 bit 0; the row is
|
|
4004
|
+
while cloth wrote 0.0011062223929911852 cloth's write
|
|
4005
|
+
last clip leaving a held joint offset (5, -0.10000382363796234, 0): cloth's offset,
|
|
4006
|
+
the clip's pose over cloth's 0.00173… untouched
|
|
4007
|
+
bindings of clips over a held cape rows 3, 4, 5, 6, 7 (shoulder + cape) 3, then NULL ×4
|
|
4008
|
+
apply pass over two held targets 8 accumulator words written none
|
|
4009
|
+
cache / exact walk over a held level cache off by 0.98 in a translation lane; within 1e-12
|
|
4010
|
+
the walk off in lane 12 (world x)
|
|
4011
|
+
```
|
|
4012
|
+
|
|
4013
|
+
**Why the bit could not have worked.** The apply pass adds every bound clip into
|
|
4014
|
+
its target's accumulator slot whatever the clip's weight, the resolve writes the
|
|
4015
|
+
row, and both run in `tick`, after `build`'s flush. `GPUStateAuthority` gates
|
|
4016
|
+
only that flush. A cape joint whose clip still named its row was the clip's on
|
|
4017
|
+
screen, bit or no bit.
|
|
4018
|
+
|
|
4019
|
+
**What changed.** A CPU writer *holds* a component (`gpu_authority_hold`):
|
|
4020
|
+
`GPUStateAuthority#held` records it, the bit clears, and `gpu_authority_grant`
|
|
4021
|
+
will not set a held bit. The animation manager hears the hold through an entity
|
|
4022
|
+
event on every joint it drives. It points that joint's bindings at
|
|
4023
|
+
`GPU_DATABASE_NULL`, whose type bits `write_object_property` ignores, and it
|
|
4024
|
+
skips the seed when the last clip leaves. When the hold ends it points them back
|
|
4025
|
+
and grants, if a clip is still bound. The exact evaluators read a held level as
|
|
4026
|
+
its offset (`t64_evaluate_local`). Cloth holds every joint it drives and never
|
|
4027
|
+
touches the bit.
|
|
4028
|
+
|
|
4029
|
+
**Not measured:** a device run. The WGSL is unchanged; what changed is what the
|
|
4030
|
+
bindings name, and the emulator runs the real apply pass over it.
|
|
4031
|
+
|
|
4032
|
+
### Found in review
|
|
4033
|
+
|
|
4034
|
+
An adversarial pass over those six commits. Every candidate was measured before it
|
|
4035
|
+
was believed.
|
|
4036
|
+
|
|
4037
|
+
- **A re-seeded rig leaked its holds** when it was taken away, or refused, before
|
|
4038
|
+
the next seeding. `reseed` cleared `seeded`, the release asks `seeded`, and the
|
|
4039
|
+
joints stayed held: their clips muted and nothing writing them. Before the hold
|
|
4040
|
+
this was a bit that lied while the clip still won on the GPU; muting made it a
|
|
4041
|
+
frozen joint. `reseed` now gives the holds back, and the seed asserts it
|
|
4042
|
+
starts from none. Red first: bits `[0, 0, 0, 0]` against `[2, 2, 2, 2]`, the
|
|
4043
|
+
bindings all NULL, after removing `Cloth`, after removing `ClothRig`, and after
|
|
4044
|
+
a refused proxy.
|
|
4045
|
+
- **One line was pinned by nothing.** Of twelve mutants over the fixes, eleven
|
|
4046
|
+
were killed. The survivor was the row mark a hold makes, which carries an offset
|
|
4047
|
+
the holder wrote before it held. It is pinned now.
|
|
4048
|
+
- Measured and kept: the bind-time bookkeeping costs 129 ns a driven entity
|
|
4049
|
+
(2.5 ms for 19,440, at registration only). The hold check costs the exact
|
|
4050
|
+
evaluation 2.3% a level (64.0 to 65.8 µs over 70 levels, two clips of 210
|
|
4051
|
+
channels, paired median).
|
|
4052
|
+
- Measured and dismissed: a muted rotation binding writes nothing to its slot,
|
|
4053
|
+
rest rotation included (now in the emulator spec). A hold queues one word, the
|
|
4054
|
+
binding's `instance`, and its end queues the row back. A renderer restart
|
|
4055
|
+
reaches `GPUAnimationManager#destroy`, which removes every listener.
|
|
4056
|
+
|
|
4057
|
+
### What a hold's end hands over
|
|
4058
|
+
|
|
4059
|
+
Found reading code in the 2026-10-06 IK design review: two things the end of a
|
|
4060
|
+
hold did not hand to a clip still bound. Cloth's release is a plain unhold that
|
|
4061
|
+
leaves each joint's offset at cloth's last write-back, so both reached it. Real
|
|
4062
|
+
clips through the manager in `cloth_rig.spec.js`, and the apply and resolve
|
|
4063
|
+
passes under the WGSL emulator in `animation_pose_pipeline.spec.js`.
|
|
4064
|
+
|
|
4065
|
+
The rest rows below read the rest each binding carries, which is what the resolve
|
|
4066
|
+
writes at weight zero (shown under the emulator, not on the cape).
|
|
4067
|
+
|
|
4068
|
+
```
|
|
4069
|
+
what before after
|
|
4070
|
+
rest a clip keying the cape carries the rest from before the seed, the offset cloth
|
|
4071
|
+
once the garment goes [0, 0, 0, 1] left, z -0.00243
|
|
4072
|
+
the same, the clip bound while cloth held cloth's pose when it bound, the offset cloth
|
|
4073
|
+
z -0.000102 left, z -0.00243
|
|
4074
|
+
row y of a cape joint under a clip keying -0.0999996, cloth's flush before -0.1000130, cloth's
|
|
4075
|
+
x alone, the garment removed between its last five steps last write-back
|
|
4076
|
+
a step and the flush
|
|
4077
|
+
```
|
|
4078
|
+
|
|
4079
|
+
**What changed.** The end of a hold, with a clip still bound, writes every
|
|
4080
|
+
binding's rest from the offset as the holder left it, with the unmute, and marks
|
|
4081
|
+
the row as a hand-over (`GPUSceneRows#mark_handover`): the flush writes it past
|
|
4082
|
+
the bit, once, and the resolve writes the axes the clip keys after it.
|
|
4083
|
+
|
|
4084
|
+
**Decided, not changed:** a joint whose last clip left while it was held keeps
|
|
4085
|
+
the holder's offset when the hold ends, not the clip's last pose (2d67be636).
|
|
4086
|
+
The clip had been muted since the hold began, or since it bound, so its last pose
|
|
4087
|
+
is one the joint has not shown since; the seed's own rule, carry on from what is
|
|
4088
|
+
on screen, gives the holder's offset.
|
|
4089
|
+
|
|
4090
|
+
**Open, not decided:** cloth's rig path leaves its last pose on the joints when it
|
|
4091
|
+
lets go, where the entity path puts the locals it captured back
|
|
4092
|
+
(`cloth_release_subtree`). The rig path never captured the joints' own offsets,
|
|
4093
|
+
but the instance holds the proxy's bind pose (`rest_local_*`), which it could put
|
|
4094
|
+
back. Measured: after the garment goes, a cape joint's offset rotation has z up
|
|
4095
|
+
to -0.00243 where that bind pose (identity, for the spec's skeleton) has 0, and a
|
|
4096
|
+
clip keying the cape carries it as its rest.
|
|
4097
|
+
|
|
4098
|
+
**Found in review** of these two fixes:
|
|
4099
|
+
|
|
4100
|
+
- **Two lines were pinned by nothing.** Of ten mutants over the fixes, eight were
|
|
4101
|
+
killed. The survivors: the `MARK_LOCAL` inside the hand-over mark, since both
|
|
4102
|
+
gap-2 specs had the holder announce its last write and so mark the row
|
|
4103
|
+
themselves; and the rest read off the wrong component, since the emulator
|
|
4104
|
+
spec's left rotation was `[0.5, 0.5, 0.5, 0.5]` and the cape turns about z
|
|
4105
|
+
alone. Both are pinned now.
|
|
4106
|
+
- **The first bind had the same hole.** A clip that first binds a joint grants
|
|
4107
|
+
the bit at once, so an offset announced earlier in that frame never reached the
|
|
4108
|
+
row: `[0, 0, 0, 1]` against the `[0.1, 0.3, 0.5, 0.806]` announced. Binding
|
|
4109
|
+
marks the hand-over too now. No engine path was found that triggers it today: the
|
|
4110
|
+
drivers re-register a whole clip set in one call, whose outgoing seed is such an
|
|
4111
|
+
announcement, but they set time from the CPU, so that seed equals what the GPU
|
|
4112
|
+
last resolved.
|
|
4113
|
+
- Measured and dismissed: the binding writer over `instance` and `rest_rotation`
|
|
4114
|
+
is two disjoint ranges of one row, which the partial upload shader spec already
|
|
4115
|
+
lands under the emulator; and the worker path writes nothing after a release,
|
|
4116
|
+
because a join for a cloth unlinked or reseeded since its dispatch is dropped.
|
|
@@ -368,7 +368,8 @@ said cloth reuses `PhysicsSystem`'s producer/`__interp_restore` contract; M5 mea
|
|
|
368
368
|
that contract is entity-keyed and a rigged garment's joints are not entities — and §13.1 and §18 carry
|
|
369
369
|
what the cloth-shaped version would be and what it would cost. What keeps a cloth-driven bone from
|
|
370
370
|
fighting an animation-driven one is not interpolation but `TransformAuthority`, which `cloth_seed_rig`
|
|
371
|
-
claims (§11.2, `MEASUREMENTS.md` §25)
|
|
371
|
+
claims (§11.2, `MEASUREMENTS.md` §25) — as a hold since §61, because the bit alone never stopped a
|
|
372
|
+
clip on the GPU.
|
|
372
373
|
|
|
373
374
|
### 4.1 Ordering, and why the answer is not to be ordered
|
|
374
375
|
|
|
@@ -1430,6 +1431,20 @@ with no component left anywhere naming which joints those were. The seed now rec
|
|
|
1430
1431
|
joints its revoke *changed*, and `cloth_release_rig` hands those back when the `Cloth` is removed or
|
|
1431
1432
|
the `ClothRig` is taken away; a joint that was already the CPU's before cloth arrived stays the CPU's.
|
|
1432
1433
|
|
|
1434
|
+
**2026-10-06: the claim never stopped a clip, and the loan was handed back to whoever asked last.**
|
|
1435
|
+
No GPU pass reads `GPUStateAuthority`. A bound clip's bindings write a joint's row through the pose
|
|
1436
|
+
accumulator every frame, after the CPU's flush, whatever the bit says, so clearing the bit only let
|
|
1437
|
+
cloth's flush and the clip race for one row, and the clip won. And cloth and `GPUAnimationManager`
|
|
1438
|
+
each flipped the same bit without the other: a clip that left during the loan was answered by
|
|
1439
|
+
cloth's re-grant with a joint nothing wrote again, and a clip that arrived during it took the bit
|
|
1440
|
+
from under cloth's write-back. The rule now is a **hold**. `GPUStateAuthority#held` records that a CPU
|
|
1441
|
+
writer has the offset, the bit stays clear while it does, and the animation manager — the only
|
|
1442
|
+
writer of the bit — mutes every binding that names a held joint and leaves its offset alone when the
|
|
1443
|
+
last clip goes. Ending the hold grants nothing; a clip still bound takes the joint back. So **"a joint
|
|
1444
|
+
cloth simulates stops being animatable by a clip" is true now, and a garment whose joints are also
|
|
1445
|
+
keyed is not an authoring error**: exporters often bake every bone, and the cape simulates anyway.
|
|
1446
|
+
`MEASUREMENTS.md` §61.
|
|
1447
|
+
|
|
1433
1448
|
**The anchor's world pose is computed, never read back.** A joint of an animated skeleton has no
|
|
1434
1449
|
CPU-side `transform_global` — nothing maintains it — so the rig path evaluates the anchor with
|
|
1435
1450
|
`pose_evaluate_world` over the clips the entity is playing, which is the engine's own sanctioned
|
|
@@ -12,12 +12,11 @@
|
|
|
12
12
|
* ## It has no `fixedUpdate`, and that is §4.1 applied a second time
|
|
13
13
|
*
|
|
14
14
|
* The index has to be refreshed from the world's transforms **before** any
|
|
15
|
-
* cloth reads it, and the
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* order does not break a non-tie.
|
|
15
|
+
* cloth reads it, and the derived order says the opposite: `updateExecutionOrder`
|
|
16
|
+
* runs a writer of a component before its readers, `ClothSystem` writes
|
|
17
|
+
* `Transform64`, and the index is not a component, so a system that steps only
|
|
18
|
+
* to read transforms into it would run after cloth. Registration order breaks
|
|
19
|
+
* only the ties that leaves.
|
|
21
20
|
*
|
|
22
21
|
* §4.1's conclusion applies unchanged: the answer is not a third mechanism, it
|
|
23
22
|
* is not needing one. So this system does not step at all. {@link refresh} is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothColliderSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothColliderSystem.js"],"names":[],"mappings":"AAcA
|
|
1
|
+
{"version":3,"file":"ClothColliderSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothColliderSystem.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH;;IAEI,8EAAsD;IAEtD,wKAIE;IAEF;;OAEG;IACH,OAFU,kBAAkB,CAEK;IAEjC;;;;;;OAMG;IACH,kBAAsB;IAEtB;;;;;;;;OAQG;IACH,iBAAc;IAEd;;;;;OAKG;IACH,qBALW,aAAa,YACb,QAAQ,aACR,WAAW,UACX,MAAM,QAoChB;IAED;;;;;OAKG;IACH,uBALW,aAAa,YACb,QAAQ,aACR,WAAW,UACX,MAAM,QAqBhB;IAED;;;;;;OAMG;IACH,WAFa,IAAI,CAkChB;IAED;;;;;;;;OAQG;IACH,uBAHW,MAAM,GACJ,IAAI,CAyBhB;IAED;;;;;;OAMG;IACH,gBAWC;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAIlB;CACJ;uBArQsB,wBAAwB;4BAMxC,uCAAuC;yBACrB,uBAAuB;8BAElB,oBAAoB;4CAVN,uDAAuD;mCAShE,mCAAmC"}
|
|
@@ -26,12 +26,11 @@ import { ClothColliderFlags } from "./ClothColliderFlags.js";
|
|
|
26
26
|
* ## It has no `fixedUpdate`, and that is §4.1 applied a second time
|
|
27
27
|
*
|
|
28
28
|
* The index has to be refreshed from the world's transforms **before** any
|
|
29
|
-
* cloth reads it, and the
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* order does not break a non-tie.
|
|
29
|
+
* cloth reads it, and the derived order says the opposite: `updateExecutionOrder`
|
|
30
|
+
* runs a writer of a component before its readers, `ClothSystem` writes
|
|
31
|
+
* `Transform64`, and the index is not a component, so a system that steps only
|
|
32
|
+
* to read transforms into it would run after cloth. Registration order breaks
|
|
33
|
+
* only the ties that leaves.
|
|
35
34
|
*
|
|
36
35
|
* §4.1's conclusion applies unchanged: the answer is not a third mechanism, it
|
|
37
36
|
* is not needing one. So this system does not step at all. {@link refresh} is
|
|
@@ -478,15 +478,12 @@ export class ClothInstance {
|
|
|
478
478
|
*/
|
|
479
479
|
gather_reach: number;
|
|
480
480
|
/**
|
|
481
|
-
* The joint entities this cloth's rig seeding
|
|
482
|
-
*
|
|
483
|
-
* the entity path and before the first rig seeding.
|
|
484
|
-
*
|
|
485
|
-
* Only the ones the revoke actually changed: a joint that was already the
|
|
486
|
-
* CPU's is not one cloth has anything to hand back.
|
|
481
|
+
* The joint entities this cloth's rig seeding holds `TransformAttachment`
|
|
482
|
+
* on (`gpu_authority_hold`), so that removing the cloth can end the hold.
|
|
483
|
+
* `null` on the entity path and before the first rig seeding.
|
|
487
484
|
* @type {number[]|null}
|
|
488
485
|
*/
|
|
489
|
-
|
|
486
|
+
held_joints: number[] | null;
|
|
490
487
|
/**
|
|
491
488
|
* Where every particle was when the current sleep window opened, or `null`
|
|
492
489
|
* before the first step — §7 P5's sleep test measures displacement from
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothInstance.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothInstance.js"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ClothInstance.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothInstance.js"],"names":[],"mappings":"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"}
|
|
@@ -538,15 +538,12 @@ export class ClothInstance {
|
|
|
538
538
|
gather_reach = 0;
|
|
539
539
|
|
|
540
540
|
/**
|
|
541
|
-
* The joint entities this cloth's rig seeding
|
|
542
|
-
*
|
|
543
|
-
* the entity path and before the first rig seeding.
|
|
544
|
-
*
|
|
545
|
-
* Only the ones the revoke actually changed: a joint that was already the
|
|
546
|
-
* CPU's is not one cloth has anything to hand back.
|
|
541
|
+
* The joint entities this cloth's rig seeding holds `TransformAttachment`
|
|
542
|
+
* on (`gpu_authority_hold`), so that removing the cloth can end the hold.
|
|
543
|
+
* `null` on the entity path and before the first rig seeding.
|
|
547
544
|
* @type {number[]|null}
|
|
548
545
|
*/
|
|
549
|
-
|
|
546
|
+
held_joints = null;
|
|
550
547
|
|
|
551
548
|
/**
|
|
552
549
|
* Where every particle was when the current sleep window opened, or `null`
|
|
@@ -37,9 +37,10 @@
|
|
|
37
37
|
* recomposed.
|
|
38
38
|
*
|
|
39
39
|
* The declaration is the honest one — cloth reads `Cloth` and `ClothExclude`,
|
|
40
|
-
* and reads and writes both `Transform64` and `TransformAttachment`.
|
|
41
|
-
*
|
|
42
|
-
* transforms and the attachment system is their reader
|
|
40
|
+
* and reads and writes both `Transform64` and `TransformAttachment`. It runs
|
|
41
|
+
* before `TransformAttachmentSystem`, which is right — cloth writes the local
|
|
42
|
+
* transforms and the attachment system is their reader — and the passes are what
|
|
43
|
+
* guarantee it: cloth steps in `fixedUpdate`, the attachment system in `update`.
|
|
43
44
|
*
|
|
44
45
|
* @author Alex Goldring
|
|
45
46
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothSystem.js"],"names":[],"mappings":"AAcA
|
|
1
|
+
{"version":3,"file":"ClothSystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothSystem.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH;;IAEI,oDAAoC;IAEpC,iUAOE;IAEF;;OAEG;IACH,OAFU,UAAU,CAEK;IAEzB;;;;;;;;;;;;OAYG;IACH,iBAAyD;IAEzD;;;;;;OAMG;IACH,qBAAkB;IAUlB;;OAEG;IACH,iCAEC;IAbD;;;OAGG;IACH,4BAEC;IAkBD;;OAEG;IACH,qBAEC;IAdD;;;;OAIG;IACH,gBAEC;IASD;;;;OAIG;IACH,iCAEC;IAUD;;OAEG;IACH;4BAToC,MAAM,KAAG,CAAC,iBAAe,IAAI,CAAC;OAWjE;IAbD;;;OAGG;IACH;4BAFoC,MAAM,KAAG,CAAC,iBAAe,IAAI,CAAC;MAIjE;IASD;;;OAGG;IACH,uCAFa,QAAQ,IAAI,CAAC,CAIzB;IAED;;;OAGG;IACH,wDAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,wDAFa,IAAI,CAIhB;IAED;;;;OAIG;IACH,YAJW,KAAK,aACL,WAAW,UACX,MAAM,QAIhB;IAED;;;;OAIG;IACH,cAJW,KAAK,aACL,WAAW,UACX,MAAM,QAIhB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACJ,IAAI,CAIhB;IAED;;;;OAIG;IACH,aAHW,MAAM,GACJ,IAAI,CAIhB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,gBAAc,SAAS,CAInC;CA2EJ;uBAzSsB,wBAAwB;4BAInB,uCAAuC;sBAE7C,YAAY;4CAPU,uDAAuD;oCAI5F,0DAA0D;8BAInC,oBAAoB;6BACrB,mBAAmB;yBACvB,eAAe;2BACb,iBAAiB"}
|
|
@@ -51,9 +51,10 @@ import { ClothWorld } from "./ClothWorld.js";
|
|
|
51
51
|
* recomposed.
|
|
52
52
|
*
|
|
53
53
|
* The declaration is the honest one — cloth reads `Cloth` and `ClothExclude`,
|
|
54
|
-
* and reads and writes both `Transform64` and `TransformAttachment`.
|
|
55
|
-
*
|
|
56
|
-
* transforms and the attachment system is their reader
|
|
54
|
+
* and reads and writes both `Transform64` and `TransformAttachment`. It runs
|
|
55
|
+
* before `TransformAttachmentSystem`, which is right — cloth writes the local
|
|
56
|
+
* transforms and the attachment system is their reader — and the passes are what
|
|
57
|
+
* guarantee it: cloth steps in `fixedUpdate`, the attachment system in `update`.
|
|
57
58
|
*
|
|
58
59
|
* @author Alex Goldring
|
|
59
60
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothWorld.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothWorld.js"],"names":[],"mappings":"AA2DA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH;IAEI;;;OAGG;IACH,SAFU,YAAY,CAEoB;IAE1C;;;;;;;;;;;;OAYG;IACH,WAFU,aAAa,EAAE,CAEV;IAEf;;;;;;;;;;;;;;;OAeG;IACH,QAFU;QAAC,WAAW,SAAW,MAAM,KAAG,CAAC,iBAAe,IAAI,CAAC,CAAA;KAAC,GAAC,IAAI,CAEvD;IAEd;;OAEG;IACH,eAFU,gBAAc,IAAI,CAEP;IAErB;;OAEG;IACH,aAFU,yBAAyB,GAAC,IAAI,CAErB;IAEnB;;;;;;OAMG;IACH,WAFU,mBAAmB,GAAC,IAAI,CAEjB;IAEjB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAFU,oBAAkB,IAAI,CAEpB;IAEZ;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAFU,MAAM,CAEP;IAET;;;;;OAKG;IACH,uBAAmB;IAEnB;;;;;OAKG;IACH,cAFU,OAAO,CAEI;IAErB;;;OAGG;IACH,oBAAwB;IAExB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uBAKE;IAEF;;;;;OAKG;IACH,2CAiBC;IAED;;;;;OAKG;IACH,YALW,KAAK,kCAEL,MAAM,GACJ,aAAa,CAczB;IAED;;;;;;;;OAQG;IACH,iDAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,iDAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,aAAa,GAAC,SAAS,CA0BnC;IAyED;;;;;;;;;;;OAWG;IACH,eAHW,MAAM,GACJ,aAAa,GAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"ClothWorld.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/ClothWorld.js"],"names":[],"mappings":"AA2DA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH;IAEI;;;OAGG;IACH,SAFU,YAAY,CAEoB;IAE1C;;;;;;;;;;;;OAYG;IACH,WAFU,aAAa,EAAE,CAEV;IAEf;;;;;;;;;;;;;;;OAeG;IACH,QAFU;QAAC,WAAW,SAAW,MAAM,KAAG,CAAC,iBAAe,IAAI,CAAC,CAAA;KAAC,GAAC,IAAI,CAEvD;IAEd;;OAEG;IACH,eAFU,gBAAc,IAAI,CAEP;IAErB;;OAEG;IACH,aAFU,yBAAyB,GAAC,IAAI,CAErB;IAEnB;;;;;;OAMG;IACH,WAFU,mBAAmB,GAAC,IAAI,CAEjB;IAEjB;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAFU,oBAAkB,IAAI,CAEpB;IAEZ;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAFU,MAAM,CAEP;IAET;;;;;OAKG;IACH,uBAAmB;IAEnB;;;;;OAKG;IACH,cAFU,OAAO,CAEI;IAErB;;;OAGG;IACH,oBAAwB;IAExB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,uBAKE;IAEF;;;;;OAKG;IACH,2CAiBC;IAED;;;;;OAKG;IACH,YALW,KAAK,kCAEL,MAAM,GACJ,aAAa,CAczB;IAED;;;;;;;;OAQG;IACH,iDAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,iDAFa,IAAI,CAIhB;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,aAAa,GAAC,SAAS,CA0BnC;IAyED;;;;;;;;;;;OAWG;IACH,eAHW,MAAM,GACJ,aAAa,GAAC,SAAS,CAuBnC;IAED;;;;;;;OAOG;IACH,aAHW,MAAM,GACJ,IAAI,CAShB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,aAAa,GAAC,SAAS,CAInC;IAED;;;;;OAKG;IACH,uCAFW,MAAM,QAgBhB;IAED;;;;;;;;;OASG;IACH,wBANW,aAAa,mCAEb,MAAM,GACJ,OAAO,CA8BnB;IAED;;;;;;;OAOG;IACH,iBAJW,aAAa,gCAEX,IAAI,CA4ChB;IAwFD;;;;;;;;;;;OAWG;IACH,kBAPW,aAAa,MACb,MAAM,UACN,YAAY,UACZ,MAAM,GACJ,OAAO,CA0PnB;;CA8EJ;8BArgC6B,oBAAoB;0CAjB3C,gEAAgE;oCAcnC,0BAA0B;sBA4BxC,YAAY"}
|
|
@@ -478,6 +478,16 @@ export class ClothWorld {
|
|
|
478
478
|
return undefined;
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
+
// A rig's holds on its joints go with the binding being thrown away. Kept across the gap
|
|
482
|
+
// they would outlive `seeded`, which is all `#release` asks: a garment removed, or a rig
|
|
483
|
+
// refused, before the next seeding took them over would leave its joints held, the clips
|
|
484
|
+
// that key them muted, and nothing writing them.
|
|
485
|
+
const ecd = this.entityManager === null ? null : this.entityManager.dataset;
|
|
486
|
+
|
|
487
|
+
if (ecd !== null && ecd !== undefined) {
|
|
488
|
+
cloth_release_rig(instance, ecd);
|
|
489
|
+
}
|
|
490
|
+
|
|
481
491
|
instance.seeded = false;
|
|
482
492
|
instance.anchor_valid = false;
|
|
483
493
|
|
|
@@ -7,22 +7,23 @@
|
|
|
7
7
|
* identical either way; only seeding and write-back differ", and this file plus
|
|
8
8
|
* `cloth_write_back_rig.js` is the whole of the difference.
|
|
9
9
|
*
|
|
10
|
-
* ## The joints are entities, and cloth
|
|
10
|
+
* ## The joints are entities, and cloth holds their offsets
|
|
11
11
|
*
|
|
12
12
|
* A skinned model is a prefab spawned as entities, so a joint is an entity with
|
|
13
13
|
* a `TransformAttachment` — the offset from its parent joint — and a
|
|
14
|
-
* `GPUStateAuthority` saying who writes that offset's row. A
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* `GPUStateAuthority` saying who writes that offset's row. A clip bound to a
|
|
15
|
+
* joint writes the row on the GPU every frame, through the pose accumulator,
|
|
16
|
+
* after the CPU's flush and whatever any bit says. The bit states that, and
|
|
17
|
+
* stops the flush from racing it; it does not stop the clip.
|
|
18
18
|
*
|
|
19
|
-
* So the seed **
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
19
|
+
* So the seed **holds** every joint it drives (`gpu_authority_hold`): the bit
|
|
20
|
+
* clears, the animation manager mutes every binding that names the joint, and
|
|
21
|
+
* the row is what the write-back wrote. A clip that binds a held joint later
|
|
22
|
+
* binds muted, and one that leaves it leaves cloth's offset alone. Ending the
|
|
23
|
+
* hold grants nothing; a clip still bound takes the joint back. So a cape
|
|
24
|
+
* simulates under a clip that keys its bones too — exporters often bake every
|
|
25
|
+
* bone — and the exact evaluation (`t64_evaluate_world`) answers a held joint
|
|
26
|
+
* with cloth's offset, as the GPU shows it.
|
|
26
27
|
*
|
|
27
28
|
* ## The animated pose is constant, exactly as it is for a rope
|
|
28
29
|
*
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
* animated pose comes from the skeleton and is live".
|
|
33
34
|
*
|
|
34
35
|
* For a **rigged** garment it is not live either, and the reason is the
|
|
35
|
-
*
|
|
36
|
+
* hold above: cloth owns those joints, so nothing else poses them,
|
|
36
37
|
* so their authored pose is the proxy's baked bind pose — constant in the
|
|
37
38
|
* anchor's frame, exactly as a rope's is. What moves is the anchor, and the
|
|
38
39
|
* anchor is a joint of the character's own animated skeleton, whose pose the
|
|
@@ -52,18 +53,17 @@
|
|
|
52
53
|
*/
|
|
53
54
|
export function cloth_seed_rig(instance: ClothInstance, proxy: ClothProxy, joints: number[], ecd: EntityComponentDataset, dt: number): void;
|
|
54
55
|
/**
|
|
55
|
-
*
|
|
56
|
-
* seeding took from the GPU.
|
|
56
|
+
* End the hold this cloth's seeding took on every joint's `TransformAttachment`.
|
|
57
57
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* that
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
58
|
+
* Ending a hold grants nothing, and that is the point: who writes a joint once
|
|
59
|
+
* the garment is gone is not cloth's to say. A clip still bound to the joint
|
|
60
|
+
* takes it back (the animation manager hears the hold end); a joint no clip
|
|
61
|
+
* binds stays the CPU's, holding the offset cloth last wrote. Either way the
|
|
62
|
+
* joint starts from that offset: a clip taking it back rests there, and finds
|
|
63
|
+
* it in the row on every axis it does not key. Granting it here
|
|
64
|
+
* instead — as this did — hands a joint whose clip left during the hold to a
|
|
65
|
+
* GPU that has nothing to write into it: the flush skips the row, no clip pass
|
|
66
|
+
* writes it, and the joint is frozen for good.
|
|
67
67
|
*
|
|
68
68
|
* @param {ClothInstance} instance
|
|
69
69
|
* @param {EntityComponentDataset} ecd
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_seed_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_rig.js"],"names":[],"mappings":"AASA
|
|
1
|
+
{"version":3,"file":"cloth_seed_rig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/ecs/cloth_seed_rig.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH;;;;;;;;GAQG;AACH,mFAJW,MAAM,EAAE,mCAER,MAAM,QAqFhB;AAoED;;;;;;;;;;;;;;;;GAgBG;AACH,yFAFa,IAAI,CAoBhB"}
|
|
@@ -2,8 +2,8 @@ import { assert } from "../../../../core/assert.js";
|
|
|
2
2
|
import { quat3_multiply } from "../../../../core/geom/3d/quaternion/quat3_multiply.js";
|
|
3
3
|
import { v3_quaternion_apply } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
4
4
|
import { GPUStateAuthorityFlags } from "../../../ecs/gpu/GPUStateAuthorityFlags.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { gpu_authority_hold } from "../../../ecs/gpu/gpu_authority_hold.js";
|
|
6
|
+
import { gpu_authority_unhold } from "../../../ecs/gpu/gpu_authority_unhold.js";
|
|
7
7
|
import { TransformAttachment } from "../../../ecs/transform-attachment/TransformAttachment.js";
|
|
8
8
|
import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
|
|
9
9
|
|
|
@@ -16,22 +16,23 @@ import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
|
|
|
16
16
|
* identical either way; only seeding and write-back differ", and this file plus
|
|
17
17
|
* `cloth_write_back_rig.js` is the whole of the difference.
|
|
18
18
|
*
|
|
19
|
-
* ## The joints are entities, and cloth
|
|
19
|
+
* ## The joints are entities, and cloth holds their offsets
|
|
20
20
|
*
|
|
21
21
|
* A skinned model is a prefab spawned as entities, so a joint is an entity with
|
|
22
22
|
* a `TransformAttachment` — the offset from its parent joint — and a
|
|
23
|
-
* `GPUStateAuthority` saying who writes that offset's row. A
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* `GPUStateAuthority` saying who writes that offset's row. A clip bound to a
|
|
24
|
+
* joint writes the row on the GPU every frame, through the pose accumulator,
|
|
25
|
+
* after the CPU's flush and whatever any bit says. The bit states that, and
|
|
26
|
+
* stops the flush from racing it; it does not stop the clip.
|
|
27
27
|
*
|
|
28
|
-
* So the seed **
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
28
|
+
* So the seed **holds** every joint it drives (`gpu_authority_hold`): the bit
|
|
29
|
+
* clears, the animation manager mutes every binding that names the joint, and
|
|
30
|
+
* the row is what the write-back wrote. A clip that binds a held joint later
|
|
31
|
+
* binds muted, and one that leaves it leaves cloth's offset alone. Ending the
|
|
32
|
+
* hold grants nothing; a clip still bound takes the joint back. So a cape
|
|
33
|
+
* simulates under a clip that keys its bones too — exporters often bake every
|
|
34
|
+
* bone — and the exact evaluation (`t64_evaluate_world`) answers a held joint
|
|
35
|
+
* with cloth's offset, as the GPU shows it.
|
|
35
36
|
*
|
|
36
37
|
* ## The animated pose is constant, exactly as it is for a rope
|
|
37
38
|
*
|
|
@@ -41,7 +42,7 @@ import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
|
|
|
41
42
|
* animated pose comes from the skeleton and is live".
|
|
42
43
|
*
|
|
43
44
|
* For a **rigged** garment it is not live either, and the reason is the
|
|
44
|
-
*
|
|
45
|
+
* hold above: cloth owns those joints, so nothing else poses them,
|
|
45
46
|
* so their authored pose is the proxy's baked bind pose — constant in the
|
|
46
47
|
* anchor's frame, exactly as a rope's is. What moves is the anchor, and the
|
|
47
48
|
* anchor is a joint of the character's own animated skeleton, whose pose the
|
|
@@ -63,6 +64,10 @@ import { cloth_build_children, cloth_build_rows } from "./cloth_build_rows.js";
|
|
|
63
64
|
export function cloth_seed_rig(instance, proxy, joints, ecd, dt) {
|
|
64
65
|
assert.ok(proxy.isClothProxy === true, 'proxy must be a ClothProxy');
|
|
65
66
|
|
|
67
|
+
// Seeding takes the joints from nothing: `ClothWorld#reseed`, the only way back to an unseeded
|
|
68
|
+
// instance, gives the last seeding's holds back first.
|
|
69
|
+
assert.equal(instance.held_joints, null, 'a rig seeds over a rig that still holds its joints; ClothWorld#reseed gives them back first');
|
|
70
|
+
|
|
66
71
|
const joint_count = proxy.joint_count;
|
|
67
72
|
|
|
68
73
|
// Node 0 is the anchor, exactly as it is for the entity path: the fixed
|
|
@@ -89,10 +94,10 @@ export function cloth_seed_rig(instance, proxy, joints, ecd, dt) {
|
|
|
89
94
|
|
|
90
95
|
node_attachment[0] = null;
|
|
91
96
|
|
|
92
|
-
// What this seeding
|
|
93
|
-
// nothing
|
|
94
|
-
//
|
|
95
|
-
const
|
|
97
|
+
// What this seeding holds, so that giving it back is possible. A hold that
|
|
98
|
+
// nothing ends is half a transaction, and the half that is missing is the
|
|
99
|
+
// one that runs when the garment is removed.
|
|
100
|
+
const held = [];
|
|
96
101
|
|
|
97
102
|
for (let i = 0; i < joint_count; i++) {
|
|
98
103
|
const joint = joints[proxy.joint[i]];
|
|
@@ -108,15 +113,14 @@ export function cloth_seed_rig(instance, proxy, joints, ecd, dt) {
|
|
|
108
113
|
|
|
109
114
|
node_attachment[i + 1] = attachment;
|
|
110
115
|
|
|
111
|
-
// See the module docblock.
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
116
|
+
// See the module docblock. Every joint, whether or not a clip drives it now: one may bind
|
|
117
|
+
// it later, and the hold is what it finds there.
|
|
118
|
+
gpu_authority_hold(ecd, joint, GPUStateAuthorityFlags.TransformAttachment);
|
|
119
|
+
|
|
120
|
+
held.push(joint);
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
instance.
|
|
123
|
+
instance.held_joints = held;
|
|
120
124
|
|
|
121
125
|
instance.node_joint = node_joint;
|
|
122
126
|
instance.node_attachment = node_attachment;
|
|
@@ -209,41 +213,40 @@ function read_bind_pose(instance, proxy) {
|
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
/**
|
|
212
|
-
*
|
|
213
|
-
* seeding took from the GPU.
|
|
214
|
-
*
|
|
215
|
-
* The seed revokes so that the write-back reaches the row at all, and the
|
|
216
|
-
* consequence the module docblock states — "a joint cloth simulates stops being
|
|
217
|
-
* animatable by a clip" — is only the right trade while the cloth is *there*.
|
|
218
|
-
* A garment removed and nothing re-granting leaves its joints owned by a CPU
|
|
219
|
-
* that is no longer writing them: neither animated nor simulated, and stuck in
|
|
220
|
-
* the pose the solver stopped in.
|
|
216
|
+
* End the hold this cloth's seeding took on every joint's `TransformAttachment`.
|
|
221
217
|
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
218
|
+
* Ending a hold grants nothing, and that is the point: who writes a joint once
|
|
219
|
+
* the garment is gone is not cloth's to say. A clip still bound to the joint
|
|
220
|
+
* takes it back (the animation manager hears the hold end); a joint no clip
|
|
221
|
+
* binds stays the CPU's, holding the offset cloth last wrote. Either way the
|
|
222
|
+
* joint starts from that offset: a clip taking it back rests there, and finds
|
|
223
|
+
* it in the row on every axis it does not key. Granting it here
|
|
224
|
+
* instead — as this did — hands a joint whose clip left during the hold to a
|
|
225
|
+
* GPU that has nothing to write into it: the flush skips the row, no clip pass
|
|
226
|
+
* writes it, and the joint is frozen for good.
|
|
224
227
|
*
|
|
225
228
|
* @param {ClothInstance} instance
|
|
226
229
|
* @param {EntityComponentDataset} ecd
|
|
227
230
|
* @returns {void}
|
|
228
231
|
*/
|
|
229
232
|
export function cloth_release_rig(instance, ecd) {
|
|
230
|
-
const
|
|
233
|
+
const held = instance.held_joints;
|
|
231
234
|
|
|
232
|
-
if (
|
|
235
|
+
if (held === null) {
|
|
233
236
|
return;
|
|
234
237
|
}
|
|
235
238
|
|
|
236
|
-
for (let i = 0; i <
|
|
237
|
-
const joint =
|
|
239
|
+
for (let i = 0; i < held.length; i++) {
|
|
240
|
+
const joint = held[i];
|
|
238
241
|
|
|
239
242
|
if (!ecd.entityExists(joint)) {
|
|
240
243
|
continue;
|
|
241
244
|
}
|
|
242
245
|
|
|
243
|
-
|
|
246
|
+
gpu_authority_unhold(ecd, joint, GPUStateAuthorityFlags.TransformAttachment);
|
|
244
247
|
}
|
|
245
248
|
|
|
246
|
-
instance.
|
|
249
|
+
instance.held_joints = null;
|
|
247
250
|
}
|
|
248
251
|
|
|
249
252
|
const COMPOSE = new Float64Array(3);
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* worst a shape one fixed step stale.
|
|
22
22
|
*
|
|
23
23
|
* That is also the shape of the engine's own precedent:
|
|
24
|
-
* `
|
|
24
|
+
* `IKGoalSystem` evaluates the world poses the hierarchy composes
|
|
25
25
|
* and writes local ones back, and §11.2's rig path writes
|
|
26
26
|
* `Node3D.transform_local` for the same reason — a local transform is what a
|
|
27
27
|
* joint angle *is*.
|
|
@@ -33,7 +33,7 @@ import { cloth_reconstruct_pose } from "./cloth_reconstruct_pose.js";
|
|
|
33
33
|
* worst a shape one fixed step stale.
|
|
34
34
|
*
|
|
35
35
|
* That is also the shape of the engine's own precedent:
|
|
36
|
-
* `
|
|
36
|
+
* `IKGoalSystem` evaluates the world poses the hierarchy composes
|
|
37
37
|
* and writes local ones back, and §11.2's rig path writes
|
|
38
38
|
* `Node3D.transform_local` for the same reason — a local transform is what a
|
|
39
39
|
* joint angle *is*.
|