@woosh/meep-engine 2.147.0 → 2.148.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/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts +4 -4
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.d.ts.map +1 -1
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite.js +48 -52
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts +23 -21
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.d.ts.map +1 -1
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_2d.js +41 -406
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts +5 -4
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.d.ts.map +1 -1
- package/src/core/math/spline/spline3_hermite_intersection_spline3_hermite_nd.js +400 -395
- package/src/engine/physics/body/SolverBodyState.d.ts +142 -0
- package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -0
- package/src/engine/physics/body/SolverBodyState.js +251 -0
- package/src/engine/physics/broadphase/generate_pairs.d.ts +2 -1
- package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
- package/src/engine/physics/broadphase/generate_pairs.js +5 -3
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -1
- package/src/engine/physics/constraint/solve_constraints.js +691 -673
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +21 -18
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +223 -91
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts +23 -0
- package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
- package/src/engine/physics/inertia/world_inverse_inertia.js +116 -77
- package/src/engine/physics/integration/integrate_position.d.ts +11 -1
- package/src/engine/physics/integration/integrate_position.d.ts.map +1 -1
- package/src/engine/physics/integration/integrate_position.js +97 -79
- package/src/engine/physics/integration/integrate_velocity.d.ts +12 -3
- package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -1
- package/src/engine/physics/integration/integrate_velocity.js +201 -160
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_box_manifold.js +750 -665
- package/src/engine/physics/narrowphase/box_triangle_contact.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_triangle_contact.js +4 -34
- package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts +16 -0
- package/src/engine/physics/narrowphase/clip_against_axis_uv.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/clip_against_axis_uv.js +49 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +24 -3
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +7 -4
- package/src/engine/physics/solver/solve_contacts.d.ts +2 -2
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +1341 -1173
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* # SolverBodyState — data-oriented mirror of the per-body solver hot state
|
|
3
|
+
*
|
|
4
|
+
* The TGS substep window (contact solver, joint solver, gravity / position
|
|
5
|
+
* integration) reads and writes a small, fixed set of per-body quantities
|
|
6
|
+
* thousands of times per step: linear / angular velocity, inverse mass,
|
|
7
|
+
* inverse-inertia diagonal, and orientation. In the object world those live on
|
|
8
|
+
* the {@link RigidBody} and {@link Transform} *components*, reached via
|
|
9
|
+
* `system.__bodies[idx]` / `system.__transforms[idx]` — a chain of pointer
|
|
10
|
+
* dereferences (array → component object → `Vector3` field) on the hottest
|
|
11
|
+
* inner loop in the engine.
|
|
12
|
+
*
|
|
13
|
+
* This class packs exactly those quantities into one ArrayBuffer-backed,
|
|
14
|
+
* stride-{@link SBS_STRIDE} `Float64Array` indexed by **body slot index** (the
|
|
15
|
+
* same index the rest of the physics system already uses). A body's whole
|
|
16
|
+
* solver state sits in one contiguous span, so the solver reads it with flat
|
|
17
|
+
* typed-array indexing and no object dereference.
|
|
18
|
+
*
|
|
19
|
+
* ## Lifecycle within one `fixedUpdate`
|
|
20
|
+
*
|
|
21
|
+
* - {@link begin} once, after islands are built: ensures capacity and rolls
|
|
22
|
+
* the per-step gather stamp.
|
|
23
|
+
* - {@link gather} every body referenced this step (the awake set + the
|
|
24
|
+
* static / kinematic anchors referenced by contacts and joints). Idempotent
|
|
25
|
+
* per step via the stamp, so callers may gather the same body redundantly.
|
|
26
|
+
* MUST run after the once-per-step force integration (so the gathered
|
|
27
|
+
* velocity is post-force) and before any substep stage reads it.
|
|
28
|
+
* - the substep loop mutates `data` in place.
|
|
29
|
+
* - {@link scatter} once at the end: write the persistent linear / angular
|
|
30
|
+
* velocity back to each gathered body's `RigidBody`. Pose is NOT scattered
|
|
31
|
+
* here — `integrate_position` keeps the authoritative pose on the
|
|
32
|
+
* `Transform` (write-through, so its `onChanged` subscribers and the
|
|
33
|
+
* per-substep concave re-detection still see the moved pose); the
|
|
34
|
+
* orientation quaternion is mirrored into `data` purely for the impulse
|
|
35
|
+
* loop's world-inverse-inertia evaluation.
|
|
36
|
+
*
|
|
37
|
+
* ## Material content
|
|
38
|
+
*
|
|
39
|
+
* For Static / Kinematic bodies `invMass` and the inverse-inertia diagonal are
|
|
40
|
+
* stored as **zero** regardless of the component values — the solver treats
|
|
41
|
+
* "no inverse mass / no inverse inertia" as immovable, which is exactly how the
|
|
42
|
+
* object path's `kind !== Dynamic` guards behave. Velocity is mirrored as-is
|
|
43
|
+
* (a kinematic mover carries a real velocity the contact rows must see; a
|
|
44
|
+
* static reads zero). Scattering velocity back to a non-dynamic body is a
|
|
45
|
+
* no-op in value (the solver never moves it), so scatter need not special-case.
|
|
46
|
+
*
|
|
47
|
+
* The arithmetic the solver performs on this data is identical to the object
|
|
48
|
+
* path — only the *source of the operands* changes — so the engine's
|
|
49
|
+
* same-runtime bit-identical determinism contract is preserved.
|
|
50
|
+
*
|
|
51
|
+
* @author Alex Goldring
|
|
52
|
+
* @copyright Company Named Limited (c) 2026
|
|
53
|
+
*/
|
|
54
|
+
/** Inverse mass (0 for Static / Kinematic). */
|
|
55
|
+
export const SBS_INV_MASS: 0;
|
|
56
|
+
/** Inverse-inertia diagonal, body-local principal frame (0,0,0 for non-dynamic). */
|
|
57
|
+
export const SBS_INV_I_X: 1;
|
|
58
|
+
export const SBS_INV_I_Y: 2;
|
|
59
|
+
export const SBS_INV_I_Z: 3;
|
|
60
|
+
/** Orientation quaternion (mirrors `transform.rotation`, refreshed per substep). */
|
|
61
|
+
export const SBS_QX: 4;
|
|
62
|
+
export const SBS_QY: 5;
|
|
63
|
+
export const SBS_QZ: 6;
|
|
64
|
+
export const SBS_QW: 7;
|
|
65
|
+
/** Persistent linear velocity. */
|
|
66
|
+
export const SBS_LV_X: 8;
|
|
67
|
+
export const SBS_LV_Y: 9;
|
|
68
|
+
export const SBS_LV_Z: 10;
|
|
69
|
+
/** Persistent angular velocity. */
|
|
70
|
+
export const SBS_AV_X: 11;
|
|
71
|
+
export const SBS_AV_Y: 12;
|
|
72
|
+
export const SBS_AV_Z: 13;
|
|
73
|
+
/** Doubles per body. */
|
|
74
|
+
export const SBS_STRIDE: 14;
|
|
75
|
+
export class SolverBodyState {
|
|
76
|
+
constructor(initial_capacity?: number);
|
|
77
|
+
/**
|
|
78
|
+
* Interleaved per-body state, `slot_index * SBS_STRIDE + field`.
|
|
79
|
+
* @type {Float64Array}
|
|
80
|
+
*/
|
|
81
|
+
data: Float64Array;
|
|
82
|
+
/**
|
|
83
|
+
* Per-body "gathered this step" stamp; equals {@link __gen} when the
|
|
84
|
+
* body's slot has been gathered in the current step.
|
|
85
|
+
* @private
|
|
86
|
+
* @type {Int32Array}
|
|
87
|
+
*/
|
|
88
|
+
private __stamp;
|
|
89
|
+
/**
|
|
90
|
+
* Dense list of slot indices gathered this step, for {@link scatter}.
|
|
91
|
+
* @private
|
|
92
|
+
* @type {Uint32Array}
|
|
93
|
+
*/
|
|
94
|
+
private __gathered;
|
|
95
|
+
/** @private */
|
|
96
|
+
private __gathered_count;
|
|
97
|
+
/**
|
|
98
|
+
* Monotonic per-step generation. {@link begin} increments it so the
|
|
99
|
+
* previous step's stamps are stale without an O(n) clear.
|
|
100
|
+
* @private
|
|
101
|
+
*/
|
|
102
|
+
private __gen;
|
|
103
|
+
/** @private */
|
|
104
|
+
private __capacity;
|
|
105
|
+
/**
|
|
106
|
+
* Number of bodies gathered in the current step.
|
|
107
|
+
* @returns {number}
|
|
108
|
+
*/
|
|
109
|
+
get gathered_count(): number;
|
|
110
|
+
/**
|
|
111
|
+
* Ensure the typed arrays can index slot `[0, hwm)` and roll the per-step
|
|
112
|
+
* gather state. Call once per `fixedUpdate`, after islands are built.
|
|
113
|
+
*
|
|
114
|
+
* @param {number} hwm body-storage high-water mark
|
|
115
|
+
*/
|
|
116
|
+
begin(hwm: number): void;
|
|
117
|
+
/**
|
|
118
|
+
* Mirror one body's solver state into `data` if not already gathered this
|
|
119
|
+
* step. Idempotent per step. Reads the body's current (post-force)
|
|
120
|
+
* velocity and current pose.
|
|
121
|
+
*
|
|
122
|
+
* @param {number} idx body slot index
|
|
123
|
+
* @param {RigidBody} rb
|
|
124
|
+
* @param {Transform} transform
|
|
125
|
+
*/
|
|
126
|
+
gather(idx: number, rb: RigidBody, transform: Transform): void;
|
|
127
|
+
/**
|
|
128
|
+
* Write the solved persistent linear / angular velocity back onto every
|
|
129
|
+
* gathered body's `RigidBody`. Direct typed-array writes into the
|
|
130
|
+
* `Vector3` backing — the same observer-bypassing path the solver already
|
|
131
|
+
* uses for velocity (`lv[0] += …`), so no `onChanged` semantics change.
|
|
132
|
+
*
|
|
133
|
+
* @param {RigidBody[]} bodies sparse, indexed by slot
|
|
134
|
+
*/
|
|
135
|
+
scatter(bodies: RigidBody[]): void;
|
|
136
|
+
/**
|
|
137
|
+
* @private
|
|
138
|
+
* @param {number} hwm
|
|
139
|
+
*/
|
|
140
|
+
private __grow;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=SolverBodyState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SolverBodyState.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/body/SolverBodyState.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,+CAA+C;AAC/C,6BAA8B;AAC9B,oFAAoF;AACpF,4BAA6B;AAC7B,4BAA6B;AAC7B,4BAA6B;AAC7B,oFAAoF;AACpF,uBAAwB;AACxB,uBAAwB;AACxB,uBAAwB;AACxB,uBAAwB;AACxB,kCAAkC;AAClC,yBAA0B;AAC1B,yBAA0B;AAC1B,0BAA2B;AAC3B,mCAAmC;AACnC,0BAA2B;AAC3B,0BAA2B;AAC3B,0BAA2B;AAE3B,wBAAwB;AACxB,4BAA6B;AAE7B;IACI,uCAoCC;IAjCG;;;OAGG;IACH,MAFU,YAAY,CAEwB;IAE9C;;;;;OAKG;IACH,gBAAkC;IAElC;;;;OAIG;IACH,mBAAsC;IAEtC,eAAe;IACf,yBAAyB;IAEzB;;;;OAIG;IACH,cAAc;IAEd,eAAe;IACf,mBAAqB;IAGzB;;;OAGG;IACH,6BAEC;IAED;;;;;OAKG;IACH,WAFW,MAAM,QAiBhB;IAED;;;;;;;;OAQG;IACH,YAJW,MAAM,6CA8ChB;IAED;;;;;;;OAOG;IACH,gBAFW,WAAW,QAoBrB;IAED;;;OAGG;IACH,eAcC;CACJ"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { ceilPowerOfTwo } from "../../../core/binary/operations/ceilPowerOfTwo.js";
|
|
2
|
+
import { BodyKind } from "../ecs/BodyKind.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* # SolverBodyState — data-oriented mirror of the per-body solver hot state
|
|
6
|
+
*
|
|
7
|
+
* The TGS substep window (contact solver, joint solver, gravity / position
|
|
8
|
+
* integration) reads and writes a small, fixed set of per-body quantities
|
|
9
|
+
* thousands of times per step: linear / angular velocity, inverse mass,
|
|
10
|
+
* inverse-inertia diagonal, and orientation. In the object world those live on
|
|
11
|
+
* the {@link RigidBody} and {@link Transform} *components*, reached via
|
|
12
|
+
* `system.__bodies[idx]` / `system.__transforms[idx]` — a chain of pointer
|
|
13
|
+
* dereferences (array → component object → `Vector3` field) on the hottest
|
|
14
|
+
* inner loop in the engine.
|
|
15
|
+
*
|
|
16
|
+
* This class packs exactly those quantities into one ArrayBuffer-backed,
|
|
17
|
+
* stride-{@link SBS_STRIDE} `Float64Array` indexed by **body slot index** (the
|
|
18
|
+
* same index the rest of the physics system already uses). A body's whole
|
|
19
|
+
* solver state sits in one contiguous span, so the solver reads it with flat
|
|
20
|
+
* typed-array indexing and no object dereference.
|
|
21
|
+
*
|
|
22
|
+
* ## Lifecycle within one `fixedUpdate`
|
|
23
|
+
*
|
|
24
|
+
* - {@link begin} once, after islands are built: ensures capacity and rolls
|
|
25
|
+
* the per-step gather stamp.
|
|
26
|
+
* - {@link gather} every body referenced this step (the awake set + the
|
|
27
|
+
* static / kinematic anchors referenced by contacts and joints). Idempotent
|
|
28
|
+
* per step via the stamp, so callers may gather the same body redundantly.
|
|
29
|
+
* MUST run after the once-per-step force integration (so the gathered
|
|
30
|
+
* velocity is post-force) and before any substep stage reads it.
|
|
31
|
+
* - the substep loop mutates `data` in place.
|
|
32
|
+
* - {@link scatter} once at the end: write the persistent linear / angular
|
|
33
|
+
* velocity back to each gathered body's `RigidBody`. Pose is NOT scattered
|
|
34
|
+
* here — `integrate_position` keeps the authoritative pose on the
|
|
35
|
+
* `Transform` (write-through, so its `onChanged` subscribers and the
|
|
36
|
+
* per-substep concave re-detection still see the moved pose); the
|
|
37
|
+
* orientation quaternion is mirrored into `data` purely for the impulse
|
|
38
|
+
* loop's world-inverse-inertia evaluation.
|
|
39
|
+
*
|
|
40
|
+
* ## Material content
|
|
41
|
+
*
|
|
42
|
+
* For Static / Kinematic bodies `invMass` and the inverse-inertia diagonal are
|
|
43
|
+
* stored as **zero** regardless of the component values — the solver treats
|
|
44
|
+
* "no inverse mass / no inverse inertia" as immovable, which is exactly how the
|
|
45
|
+
* object path's `kind !== Dynamic` guards behave. Velocity is mirrored as-is
|
|
46
|
+
* (a kinematic mover carries a real velocity the contact rows must see; a
|
|
47
|
+
* static reads zero). Scattering velocity back to a non-dynamic body is a
|
|
48
|
+
* no-op in value (the solver never moves it), so scatter need not special-case.
|
|
49
|
+
*
|
|
50
|
+
* The arithmetic the solver performs on this data is identical to the object
|
|
51
|
+
* path — only the *source of the operands* changes — so the engine's
|
|
52
|
+
* same-runtime bit-identical determinism contract is preserved.
|
|
53
|
+
*
|
|
54
|
+
* @author Alex Goldring
|
|
55
|
+
* @copyright Company Named Limited (c) 2026
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/** Inverse mass (0 for Static / Kinematic). */
|
|
59
|
+
export const SBS_INV_MASS = 0;
|
|
60
|
+
/** Inverse-inertia diagonal, body-local principal frame (0,0,0 for non-dynamic). */
|
|
61
|
+
export const SBS_INV_I_X = 1;
|
|
62
|
+
export const SBS_INV_I_Y = 2;
|
|
63
|
+
export const SBS_INV_I_Z = 3;
|
|
64
|
+
/** Orientation quaternion (mirrors `transform.rotation`, refreshed per substep). */
|
|
65
|
+
export const SBS_QX = 4;
|
|
66
|
+
export const SBS_QY = 5;
|
|
67
|
+
export const SBS_QZ = 6;
|
|
68
|
+
export const SBS_QW = 7;
|
|
69
|
+
/** Persistent linear velocity. */
|
|
70
|
+
export const SBS_LV_X = 8;
|
|
71
|
+
export const SBS_LV_Y = 9;
|
|
72
|
+
export const SBS_LV_Z = 10;
|
|
73
|
+
/** Persistent angular velocity. */
|
|
74
|
+
export const SBS_AV_X = 11;
|
|
75
|
+
export const SBS_AV_Y = 12;
|
|
76
|
+
export const SBS_AV_Z = 13;
|
|
77
|
+
|
|
78
|
+
/** Doubles per body. */
|
|
79
|
+
export const SBS_STRIDE = 14;
|
|
80
|
+
|
|
81
|
+
export class SolverBodyState {
|
|
82
|
+
constructor(initial_capacity = 16) {
|
|
83
|
+
const cap = ceilPowerOfTwo(Math.max(4, initial_capacity));
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Interleaved per-body state, `slot_index * SBS_STRIDE + field`.
|
|
87
|
+
* @type {Float64Array}
|
|
88
|
+
*/
|
|
89
|
+
this.data = new Float64Array(cap * SBS_STRIDE);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Per-body "gathered this step" stamp; equals {@link __gen} when the
|
|
93
|
+
* body's slot has been gathered in the current step.
|
|
94
|
+
* @private
|
|
95
|
+
* @type {Int32Array}
|
|
96
|
+
*/
|
|
97
|
+
this.__stamp = new Int32Array(cap);
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Dense list of slot indices gathered this step, for {@link scatter}.
|
|
101
|
+
* @private
|
|
102
|
+
* @type {Uint32Array}
|
|
103
|
+
*/
|
|
104
|
+
this.__gathered = new Uint32Array(cap);
|
|
105
|
+
|
|
106
|
+
/** @private */
|
|
107
|
+
this.__gathered_count = 0;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Monotonic per-step generation. {@link begin} increments it so the
|
|
111
|
+
* previous step's stamps are stale without an O(n) clear.
|
|
112
|
+
* @private
|
|
113
|
+
*/
|
|
114
|
+
this.__gen = 0;
|
|
115
|
+
|
|
116
|
+
/** @private */
|
|
117
|
+
this.__capacity = cap;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Number of bodies gathered in the current step.
|
|
122
|
+
* @returns {number}
|
|
123
|
+
*/
|
|
124
|
+
get gathered_count() {
|
|
125
|
+
return this.__gathered_count;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Ensure the typed arrays can index slot `[0, hwm)` and roll the per-step
|
|
130
|
+
* gather state. Call once per `fixedUpdate`, after islands are built.
|
|
131
|
+
*
|
|
132
|
+
* @param {number} hwm body-storage high-water mark
|
|
133
|
+
*/
|
|
134
|
+
begin(hwm) {
|
|
135
|
+
if (hwm > this.__capacity) {
|
|
136
|
+
this.__grow(hwm);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Roll the generation; on (astronomically unlikely) Int32 wrap, clear
|
|
140
|
+
// stamps so a recycled generation value can't read as "gathered".
|
|
141
|
+
const next = (this.__gen + 1) | 0;
|
|
142
|
+
if (next <= 0) {
|
|
143
|
+
this.__stamp.fill(0);
|
|
144
|
+
this.__gen = 1;
|
|
145
|
+
} else {
|
|
146
|
+
this.__gen = next;
|
|
147
|
+
}
|
|
148
|
+
this.__gathered_count = 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Mirror one body's solver state into `data` if not already gathered this
|
|
153
|
+
* step. Idempotent per step. Reads the body's current (post-force)
|
|
154
|
+
* velocity and current pose.
|
|
155
|
+
*
|
|
156
|
+
* @param {number} idx body slot index
|
|
157
|
+
* @param {RigidBody} rb
|
|
158
|
+
* @param {Transform} transform
|
|
159
|
+
*/
|
|
160
|
+
gather(idx, rb, transform) {
|
|
161
|
+
const stamp = this.__stamp;
|
|
162
|
+
if (stamp[idx] === this.__gen) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
stamp[idx] = this.__gen;
|
|
166
|
+
this.__gathered[this.__gathered_count++] = idx;
|
|
167
|
+
|
|
168
|
+
const d = this.data;
|
|
169
|
+
const base = idx * SBS_STRIDE;
|
|
170
|
+
|
|
171
|
+
const dynamic = rb.kind === BodyKind.Dynamic;
|
|
172
|
+
if (dynamic) {
|
|
173
|
+
d[base + SBS_INV_MASS] = rb.mass > 0 ? 1 / rb.mass : 0;
|
|
174
|
+
const ii = rb.inverseInertiaLocal;
|
|
175
|
+
d[base + SBS_INV_I_X] = ii.x;
|
|
176
|
+
d[base + SBS_INV_I_Y] = ii.y;
|
|
177
|
+
d[base + SBS_INV_I_Z] = ii.z;
|
|
178
|
+
} else {
|
|
179
|
+
// Static / Kinematic: immovable to the solver — no inverse mass,
|
|
180
|
+
// no inverse inertia (mirrors the object path's `kind` guards).
|
|
181
|
+
d[base + SBS_INV_MASS] = 0;
|
|
182
|
+
d[base + SBS_INV_I_X] = 0;
|
|
183
|
+
d[base + SBS_INV_I_Y] = 0;
|
|
184
|
+
d[base + SBS_INV_I_Z] = 0;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const q = transform.rotation;
|
|
188
|
+
d[base + SBS_QX] = q[0];
|
|
189
|
+
d[base + SBS_QY] = q[1];
|
|
190
|
+
d[base + SBS_QZ] = q[2];
|
|
191
|
+
d[base + SBS_QW] = q[3];
|
|
192
|
+
|
|
193
|
+
const lv = rb.linearVelocity;
|
|
194
|
+
d[base + SBS_LV_X] = lv[0];
|
|
195
|
+
d[base + SBS_LV_Y] = lv[1];
|
|
196
|
+
d[base + SBS_LV_Z] = lv[2];
|
|
197
|
+
|
|
198
|
+
const av = rb.angularVelocity;
|
|
199
|
+
d[base + SBS_AV_X] = av[0];
|
|
200
|
+
d[base + SBS_AV_Y] = av[1];
|
|
201
|
+
d[base + SBS_AV_Z] = av[2];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Write the solved persistent linear / angular velocity back onto every
|
|
206
|
+
* gathered body's `RigidBody`. Direct typed-array writes into the
|
|
207
|
+
* `Vector3` backing — the same observer-bypassing path the solver already
|
|
208
|
+
* uses for velocity (`lv[0] += …`), so no `onChanged` semantics change.
|
|
209
|
+
*
|
|
210
|
+
* @param {RigidBody[]} bodies sparse, indexed by slot
|
|
211
|
+
*/
|
|
212
|
+
scatter(bodies) {
|
|
213
|
+
const d = this.data;
|
|
214
|
+
const list = this.__gathered;
|
|
215
|
+
const n = this.__gathered_count;
|
|
216
|
+
for (let i = 0; i < n; i++) {
|
|
217
|
+
const idx = list[i];
|
|
218
|
+
const rb = bodies[idx];
|
|
219
|
+
if (rb === undefined) continue;
|
|
220
|
+
const base = idx * SBS_STRIDE;
|
|
221
|
+
const lv = rb.linearVelocity;
|
|
222
|
+
lv[0] = d[base + SBS_LV_X];
|
|
223
|
+
lv[1] = d[base + SBS_LV_Y];
|
|
224
|
+
lv[2] = d[base + SBS_LV_Z];
|
|
225
|
+
const av = rb.angularVelocity;
|
|
226
|
+
av[0] = d[base + SBS_AV_X];
|
|
227
|
+
av[1] = d[base + SBS_AV_Y];
|
|
228
|
+
av[2] = d[base + SBS_AV_Z];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @private
|
|
234
|
+
* @param {number} hwm
|
|
235
|
+
*/
|
|
236
|
+
__grow(hwm) {
|
|
237
|
+
const cap = ceilPowerOfTwo(hwm);
|
|
238
|
+
const next_data = new Float64Array(cap * SBS_STRIDE);
|
|
239
|
+
const next_stamp = new Int32Array(cap);
|
|
240
|
+
const next_gathered = new Uint32Array(cap);
|
|
241
|
+
// No need to copy `data` — it is fully repopulated by `gather` each
|
|
242
|
+
// step before any read. `__stamp` must NOT carry stale gen values into
|
|
243
|
+
// the grown region; a fresh zero-filled array plus the live `__gen`
|
|
244
|
+
// (always >= 1 after begin) guarantees grown slots read as un-gathered.
|
|
245
|
+
next_stamp.set(this.__stamp);
|
|
246
|
+
this.data = next_data;
|
|
247
|
+
this.__stamp = next_stamp;
|
|
248
|
+
this.__gathered = next_gathered;
|
|
249
|
+
this.__capacity = cap;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -28,11 +28,12 @@
|
|
|
28
28
|
* slot, no narrowphase, no contact events. Existing cached
|
|
29
29
|
* manifolds for a rejected pair time out naturally via the
|
|
30
30
|
* manifold-store grace counter.
|
|
31
|
+
* @param {*} [pair_filter_this_arg]
|
|
31
32
|
*/
|
|
32
33
|
export function generate_pairs(storage: BodyStorage, dynamic_bvh: BVH, static_bvh: BVH, manifolds: ManifoldStore, body_collider_lists: Array<Array<{
|
|
33
34
|
collider: Collider;
|
|
34
35
|
transform: Transform;
|
|
35
36
|
entity: number;
|
|
36
37
|
bvhNode: number;
|
|
37
|
-
}>>, pair_list_out: PairList, pair_filter?: (idA: number, idB: number) => boolean): void;
|
|
38
|
+
}>>, pair_list_out: PairList, pair_filter?: (idA: number, idB: number) => boolean, pair_filter_this_arg?: any): void;
|
|
38
39
|
//# sourceMappingURL=generate_pairs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate_pairs.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/generate_pairs.js"],"names":[],"mappings":"AAMA
|
|
1
|
+
{"version":3,"file":"generate_pairs.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/broadphase/generate_pairs.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,uIATW,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,oCA8EhD"}
|
|
@@ -34,6 +34,7 @@ const candidates = new Uint32Array(1024);
|
|
|
34
34
|
* slot, no narrowphase, no contact events. Existing cached
|
|
35
35
|
* manifolds for a rejected pair time out naturally via the
|
|
36
36
|
* manifold-store grace counter.
|
|
37
|
+
* @param {*} [pair_filter_this_arg]
|
|
37
38
|
*/
|
|
38
39
|
export function generate_pairs(
|
|
39
40
|
storage,
|
|
@@ -42,7 +43,8 @@ export function generate_pairs(
|
|
|
42
43
|
manifolds,
|
|
43
44
|
body_collider_lists,
|
|
44
45
|
pair_list_out,
|
|
45
|
-
pair_filter = null
|
|
46
|
+
pair_filter = null,
|
|
47
|
+
pair_filter_this_arg = null,
|
|
46
48
|
) {
|
|
47
49
|
pair_list_out.clear();
|
|
48
50
|
|
|
@@ -80,7 +82,7 @@ export function generate_pairs(
|
|
|
80
82
|
|
|
81
83
|
const existing = manifolds.find(idA, idB);
|
|
82
84
|
if (existing !== -1 && manifolds.is_touched(existing)) continue;
|
|
83
|
-
if (pair_filter !== null && !pair_filter(idA, idB)) continue;
|
|
85
|
+
if (pair_filter !== null && !pair_filter.call(pair_filter_this_arg, idA, idB)) continue;
|
|
84
86
|
manifolds.acquire(idA, idB);
|
|
85
87
|
pair_list_out.push(idA, idB);
|
|
86
88
|
}
|
|
@@ -99,7 +101,7 @@ export function generate_pairs(
|
|
|
99
101
|
|
|
100
102
|
const existing = manifolds.find(idA, idB);
|
|
101
103
|
if (existing !== -1 && manifolds.is_touched(existing)) continue;
|
|
102
|
-
if (pair_filter !== null && !pair_filter(idA, idB)) continue;
|
|
104
|
+
if (pair_filter !== null && !pair_filter.call(pair_filter_this_arg, idA, idB)) continue;
|
|
103
105
|
manifolds.acquire(idA, idB);
|
|
104
106
|
pair_list_out.push(idA, idB);
|
|
105
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solve_constraints.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/constraint/solve_constraints.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"solve_constraints.d.ts","sourceRoot":"","sources":["../../../../../src/engine/physics/constraint/solve_constraints.js"],"names":[],"mappings":"AAiOA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,sCAHW,MAAM,MAAa,MAAM,MAAa,MAAM,MAAa,MAAM,OAC/D,YAAY,QAkCtB;AA0JD;;;;;;;;;;;;;GAaG;AACH,qCANW,OAAO,iCAEP,MAAM,SAEN,MAAM,QAsPhB"}
|