@woosh/meep-engine 3.44.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/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/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/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 +5 -0
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +48 -2
- package/src/engine/graphics3/AnimationSystem.d.ts +5 -0
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +47 -2
- package/src/engine/graphics3/register_clips.d.ts +29 -0
- package/src/engine/graphics3/register_clips.d.ts.map +1 -1
- package/src/engine/graphics3/register_clips.js +52 -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/PLAN.md +10 -8
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts +22 -0
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.d.ts.map +1 -1
- package/src/engine/physics/cloth/build/cloth_bind_in_frame.js +51 -19
- 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 +16 -2
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.d.ts.map +1 -1
- package/src/engine/physics/cloth/build/cloth_proxy_from_mesh.js +19 -24
- 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.map +1 -1
- package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +16 -61
- 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/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +40 -130
- package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_build_rows.js +17 -58
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_dynamics_map.js +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 +44 -104
- package/src/engine/physics/cloth/ecs/cloth_geodesic.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_geodesic.js +6 -13
- package/src/engine/physics/cloth/ecs/cloth_holds.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_holds.js +15 -40
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +45 -79
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +7 -27
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +30 -62
- 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 +2 -28
- package/src/engine/physics/cloth/playground/garment_main.js +4 -19
- package/src/engine/physics/cloth/playground/main.js +6 -48
- 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.map +1 -1
- package/src/engine/physics/cloth/solver/ClothState.js +16 -76
- 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.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_contact_find.js +3 -2
- package/src/engine/physics/cloth/solver/cloth_hold_line.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_hold_line.js +2 -14
- 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.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_self_find.js +6 -55
- 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_step.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step.js +6 -28
- package/src/engine/physics/cloth/solver/cloth_step_instance.d.ts.map +1 -1
- package/src/engine/physics/cloth/solver/cloth_step_instance.js +2 -3
- 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/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 +3 -1
- package/src/engine/physics/cloth/wind/cloth_sample_air.d.ts.map +1 -1
- package/src/engine/physics/cloth/wind/cloth_sample_air.js +40 -62
- 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/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/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/playground/image_decode_bench/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_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/main.d.ts.map +1 -1
- package/src/shade/playground/texture_encode/main.js +2 -1
- 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/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/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/particles/optimizer/dag/particle_vector_extract.d.ts.map +1 -1
- package/src/shade/renderer/particles/optimizer/dag/particle_vector_extract.js +3 -2
|
@@ -7,7 +7,8 @@ import { System } from "../ecs/System.js";
|
|
|
7
7
|
import { AnimationClips } from "./animation/AnimationClips.js";
|
|
8
8
|
import { ClipListPlayer } from "./animation/ClipListPlayer.js";
|
|
9
9
|
import { write_clip_playback } from "./animation/write_clip_playback.js";
|
|
10
|
-
import { register_clips, unregister_clips } from "./register_clips.js";
|
|
10
|
+
import { hold_clip_targets, register_clips, release_clip_targets, unregister_clips } from "./register_clips.js";
|
|
11
|
+
import { RowChains } from "./RowChains.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* @type {ClipPlayback[]}
|
|
@@ -27,6 +28,10 @@ const NOTHING = Object.freeze([]);
|
|
|
27
28
|
* components, whoever put them there — a model `MeshSystem` loaded, or a rig built in code. New
|
|
28
29
|
* clips are a new component, which this system sees as the entity leaving and coming back.
|
|
29
30
|
*
|
|
31
|
+
* **Every node the clips key holds a row here** ({@link hold_clip_targets}), from the clips being
|
|
32
|
+
* taken up until they go. A clip binds only once all of them do, and a keyed node outside every skin
|
|
33
|
+
* with nothing drawn under it is held by no other system.
|
|
34
|
+
*
|
|
30
35
|
* **It is the CPU that plays the animation and the GPU that draws it.** Shade can advance a clip
|
|
31
36
|
* itself, and this never asks it to — `AnimationClipFlags.Playing` is left clear and every audible
|
|
32
37
|
* clip's time is written down each frame from the player's own clock. That is I-4: the pose
|
|
@@ -51,10 +56,17 @@ export class AnimationSystem extends System {
|
|
|
51
56
|
#scene;
|
|
52
57
|
|
|
53
58
|
/**
|
|
54
|
-
* @type {Map<number, {player: ClipListPlayer, clips: ShadeAnimationClip[], bound: boolean, clip_registration: ClipRegistration|null, played_slots: Int32Array, written: Float32Array, poses: PosePlayback[]}>}
|
|
59
|
+
* @type {Map<number, {player: ClipListPlayer, clips: ShadeAnimationClip[], bound: boolean, held: boolean, clip_registration: ClipRegistration|null, played_slots: Int32Array, written: Float32Array, poses: PosePlayback[]}>}
|
|
55
60
|
*/
|
|
56
61
|
#entries = new Map();
|
|
57
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The chains of the nodes the clips key. Null until the system has a dataset.
|
|
65
|
+
*
|
|
66
|
+
* @type {RowChains|null}
|
|
67
|
+
*/
|
|
68
|
+
#chains = null;
|
|
69
|
+
|
|
58
70
|
/**
|
|
59
71
|
* @param {GraphicsEngine} graphics
|
|
60
72
|
* @param {Scene} scene
|
|
@@ -169,6 +181,7 @@ export class AnimationSystem extends System {
|
|
|
169
181
|
player: ClipListPlayer.from(component),
|
|
170
182
|
clips: clips.clips,
|
|
171
183
|
bound: false,
|
|
184
|
+
held: false,
|
|
172
185
|
clip_registration: null,
|
|
173
186
|
played_slots: new Int32Array(0),
|
|
174
187
|
written: new Float32Array(0),
|
|
@@ -186,17 +199,41 @@ export class AnimationSystem extends System {
|
|
|
186
199
|
|
|
187
200
|
if (entry !== undefined) {
|
|
188
201
|
this.#release_clips(entry);
|
|
202
|
+
|
|
203
|
+
if (entry.held) {
|
|
204
|
+
release_clip_targets(this.#chains, entry.clips);
|
|
205
|
+
|
|
206
|
+
entry.held = false;
|
|
207
|
+
}
|
|
189
208
|
}
|
|
190
209
|
|
|
191
210
|
this.#entries.delete(entity);
|
|
192
211
|
}
|
|
193
212
|
|
|
213
|
+
async startup(entityManager) {
|
|
214
|
+
// the scene's rows are this dataset's entities; the first system to place one says so
|
|
215
|
+
const dataset = entityManager.dataset;
|
|
216
|
+
const scene = this.#scene;
|
|
217
|
+
|
|
218
|
+
assert.ok(
|
|
219
|
+
scene.dataset === null || scene.dataset === undefined || scene.dataset === dataset,
|
|
220
|
+
'the scene is bound to another dataset'
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
scene.dataset = dataset;
|
|
224
|
+
|
|
225
|
+
this.#chains = new RowChains(dataset);
|
|
226
|
+
}
|
|
227
|
+
|
|
194
228
|
async shutdown(entityManager) {
|
|
195
229
|
for (const entry of this.#entries.values()) {
|
|
196
230
|
this.#release_clips(entry);
|
|
197
231
|
}
|
|
198
232
|
|
|
199
233
|
this.#entries.clear();
|
|
234
|
+
|
|
235
|
+
this.#chains.destroy();
|
|
236
|
+
this.#chains = null;
|
|
200
237
|
}
|
|
201
238
|
|
|
202
239
|
/**
|
|
@@ -328,6 +365,11 @@ export class AnimationSystem extends System {
|
|
|
328
365
|
entry.poses = clips.map(() => new PosePlayback());
|
|
329
366
|
|
|
330
367
|
entry.bound = true;
|
|
368
|
+
|
|
369
|
+
// before anything registers, so the clips bind in the update that registers them
|
|
370
|
+
hold_clip_targets(this.#chains, clips);
|
|
371
|
+
|
|
372
|
+
entry.held = true;
|
|
331
373
|
}
|
|
332
374
|
|
|
333
375
|
/**
|
|
@@ -342,6 +384,9 @@ export class AnimationSystem extends System {
|
|
|
342
384
|
// that ends while the renderer is being replaced still says so.
|
|
343
385
|
const manager = context === null ? null : context.animation_manager;
|
|
344
386
|
|
|
387
|
+
// a new context after a restart is acquired in whole; until there is one, holds are recorded
|
|
388
|
+
this.#chains.bind(context === null ? null : context.rows);
|
|
389
|
+
|
|
345
390
|
for (const [entity, entry] of this.#entries) {
|
|
346
391
|
if (!entry.bound) {
|
|
347
392
|
this.#bind(entry, entity, ecd);
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hold a row, with the chain above it, for every entity the clips key.
|
|
3
|
+
*
|
|
4
|
+
* **A clip binds only once every node it keys holds a row**, and until then it is queued and moves
|
|
5
|
+
* nothing. A skin holds its joints' chains and a primitive its own, but a keyed node that is neither
|
|
6
|
+
* — a leaf an exporter left out of the skin, a socket nothing is attached to yet, an animated empty
|
|
7
|
+
* — is held by nothing else, and one such node keeps the whole clip from playing. So the driver that
|
|
8
|
+
* plays the clips holds every node they key, for as long as it has the clips.
|
|
9
|
+
*
|
|
10
|
+
* Every clip of the set, not only the ones registered: the set is replaced and never edited, so its
|
|
11
|
+
* targets are settled once, while which of its clips are registered moves with the list or the graph.
|
|
12
|
+
*
|
|
13
|
+
* One hold per channel, given back one per channel by {@link release_clip_targets}: the chains count
|
|
14
|
+
* holds, so a node keyed by several channels is held until the last of them is released.
|
|
15
|
+
*
|
|
16
|
+
* @param {RowChains} chains
|
|
17
|
+
* @param {ShadeAnimationClip[]} clips their channels target entities
|
|
18
|
+
*/
|
|
19
|
+
export function hold_clip_targets(chains: RowChains, clips: ShadeAnimationClip[]): void;
|
|
20
|
+
/**
|
|
21
|
+
* Give back what {@link hold_clip_targets} took for the same clips. Released after the clips are
|
|
22
|
+
* unregistered, so no binding outlives the row it writes.
|
|
23
|
+
*
|
|
24
|
+
* @param {RowChains} chains
|
|
25
|
+
* @param {ShadeAnimationClip[]} clips
|
|
26
|
+
*/
|
|
27
|
+
export function release_clip_targets(chains: RowChains, clips: ShadeAnimationClip[]): void;
|
|
1
28
|
/**
|
|
2
29
|
* Make some of an entity's clips playable — the ones a driver actually plays, and no others.
|
|
3
30
|
*
|
|
@@ -28,6 +55,7 @@ export function unregister_clips(registration: ClipRegistration): void;
|
|
|
28
55
|
/**
|
|
29
56
|
* @typedef {import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext} GPUSceneContext
|
|
30
57
|
* @typedef {import("../../shade/renderer/animation/ShadeAnimationClip.js").ShadeAnimationClip} ShadeAnimationClip
|
|
58
|
+
* @typedef {import("./RowChains.js").RowChains} RowChains
|
|
31
59
|
*/
|
|
32
60
|
/**
|
|
33
61
|
* The id a clip has when nobody registered it.
|
|
@@ -61,4 +89,5 @@ export class ClipRegistration {
|
|
|
61
89
|
}
|
|
62
90
|
export type GPUSceneContext = import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext;
|
|
63
91
|
export type ShadeAnimationClip = import("../../shade/renderer/animation/ShadeAnimationClip.js").ShadeAnimationClip;
|
|
92
|
+
export type RowChains = import("./RowChains.js").RowChains;
|
|
64
93
|
//# sourceMappingURL=register_clips.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register_clips.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/register_clips.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"register_clips.d.ts","sourceRoot":"","sources":["../../../../src/engine/graphics3/register_clips.js"],"names":[],"mappings":"AAyCA;;;;;;;;;;;;;;;;;GAiBG;AACH,0CAHW,SAAS,SACT,kBAAkB,EAAE,QAa9B;AAED;;;;;;GAMG;AACH,6CAHW,SAAS,SACT,kBAAkB,EAAE,QAa9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wCALW,eAAe,SACf,kBAAkB,EAAE,SACpB,UAAU,MAAM,CAAC,GACf,gBAAgB,CA6B5B;AAED;;;;;;;GAOG;AACH,+CAFW,gBAAgB,QAqB1B;AAnKD;;;;GAIG;AAEH;;;GAGG;AACH,kCAFU,MAAM,CAEsB;AAEtC;;;;;;;GAOG;AACH;IACI;;;;;;;;;OASG;IACH,SAFU,eAAe,GAAC,IAAI,CAEf;IAEf;;OAEG;IACH,KAFU,UAAU,CAEI;CAC3B;8BApCY,OAAO,+CAA+C,EAAE,eAAe;iCACvE,OAAO,sDAAsD,EAAE,kBAAkB;wBACjF,OAAO,gBAAgB,EAAE,SAAS"}
|
|
@@ -3,6 +3,7 @@ import { assert } from "../../core/assert.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* @typedef {import("../../shade/renderer/scene/GPUSceneContext.js").GPUSceneContext} GPUSceneContext
|
|
5
5
|
* @typedef {import("../../shade/renderer/animation/ShadeAnimationClip.js").ShadeAnimationClip} ShadeAnimationClip
|
|
6
|
+
* @typedef {import("./RowChains.js").RowChains} RowChains
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -38,6 +39,57 @@ export class ClipRegistration {
|
|
|
38
39
|
ids = new Int32Array(0);
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Hold a row, with the chain above it, for every entity the clips key.
|
|
44
|
+
*
|
|
45
|
+
* **A clip binds only once every node it keys holds a row**, and until then it is queued and moves
|
|
46
|
+
* nothing. A skin holds its joints' chains and a primitive its own, but a keyed node that is neither
|
|
47
|
+
* — a leaf an exporter left out of the skin, a socket nothing is attached to yet, an animated empty
|
|
48
|
+
* — is held by nothing else, and one such node keeps the whole clip from playing. So the driver that
|
|
49
|
+
* plays the clips holds every node they key, for as long as it has the clips.
|
|
50
|
+
*
|
|
51
|
+
* Every clip of the set, not only the ones registered: the set is replaced and never edited, so its
|
|
52
|
+
* targets are settled once, while which of its clips are registered moves with the list or the graph.
|
|
53
|
+
*
|
|
54
|
+
* One hold per channel, given back one per channel by {@link release_clip_targets}: the chains count
|
|
55
|
+
* holds, so a node keyed by several channels is held until the last of them is released.
|
|
56
|
+
*
|
|
57
|
+
* @param {RowChains} chains
|
|
58
|
+
* @param {ShadeAnimationClip[]} clips their channels target entities
|
|
59
|
+
*/
|
|
60
|
+
export function hold_clip_targets(chains, clips) {
|
|
61
|
+
assert.defined(chains, 'chains');
|
|
62
|
+
assert.isArray(clips, 'clips');
|
|
63
|
+
|
|
64
|
+
for (let i = 0; i < clips.length; i++) {
|
|
65
|
+
const channels = clips[i].channels;
|
|
66
|
+
|
|
67
|
+
for (let j = 0; j < channels.length; j++) {
|
|
68
|
+
chains.hold(channels[j].target);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Give back what {@link hold_clip_targets} took for the same clips. Released after the clips are
|
|
75
|
+
* unregistered, so no binding outlives the row it writes.
|
|
76
|
+
*
|
|
77
|
+
* @param {RowChains} chains
|
|
78
|
+
* @param {ShadeAnimationClip[]} clips
|
|
79
|
+
*/
|
|
80
|
+
export function release_clip_targets(chains, clips) {
|
|
81
|
+
assert.defined(chains, 'chains');
|
|
82
|
+
assert.isArray(clips, 'clips');
|
|
83
|
+
|
|
84
|
+
for (let i = 0; i < clips.length; i++) {
|
|
85
|
+
const channels = clips[i].channels;
|
|
86
|
+
|
|
87
|
+
for (let j = 0; j < channels.length; j++) {
|
|
88
|
+
chains.release(channels[j].target);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
41
93
|
/**
|
|
42
94
|
* Make some of an entity's clips playable — the ones a driver actually plays, and no others.
|
|
43
95
|
*
|
|
@@ -50,4 +50,13 @@ export function fatten_world_aabb_array(aabb: number[] | Float32Array | Float64A
|
|
|
50
50
|
* @param {number} dt step size
|
|
51
51
|
*/
|
|
52
52
|
export function compute_fat_world_aabb(result: number[] | Float32Array | Float64Array, result_offset: number, shape: AbstractShape3D, transform: Transform64, vx: number, vy: number, vz: number, dt: number): void;
|
|
53
|
+
/**
|
|
54
|
+
* Constant inflation applied to a world AABB so a small motion doesn't churn
|
|
55
|
+
* the broadphase. Tuned to Box2D / Bullet conventions. Symmetric: jitter has
|
|
56
|
+
* no preferred direction.
|
|
57
|
+
*
|
|
58
|
+
* Exported because `ClothColliderIndex` fattens its leaves by the same slack, for the same reason.
|
|
59
|
+
* @type {number}
|
|
60
|
+
*/
|
|
61
|
+
export const FAT_LINEAR: number;
|
|
53
62
|
//# sourceMappingURL=compute_fat_world_aabb.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compute_fat_world_aabb.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/compute_fat_world_aabb.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compute_fat_world_aabb.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/compute_fat_world_aabb.js"],"names":[],"mappings":"AAyBA;;;;;;;;GAQG;AACH,2CALW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,MAAM,wDAchB;AAED;;;;;;;;;;;;;GAaG;AACH,wCAPW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,UAClC,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAUhB;AAKD;;;;;;;;;;GAUG;AACH,8CANW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,UAClC,MAAM,YACN,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,mBAClC,MAAM,MACN,MAAM,QAkBhB;AAED;;;;;;;;;;;;;GAaG;AACH,+CATW,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,iBAClC,MAAM,sDAGN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAShB;AAvHD;;;;;;;GAOG;AACH,yBAFU,MAAM,CAEe"}
|
|
@@ -6,9 +6,11 @@ const scratch_local = new Float64Array(6);
|
|
|
6
6
|
* Constant inflation applied to a world AABB so a small motion doesn't churn
|
|
7
7
|
* the broadphase. Tuned to Box2D / Bullet conventions. Symmetric: jitter has
|
|
8
8
|
* no preferred direction.
|
|
9
|
+
*
|
|
10
|
+
* Exported because `ClothColliderIndex` fattens its leaves by the same slack, for the same reason.
|
|
9
11
|
* @type {number}
|
|
10
12
|
*/
|
|
11
|
-
const FAT_LINEAR = 0.05;
|
|
13
|
+
export const FAT_LINEAR = 0.05;
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Per-second-of-velocity inflation. Two seconds of motion is a generous
|
|
@@ -270,7 +270,7 @@ export class ClothCollider {
|
|
|
270
270
|
friction_scale = 1; // multiplies the entity's Collider#friction
|
|
271
271
|
layer = 1; // RigidBody semantics, and see below
|
|
272
272
|
mask = 0xFFFFFFFF;
|
|
273
|
-
flags = 0; // ClothColliderFlags
|
|
273
|
+
flags = 0; // ClothColliderFlags: none defined; bit 0 was Static, retired
|
|
274
274
|
}
|
|
275
275
|
```
|
|
276
276
|
|
|
@@ -675,10 +675,12 @@ bundles — the engine ships raw source, and a check moved out of `assert.*` sto
|
|
|
675
675
|
### 5.4 Colouring
|
|
676
676
|
|
|
677
677
|
The particle graph is coloured so no constraint touches two particles of the same colour, using the
|
|
678
|
-
|
|
679
|
-
`
|
|
680
|
-
the
|
|
681
|
-
|
|
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;
|
|
682
684
|
for a chain it runs at link time on a graph of a few dozen nodes. Nothing colours per step and the
|
|
683
685
|
runtime never sees a graph object.
|
|
684
686
|
|
|
@@ -1620,7 +1622,7 @@ For a **rigged** garment, only steps 5–8 run, over the joint graph rather than
|
|
|
1620
1622
|
(`cloth_rig.spec.js`).
|
|
1621
1623
|
6. Bake `d_geo` — geodesic distance from every particle to the fixed set. This one array drives the
|
|
1622
1624
|
tether row, the slack profile, and the pinning, so the three cannot disagree.
|
|
1623
|
-
7. Colour the particle graph (`
|
|
1625
|
+
7. Colour the particle graph (`csr_graph_color_greedy`, checked by `csr_graph_validate_coloring`), and permute
|
|
1624
1626
|
the particle order so each colour is a contiguous range.
|
|
1625
1627
|
8. Resolve joint **names to indices** into `Skin#joints`, using `SceneBundleInstance#nodes`. This is
|
|
1626
1628
|
the only place a name appears anywhere in the system.
|
|
@@ -1803,9 +1805,9 @@ What this design takes from the engine rather than building:
|
|
|
1803
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` |
|
|
1804
1806
|
| Proxy decimation | `bt_mesh_simplify_by_error`, `bt_mesh_compute_vertex_quadrics` |
|
|
1805
1807
|
| Mesh cleanup | `geometry_deduplicate_vertices` |
|
|
1806
|
-
| Graph colouring | `core/graph/
|
|
1808
|
+
| Graph colouring | `core/graph/csr/csr_graph_color_greedy.js`, `csr_graph_validate_coloring.js` |
|
|
1807
1809
|
| Collider shapes and their SDFs | `core/geom/3d/shape/*` — closed-form `signed_distance_at_point` on every primitive |
|
|
1808
|
-
| Collider AABBs, pose caching | `core/geom/3d/aabb/*`, `
|
|
1810
|
+
| Collider AABBs, pose caching | `core/geom/3d/aabb/*`, `aabb3_transform_oriented_array` |
|
|
1809
1811
|
| Collider ECS wiring | `Collider`, `ColliderFlags`, `ColliderObserverSystem` (as the pattern) |
|
|
1810
1812
|
| "Opt a collider into a second simulation" | `FluidObstacle` + `FluidObstacleSystem`, `AcousticBody` |
|
|
1811
1813
|
| Collider index shape | `AcousticOccluderIndex` + `OccluderBody` |
|
|
@@ -10,6 +10,12 @@
|
|
|
10
10
|
* bind pose — so that a re-seed reads what was authored rather than what the
|
|
11
11
|
* solver left on the joints.
|
|
12
12
|
*
|
|
13
|
+
* Rigid, as every pose cloth holds is: a local scale is not applied. That is
|
|
14
|
+
* not a convention this can opt out of alone — the write-back is rigid too,
|
|
15
|
+
* and the GPU applies a parent's scale on top of what cloth writes, so a
|
|
16
|
+
* scaled bake would draw a scaled link twice over. A builder refuses a rig
|
|
17
|
+
* where it would matter, with {@link cloth_bind_scaled_above}.
|
|
18
|
+
*
|
|
13
19
|
* @author Alex Goldring
|
|
14
20
|
* @copyright Company Named Limited (c) 2026
|
|
15
21
|
*
|
|
@@ -18,5 +24,21 @@
|
|
|
18
24
|
* @returns {function(number): Float64Array}
|
|
19
25
|
*/
|
|
20
26
|
export function cloth_bind_in_frame(prefab: Prefab, frame: number): (arg0: number) => Float64Array;
|
|
27
|
+
/**
|
|
28
|
+
* The nearest node above `node`, up to and including the prefab's root, whose
|
|
29
|
+
* rest scale is not one; or -1.
|
|
30
|
+
*
|
|
31
|
+
* Cloth simulates and writes back rigid poses, and everything under a scaled
|
|
32
|
+
* node is drawn scaled: a link below one is simulated at its authored length and
|
|
33
|
+
* drawn at that times the scale, and a scale above the frame draws the whole
|
|
34
|
+
* garment at another size than the one its colliders meet. Measured, a 10 cm
|
|
35
|
+
* chain under a joint scaled by 2: simulated links 0.1, drawn 0.2. A node's own
|
|
36
|
+
* scale moves nothing cloth places, so it is not asked about.
|
|
37
|
+
*
|
|
38
|
+
* @param {Prefab} prefab
|
|
39
|
+
* @param {number} node
|
|
40
|
+
* @returns {number}
|
|
41
|
+
*/
|
|
42
|
+
export function cloth_bind_scaled_above(prefab: Prefab, node: number): number;
|
|
21
43
|
export type Prefab = import("../../../graphics3/prefab/Prefab.js").Prefab;
|
|
22
44
|
//# sourceMappingURL=cloth_bind_in_frame.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_bind_in_frame.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/build/cloth_bind_in_frame.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH
|
|
1
|
+
{"version":3,"file":"cloth_bind_in_frame.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/build/cloth_bind_in_frame.js"],"names":[],"mappings":"AAOA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,4CAJW,MAAM,SACN,MAAM,UACK,MAAM,KAAG,YAAY,CAqC1C;AASD;;;;;;;;;;;;;;GAcG;AACH,gDAJW,MAAM,QACN,MAAM,GACJ,MAAM,CAgBlB;qBAlGY,OAAO,qCAAqC,EAAE,MAAM"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { v3_quaternion_apply } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
1
|
+
import { pose3_compose_array } from "../../../../core/geom/3d/pose/pose3_compose_array.js";
|
|
3
2
|
import {
|
|
4
3
|
TRANSFORM64_ROTATION_OFFSET,
|
|
4
|
+
TRANSFORM64_SCALE_OFFSET,
|
|
5
5
|
TRANSFORM64_TRANSLATION_OFFSET
|
|
6
6
|
} from "../../../ecs/transform/Transform64.js";
|
|
7
7
|
|
|
@@ -18,6 +18,12 @@ import {
|
|
|
18
18
|
* bind pose — so that a re-seed reads what was authored rather than what the
|
|
19
19
|
* solver left on the joints.
|
|
20
20
|
*
|
|
21
|
+
* Rigid, as every pose cloth holds is: a local scale is not applied. That is
|
|
22
|
+
* not a convention this can opt out of alone — the write-back is rigid too,
|
|
23
|
+
* and the GPU applies a parent's scale on top of what cloth writes, so a
|
|
24
|
+
* scaled bake would draw a scaled link twice over. A builder refuses a rig
|
|
25
|
+
* where it would matter, with {@link cloth_bind_scaled_above}.
|
|
26
|
+
*
|
|
21
27
|
* @author Alex Goldring
|
|
22
28
|
* @copyright Company Named Limited (c) 2026
|
|
23
29
|
*
|
|
@@ -45,25 +51,13 @@ export function cloth_bind_in_frame(prefab, frame) {
|
|
|
45
51
|
|
|
46
52
|
answer = new Float64Array(7);
|
|
47
53
|
|
|
48
|
-
|
|
54
|
+
pose3_compose_array(
|
|
49
55
|
answer, 0,
|
|
50
|
-
local[TRANSFORM64_TRANSLATION_OFFSET],
|
|
51
|
-
local[TRANSFORM64_TRANSLATION_OFFSET + 1],
|
|
52
|
-
local[TRANSFORM64_TRANSLATION_OFFSET + 2],
|
|
53
|
-
above[3], above[4], above[5], above[6]
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
answer[0] += above[0];
|
|
57
|
-
answer[1] += above[1];
|
|
58
|
-
answer[2] += above[2];
|
|
59
|
-
|
|
60
|
-
quat3_multiply(
|
|
61
56
|
answer, 3,
|
|
62
|
-
above
|
|
63
|
-
|
|
64
|
-
local
|
|
65
|
-
local
|
|
66
|
-
local[TRANSFORM64_ROTATION_OFFSET + 3]
|
|
57
|
+
above, 0,
|
|
58
|
+
above, 3,
|
|
59
|
+
local, TRANSFORM64_TRANSLATION_OFFSET,
|
|
60
|
+
local, TRANSFORM64_ROTATION_OFFSET
|
|
67
61
|
);
|
|
68
62
|
|
|
69
63
|
known.set(node, answer);
|
|
@@ -73,3 +67,41 @@ export function cloth_bind_in_frame(prefab, frame) {
|
|
|
73
67
|
|
|
74
68
|
return pose;
|
|
75
69
|
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* How far a rest scale may be from one before it is a scale: the tolerance
|
|
73
|
+
* `prefab_normalize_skin_frames` holds a skin's frame to, for the same reason.
|
|
74
|
+
* @type {number}
|
|
75
|
+
*/
|
|
76
|
+
const SCALE_TOLERANCE = 1e-4;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The nearest node above `node`, up to and including the prefab's root, whose
|
|
80
|
+
* rest scale is not one; or -1.
|
|
81
|
+
*
|
|
82
|
+
* Cloth simulates and writes back rigid poses, and everything under a scaled
|
|
83
|
+
* node is drawn scaled: a link below one is simulated at its authored length and
|
|
84
|
+
* drawn at that times the scale, and a scale above the frame draws the whole
|
|
85
|
+
* garment at another size than the one its colliders meet. Measured, a 10 cm
|
|
86
|
+
* chain under a joint scaled by 2: simulated links 0.1, drawn 0.2. A node's own
|
|
87
|
+
* scale moves nothing cloth places, so it is not asked about.
|
|
88
|
+
*
|
|
89
|
+
* @param {Prefab} prefab
|
|
90
|
+
* @param {number} node
|
|
91
|
+
* @returns {number}
|
|
92
|
+
*/
|
|
93
|
+
export function cloth_bind_scaled_above(prefab, node) {
|
|
94
|
+
const parent = prefab.parent;
|
|
95
|
+
|
|
96
|
+
for (let above = parent[node]; above >= 0; above = parent[above]) {
|
|
97
|
+
const local = prefab.local[above];
|
|
98
|
+
|
|
99
|
+
if (Math.abs(local[TRANSFORM64_SCALE_OFFSET] - 1) > SCALE_TOLERANCE
|
|
100
|
+
|| Math.abs(local[TRANSFORM64_SCALE_OFFSET + 1] - 1) > SCALE_TOLERANCE
|
|
101
|
+
|| Math.abs(local[TRANSFORM64_SCALE_OFFSET + 2] - 1) > SCALE_TOLERANCE) {
|
|
102
|
+
return above;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return -1;
|
|
107
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_proxy_from_joints.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/build/cloth_proxy_from_joints.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_proxy_from_joints.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/build/cloth_proxy_from_joints.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;GAKG;AAEH;;;;;GAKG;AAEH;;;;;;;;;;;;;;GAcG;AACH,gDARW,MAAM,QACN,IAAI,eAEJ,MAAM,EAAE;IAES,IAAI,GAArB,MAAM;IACJ,qBAAqB,CA6QjC;qBA9UY,OAAO,qCAAqC,EAAE,MAAM;mBACpD,OAAO,8CAA8C,EAAE,IAAI;;;;;;;;WAwC1D,MAAM;;;;eACN,UAAU;;;;;;WAKV,UAAU,GAAC,IAAI;;;;YACf,eAAe,EAAE;;;;WACjB,MAAM;;2BAtDO,iBAAiB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ClothProxy } from "./ClothProxy.js";
|
|
2
|
-
import { cloth_bind_in_frame } from "./cloth_bind_in_frame.js";
|
|
2
|
+
import { cloth_bind_in_frame, cloth_bind_scaled_above } from "./cloth_bind_in_frame.js";
|
|
3
|
+
import { number_compare_ascending } from "../../../../core/primitives/numbers/number_compare_ascending.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @typedef {import("../../../graphics3/prefab/Prefab.js").Prefab} Prefab
|
|
@@ -161,7 +162,7 @@ export function cloth_proxy_from_joints(prefab, skin, joint_names, { name = "" }
|
|
|
161
162
|
}
|
|
162
163
|
}
|
|
163
164
|
|
|
164
|
-
hung_from.sort(
|
|
165
|
+
hung_from.sort(number_compare_ascending);
|
|
165
166
|
|
|
166
167
|
// The frame: the nearest skin joint above every bone the garment hangs from
|
|
167
168
|
// — for one bone, the bone itself.
|
|
@@ -236,6 +237,19 @@ export function cloth_proxy_from_joints(prefab, skin, joint_names, { name = "" }
|
|
|
236
237
|
|
|
237
238
|
const particle_name = [];
|
|
238
239
|
|
|
240
|
+
for (let i = 0; i < particle_count; i++) {
|
|
241
|
+
const scaled = cloth_bind_scaled_above(prefab, ordered[i]);
|
|
242
|
+
|
|
243
|
+
if (scaled >= 0) {
|
|
244
|
+
const local = prefab.local[scaled];
|
|
245
|
+
|
|
246
|
+
return refuse(
|
|
247
|
+
`${name}: "${name_of[scaled]}", above "${name_of[ordered[i]]}", is scaled by (${local.scale_x}, ${local.scale_y}, ${local.scale_z}) at rest;`
|
|
248
|
+
+ ` cloth poses its joints rigidly, so it would simulate a different garment from the one drawn`
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
239
253
|
const pose = cloth_bind_in_frame(prefab, frame_node);
|
|
240
254
|
|
|
241
255
|
for (let i = 0; i < particle_count; i++) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_proxy_from_mesh.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/build/cloth_proxy_from_mesh.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_proxy_from_mesh.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/build/cloth_proxy_from_mesh.js"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;GAUG;AACH,8CARW,MAAM,QACN,IAAI,eACJ,MAAM,EAAE,aACR,UAAU,GAAC,MAAM,EAAE;IAEF,IAAI,GAArB,MAAM;IACJ,qBAAqB,CA8MjC;qBApQY,OAAO,qCAAqC,EAAE,MAAM;mBACpD,OAAO,8CAA8C,EAAE,IAAI;oCAC3D,OAAO,8BAA8B,EAAE,qBAAqB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { tri3_area } from "../../../../core/geom/3d/triangle/tri3_area.js";
|
|
1
2
|
import { ClothProxy } from "./ClothProxy.js";
|
|
2
|
-
import { cloth_bind_in_frame } from "./cloth_bind_in_frame.js";
|
|
3
|
+
import { cloth_bind_in_frame, cloth_bind_scaled_above } from "./cloth_bind_in_frame.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* @typedef {import("../../../graphics3/prefab/Prefab.js").Prefab} Prefab
|
|
@@ -140,6 +141,18 @@ export function cloth_proxy_from_mesh(prefab, skin, joint_names, triangles, { na
|
|
|
140
141
|
return refuse(`${name}: ${triangles.length} triangle indices is not a whole number of triangles`);
|
|
141
142
|
}
|
|
142
143
|
|
|
144
|
+
// Every vertex joint hangs from the frame, so one walk up from any of them asks the lot.
|
|
145
|
+
const scaled = cloth_bind_scaled_above(prefab, node[0]);
|
|
146
|
+
|
|
147
|
+
if (scaled >= 0) {
|
|
148
|
+
const local = prefab.local[scaled];
|
|
149
|
+
|
|
150
|
+
return refuse(
|
|
151
|
+
`${name}: "${name_of[scaled]}", above "${name_of[node[0]]}", is scaled by (${local.scale_x}, ${local.scale_y}, ${local.scale_z}) at rest;`
|
|
152
|
+
+ ` cloth poses its joints rigidly, so it would simulate a different garment from the one drawn`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
143
156
|
const pose = cloth_bind_in_frame(prefab, frame_node);
|
|
144
157
|
|
|
145
158
|
const rest_position = new Float32Array(particle_count * 3);
|
|
@@ -176,7 +189,11 @@ export function cloth_proxy_from_mesh(prefab, skin, joint_names, triangles, { na
|
|
|
176
189
|
}
|
|
177
190
|
}
|
|
178
191
|
|
|
179
|
-
if (
|
|
192
|
+
if (tri3_area(
|
|
193
|
+
rest_position[i0 * 3], rest_position[i0 * 3 + 1], rest_position[i0 * 3 + 2],
|
|
194
|
+
rest_position[i1 * 3], rest_position[i1 * 3 + 1], rest_position[i1 * 3 + 2],
|
|
195
|
+
rest_position[i2 * 3], rest_position[i2 * 3 + 1], rest_position[i2 * 3 + 2]
|
|
196
|
+
) <= 0) {
|
|
180
197
|
return refuse(
|
|
181
198
|
`${name}: triangle ${t} ("${joint_names[i0]}", "${joint_names[i1]}", "${joint_names[i2]}") has no area,`
|
|
182
199
|
+ ` so no normal and no hinge across it`
|
|
@@ -248,28 +265,6 @@ export function cloth_proxy_from_mesh(prefab, skin, joint_names, triangles, { na
|
|
|
248
265
|
};
|
|
249
266
|
}
|
|
250
267
|
|
|
251
|
-
/**
|
|
252
|
-
* Twice the area of a triangle of the rest pose.
|
|
253
|
-
*
|
|
254
|
-
* @param {Float32Array} position
|
|
255
|
-
* @param {number} a
|
|
256
|
-
* @param {number} b
|
|
257
|
-
* @param {number} c
|
|
258
|
-
* @returns {number}
|
|
259
|
-
* @private
|
|
260
|
-
*/
|
|
261
|
-
function twice_area(position, a, b, c) {
|
|
262
|
-
const ux = position[b * 3] - position[a * 3];
|
|
263
|
-
const uy = position[b * 3 + 1] - position[a * 3 + 1];
|
|
264
|
-
const uz = position[b * 3 + 2] - position[a * 3 + 2];
|
|
265
|
-
|
|
266
|
-
const vx = position[c * 3] - position[a * 3];
|
|
267
|
-
const vy = position[c * 3 + 1] - position[a * 3 + 1];
|
|
268
|
-
const vz = position[c * 3 + 2] - position[a * 3 + 2];
|
|
269
|
-
|
|
270
|
-
return Math.hypot(uy * vz - uz * vy, uz * vx - ux * vz, ux * vy - uy * vx);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
268
|
/**
|
|
274
269
|
* @param {string} error
|
|
275
270
|
* @returns {ClothProxyBuildResult}
|
|
@@ -164,6 +164,13 @@ export class ClothColliderIndex {
|
|
|
164
164
|
* ignores it, so a distance in the shape's local frame is a distance in
|
|
165
165
|
* world space.
|
|
166
166
|
*
|
|
167
|
+
* A pose equal to the one the record already holds is not refit: its
|
|
168
|
+
* bounds were fit to exactly this pair of poses when either last changed —
|
|
169
|
+
* here, in {@link placePose}, or in {@link advance} — so the refit would
|
|
170
|
+
* write what is there. That is what a collider that never moves costs, and
|
|
171
|
+
* why nothing has to say it will not: 1.43 µs per collider per step
|
|
172
|
+
* refitting, 0.42 µs skipping, of which {@link advance} is 0.32.
|
|
173
|
+
*
|
|
167
174
|
* @param {number} handle
|
|
168
175
|
* @param {number} tx
|
|
169
176
|
* @param {number} ty
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothColliderIndex.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/ClothColliderIndex.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ClothColliderIndex.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/ClothColliderIndex.js"],"names":[],"mappings":"AAkDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH;IAEI;;;;;;OAMG;IACH,OAFU,YAAY,CAEM;IAE5B;;;;;OAKG;IACH,MAFU,UAAU,CAEK;IAEzB;;;;OAIG;IACH,OAFU,MAAM,CAEN;IAEV;;;;;;OAMG;IACH,eAFU,MAAM,CAEE;IAElB;;;;;;OAMG;IACH,qBAFU,MAAM,CAEQ;IAoFxB;;;;;;;;;;;OAWG;IACH,sCAPW,MAAM,aACN,MAAM,SACN,MAAM,QACN,MAAM,UACN,MAAM,GACJ,MAAM,CA8DlB;IAED;;;;;;;OAOG;IACH,eAHW,MAAM,GACJ,IAAI,CAkChB;IAED;;;;OAIG;IACH,eAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,mBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAFa,IAAI,CA4ChB;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,gBAVW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,IAAI,CAqBhB;IAsLD;;;;;;;;;;;;;;;OAeG;IACH,kBAVW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,GACJ,IAAI,CAqBhB;IAED;;;;;;;;OAQG;IACH,mBALW,MAAM,YACN,MAAM,aACN,MAAM,GACJ,IAAI,CAoBhB;IAED;;;;;OAKG;IACH,kBALW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,IAAI,CAWhB;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAdW,MAAM,EAAE,SACR,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,SACN,MAAM,QACN,MAAM,YACN,OAAO,GAGL,MAAM,CAWlB;IAED;;;;;;;;;;;OAWG;IACH,gBARW,MAAM,EAAE,OACR,MAAM,EAAE,GAAC,YAAY,GAAC,YAAY,cAClC,MAAM,SACN,MAAM,QACN,MAAM,WACN,OAAO,GACL,MAAM,CA6DlB;;CAyGJ"}
|