@woosh/meep-engine 3.40.0 → 3.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/geom/3d/quaternion/swing_twist_clamp.d.ts +24 -0
- package/src/core/geom/3d/quaternion/swing_twist_clamp.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_clamp.js +62 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.d.ts +15 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_compose.js +36 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.d.ts +39 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/swing_twist_error.js +85 -0
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.d.ts +11 -6
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_rigid_align_paired_unit_vectors.js +27 -13
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts +25 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.d.ts.map +1 -0
- package/src/core/math/linalg/eigen/matrix_symmetric_4x4_eigen.js +166 -0
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts +5 -3
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.d.ts.map +1 -1
- package/src/core/math/linalg/eigen/matrix_top_eigenvector_power_iteration.js +5 -3
- package/src/engine/animation/curve/AnimationCurve.d.ts +3 -0
- package/src/engine/animation/curve/AnimationCurve.d.ts.map +1 -1
- package/src/engine/animation/curve/AnimationCurve.js +6 -1
- package/src/engine/ecs/EntityManager.d.ts +9 -1
- package/src/engine/ecs/EntityManager.d.ts.map +1 -1
- package/src/engine/ecs/EntityManager.js +26 -27
- package/src/engine/ecs/gpu/GPUStateAuthority.d.ts +20 -0
- package/src/engine/ecs/gpu/GPUStateAuthority.d.ts.map +1 -1
- package/src/engine/ecs/gpu/GPUStateAuthority.js +21 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.d.ts +13 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.d.ts.map +1 -0
- package/src/engine/ecs/gpu/GPU_AUTHORITY_EVENT_HOLD_CHANGE.js +12 -0
- package/src/engine/ecs/gpu/gpu_authority_grant.d.ts +6 -0
- package/src/engine/ecs/gpu/gpu_authority_grant.d.ts.map +1 -1
- package/src/engine/ecs/gpu/gpu_authority_grant.js +7 -1
- package/src/engine/ecs/gpu/gpu_authority_held.d.ts +14 -0
- package/src/engine/ecs/gpu/gpu_authority_held.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_held.js +23 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.d.ts +23 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_hold.js +41 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.d.ts +14 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.d.ts.map +1 -0
- package/src/engine/ecs/gpu/gpu_authority_unhold.js +32 -0
- package/src/engine/ecs/ik/IKGoal.d.ts +59 -0
- package/src/engine/ecs/ik/IKGoal.d.ts.map +1 -0
- package/src/engine/ecs/ik/IKGoal.js +83 -0
- package/src/engine/ecs/ik/IKGoalSystem.d.ts +75 -0
- package/src/engine/ecs/ik/IKGoalSystem.d.ts.map +1 -0
- package/src/engine/ecs/ik/IKGoalSystem.js +1456 -0
- package/src/engine/ecs/ik/PLAN.md +179 -0
- package/src/engine/ecs/speaker/VoiceSystem.d.ts +2 -2
- package/src/engine/ecs/speaker/VoiceSystem.d.ts.map +1 -1
- package/src/engine/ecs/storage/BinaryBufferSerializer.d.ts.map +1 -1
- package/src/engine/ecs/storage/BinaryBufferSerializer.js +4 -5
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +7 -3
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.d.ts.map +1 -1
- package/src/engine/ecs/storage/populateEngineSerializationRegistry.js +1 -2
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.d.ts +33 -0
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.d.ts.map +1 -0
- package/src/engine/ecs/system/orderSystemsByDeclaredAccess.js +282 -0
- package/src/engine/ecs/transform/T64WorldCache.js +139 -139
- package/src/engine/ecs/transform/t64_evaluate_local.d.ts +25 -0
- package/src/engine/ecs/transform/t64_evaluate_local.d.ts.map +1 -0
- package/src/engine/ecs/transform/t64_evaluate_local.js +35 -0
- package/src/engine/ecs/transform/t64_evaluate_world.d.ts +5 -3
- package/src/engine/ecs/transform/t64_evaluate_world.d.ts.map +1 -1
- package/src/engine/ecs/transform/t64_evaluate_world.js +128 -126
- package/src/engine/graphics3/AnimationGraphSystem.d.ts +2 -0
- package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationGraphSystem.js +337 -329
- package/src/engine/graphics3/AnimationSystem.d.ts +2 -0
- package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
- package/src/engine/graphics3/AnimationSystem.js +360 -352
- package/src/engine/physics/cloth/MEASUREMENTS.md +130 -0
- package/src/engine/physics/cloth/PLAN.md +16 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +5 -6
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +5 -6
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +4 -7
- package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothInstance.js +4 -7
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +4 -3
- package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothSystem.js +4 -3
- package/src/engine/physics/cloth/ecs/ClothWorld.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/ClothWorld.js +10 -0
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +24 -24
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -1
- package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +46 -43
- package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +1 -1
- package/src/engine/physics/cloth/ecs/cloth_write_back.js +1 -1
- package/src/engine/physics/constraint/solve_constraints.d.ts +0 -35
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +1 -83
- package/src/engine/physics/ecs/ContactProbe.d.ts +73 -0
- package/src/engine/physics/ecs/ContactProbe.d.ts.map +1 -0
- package/src/engine/physics/ecs/ContactProbe.js +103 -0
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts +44 -0
- package/src/engine/physics/ecs/ContactProbeSystem.d.ts.map +1 -0
- package/src/engine/physics/ecs/ContactProbeSystem.js +397 -0
- package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +1 -1
- package/src/engine/physics/fluid/ecs/FluidComponent.js +1 -1
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.d.ts +205 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/FrameFabrikProblem.js +245 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.d.ts +21 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_limit_from_joint.js +63 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts +33 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/frame_fabrik/frame_fabrik_solve.js +874 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.d.ts +27 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/joint_hinge_mid_axis.js +77 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.d.ts +36 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.d.ts.map +1 -0
- package/src/engine/physics/inverse_kinematics/two_bone_path_solve.js +97 -0
- package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts +33 -11
- package/src/engine/physics/inverse_kinematics/two_joint_ik.d.ts.map +1 -1
- package/src/engine/physics/inverse_kinematics/two_joint_ik.js +158 -67
- package/src/shade/renderer/animation/ANIMATION_TRACK_BINDING_STRUCT.d.ts.map +1 -1
- package/src/shade/renderer/animation/ANIMATION_TRACK_BINDING_STRUCT.js +10 -1
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +10 -4
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +251 -23
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts +12 -4
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.d.ts.map +1 -1
- package/src/shade/renderer/animation/POSE_ACCUMULATOR_LAYOUT.js +12 -4
- package/src/shade/renderer/animation/chunk_pose_accumulator.d.ts.map +1 -1
- package/src/shade/renderer/animation/chunk_pose_accumulator.js +14 -1
- package/src/shade/renderer/animation/pose/PoseChannelIndex.d.ts +78 -0
- package/src/shade/renderer/animation/pose/PoseChannelIndex.d.ts.map +1 -0
- package/src/shade/renderer/animation/pose/PoseChannelIndex.js +274 -0
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts +40 -3
- package/src/shade/renderer/animation/pose/PosePlayback.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/PosePlayback.js +77 -3
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts +21 -3
- package/src/shade/renderer/animation/pose/pose_evaluate_local.d.ts.map +1 -1
- package/src/shade/renderer/animation/pose/pose_evaluate_local.js +79 -11
- package/src/shade/renderer/animation/shader_animation_apply.js +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts +3 -2
- package/src/shade/renderer/animation/shader_animation_pose_resolve.d.ts.map +1 -1
- package/src/shade/renderer/animation/shader_animation_pose_resolve.js +187 -176
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.d.ts +3 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property.js +5 -2
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts +4 -0
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.d.ts.map +1 -1
- package/src/shade/renderer/object_property/chunk_write_object_property_node3d.js +6 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.d.ts +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/geometry_deduplicate.js +135 -73
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.d.ts +7 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.d.ts.map +1 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/cover_greedy.js +29 -1
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.d.ts +19 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/face_neighbourhood_hash.js +167 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.d.ts +25 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/neighbourhood_anchor_index.js +124 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.d.ts +19 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.d.ts.map +1 -0
- package/src/shade/renderer/scene/optimization/geometry/internal/seed_correspondence_from_face_pair.js +48 -0
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +17 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
- package/src/shade/renderer/scene/rows/GPUSceneRows.js +29 -3
- package/src/engine/ecs/ik/IKConstraint.d.ts +0 -52
- package/src/engine/ecs/ik/IKConstraint.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKConstraint.js +0 -95
- package/src/engine/ecs/ik/IKProblem.d.ts +0 -45
- package/src/engine/ecs/ik/IKProblem.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKProblem.js +0 -58
- package/src/engine/ecs/ik/IKSolver.d.ts +0 -8
- package/src/engine/ecs/ik/IKSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/IKSolver.js +0 -9
- package/src/engine/ecs/ik/InverseKinematics.d.ts +0 -48
- package/src/engine/ecs/ik/InverseKinematics.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematics.js +0 -119
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.d.ts +0 -19
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematicsSerializationAdapter.js +0 -72
- package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts +0 -54
- package/src/engine/ecs/ik/InverseKinematicsSystem.d.ts.map +0 -1
- package/src/engine/ecs/ik/InverseKinematicsSystem.js +0 -212
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts +0 -8
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +0 -153
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts +0 -5
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.d.ts.map +0 -1
- package/src/engine/ecs/ik/TwoBoneInverseKinematicsSolver.js +0 -120
- package/src/engine/ecs/ik/ik_bone_chain.d.ts +0 -64
- package/src/engine/ecs/ik/ik_bone_chain.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_bone_chain.js +0 -142
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts +0 -42
- package/src/engine/ecs/ik/ik_probe_terrain_contact.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_probe_terrain_contact.js +0 -123
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts +0 -18
- package/src/engine/ecs/ik/ik_write_local_rotation.d.ts.map +0 -1
- package/src/engine/ecs/ik/ik_write_local_rotation.js +0 -32
|
@@ -1,38 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Swing-twist decomposition of the relative rotation `qD = conj(qA)⊗qB`, giving
|
|
3
|
-
* the per-frame-axis angular positions used by wide-cone angular DOFs.
|
|
4
|
-
*
|
|
5
|
-
* Decomposes `qD = swing ⊗ twist`, with **twist** the rotation about frame
|
|
6
|
-
* axis X (the bone / twist axis) and **swing** the residual tilt (a rotation
|
|
7
|
-
* about an axis in the YZ plane that carries X to its new direction). Writes,
|
|
8
|
-
* into `out`:
|
|
9
|
-
* - `out[0]` = signed twist angle about X, in `(−π, π]` — *exact*, so a twist
|
|
10
|
-
* limit engages at the true angle, not the `2·sin(θ/2)` small-angle proxy;
|
|
11
|
-
* - `out[1]`, `out[2]` = the swing angle distributed over Y and Z
|
|
12
|
-
* (`φ·axis`, φ the true swing angle), so independent Y/Z swing limits form
|
|
13
|
-
* an accurate (box-shaped) cone that holds at large tilt.
|
|
14
|
-
* Reduces continuously to the small-angle vector near identity. Pure scratch /
|
|
15
|
-
* locals — no allocation, suitable for the per-substep hot loop. (The Quaternion
|
|
16
|
-
* class has an object-based `computeSwingAndTwist`; this is the inlined,
|
|
17
|
-
* allocation-free form — see the bench that justifies it.)
|
|
18
|
-
*
|
|
19
|
-
* @param {number} dx qD x
|
|
20
|
-
* @param {number} dy qD y
|
|
21
|
-
* @param {number} dz qD z
|
|
22
|
-
* @param {number} dw qD w
|
|
23
|
-
* @param {Float64Array} out length-3 destination (frame-axis positions)
|
|
24
|
-
*/
|
|
25
|
-
export function swing_twist_error(dx: number, dy: number, dz: number, dw: number, out: Float64Array): void;
|
|
26
|
-
/**
|
|
27
|
-
* {@link swing_twist_error} with `qD` read from `q[q_offset ..+3]`, `[x, y, z, w]`: the one place the
|
|
28
|
-
* arithmetic lives. For a caller whose inlining budget is spent, where a call taking the four numbers
|
|
29
|
-
* would box each into a new heap object.
|
|
30
|
-
*
|
|
31
|
-
* @param {Float64Array} q
|
|
32
|
-
* @param {number} q_offset
|
|
33
|
-
* @param {Float64Array} out length-3 destination (frame-axis positions)
|
|
34
|
-
*/
|
|
35
|
-
export function swing_twist_error_array(q: Float64Array, q_offset: number, out: Float64Array): void;
|
|
36
1
|
/**
|
|
37
2
|
* Solve every joint for one substep: prepare each joint's rows at the current
|
|
38
3
|
* poses, then run `iters` Gauss-Seidel passes over all of them. The first pass
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solve_constraints.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/constraint/solve_constraints.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"solve_constraints.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/constraint/solve_constraints.js"],"names":[],"mappings":"AAs6BA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qCAXW,OAAO,iCAEP,MAAM,SAEN,MAAM,YAGN,OAAO,QAgCjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qCAJW,OAAO,mCAEP,OAAO,QAgBjB"}
|
|
@@ -2,6 +2,7 @@ import { assert } from "../../../core/assert.js";
|
|
|
2
2
|
import { apply_impulse_to_body } from "../solver/apply_impulse_to_body.js";
|
|
3
3
|
import { quat3_multiply_array } from "../../../core/geom/3d/quaternion/quat3_multiply.js";
|
|
4
4
|
import { quat3_to_matrix3_array } from "../../../core/geom/3d/quaternion/quat3_to_matrix3.js";
|
|
5
|
+
import { swing_twist_error_array } from "../../../core/geom/3d/quaternion/swing_twist_error.js";
|
|
5
6
|
import { v3_quaternion_apply_array } from "../../../core/geom/vec3/v3_quaternion_apply.js";
|
|
6
7
|
import { TRANSFORM64_ROTATION_OFFSET } from "../../ecs/transform/Transform64.js";
|
|
7
8
|
import { body_id_index } from "../body/BodyStorage.js";
|
|
@@ -406,89 +407,6 @@ function invert_sym3(K, out) {
|
|
|
406
407
|
return true;
|
|
407
408
|
}
|
|
408
409
|
|
|
409
|
-
/**
|
|
410
|
-
* Swing-twist decomposition of the relative rotation `qD = conj(qA)⊗qB`, giving
|
|
411
|
-
* the per-frame-axis angular positions used by wide-cone angular DOFs.
|
|
412
|
-
*
|
|
413
|
-
* Decomposes `qD = swing ⊗ twist`, with **twist** the rotation about frame
|
|
414
|
-
* axis X (the bone / twist axis) and **swing** the residual tilt (a rotation
|
|
415
|
-
* about an axis in the YZ plane that carries X to its new direction). Writes,
|
|
416
|
-
* into `out`:
|
|
417
|
-
* - `out[0]` = signed twist angle about X, in `(−π, π]` — *exact*, so a twist
|
|
418
|
-
* limit engages at the true angle, not the `2·sin(θ/2)` small-angle proxy;
|
|
419
|
-
* - `out[1]`, `out[2]` = the swing angle distributed over Y and Z
|
|
420
|
-
* (`φ·axis`, φ the true swing angle), so independent Y/Z swing limits form
|
|
421
|
-
* an accurate (box-shaped) cone that holds at large tilt.
|
|
422
|
-
* Reduces continuously to the small-angle vector near identity. Pure scratch /
|
|
423
|
-
* locals — no allocation, suitable for the per-substep hot loop. (The Quaternion
|
|
424
|
-
* class has an object-based `computeSwingAndTwist`; this is the inlined,
|
|
425
|
-
* allocation-free form — see the bench that justifies it.)
|
|
426
|
-
*
|
|
427
|
-
* @param {number} dx qD x
|
|
428
|
-
* @param {number} dy qD y
|
|
429
|
-
* @param {number} dz qD z
|
|
430
|
-
* @param {number} dw qD w
|
|
431
|
-
* @param {Float64Array} out length-3 destination (frame-axis positions)
|
|
432
|
-
*/
|
|
433
|
-
export function swing_twist_error(dx, dy, dz, dw, out) {
|
|
434
|
-
const q = swing_twist_inputs;
|
|
435
|
-
|
|
436
|
-
q[0] = dx;
|
|
437
|
-
q[1] = dy;
|
|
438
|
-
q[2] = dz;
|
|
439
|
-
q[3] = dw;
|
|
440
|
-
|
|
441
|
-
swing_twist_error_array(q, 0, out);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/** Where {@link swing_twist_error} packs its quaternion. */
|
|
445
|
-
const swing_twist_inputs = new Float64Array(4);
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* {@link swing_twist_error} with `qD` read from `q[q_offset ..+3]`, `[x, y, z, w]`: the one place the
|
|
449
|
-
* arithmetic lives. For a caller whose inlining budget is spent, where a call taking the four numbers
|
|
450
|
-
* would box each into a new heap object.
|
|
451
|
-
*
|
|
452
|
-
* @param {Float64Array} q
|
|
453
|
-
* @param {number} q_offset
|
|
454
|
-
* @param {Float64Array} out length-3 destination (frame-axis positions)
|
|
455
|
-
*/
|
|
456
|
-
export function swing_twist_error_array(q, q_offset, out) {
|
|
457
|
-
let dx = q[q_offset], dy = q[q_offset + 1], dz = q[q_offset + 2], dw = q[q_offset + 3];
|
|
458
|
-
|
|
459
|
-
// Shortest arc: work with the hemisphere where dw ≥ 0.
|
|
460
|
-
if (dw < 0) { dx = -dx; dy = -dy; dz = -dz; dw = -dw; }
|
|
461
|
-
|
|
462
|
-
const nxt = Math.sqrt(dx * dx + dw * dw); // |twist| (before normalising)
|
|
463
|
-
let sy, sz, sw;
|
|
464
|
-
if (nxt < 1e-12) {
|
|
465
|
-
// dw ≈ 0 and dx ≈ 0: a ~180° pure swing — twist is undefined, take 0.
|
|
466
|
-
out[0] = 0;
|
|
467
|
-
// Swing is qD itself; distribute its angle over Y/Z below.
|
|
468
|
-
sy = dy; sz = dz; sw = dw;
|
|
469
|
-
} else {
|
|
470
|
-
out[0] = 2 * Math.atan2(dx, dw); // exact signed twist about X
|
|
471
|
-
const tx = dx / nxt, tw = dw / nxt; // normalised twist (tx,0,0,tw)
|
|
472
|
-
// swing = qD ⊗ conj(twist); its X component is identically 0.
|
|
473
|
-
sy = dy * tw - dz * tx;
|
|
474
|
-
sz = dy * tx + dz * tw;
|
|
475
|
-
sw = dw * tw + dx * tx;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
if (sw < 0) { sy = -sy; sz = -sz; sw = -sw; }
|
|
479
|
-
const syz = Math.sqrt(sy * sy + sz * sz);
|
|
480
|
-
if (syz < 1e-9) {
|
|
481
|
-
// Near-zero swing: small-angle vector (continuous with φ·axis as φ→0).
|
|
482
|
-
out[1] = 2 * sy;
|
|
483
|
-
out[2] = 2 * sz;
|
|
484
|
-
} else {
|
|
485
|
-
const phi = 2 * Math.atan2(syz, sw); // exact swing angle in [0, π]
|
|
486
|
-
const s = phi / syz;
|
|
487
|
-
out[1] = sy * s;
|
|
488
|
-
out[2] = sz * s;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
410
|
/**
|
|
493
411
|
* Fill the row parameters for one DOF given its mode, signed position and
|
|
494
412
|
* signed velocity.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds where a cast from a reference meets the world, and puts the entity it is on there.
|
|
3
|
+
*
|
|
4
|
+
* Every tick {@link ContactProbeSystem} casts a sphere of {@link radius} — a ray, at 0 — from the
|
|
5
|
+
* reference's world position plus {@link offset}, along {@link direction}, for {@link distance}, through
|
|
6
|
+
* the physics system's colliders. On a hit the entity is placed at the contact on the surface, turned
|
|
7
|
+
* as the reference is and tilted so the reference's up is the surface's normal. On a miss it is placed
|
|
8
|
+
* where the reference is. It knows nothing about who reads it: a foot reaching for the ground, a decal,
|
|
9
|
+
* an AI checking its footing.
|
|
10
|
+
*
|
|
11
|
+
* - The entity is placed through its own {@link TransformAttachment}, whose parent is up to the rig.
|
|
12
|
+
* - The character's own colliders are passed through: those whose lifetime ({@link ParentEntity})
|
|
13
|
+
* leads to the same root as the probe's own.
|
|
14
|
+
* - The reference may be a bone a clip drives: its pose is evaluated exactly, as the GPU shows it. It
|
|
15
|
+
* must not be a bone a CPU writer holds (IK, cloth), or the probe would read that writer's answer
|
|
16
|
+
* and the writer would chase its own output.
|
|
17
|
+
*
|
|
18
|
+
* Entity ids are transient, so this is never saved.
|
|
19
|
+
*
|
|
20
|
+
* @author Alex Goldring
|
|
21
|
+
* @copyright Company Named Limited (c) 2026
|
|
22
|
+
*/
|
|
23
|
+
export class ContactProbe {
|
|
24
|
+
/**
|
|
25
|
+
* @param {{reference:number, offset:number[], direction:number[], distance:number, radius:number}} options
|
|
26
|
+
* every field required
|
|
27
|
+
* @returns {ContactProbe}
|
|
28
|
+
*/
|
|
29
|
+
static from({ reference, offset, direction, distance, radius }: {
|
|
30
|
+
reference: number;
|
|
31
|
+
offset: number[];
|
|
32
|
+
direction: number[];
|
|
33
|
+
distance: number;
|
|
34
|
+
radius: number;
|
|
35
|
+
}): ContactProbe;
|
|
36
|
+
/**
|
|
37
|
+
* The entity the cast starts from.
|
|
38
|
+
* @type {number}
|
|
39
|
+
*/
|
|
40
|
+
reference: number;
|
|
41
|
+
/**
|
|
42
|
+
* Where the cast starts, relative to the reference's world position, in world axes.
|
|
43
|
+
* @readonly
|
|
44
|
+
* @type {Float64Array}
|
|
45
|
+
*/
|
|
46
|
+
readonly offset: Float64Array;
|
|
47
|
+
/**
|
|
48
|
+
* Which way the cast goes, in world, of unit length.
|
|
49
|
+
* @readonly
|
|
50
|
+
* @type {Float64Array}
|
|
51
|
+
*/
|
|
52
|
+
readonly direction: Float64Array;
|
|
53
|
+
/**
|
|
54
|
+
* How far the cast reaches.
|
|
55
|
+
* @type {number}
|
|
56
|
+
*/
|
|
57
|
+
distance: number;
|
|
58
|
+
/**
|
|
59
|
+
* The radius of the sphere cast; 0 casts a ray.
|
|
60
|
+
* @type {number}
|
|
61
|
+
*/
|
|
62
|
+
radius: number;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the last cast met anything. Written by {@link ContactProbeSystem}.
|
|
65
|
+
* @type {boolean}
|
|
66
|
+
*/
|
|
67
|
+
hit: boolean;
|
|
68
|
+
}
|
|
69
|
+
export namespace ContactProbe {
|
|
70
|
+
let typeName: string;
|
|
71
|
+
let serializable: boolean;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=ContactProbe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactProbe.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/ContactProbe.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH;IAuCI;;;;OAIG;IACH,gEAJW;QAAC,SAAS,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,EAAE,CAAC;QAAC,SAAS,EAAC,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAA;KAAC,GAErF,YAAY,CAuBxB;IAhED;;;OAGG;IACH,WAFU,MAAM,CAED;IAEf;;;;OAIG;IACH,iBAFU,YAAY,CAEO;IAE7B;;;;OAIG;IACH,oBAFU,YAAY,CAEgB;IAEtC;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,QAFU,MAAM,CAEL;IAEX;;;OAGG;IACH,KAFU,OAAO,CAEL;CA6Bf;;kBAIS,MAAM;sBAMN,OAAO"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Finds where a cast from a reference meets the world, and puts the entity it is on there.
|
|
5
|
+
*
|
|
6
|
+
* Every tick {@link ContactProbeSystem} casts a sphere of {@link radius} — a ray, at 0 — from the
|
|
7
|
+
* reference's world position plus {@link offset}, along {@link direction}, for {@link distance}, through
|
|
8
|
+
* the physics system's colliders. On a hit the entity is placed at the contact on the surface, turned
|
|
9
|
+
* as the reference is and tilted so the reference's up is the surface's normal. On a miss it is placed
|
|
10
|
+
* where the reference is. It knows nothing about who reads it: a foot reaching for the ground, a decal,
|
|
11
|
+
* an AI checking its footing.
|
|
12
|
+
*
|
|
13
|
+
* - The entity is placed through its own {@link TransformAttachment}, whose parent is up to the rig.
|
|
14
|
+
* - The character's own colliders are passed through: those whose lifetime ({@link ParentEntity})
|
|
15
|
+
* leads to the same root as the probe's own.
|
|
16
|
+
* - The reference may be a bone a clip drives: its pose is evaluated exactly, as the GPU shows it. It
|
|
17
|
+
* must not be a bone a CPU writer holds (IK, cloth), or the probe would read that writer's answer
|
|
18
|
+
* and the writer would chase its own output.
|
|
19
|
+
*
|
|
20
|
+
* Entity ids are transient, so this is never saved.
|
|
21
|
+
*
|
|
22
|
+
* @author Alex Goldring
|
|
23
|
+
* @copyright Company Named Limited (c) 2026
|
|
24
|
+
*/
|
|
25
|
+
export class ContactProbe {
|
|
26
|
+
/**
|
|
27
|
+
* The entity the cast starts from.
|
|
28
|
+
* @type {number}
|
|
29
|
+
*/
|
|
30
|
+
reference = -1;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Where the cast starts, relative to the reference's world position, in world axes.
|
|
34
|
+
* @readonly
|
|
35
|
+
* @type {Float64Array}
|
|
36
|
+
*/
|
|
37
|
+
offset = new Float64Array(3);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Which way the cast goes, in world, of unit length.
|
|
41
|
+
* @readonly
|
|
42
|
+
* @type {Float64Array}
|
|
43
|
+
*/
|
|
44
|
+
direction = Float64Array.of(0, -1, 0);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* How far the cast reaches.
|
|
48
|
+
* @type {number}
|
|
49
|
+
*/
|
|
50
|
+
distance = 0;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The radius of the sphere cast; 0 casts a ray.
|
|
54
|
+
* @type {number}
|
|
55
|
+
*/
|
|
56
|
+
radius = 0;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Whether the last cast met anything. Written by {@link ContactProbeSystem}.
|
|
60
|
+
* @type {boolean}
|
|
61
|
+
*/
|
|
62
|
+
hit = false;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {{reference:number, offset:number[], direction:number[], distance:number, radius:number}} options
|
|
66
|
+
* every field required
|
|
67
|
+
* @returns {ContactProbe}
|
|
68
|
+
*/
|
|
69
|
+
static from({ reference, offset, direction, distance, radius }) {
|
|
70
|
+
assert.isNonNegativeInteger(reference, 'reference');
|
|
71
|
+
assert.equal(offset.length, 3, 'offset is [x, y, z]');
|
|
72
|
+
assert.equal(direction.length, 3, 'direction is [x, y, z]');
|
|
73
|
+
assert.ok(Math.abs(Math.hypot(direction[0], direction[1], direction[2]) - 1) < 1e-9, 'direction is of unit length');
|
|
74
|
+
assert.ok(distance > 0, 'distance is positive');
|
|
75
|
+
assert.ok(radius >= 0, 'radius is not negative');
|
|
76
|
+
|
|
77
|
+
const probe = new ContactProbe();
|
|
78
|
+
|
|
79
|
+
probe.reference = reference;
|
|
80
|
+
probe.offset[0] = offset[0];
|
|
81
|
+
probe.offset[1] = offset[1];
|
|
82
|
+
probe.offset[2] = offset[2];
|
|
83
|
+
probe.direction[0] = direction[0];
|
|
84
|
+
probe.direction[1] = direction[1];
|
|
85
|
+
probe.direction[2] = direction[2];
|
|
86
|
+
probe.distance = distance;
|
|
87
|
+
probe.radius = radius;
|
|
88
|
+
|
|
89
|
+
return probe;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @readonly
|
|
95
|
+
* @type {string}
|
|
96
|
+
*/
|
|
97
|
+
ContactProbe.typeName = "ContactProbe";
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Entity ids are transient: serialization is not applicable.
|
|
101
|
+
* @type {boolean}
|
|
102
|
+
*/
|
|
103
|
+
ContactProbe.serializable = false;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Casts each {@link ContactProbe} and places its entity at what the cast meets.
|
|
3
|
+
*
|
|
4
|
+
* Runs in `update`, where the clips' times for the tick are set: a reference a clip drives is
|
|
5
|
+
* evaluated exactly (`T64WorldCache`), as the GPU draws it.
|
|
6
|
+
*
|
|
7
|
+
* **Register it before a system that reads where it puts its entities** and that writes
|
|
8
|
+
* `TransformAttachment` too, IK's among them. Both read and write `TransformAttachment`, so the
|
|
9
|
+
* order declared access derives leaves the two a cycle, and between them the scheduler keeps the
|
|
10
|
+
* order they were registered in.
|
|
11
|
+
*
|
|
12
|
+
* @author Alex Goldring
|
|
13
|
+
* @copyright Company Named Limited (c) 2026
|
|
14
|
+
*/
|
|
15
|
+
export class ContactProbeSystem extends System<any> {
|
|
16
|
+
constructor();
|
|
17
|
+
dependencies: (typeof TransformAttachment | typeof ContactProbe)[];
|
|
18
|
+
components_used: (ResourceAccessSpecification<typeof Transform64> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof AnimationGraphController> | ResourceAccessSpecification<typeof Animation> | ResourceAccessSpecification<typeof TransformAttachment> | ResourceAccessSpecification<typeof GPUStateAuthority> | ResourceAccessSpecification<typeof ParentEntity> | ResourceAccessSpecification<typeof ContactProbe>)[];
|
|
19
|
+
/**
|
|
20
|
+
* @param {ContactProbe} probe
|
|
21
|
+
* @param {TransformAttachment} attachment
|
|
22
|
+
* @param {number} entity
|
|
23
|
+
*/
|
|
24
|
+
link(probe: ContactProbe, attachment: TransformAttachment, entity: number): void;
|
|
25
|
+
/**
|
|
26
|
+
* @param {ContactProbe} probe
|
|
27
|
+
* @param {TransformAttachment} attachment
|
|
28
|
+
* @param {number} entity
|
|
29
|
+
*/
|
|
30
|
+
unlink(probe: ContactProbe, attachment: TransformAttachment, entity: number): void;
|
|
31
|
+
update(time_delta_seconds: any): void;
|
|
32
|
+
#private;
|
|
33
|
+
}
|
|
34
|
+
import { System } from "../../ecs/System.js";
|
|
35
|
+
import { TransformAttachment } from "../../ecs/transform-attachment/TransformAttachment.js";
|
|
36
|
+
import { ContactProbe } from "./ContactProbe.js";
|
|
37
|
+
import { Transform64 } from "../../ecs/transform/Transform64.js";
|
|
38
|
+
import { ResourceAccessSpecification } from "../../../core/model/ResourceAccessSpecification.js";
|
|
39
|
+
import { Collider } from "./Collider.js";
|
|
40
|
+
import { AnimationGraphController } from "../../graphics3/animation/AnimationGraphController.js";
|
|
41
|
+
import { Animation } from "../../ecs/animation/Animation.js";
|
|
42
|
+
import { GPUStateAuthority } from "../../ecs/gpu/GPUStateAuthority.js";
|
|
43
|
+
import { ParentEntity } from "../../ecs/parent/ParentEntity.js";
|
|
44
|
+
//# sourceMappingURL=ContactProbeSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ContactProbeSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/ContactProbeSystem.js"],"names":[],"mappings":"AAqEA;;;;;;;;;;;;;GAaG;AACH;;IAEI,mEAAmD;IAEnD,2bASE;IAyCF;;;;OAIG;IACH,YAJW,YAAY,cACZ,mBAAmB,UACnB,MAAM,QAUhB;IAED;;;;OAIG;IACH,cAJW,YAAY,cACZ,mBAAmB,UACnB,MAAM,QAWhB;IAED,sCA2BC;;CAiKJ;uBA1VsB,qBAAqB;oCAER,uDAAuD;6BAY9D,mBAAmB;4BALzC,oCAAoC;4CAbC,oDAAoD;yBAiBvE,eAAe;yCAHC,uDAAuD;0BAbtE,kCAAkC;kCAC1B,oCAAoC;6BACzC,kCAAkC"}
|