@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EntityComponentDataset } from "../../../ecs/EntityComponentDataset.js";
|
|
2
2
|
import { FluidComponent } from "../../fluid/ecs/FluidComponent.js";
|
|
3
3
|
import { fluid_build_world_to_grid } from "../../fluid/ecs/fluid_build_world_to_grid.js";
|
|
4
|
+
import { fluid_sample_velocity_world_mps } from "../../fluid/ecs/fluid_sample_velocity_world_mps.js";
|
|
4
5
|
import { CLOTH_DYNAMICS_BY_NAME } from "../ecs/cloth_dynamics_library.js";
|
|
5
6
|
import { cloth_bend_ratio, cloth_drag_response } from "../ecs/cloth_dynamics_map.js";
|
|
6
7
|
import { cloth_step } from "../solver/cloth_step.js";
|
|
@@ -389,14 +390,14 @@ function draw_field() {
|
|
|
389
390
|
continue;
|
|
390
391
|
}
|
|
391
392
|
|
|
392
|
-
|
|
393
|
+
// In metres a second, as `ClothFluidWind` reads it.
|
|
394
|
+
fluid_sample_velocity_world_mps(sample, 0, component, x, y, z);
|
|
393
395
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
const vz = sample[2] * cell_size;
|
|
396
|
+
const vx = sample[0];
|
|
397
|
+
const vy = sample[1];
|
|
398
|
+
const vz = sample[2];
|
|
398
399
|
|
|
399
|
-
const speed = Math.hypot(vx,
|
|
400
|
+
const speed = Math.hypot(vx, vy, vz);
|
|
400
401
|
|
|
401
402
|
if (speed < 1e-3) {
|
|
402
403
|
continue;
|
|
@@ -406,7 +407,7 @@ function draw_field() {
|
|
|
406
407
|
|
|
407
408
|
const depth = project(from, camera, x, y, z, width, height);
|
|
408
409
|
|
|
409
|
-
project(to, camera, x + vx * scale, y +
|
|
410
|
+
project(to, camera, x + vx * scale, y + vy * scale, z + vz * scale, width, height);
|
|
410
411
|
|
|
411
412
|
if (depth <= 0) {
|
|
412
413
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClothState.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/ClothState.js"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ClothState.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/ClothState.js"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { assert } from "../../../../core/assert.js";
|
|
2
|
+
import { csr_build_incidence } from "../../../../core/graph/csr/csr_build_incidence.js";
|
|
2
3
|
import { CCR_STRIDE } from "../collider/ClothColliderRecord.js";
|
|
3
4
|
import { cloth_color_order, cloth_color_particles } from "./cloth_color_particles.js";
|
|
5
|
+
import { cloth_particle_of_source } from "./cloth_particle_of_source.js";
|
|
4
6
|
import { CLOTH_COLLIDER_SLOTS } from "./cloth_solver_constants.js";
|
|
5
7
|
import { CLOTH_SELF_PAIRS_PER_PARTICLE } from "./cloth_self_find.js";
|
|
6
8
|
import { CLOTH_CONTACT_SLOTS } from "./constraint/cloth_contact_row.js";
|
|
@@ -787,9 +789,7 @@ export class ClothState {
|
|
|
787
789
|
// `order` maps permuted → source; the rows need source → permuted.
|
|
788
790
|
const particle_of_source = new Int32Array(particle_count);
|
|
789
791
|
|
|
790
|
-
|
|
791
|
-
particle_of_source[order[i]] = i;
|
|
792
|
-
}
|
|
792
|
+
cloth_particle_of_source(particle_of_source, order, particle_count);
|
|
793
793
|
|
|
794
794
|
const state = new ClothState();
|
|
795
795
|
|
|
@@ -852,9 +852,15 @@ export class ClothState {
|
|
|
852
852
|
state.bend_penalty[row] = stiffness < Infinity ? stiffness : 0;
|
|
853
853
|
}
|
|
854
854
|
|
|
855
|
-
|
|
855
|
+
// Grouping the flat particle table gives the flat index `row·2 + slot`,
|
|
856
|
+
// which is the packed `(row << 1) | slot` the stretch accumulation
|
|
857
|
+
// decodes, already in ascending row order within each particle — so the
|
|
858
|
+
// row tables are walked forwards during a sweep even though the
|
|
859
|
+
// particles are in colour order. The bend table below is the same with
|
|
860
|
+
// `(row << 2) | slot`.
|
|
861
|
+
csr_build_incidence(
|
|
856
862
|
state.stretch_adjacency_offset, state.stretch_adjacency,
|
|
857
|
-
state.stretch_particle, stretch_count
|
|
863
|
+
state.stretch_particle, stretch_count * 2, particle_count
|
|
858
864
|
);
|
|
859
865
|
|
|
860
866
|
for (let row = 0; row < leash_count; row++) {
|
|
@@ -877,12 +883,13 @@ export class ClothState {
|
|
|
877
883
|
: particle_of_source[leash_source[row]];
|
|
878
884
|
}
|
|
879
885
|
|
|
880
|
-
|
|
886
|
+
csr_build_incidence(
|
|
881
887
|
state.bend_adjacency_offset, state.bend_adjacency,
|
|
882
|
-
state.bend_particle, bend_count
|
|
888
|
+
state.bend_particle, bend_count * 4, particle_count
|
|
883
889
|
);
|
|
884
890
|
|
|
885
|
-
|
|
891
|
+
// A unary row kind's flat index is its row index: nothing to unpack.
|
|
892
|
+
csr_build_incidence(
|
|
886
893
|
state.leash_adjacency_offset, state.leash_adjacency,
|
|
887
894
|
state.leash_particle, leash_count, particle_count
|
|
888
895
|
);
|
|
@@ -904,7 +911,7 @@ export class ClothState {
|
|
|
904
911
|
state.backstop_plane[row * 6 + 4] = 1;
|
|
905
912
|
}
|
|
906
913
|
|
|
907
|
-
|
|
914
|
+
csr_build_incidence(
|
|
908
915
|
state.backstop_adjacency_offset, state.backstop_adjacency,
|
|
909
916
|
state.backstop_particle, backstop_count, particle_count
|
|
910
917
|
);
|
|
@@ -1215,70 +1222,3 @@ function allocate(
|
|
|
1215
1222
|
|
|
1216
1223
|
assert.equal(cursor, total, 'buffer cursor at end of allocation');
|
|
1217
1224
|
}
|
|
1218
|
-
|
|
1219
|
-
/**
|
|
1220
|
-
* The {@link build_adjacency} of a **unary** row kind: one particle per row, so
|
|
1221
|
-
* an entry is a bare row index rather than a packed `(row, slot)` pair and
|
|
1222
|
-
* there is nothing to shift.
|
|
1223
|
-
*
|
|
1224
|
-
* @param {Int32Array} offset out, `particle_count + 1`
|
|
1225
|
-
* @param {Int32Array} adjacency out, `row_count`
|
|
1226
|
-
* @param {Int32Array} row_particle particle index per row
|
|
1227
|
-
* @param {number} row_count
|
|
1228
|
-
* @param {number} particle_count
|
|
1229
|
-
* @private
|
|
1230
|
-
*/
|
|
1231
|
-
function build_unary_adjacency(offset, adjacency, row_particle, row_count, particle_count) {
|
|
1232
|
-
for (let row = 0; row < row_count; row++) {
|
|
1233
|
-
offset[row_particle[row] + 1]++;
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
for (let i = 0; i < particle_count; i++) {
|
|
1237
|
-
offset[i + 1] += offset[i];
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
|
-
const cursor = offset.slice(0, particle_count);
|
|
1241
|
-
|
|
1242
|
-
for (let row = 0; row < row_count; row++) {
|
|
1243
|
-
adjacency[cursor[row_particle[row]]++] = row;
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
/**
|
|
1248
|
-
* Counting sort of `(particle, row, slot)` incidences into CSR, with the slot
|
|
1249
|
-
* folded into the low bits of each entry so the accumulation loop reads one
|
|
1250
|
-
* word per row it touches.
|
|
1251
|
-
*
|
|
1252
|
-
* Entries within a particle come out in ascending row order, which keeps the
|
|
1253
|
-
* row tables walked forwards during a sweep even though the particles are in
|
|
1254
|
-
* colour order.
|
|
1255
|
-
*
|
|
1256
|
-
* @param {Int32Array} offset out, `particle_count + 1`
|
|
1257
|
-
* @param {Int32Array} adjacency out, `row_count * arity`
|
|
1258
|
-
* @param {Int32Array} row_particle particle indices, `arity` per row
|
|
1259
|
-
* @param {number} row_count
|
|
1260
|
-
* @param {number} arity 2 for stretch, 4 for bend
|
|
1261
|
-
* @param {number} particle_count
|
|
1262
|
-
* @private
|
|
1263
|
-
*/
|
|
1264
|
-
function build_adjacency(offset, adjacency, row_particle, row_count, arity, particle_count) {
|
|
1265
|
-
const shift = arity === 2 ? 1 : 2;
|
|
1266
|
-
|
|
1267
|
-
for (let i = 0; i < row_count * arity; i++) {
|
|
1268
|
-
offset[row_particle[i] + 1]++;
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
for (let i = 0; i < particle_count; i++) {
|
|
1272
|
-
offset[i + 1] += offset[i];
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
const cursor = offset.slice(0, particle_count);
|
|
1276
|
-
|
|
1277
|
-
for (let row = 0; row < row_count; row++) {
|
|
1278
|
-
for (let slot = 0; slot < arity; slot++) {
|
|
1279
|
-
const particle = row_particle[row * arity + slot];
|
|
1280
|
-
|
|
1281
|
-
adjacency[cursor[particle]++] = (row << shift) | slot;
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
@@ -19,17 +19,19 @@
|
|
|
19
19
|
* against 76 for its 14,802 tetrahedra — the same asymmetry, and the reason
|
|
20
20
|
* this design colours vertices rather than constraints.
|
|
21
21
|
*
|
|
22
|
-
* This runs **once**, at build time, on
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* This runs **once**, at build time, on the sorted CSR adjacency
|
|
23
|
+
* {@link cloth_particle_coupling} builds — the same edge set the
|
|
24
|
+
* self-collision exclusions are. The runtime never sees a graph:
|
|
25
|
+
* {@link ClothState} bakes the result into a permuted particle order plus a
|
|
26
|
+
* range per colour, so the sweep is a pair of nested counted loops over
|
|
27
|
+
* contiguous indices.
|
|
26
28
|
*
|
|
27
29
|
* The greedy colouriser is fed a largest-degree-first order (Welsh–Powell),
|
|
28
30
|
* which is the cheap heuristic that gets a regular triangulated sheet down to
|
|
29
|
-
* the 8–10 colours §5.4 predicts. The result is checked with
|
|
30
|
-
* {@link
|
|
31
|
-
* let two coupled particles race is caught in a dev build and compiles
|
|
32
|
-
* a shipped one.
|
|
31
|
+
* the 8–10 colours §5.4 predicts. The result is checked with
|
|
32
|
+
* {@link csr_graph_validate_coloring} behind `assert.*`, so a colouring that
|
|
33
|
+
* would let two coupled particles race is caught in a dev build and compiles
|
|
34
|
+
* out of a shipped one.
|
|
33
35
|
*
|
|
34
36
|
* @author Alex Goldring
|
|
35
37
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_color_particles.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_color_particles.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_color_particles.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_color_particles.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH;;;;;;;;;GASG;AACH,sDAPW,MAAM,oBACN,UAAU,GAAC,MAAM,EAAE,iBACnB,MAAM,iBACN,UAAU,GAAC,MAAM,EAAE,cACnB,MAAM,GACJ,WAAW,CA+BvB;AA8BD;;;;;;;;;;;;;GAaG;AACH,0CANW,WAAW,kBACX,MAAM,GACJ;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAC,CAuBhF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { assert } from "../../../../core/assert.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { csr_build_incidence } from "../../../../core/graph/csr/csr_build_incidence.js";
|
|
3
|
+
import { csr_graph_color_greedy } from "../../../../core/graph/csr/csr_graph_color_greedy.js";
|
|
4
|
+
import { csr_graph_validate_coloring } from "../../../../core/graph/csr/csr_graph_validate_coloring.js";
|
|
5
|
+
import { cloth_particle_coupling } from "./cloth_particle_coupling.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* # Particle-graph colouring for the cloth solver
|
|
@@ -24,17 +25,19 @@ import { Graph } from "../../../../core/graph/v2/Graph.js";
|
|
|
24
25
|
* against 76 for its 14,802 tetrahedra — the same asymmetry, and the reason
|
|
25
26
|
* this design colours vertices rather than constraints.
|
|
26
27
|
*
|
|
27
|
-
* This runs **once**, at build time, on
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* This runs **once**, at build time, on the sorted CSR adjacency
|
|
29
|
+
* {@link cloth_particle_coupling} builds — the same edge set the
|
|
30
|
+
* self-collision exclusions are. The runtime never sees a graph:
|
|
31
|
+
* {@link ClothState} bakes the result into a permuted particle order plus a
|
|
32
|
+
* range per colour, so the sweep is a pair of nested counted loops over
|
|
33
|
+
* contiguous indices.
|
|
31
34
|
*
|
|
32
35
|
* The greedy colouriser is fed a largest-degree-first order (Welsh–Powell),
|
|
33
36
|
* which is the cheap heuristic that gets a regular triangulated sheet down to
|
|
34
|
-
* the 8–10 colours §5.4 predicts. The result is checked with
|
|
35
|
-
* {@link
|
|
36
|
-
* let two coupled particles race is caught in a dev build and compiles
|
|
37
|
-
* a shipped one.
|
|
37
|
+
* the 8–10 colours §5.4 predicts. The result is checked with
|
|
38
|
+
* {@link csr_graph_validate_coloring} behind `assert.*`, so a colouring that
|
|
39
|
+
* would let two coupled particles race is caught in a dev build and compiles
|
|
40
|
+
* out of a shipped one.
|
|
38
41
|
*
|
|
39
42
|
* @author Alex Goldring
|
|
40
43
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -56,83 +59,25 @@ export function cloth_color_particles(
|
|
|
56
59
|
bend_particle, bend_count
|
|
57
60
|
) {
|
|
58
61
|
assert.isNonNegativeInteger(particle_count, 'particle_count');
|
|
59
|
-
assert.isNonNegativeInteger(stretch_count, 'stretch_count');
|
|
60
|
-
assert.isNonNegativeInteger(bend_count, 'bend_count');
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
return new Uint32Array(0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const graph = new Graph();
|
|
67
|
-
|
|
68
|
-
// Nodes are the particle indices themselves, inserted in order, so the
|
|
69
|
-
// colouriser's node array is the identity permutation and `colors[i]` is
|
|
70
|
-
// the colour of particle `i` without a second lookup.
|
|
71
|
-
for (let i = 0; i < particle_count; i++) {
|
|
72
|
-
graph.addNode(i);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// `Graph#hasEdge` is identity-based, so the same pair added twice becomes
|
|
76
|
-
// two edges and shows up twice in a neighbour list. A garment adds every
|
|
77
|
-
// hinge's shared edge once as a stretch row and again as a bend pair, so
|
|
78
|
-
// the duplicates are the common case rather than the exception; they cost
|
|
79
|
-
// the colouriser a linear `indexOf` each. Fold them here instead.
|
|
80
|
-
const seen = new Set();
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @param {number} a
|
|
84
|
-
* @param {number} b
|
|
85
|
-
*/
|
|
86
|
-
const couple = (a, b) => {
|
|
87
|
-
if (a === b) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const key = a < b ? a * particle_count + b : b * particle_count + a;
|
|
63
|
+
const colors = new Uint32Array(particle_count);
|
|
92
64
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
seen.add(key);
|
|
98
|
-
|
|
99
|
-
graph.createEdge(a, b);
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// A stretch row couples its two endpoints.
|
|
103
|
-
for (let row = 0; row < stretch_count; row++) {
|
|
104
|
-
const a = stretch_particle[row * 2];
|
|
105
|
-
const b = stretch_particle[row * 2 + 1];
|
|
106
|
-
|
|
107
|
-
assert.ok(a >= 0 && a < particle_count, `stretch row ${row} particle 0 (=${a}) out of range`);
|
|
108
|
-
assert.ok(b >= 0 && b < particle_count, `stretch row ${row} particle 1 (=${b}) out of range`);
|
|
109
|
-
|
|
110
|
-
couple(a, b);
|
|
65
|
+
if (particle_count === 0) {
|
|
66
|
+
return colors;
|
|
111
67
|
}
|
|
112
68
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
for (let i = 0; i < 4; i++) {
|
|
120
|
-
const a = bend_particle[base + i];
|
|
121
|
-
|
|
122
|
-
assert.ok(a >= 0 && a < particle_count, `bend row ${row} particle ${i} (=${a}) out of range`);
|
|
123
|
-
|
|
124
|
-
for (let j = i + 1; j < 4; j++) {
|
|
125
|
-
couple(a, bend_particle[base + j]);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
69
|
+
const { offset, partner } = cloth_particle_coupling(
|
|
70
|
+
particle_count,
|
|
71
|
+
stretch_particle, stretch_count,
|
|
72
|
+
bend_particle, bend_count
|
|
73
|
+
);
|
|
129
74
|
|
|
130
|
-
const order = order_by_descending_degree(
|
|
75
|
+
const order = order_by_descending_degree(offset, particle_count);
|
|
131
76
|
|
|
132
|
-
|
|
77
|
+
csr_graph_color_greedy(colors, offset, partner, order, particle_count);
|
|
133
78
|
|
|
134
79
|
assert.ok(
|
|
135
|
-
|
|
80
|
+
csr_graph_validate_coloring(colors, offset, partner, particle_count),
|
|
136
81
|
'cloth particle colouring is invalid — two coupled particles share a colour'
|
|
137
82
|
);
|
|
138
83
|
|
|
@@ -147,18 +92,13 @@ export function cloth_color_particles(
|
|
|
147
92
|
* Ties are broken by particle index so the ordering — and therefore the whole
|
|
148
93
|
* baked layout — is a deterministic function of the topology alone.
|
|
149
94
|
*
|
|
150
|
-
* @param {
|
|
95
|
+
* @param {Int32Array} offset CSR offsets of the deduplicated particle graph, so
|
|
96
|
+
* a row's length is the particle's degree
|
|
151
97
|
* @param {number} particle_count
|
|
152
98
|
* @returns {Uint32Array}
|
|
153
99
|
* @private
|
|
154
100
|
*/
|
|
155
|
-
function order_by_descending_degree(
|
|
156
|
-
const degree = new Int32Array(particle_count);
|
|
157
|
-
|
|
158
|
-
for (let i = 0; i < particle_count; i++) {
|
|
159
|
-
degree[i] = graph.getNeighbours(i).length;
|
|
160
|
-
}
|
|
161
|
-
|
|
101
|
+
function order_by_descending_degree(offset, particle_count) {
|
|
162
102
|
const order = new Uint32Array(particle_count);
|
|
163
103
|
|
|
164
104
|
for (let i = 0; i < particle_count; i++) {
|
|
@@ -167,7 +107,7 @@ function order_by_descending_degree(graph, particle_count) {
|
|
|
167
107
|
|
|
168
108
|
// `Array#sort` over a typed array is a numeric sort already; the comparator
|
|
169
109
|
// is here for the tie-break, not for the ordering of the degrees.
|
|
170
|
-
order.sort((a, b) => (
|
|
110
|
+
order.sort((a, b) => ((offset[b + 1] - offset[b]) - (offset[a + 1] - offset[a])) || (a - b));
|
|
171
111
|
|
|
172
112
|
return order;
|
|
173
113
|
}
|
|
@@ -200,21 +140,9 @@ export function cloth_color_order(colors, particle_count) {
|
|
|
200
140
|
}
|
|
201
141
|
|
|
202
142
|
const colour_offset = new Int32Array(colour_count + 1);
|
|
203
|
-
|
|
204
|
-
for (let i = 0; i < particle_count; i++) {
|
|
205
|
-
colour_offset[colors[i] + 1]++;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
for (let c = 0; c < colour_count; c++) {
|
|
209
|
-
colour_offset[c + 1] += colour_offset[c];
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const cursor = colour_offset.slice(0, colour_count);
|
|
213
143
|
const order = new Int32Array(particle_count);
|
|
214
144
|
|
|
215
|
-
|
|
216
|
-
order[cursor[colors[i]]++] = i;
|
|
217
|
-
}
|
|
145
|
+
csr_build_incidence(colour_offset, order, colors, particle_count, colour_count);
|
|
218
146
|
|
|
219
147
|
return { colour_count, colour_offset, order };
|
|
220
148
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_contact_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_contact_find.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_contact_find.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_contact_find.js"],"names":[],"mappings":"AAiHA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,6DAbW,YAAY,GAAC,YAAY,QACzB,UAAU,SACV,MAAM,MACN,MAAM,oBAGN,MAAM,GAKJ,MAAM,CAwLlB;AAvSD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AAEH;;;;;;;;;GASG;AACH,mCAFU,MAAM,CAEsB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { v3_length } from "../../../../core/geom/vec3/v3_length.js";
|
|
1
2
|
import {
|
|
2
3
|
CCR_AABB_MAX_X,
|
|
3
4
|
CCR_AABB_MAX_Y,
|
|
@@ -172,7 +173,7 @@ export function cloth_contact_find(state, table, keys, count, dt, kinematic_trav
|
|
|
172
173
|
for (let record = 0; record < count; record++) {
|
|
173
174
|
const r = record * CCR_STRIDE;
|
|
174
175
|
|
|
175
|
-
TRAVEL[record] =
|
|
176
|
+
TRAVEL[record] = v3_length(
|
|
176
177
|
table[r + CCR_TX] - table[r + CCR_PREV_TX],
|
|
177
178
|
table[r + CCR_TY] - table[r + CCR_PREV_TY],
|
|
178
179
|
table[r + CCR_TZ] - table[r + CCR_PREV_TZ]
|
|
@@ -218,7 +219,7 @@ export function cloth_contact_find(state, table, keys, count, dt, kinematic_trav
|
|
|
218
219
|
// How far this particle carries its current velocity across the step.
|
|
219
220
|
// Hoisted out of the record loop: it is a property of the particle, and
|
|
220
221
|
// the loop below is the hot one.
|
|
221
|
-
const travel = dt *
|
|
222
|
+
const travel = dt * v3_length(velocity[p], velocity[p + 1], velocity[p + 2]) + kinematic_travel;
|
|
222
223
|
|
|
223
224
|
let found = 0;
|
|
224
225
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_hold_line.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_hold_line.js"],"names":[],"mappings":"AAyGA;;;;;;;;;;;;;;GAcG;AACH,0CAPW,YAAY,YACZ,YAAY,QACZ,UAAU,cACV,MAAM,GACJ,OAAO,CAiGnB;AAED;;;;;;;;;;GAUG;AACH,8DANW,YAAY,qBACZ,MAAM,kBACN,YAAY,GAAC,YAAY,GAAC,IAAI,GAE5B,MAAM,
|
|
1
|
+
{"version":3,"file":"cloth_hold_line.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_hold_line.js"],"names":[],"mappings":"AAyGA;;;;;;;;;;;;;;GAcG;AACH,0CAPW,YAAY,YACZ,YAAY,QACZ,UAAU,cACV,MAAM,GACJ,OAAO,CAiGnB;AAED;;;;;;;;;;GAUG;AACH,8DANW,YAAY,qBACZ,MAAM,kBACN,YAAY,GAAC,YAAY,GAAC,IAAI,GAE5B,MAAM,CAqHlB;AArUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAEH;;;;;;;;;;;;;GAaG;AACH,wCAFU,MAAM,CAEkC;AAElD;;;GAGG;AACH,oCAFU,MAAM,CAEuB"}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
CVA_H_YZ,
|
|
13
13
|
CVA_H_ZZ,
|
|
14
14
|
CVA_STRIDE,
|
|
15
|
-
|
|
15
|
+
cloth_vertex_accumulator_seed
|
|
16
16
|
} from "./cloth_vertex_accumulator.js";
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -268,19 +268,7 @@ export function cloth_hold_line_turn(state, line, inverse_h_squared, collider_ta
|
|
|
268
268
|
|
|
269
269
|
// The vertex update's assembly, seeded the same way, with only the rows
|
|
270
270
|
// the turn can see.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
accumulator[CVA_F_X] = -mass_over_h_squared * (x - inertial[p]);
|
|
274
|
-
accumulator[CVA_F_Y] = -mass_over_h_squared * (y - inertial[p + 1]);
|
|
275
|
-
accumulator[CVA_F_Z] = -mass_over_h_squared * (z - inertial[p + 2]);
|
|
276
|
-
|
|
277
|
-
accumulator[CVA_H_XX] = mass_over_h_squared;
|
|
278
|
-
accumulator[CVA_H_YY] = mass_over_h_squared;
|
|
279
|
-
accumulator[CVA_H_ZZ] = mass_over_h_squared;
|
|
280
|
-
accumulator[CVA_H_XY] = 0;
|
|
281
|
-
accumulator[CVA_H_XZ] = 0;
|
|
282
|
-
accumulator[CVA_H_YZ] = 0;
|
|
283
|
-
accumulator[CVA_TRUST] = Infinity;
|
|
271
|
+
cloth_vertex_accumulator_seed(accumulator, position, inertial, p, inverse_h_squared / inverse_mass);
|
|
284
272
|
|
|
285
273
|
cloth_leash_accumulate(accumulator, state, i);
|
|
286
274
|
cloth_backstop_accumulate(accumulator, state, i);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Total kinetic energy of a cloth's free particles, `Σ ½·|v|²/w` over every
|
|
3
|
+
* particle with a non-zero inverse mass `w`, in joules.
|
|
4
|
+
*
|
|
5
|
+
* A held particle (`w = 0`) is skipped rather than treated as infinitely heavy:
|
|
6
|
+
* its velocity is whatever its holder gave it, and a cloth hanging still from a
|
|
7
|
+
* moving hand has come to rest in every sense §7 P5 means. A cloth that has
|
|
8
|
+
* settled reads zero and a cloth that is ringing does not, which is why the
|
|
9
|
+
* measurements read this rather than a displacement threshold.
|
|
10
|
+
*
|
|
11
|
+
* A diagnostic for specs, measurements and the playgrounds; nothing in the
|
|
12
|
+
* step reads it.
|
|
13
|
+
*
|
|
14
|
+
* @param {ClothState} state
|
|
15
|
+
* @returns {number} joules
|
|
16
|
+
*
|
|
17
|
+
* @author Alex Goldring
|
|
18
|
+
* @copyright Company Named Limited (c) 2026
|
|
19
|
+
*/
|
|
20
|
+
export function cloth_kinetic_energy(state: ClothState): number;
|
|
21
|
+
//# sourceMappingURL=cloth_kinetic_energy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_kinetic_energy.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_kinetic_energy.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,yDALa,MAAM,CA8BlB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Total kinetic energy of a cloth's free particles, `Σ ½·|v|²/w` over every
|
|
3
|
+
* particle with a non-zero inverse mass `w`, in joules.
|
|
4
|
+
*
|
|
5
|
+
* A held particle (`w = 0`) is skipped rather than treated as infinitely heavy:
|
|
6
|
+
* its velocity is whatever its holder gave it, and a cloth hanging still from a
|
|
7
|
+
* moving hand has come to rest in every sense §7 P5 means. A cloth that has
|
|
8
|
+
* settled reads zero and a cloth that is ringing does not, which is why the
|
|
9
|
+
* measurements read this rather than a displacement threshold.
|
|
10
|
+
*
|
|
11
|
+
* A diagnostic for specs, measurements and the playgrounds; nothing in the
|
|
12
|
+
* step reads it.
|
|
13
|
+
*
|
|
14
|
+
* @param {ClothState} state
|
|
15
|
+
* @returns {number} joules
|
|
16
|
+
*
|
|
17
|
+
* @author Alex Goldring
|
|
18
|
+
* @copyright Company Named Limited (c) 2026
|
|
19
|
+
*/
|
|
20
|
+
export function cloth_kinetic_energy(state) {
|
|
21
|
+
const particle_count = state.particle_count;
|
|
22
|
+
|
|
23
|
+
const mass_inverse = state.mass_inverse;
|
|
24
|
+
const velocity = state.velocity;
|
|
25
|
+
|
|
26
|
+
let energy = 0;
|
|
27
|
+
|
|
28
|
+
for (let i = 0; i < particle_count; i++) {
|
|
29
|
+
const w = mass_inverse[i];
|
|
30
|
+
|
|
31
|
+
if (w === 0) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const p = i * 3;
|
|
36
|
+
|
|
37
|
+
const vx = velocity[p];
|
|
38
|
+
const vy = velocity[p + 1];
|
|
39
|
+
const vz = velocity[p + 2];
|
|
40
|
+
|
|
41
|
+
energy += 0.5 * (vx * vx + vy * vy + vz * vz) / w;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return energy;
|
|
45
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The particle graph a cloth's rows imply: an edge between every two particles
|
|
3
|
+
* that share a row, as a sorted CSR adjacency.
|
|
4
|
+
*
|
|
5
|
+
* A stretch row couples its two endpoints; a bend stencil couples all six pairs
|
|
6
|
+
* of its four particles, since every one of them appears in the same row. Two
|
|
7
|
+
* build-time consumers want exactly this set — the colouring, where an edge is
|
|
8
|
+
* a pair that must not be updated at once (`cloth_color_particles.js`), and the
|
|
9
|
+
* self-collision exclusions, where it is a pair a row already governs
|
|
10
|
+
* (`cloth_self_find.js`) — and this is the one place it is built.
|
|
11
|
+
*
|
|
12
|
+
* The set is deduplicated, because a garment adds every hinge's shared edge
|
|
13
|
+
* once as a stretch row and again as a bend pair, so duplicates are the common
|
|
14
|
+
* case; and a row that names one particle twice couples nothing. Each particle's
|
|
15
|
+
* partners come out ascending, which is the contract the exclusion scans read.
|
|
16
|
+
*
|
|
17
|
+
* Build-time only: it allocates its result and a scratch the size of the
|
|
18
|
+
* half-edge list.
|
|
19
|
+
*
|
|
20
|
+
* @param {number} particle_count
|
|
21
|
+
* @param {Int32Array|number[]} stretch_particle particle index pairs, 2 per row
|
|
22
|
+
* @param {number} stretch_count
|
|
23
|
+
* @param {Int32Array|number[]} bend_particle particle index quads, 4 per row
|
|
24
|
+
* @param {number} bend_count
|
|
25
|
+
* @returns {{offset: Int32Array, partner: Int32Array}} `partner[offset[i] .. offset[i + 1])` are the
|
|
26
|
+
* particles sharing a row with `i`, ascending, without `i` itself
|
|
27
|
+
*/
|
|
28
|
+
export function cloth_particle_coupling(particle_count: number, stretch_particle: Int32Array | number[], stretch_count: number, bend_particle: Int32Array | number[], bend_count: number): {
|
|
29
|
+
offset: Int32Array;
|
|
30
|
+
partner: Int32Array;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=cloth_particle_coupling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloth_particle_coupling.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/solver/cloth_particle_coupling.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wDARW,MAAM,oBACN,UAAU,GAAC,MAAM,EAAE,iBACnB,MAAM,iBACN,UAAU,GAAC,MAAM,EAAE,cACnB,MAAM,GACJ;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAC,CAyGrD"}
|