@woosh/meep-engine 2.145.0 → 2.147.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/shape/HeightMapShape3D.d.ts +33 -3
- package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
- package/src/core/geom/3d/shape/HeightMapShape3D.js +486 -451
- package/src/engine/control/first-person/DESIGN_COLLISION.md +365 -352
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts +1 -14
- package/src/engine/control/first-person/FirstPersonPlayerController.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts +20 -8
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.d.ts.map +1 -1
- package/src/engine/control/first-person/FirstPersonPlayerControllerConfig.js +552 -546
- package/src/engine/control/first-person/TODO.md +13 -11
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts +8 -3
- package/src/engine/control/first-person/abilities/LedgeGrab.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/LedgeGrab.js +213 -199
- package/src/engine/control/first-person/abilities/Mantle.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/Mantle.js +195 -188
- package/src/engine/control/first-person/abilities/WallJump.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/WallJump.js +11 -3
- package/src/engine/control/first-person/abilities/WallRun.d.ts.map +1 -1
- package/src/engine/control/first-person/abilities/WallRun.js +183 -163
- package/src/engine/control/first-person/collision/KinematicMover.d.ts.map +1 -1
- package/src/engine/control/first-person/collision/KinematicMover.js +634 -592
- package/src/engine/control/first-person/prototype_first_person_controller.js +1003 -901
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +9 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -1
- package/src/engine/control/first-person/sensors/FirstPersonSensors.js +87 -77
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts +8 -0
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -1
- package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +229 -196
- package/src/engine/ecs/EntityManager.d.ts +34 -11
- package/src/engine/ecs/EntityManager.d.ts.map +1 -1
- package/src/engine/ecs/EntityManager.js +71 -42
- package/src/engine/interpolation/BinaryInterpolationAdapter.d.ts.map +1 -0
- package/src/engine/interpolation/Interpoland.d.ts +48 -0
- package/src/engine/interpolation/Interpoland.d.ts.map +1 -0
- package/src/engine/interpolation/Interpoland.js +49 -0
- package/src/engine/interpolation/Interpolated.d.ts +101 -0
- package/src/engine/interpolation/Interpolated.d.ts.map +1 -0
- package/src/engine/interpolation/Interpolated.js +149 -0
- package/src/engine/{network/sim → interpolation}/InterpolationLog.d.ts +1 -1
- package/src/engine/interpolation/InterpolationLog.d.ts.map +1 -0
- package/src/engine/{network/sim → interpolation}/InterpolationLog.js +2 -2
- package/src/engine/interpolation/InterpolationSystem.d.ts +116 -0
- package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -0
- package/src/engine/interpolation/InterpolationSystem.js +233 -0
- package/src/engine/interpolation/PoseInterpolationAdapter.d.ts +17 -0
- package/src/engine/interpolation/PoseInterpolationAdapter.d.ts.map +1 -0
- package/src/engine/interpolation/PoseInterpolationAdapter.js +61 -0
- package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts +35 -0
- package/src/engine/interpolation/TransformPoseSerializationAdapter.d.ts.map +1 -0
- package/src/engine/interpolation/TransformPoseSerializationAdapter.js +57 -0
- package/src/engine/interpolation/pose_interpoland.d.ts +18 -0
- package/src/engine/interpolation/pose_interpoland.d.ts.map +1 -0
- package/src/engine/interpolation/pose_interpoland.js +27 -0
- package/src/engine/network/NetworkSession.d.ts +2 -2
- package/src/engine/network/NetworkSession.d.ts.map +1 -1
- package/src/engine/network/NetworkSession.js +2 -2
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts +1 -1
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/QuaternionInterpolationAdapter.js +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/TransformInterpolationAdapter.js +1 -1
- package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts +1 -1
- package/src/engine/network/adapters/Vector3InterpolationAdapter.d.ts.map +1 -1
- package/src/engine/network/adapters/Vector3InterpolationAdapter.js +1 -1
- package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +287 -0
- package/src/engine/physics/PLAN.md +944 -809
- package/src/engine/physics/body/BodyStorage.d.ts +9 -0
- package/src/engine/physics/body/BodyStorage.d.ts.map +1 -1
- package/src/engine/physics/body/BodyStorage.js +23 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +7 -0
- package/src/engine/physics/ccd/linear_sweep.d.ts +97 -0
- package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -0
- package/src/engine/physics/ccd/linear_sweep.js +238 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +82 -3
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +227 -8
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts +6 -0
- package/src/engine/physics/ecs/RigidBodyFlags.d.ts.map +1 -1
- package/src/engine/physics/ecs/RigidBodyFlags.js +6 -0
- package/src/engine/physics/narrowphase/box_triangle_contact.js +814 -811
- package/src/engine/physics/narrowphase/compute_penetration.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/compute_penetration.js +325 -323
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts +27 -8
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/decomposition/heightmap_enumerate_triangles.js +235 -204
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +97 -13
- package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
- package/src/engine/physics/queries/overlap_shape.js +185 -183
- package/src/engine/simulation/Ticker.d.ts +14 -0
- package/src/engine/simulation/Ticker.d.ts.map +1 -1
- package/src/engine/simulation/Ticker.js +136 -1
- package/src/engine/network/sim/BinaryInterpolationAdapter.d.ts.map +0 -1
- package/src/engine/network/sim/InterpolationLog.d.ts.map +0 -1
- /package/src/engine/{network/sim → interpolation}/BinaryInterpolationAdapter.d.ts +0 -0
- /package/src/engine/{network/sim → interpolation}/BinaryInterpolationAdapter.js +0 -0
|
@@ -61,6 +61,7 @@ export class BodyStorage {
|
|
|
61
61
|
__awake_count: number;
|
|
62
62
|
__free_heap: Uint32Array;
|
|
63
63
|
__free_count: number;
|
|
64
|
+
__entity_to_index: Map<any, any>;
|
|
64
65
|
/**
|
|
65
66
|
* Currently allocated body count (live, regardless of awake/sleeping).
|
|
66
67
|
* @returns {number}
|
|
@@ -109,6 +110,14 @@ export class BodyStorage {
|
|
|
109
110
|
* @returns {number} entity for the body, or -1 if the slot is free.
|
|
110
111
|
*/
|
|
111
112
|
entity_at(index: number): number;
|
|
113
|
+
/**
|
|
114
|
+
* Body index for `entity`, or {@link BODY_INDEX_ABSENT} if no live body owns
|
|
115
|
+
* it. O(1) reverse of {@link entity_at} — the lookup callers use on the
|
|
116
|
+
* link / attach / joint paths instead of scanning the slot table.
|
|
117
|
+
* @param {number} entity
|
|
118
|
+
* @returns {number}
|
|
119
|
+
*/
|
|
120
|
+
index_of_entity(entity: number): number;
|
|
112
121
|
/**
|
|
113
122
|
* @param {number} index
|
|
114
123
|
* @returns {number}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BodyStorage.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/BodyStorage.js"],"names":[],"mappings":"AA2BA;;;;;;GAMG;AACH,oCAJW,MAAM,cACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,2CAHW,MAAM,GACJ,MAAM,CAIlB;AAlCD;;;;GAIG;AACH,gCAFU,MAAM,CAEoB;AA+BpC;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAEI;;;OAGG;IACH,+BAFW,MAAM,
|
|
1
|
+
{"version":3,"file":"BodyStorage.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/BodyStorage.js"],"names":[],"mappings":"AA2BA;;;;;;GAMG;AACH,oCAJW,MAAM,cACN,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,sCAHW,MAAM,GACJ,MAAM,CAIlB;AAED;;;;GAIG;AACH,2CAHW,MAAM,GACJ,MAAM,CAIlB;AAlCD;;;;GAIG;AACH,gCAFU,MAAM,CAEoB;AA+BpC;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAEI;;;OAGG;IACH,+BAFW,MAAM,EAqChB;IA9BG,mBAAqB;IAGrB,gBAAgB;IAEhB,uBAAqC;IACrC,0BAAwC;IACxC,oBAAkC;IAClC,qBAAmC;IAGnC,oBAAkC;IAGlC,0BAAwC;IACxC,wBAAsC;IACtC,sBAAsB;IAGtB,yBAAuC;IACvC,qBAAqB;IAMrB,iCAAkC;IAMtC;;;OAGG;IACH,mBAEC;IAED;;;OAGG;IACH,uBAEC;IAED;;;OAGG;IACH,0BAEC;IAED;;;;OAIG;IACH,8BAEC;IAED;;;;;;;OAOG;IACH,iBAHW,MAAM,GACJ,MAAM,CA0BlB;IAED;;;;;OAKG;IACH,qBAFW,MAAM,QAwBhB;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,OAAO,CAWnB;IAED;;;OAGG;IACH,iBAHW,MAAM,GACJ,MAAM,CAOlB;IAED;;;;;;OAMG;IACH,wBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,eAHW,MAAM,GACJ,QAAQ,GAAC,MAAM,CAI3B;IAED;;;OAGG;IACH,gBAHW,MAAM,QACN,QAAQ,GAAC,MAAM,QAIzB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,iBAHW,MAAM,SACN,MAAM,QAIhB;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;OAIG;IACH,gBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;;OAIG;IACH,YAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,kBAFW,MAAM,QAShB;IAED;;;OAGG;IACH,qBAFW,MAAM,QAShB;IAED;;;;OAIG;IACH,0BAOC;IAED;;OAEG;IACH,eAiCC;IAID;;;OAGG;IACH,oBAgBC;IAED;;;OAGG;IACH,mBAqBC;CACJ;yBAhcwB,oBAAoB"}
|
|
@@ -106,6 +106,12 @@ export class BodyStorage {
|
|
|
106
106
|
this.__free_heap = new Uint32Array(cap);
|
|
107
107
|
this.__free_count = 0;
|
|
108
108
|
|
|
109
|
+
// Entity → body-index map (one body per entity). Keeps {@link
|
|
110
|
+
// index_of_entity} O(1) instead of an O(N) scan over the slot table on
|
|
111
|
+
// every collider attach / detach and joint link. Maintained on
|
|
112
|
+
// allocate / free; never grows with the typed arrays (a plain Map).
|
|
113
|
+
this.__entity_to_index = new Map();
|
|
114
|
+
|
|
109
115
|
// Initialise reverse map to BODY_INDEX_ABSENT.
|
|
110
116
|
this.__awake_pos.fill(BODY_INDEX_ABSENT);
|
|
111
117
|
}
|
|
@@ -167,6 +173,7 @@ export class BodyStorage {
|
|
|
167
173
|
this.__kinds[index] = BodyKind.Dynamic;
|
|
168
174
|
this.__flags[index] = 0;
|
|
169
175
|
this.__alive[index] = 1;
|
|
176
|
+
this.__entity_to_index.set(entity, index);
|
|
170
177
|
|
|
171
178
|
// Insert into awake set.
|
|
172
179
|
const awake_pos = this.__awake_count++;
|
|
@@ -196,6 +203,10 @@ export class BodyStorage {
|
|
|
196
203
|
|
|
197
204
|
this.__alive[index] = 0;
|
|
198
205
|
|
|
206
|
+
// Drop the entity → index mapping (the slot still holds the old entity
|
|
207
|
+
// value until reallocation, so delete by it now while it's valid).
|
|
208
|
+
this.__entity_to_index.delete(this.__entities[index]);
|
|
209
|
+
|
|
199
210
|
// Bump generation; wraps mod 256.
|
|
200
211
|
this.__generations[index] = (this.__generations[index] + 1) & GENERATION_MASK;
|
|
201
212
|
|
|
@@ -229,6 +240,18 @@ export class BodyStorage {
|
|
|
229
240
|
return this.__entities[index];
|
|
230
241
|
}
|
|
231
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Body index for `entity`, or {@link BODY_INDEX_ABSENT} if no live body owns
|
|
245
|
+
* it. O(1) reverse of {@link entity_at} — the lookup callers use on the
|
|
246
|
+
* link / attach / joint paths instead of scanning the slot table.
|
|
247
|
+
* @param {number} entity
|
|
248
|
+
* @returns {number}
|
|
249
|
+
*/
|
|
250
|
+
index_of_entity(entity) {
|
|
251
|
+
const idx = this.__entity_to_index.get(entity);
|
|
252
|
+
return idx === undefined ? BODY_INDEX_ABSENT : idx;
|
|
253
|
+
}
|
|
254
|
+
|
|
232
255
|
/**
|
|
233
256
|
* @param {number} index
|
|
234
257
|
* @returns {number}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate_pairs.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/generate_pairs.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate_pairs.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/generate_pairs.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,uIARW,MAAM,MAAM;IAAC,QAAQ,WAAW;IAAC,SAAS,YAAY;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC,+CAElF,MAAM,OAAO,MAAM,KAAK,OAAO,QA4EhD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assert } from "../../../core/assert.js";
|
|
1
2
|
import { bvh_query_user_data_overlaps_aabb } from "../../../core/bvh2/bvh3/query/bvh_query_user_data_overlaps_aabb.js";
|
|
2
3
|
|
|
3
4
|
const scratch_aabb = new Float64Array(6);
|
|
@@ -65,6 +66,11 @@ export function generate_pairs(
|
|
|
65
66
|
dynamic_bvh,
|
|
66
67
|
scratch_aabb
|
|
67
68
|
);
|
|
69
|
+
// The BVH query writes leaves unconditionally — at capacity it both
|
|
70
|
+
// drops leaves (typed-array OOB writes no-op) AND returns a count
|
|
71
|
+
// past the buffer end, so the loop below would read `undefined`
|
|
72
|
+
// candidates and build garbage pairs. Guard the buffer size.
|
|
73
|
+
assert.lessThan(n, candidates.length, 'generate_pairs: dynamic broadphase overflowed the candidate buffer');
|
|
68
74
|
for (let c = 0; c < n; c++) {
|
|
69
75
|
const other = candidates[c];
|
|
70
76
|
if (other === my_packed) continue;
|
|
@@ -85,6 +91,7 @@ export function generate_pairs(
|
|
|
85
91
|
static_bvh,
|
|
86
92
|
scratch_aabb
|
|
87
93
|
);
|
|
94
|
+
assert.lessThan(n, candidates.length, 'generate_pairs: static broadphase overflowed the candidate buffer');
|
|
88
95
|
for (let c = 0; c < n; c++) {
|
|
89
96
|
const other = candidates[c];
|
|
90
97
|
const idA = my_packed < other ? my_packed : other;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sweep `shape` (held at the fixed `rotation`) linearly from `(fx,fy,fz)` to
|
|
3
|
+
* `(tx,ty,tz)` through both broadphase trees, ignoring colliders owned by
|
|
4
|
+
* `exclude_entity`.
|
|
5
|
+
*
|
|
6
|
+
* Returns the traversable fraction of the segment in `[0, 1]`: `1` means the
|
|
7
|
+
* path is clear; a value `< 1` means a blocker was hit at that fraction and
|
|
8
|
+
* `result` has been filled — `result.position` is the swept-shape centre at
|
|
9
|
+
* first contact, `result.normal` is the blocker's outward surface normal
|
|
10
|
+
* (B → A), `result.entity` / `result.body_id` the blocker.
|
|
11
|
+
*
|
|
12
|
+
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
13
|
+
* @param {import("../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D} shape
|
|
14
|
+
* @param {{x:number,y:number,z:number,w:number}} rotation fixed orientation
|
|
15
|
+
* @param {number} fx
|
|
16
|
+
* @param {number} fy
|
|
17
|
+
* @param {number} fz
|
|
18
|
+
* @param {number} tx
|
|
19
|
+
* @param {number} ty
|
|
20
|
+
* @param {number} tz
|
|
21
|
+
* @param {number} exclude_entity entity to ignore (the swept body itself)
|
|
22
|
+
* @param {PhysicsSurfacePoint} result populated on hit; untouched on a clear path
|
|
23
|
+
* @returns {number} traversable fraction in [0, 1]
|
|
24
|
+
*/
|
|
25
|
+
export function ccd_sweep_segment(system: import("../ecs/PhysicsSystem.js").PhysicsSystem, shape: import("../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D, rotation: {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
z: number;
|
|
29
|
+
w: number;
|
|
30
|
+
}, fx: number, fy: number, fz: number, tx: number, ty: number, tz: number, exclude_entity: number, result: PhysicsSurfacePoint): number;
|
|
31
|
+
/**
|
|
32
|
+
* Post-solve continuous-collision pass over the awake set. For each awake
|
|
33
|
+
* Dynamic body flagged {@link RigidBodyFlags.CCD} that moved more than
|
|
34
|
+
* {@link CCD_MIN_SWEEP_DISTANCE} this step, sweep its primary collider along the
|
|
35
|
+
* step's net translation and stop it at the first blocker (clamp pose + remove
|
|
36
|
+
* inbound normal velocity).
|
|
37
|
+
*
|
|
38
|
+
* Start-of-step positions are captured into `system.__ccd_start_pos` (3 doubles
|
|
39
|
+
* per body index) before the substep loop; this pass reads the final pose from
|
|
40
|
+
* the live Transform. Iterates the awake list in storage order, so it is
|
|
41
|
+
* deterministic.
|
|
42
|
+
*
|
|
43
|
+
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
44
|
+
*/
|
|
45
|
+
export function ccd_resolve(system: import("../ecs/PhysicsSystem.js").PhysicsSystem): void;
|
|
46
|
+
/**
|
|
47
|
+
* Continuous collision detection — linear shape-cast (the "speculative margin
|
|
48
|
+
* floor, upgraded to an opt-in per-body sweep" item from PLAN.md).
|
|
49
|
+
*
|
|
50
|
+
* The discrete pipeline detects contacts by overlap at step boundaries: a body
|
|
51
|
+
* that moves more than its own thickness in one step can start a step on one
|
|
52
|
+
* side of a thin wall and end on the other, never overlapping it on any frame
|
|
53
|
+
* the broadphase samples — it tunnels. The speculative fat-AABB margin
|
|
54
|
+
* (`compute_fat_world_aabb`) covers moderate speeds; genuinely fast movers
|
|
55
|
+
* (bullets, dropped debris, a body flung by an explosion) need a swept test.
|
|
56
|
+
*
|
|
57
|
+
* Approach (Box2D `b2_continuousPhysics`-style conservative advancement): after
|
|
58
|
+
* the substep solver has produced each body's final pose, sweep a CCD-flagged
|
|
59
|
+
* fast mover's primary collider along its NET step translation
|
|
60
|
+
* (start-of-step → final pose) using the existing {@link shape_cast} TOI engine.
|
|
61
|
+
* On the first blocker, clamp the body to the contact pose and remove the
|
|
62
|
+
* inbound normal component of its velocity (an inelastic stop) — the next
|
|
63
|
+
* discrete step then resolves the now-touching contact with the real
|
|
64
|
+
* material / restitution.
|
|
65
|
+
*
|
|
66
|
+
* Scope (v1, deliberate):
|
|
67
|
+
* - LINEAR sweep only: the orientation is held fixed through the sweep (the
|
|
68
|
+
* per-step angular motion is small at the fixed-step rate).
|
|
69
|
+
* - PRIMARY same-entity collider: a compound body sweeps its first collider;
|
|
70
|
+
* child-entity colliders (whose transform is synced outside the step) are
|
|
71
|
+
* not swept.
|
|
72
|
+
* - EXACT against static geometry (the static BVH holds tight, never-moved
|
|
73
|
+
* leaves); APPROXIMATE against other dynamic bodies (they have moved this
|
|
74
|
+
* step too, but the sweep sees their start-of-step broadphase AABBs) — the
|
|
75
|
+
* speculative-margin floor for the dynamic-vs-dynamic case.
|
|
76
|
+
* - The CCD stop itself is inelastic; the impact does not bounce. Restitution
|
|
77
|
+
* applies on the next discrete contact.
|
|
78
|
+
*/
|
|
79
|
+
/**
|
|
80
|
+
* Minimum per-step displacement (metres) before a CCD sweep is worth running.
|
|
81
|
+
* Its ONLY job is to skip a body that didn't meaningfully move — a resting /
|
|
82
|
+
* sleeping-soon body whose displacement is sub-millimetre jitter — which avoids
|
|
83
|
+
* a degenerate zero-length sweep and saves the query cost.
|
|
84
|
+
*
|
|
85
|
+
* It must NOT be tied to the body's own size. Tunnelling risk is governed by the
|
|
86
|
+
* *obstacle's* thickness, not the mover's: a 2 m sphere drifting at 0.5 m/step
|
|
87
|
+
* still passes clean through a 1 cm floor. A small absolute slop catches that;
|
|
88
|
+
* gating on a fraction of the body's extent would (wrongly) wait until the body
|
|
89
|
+
* moved more than its own radius and miss every thin-obstacle tunnel below that
|
|
90
|
+
* speed. The discrete narrowphase still owns any obstacle thicker than a body's
|
|
91
|
+
* per-step move, so CCD reliably prevents tunnelling of obstacles thicker than
|
|
92
|
+
* this slop.
|
|
93
|
+
* @type {number}
|
|
94
|
+
*/
|
|
95
|
+
export const CCD_MIN_SWEEP_DISTANCE: number;
|
|
96
|
+
import { PhysicsSurfacePoint } from "../queries/PhysicsSurfacePoint.js";
|
|
97
|
+
//# sourceMappingURL=linear_sweep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linear_sweep.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ccd/linear_sweep.js"],"names":[],"mappings":"AA8FA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,0CAbW,OAAO,yBAAyB,EAAE,aAAa,SAC/C,OAAO,gDAAgD,EAAE,eAAe,YACxE;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,MACrC,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,MACN,MAAM,kBACN,MAAM,UACN,mBAAmB,GACjB,MAAM,CAmClB;AAED;;;;;;;;;;;;;GAaG;AACH,oCAFW,OAAO,yBAAyB,EAAE,aAAa,QAwEzD;AAvOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,qCAFU,MAAM,CAE2B;oCArDP,mCAAmC"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { Ray3 } from "../../../core/geom/3d/ray/Ray3.js";
|
|
2
|
+
import { BodyKind } from "../ecs/BodyKind.js";
|
|
3
|
+
import { RigidBodyFlags } from "../ecs/RigidBodyFlags.js";
|
|
4
|
+
import { PhysicsSurfacePoint } from "../queries/PhysicsSurfacePoint.js";
|
|
5
|
+
import { shape_cast } from "../queries/shape_cast.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Continuous collision detection — linear shape-cast (the "speculative margin
|
|
9
|
+
* floor, upgraded to an opt-in per-body sweep" item from PLAN.md).
|
|
10
|
+
*
|
|
11
|
+
* The discrete pipeline detects contacts by overlap at step boundaries: a body
|
|
12
|
+
* that moves more than its own thickness in one step can start a step on one
|
|
13
|
+
* side of a thin wall and end on the other, never overlapping it on any frame
|
|
14
|
+
* the broadphase samples — it tunnels. The speculative fat-AABB margin
|
|
15
|
+
* (`compute_fat_world_aabb`) covers moderate speeds; genuinely fast movers
|
|
16
|
+
* (bullets, dropped debris, a body flung by an explosion) need a swept test.
|
|
17
|
+
*
|
|
18
|
+
* Approach (Box2D `b2_continuousPhysics`-style conservative advancement): after
|
|
19
|
+
* the substep solver has produced each body's final pose, sweep a CCD-flagged
|
|
20
|
+
* fast mover's primary collider along its NET step translation
|
|
21
|
+
* (start-of-step → final pose) using the existing {@link shape_cast} TOI engine.
|
|
22
|
+
* On the first blocker, clamp the body to the contact pose and remove the
|
|
23
|
+
* inbound normal component of its velocity (an inelastic stop) — the next
|
|
24
|
+
* discrete step then resolves the now-touching contact with the real
|
|
25
|
+
* material / restitution.
|
|
26
|
+
*
|
|
27
|
+
* Scope (v1, deliberate):
|
|
28
|
+
* - LINEAR sweep only: the orientation is held fixed through the sweep (the
|
|
29
|
+
* per-step angular motion is small at the fixed-step rate).
|
|
30
|
+
* - PRIMARY same-entity collider: a compound body sweeps its first collider;
|
|
31
|
+
* child-entity colliders (whose transform is synced outside the step) are
|
|
32
|
+
* not swept.
|
|
33
|
+
* - EXACT against static geometry (the static BVH holds tight, never-moved
|
|
34
|
+
* leaves); APPROXIMATE against other dynamic bodies (they have moved this
|
|
35
|
+
* step too, but the sweep sees their start-of-step broadphase AABBs) — the
|
|
36
|
+
* speculative-margin floor for the dynamic-vs-dynamic case.
|
|
37
|
+
* - The CCD stop itself is inelastic; the impact does not bounce. Restitution
|
|
38
|
+
* applies on the next discrete contact.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Minimum per-step displacement (metres) before a CCD sweep is worth running.
|
|
43
|
+
* Its ONLY job is to skip a body that didn't meaningfully move — a resting /
|
|
44
|
+
* sleeping-soon body whose displacement is sub-millimetre jitter — which avoids
|
|
45
|
+
* a degenerate zero-length sweep and saves the query cost.
|
|
46
|
+
*
|
|
47
|
+
* It must NOT be tied to the body's own size. Tunnelling risk is governed by the
|
|
48
|
+
* *obstacle's* thickness, not the mover's: a 2 m sphere drifting at 0.5 m/step
|
|
49
|
+
* still passes clean through a 1 cm floor. A small absolute slop catches that;
|
|
50
|
+
* gating on a fraction of the body's extent would (wrongly) wait until the body
|
|
51
|
+
* moved more than its own radius and miss every thin-obstacle tunnel below that
|
|
52
|
+
* speed. The discrete narrowphase still owns any obstacle thicker than a body's
|
|
53
|
+
* per-step move, so CCD reliably prevents tunnelling of obstacles thicker than
|
|
54
|
+
* this slop.
|
|
55
|
+
* @type {number}
|
|
56
|
+
*/
|
|
57
|
+
export const CCD_MIN_SWEEP_DISTANCE = 1e-3;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Impact distances at or below this (metres) mean the body was already
|
|
61
|
+
* overlapping the target at the start of the step — i.e. a resting / sliding
|
|
62
|
+
* contact the discrete solver owns, not a tunnel. The sweep ignores these so
|
|
63
|
+
* CCD never clamps a body to a surface it is merely sitting or sliding on.
|
|
64
|
+
* @type {number}
|
|
65
|
+
*/
|
|
66
|
+
const CCD_INITIAL_OVERLAP_EPS = 1e-6;
|
|
67
|
+
|
|
68
|
+
// ── Module scratch ──────────────────────────────────────────────────────────
|
|
69
|
+
// CCD runs inside the step loop; reuse buffers so the pass allocates nothing.
|
|
70
|
+
|
|
71
|
+
/** Swept ray, re-seeded per sweep (origin, unit direction, tMax). */
|
|
72
|
+
const _ray = new Ray3();
|
|
73
|
+
|
|
74
|
+
/** Sweep result reused across bodies inside {@link ccd_resolve}. */
|
|
75
|
+
const _hit = new PhysicsSurfacePoint();
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Entity whose colliders the current sweep must ignore (the moving body's own).
|
|
79
|
+
* Module-scoped so {@link _exclude_self} stays a stable, non-allocating
|
|
80
|
+
* reference handed to {@link shape_cast}.
|
|
81
|
+
* @type {number}
|
|
82
|
+
*/
|
|
83
|
+
let _exclude_entity = -1;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Self-exclusion filter for the sweep: drop candidates owned by the moving
|
|
87
|
+
* body's own entity (otherwise the body would "hit itself" at `t = 0`).
|
|
88
|
+
* @param {number} entity
|
|
89
|
+
* @returns {boolean}
|
|
90
|
+
*/
|
|
91
|
+
function _exclude_self(entity) {
|
|
92
|
+
return entity !== _exclude_entity;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Sweep `shape` (held at the fixed `rotation`) linearly from `(fx,fy,fz)` to
|
|
97
|
+
* `(tx,ty,tz)` through both broadphase trees, ignoring colliders owned by
|
|
98
|
+
* `exclude_entity`.
|
|
99
|
+
*
|
|
100
|
+
* Returns the traversable fraction of the segment in `[0, 1]`: `1` means the
|
|
101
|
+
* path is clear; a value `< 1` means a blocker was hit at that fraction and
|
|
102
|
+
* `result` has been filled — `result.position` is the swept-shape centre at
|
|
103
|
+
* first contact, `result.normal` is the blocker's outward surface normal
|
|
104
|
+
* (B → A), `result.entity` / `result.body_id` the blocker.
|
|
105
|
+
*
|
|
106
|
+
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
107
|
+
* @param {import("../../../core/geom/3d/shape/AbstractShape3D.js").AbstractShape3D} shape
|
|
108
|
+
* @param {{x:number,y:number,z:number,w:number}} rotation fixed orientation
|
|
109
|
+
* @param {number} fx
|
|
110
|
+
* @param {number} fy
|
|
111
|
+
* @param {number} fz
|
|
112
|
+
* @param {number} tx
|
|
113
|
+
* @param {number} ty
|
|
114
|
+
* @param {number} tz
|
|
115
|
+
* @param {number} exclude_entity entity to ignore (the swept body itself)
|
|
116
|
+
* @param {PhysicsSurfacePoint} result populated on hit; untouched on a clear path
|
|
117
|
+
* @returns {number} traversable fraction in [0, 1]
|
|
118
|
+
*/
|
|
119
|
+
export function ccd_sweep_segment(
|
|
120
|
+
system, shape, rotation,
|
|
121
|
+
fx, fy, fz, tx, ty, tz,
|
|
122
|
+
exclude_entity, result,
|
|
123
|
+
) {
|
|
124
|
+
const dx = tx - fx;
|
|
125
|
+
const dy = ty - fy;
|
|
126
|
+
const dz = tz - fz;
|
|
127
|
+
const len = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
128
|
+
if (len === 0) return 1;
|
|
129
|
+
|
|
130
|
+
const inv = 1 / len;
|
|
131
|
+
_ray[0] = fx; _ray[1] = fy; _ray[2] = fz;
|
|
132
|
+
_ray[3] = dx * inv; _ray[4] = dy * inv; _ray[5] = dz * inv;
|
|
133
|
+
_ray[6] = len; // tMax in metres — direction is unit length
|
|
134
|
+
|
|
135
|
+
_exclude_entity = exclude_entity;
|
|
136
|
+
if (!shape_cast(system, _ray, shape, rotation, result, _exclude_self)) {
|
|
137
|
+
return 1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// An impact at t ≈ 0 means the swept shape was already overlapping the
|
|
141
|
+
// target at the segment start — a resting / sliding contact, not a tunnel.
|
|
142
|
+
// The discrete solver owns it; clamping here would freeze a body onto a
|
|
143
|
+
// surface it is sitting or sliding on. Treat as a clear path.
|
|
144
|
+
if (result.t <= CCD_INITIAL_OVERLAP_EPS) return 1;
|
|
145
|
+
|
|
146
|
+
// result.t is the impact distance along the unit direction; normalise to a
|
|
147
|
+
// segment fraction. shape_cast reports the just-SEPARATING side of its
|
|
148
|
+
// bisection, so the swept shape at `result.t` is provably not overlapping —
|
|
149
|
+
// safe to place the body there.
|
|
150
|
+
const frac = result.t * inv;
|
|
151
|
+
return frac < 1 ? frac : 1;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Post-solve continuous-collision pass over the awake set. For each awake
|
|
156
|
+
* Dynamic body flagged {@link RigidBodyFlags.CCD} that moved more than
|
|
157
|
+
* {@link CCD_MIN_SWEEP_DISTANCE} this step, sweep its primary collider along the
|
|
158
|
+
* step's net translation and stop it at the first blocker (clamp pose + remove
|
|
159
|
+
* inbound normal velocity).
|
|
160
|
+
*
|
|
161
|
+
* Start-of-step positions are captured into `system.__ccd_start_pos` (3 doubles
|
|
162
|
+
* per body index) before the substep loop; this pass reads the final pose from
|
|
163
|
+
* the live Transform. Iterates the awake list in storage order, so it is
|
|
164
|
+
* deterministic.
|
|
165
|
+
*
|
|
166
|
+
* @param {import("../ecs/PhysicsSystem.js").PhysicsSystem} system
|
|
167
|
+
*/
|
|
168
|
+
export function ccd_resolve(system) {
|
|
169
|
+
const storage = system.storage;
|
|
170
|
+
const count = storage.awake_count;
|
|
171
|
+
const lists = system.__body_collider_lists;
|
|
172
|
+
const start = system.__ccd_start_pos;
|
|
173
|
+
const CCD = RigidBodyFlags.CCD;
|
|
174
|
+
|
|
175
|
+
for (let i = 0; i < count; i++) {
|
|
176
|
+
const idx = storage.awake_at(i);
|
|
177
|
+
|
|
178
|
+
const rb = system.__bodies[idx];
|
|
179
|
+
if (rb === undefined) continue;
|
|
180
|
+
if ((rb.flags & CCD) === 0) continue;
|
|
181
|
+
if (rb.kind !== BodyKind.Dynamic) continue;
|
|
182
|
+
|
|
183
|
+
const list = lists[idx];
|
|
184
|
+
if (list === undefined || list.length === 0) continue;
|
|
185
|
+
const primary = list[0];
|
|
186
|
+
const tr = primary.transform;
|
|
187
|
+
const p = tr.position;
|
|
188
|
+
|
|
189
|
+
const base = idx * 3;
|
|
190
|
+
const sx = start[base];
|
|
191
|
+
const sy = start[base + 1];
|
|
192
|
+
const sz = start[base + 2];
|
|
193
|
+
const ex = p[0];
|
|
194
|
+
const ey = p[1];
|
|
195
|
+
const ez = p[2];
|
|
196
|
+
|
|
197
|
+
const dx = ex - sx;
|
|
198
|
+
const dy = ey - sy;
|
|
199
|
+
const dz = ez - sz;
|
|
200
|
+
const disp2 = dx * dx + dy * dy + dz * dz;
|
|
201
|
+
if (disp2 === 0) continue;
|
|
202
|
+
|
|
203
|
+
// Motion gate: skip a body that barely moved (resting / negligible
|
|
204
|
+
// jitter) — avoids a degenerate sweep and the query cost. NOT tied to
|
|
205
|
+
// body size: a body tunnels a thin obstacle at speeds well below its
|
|
206
|
+
// own extent, so the threshold is a small absolute slop. A resting /
|
|
207
|
+
// sliding body that does clear it is still safe — the sweep ignores its
|
|
208
|
+
// initial-overlap contact (see CCD_INITIAL_OVERLAP_EPS).
|
|
209
|
+
if (disp2 <= CCD_MIN_SWEEP_DISTANCE * CCD_MIN_SWEEP_DISTANCE) continue;
|
|
210
|
+
|
|
211
|
+
const shape = primary.collider.shape;
|
|
212
|
+
const frac = ccd_sweep_segment(
|
|
213
|
+
system, shape, tr.rotation,
|
|
214
|
+
sx, sy, sz, ex, ey, ez,
|
|
215
|
+
primary.entity, _hit,
|
|
216
|
+
);
|
|
217
|
+
if (frac >= 1) continue; // clear path — no tunnelling this step
|
|
218
|
+
|
|
219
|
+
// Clamp the body to the first-contact pose (swept-shape centre at the
|
|
220
|
+
// TOI), so it cannot end the step on the far side of the blocker.
|
|
221
|
+
const hp = _hit.position;
|
|
222
|
+
p.set(hp[0], hp[1], hp[2]);
|
|
223
|
+
|
|
224
|
+
// Remove the inbound normal component of velocity (inelastic stop).
|
|
225
|
+
// `_hit.normal` is the blocker's outward surface normal; the body is
|
|
226
|
+
// moving into it (v·n < 0). Zeroing that component leaves the tangential
|
|
227
|
+
// slide intact and never adds energy. The next discrete step applies the
|
|
228
|
+
// real restitution / friction on the established contact.
|
|
229
|
+
const n = _hit.normal;
|
|
230
|
+
const lv = rb.linearVelocity;
|
|
231
|
+
const vn = lv[0] * n[0] + lv[1] * n[1] + lv[2] * n[2];
|
|
232
|
+
if (vn < 0) {
|
|
233
|
+
lv[0] -= vn * n[0];
|
|
234
|
+
lv[1] -= vn * n[1];
|
|
235
|
+
lv[2] -= vn * n[2];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
@@ -196,6 +196,21 @@ export class PhysicsSystem extends System<any, any, any, any, any> {
|
|
|
196
196
|
* @type {Float64Array}
|
|
197
197
|
*/
|
|
198
198
|
__pseudo_velocity: Float64Array;
|
|
199
|
+
/**
|
|
200
|
+
* Master switch for the continuous-collision pass. When false the
|
|
201
|
+
* {@link RigidBodyFlags.CCD} flag is ignored and no swept queries run.
|
|
202
|
+
* @type {boolean}
|
|
203
|
+
*/
|
|
204
|
+
ccdEnabled: boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Start-of-step world positions for CCD-flagged bodies — 3 doubles per
|
|
207
|
+
* body slot index (`[x, y, z]`). Captured in Stage 1 before the substep
|
|
208
|
+
* loop integrates poses; the CCD pass ({@link ccd_resolve}) sweeps from
|
|
209
|
+
* here to the final pose. Grows to `storage.high_water_mark * 3`; only
|
|
210
|
+
* CCD-flagged slots are written each step.
|
|
211
|
+
* @type {Float64Array}
|
|
212
|
+
*/
|
|
213
|
+
__ccd_start_pos: Float64Array;
|
|
199
214
|
/**
|
|
200
215
|
* Bound reference to {@link __pair_filter} so we hand the same
|
|
201
216
|
* callable to {@link generate_pairs} each step without per-step
|
|
@@ -203,6 +218,23 @@ export class PhysicsSystem extends System<any, any, any, any, any> {
|
|
|
203
218
|
* @private
|
|
204
219
|
*/
|
|
205
220
|
private __pair_filter_bound;
|
|
221
|
+
/**
|
|
222
|
+
* Optional shared interpolation log to produce per-step pose snapshots
|
|
223
|
+
* into (the {@link InterpolationSystem}'s log). When set — and only then —
|
|
224
|
+
* each fixedUpdate restores every awake {@link Interpolated} body's live
|
|
225
|
+
* components from the previous tick (undoing render-time interpolation so
|
|
226
|
+
* the sim reads authoritative state), then records the post-step state
|
|
227
|
+
* under the current `entityManager.fixedStepTick`. Null on a headless /
|
|
228
|
+
* non-rendering world, where the producer work is skipped entirely.
|
|
229
|
+
* @type {InterpolationLog|null}
|
|
230
|
+
*/
|
|
231
|
+
interpolationLog: InterpolationLog | null;
|
|
232
|
+
/**
|
|
233
|
+
* Reusable decode buffer for restoring interpolated snapshots.
|
|
234
|
+
* @private
|
|
235
|
+
* @type {BinaryBuffer}
|
|
236
|
+
*/
|
|
237
|
+
private __interp_scratch;
|
|
206
238
|
/**
|
|
207
239
|
* Symmetric layer/mask check + optional user callback. Called per
|
|
208
240
|
* candidate pair during broadphase. Returns `true` to accept the pair.
|
|
@@ -322,9 +354,9 @@ export class PhysicsSystem extends System<any, any, any, any, any> {
|
|
|
322
354
|
*/
|
|
323
355
|
detach_collider(body_entity: number, collider: Collider): void;
|
|
324
356
|
/**
|
|
325
|
-
*
|
|
326
|
-
* O(
|
|
327
|
-
*
|
|
357
|
+
* Resolve an entity to its body index, or -1 if no live body owns it.
|
|
358
|
+
* O(1) via {@link BodyStorage#index_of_entity}'s entity → index map — used
|
|
359
|
+
* on the collider attach / detach and joint link paths.
|
|
328
360
|
*
|
|
329
361
|
* @private
|
|
330
362
|
* @param {number} entity
|
|
@@ -453,6 +485,32 @@ export class PhysicsSystem extends System<any, any, any, any, any> {
|
|
|
453
485
|
y: number;
|
|
454
486
|
z: number;
|
|
455
487
|
}): void;
|
|
488
|
+
/**
|
|
489
|
+
* Teleport a body to a new pose, bypassing integration: writes the body's
|
|
490
|
+
* Transform directly and wakes it. For an interpolated body this also flags a
|
|
491
|
+
* render `snap` on its {@link Interpolated} component, so the producer keeps
|
|
492
|
+
* this pose (rather than restoring the previous tick over it) and the
|
|
493
|
+
* renderer shows the new pose without sliding across the jump.
|
|
494
|
+
*
|
|
495
|
+
* This is the authoritative way to reposition an interpolated body — a raw
|
|
496
|
+
* `Transform` write would be undone by the per-step restore. Velocity is left
|
|
497
|
+
* as-is; zero it via {@link setLinearVelocity} if the teleport should also
|
|
498
|
+
* stop the body.
|
|
499
|
+
*
|
|
500
|
+
* @param {RigidBody} rigidBody
|
|
501
|
+
* @param {Vector3|{x:number,y:number,z:number}} position world position
|
|
502
|
+
* @param {Quaternion|{x:number,y:number,z:number,w:number}} rotation world unit-quaternion rotation
|
|
503
|
+
*/
|
|
504
|
+
setPose(rigidBody: RigidBody, position: Vector3 | {
|
|
505
|
+
x: number;
|
|
506
|
+
y: number;
|
|
507
|
+
z: number;
|
|
508
|
+
}, rotation: Quaternion | {
|
|
509
|
+
x: number;
|
|
510
|
+
y: number;
|
|
511
|
+
z: number;
|
|
512
|
+
w: number;
|
|
513
|
+
}): void;
|
|
456
514
|
/**
|
|
457
515
|
* Force the body awake. Static bodies are ignored.
|
|
458
516
|
* @param {RigidBody} rigidBody
|
|
@@ -659,6 +717,27 @@ export class PhysicsSystem extends System<any, any, any, any, any> {
|
|
|
659
717
|
* @private
|
|
660
718
|
*/
|
|
661
719
|
private __dispatch_contact_events;
|
|
720
|
+
/**
|
|
721
|
+
* Producer — restore pass. At the top of a fixed step, reset every awake
|
|
722
|
+
* {@link Interpolated} body's live components to their authoritative state
|
|
723
|
+
* from the previous tick's snapshot, undoing any render-time interpolation
|
|
724
|
+
* the {@link InterpolationSystem} wrote between frames so the sim integrates
|
|
725
|
+
* from truth, not an interpolated pose. A body with no previous snapshot
|
|
726
|
+
* (first step ever, or just woken) is left as-is — its live state is already
|
|
727
|
+
* authoritative. No-op unless {@link interpolationLog} is wired.
|
|
728
|
+
* @private
|
|
729
|
+
*/
|
|
730
|
+
private __interp_restore;
|
|
731
|
+
/**
|
|
732
|
+
* Producer — record pass. At the end of a fixed step, snapshot every awake
|
|
733
|
+
* {@link Interpolated} body's live components into the shared log under the
|
|
734
|
+
* current `entityManager.fixedStepTick`. The render-time
|
|
735
|
+
* {@link InterpolationSystem} blends consecutive ticks from these snapshots.
|
|
736
|
+
* Only awake (moving) bodies are recorded, so the log stays sparse. No-op
|
|
737
|
+
* unless {@link interpolationLog} is wired.
|
|
738
|
+
* @private
|
|
739
|
+
*/
|
|
740
|
+
private __interp_record;
|
|
662
741
|
fixedUpdate(dt: any): void;
|
|
663
742
|
/**
|
|
664
743
|
* @readonly
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhysicsSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/PhysicsSystem.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PhysicsSystem.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/ecs/PhysicsSystem.js"],"names":[],"mappings":"AAkEA;;;;;;;;;;;;;;;;GAgBG;AACH;IAEI,cAkQC;IA/PG,sDAA0C;IAE1C,kKAIC;IAED;;OAEG;IACH,SAFU,WAAW,CAEW;IAEhC;;OAEG;IACH,WAFU,GAAG,CAEa;IAE1B;;OAEG;IACH,YAFU,GAAG,CAEc;IAE3B;;;OAGG;IACH,WAFU,aAAa,CAEa;IAEpC;;;;OAIG;IACH,OAFU,QAAQ,CAES;IAE3B;;;;OAIG;IACH,eAFU,kBAAkB,CAEiB;IAE7C;;;;;;;OAOG;IACH,SAFU,aAAa,CAEW;IAElC;;;;;;OAMG;IACH,2BAFU,MAAM,CAEqB;IAErC;;;;OAIG;IACH,oBAFU,MAAM,CAEa;IAE7B;;;;;;;;;;;OAWG;IACH,UAFU,MAAM,CAEC;IAEjB;;;;;OAKG;IACH,oBAFU,MAAM,CAEW;IAE3B;;;OAGG;IACH,oBAFU,MAAM,CAEW;IAE3B;;;;OAIG;IACH,0BAOC;IAED;;;;OAIG;IACH,kBAFU,OAAO,CAEsB;IAEvC;;;;OAIG;IACH,yBAFU,MAAM,CAEkB;IAElC;;;;OAIG;IACH,wBAFU,MAAM,CAEiB;IAEjC;;;;OAIG;IACH,uBAFU,MAAM,CAEgB;IAEhC;;;;;OAKG;IACH,yBAA4B;IAE5B;;;;;OAKG;IACH,UAFU,SAAS,EAAE,CAEH;IAClB,0BAA0B;IAC1B,cADW,SAAS,EAAE,CACA;IAEtB;;;;;;;;OAQG;IACH,uBAFU,MAAM,MAAM;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,SAAS,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC,CAEpE;IAE/B;;;;;OAKG;IACH,UAFU,OAAO,CAEC;IAElB;;;;OAIG;IACH,qBAAsB;IAEtB;;;;;;OAMG;IACH,iBAFU,MAAM,CAEQ;IAExB;;;;;;;;;;;;;;;;OAgBG;IACH,mBAFU,YAAY,CAEsB;IAE5C;;;;OAIG;IACH,YAFU,OAAO,CAEK;IAEtB;;;;;;;OAOG;IACH,iBAFU,YAAY,CAEoB;IAE1C;;;;;OAKG;IACH,4BAAqE;IAErE;;;;;;;;;OASG;IACH,kBAFU,mBAAiB,IAAI,CAEH;IAE5B;;;;OAIG;IACH,yBAA0C;IAI9C;;;;;;;;;;;;;OAaG;IACH,sBAqBC;IAED;;;;;;;;;;;;;;OAcG;IACH,2BAGC;IAED;;;;;;;;;;OAUG;IACH,gCAOC;IAED;;;OAGG;IACH,cAFW,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAI9C;IAED;;;OAGG;IACH,+BAFqB,MAAM,WAAU,MAAM,aAAY,QAAQ,aAAY,QAAQ,KAAK,OAAO,QAI9F;IAED;;OAEG;IACH,8BAFuB,MAAM,WAAU,MAAM,aAAY,QAAQ,aAAY,QAAQ,KAAK,OAAO,CAIhG;IAED;;;;;;OAMG;IACH,iCA8BC;IAED;;;;OAIG;IACH,iCAIC;IAED;;;;;;;;;;OAUG;IACH,gBAJW,SAAS,aACT,SAAS,UACT,MAAM,QAmBhB;IAED;;;;;;;OAOG;IACH,kBAJW,SAAS,aACT,SAAS,UACT,MAAM,QAkChB;IAED;;;;;;;;;;;;;OAaG;IACH,6BALW,MAAM,YACN,QAAQ,aACR,SAAS,oBACT,MAAM,QAmBhB;IAED;;;;;OAKG;IACH,6BAHW,MAAM,YACN,QAAQ,QAqBlB;IAED;;;;;;;;OAQG;IACH,oCAEC;IAED;;;;;;;;;OASG;IACH,+BAsBC;IAED;;;;OAIG;IACH,iCAMC;IAED;;;;OAIG;IACH,yBAHW,MAAM,GACJ,MAAM,CAKlB;IAED;;;OAGG;IACH,wBAEC;IAED;;;;;;;;;OASG;IACH,wBAHW,SAAS,WACT,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAU9C;IAED;;;;;;;;;;;OAWG;IACH,0BALW,SAAS,aACT,SAAS,WACT,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,cACpC,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAgC9C;IAED;;;;;;;;OAQG;IACH,uBAHW,SAAS,UACT,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAY9C;IAED;;;;;;;;;;;OAWG;IACH,wBALW,SAAS,aACT,SAAS,SACT,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,cACpC,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAuB9C;IAED;;;;;;OAMG;IACH,sBAHW,SAAS,SACT,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAQ9C;IAED;;;;;OAKG;IACH,6BAHW,SAAS,KACT,OAAO,GAAC;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,QAO9C;IAED;;;;;;;;;;;;;;;OAeG;IACH,mBAJW,SAAS,YACT,OAAO,GAAC;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,QA4B1D;IAED;;;OAGG;IACH,gBAFW,SAAS,QAInB;IAED;;;;OAIG;IACH,iBAFW,SAAS,QAYnB;IAED;;;;;;;;;;;;;;OAcG;IACH,oBAgCC;IAED;;;;;;;;;;;;;;OAcG;IACH,oCAgCC;IAED;;;;;OAKG;IACH,2BAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;;;;;;;OAcG;IACH,kEAJmB,MAAM,YAAW,QAAQ,KAAG,OAAO,GAEzC,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,uDALW;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,iDAE7B,MAAM,YAAW,QAAQ,KAAG,OAAO,GACzC,OAAO,CAInB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACH,0CAVW;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,YAE5B;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,UAErC,WAAW,GAAC,MAAM,EAAE,iBACpB,MAAM,oBACE,MAAM,YAAW,QAAQ,KAAG,OAAO,GAEzC,MAAM,CAIlB;IAED;;;;;;OAMG;IACH;;;;;;OAMG;IACH,qBAkBC;IAED;;;;;;;;;;;;OAYG;IACH,sBAmBC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,qBAgEC;IAED;;;;;;;;;OASG;IACH,kCAuDC;IAED;;;;;;;;;OASG;IACH,yBAsCC;IAED;;;;;;;;OAQG;IACH,wBA+BC;IAED,2BA2MC;IAGL;;;OAGG;IACH,0BAFU,OAAO,CAEsB;CANtC;uBA9lDsB,qBAAqB;0BAClB,kCAAkC;0BAuCV,gBAAgB;4CAzCtB,oDAAoD;yBAwCrD,eAAe;4BArCf,wBAAwB;oBAP/C,gCAAgC;8BAYN,6BAA6B;yBADlD,2BAA2B;mCAEC,iCAAiC;8BAIxD,4BAA4B;oBAftC,+BAA+B;mBADhC,uCAAuC;yBA0CjC,eAAe;+BAGT,qBAAqB"}
|