@woosh/meep-engine 2.139.0 → 2.140.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/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.d.ts +3 -3
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.d.ts.map +1 -1
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js +4 -4
- package/src/{engine/physics/broadphase/aabb_transform_oriented.d.ts → core/geom/3d/aabb/aabb3_transform_oriented.d.ts} +2 -2
- package/src/core/geom/3d/aabb/aabb3_transform_oriented.d.ts.map +1 -0
- package/src/{engine/physics/broadphase/aabb_transform_oriented.js → core/geom/3d/aabb/aabb3_transform_oriented.js} +1 -1
- package/src/core/geom/3d/quaternion/quat3_to_matrix3.d.ts +54 -0
- package/src/core/geom/3d/quaternion/quat3_to_matrix3.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_to_matrix3.js +69 -0
- package/src/core/geom/3d/shape/AbstractShape3D.d.ts +24 -2
- package/src/core/geom/3d/shape/AbstractShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/AbstractShape3D.js +24 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts +148 -0
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/HeightMapShape3D.js +451 -0
- package/src/core/geom/3d/shape/MeshShape3D.d.ts +210 -0
- package/src/core/geom/3d/shape/MeshShape3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/MeshShape3D.js +593 -0
- package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/TransformedShape3D.js +46 -2
- package/src/core/geom/3d/shape/Triangle3D.d.ts +95 -0
- package/src/core/geom/3d/shape/Triangle3D.d.ts.map +1 -0
- package/src/core/geom/3d/shape/Triangle3D.js +318 -0
- package/src/core/geom/3d/shape/UnionShape3D.js +13 -0
- package/src/core/geom/3d/shape/shape_mesh_from_geometry.d.ts +30 -0
- package/src/core/geom/3d/shape/shape_mesh_from_geometry.d.ts.map +1 -0
- package/src/core/geom/3d/shape/shape_mesh_from_geometry.js +64 -0
- package/src/core/geom/3d/tetrahedra/prototype_tetrahedrize_mesh.js +9 -11
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.d.ts +28 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.d.ts.map +1 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_build_vertex_to_tets_map.js +48 -0
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -1
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.js +40 -18
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts +9 -5
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.d.ts.map +1 -1
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_smooth_vertex.js +38 -10
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts +14 -5
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.d.ts.map +1 -1
- package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_vertex_is_boundary.js +47 -5
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts +19 -0
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.d.ts.map +1 -1
- package/src/core/geom/3d/topology/struct/binary/BinaryElementPool.js +75 -13
- package/src/core/geom/3d/triangle/v3_compute_triangle_normal.d.ts +2 -2
- package/src/core/geom/3d/triangle/v3_compute_triangle_normal.d.ts.map +1 -1
- package/src/core/geom/3d/triangle/v3_compute_triangle_normal.js +1 -1
- package/src/core/geom/vec3/v3_dot_array_array.d.ts +3 -3
- package/src/core/geom/vec3/v3_dot_array_array.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_dot_array_array.js +2 -2
- package/src/core/geom/vec3/v3_negate_array.d.ts +3 -3
- package/src/core/geom/vec3/v3_negate_array.d.ts.map +1 -1
- package/src/core/geom/vec3/v3_negate_array.js +2 -2
- package/src/core/geom/vec3/v3_quat3_apply.d.ts +29 -0
- package/src/core/geom/vec3/v3_quat3_apply.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_quat3_apply.js +39 -0
- package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts +30 -0
- package/src/core/geom/vec3/v3_quat3_apply_inverse.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_quat3_apply_inverse.js +41 -0
- package/src/core/geom/vec3/v3_triple_cross_product.d.ts +32 -0
- package/src/core/geom/vec3/v3_triple_cross_product.d.ts.map +1 -0
- package/src/core/geom/vec3/v3_triple_cross_product.js +45 -0
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +16 -3
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerController.js +211 -211
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +72 -8
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +37 -5
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +101 -3
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.js +1789 -1416
- package/src/engine/control/first-person/TODO.md +173 -127
- package/src/engine/control/first-person/abilities/Slide.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/Slide.js +9 -1
- package/src/engine/control/first-person/prototype_first_person_controller.js +88 -2
- package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -1
- package/src/engine/control/first-person/test/buildTestPlayer.js +9 -1
- package/src/engine/graphics/geometry/CapsuleGeometry.d.ts +42 -0
- package/src/engine/graphics/geometry/CapsuleGeometry.d.ts.map +1 -0
- package/src/engine/graphics/geometry/CapsuleGeometry.js +171 -0
- package/src/engine/physics/BULLET_REVIEW.md +945 -0
- package/src/engine/physics/CANNON_REVIEW.md +1300 -0
- package/src/engine/physics/JOLT_REVIEW.md +913 -0
- package/src/engine/physics/PLAN.md +461 -236
- package/src/engine/physics/RAPIER_REVIEW.md +934 -0
- package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +642 -0
- package/src/engine/physics/broadphase/compute_fat_world_aabb.js +2 -2
- package/src/engine/physics/contact/ManifoldStore.d.ts +83 -10
- package/src/engine/physics/contact/ManifoldStore.d.ts.map +1 -1
- package/src/engine/physics/contact/ManifoldStore.js +608 -499
- package/src/engine/physics/ecs/ColliderObserverSystem.d.ts +2 -2
- package/src/engine/physics/ecs/ColliderObserverSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +128 -20
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +1301 -1159
- package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidSimulator.js +2 -1
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +28 -6
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +39 -17
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts +6 -6
- package/src/engine/physics/gjk/expanding_polytope_algorithm.d.ts.map +1 -1
- package/src/engine/physics/gjk/expanding_polytope_algorithm.js +68 -22
- package/src/engine/physics/gjk/gjk.d.ts +28 -2
- package/src/engine/physics/gjk/gjk.d.ts.map +1 -1
- package/src/engine/physics/gjk/gjk.js +421 -378
- package/src/engine/physics/gjk/minkowski_support.d.ts +37 -0
- package/src/engine/physics/gjk/minkowski_support.d.ts.map +1 -0
- package/src/engine/physics/gjk/minkowski_support.js +75 -0
- package/src/engine/physics/gjk/mpr.d.ts +56 -0
- package/src/engine/physics/gjk/mpr.d.ts.map +1 -0
- package/src/engine/physics/gjk/mpr.js +344 -0
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +20 -5
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
- package/src/engine/physics/inertia/world_inverse_inertia.js +36 -38
- package/src/engine/physics/integration/integrate_position.d.ts +25 -7
- package/src/engine/physics/integration/integrate_position.d.ts.map +1 -1
- package/src/engine/physics/integration/integrate_position.js +43 -12
- package/src/engine/physics/integration/integrate_velocity.d.ts +30 -0
- package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -1
- package/src/engine/physics/integration/integrate_velocity.js +82 -1
- package/src/engine/physics/narrowphase/PosedShape.d.ts +0 -8
- package/src/engine/physics/narrowphase/PosedShape.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/PosedShape.js +28 -30
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_box_manifold.js +113 -17
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts +30 -0
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/box_triangle_contact.js +811 -0
- package/src/engine/physics/narrowphase/capsule_contacts.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/capsule_contacts.js +10 -56
- package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts +71 -0
- package/src/engine/physics/narrowphase/capsule_triangle_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/capsule_triangle_contact.js +375 -0
- package/src/engine/physics/narrowphase/compute_penetration.d.ts +91 -0
- package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/compute_penetration.js +396 -0
- package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts +35 -0
- package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/decomposition/aabb_world_to_local.js +80 -0
- package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.d.ts +31 -0
- package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/decomposition/decompose_to_triangles.js +55 -0
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +42 -0
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +204 -0
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts +42 -0
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/decomposition/mesh_enumerate_triangles.js +94 -0
- package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts +37 -0
- package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +37 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts +8 -2
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +1422 -382
- package/src/engine/physics/narrowphase/sphere_box_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/sphere_box_contact.js +16 -23
- package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts +48 -0
- package/src/engine/physics/narrowphase/sphere_triangle_contact.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/sphere_triangle_contact.js +143 -0
- package/src/engine/physics/queries/overlap_shape.d.ts +51 -0
- package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -0
- package/src/engine/physics/queries/overlap_shape.js +183 -0
- package/src/engine/physics/queries/shape_cast.d.ts +56 -0
- package/src/engine/physics/queries/shape_cast.d.ts.map +1 -0
- package/src/engine/physics/queries/shape_cast.js +387 -0
- package/src/engine/physics/solver/solve_contacts.d.ts +116 -30
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +641 -223
- package/src/engine/physics/broadphase/aabb_transform_oriented.d.ts.map +0 -1
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts +0 -20
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.d.ts.map +0 -1
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_unmasked_legacy.js +0 -83
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Apply the world-frame inverse inertia tensor of a rigid body to a world-space
|
|
3
3
|
* vector and write the result.
|
|
4
4
|
*
|
|
5
|
-
* Body-frame inverse inertia is
|
|
6
|
-
* (
|
|
5
|
+
* Body-frame inverse inertia is supplied as a diagonal in principal axes
|
|
6
|
+
* (a Vector3-like with `.x .y .z`). World inverse inertia is
|
|
7
7
|
* `I_w⁻¹ = R · diag · R^T` where `R` is the body's orientation. We compute
|
|
8
8
|
* `result = R · diag · R^T · v` without materialising the full 3x3 matrix:
|
|
9
9
|
*
|
|
@@ -17,21 +17,26 @@
|
|
|
17
17
|
* Sphere short-circuit: if the inverse inertia is isotropic (ix === iy === iz),
|
|
18
18
|
* the rotation cancels and `result = ix * v`. Skip the trig and save the work.
|
|
19
19
|
*
|
|
20
|
+
* Decoupled from RigidBody / Transform on purpose — callers pass only what
|
|
21
|
+
* is actually read. Lets `compute_penetration` and other standalone
|
|
22
|
+
* geometry helpers reuse this without manufacturing a body.
|
|
23
|
+
*
|
|
20
24
|
* @param {number[]|Float64Array} result length >= 3
|
|
21
25
|
* @param {number} result_offset
|
|
22
|
-
* @param {
|
|
23
|
-
*
|
|
26
|
+
* @param {{x: number, y: number, z: number}} inv_inertia_local
|
|
27
|
+
* Body-frame inverse inertia diagonal (typically `rb.inverseInertiaLocal`).
|
|
28
|
+
* @param {{x: number, y: number, z: number, w: number}} rotation
|
|
29
|
+
* Body orientation as a unit quaternion (typically `transform.rotation`).
|
|
24
30
|
* @param {number} vx
|
|
25
31
|
* @param {number} vy
|
|
26
32
|
* @param {number} vz
|
|
27
33
|
*/
|
|
28
34
|
export function world_inverse_inertia_apply(
|
|
29
35
|
result, result_offset,
|
|
30
|
-
|
|
36
|
+
inv_inertia_local, rotation,
|
|
31
37
|
vx, vy, vz
|
|
32
38
|
) {
|
|
33
|
-
const
|
|
34
|
-
const ix = ii.x, iy = ii.y, iz = ii.z;
|
|
39
|
+
const ix = inv_inertia_local.x, iy = inv_inertia_local.y, iz = inv_inertia_local.z;
|
|
35
40
|
|
|
36
41
|
if (ix === iy && iy === iz) {
|
|
37
42
|
// Isotropic — rotation cancels.
|
|
@@ -41,39 +46,32 @@ export function world_inverse_inertia_apply(
|
|
|
41
46
|
return;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
const
|
|
45
|
-
const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
|
|
49
|
+
const qx = rotation.x, qy = rotation.y, qz = rotation.z, qw = rotation.w;
|
|
46
50
|
|
|
47
51
|
// Step 1: v_body = R^T · v. R^T corresponds to applying the conjugate
|
|
48
|
-
// quaternion (-qx, -qy, -qz, qw).
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const tw = -cx * vx - cy * vy - cz * vz;
|
|
60
|
-
// v_body = t · (c*) where c* = (qx, qy, qz, qw)
|
|
61
|
-
const vbx = tx * qw + tw * qx + ty * qz - tz * qy;
|
|
62
|
-
const vby = ty * qw + tw * qy + tz * qx - tx * qz;
|
|
63
|
-
const vbz = tz * qw + tw * qz + tx * qy - ty * qx;
|
|
52
|
+
// quaternion (-qx, -qy, -qz, qw). Inlined for V8 inliner — see
|
|
53
|
+
// PosedShape.support and core/geom/vec3/v3_quat3_apply_inverse.js
|
|
54
|
+
// for the canonical form.
|
|
55
|
+
const cx = -qx, cy = -qy, cz = -qz;
|
|
56
|
+
const tx = qw * vx + cy * vz - cz * vy;
|
|
57
|
+
const ty = qw * vy + cz * vx - cx * vz;
|
|
58
|
+
const tz = qw * vz + cx * vy - cy * vx;
|
|
59
|
+
const tw = -cx * vx - cy * vy - cz * vz;
|
|
60
|
+
const vbx = tx * qw + tw * qx + ty * qz - tz * qy;
|
|
61
|
+
const vby = ty * qw + tw * qy + tz * qx - tx * qz;
|
|
62
|
+
const vbz = tz * qw + tw * qz + tx * qy - ty * qx;
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
// Step 2: scale by the principal-frame diagonal.
|
|
65
|
+
const sx = vbx * ix;
|
|
66
|
+
const sy = vby * iy;
|
|
67
|
+
const sz = vbz * iz;
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
69
|
+
// Step 3: result = R · scaled = q · scaled · q*. Inlined likewise.
|
|
70
|
+
const ux = qw * sx + qy * sz - qz * sy;
|
|
71
|
+
const uy = qw * sy + qz * sx - qx * sz;
|
|
72
|
+
const uz = qw * sz + qx * sy - qy * sx;
|
|
73
|
+
const uw = -qx * sx - qy * sy - qz * sz;
|
|
74
|
+
result[result_offset] = ux * qw + uw * (-qx) + uy * (-qz) - uz * (-qy);
|
|
75
|
+
result[result_offset + 1] = uy * qw + uw * (-qy) + uz * (-qx) - ux * (-qz);
|
|
76
|
+
result[result_offset + 2] = uz * qw + uw * (-qz) + ux * (-qy) - uy * (-qx);
|
|
79
77
|
}
|
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Integrate `transform.position` and `transform.rotation` from the body's
|
|
3
|
-
* current linear and angular velocity over a step `dt`. Static bodies are
|
|
4
|
-
* touched.
|
|
3
|
+
* current linear and angular velocity over a step `dt`. Static bodies are
|
|
4
|
+
* not touched.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* The trailing six arguments are the body's *pseudo-velocity*: the
|
|
7
|
+
* position-pass output from the constraint solver (Catto split-impulse).
|
|
8
|
+
* Pseudo-velocity exists only inside the step — it's folded into the
|
|
9
|
+
* integration so the position update reflects depth correction, then
|
|
10
|
+
* implicitly discarded. The body's persistent `linearVelocity` /
|
|
11
|
+
* `angularVelocity` (which carry restitution + warm-start across steps)
|
|
12
|
+
* are never contaminated by it.
|
|
13
|
+
*
|
|
14
|
+
* Callers with no position-pass output should pass zeros for the six
|
|
15
|
+
* pseudo arguments — folding zero is free (one add per axis).
|
|
16
|
+
*
|
|
17
|
+
* KinematicPosition bodies are treated like Dynamic for the position
|
|
18
|
+
* update — if the gameplay code is driving them, their velocity is
|
|
19
|
+
* whatever the user wrote (typically zero); the step is effectively a
|
|
20
|
+
* no-op in that case. KinematicVelocity bodies advance under their
|
|
21
|
+
* user-set velocity.
|
|
10
22
|
*
|
|
11
23
|
* @param {RigidBody} rb
|
|
12
24
|
* @param {Transform} transform
|
|
13
25
|
* @param {number} dt
|
|
26
|
+
* @param {number} ps_lin_x pseudo-linear-velocity x (0 when no contacts)
|
|
27
|
+
* @param {number} ps_lin_y
|
|
28
|
+
* @param {number} ps_lin_z
|
|
29
|
+
* @param {number} ps_ang_x pseudo-angular-velocity x (0 when no contacts)
|
|
30
|
+
* @param {number} ps_ang_y
|
|
31
|
+
* @param {number} ps_ang_z
|
|
14
32
|
*/
|
|
15
|
-
export function integrate_position(rb: RigidBody, transform: Transform, dt: number): void;
|
|
33
|
+
export function integrate_position(rb: RigidBody, transform: Transform, dt: number, ps_lin_x: number, ps_lin_y: number, ps_lin_z: number, ps_ang_x: number, ps_ang_y: number, ps_ang_z: number): void;
|
|
16
34
|
//# sourceMappingURL=integrate_position.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrate_position.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/integration/integrate_position.js"],"names":[],"mappings":"AAKA
|
|
1
|
+
{"version":3,"file":"integrate_position.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/integration/integrate_position.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,4EARW,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,YACN,MAAM,QA2ChB"}
|
|
@@ -5,19 +5,41 @@ const scratch_q = new Float64Array(4);
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Integrate `transform.position` and `transform.rotation` from the body's
|
|
8
|
-
* current linear and angular velocity over a step `dt`. Static bodies are
|
|
9
|
-
* touched.
|
|
8
|
+
* current linear and angular velocity over a step `dt`. Static bodies are
|
|
9
|
+
* not touched.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* The trailing six arguments are the body's *pseudo-velocity*: the
|
|
12
|
+
* position-pass output from the constraint solver (Catto split-impulse).
|
|
13
|
+
* Pseudo-velocity exists only inside the step — it's folded into the
|
|
14
|
+
* integration so the position update reflects depth correction, then
|
|
15
|
+
* implicitly discarded. The body's persistent `linearVelocity` /
|
|
16
|
+
* `angularVelocity` (which carry restitution + warm-start across steps)
|
|
17
|
+
* are never contaminated by it.
|
|
18
|
+
*
|
|
19
|
+
* Callers with no position-pass output should pass zeros for the six
|
|
20
|
+
* pseudo arguments — folding zero is free (one add per axis).
|
|
21
|
+
*
|
|
22
|
+
* KinematicPosition bodies are treated like Dynamic for the position
|
|
23
|
+
* update — if the gameplay code is driving them, their velocity is
|
|
24
|
+
* whatever the user wrote (typically zero); the step is effectively a
|
|
25
|
+
* no-op in that case. KinematicVelocity bodies advance under their
|
|
26
|
+
* user-set velocity.
|
|
15
27
|
*
|
|
16
28
|
* @param {RigidBody} rb
|
|
17
29
|
* @param {Transform} transform
|
|
18
30
|
* @param {number} dt
|
|
31
|
+
* @param {number} ps_lin_x pseudo-linear-velocity x (0 when no contacts)
|
|
32
|
+
* @param {number} ps_lin_y
|
|
33
|
+
* @param {number} ps_lin_z
|
|
34
|
+
* @param {number} ps_ang_x pseudo-angular-velocity x (0 when no contacts)
|
|
35
|
+
* @param {number} ps_ang_y
|
|
36
|
+
* @param {number} ps_ang_z
|
|
19
37
|
*/
|
|
20
|
-
export function integrate_position(
|
|
38
|
+
export function integrate_position(
|
|
39
|
+
rb, transform, dt,
|
|
40
|
+
ps_lin_x, ps_lin_y, ps_lin_z,
|
|
41
|
+
ps_ang_x, ps_ang_y, ps_ang_z,
|
|
42
|
+
) {
|
|
21
43
|
if (rb.kind === BodyKind.Static) {
|
|
22
44
|
return;
|
|
23
45
|
}
|
|
@@ -25,22 +47,31 @@ export function integrate_position(rb, transform, dt) {
|
|
|
25
47
|
const lv = rb.linearVelocity;
|
|
26
48
|
const p = transform.position;
|
|
27
49
|
|
|
50
|
+
// Combined integration velocity: persistent + pseudo. The pseudo
|
|
51
|
+
// contribution exists only for this step and never lands in `lv`.
|
|
52
|
+
const vx = lv[0] + ps_lin_x;
|
|
53
|
+
const vy = lv[1] + ps_lin_y;
|
|
54
|
+
const vz = lv[2] + ps_lin_z;
|
|
55
|
+
|
|
28
56
|
// Direct reads via typed-array index; the write goes through .set() so
|
|
29
57
|
// Transform's onChanged subscribers (matrix recompose, parent/child sync,
|
|
30
58
|
// viewport position, fog-of-war reveal) fire once per body per step.
|
|
31
59
|
p.set(
|
|
32
|
-
p[0] +
|
|
33
|
-
p[1] +
|
|
34
|
-
p[2] +
|
|
60
|
+
p[0] + vx * dt,
|
|
61
|
+
p[1] + vy * dt,
|
|
62
|
+
p[2] + vz * dt
|
|
35
63
|
);
|
|
36
64
|
|
|
37
65
|
const av = rb.angularVelocity;
|
|
38
|
-
|
|
66
|
+
const wx = av[0] + ps_ang_x;
|
|
67
|
+
const wy = av[1] + ps_ang_y;
|
|
68
|
+
const wz = av[2] + ps_ang_z;
|
|
69
|
+
if (wx !== 0 || wy !== 0 || wz !== 0) {
|
|
39
70
|
const q = transform.rotation;
|
|
40
71
|
quat_integrate(
|
|
41
72
|
scratch_q,
|
|
42
73
|
q[0], q[1], q[2], q[3],
|
|
43
|
-
|
|
74
|
+
wx, wy, wz,
|
|
44
75
|
dt
|
|
45
76
|
);
|
|
46
77
|
q.set(scratch_q[0], scratch_q[1], scratch_q[2], scratch_q[3]);
|
|
@@ -22,4 +22,34 @@
|
|
|
22
22
|
* @param {number} dt step size in seconds
|
|
23
23
|
*/
|
|
24
24
|
export function integrate_velocity(rb: RigidBody, transform: Transform, gx: number, gy: number, gz: number, dt: number): void;
|
|
25
|
+
/**
|
|
26
|
+
* Apply the accumulated force / torque to velocity over a step `dt`, then
|
|
27
|
+
* zero the accumulators. Gravity and damping are NOT applied here.
|
|
28
|
+
*
|
|
29
|
+
* The "once per outer step" half of the TGS integrator: a user force is a
|
|
30
|
+
* per-frame budget that must land in full exactly once, independent of
|
|
31
|
+
* substep count. Gravity is the continuous field re-applied every substep
|
|
32
|
+
* by {@link integrate_velocity_gravity}.
|
|
33
|
+
*
|
|
34
|
+
* @param {RigidBody} rb
|
|
35
|
+
* @param {Transform} transform used to rotate body-frame inertia into world
|
|
36
|
+
* @param {number} dt full outer-step size in seconds
|
|
37
|
+
*/
|
|
38
|
+
export function integrate_velocity_forces(rb: RigidBody, transform: Transform, dt: number): void;
|
|
39
|
+
/**
|
|
40
|
+
* Apply gravity and velocity damping over a (sub)step `dt`. Does NOT touch
|
|
41
|
+
* the force / torque accumulators (consumed once by
|
|
42
|
+
* {@link integrate_velocity_forces}).
|
|
43
|
+
*
|
|
44
|
+
* The "every substep" half of the TGS integrator. Per substep the body sees
|
|
45
|
+
* only `g·h` of gravity, which the per-substep contact warm-start + solve
|
|
46
|
+
* cancels exactly — keeping a resting stack at zero velocity. Damping is the
|
|
47
|
+
* stable implicit decay `v *= 1/(1 + d·dt)` applied at the substep `dt`.
|
|
48
|
+
*
|
|
49
|
+
* @param {RigidBody} rb
|
|
50
|
+
* @param {Transform} transform (unused; signature symmetry with the family)
|
|
51
|
+
* @param {number} gx @param {number} gy @param {number} gz world gravity
|
|
52
|
+
* @param {number} dt sub-step size in seconds
|
|
53
|
+
*/
|
|
54
|
+
export function integrate_velocity_gravity(rb: RigidBody, transform: Transform, gx: number, gy: number, gz: number, dt: number): void;
|
|
25
55
|
//# sourceMappingURL=integrate_velocity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrate_velocity.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/integration/integrate_velocity.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,4EALW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAoDhB"}
|
|
1
|
+
{"version":3,"file":"integrate_velocity.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/integration/integrate_velocity.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,4EALW,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,QAoDhB;AAED;;;;;;;;;;;;GAYG;AACH,mFAFW,MAAM,QA6BhB;AAED;;;;;;;;;;;;;;GAcG;AACH,oFAHW,MAAM,MAAa,MAAM,MAAa,MAAM,MAC5C,MAAM,QAwBhB"}
|
|
@@ -60,7 +60,7 @@ export function integrate_velocity(rb, transform, gx, gy, gz, dt) {
|
|
|
60
60
|
let avy = av[1];
|
|
61
61
|
let avz = av[2];
|
|
62
62
|
if (at[0] !== 0 || at[1] !== 0 || at[2] !== 0) {
|
|
63
|
-
world_inverse_inertia_apply(scratch_angular, 0, rb, transform, at[0], at[1], at[2]);
|
|
63
|
+
world_inverse_inertia_apply(scratch_angular, 0, rb.inverseInertiaLocal, transform.rotation, at[0], at[1], at[2]);
|
|
64
64
|
avx += scratch_angular[0] * dt;
|
|
65
65
|
avy += scratch_angular[1] * dt;
|
|
66
66
|
avz += scratch_angular[2] * dt;
|
|
@@ -77,3 +77,84 @@ export function integrate_velocity(rb, transform, gx, gy, gz, dt) {
|
|
|
77
77
|
af[0] = 0; af[1] = 0; af[2] = 0;
|
|
78
78
|
at[0] = 0; at[1] = 0; at[2] = 0;
|
|
79
79
|
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Apply the accumulated force / torque to velocity over a step `dt`, then
|
|
83
|
+
* zero the accumulators. Gravity and damping are NOT applied here.
|
|
84
|
+
*
|
|
85
|
+
* The "once per outer step" half of the TGS integrator: a user force is a
|
|
86
|
+
* per-frame budget that must land in full exactly once, independent of
|
|
87
|
+
* substep count. Gravity is the continuous field re-applied every substep
|
|
88
|
+
* by {@link integrate_velocity_gravity}.
|
|
89
|
+
*
|
|
90
|
+
* @param {RigidBody} rb
|
|
91
|
+
* @param {Transform} transform used to rotate body-frame inertia into world
|
|
92
|
+
* @param {number} dt full outer-step size in seconds
|
|
93
|
+
*/
|
|
94
|
+
export function integrate_velocity_forces(rb, transform, dt) {
|
|
95
|
+
const af = rb.accumulatedForce;
|
|
96
|
+
const at = rb.accumulatedTorque;
|
|
97
|
+
|
|
98
|
+
if (rb.kind !== BodyKind.Dynamic) {
|
|
99
|
+
af[0] = 0; af[1] = 0; af[2] = 0;
|
|
100
|
+
at[0] = 0; at[1] = 0; at[2] = 0;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const inv_m = rb.mass > 0 ? 1 / rb.mass : 0;
|
|
105
|
+
|
|
106
|
+
const lv = rb.linearVelocity;
|
|
107
|
+
lv[0] += af[0] * inv_m * dt;
|
|
108
|
+
lv[1] += af[1] * inv_m * dt;
|
|
109
|
+
lv[2] += af[2] * inv_m * dt;
|
|
110
|
+
|
|
111
|
+
if (at[0] !== 0 || at[1] !== 0 || at[2] !== 0) {
|
|
112
|
+
world_inverse_inertia_apply(scratch_angular, 0, rb.inverseInertiaLocal, transform.rotation, at[0], at[1], at[2]);
|
|
113
|
+
const av = rb.angularVelocity;
|
|
114
|
+
av[0] += scratch_angular[0] * dt;
|
|
115
|
+
av[1] += scratch_angular[1] * dt;
|
|
116
|
+
av[2] += scratch_angular[2] * dt;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
af[0] = 0; af[1] = 0; af[2] = 0;
|
|
120
|
+
at[0] = 0; at[1] = 0; at[2] = 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Apply gravity and velocity damping over a (sub)step `dt`. Does NOT touch
|
|
125
|
+
* the force / torque accumulators (consumed once by
|
|
126
|
+
* {@link integrate_velocity_forces}).
|
|
127
|
+
*
|
|
128
|
+
* The "every substep" half of the TGS integrator. Per substep the body sees
|
|
129
|
+
* only `g·h` of gravity, which the per-substep contact warm-start + solve
|
|
130
|
+
* cancels exactly — keeping a resting stack at zero velocity. Damping is the
|
|
131
|
+
* stable implicit decay `v *= 1/(1 + d·dt)` applied at the substep `dt`.
|
|
132
|
+
*
|
|
133
|
+
* @param {RigidBody} rb
|
|
134
|
+
* @param {Transform} transform (unused; signature symmetry with the family)
|
|
135
|
+
* @param {number} gx @param {number} gy @param {number} gz world gravity
|
|
136
|
+
* @param {number} dt sub-step size in seconds
|
|
137
|
+
*/
|
|
138
|
+
export function integrate_velocity_gravity(rb, transform, gx, gy, gz, dt) {
|
|
139
|
+
if (rb.kind !== BodyKind.Dynamic) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const gs = rb.gravityScale;
|
|
144
|
+
const lv = rb.linearVelocity;
|
|
145
|
+
let lvx = lv[0] + gx * gs * dt;
|
|
146
|
+
let lvy = lv[1] + gy * gs * dt;
|
|
147
|
+
let lvz = lv[2] + gz * gs * dt;
|
|
148
|
+
|
|
149
|
+
if (rb.linearDamping > 0) {
|
|
150
|
+
const k = 1 / (1 + rb.linearDamping * dt);
|
|
151
|
+
lvx *= k; lvy *= k; lvz *= k;
|
|
152
|
+
}
|
|
153
|
+
lv[0] = lvx; lv[1] = lvy; lv[2] = lvz;
|
|
154
|
+
|
|
155
|
+
if (rb.angularDamping > 0) {
|
|
156
|
+
const av = rb.angularVelocity;
|
|
157
|
+
const k = 1 / (1 + rb.angularDamping * dt);
|
|
158
|
+
av[0] *= k; av[1] *= k; av[2] *= k;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -45,14 +45,6 @@ export class PosedShape extends AbstractShape3D {
|
|
|
45
45
|
z: number;
|
|
46
46
|
w: number;
|
|
47
47
|
}): void;
|
|
48
|
-
/**
|
|
49
|
-
* @param {number[]|Float32Array|Float64Array} result
|
|
50
|
-
* @param {number} result_offset
|
|
51
|
-
* @param {number} dx world-space query direction x (unit)
|
|
52
|
-
* @param {number} dy world-space query direction y
|
|
53
|
-
* @param {number} dz world-space query direction z
|
|
54
|
-
*/
|
|
55
|
-
support(result: number[] | Float32Array | Float64Array, result_offset: number, dx: number, dy: number, dz: number): void;
|
|
56
48
|
compute_bounding_box(result: any): void;
|
|
57
49
|
}
|
|
58
50
|
import { AbstractShape3D } from "../../../core/geom/3d/shape/AbstractShape3D.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PosedShape.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/PosedShape.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAKQ,mCAAmC;IACnC,OADW,eAAe,GAAC,IAAI,CACd;IAEjB,WAAW;IAAE,WAAW;IAAE,WAAW;IACrC,WAAW;IAAE,WAAW;IAAE,WAAW;IAAE,WAAW;IAGtD;;;;;;;OAOG;IACH,aAJW,eAAe,YACf,UAAQ;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,YACpC,aAAW;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAM1D;
|
|
1
|
+
{"version":3,"file":"PosedShape.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/PosedShape.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAKQ,mCAAmC;IACnC,OADW,eAAe,GAAC,IAAI,CACd;IAEjB,WAAW;IAAE,WAAW;IAAE,WAAW;IACrC,WAAW;IAAE,WAAW;IAAE,WAAW;IAAE,WAAW;IAGtD;;;;;;;OAOG;IACH,aAJW,eAAe,YACf,UAAQ;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,YACpC,aAAW;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAM1D;IAgDD,wCASC;CACJ;gCA1G+B,gDAAgD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { aabb3_transform_oriented } from "../../../core/geom/3d/aabb/aabb3_transform_oriented.js";
|
|
1
2
|
import { AbstractShape3D } from "../../../core/geom/3d/shape/AbstractShape3D.js";
|
|
2
|
-
import { aabb_transform_oriented } from "../broadphase/aabb_transform_oriented.js";
|
|
3
3
|
|
|
4
4
|
const scratch_local = new Float64Array(3);
|
|
5
5
|
const scratch_local_aabb = new Float64Array(6);
|
|
@@ -57,49 +57,47 @@ export class PosedShape extends AbstractShape3D {
|
|
|
57
57
|
* @param {number} dz world-space query direction z
|
|
58
58
|
*/
|
|
59
59
|
support(result, result_offset, dx, dy, dz) {
|
|
60
|
-
//
|
|
61
|
-
//
|
|
60
|
+
// Inline q·v·q* math: PosedShape.support is the hottest GJK call
|
|
61
|
+
// (twice per iteration of the body-level fallback, once per
|
|
62
|
+
// triangle for concave dispatch). V8 declines to inline
|
|
63
|
+
// v3_quat3_apply at 9-arg call sites, so the math is repeated
|
|
64
|
+
// inline here at the cost of ~7 extra lines per direction.
|
|
65
|
+
// See core/geom/vec3/v3_quat3_apply.js for the canonical form
|
|
66
|
+
// — this is a literal expansion of it.
|
|
62
67
|
const qx = this.qx, qy = this.qy, qz = this.qz, qw = this.qw;
|
|
63
68
|
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
|
|
69
|
+
// Rotate world direction into body frame via the conjugate
|
|
70
|
+
// quaternion: v_local = q* · v_world · q. Conjugate xyz are
|
|
71
|
+
// negated (cx, cy, cz below).
|
|
72
|
+
const tdx = qw * dx - qy * dz + qz * dy;
|
|
73
|
+
const tdy = qw * dy - qz * dx + qx * dz;
|
|
74
|
+
const tdz = qw * dz - qx * dy + qy * dx;
|
|
75
|
+
const tdw = qx * dx + qy * dy + qz * dz;
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const tz = qw * dz + cx * dy - cy * dx;
|
|
72
|
-
const tw = -cx * dx - cy * dy - cz * dz;
|
|
73
|
-
|
|
74
|
-
// result_local = t · c^-1; conjugate of c is (-cx,-cy,-cz,qw) = (qx,qy,qz,qw) = original q
|
|
75
|
-
const ldx = tx * qw + tw * (-cx) + ty * (-cz) - tz * (-cy);
|
|
76
|
-
const ldy = ty * qw + tw * (-cy) + tz * (-cx) - tx * (-cz);
|
|
77
|
-
const ldz = tz * qw + tw * (-cz) + tx * (-cy) - ty * (-cx);
|
|
77
|
+
const ldx = tdx * qw + tdw * qx + tdy * qz - tdz * qy;
|
|
78
|
+
const ldy = tdy * qw + tdw * qy + tdz * qx - tdx * qz;
|
|
79
|
+
const ldz = tdz * qw + tdw * qz + tdx * qy - tdy * qx;
|
|
78
80
|
|
|
79
81
|
// Ask the local shape for its support point in body-local space.
|
|
80
82
|
this.shape.support(scratch_local, 0, ldx, ldy, ldz);
|
|
81
83
|
|
|
82
|
-
// Rotate
|
|
84
|
+
// Rotate the body-local support point back to world: v_world =
|
|
85
|
+
// q · v_local · q*.
|
|
83
86
|
const lsx = scratch_local[0], lsy = scratch_local[1], lsz = scratch_local[2];
|
|
84
87
|
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
const iw = -qx * lsx - qy * lsy - qz * lsz;
|
|
90
|
-
|
|
91
|
-
const wx = ix * qw + iw * (-qx) + iy * (-qz) - iz * (-qy);
|
|
92
|
-
const wy = iy * qw + iw * (-qy) + iz * (-qx) - ix * (-qz);
|
|
93
|
-
const wz = iz * qw + iw * (-qz) + ix * (-qy) - iy * (-qx);
|
|
88
|
+
const tsx = qw * lsx + qy * lsz - qz * lsy;
|
|
89
|
+
const tsy = qw * lsy + qz * lsx - qx * lsz;
|
|
90
|
+
const tsz = qw * lsz + qx * lsy - qy * lsx;
|
|
91
|
+
const tsw = -qx * lsx - qy * lsy - qz * lsz;
|
|
94
92
|
|
|
95
|
-
result[result_offset]
|
|
96
|
-
result[result_offset + 1] =
|
|
97
|
-
result[result_offset + 2] =
|
|
93
|
+
result[result_offset] = tsx * qw - tsw * qx - tsy * qz + tsz * qy + this.px;
|
|
94
|
+
result[result_offset + 1] = tsy * qw - tsw * qy - tsz * qx + tsx * qz + this.py;
|
|
95
|
+
result[result_offset + 2] = tsz * qw - tsw * qz - tsx * qy + tsy * qx + this.pz;
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
compute_bounding_box(result) {
|
|
101
99
|
this.shape.compute_bounding_box(scratch_local_aabb);
|
|
102
|
-
|
|
100
|
+
aabb3_transform_oriented(
|
|
103
101
|
result, 0,
|
|
104
102
|
scratch_local_aabb[0], scratch_local_aabb[1], scratch_local_aabb[2],
|
|
105
103
|
scratch_local_aabb[3], scratch_local_aabb[4], scratch_local_aabb[5],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"box_box_manifold.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/box_box_manifold.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"box_box_manifold.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/narrowphase/box_box_manifold.js"],"names":[],"mappings":"AA+HA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,sCAvBW,MAAM,EAAE,GAAC,YAAY,MACrB,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,OACN,MAAM,GACJ,OAAO,CA0anB;AAvhBD;;;GAGG;AACH,iCAFU,MAAM,CAEoD"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { line3_closest_points_segment_segment } from "../../../core/geom/3d/line/line3_closest_points_segment_segment.js";
|
|
2
|
+
import { quat3_to_matrix3 } from "../../../core/geom/3d/quaternion/quat3_to_matrix3.js";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Multi-point manifold construction for two oriented bounding boxes.
|
|
3
6
|
*
|
|
@@ -61,16 +64,11 @@ const clipped_uv_out = new Float64Array(8 * 2);
|
|
|
61
64
|
// Stride 4 per candidate: x, y, z, depth.
|
|
62
65
|
const candidates = new Float64Array(8 * 4);
|
|
63
66
|
|
|
64
|
-
//
|
|
67
|
+
// Output of line3_closest_points_segment_segment for the edge-cross
|
|
68
|
+
// SAT-winner path: (s, t) parameters along the two edges.
|
|
69
|
+
const scratch_edge_st = new Float64Array(2);
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
const xx = qx * qx, yy = qy * qy, zz = qz * qz;
|
|
68
|
-
const xy = qx * qy, xz = qx * qz, yz = qy * qz;
|
|
69
|
-
const wx = qw * qx, wy = qw * qy, wz = qw * qz;
|
|
70
|
-
out[off] = 1 - 2 * (yy + zz); out[off + 1] = 2 * (xy + wz); out[off + 2] = 2 * (xz - wy);
|
|
71
|
-
out[off + 3] = 2 * (xy - wz); out[off + 4] = 1 - 2 * (xx + zz); out[off + 5] = 2 * (yz + wx);
|
|
72
|
-
out[off + 6] = 2 * (xz + wy); out[off + 7] = 2 * (yz - wx); out[off + 8] = 1 - 2 * (xx + yy);
|
|
73
|
-
}
|
|
71
|
+
// --- helpers ---------------------------------------------------------------
|
|
74
72
|
|
|
75
73
|
function projected_half_extent(axes, off, hx, hy, hz, lx, ly, lz) {
|
|
76
74
|
const px = lx * axes[off] + ly * axes[off + 1] + lz * axes[off + 2];
|
|
@@ -157,8 +155,8 @@ export function box_box_manifold(
|
|
|
157
155
|
ax, ay, az, aqx, aqy, aqz, aqw, ahx, ahy, ahz,
|
|
158
156
|
bx, by, bz, bqx, bqy, bqz, bqw, bhx, bhy, bhz
|
|
159
157
|
) {
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
quat3_to_matrix3(scratch_axes_a, 0, aqx, aqy, aqz, aqw);
|
|
159
|
+
quat3_to_matrix3(scratch_axes_b, 0, bqx, bqy, bqz, bqw);
|
|
162
160
|
|
|
163
161
|
const ta = scratch_axes_a;
|
|
164
162
|
const tb = scratch_axes_b;
|
|
@@ -217,14 +215,112 @@ export function box_box_manifold(
|
|
|
217
215
|
const nx = best_nx, ny = best_ny, nz = best_nz;
|
|
218
216
|
out[0] = nx; out[1] = ny; out[2] = nz;
|
|
219
217
|
|
|
220
|
-
// ---- Edge-cross axis:
|
|
218
|
+
// ---- Edge-cross axis: closest-pair on the two involved edges ----
|
|
219
|
+
//
|
|
220
|
+
// When SAT identifies an edge-edge separating axis (source 6..14 =
|
|
221
|
+
// 6 + i*3 + j, where `i` is box A's local edge-axis index and
|
|
222
|
+
// `j` is box B's), the contact happens where one specific edge of
|
|
223
|
+
// A crosses (or is closest to) one specific edge of B. The earlier
|
|
224
|
+
// body-centre-midpoint fallback was sufficient for "we know they
|
|
225
|
+
// collide" but produced lever arms that confused the solver — for
|
|
226
|
+
// skewed-box stacks this led to slow drift.
|
|
227
|
+
//
|
|
228
|
+
// Procedure:
|
|
229
|
+
// 1. Decode (i, j) from `best_source`.
|
|
230
|
+
// 2. Among box A's 4 parallel edges along axis i, pick the one
|
|
231
|
+
// whose corner is most in the −n direction (closest to B).
|
|
232
|
+
// 3. Same for box B with +n direction.
|
|
233
|
+
// 4. `line3_closest_points_segment_segment` returns (s, t)
|
|
234
|
+
// parameters; reconstruct the world contact on each edge.
|
|
221
235
|
if (best_source >= 6) {
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
const
|
|
236
|
+
const ax_src = best_source - 6;
|
|
237
|
+
const i_a = (ax_src / 3) | 0;
|
|
238
|
+
const j_b = ax_src - i_a * 3;
|
|
239
|
+
|
|
240
|
+
// Edge directions in world.
|
|
241
|
+
const edge_a_dx = ta[i_a * 3];
|
|
242
|
+
const edge_a_dy = ta[i_a * 3 + 1];
|
|
243
|
+
const edge_a_dz = ta[i_a * 3 + 2];
|
|
244
|
+
const edge_b_dx = tb[j_b * 3];
|
|
245
|
+
const edge_b_dy = tb[j_b * 3 + 1];
|
|
246
|
+
const edge_b_dz = tb[j_b * 3 + 2];
|
|
247
|
+
|
|
248
|
+
// Edge half-extents (along the chosen axis).
|
|
249
|
+
const edge_a_half = i_a === 0 ? ahx : (i_a === 1 ? ahy : ahz);
|
|
250
|
+
const edge_b_half = j_b === 0 ? bhx : (j_b === 1 ? bhy : bhz);
|
|
251
|
+
|
|
252
|
+
// Perpendicular axes (the other two) and their half-extents.
|
|
253
|
+
let u_a_idx, v_a_idx;
|
|
254
|
+
if (i_a === 0) { u_a_idx = 1; v_a_idx = 2; }
|
|
255
|
+
else if (i_a === 1) { u_a_idx = 2; v_a_idx = 0; }
|
|
256
|
+
else { u_a_idx = 0; v_a_idx = 1; }
|
|
257
|
+
const u_a_x = ta[u_a_idx * 3], u_a_y = ta[u_a_idx * 3 + 1], u_a_z = ta[u_a_idx * 3 + 2];
|
|
258
|
+
const v_a_x = ta[v_a_idx * 3], v_a_y = ta[v_a_idx * 3 + 1], v_a_z = ta[v_a_idx * 3 + 2];
|
|
259
|
+
const half_u_a = u_a_idx === 0 ? ahx : (u_a_idx === 1 ? ahy : ahz);
|
|
260
|
+
const half_v_a = v_a_idx === 0 ? ahx : (v_a_idx === 1 ? ahy : ahz);
|
|
261
|
+
|
|
262
|
+
let u_b_idx, v_b_idx;
|
|
263
|
+
if (j_b === 0) { u_b_idx = 1; v_b_idx = 2; }
|
|
264
|
+
else if (j_b === 1) { u_b_idx = 2; v_b_idx = 0; }
|
|
265
|
+
else { u_b_idx = 0; v_b_idx = 1; }
|
|
266
|
+
const u_b_x = tb[u_b_idx * 3], u_b_y = tb[u_b_idx * 3 + 1], u_b_z = tb[u_b_idx * 3 + 2];
|
|
267
|
+
const v_b_x = tb[v_b_idx * 3], v_b_y = tb[v_b_idx * 3 + 1], v_b_z = tb[v_b_idx * 3 + 2];
|
|
268
|
+
const half_u_b = u_b_idx === 0 ? bhx : (u_b_idx === 1 ? bhy : bhz);
|
|
269
|
+
const half_v_b = v_b_idx === 0 ? bhx : (v_b_idx === 1 ? bhy : bhz);
|
|
270
|
+
|
|
271
|
+
// The contact normal `n` (= best_n) points B → A. From A's
|
|
272
|
+
// perspective B is in the −n direction; pick the A-corner most
|
|
273
|
+
// in that direction. From B's perspective A is in +n; pick the
|
|
274
|
+
// B-corner most in +n.
|
|
275
|
+
const minus_n_dot_u_a = -(nx * u_a_x + ny * u_a_y + nz * u_a_z);
|
|
276
|
+
const minus_n_dot_v_a = -(nx * v_a_x + ny * v_a_y + nz * v_a_z);
|
|
277
|
+
const u_sign_a = minus_n_dot_u_a >= 0 ? 1 : -1;
|
|
278
|
+
const v_sign_a = minus_n_dot_v_a >= 0 ? 1 : -1;
|
|
279
|
+
|
|
280
|
+
const plus_n_dot_u_b = nx * u_b_x + ny * u_b_y + nz * u_b_z;
|
|
281
|
+
const plus_n_dot_v_b = nx * v_b_x + ny * v_b_y + nz * v_b_z;
|
|
282
|
+
const u_sign_b = plus_n_dot_u_b >= 0 ? 1 : -1;
|
|
283
|
+
const v_sign_b = plus_n_dot_v_b >= 0 ? 1 : -1;
|
|
284
|
+
|
|
285
|
+
// Box-A edge centre = A_centre + u_sign_a * half_u_a * u_a
|
|
286
|
+
// + v_sign_a * half_v_a * v_a.
|
|
287
|
+
const corner_a_cx = ax + u_a_x * u_sign_a * half_u_a + v_a_x * v_sign_a * half_v_a;
|
|
288
|
+
const corner_a_cy = ay + u_a_y * u_sign_a * half_u_a + v_a_y * v_sign_a * half_v_a;
|
|
289
|
+
const corner_a_cz = az + u_a_z * u_sign_a * half_u_a + v_a_z * v_sign_a * half_v_a;
|
|
290
|
+
const edge_a_p1_x = corner_a_cx - edge_a_dx * edge_a_half;
|
|
291
|
+
const edge_a_p1_y = corner_a_cy - edge_a_dy * edge_a_half;
|
|
292
|
+
const edge_a_p1_z = corner_a_cz - edge_a_dz * edge_a_half;
|
|
293
|
+
const edge_a_p2_x = corner_a_cx + edge_a_dx * edge_a_half;
|
|
294
|
+
const edge_a_p2_y = corner_a_cy + edge_a_dy * edge_a_half;
|
|
295
|
+
const edge_a_p2_z = corner_a_cz + edge_a_dz * edge_a_half;
|
|
296
|
+
|
|
297
|
+
const corner_b_cx = bx + u_b_x * u_sign_b * half_u_b + v_b_x * v_sign_b * half_v_b;
|
|
298
|
+
const corner_b_cy = by + u_b_y * u_sign_b * half_u_b + v_b_y * v_sign_b * half_v_b;
|
|
299
|
+
const corner_b_cz = bz + u_b_z * u_sign_b * half_u_b + v_b_z * v_sign_b * half_v_b;
|
|
300
|
+
const edge_b_p1_x = corner_b_cx - edge_b_dx * edge_b_half;
|
|
301
|
+
const edge_b_p1_y = corner_b_cy - edge_b_dy * edge_b_half;
|
|
302
|
+
const edge_b_p1_z = corner_b_cz - edge_b_dz * edge_b_half;
|
|
303
|
+
const edge_b_p2_x = corner_b_cx + edge_b_dx * edge_b_half;
|
|
304
|
+
const edge_b_p2_y = corner_b_cy + edge_b_dy * edge_b_half;
|
|
305
|
+
const edge_b_p2_z = corner_b_cz + edge_b_dz * edge_b_half;
|
|
306
|
+
|
|
307
|
+
line3_closest_points_segment_segment(
|
|
308
|
+
scratch_edge_st,
|
|
309
|
+
edge_a_p1_x, edge_a_p1_y, edge_a_p1_z, edge_a_p2_x, edge_a_p2_y, edge_a_p2_z,
|
|
310
|
+
edge_b_p1_x, edge_b_p1_y, edge_b_p1_z, edge_b_p2_x, edge_b_p2_y, edge_b_p2_z
|
|
311
|
+
);
|
|
312
|
+
const s = scratch_edge_st[0];
|
|
313
|
+
const t = scratch_edge_st[1];
|
|
314
|
+
const contact_a_x = edge_a_p1_x + s * (edge_a_p2_x - edge_a_p1_x);
|
|
315
|
+
const contact_a_y = edge_a_p1_y + s * (edge_a_p2_y - edge_a_p1_y);
|
|
316
|
+
const contact_a_z = edge_a_p1_z + s * (edge_a_p2_z - edge_a_p1_z);
|
|
317
|
+
const contact_b_x = edge_b_p1_x + t * (edge_b_p2_x - edge_b_p1_x);
|
|
318
|
+
const contact_b_y = edge_b_p1_y + t * (edge_b_p2_y - edge_b_p1_y);
|
|
319
|
+
const contact_b_z = edge_b_p1_z + t * (edge_b_p2_z - edge_b_p1_z);
|
|
320
|
+
|
|
225
321
|
out[3] = 1;
|
|
226
|
-
out[4] =
|
|
227
|
-
out[7] =
|
|
322
|
+
out[4] = contact_a_x; out[5] = contact_a_y; out[6] = contact_a_z;
|
|
323
|
+
out[7] = contact_b_x; out[8] = contact_b_y; out[9] = contact_b_z;
|
|
228
324
|
out[10] = best_overlap;
|
|
229
325
|
return true;
|
|
230
326
|
}
|