@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
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { bvh_query_user_data_overlaps_aabb } from "../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js";
|
|
2
|
+
import { returnTrue } from "../../../core/function/returnTrue.js";
|
|
3
|
+
import { aabb3_transform_oriented } from "../../../core/geom/3d/aabb/aabb3_transform_oriented.js";
|
|
4
|
+
import { body_id_index } from "../body/BodyStorage.js";
|
|
5
|
+
import { gjk } from "../gjk/gjk.js";
|
|
6
|
+
import { mpr } from "../gjk/mpr.js";
|
|
7
|
+
import { PosedShape } from "../narrowphase/PosedShape.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Bisection halts when the search interval is below this fraction of
|
|
11
|
+
* the sweep length. With `MAX_BISECTION = 32` and a unit-length sweep
|
|
12
|
+
* the achieved precision is ≈ 1 / 2³² (well below any practical
|
|
13
|
+
* world-scale tolerance), but we cap on relative tolerance so a
|
|
14
|
+
* 10 m sweep doesn't insist on sub-micron precision.
|
|
15
|
+
* @type {number}
|
|
16
|
+
*/
|
|
17
|
+
const TOI_TOLERANCE = 1e-4;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Maximum bisection iterations. `log2(1 / TOI_TOLERANCE)` is enough
|
|
21
|
+
* for any practical sweep; this is the hard upper bound to prevent
|
|
22
|
+
* pathological inputs (NaN ray, etc.) from hanging the query.
|
|
23
|
+
* @type {number}
|
|
24
|
+
*/
|
|
25
|
+
const MAX_BISECTION = 32;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Coarse linear-search resolution for finding *any* overlap moment
|
|
29
|
+
* along the per-candidate AABB-overlap interval (NOT the full sweep —
|
|
30
|
+
* see `aabb_overlap_interval` for the analytical narrowing that runs
|
|
31
|
+
* upstream). 32 substeps over the AABB-overlap window is dense enough
|
|
32
|
+
* for any sweep where the shape's smallest extent is on the order of
|
|
33
|
+
* its AABB's extent (true for spheres / boxes / capsules); the slab
|
|
34
|
+
* intersection keeps that interval small even for kilometre-scale
|
|
35
|
+
* sweeps, so this isn't the limit it would otherwise be.
|
|
36
|
+
* @type {number}
|
|
37
|
+
*/
|
|
38
|
+
const COARSE_STEPS = 32;
|
|
39
|
+
|
|
40
|
+
const swept_aabb = new Float64Array(6);
|
|
41
|
+
const local_aabb = new Float64Array(6);
|
|
42
|
+
const initial_aabb = new Float64Array(6);
|
|
43
|
+
const target_local_aabb = new Float64Array(6);
|
|
44
|
+
const target_world_aabb = new Float64Array(6);
|
|
45
|
+
|
|
46
|
+
// GJK simplex buffer (used to detect overlap during the bisection).
|
|
47
|
+
const simplex_buf = new Float64Array(12);
|
|
48
|
+
|
|
49
|
+
// Scratch for MPR's MTV output — same vec3 convention as EPA: direction
|
|
50
|
+
// is "A's interior into B" with the magnitude being the depth. We use
|
|
51
|
+
// MPR for the contact-normal recovery at the kiss point because it
|
|
52
|
+
// converges reliably on smooth-vs-smooth supports where EPA hits its
|
|
53
|
+
// iteration cap before tightening (sphere-vs-sphere shallow overlap).
|
|
54
|
+
const mpr_result = new Float64Array(3);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Long-lived PosedShape adapters for the swept shape and the
|
|
58
|
+
* candidate's collider. Both are re-bound per query — the swept one
|
|
59
|
+
* also gets its position field re-written every bisection step
|
|
60
|
+
* without re-running `setup()`, since shape and rotation are
|
|
61
|
+
* constant through the sweep.
|
|
62
|
+
*/
|
|
63
|
+
const swept_posed = new PosedShape();
|
|
64
|
+
const candidate_posed = new PosedShape();
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Buffer for the union of static-BVH and dynamic-BVH candidates that
|
|
68
|
+
* overlap the swept AABB. Grows by doubling on the rare overflow.
|
|
69
|
+
* @type {Uint32Array}
|
|
70
|
+
*/
|
|
71
|
+
let scratch_candidates = new Uint32Array(64);
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Sweep a convex shape along a ray and find the first body it would
|
|
75
|
+
* hit. Used by character controllers (sweep a capsule along intended
|
|
76
|
+
* movement to find blockers), high-speed projectile movement (avoid
|
|
77
|
+
* tunnelling without paying for full per-body CCD), and any kinematic
|
|
78
|
+
* "where would this body end up if I tried to move it?" query.
|
|
79
|
+
*
|
|
80
|
+
* Pipeline:
|
|
81
|
+
* 1. Build the swept AABB: the shape's local-frame AABB rotated
|
|
82
|
+
* into world by `rotation`, translated to `ray.origin`, then
|
|
83
|
+
* stretched along `ray.direction * ray.tMax`.
|
|
84
|
+
* 2. Query both broadphase BVHs (static + dynamic) for leaves whose
|
|
85
|
+
* AABB overlaps the swept volume.
|
|
86
|
+
* 3. For each candidate, bisect the [0, best_t] interval for the
|
|
87
|
+
* smallest `t` at which the swept shape overlaps the candidate's
|
|
88
|
+
* collider. GJK on each midpoint.
|
|
89
|
+
*
|
|
90
|
+
* Picking `best_t` (rather than always running the full [0, tMax]
|
|
91
|
+
* bisection) is the early-termination optimisation: once we have a
|
|
92
|
+
* hit at some t, no later candidate can produce a smaller TOI by
|
|
93
|
+
* being checked at its full [0, tMax] interval.
|
|
94
|
+
*
|
|
95
|
+
* Output on hit:
|
|
96
|
+
* - `result.t` — sweep distance to impact (in the same units as
|
|
97
|
+
* `ray.direction`'s magnitude; for a unit-direction ray, this is
|
|
98
|
+
* metres).
|
|
99
|
+
* - `result.position` — `ray.origin + t * ray.direction`, i.e. the
|
|
100
|
+
* centre of the swept shape at the moment of first contact. NOT
|
|
101
|
+
* a point on the target's surface; that would need narrowphase
|
|
102
|
+
* refinement which the broadphase-only architecture doesn't have
|
|
103
|
+
* wired up yet.
|
|
104
|
+
* - `result.normal` — target surface's outward normal at the kiss
|
|
105
|
+
* point (unit length), computed by running GJK + EPA against the
|
|
106
|
+
* just-overlapping configuration at the TOI. Falls back to
|
|
107
|
+
* `-ray.direction` on the rare case EPA degenerates (NaN / zero
|
|
108
|
+
* depth) — see comment near the EPA call.
|
|
109
|
+
* - `result.entity` / `result.body_id` — the hit body.
|
|
110
|
+
*
|
|
111
|
+
* Output on miss: untouched; same convention as `raycast`.
|
|
112
|
+
*
|
|
113
|
+
* @param {PhysicsSystem} system
|
|
114
|
+
* @param {Ray3} ray origin + unit direction + `tMax`
|
|
115
|
+
* @param {AbstractShape3D} shape shape being swept, in its local frame
|
|
116
|
+
* @param {{x:number,y:number,z:number,w:number}} rotation fixed orientation
|
|
117
|
+
* @param {PhysicsSurfacePoint} result populated on hit; untouched on miss
|
|
118
|
+
* @param {(entity:number, collider:Collider)=>boolean} [filter] mandatory in
|
|
119
|
+
* contract; defaults to {@link returnTrue}
|
|
120
|
+
* @returns {boolean}
|
|
121
|
+
*/
|
|
122
|
+
export function shape_cast(system, ray, shape, rotation, result, filter = returnTrue) {
|
|
123
|
+
const ox = ray.origin_x;
|
|
124
|
+
const oy = ray.origin_y;
|
|
125
|
+
const oz = ray.origin_z;
|
|
126
|
+
const dx = ray.direction_x;
|
|
127
|
+
const dy = ray.direction_y;
|
|
128
|
+
const dz = ray.direction_z;
|
|
129
|
+
const tMax = ray.tMax;
|
|
130
|
+
if (!(tMax > 0) || !Number.isFinite(tMax)) return false;
|
|
131
|
+
|
|
132
|
+
const rx = rotation.x, ry = rotation.y, rz = rotation.z, rw = rotation.w;
|
|
133
|
+
|
|
134
|
+
// ── 1. Swept AABB ──────────────────────────────────────────────
|
|
135
|
+
shape.compute_bounding_box(local_aabb);
|
|
136
|
+
// Rotation around ray.origin gives the shape's initial AABB in
|
|
137
|
+
// world space.
|
|
138
|
+
aabb3_transform_oriented(
|
|
139
|
+
initial_aabb, 0,
|
|
140
|
+
local_aabb[0], local_aabb[1], local_aabb[2],
|
|
141
|
+
local_aabb[3], local_aabb[4], local_aabb[5],
|
|
142
|
+
ox, oy, oz,
|
|
143
|
+
rx, ry, rz, rw
|
|
144
|
+
);
|
|
145
|
+
// Stretch by the sweep displacement. Positive direction components
|
|
146
|
+
// push the +face out; negative components push the −face out.
|
|
147
|
+
swept_aabb[0] = initial_aabb[0];
|
|
148
|
+
swept_aabb[1] = initial_aabb[1];
|
|
149
|
+
swept_aabb[2] = initial_aabb[2];
|
|
150
|
+
swept_aabb[3] = initial_aabb[3];
|
|
151
|
+
swept_aabb[4] = initial_aabb[4];
|
|
152
|
+
swept_aabb[5] = initial_aabb[5];
|
|
153
|
+
if (dx > 0) swept_aabb[3] += dx * tMax; else swept_aabb[0] += dx * tMax;
|
|
154
|
+
if (dy > 0) swept_aabb[4] += dy * tMax; else swept_aabb[1] += dy * tMax;
|
|
155
|
+
if (dz > 0) swept_aabb[5] += dz * tMax; else swept_aabb[2] += dz * tMax;
|
|
156
|
+
|
|
157
|
+
// ── 2. Broadphase: gather candidates from both trees ───────────
|
|
158
|
+
const n_static = bvh_query_user_data_overlaps_aabb(
|
|
159
|
+
scratch_candidates, 0, system.staticBvh, swept_aabb
|
|
160
|
+
);
|
|
161
|
+
const n_dynamic = bvh_query_user_data_overlaps_aabb(
|
|
162
|
+
scratch_candidates, n_static, system.dynamicBvh, swept_aabb
|
|
163
|
+
);
|
|
164
|
+
const n_total = n_static + n_dynamic;
|
|
165
|
+
if (n_total === 0) return false;
|
|
166
|
+
|
|
167
|
+
// ── 3. Narrowphase: per-candidate bisection ────────────────────
|
|
168
|
+
//
|
|
169
|
+
// Re-bind the swept shape's PosedShape once for shape + rotation;
|
|
170
|
+
// we update `px/py/pz` per bisection midpoint without rerunning
|
|
171
|
+
// setup (px/py/pz are public fields by contract).
|
|
172
|
+
swept_posed.shape = shape;
|
|
173
|
+
swept_posed.qx = rx; swept_posed.qy = ry; swept_posed.qz = rz; swept_posed.qw = rw;
|
|
174
|
+
|
|
175
|
+
let best_t = tMax;
|
|
176
|
+
let best_body_id = -1;
|
|
177
|
+
let best_entity = -1;
|
|
178
|
+
|
|
179
|
+
for (let i = 0; i < n_total; i++) {
|
|
180
|
+
const body_id = scratch_candidates[i];
|
|
181
|
+
const body_idx = body_id_index(body_id);
|
|
182
|
+
const entity = system.entityOf(body_id);
|
|
183
|
+
if (entity < 0) continue;
|
|
184
|
+
|
|
185
|
+
const collider = system.__primary_collider(body_idx);
|
|
186
|
+
if (collider === null) continue;
|
|
187
|
+
if (!filter(entity, collider)) continue;
|
|
188
|
+
|
|
189
|
+
const target_tr = system.__transforms[body_idx];
|
|
190
|
+
candidate_posed.setup(collider.shape, target_tr.position, target_tr.rotation);
|
|
191
|
+
|
|
192
|
+
// Already overlapping at t = 0? Return immediately — can't beat
|
|
193
|
+
// this, and the bisection's "no overlap at lo, overlap at hi"
|
|
194
|
+
// invariant doesn't hold.
|
|
195
|
+
swept_posed.px = ox; swept_posed.py = oy; swept_posed.pz = oz;
|
|
196
|
+
if (gjk(simplex_buf, swept_posed, candidate_posed)) {
|
|
197
|
+
best_t = 0;
|
|
198
|
+
best_body_id = body_id;
|
|
199
|
+
best_entity = entity;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ── Slab intersection: narrow the search interval analytically ─
|
|
204
|
+
//
|
|
205
|
+
// Compute the body's tight world AABB and intersect it with the
|
|
206
|
+
// swept shape's AABB sliding along the sweep direction. The
|
|
207
|
+
// result is the t-interval `[t_aabb_enter, t_aabb_exit]` during
|
|
208
|
+
// which the two AABBs overlap. Outside this interval the actual
|
|
209
|
+
// shapes can't overlap either (AABB is a superset of the
|
|
210
|
+
// shape), so we get to skip all of [0, t_aabb_enter) and
|
|
211
|
+
// (t_aabb_exit, best_t] without testing.
|
|
212
|
+
//
|
|
213
|
+
// This is the key to making `shapeCast` scale to long sweeps:
|
|
214
|
+
// a 1 km cast of a 1 m sphere against another 1 m sphere has an
|
|
215
|
+
// AABB-overlap window of ≈ 2 m (the sum of diameters along the
|
|
216
|
+
// sweep axis), reducing the coarse-step grid from a 30 m
|
|
217
|
+
// resolution (1000/32) to 6 cm (2/32).
|
|
218
|
+
collider.shape.compute_bounding_box(target_local_aabb);
|
|
219
|
+
aabb3_transform_oriented(
|
|
220
|
+
target_world_aabb, 0,
|
|
221
|
+
target_local_aabb[0], target_local_aabb[1], target_local_aabb[2],
|
|
222
|
+
target_local_aabb[3], target_local_aabb[4], target_local_aabb[5],
|
|
223
|
+
target_tr.position.x, target_tr.position.y, target_tr.position.z,
|
|
224
|
+
target_tr.rotation.x, target_tr.rotation.y, target_tr.rotation.z, target_tr.rotation.w
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
let t_aabb_enter = -Infinity;
|
|
228
|
+
let t_aabb_exit = Infinity;
|
|
229
|
+
let skip_candidate = false;
|
|
230
|
+
for (let ax = 0; ax < 3; ax++) {
|
|
231
|
+
const init_min = initial_aabb[ax];
|
|
232
|
+
const init_max = initial_aabb[ax + 3];
|
|
233
|
+
const body_min = target_world_aabb[ax];
|
|
234
|
+
const body_max = target_world_aabb[ax + 3];
|
|
235
|
+
const d_ax = ax === 0 ? dx : (ax === 1 ? dy : dz);
|
|
236
|
+
if (d_ax === 0) {
|
|
237
|
+
// Static along this axis: AABBs must overlap in their
|
|
238
|
+
// initial position or this candidate is unreachable.
|
|
239
|
+
if (init_max < body_min || init_min > body_max) {
|
|
240
|
+
skip_candidate = true;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
// swept_min(t) = init_min + d·t, swept_max(t) = init_max + d·t.
|
|
246
|
+
// Slab-enter: swept_max(t) = body_min → t = (body_min − init_max) / d
|
|
247
|
+
// Slab-exit: swept_min(t) = body_max → t = (body_max − init_min) / d
|
|
248
|
+
const t1 = (body_min - init_max) / d_ax;
|
|
249
|
+
const t2 = (body_max - init_min) / d_ax;
|
|
250
|
+
const lo = t1 < t2 ? t1 : t2;
|
|
251
|
+
const hi = t1 < t2 ? t2 : t1;
|
|
252
|
+
if (lo > t_aabb_enter) t_aabb_enter = lo;
|
|
253
|
+
if (hi < t_aabb_exit) t_aabb_exit = hi;
|
|
254
|
+
}
|
|
255
|
+
if (skip_candidate) continue;
|
|
256
|
+
if (t_aabb_enter > t_aabb_exit) continue;
|
|
257
|
+
|
|
258
|
+
// Clamp to the relevant t-window: [0, best_t]. Anything beyond
|
|
259
|
+
// best_t can't tighten the answer.
|
|
260
|
+
const t_start = t_aabb_enter > 0 ? t_aabb_enter : 0;
|
|
261
|
+
const t_end = t_aabb_exit < best_t ? t_aabb_exit : best_t;
|
|
262
|
+
if (t_start >= t_end) continue;
|
|
263
|
+
|
|
264
|
+
// Coarse-search within the narrowed interval to find any t for
|
|
265
|
+
// which the shapes overlap (their AABBs do by construction; the
|
|
266
|
+
// shapes themselves may not, e.g. two spheres passing alongside).
|
|
267
|
+
const step_dt = (t_end - t_start) / COARSE_STEPS;
|
|
268
|
+
let t_prev = t_start;
|
|
269
|
+
let t_hi = -1;
|
|
270
|
+
for (let s = 1; s <= COARSE_STEPS; s++) {
|
|
271
|
+
const t = t_start + s * step_dt;
|
|
272
|
+
swept_posed.px = ox + dx * t;
|
|
273
|
+
swept_posed.py = oy + dy * t;
|
|
274
|
+
swept_posed.pz = oz + dz * t;
|
|
275
|
+
if (gjk(simplex_buf, swept_posed, candidate_posed)) {
|
|
276
|
+
t_hi = t;
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
t_prev = t;
|
|
280
|
+
}
|
|
281
|
+
if (t_hi < 0) continue;
|
|
282
|
+
|
|
283
|
+
// Bisect [t_prev, t_hi]: invariant is `gjk(t_lo) === false` and
|
|
284
|
+
// `gjk(t_hi) === true`.
|
|
285
|
+
let t_lo = t_prev;
|
|
286
|
+
const stop_width = TOI_TOLERANCE * tMax;
|
|
287
|
+
for (let bi = 0; bi < MAX_BISECTION && (t_hi - t_lo) > stop_width; bi++) {
|
|
288
|
+
const t_mid = (t_lo + t_hi) * 0.5;
|
|
289
|
+
swept_posed.px = ox + dx * t_mid;
|
|
290
|
+
swept_posed.py = oy + dy * t_mid;
|
|
291
|
+
swept_posed.pz = oz + dz * t_mid;
|
|
292
|
+
if (gjk(simplex_buf, swept_posed, candidate_posed)) {
|
|
293
|
+
t_hi = t_mid;
|
|
294
|
+
} else {
|
|
295
|
+
t_lo = t_mid;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Use t_lo (the just-SEPARATING side of the bisection) rather
|
|
300
|
+
// than t_hi (just-overlapping). With the fixed GJK that no
|
|
301
|
+
// longer flags 5 mm-clear gaps as overlap, the bisection is
|
|
302
|
+
// tight; reporting t_lo gives kinematic callers a conservative
|
|
303
|
+
// TOI — the swept shape at the reported moment is provably NOT
|
|
304
|
+
// overlapping the target. The normal-probe below steps a few
|
|
305
|
+
// mm past best_t to get a valid simplex for MPR.
|
|
306
|
+
if (t_lo < best_t) {
|
|
307
|
+
best_t = t_lo;
|
|
308
|
+
best_body_id = body_id;
|
|
309
|
+
best_entity = entity;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (best_body_id === -1) return false;
|
|
314
|
+
|
|
315
|
+
const rp = result.position;
|
|
316
|
+
const rn = result.normal;
|
|
317
|
+
|
|
318
|
+
const swept_x = ox + dx * best_t;
|
|
319
|
+
const swept_y = oy + dy * best_t;
|
|
320
|
+
const swept_z = oz + dz * best_t;
|
|
321
|
+
|
|
322
|
+
rp[0] = swept_x;
|
|
323
|
+
rp[1] = swept_y;
|
|
324
|
+
rp[2] = swept_z;
|
|
325
|
+
|
|
326
|
+
// ── Contact-normal recovery via MPR ────────────────────────────
|
|
327
|
+
//
|
|
328
|
+
// Bisection converges with `swept_posed` somewhere within
|
|
329
|
+
// `stop_width = TOI_TOLERANCE * tMax` of the true contact. At
|
|
330
|
+
// exactly `best_t` the overlap depth is therefore sub-millimetre
|
|
331
|
+
// on practical sweeps. EPA on smooth-vs-smooth supports at this
|
|
332
|
+
// overlap can't tighten before its iteration cap and returns a
|
|
333
|
+
// direction off by ~30° from truth. MPR is the better tool here:
|
|
334
|
+
// it converges in 5-15 iterations on smooth surfaces, same MTV
|
|
335
|
+
// output convention as EPA (direction = A's interior into B,
|
|
336
|
+
// magnitude = depth).
|
|
337
|
+
//
|
|
338
|
+
// We still advance the swept centre by NORMAL_PROBE_OFFSET past
|
|
339
|
+
// best_t (a few mm into the target) before sampling — the extra
|
|
340
|
+
// overlap gives both MPR and the body-centre sign check a more
|
|
341
|
+
// robust geometric basis. The reported `result.t` stays at
|
|
342
|
+
// `best_t`; only the normal probe moves.
|
|
343
|
+
//
|
|
344
|
+
// Sign-validation: MPR's polytope can also settle on either side
|
|
345
|
+
// of the origin for highly symmetric configurations, so we dot
|
|
346
|
+
// against the body-centre axis and flip if needed (same pattern
|
|
347
|
+
// as `narrowphase_step`'s EPA path). The stored normal is the
|
|
348
|
+
// target's outward surface normal — `B → A` direction — i.e. the
|
|
349
|
+
// negated (validated) MTV.
|
|
350
|
+
const NORMAL_PROBE_OFFSET = 0.01;
|
|
351
|
+
const probe_t = best_t + NORMAL_PROBE_OFFSET;
|
|
352
|
+
const probe_x = ox + dx * probe_t;
|
|
353
|
+
const probe_y = oy + dy * probe_t;
|
|
354
|
+
const probe_z = oz + dz * probe_t;
|
|
355
|
+
const best_body_idx = body_id_index(best_body_id);
|
|
356
|
+
const best_collider = system.__primary_collider(best_body_idx);
|
|
357
|
+
let normal_x = -dx, normal_y = -dy, normal_z = -dz;
|
|
358
|
+
if (best_collider !== null) {
|
|
359
|
+
const best_tr = system.__transforms[best_body_idx];
|
|
360
|
+
candidate_posed.setup(best_collider.shape, best_tr.position, best_tr.rotation);
|
|
361
|
+
swept_posed.px = probe_x;
|
|
362
|
+
swept_posed.py = probe_y;
|
|
363
|
+
swept_posed.pz = probe_z;
|
|
364
|
+
if (mpr(mpr_result, 0, swept_posed, candidate_posed)) {
|
|
365
|
+
let ex = mpr_result[0], ey = mpr_result[1], ez = mpr_result[2];
|
|
366
|
+
const depth = Math.sqrt(ex * ex + ey * ey + ez * ez);
|
|
367
|
+
if (depth > 0 && Number.isFinite(depth)) {
|
|
368
|
+
const ab_x = best_tr.position.x - probe_x;
|
|
369
|
+
const ab_y = best_tr.position.y - probe_y;
|
|
370
|
+
const ab_z = best_tr.position.z - probe_z;
|
|
371
|
+
if (ex * ab_x + ey * ab_y + ez * ab_z < 0) {
|
|
372
|
+
ex = -ex; ey = -ey; ez = -ez;
|
|
373
|
+
}
|
|
374
|
+
const inv = 1 / depth;
|
|
375
|
+
normal_x = -ex * inv;
|
|
376
|
+
normal_y = -ey * inv;
|
|
377
|
+
normal_z = -ez * inv;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
rn[0] = normal_x; rn[1] = normal_y; rn[2] = normal_z;
|
|
383
|
+
result.t = best_t;
|
|
384
|
+
result.entity = best_entity;
|
|
385
|
+
result.body_id = best_body_id;
|
|
386
|
+
return true;
|
|
387
|
+
}
|
|
@@ -1,36 +1,122 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
2
|
+
* Stage 1 — prepare the contact constraints for an outer step.
|
|
3
|
+
*
|
|
4
|
+
* Packs every touched, non-sensor contact into the flat scratch arrays:
|
|
5
|
+
* local-frame witness anchors, tangent basis, effective masses, friction,
|
|
6
|
+
* the restitution approach velocity, and the warm-start replay (applied
|
|
7
|
+
* once here, not per substep). Computes the SPOOK gains from the SUBSTEP
|
|
8
|
+
* size `dt_sub` because the position correction runs once per substep.
|
|
9
|
+
*
|
|
10
|
+
* @param {ManifoldStore} manifolds
|
|
11
|
+
* @param {PhysicsSystem} system
|
|
12
|
+
* @param {number} dt_sub substep size `dt / substeps`
|
|
13
|
+
* @returns {number} number of contacts prepared (also stored module-side)
|
|
14
|
+
*/
|
|
15
|
+
export function prepare_contacts(manifolds: ManifoldStore, system: PhysicsSystem, dt_sub: number): number;
|
|
16
|
+
/**
|
|
17
|
+
* Stage 1b (per substep) — warm-start: replay the cached accumulated
|
|
18
|
+
* impulses `(j_n, j_t1, j_t2)` onto persistent velocity using the current
|
|
19
|
+
* (refreshed) lever arms and tangents. Run once per substep, after
|
|
20
|
+
* {@link refresh_contacts} and before {@link solve_velocity}.
|
|
21
|
+
*
|
|
22
|
+
* Per-substep warm-start is the crux of stable TGS: the stored impulse is a
|
|
23
|
+
* per-substep quantity (≈ the impulse to counter one substep of gravity), so
|
|
24
|
+
* replaying it each substep balances that substep's `integrate_velocity_gravity`
|
|
25
|
+
* and a resting contact holds at zero velocity. `solve_velocity` then only
|
|
26
|
+
* has to correct the residual, which converges in a few iterations even for
|
|
27
|
+
* deep chains because each substep carries just `h` of gravity.
|
|
28
|
+
*
|
|
29
|
+
* @param {ManifoldStore} manifolds
|
|
30
|
+
* @param {PhysicsSystem} system
|
|
31
|
+
*/
|
|
32
|
+
export function warm_start_contacts(manifolds: ManifoldStore, system: PhysicsSystem): void;
|
|
33
|
+
/**
|
|
34
|
+
* Stage 2 (per substep) — re-derive each contact's geometry from the
|
|
35
|
+
* bodies' current poses and the local witness anchors captured at prepare.
|
|
36
|
+
*
|
|
37
|
+
* For each contact:
|
|
38
|
+
* - rotate the stored local witnesses back to world by the current pose to
|
|
39
|
+
* get the moved contact points `cpA`, `cpB`;
|
|
40
|
+
* - current penetration `depth_now = depth0 − Δseparation`, where
|
|
41
|
+
* `Δseparation = (cpA − wA − (cpB − wB)) · n` is the change since prepare.
|
|
42
|
+
* Anchoring on the trusted prepare-time depth makes the sign convention
|
|
43
|
+
* irrelevant — only the analytic delta uses the anchors;
|
|
44
|
+
* - rebuild the impulse levers `rA`/`rB` from the moved midpoint;
|
|
45
|
+
* - recompute the position-correction bias from `depth_now`.
|
|
46
|
+
*
|
|
47
|
+
* The contact normal and tangents are held fixed for the outer step (valid
|
|
48
|
+
* for the small per-step rotation), so they are not recomputed here.
|
|
49
|
+
*
|
|
50
|
+
* @param {ManifoldStore} manifolds
|
|
51
|
+
* @param {PhysicsSystem} system
|
|
52
|
+
*/
|
|
53
|
+
export function refresh_contacts(manifolds: ManifoldStore, system: PhysicsSystem): void;
|
|
54
|
+
/**
|
|
55
|
+
* Stage 3 (per substep) — velocity iterations enforcing pure
|
|
56
|
+
* non-penetration (`vn → 0`) plus Coulomb-disk friction. No bias: depth
|
|
57
|
+
* correction is the position pass, restitution is the one-shot pass.
|
|
58
|
+
*
|
|
59
|
+
* @param {ManifoldStore} manifolds
|
|
60
|
+
* @param {PhysicsSystem} system
|
|
61
|
+
* @param {number} iters
|
|
62
|
+
*/
|
|
63
|
+
export function solve_velocity(manifolds: ManifoldStore, system: PhysicsSystem, iters: number): void;
|
|
64
|
+
/**
|
|
65
|
+
* Stage 4 (once, after the substep loop) — one-shot restitution
|
|
66
|
+
* (Box2D-v3 `b2ApplyRestitution`, Catto 2018). Drives `vn → -e · vn_approach`
|
|
67
|
+
* exactly once per closing contact, gated on (a) the contact having been
|
|
68
|
+
* closing faster than the threshold at prepare, and (b) a compressive
|
|
69
|
+
* normal impulse having formed during the velocity solve. The added impulse
|
|
70
|
+
* accumulates into the same normal-impulse slot so it composes with
|
|
71
|
+
* warm-start next frame.
|
|
28
72
|
*
|
|
29
73
|
* @param {ManifoldStore} manifolds
|
|
30
|
-
* @param {PhysicsSystem} system
|
|
31
|
-
|
|
74
|
+
* @param {PhysicsSystem} system
|
|
75
|
+
*/
|
|
76
|
+
export function apply_restitution(manifolds: ManifoldStore, system: PhysicsSystem): void;
|
|
77
|
+
/**
|
|
78
|
+
* Stage 5 (per substep) — split-impulse position correction. Normal-only
|
|
79
|
+
* (friction in the pseudo-velocity pass is ill-defined). Reads the per-body
|
|
80
|
+
* pseudo-velocity, applies a clamped normal impulse driven by the refreshed
|
|
81
|
+
* `bias_position`, and writes the increment back into the pseudo buffer. The
|
|
82
|
+
* pose integrator folds pseudo-velocity into `pos += v · dt` and discards it.
|
|
83
|
+
*
|
|
84
|
+
* The pseudo buffer must be zeroed by the caller before this stage each
|
|
85
|
+
* substep (it's a per-substep correction). The position accumulator
|
|
86
|
+
* `scratch_pos_jn` is likewise reset here per substep.
|
|
87
|
+
*
|
|
88
|
+
* @param {ManifoldStore} manifolds
|
|
89
|
+
* @param {PhysicsSystem} system
|
|
90
|
+
* @param {number} pos_iters
|
|
91
|
+
*/
|
|
92
|
+
export function solve_position(manifolds: ManifoldStore, system: PhysicsSystem, pos_iters: number): void;
|
|
93
|
+
/**
|
|
94
|
+
* Convenience single-step driver: prepare → refresh → velocity →
|
|
95
|
+
* restitution → position, all at the full `dt` (one substep). Equivalent to
|
|
96
|
+
* the Phase-2 solver. The substepped path in `PhysicsSystem.fixedUpdate`
|
|
97
|
+
* calls the stages directly; this entry point exists for callers/tests that
|
|
98
|
+
* want a one-shot solve.
|
|
99
|
+
*
|
|
100
|
+
* The position pass writes `system.__pseudo_velocity`; the caller must zero
|
|
101
|
+
* that buffer before this call and fold it into the pose afterwards.
|
|
102
|
+
*
|
|
103
|
+
* @param {ManifoldStore} manifolds
|
|
104
|
+
* @param {PhysicsSystem} system
|
|
105
|
+
* @param {number} dt
|
|
32
106
|
* @param {number} [iters]
|
|
33
|
-
* @param {
|
|
107
|
+
* @param {number} [pos_iters]
|
|
108
|
+
*/
|
|
109
|
+
export function solve_contacts(manifolds: ManifoldStore, system: PhysicsSystem, dt: number, iters?: number, pos_iters?: number): void;
|
|
110
|
+
/**
|
|
111
|
+
* Velocity-iteration count per substep. With substepping the per-substep
|
|
112
|
+
* count can be lower than a single-step PGS solver would need, because the
|
|
113
|
+
* outer loop revisits the contact set `substeps` times.
|
|
114
|
+
* @type {number}
|
|
115
|
+
*/
|
|
116
|
+
export const DEFAULT_VELOCITY_ITERATIONS: number;
|
|
117
|
+
/**
|
|
118
|
+
* Position-iteration count per substep (split-impulse pseudo-velocity pass).
|
|
119
|
+
* @type {number}
|
|
34
120
|
*/
|
|
35
|
-
export
|
|
121
|
+
export const DEFAULT_POSITION_ITERATIONS: number;
|
|
36
122
|
//# sourceMappingURL=solve_contacts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solve_contacts.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/solver/solve_contacts.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"solve_contacts.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/solver/solve_contacts.js"],"names":[],"mappings":"AA8ZA;;;;;;;;;;;;;GAaG;AACH,0FAHW,MAAM,GACJ,MAAM,CA4IlB;AAED;;;;;;;;;;;;;;;GAeG;AACH,2FAuCC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wFA2DC;AAED;;;;;;;;GAQG;AACH,uFAFW,MAAM,QA2GhB;AAED;;;;;;;;;;;GAWG;AACH,yFA4DC;AAED;;;;;;;;;;;;;;GAcG;AACH,2FAFW,MAAM,QA4EhB;AAED;;;;;;;;;;;;;;;GAeG;AACH,oFAJW,MAAM,UACN,MAAM,cACN,MAAM,QAYhB;AAl7BD;;;;;GAKG;AACH,0CAFU,MAAM,CAEuB;AAEvC;;;GAGG;AACH,0CAFU,MAAM,CAEsB"}
|