@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,8 +1,15 @@
|
|
|
1
1
|
import { assert } from "../../../../core/assert.js";
|
|
2
2
|
import { BVH, NULL_NODE } from "../../../../core/bvh2/bvh3/BVH.js";
|
|
3
|
+
import { number_compare_ascending } from "../../../../core/primitives/numbers/number_compare_ascending.js";
|
|
3
4
|
import {
|
|
4
5
|
bvh_query_user_data_intersects_aabb
|
|
5
6
|
} from "../../../../core/bvh2/bvh3/query/bvh_query_user_data_intersects_aabb.js";
|
|
7
|
+
import { array_copy } from "../../../../core/collection/array/array_copy.js";
|
|
8
|
+
import { array_range_equal_strict } from "../../../../core/collection/array/array_range_equal_strict.js";
|
|
9
|
+
import { array_remove_first } from "../../../../core/collection/array/array_remove_first.js";
|
|
10
|
+
import { array_sort_insertion_ascending } from "../../../../core/collection/array/array_sort_insertion_ascending.js";
|
|
11
|
+
import { aabb3_array_round_outward_f32 } from "../../../../core/geom/3d/aabb/aabb3_array_round_outward_f32.js";
|
|
12
|
+
import { FAT_LINEAR } from "../../broadphase/compute_fat_world_aabb.js";
|
|
6
13
|
import {
|
|
7
14
|
CCR_AABB_MAX_X,
|
|
8
15
|
CCR_AABB_MAX_Y,
|
|
@@ -341,11 +348,9 @@ export class ClothColliderIndex {
|
|
|
341
348
|
const node = this.#node[handle];
|
|
342
349
|
|
|
343
350
|
if (node === NULL_NODE) {
|
|
344
|
-
const
|
|
351
|
+
const planes = this.#planes;
|
|
345
352
|
|
|
346
|
-
|
|
347
|
-
this.#planes.splice(at, 1);
|
|
348
|
-
}
|
|
353
|
+
array_remove_first(planes, handle, 0, planes.length);
|
|
349
354
|
} else {
|
|
350
355
|
this.#bvh.remove_leaf(node);
|
|
351
356
|
this.#bvh.release_node(node);
|
|
@@ -419,22 +424,11 @@ export class ClothColliderIndex {
|
|
|
419
424
|
this.max_inflation = table[r + CCR_INFLATION];
|
|
420
425
|
}
|
|
421
426
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|| table[r + CCR_PREV_QX] !== table[r + CCR_QX]
|
|
426
|
-
|| table[r + CCR_PREV_QY] !== table[r + CCR_QY]
|
|
427
|
-
|| table[r + CCR_PREV_QZ] !== table[r + CCR_QZ]
|
|
428
|
-
|| table[r + CCR_PREV_QW] !== table[r + CCR_QW];
|
|
429
|
-
|
|
430
|
-
table[r + CCR_PREV_TX] = table[r + CCR_TX];
|
|
431
|
-
table[r + CCR_PREV_TY] = table[r + CCR_TY];
|
|
432
|
-
table[r + CCR_PREV_TZ] = table[r + CCR_TZ];
|
|
427
|
+
// A pose is seven contiguous slots, translation then rotation, in
|
|
428
|
+
// both the current and the previous half of the record.
|
|
429
|
+
const moved = !array_range_equal_strict(table, r + CCR_PREV_TX, table, r + CCR_TX, POSE_SLOTS);
|
|
433
430
|
|
|
434
|
-
table
|
|
435
|
-
table[r + CCR_PREV_QY] = table[r + CCR_QY];
|
|
436
|
-
table[r + CCR_PREV_QZ] = table[r + CCR_QZ];
|
|
437
|
-
table[r + CCR_PREV_QW] = table[r + CCR_QW];
|
|
431
|
+
array_copy(table, r + CCR_TX, table, r + CCR_PREV_TX, POSE_SLOTS);
|
|
438
432
|
|
|
439
433
|
if (moved) {
|
|
440
434
|
cloth_collider_refit_bounds(table, handle, CCR_STRIDE);
|
|
@@ -451,6 +445,13 @@ export class ClothColliderIndex {
|
|
|
451
445
|
* ignores it, so a distance in the shape's local frame is a distance in
|
|
452
446
|
* world space.
|
|
453
447
|
*
|
|
448
|
+
* A pose equal to the one the record already holds is not refit: its
|
|
449
|
+
* bounds were fit to exactly this pair of poses when either last changed —
|
|
450
|
+
* here, in {@link placePose}, or in {@link advance} — so the refit would
|
|
451
|
+
* write what is there. That is what a collider that never moves costs, and
|
|
452
|
+
* why nothing has to say it will not: 1.43 µs per collider per step
|
|
453
|
+
* refitting, 0.42 µs skipping, of which {@link advance} is 0.32.
|
|
454
|
+
*
|
|
454
455
|
* @param {number} handle
|
|
455
456
|
* @param {number} tx
|
|
456
457
|
* @param {number} ty
|
|
@@ -471,6 +472,35 @@ export class ClothColliderIndex {
|
|
|
471
472
|
|
|
472
473
|
const r = handle * CCR_STRIDE;
|
|
473
474
|
|
|
475
|
+
if (table[r + CCR_TX] === tx && table[r + CCR_TY] === ty && table[r + CCR_TZ] === tz
|
|
476
|
+
&& table[r + CCR_QX] === qx && table[r + CCR_QY] === qy
|
|
477
|
+
&& table[r + CCR_QZ] === qz && table[r + CCR_QW] === qw
|
|
478
|
+
// no leaf — never posed, or a plane, which is never in the tree — refits regardless
|
|
479
|
+
&& this.#node[handle] !== NULL_NODE) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
this.#pose(handle, tx, ty, tz, qx, qy, qz, qw);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Write the current pose and refit, unconditionally.
|
|
488
|
+
*
|
|
489
|
+
* @param {number} handle
|
|
490
|
+
* @param {number} tx
|
|
491
|
+
* @param {number} ty
|
|
492
|
+
* @param {number} tz
|
|
493
|
+
* @param {number} qx
|
|
494
|
+
* @param {number} qy
|
|
495
|
+
* @param {number} qz
|
|
496
|
+
* @param {number} qw
|
|
497
|
+
* @private
|
|
498
|
+
*/
|
|
499
|
+
#pose(handle, tx, ty, tz, qx, qy, qz, qw) {
|
|
500
|
+
const table = this.table;
|
|
501
|
+
|
|
502
|
+
const r = handle * CCR_STRIDE;
|
|
503
|
+
|
|
474
504
|
if (table[r + CCR_TX] !== tx || table[r + CCR_TY] !== ty || table[r + CCR_TZ] !== tz
|
|
475
505
|
|| table[r + CCR_QX] !== qx || table[r + CCR_QY] !== qy
|
|
476
506
|
|| table[r + CCR_QZ] !== qz || table[r + CCR_QW] !== qw) {
|
|
@@ -561,9 +591,15 @@ export class ClothColliderIndex {
|
|
|
561
591
|
if (lower < STORED_AABB[axis] || upper > STORED_AABB[axis + 3]) contained = false;
|
|
562
592
|
// A one-step outlier must not leave a scene-sized leaf behind once
|
|
563
593
|
// motion stops. Allow ordinary jitter to keep spending the slack.
|
|
594
|
+
// The yardstick is twice what a store would write now: the slack
|
|
595
|
+
// on both sides plus the outward rounding, which grows each side by
|
|
596
|
+
// under one float32 step of its magnitude. Without that term a leaf
|
|
597
|
+
// far enough out that a step outgrows the slack — past about four
|
|
598
|
+
// hundred kilometres — would read as oversized straight after being
|
|
599
|
+
// stored, and be re-homed every step.
|
|
564
600
|
if (STORED_AABB[axis + 3] - STORED_AABB[axis]
|
|
565
|
-
> 2 * (upper - lower + 2 *
|
|
566
|
-
+ (Math.abs(lower) + Math.abs(upper)) *
|
|
601
|
+
> 2 * (upper - lower + 2 * FAT_LINEAR
|
|
602
|
+
+ (Math.abs(lower) + Math.abs(upper) + 2 * FAT_LINEAR) * FLOAT32_STEP)) oversized = true;
|
|
567
603
|
}
|
|
568
604
|
|
|
569
605
|
if (contained && !oversized) {
|
|
@@ -589,18 +625,18 @@ export class ClothColliderIndex {
|
|
|
589
625
|
* Write a record's swept bounds plus its contact reach into {@link FAT_AABB}
|
|
590
626
|
* with the slack the refit skip spends, and store them on the leaf.
|
|
591
627
|
*
|
|
592
|
-
* The slack
|
|
593
|
-
* `Float64` world
|
|
594
|
-
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
598
|
-
* past
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
628
|
+
* The slack covers jitter; it does not cover the tree's `Float32` nodes
|
|
629
|
+
* holding a `Float64` world. {@link BVH#node_set_aabb} rounds each bound to
|
|
630
|
+
* the nearest `Float32`, and `Float32`'s step is a *proportion* of the
|
|
631
|
+
* magnitude — a millimetre at ten kilometres out, but **a whole metre at
|
|
632
|
+
* ten thousand**, which is well past any constant: measured, a leaf there
|
|
633
|
+
* fattened by 5 cm came back 45 cm inside its own record. A bound that
|
|
634
|
+
* rounds inward past its slack is a leaf smaller than the record it stands
|
|
635
|
+
* for, and that is a collider the tree stops answering with — silently,
|
|
636
|
+
* and only far from the origin, which is the worst shape a bug can have.
|
|
637
|
+
* So the fattened box is rounded outward to `Float32` before it is stored,
|
|
638
|
+
* which makes the store exact at every scale and leaves the constant to do
|
|
639
|
+
* only its own job.
|
|
604
640
|
*
|
|
605
641
|
* The exact test in {@link query} reads the `Float64` record, so the tree
|
|
606
642
|
* only ever has to avoid a false **negative**; being generous here costs a
|
|
@@ -618,10 +654,12 @@ export class ClothColliderIndex {
|
|
|
618
654
|
const lower = table[r + CCR_AABB_MIN_X + axis] - reach;
|
|
619
655
|
const upper = table[r + CCR_AABB_MAX_X + axis] + reach;
|
|
620
656
|
|
|
621
|
-
FAT_AABB[axis] = lower -
|
|
622
|
-
FAT_AABB[axis + 3] = upper +
|
|
657
|
+
FAT_AABB[axis] = lower - FAT_LINEAR;
|
|
658
|
+
FAT_AABB[axis + 3] = upper + FAT_LINEAR;
|
|
623
659
|
}
|
|
624
660
|
|
|
661
|
+
aabb3_array_round_outward_f32(FAT_AABB, 0, FAT_AABB, 0);
|
|
662
|
+
|
|
625
663
|
this.#bvh.node_set_aabb(node, FAT_AABB);
|
|
626
664
|
}
|
|
627
665
|
|
|
@@ -657,7 +695,9 @@ export class ClothColliderIndex {
|
|
|
657
695
|
this.table[r + CCR_PREV_QZ] = qz;
|
|
658
696
|
this.table[r + CCR_PREV_QW] = qw;
|
|
659
697
|
|
|
660
|
-
|
|
698
|
+
// Not {@link setPose}: the previous pose has just changed, so the
|
|
699
|
+
// bounds are stale even when the current one has not.
|
|
700
|
+
this.#pose(handle, tx, ty, tz, qx, qy, qz, qw);
|
|
661
701
|
}
|
|
662
702
|
|
|
663
703
|
/**
|
|
@@ -926,21 +966,19 @@ export class ClothColliderIndex {
|
|
|
926
966
|
}
|
|
927
967
|
|
|
928
968
|
/**
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
*
|
|
969
|
+
* One `Float32` step as a proportion of a value's magnitude, an upper bound
|
|
970
|
+
* for every normal `Float32`: 23 fraction bits, so a step is at most `2^-23`
|
|
971
|
+
* of the magnitude. The most an outward rounding can widen a bound by.
|
|
932
972
|
* @type {number}
|
|
933
973
|
*/
|
|
934
|
-
const
|
|
974
|
+
const FLOAT32_STEP = 2 ** -23;
|
|
935
975
|
|
|
936
976
|
/**
|
|
937
|
-
*
|
|
938
|
-
*
|
|
939
|
-
* rounding does. `Float32` carries 23 fraction bits, so one ulp is `2^-23` of
|
|
940
|
-
* the magnitude and two is the first multiple that is unconditionally outside.
|
|
977
|
+
* Slots in one pose, `[tx, ty, tz, qx, qy, qz, qw]`: {@link CCR_TX} to {@link CCR_QW}, and the same
|
|
978
|
+
* from {@link CCR_PREV_TX}.
|
|
941
979
|
* @type {number}
|
|
942
980
|
*/
|
|
943
|
-
const
|
|
981
|
+
const POSE_SLOTS = 7;
|
|
944
982
|
|
|
945
983
|
/**
|
|
946
984
|
* The box being queried, `[min_x, min_y, min_z, max_x, max_y, max_z]`: what the tree is walked with
|
|
@@ -972,23 +1010,12 @@ function sort_handles(handles) {
|
|
|
972
1010
|
const n = handles.length;
|
|
973
1011
|
|
|
974
1012
|
if (n > INSERTION_SORT_LIMIT) {
|
|
975
|
-
handles.sort(
|
|
1013
|
+
handles.sort(number_compare_ascending);
|
|
976
1014
|
|
|
977
1015
|
return;
|
|
978
1016
|
}
|
|
979
1017
|
|
|
980
|
-
|
|
981
|
-
const handle = handles[i];
|
|
982
|
-
|
|
983
|
-
let j = i - 1;
|
|
984
|
-
|
|
985
|
-
while (j >= 0 && handles[j] > handle) {
|
|
986
|
-
handles[j + 1] = handles[j];
|
|
987
|
-
j--;
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
handles[j + 1] = handle;
|
|
991
|
-
}
|
|
1018
|
+
array_sort_insertion_ascending(handles, 0, n);
|
|
992
1019
|
}
|
|
993
1020
|
|
|
994
1021
|
/**
|
|
@@ -1002,12 +1029,3 @@ const FAT_AABB = new Float64Array(6);
|
|
|
1002
1029
|
* @type {Float32Array}
|
|
1003
1030
|
*/
|
|
1004
1031
|
const STORED_AABB = new Float32Array(6);
|
|
1005
|
-
|
|
1006
|
-
/**
|
|
1007
|
-
* @param {number} a
|
|
1008
|
-
* @param {number} b
|
|
1009
|
-
* @returns {number}
|
|
1010
|
-
*/
|
|
1011
|
-
function ASCENDING(a, b) {
|
|
1012
|
-
return a - b;
|
|
1013
|
-
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_collider_bounds.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_bounds.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_collider_bounds.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_bounds.js"],"names":[],"mappings":"AAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,oDAJW,MAAM,eACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,mDALW,YAAY,GAAC,YAAY,UACzB,MAAM,UACN,MAAM,GACJ,IAAI,CA2BhB"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
m4_from_rotation_translation_scale_array
|
|
4
|
-
} from "../../../../core/geom/3d/mat4/m4_from_rotation_translation_scale_array.js";
|
|
1
|
+
import { aabb3_transform_oriented_array } from "../../../../core/geom/3d/aabb/aabb3_transform_oriented.js";
|
|
5
2
|
import { v3_quaternion_apply_array } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
3
|
+
import { max2_exact } from "../../../../core/math/max2_exact.js";
|
|
4
|
+
import { min2_exact } from "../../../../core/math/min2_exact.js";
|
|
6
5
|
import { ClothColliderKind } from "./ClothColliderKind.js";
|
|
7
6
|
import {
|
|
8
7
|
CCR_AABB_MAX_X,
|
|
9
8
|
CCR_AABB_MIN_X,
|
|
10
9
|
CCR_KIND,
|
|
11
10
|
CCR_PARAM_0,
|
|
12
|
-
CCR_PARAM_1,
|
|
13
|
-
CCR_PARAM_2,
|
|
14
11
|
CCR_PARAM_3,
|
|
15
12
|
CCR_PREV_QX,
|
|
16
13
|
CCR_PREV_TX,
|
|
@@ -87,91 +84,25 @@ export function cloth_collider_refit_bounds(table, record, stride) {
|
|
|
87
84
|
|
|
88
85
|
cloth_collider_local_bounds(LOCAL_BOUNDS, table, record, stride);
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
// Each pose is seven contiguous slots, translation then rotation, which is
|
|
88
|
+
// the layout the transform reads — so it reads them where they sit in the
|
|
89
|
+
// table rather than as numbers handed through a call, each of which would
|
|
90
|
+
// be boxed into a heap object wherever the call is not inlined.
|
|
91
|
+
aabb3_transform_oriented_array(CURRENT_BOUNDS, 0, LOCAL_BOUNDS, 0, table, r + CCR_TX);
|
|
92
|
+
aabb3_transform_oriented_array(PREVIOUS_BOUNDS, 0, LOCAL_BOUNDS, 0, table, r + CCR_PREV_TX);
|
|
92
93
|
|
|
94
|
+
// Not `aabb3_array_combine`: its `min2` / `max2` drop a NaN in their first
|
|
95
|
+
// operand, so a NaN pose would leave the other pose's bound depending on
|
|
96
|
+
// which side it was on. The refit keeps `Math.min`'s answer instead.
|
|
93
97
|
for (let axis = 0; axis < 3; axis++) {
|
|
94
|
-
table[r + CCR_AABB_MIN_X + axis] =
|
|
95
|
-
table[r + CCR_AABB_MAX_X + axis] =
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* `Math.min(a, b)` without the call: the smaller, NaN if either is, and `-0` below `+0`. The refit
|
|
101
|
-
* runs a few times a cloth a step, so V8 is slow to optimise it, and until it does `Math.min` is a
|
|
102
|
-
* call into a builtin that hands its answer back boxed into a heap object.
|
|
103
|
-
*
|
|
104
|
-
* The same as `Math.min` under `Object.is` for every pair of numbers. A NaN answer is the canonical
|
|
105
|
-
* NaN; which NaN `Math.min` answers is the platform's (on x64, the one with the sign bit set).
|
|
106
|
-
*
|
|
107
|
-
* @param {number} a
|
|
108
|
-
* @param {number} b
|
|
109
|
-
* @returns {number}
|
|
110
|
-
* @private
|
|
111
|
-
*/
|
|
112
|
-
function min_exact(a, b) {
|
|
113
|
-
if (a < b) {
|
|
114
|
-
return a;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (b < a) {
|
|
118
|
-
return b;
|
|
98
|
+
table[r + CCR_AABB_MIN_X + axis] = min2_exact(CURRENT_BOUNDS[axis], PREVIOUS_BOUNDS[axis]);
|
|
99
|
+
table[r + CCR_AABB_MAX_X + axis] = max2_exact(CURRENT_BOUNDS[axis + 3], PREVIOUS_BOUNDS[axis + 3]);
|
|
119
100
|
}
|
|
120
|
-
|
|
121
|
-
if (a === b) {
|
|
122
|
-
// equal, and of two zeros the negative one if either is
|
|
123
|
-
return a === 0 && 1 / a > 0 ? b : a;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// one of them is NaN
|
|
127
|
-
return NaN;
|
|
128
101
|
}
|
|
129
102
|
|
|
130
103
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* @param {number} a
|
|
135
|
-
* @param {number} b
|
|
136
|
-
* @returns {number}
|
|
137
|
-
* @private
|
|
138
|
-
*/
|
|
139
|
-
function max_exact(a, b) {
|
|
140
|
-
if (a > b) {
|
|
141
|
-
return a;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
if (b > a) {
|
|
145
|
-
return b;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (a === b) {
|
|
149
|
-
// equal, and of two zeros the positive one if either is
|
|
150
|
-
return a === 0 && 1 / a < 0 ? b : a;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return NaN;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* @param {Float64Array} out
|
|
158
|
-
* @param {Float32Array|Float64Array} table
|
|
159
|
-
* @param {number} rotation slot of the pose's rotation
|
|
160
|
-
* @param {number} translation slot of the pose's translation
|
|
161
|
-
* @private
|
|
162
|
-
*/
|
|
163
|
-
function project(out, table, rotation, translation) {
|
|
164
|
-
// The pose is read where it sits in the table. Handed to the compose as ten numbers, the seven
|
|
165
|
-
// that are not small integers were each boxed into a heap object wherever the call was not
|
|
166
|
-
// inlined.
|
|
167
|
-
m4_from_rotation_translation_scale_array(POSE, table, rotation, table, translation, UNIT_SCALE, 0);
|
|
168
|
-
|
|
169
|
-
aabb3_matrix4_project(out, LOCAL_BOUNDS, POSE);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* A half-space's bounds, which cannot go through {@link aabb3_matrix4_project}
|
|
174
|
-
* — an infinite extent multiplied by a zero matrix element is `NaN`. The
|
|
104
|
+
* A half-space's bounds, which cannot go through {@link aabb3_transform_oriented_array}
|
|
105
|
+
* — an infinite extent multiplied by a zero rotation element is `NaN`. The
|
|
175
106
|
* plane's world normal is its local normal rotated by the pose, and the bound
|
|
176
107
|
* exists on an axis exactly when that normal is aligned with it.
|
|
177
108
|
*
|
|
@@ -190,7 +121,7 @@ function refit_plane(table, r) {
|
|
|
190
121
|
const rotation = r + PLANE_POSES[p];
|
|
191
122
|
const translation = r + PLANE_POSES[p + 1];
|
|
192
123
|
|
|
193
|
-
// the local normal and the rotation straight from the table, as
|
|
124
|
+
// the local normal and the rotation straight from the table, as for the other kinds
|
|
194
125
|
v3_quaternion_apply_array(PLANE_NORMAL, 0, table, r + CCR_PARAM_0, table, rotation);
|
|
195
126
|
|
|
196
127
|
// The boundary plane passes through `R·(offset·n_local) + t`, so its
|
|
@@ -208,9 +139,9 @@ function refit_plane(table, r) {
|
|
|
208
139
|
// different ways is not a half-space, so the looser of the two wins
|
|
209
140
|
// and a rotating plane simply stops bounding anything.
|
|
210
141
|
if (n > PLANE_AXIS_TOLERANCE) {
|
|
211
|
-
table[r + CCR_AABB_MAX_X + axis] =
|
|
142
|
+
table[r + CCR_AABB_MAX_X + axis] = max2_exact(table[r + CCR_AABB_MAX_X + axis], offset);
|
|
212
143
|
} else if (n < -PLANE_AXIS_TOLERANCE) {
|
|
213
|
-
table[r + CCR_AABB_MIN_X + axis] =
|
|
144
|
+
table[r + CCR_AABB_MIN_X + axis] = min2_exact(table[r + CCR_AABB_MIN_X + axis], -offset);
|
|
214
145
|
}
|
|
215
146
|
}
|
|
216
147
|
}
|
|
@@ -268,16 +199,3 @@ const CURRENT_BOUNDS = new Float64Array(6);
|
|
|
268
199
|
* @private
|
|
269
200
|
*/
|
|
270
201
|
const PREVIOUS_BOUNDS = new Float64Array(6);
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* @type {Float64Array}
|
|
274
|
-
* @private
|
|
275
|
-
*/
|
|
276
|
-
const POSE = new Float64Array(16);
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* The scale {@link project} composes with: a collider's pose is rigid.
|
|
280
|
-
* @type {Float64Array}
|
|
281
|
-
* @private
|
|
282
|
-
*/
|
|
283
|
-
const UNIT_SCALE = new Float64Array([1, 1, 1]);
|
|
@@ -5,11 +5,8 @@
|
|
|
5
5
|
* It runs when a `ClothCollider` is linked or its shape changes, never per step
|
|
6
6
|
* and never per particle.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* and because a marker per kind would be five new fields on `core` shapes for
|
|
11
|
-
* one consumer's benefit. The ordering matters in one place and is commented
|
|
12
|
-
* where it does.
|
|
8
|
+
* Each kind is asked by its prototype marker, as the physics narrowphase asks;
|
|
9
|
+
* the five are unrelated classes, so the order of the tests does not matter.
|
|
13
10
|
*
|
|
14
11
|
* @author Alex Goldring
|
|
15
12
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_collider_pack.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_pack.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_collider_pack.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_pack.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;GASG;AACH,2CAPW,YAAY,GAAC,YAAY,UACzB,MAAM,kCAEN,MAAM,GACJ,OAAO,CAiFnB;AAED;;;;;;;;;;;;;;GAcG;AACH,iDANW,YAAY,GAAC,MAAM,EAAE,SACrB,YAAY,GAAC,YAAY,UACzB,MAAM,UACN,MAAM,GACJ,OAAO,CAqCnB"}
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import { BoxShape3D } from "../../../../core/geom/3d/shape/BoxShape3D.js";
|
|
2
|
-
import { CapsuleShape3D } from "../../../../core/geom/3d/shape/CapsuleShape3D.js";
|
|
3
|
-
import { CylinderShape3D } from "../../../../core/geom/3d/shape/CylinderShape3D.js";
|
|
4
|
-
import { PlaneShape3D } from "../../../../core/geom/3d/shape/PlaneShape3D.js";
|
|
5
|
-
import { SphereShape3D } from "../../../../core/geom/3d/shape/SphereShape3D.js";
|
|
6
1
|
import { ClothColliderKind } from "./ClothColliderKind.js";
|
|
7
2
|
import {
|
|
8
3
|
CCR_FEATURE,
|
|
@@ -20,11 +15,8 @@ import {
|
|
|
20
15
|
* It runs when a `ClothCollider` is linked or its shape changes, never per step
|
|
21
16
|
* and never per particle.
|
|
22
17
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* and because a marker per kind would be five new fields on `core` shapes for
|
|
26
|
-
* one consumer's benefit. The ordering matters in one place and is commented
|
|
27
|
-
* where it does.
|
|
18
|
+
* Each kind is asked by its prototype marker, as the physics narrowphase asks;
|
|
19
|
+
* the five are unrelated classes, so the order of the tests does not matter.
|
|
28
20
|
*
|
|
29
21
|
* @author Alex Goldring
|
|
30
22
|
* @copyright Company Named Limited (c) 2026
|
|
@@ -43,7 +35,7 @@ import {
|
|
|
43
35
|
export function cloth_collider_pack(table, record, shape, stride) {
|
|
44
36
|
const r = record * stride;
|
|
45
37
|
|
|
46
|
-
if (shape
|
|
38
|
+
if (shape.isSphereShape3D === true) {
|
|
47
39
|
// Covers UnitSphereShape3D, which is a SphereShape3D of radius 1.
|
|
48
40
|
const radius = shape.radius;
|
|
49
41
|
|
|
@@ -57,7 +49,7 @@ export function cloth_collider_pack(table, record, shape, stride) {
|
|
|
57
49
|
return true;
|
|
58
50
|
}
|
|
59
51
|
|
|
60
|
-
if (shape
|
|
52
|
+
if (shape.isCapsuleShape3D === true) {
|
|
61
53
|
const radius = shape.radius;
|
|
62
54
|
|
|
63
55
|
table[r + CCR_KIND] = ClothColliderKind.Capsule;
|
|
@@ -72,7 +64,7 @@ export function cloth_collider_pack(table, record, shape, stride) {
|
|
|
72
64
|
return true;
|
|
73
65
|
}
|
|
74
66
|
|
|
75
|
-
if (shape
|
|
67
|
+
if (shape.isBoxShape3D === true) {
|
|
76
68
|
// Covers UnitCubeShape3D, which is a BoxShape3D pinned to 0.5.
|
|
77
69
|
const h = shape.half_extents;
|
|
78
70
|
|
|
@@ -90,7 +82,7 @@ export function cloth_collider_pack(table, record, shape, stride) {
|
|
|
90
82
|
return true;
|
|
91
83
|
}
|
|
92
84
|
|
|
93
|
-
if (shape
|
|
85
|
+
if (shape.isCylinderShape3D === true) {
|
|
94
86
|
const radius = shape.radius;
|
|
95
87
|
|
|
96
88
|
table[r + CCR_KIND] = ClothColliderKind.Cylinder;
|
|
@@ -103,7 +95,7 @@ export function cloth_collider_pack(table, record, shape, stride) {
|
|
|
103
95
|
return true;
|
|
104
96
|
}
|
|
105
97
|
|
|
106
|
-
if (shape
|
|
98
|
+
if (shape.isPlaneShape3D === true) {
|
|
107
99
|
table[r + CCR_KIND] = ClothColliderKind.Plane;
|
|
108
100
|
table[r + CCR_PARAM_0] = shape.normal_x;
|
|
109
101
|
table[r + CCR_PARAM_1] = shape.normal_y;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloth_collider_sdf.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_sdf.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cloth_collider_sdf.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/cloth/collider/cloth_collider_sdf.js"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8CALW,YAAY,GAAC,YAAY,SACzB,MAAM,KACN,MAAM,GACJ,IAAI,CAmBhB;AAED;;;;;;;;;;;;;;GAcG;AACH,yDATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,mBAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,MAAM,CAclB;AAED;;;;;;;;;;;;;;GAcG;AACH,0DATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAElC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,SACN,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,gBAClC,MAAM,GACJ,IAAI,CAgChB;AAED;;;;;;;;;;;;;;;GAeG;AACH,+CATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,IAAI,CAQhB;AAED;;;;;;;;;;;GAWG;AACH,qDARW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,SACN,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,gBAClC,MAAM,GACJ,IAAI,CAMhB;AAED;;;;;;;;;;;;;GAaG;AACH,6CATW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,KACN,MAAM,KACN,MAAM,KACN,MAAM,GACJ,IAAI,CAQhB;AAED;;;;;;;;;;;GAWG;AACH,mDARW,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,cAClC,MAAM,SACN,YAAY,GAAC,YAAY,UACzB,MAAM,SACN,YAAY,GAAC,YAAY,GAAC,MAAM,EAAE,gBAClC,MAAM,GACJ,IAAI,CAMhB"}
|
|
@@ -1,31 +1,24 @@
|
|
|
1
|
+
import { pose3_apply_inverse_point_array } from "../../../../core/geom/3d/pose/pose3_apply_inverse_point_array.js";
|
|
2
|
+
import { pose3_apply_point_array } from "../../../../core/geom/3d/pose/pose3_apply_point_array.js";
|
|
3
|
+
import { quat3_nlerp_array } from "../../../../core/geom/3d/quaternion/quat3_nlerp.js";
|
|
1
4
|
import { sdf3_box_gradient_array } from "../../../../core/geom/3d/shape/sdf/sdf3_box.js";
|
|
2
5
|
import { sdf3_capsule_gradient_array } from "../../../../core/geom/3d/shape/sdf/sdf3_capsule.js";
|
|
3
6
|
import { sdf3_cylinder_gradient_array } from "../../../../core/geom/3d/shape/sdf/sdf3_cylinder.js";
|
|
4
7
|
import { sdf3_plane_gradient_array } from "../../../../core/geom/3d/shape/sdf/sdf3_plane.js";
|
|
5
8
|
import { sdf3_sphere_gradient_array } from "../../../../core/geom/3d/shape/sdf/sdf3_sphere.js";
|
|
6
9
|
import { v3_quaternion_apply_array } from "../../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
7
|
-
import { v3_quaternion_apply_inverse_array } from "../../../../core/geom/vec3/v3_quaternion_apply_inverse.js";
|
|
8
10
|
import {
|
|
9
|
-
CCR_INTERP_QW,
|
|
10
11
|
CCR_INTERP_QX,
|
|
11
|
-
CCR_INTERP_QY,
|
|
12
|
-
CCR_INTERP_QZ,
|
|
13
12
|
CCR_INTERP_TX,
|
|
14
13
|
CCR_INTERP_TY,
|
|
15
14
|
CCR_INTERP_TZ,
|
|
16
15
|
CCR_KIND,
|
|
17
16
|
CCR_PARAM_0,
|
|
18
|
-
CCR_PREV_QW,
|
|
19
17
|
CCR_PREV_QX,
|
|
20
|
-
CCR_PREV_QY,
|
|
21
|
-
CCR_PREV_QZ,
|
|
22
18
|
CCR_PREV_TX,
|
|
23
19
|
CCR_PREV_TY,
|
|
24
20
|
CCR_PREV_TZ,
|
|
25
|
-
CCR_QW,
|
|
26
21
|
CCR_QX,
|
|
27
|
-
CCR_QY,
|
|
28
|
-
CCR_QZ,
|
|
29
22
|
CCR_STRIDE,
|
|
30
23
|
CCR_TX,
|
|
31
24
|
CCR_TY,
|
|
@@ -89,42 +82,12 @@ export function cloth_collider_pose_at(table, count, t) {
|
|
|
89
82
|
table[r + CCR_INTERP_TY] = s * table[r + CCR_PREV_TY] + t * table[r + CCR_TY];
|
|
90
83
|
table[r + CCR_INTERP_TZ] = s * table[r + CCR_PREV_TZ] + t * table[r + CCR_TZ];
|
|
91
84
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
let by = table[r + CCR_QY];
|
|
99
|
-
let bz = table[r + CCR_QZ];
|
|
100
|
-
let bw = table[r + CCR_QW];
|
|
101
|
-
|
|
102
|
-
// `q` and `−q` are one rotation, so the pair has to be brought onto the
|
|
103
|
-
// same hemisphere or the interpolation takes the long way round — which
|
|
104
|
-
// for a collider is a bone that spins through the character.
|
|
105
|
-
if (ax * bx + ay * by + az * bz + aw * bw < 0) {
|
|
106
|
-
bx = -bx;
|
|
107
|
-
by = -by;
|
|
108
|
-
bz = -bz;
|
|
109
|
-
bw = -bw;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const qx = s * ax + t * bx;
|
|
113
|
-
const qy = s * ay + t * by;
|
|
114
|
-
const qz = s * az + t * bz;
|
|
115
|
-
const qw = s * aw + t * bw;
|
|
116
|
-
|
|
117
|
-
const length = Math.sqrt(qx * qx + qy * qy + qz * qz + qw * qw);
|
|
118
|
-
|
|
119
|
-
// Two opposed quaternions cancel exactly, which the hemisphere fix
|
|
120
|
-
// above makes impossible; the guard is for a record whose poses were
|
|
121
|
-
// never written rather than for a rotation.
|
|
122
|
-
const inverse = length > 0 ? 1 / length : 0;
|
|
123
|
-
|
|
124
|
-
table[r + CCR_INTERP_QX] = qx * inverse;
|
|
125
|
-
table[r + CCR_INTERP_QY] = qy * inverse;
|
|
126
|
-
table[r + CCR_INTERP_QZ] = qz * inverse;
|
|
127
|
-
table[r + CCR_INTERP_QW] = length > 0 ? qw * inverse : 1;
|
|
85
|
+
// Both poses' quaternions are contiguous `[x, y, z, w]` slots, so the
|
|
86
|
+
// blend reads them in place. `q` and `−q` are one rotation; the
|
|
87
|
+
// hemisphere flip inside the nlerp is what keeps the pair from
|
|
88
|
+
// interpolating the long way round — which for a collider is a bone
|
|
89
|
+
// that spins through the character.
|
|
90
|
+
quat3_nlerp_array(table, r + CCR_INTERP_QX, table, r + CCR_PREV_QX, table, r + CCR_QX, t);
|
|
128
91
|
}
|
|
129
92
|
}
|
|
130
93
|
|
|
@@ -175,11 +138,11 @@ export function cloth_collider_signed_distance(gradient, gradient_offset, table,
|
|
|
175
138
|
export function cloth_collider_signed_distance_array(out, out_offset, table, record, point, point_offset) {
|
|
176
139
|
const r = record * CCR_STRIDE;
|
|
177
140
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
141
|
+
pose3_apply_inverse_point_array(
|
|
142
|
+
LOCAL_POINT, 0,
|
|
143
|
+
table, r + CCR_INTERP_TX, table, r + CCR_INTERP_QX,
|
|
144
|
+
point, point_offset
|
|
145
|
+
);
|
|
183
146
|
|
|
184
147
|
const kind = table[r + CCR_KIND];
|
|
185
148
|
|
|
@@ -243,11 +206,7 @@ export function cloth_collider_from_local(out, out_offset, table, record, x, y,
|
|
|
243
206
|
export function cloth_collider_from_local_array(out, out_offset, table, record, point, point_offset) {
|
|
244
207
|
const r = record * CCR_STRIDE;
|
|
245
208
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
out[out_offset] += table[r + CCR_INTERP_TX];
|
|
249
|
-
out[out_offset + 1] += table[r + CCR_INTERP_TY];
|
|
250
|
-
out[out_offset + 2] += table[r + CCR_INTERP_TZ];
|
|
209
|
+
pose3_apply_point_array(out, out_offset, table, r + CCR_INTERP_TX, table, r + CCR_INTERP_QX, point, point_offset);
|
|
251
210
|
}
|
|
252
211
|
|
|
253
212
|
/**
|
|
@@ -287,11 +246,7 @@ export function cloth_collider_to_local(out, out_offset, table, record, x, y, z)
|
|
|
287
246
|
export function cloth_collider_to_local_array(out, out_offset, table, record, point, point_offset) {
|
|
288
247
|
const r = record * CCR_STRIDE;
|
|
289
248
|
|
|
290
|
-
|
|
291
|
-
LOCAL_POINT[1] = point[point_offset + 1] - table[r + CCR_INTERP_TY];
|
|
292
|
-
LOCAL_POINT[2] = point[point_offset + 2] - table[r + CCR_INTERP_TZ];
|
|
293
|
-
|
|
294
|
-
v3_quaternion_apply_inverse_array(out, out_offset, LOCAL_POINT, 0, table, r + CCR_INTERP_QX);
|
|
249
|
+
pose3_apply_inverse_point_array(out, out_offset, table, r + CCR_INTERP_TX, table, r + CCR_INTERP_QX, point, point_offset);
|
|
295
250
|
}
|
|
296
251
|
|
|
297
252
|
/**
|