@forgeax/engine-physics 0.1.27 → 0.1.28
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/README.md +115 -1
- package/dist/__tests__/derived-physics.unit.test.d.ts +2 -0
- package/dist/__tests__/derived-physics.unit.test.d.ts.map +1 -0
- package/dist/derived-physics.d.ts +218 -0
- package/dist/derived-physics.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +415 -2
- package/dist/index.mjs.map +1 -1
- package/dist/physics-world.d.ts +60 -2
- package/dist/physics-world.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/__tests__/derived-physics.unit.test.ts +156 -0
- package/src/derived-physics.ts +740 -0
- package/src/index.ts +31 -0
- package/src/physics-world.ts +79 -2
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Three ECS systems run in order every frame (registered by `physicsPlugin` during
|
|
|
39
39
|
|
|
40
40
|
| Phase | System Name | Runs After | What It Does |
|
|
41
41
|
|:--|:--|:--|:--|
|
|
42
|
-
| 1. Sync | `physicsSyncBackend` | `propagateTransforms` |
|
|
42
|
+
| 1. Sync | `physicsSyncBackend` | `propagateTransforms` | Reconciles Transform-bearing entities with Collider or RigidBody; a RigidBody-only entity creates a native body without a placeholder collider |
|
|
43
43
|
| 2. Step | `physicsStepSimulation` | `physicsSyncBackend` | Reads the constant `FixedTime.delta`; calls `PhysicsWorld.step()` once per bounded fixed iteration |
|
|
44
44
|
| 3. Writeback | `physicsWriteback` | `physicsStepSimulation` | Calls `writebackDynamicBodies()`; writes dynamic-body pose back to ECS `Transform` |
|
|
45
45
|
|
|
@@ -232,3 +232,117 @@ vectors, or backend World objects through App, Preview, or Remote.
|
|
|
232
232
|
On failure, branch on `error.code`, read `expected`, `hint`, and the narrowed
|
|
233
233
|
`detail`, then rebuild the participant or target named by the hint. A physics
|
|
234
234
|
participant is not a network rollback store, RHI tape, or game replay owner.
|
|
235
|
+
|
|
236
|
+
## Derived voxel shape candidates (3D)
|
|
237
|
+
|
|
238
|
+
A Transform-bearing RigidBody can receive derived shapes without an ordinary
|
|
239
|
+
Collider. Adding, editing, or removing an ordinary Collider preserves committed
|
|
240
|
+
derived shapes on that same body. Prepared native shapes are disabled and
|
|
241
|
+
massless; only the admitted shape set contributes automatic density.
|
|
242
|
+
|
|
243
|
+
For paired standard geometry, pass the optional synchronous `commitGeometry`
|
|
244
|
+
argument to `admitDerivedShapeCandidate`. Physics invokes this once after native
|
|
245
|
+
staging and before step/publication; failure rolls back through the same native
|
|
246
|
+
old-state restoration as an admission failure. The callback performs only the
|
|
247
|
+
complete Renderer binding commit and returns its Result. It must not query physics,
|
|
248
|
+
draw, enqueue more work, or perform fallible work after a successful binding change.
|
|
249
|
+
The borrowed `getDerivedAdmission(entity)` proof exists only in that interval;
|
|
250
|
+
publications remain unavailable until the normal step/writeback boundary. See the
|
|
251
|
+
[paired Render example](../render/README.md#paired-physics-admission).
|
|
252
|
+
|
|
253
|
+
| Paired result | Observable state |
|
|
254
|
+
|:--|:--|
|
|
255
|
+
| Native staging fails | Geometry commit not called; old state retained or explicit rebuild required |
|
|
256
|
+
| Geometry refuses | Native rollback; no new physics publication; old MeshFilter retained |
|
|
257
|
+
| Geometry callback throws | Its ECS writes are uncertain; physics queries and rendering stop with explicit rebuild-required state |
|
|
258
|
+
| Geometry succeeds | Step and writeback precede physics publication; Renderer draw follows World update |
|
|
259
|
+
| Zero fixed steps | Both candidates stay pending and old state remains visible |
|
|
260
|
+
|
|
261
|
+
Wave 1 keeps derived geometry inside the one `PhysicsWorld`. A consumer submits
|
|
262
|
+
an immutable, standard-data description; the Rapier 3D owner creates disabled
|
|
263
|
+
native `Voxels` colliders during preparation, then admits the whole candidate at
|
|
264
|
+
the next fixed-step boundary. No Rapier handle, native world, worker, or second
|
|
265
|
+
transaction registry crosses this API.
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
import type { PhysicsWorld, DerivedPhysicsCandidateInput } from '@forgeax/engine-physics';
|
|
269
|
+
|
|
270
|
+
declare const physics: PhysicsWorld;
|
|
271
|
+
declare const candidateInput: DerivedPhysicsCandidateInput;
|
|
272
|
+
|
|
273
|
+
const prepared = physics.prepareDerivedShapeCandidate?.(candidateInput);
|
|
274
|
+
if (prepared?.ok) {
|
|
275
|
+
const admitted = physics.admitDerivedShapeCandidate?.(prepared.value);
|
|
276
|
+
if (admitted?.ok) {
|
|
277
|
+
// Physics systems call step() from FixedUpdate. In an ECS-bound world the
|
|
278
|
+
// publication becomes visible only after physicsWriteback and
|
|
279
|
+
// physicsCollisionSync complete; direct PhysicsWorld consumers finalize in
|
|
280
|
+
// step() because they have no ECS writeback phase.
|
|
281
|
+
void physics.getDerivedPublication?.(candidateInput.entity);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The fixed-step ownership is deliberately small:
|
|
287
|
+
|
|
288
|
+
```mermaid
|
|
289
|
+
sequenceDiagram
|
|
290
|
+
participant U as Update consumer
|
|
291
|
+
participant P as PhysicsWorld
|
|
292
|
+
participant R as Rapier World
|
|
293
|
+
U->>P: prepareDerivedShapeCandidate(input)
|
|
294
|
+
P->>R: create disabled Voxels per local Shape
|
|
295
|
+
U->>P: admitDerivedShapeCandidate(candidate)
|
|
296
|
+
P->>R: activate candidate before step
|
|
297
|
+
P->>R: step + refresh queries
|
|
298
|
+
P-->>U: publication/contact facts at fixedStep
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
`VoxelShapeInput.cells` is a contiguous integer `x,y,z` `Int32Array` (or a
|
|
302
|
+
tuple list), `voxelSize` is positive, and `origin` is local. A cell at
|
|
303
|
+
`[i,j,k]` occupies the local box whose center is
|
|
304
|
+
`((i + 0.5) * sx, (j + 0.5) * sy, (k + 0.5) * sz)`; negative coordinates stay
|
|
305
|
+
negative and are never rounded through a chunk index. A seam is accepted only
|
|
306
|
+
when both Shapes have equal voxel size, quaternion-equivalent orientation, and
|
|
307
|
+
an integer grid offset that matches `originB - originA` in that grid. Different
|
|
308
|
+
grid sizes, unaligned rotations, origin/offset mismatches, or different Body
|
|
309
|
+
identities return `derived-seam-invalid` rather than silently coupling shapes.
|
|
310
|
+
|
|
311
|
+
The candidate may also carry a body type, explicit mass/center of mass/principal
|
|
312
|
+
inertia (including its principal frame), a `preserve | reset` velocity policy,
|
|
313
|
+
an explicit `motion` snapshot (`centerOfMass`, `linearVelocity`, and
|
|
314
|
+
`angularVelocity`), and bounded spring/hinge updates. Every candidate carries a producer
|
|
315
|
+
`sourceKey` and revision. Every constraint endpoint carries a
|
|
316
|
+
`{ sourceKey, revision }` dependency; migration is rejected when either end is
|
|
317
|
+
stale or missing, and these dependencies are included in the portable
|
|
318
|
+
snapshot. Explicit mass zeros collider density before
|
|
319
|
+
Rapier applies the authored mass properties, so the same density is not counted
|
|
320
|
+
twice. With `preserve`, the committed linear velocity follows
|
|
321
|
+
`v_new = v_old + omega_old x (COM_new - COM_old)` and angular velocity is
|
|
322
|
+
retained; `reset` intentionally clears both. Constraints use the same Rapier
|
|
323
|
+
solver and expose only the consumer's stable `id` and revision.
|
|
324
|
+
|
|
325
|
+
Preparation and cancellation are non-visible. A stale revision, duplicate
|
|
326
|
+
Shape identity, invalid mass, pending duplicate, missing Body, or bounded
|
|
327
|
+
candidate overflow returns `DerivedPhysicsError` with `code`, `expected`,
|
|
328
|
+
`hint`, and narrowed `detail`; the last publication remains intact. A
|
|
329
|
+
PhysicsWorld bounds 32 in-flight candidates, 64 shapes/64 constraints and
|
|
330
|
+
8 MiB of staged candidate data (with a 262144-cell per-candidate ceiling).
|
|
331
|
+
If a native operation fails after admission, `getDerivedFailure(entity)` returns
|
|
332
|
+
a structured failure receipt and the candidate is failed/cleaned while the
|
|
333
|
+
prior body, shapes and constraints remain queryable; the backend never silently
|
|
334
|
+
swallows the native error. `getContactObservations()` contains only detached facts from the real Rapier
|
|
335
|
+
event drain: `fixedStep`, entity identities, optional Shape identities, and
|
|
336
|
+
optional sampled point/normal. It does not claim impulse or energy data.
|
|
337
|
+
|
|
338
|
+
For explicit recovery, call `captureDerivedPhysicsState()` only at a committed
|
|
339
|
+
boundary. The returned cells, Shape revisions, seams, mass policy, velocity
|
|
340
|
+
policy, committed COM/linear/angular motion, and constraint inputs are portable;
|
|
341
|
+
`restoreDerivedPhysicsState()` admits the complete snapshot as one dependency-
|
|
342
|
+
consistent batch, so a two-body constraint is never restored against a stale
|
|
343
|
+
endpoint and native handles/pending candidates are never serialized. A native
|
|
344
|
+
failure after mass/body/constraint mutation either restores the complete old
|
|
345
|
+
state and exposes `old-state-retained`, or reports `rebuild-required` and blocks
|
|
346
|
+
queries; it is never reported as a ready partial commit. Device or World teardown
|
|
347
|
+
invalidates pending work; the 2D `PhysicsWorld2D` contract remains unchanged and
|
|
348
|
+
does not pretend to support 3D voxel shapes.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derived-physics.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/derived-physics.unit.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { type Result } from '@forgeax/engine-types';
|
|
2
|
+
/** A portable integer grid coordinate. */
|
|
3
|
+
export type VoxelCell = readonly [number, number, number];
|
|
4
|
+
/** A portable quaternion used by derived-physics inputs. */
|
|
5
|
+
export type PhysicsQuaternion = readonly [number, number, number, number];
|
|
6
|
+
/** A portable three-component vector used by derived-physics inputs. */
|
|
7
|
+
export type PhysicsVector = readonly [number, number, number];
|
|
8
|
+
/**
|
|
9
|
+
* One local voxel shape. `cells` contains contiguous x/y/z triples. The
|
|
10
|
+
* backend copies it while preparing a candidate, so callers may reuse their
|
|
11
|
+
* scratch buffer after the call returns.
|
|
12
|
+
*/
|
|
13
|
+
export interface VoxelShapeInput {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly revision: number;
|
|
16
|
+
readonly cells: Int32Array | readonly VoxelCell[];
|
|
17
|
+
readonly voxelSize: PhysicsVector;
|
|
18
|
+
readonly origin?: PhysicsVector;
|
|
19
|
+
readonly rotation?: PhysicsQuaternion;
|
|
20
|
+
readonly friction?: number;
|
|
21
|
+
readonly restitution?: number;
|
|
22
|
+
readonly density?: number;
|
|
23
|
+
readonly isSensor?: boolean;
|
|
24
|
+
readonly collisionGroups?: number;
|
|
25
|
+
readonly solverGroups?: number;
|
|
26
|
+
}
|
|
27
|
+
/** Stable producer identity and revision for one constraint endpoint. */
|
|
28
|
+
export interface PhysicsConstraintBodyDependency {
|
|
29
|
+
readonly sourceKey: string;
|
|
30
|
+
readonly revision: number;
|
|
31
|
+
}
|
|
32
|
+
/** Explicit or density-derived rigid-body mass properties. */
|
|
33
|
+
export type PhysicsMassProperties = {
|
|
34
|
+
readonly mode: 'automatic';
|
|
35
|
+
readonly density?: number;
|
|
36
|
+
} | {
|
|
37
|
+
readonly mode: 'explicit';
|
|
38
|
+
readonly mass: number;
|
|
39
|
+
readonly centerOfMass: PhysicsVector;
|
|
40
|
+
readonly principalInertia: PhysicsVector;
|
|
41
|
+
readonly principalInertiaLocalFrame?: PhysicsQuaternion;
|
|
42
|
+
};
|
|
43
|
+
/** How a topology replacement carries the committed body's motion. */
|
|
44
|
+
export type PhysicsVelocityPolicy = 'preserve' | 'reset';
|
|
45
|
+
/**
|
|
46
|
+
* Consumer-visible movement state for one committed derived body.
|
|
47
|
+
*
|
|
48
|
+
* `centerOfMass` is world-space (the same frame as the body's transform),
|
|
49
|
+
* while both velocity vectors are world-space. Keeping this as one POD
|
|
50
|
+
* value makes snapshot/recovery carry the complete motion boundary instead
|
|
51
|
+
* of exposing Rapier objects or asking consumers to infer velocity from
|
|
52
|
+
* successive transforms.
|
|
53
|
+
*/
|
|
54
|
+
export interface DerivedPhysicsMotion {
|
|
55
|
+
readonly centerOfMass: PhysicsVector;
|
|
56
|
+
readonly linearVelocity: PhysicsVector;
|
|
57
|
+
readonly angularVelocity: PhysicsVector;
|
|
58
|
+
}
|
|
59
|
+
/** Stable, consumer-owned constraint input. */
|
|
60
|
+
export type PhysicsConstraintInput = {
|
|
61
|
+
readonly id: string;
|
|
62
|
+
readonly revision: number;
|
|
63
|
+
readonly kind: 'spring';
|
|
64
|
+
readonly bodyA: number;
|
|
65
|
+
readonly bodyB: number;
|
|
66
|
+
readonly bodyASource: PhysicsConstraintBodyDependency;
|
|
67
|
+
readonly bodyBSource: PhysicsConstraintBodyDependency;
|
|
68
|
+
readonly anchorA: PhysicsVector;
|
|
69
|
+
readonly anchorB: PhysicsVector;
|
|
70
|
+
readonly restLength: number;
|
|
71
|
+
readonly stiffness: number;
|
|
72
|
+
readonly damping: number;
|
|
73
|
+
} | {
|
|
74
|
+
readonly id: string;
|
|
75
|
+
readonly revision: number;
|
|
76
|
+
readonly kind: 'hinge';
|
|
77
|
+
readonly bodyA: number;
|
|
78
|
+
readonly bodyB: number;
|
|
79
|
+
readonly bodyASource: PhysicsConstraintBodyDependency;
|
|
80
|
+
readonly bodyBSource: PhysicsConstraintBodyDependency;
|
|
81
|
+
readonly anchorA: PhysicsVector;
|
|
82
|
+
readonly anchorB: PhysicsVector;
|
|
83
|
+
readonly axis: PhysicsVector;
|
|
84
|
+
readonly limits?: readonly [number, number];
|
|
85
|
+
};
|
|
86
|
+
/** All data needed to prepare one body's derived shape replacement. */
|
|
87
|
+
export interface DerivedPhysicsCandidateInput {
|
|
88
|
+
readonly entity: number;
|
|
89
|
+
readonly revision: number;
|
|
90
|
+
readonly sourceKey: string;
|
|
91
|
+
readonly shapes: readonly VoxelShapeInput[];
|
|
92
|
+
readonly seams?: readonly DerivedShapeSeamInput[];
|
|
93
|
+
readonly bodyType?: 'static' | 'dynamic' | 'kinematic';
|
|
94
|
+
readonly massProperties?: PhysicsMassProperties;
|
|
95
|
+
readonly velocityPolicy?: PhysicsVelocityPolicy;
|
|
96
|
+
/** Optional committed motion to restore after native mass admission. */
|
|
97
|
+
readonly motion?: DerivedPhysicsMotion;
|
|
98
|
+
readonly constraints?: readonly PhysicsConstraintInput[];
|
|
99
|
+
/** Optional World identity; it is checked when the backend is ECS-bound. */
|
|
100
|
+
readonly worldIdentity?: object;
|
|
101
|
+
}
|
|
102
|
+
/** A same-body integer-grid seam maintained by the Rapier voxel backend. */
|
|
103
|
+
export interface DerivedShapeSeamInput {
|
|
104
|
+
readonly shapeA: string;
|
|
105
|
+
readonly shapeB: string;
|
|
106
|
+
/** Grid-space origin of B relative to A; all components must be integers. */
|
|
107
|
+
readonly offset: PhysicsVector;
|
|
108
|
+
}
|
|
109
|
+
/** Candidate lifecycle visible to a consumer. */
|
|
110
|
+
export type DerivedPhysicsCandidateState = 'ready' | 'queued' | 'published' | 'cancelled' | 'invalidated' | 'failed';
|
|
111
|
+
/** Opaque-enough prepared candidate. Native handles never cross this type. */
|
|
112
|
+
export interface DerivedPhysicsCandidate {
|
|
113
|
+
readonly candidateId: string;
|
|
114
|
+
readonly generation: number;
|
|
115
|
+
/** Per-PhysicsWorld owner identity; candidate IDs are not global. */
|
|
116
|
+
readonly owner: object;
|
|
117
|
+
readonly input: Readonly<DerivedPhysicsCandidateInput>;
|
|
118
|
+
readonly state: DerivedPhysicsCandidateState;
|
|
119
|
+
}
|
|
120
|
+
/** Stable receipt emitted when a candidate becomes the committed shape set. */
|
|
121
|
+
export interface DerivedPhysicsPublication {
|
|
122
|
+
readonly candidateId: string;
|
|
123
|
+
readonly entity: number;
|
|
124
|
+
readonly revision: number;
|
|
125
|
+
readonly fixedStep: number;
|
|
126
|
+
readonly shapeIds: readonly string[];
|
|
127
|
+
readonly generation: number;
|
|
128
|
+
}
|
|
129
|
+
/** Structured admission failure that leaves the prior publication queryable. */
|
|
130
|
+
export interface DerivedPhysicsFailure {
|
|
131
|
+
readonly candidateId: string;
|
|
132
|
+
readonly entity: number;
|
|
133
|
+
readonly revision: number;
|
|
134
|
+
readonly fixedStep: number;
|
|
135
|
+
readonly error: DerivedPhysicsError;
|
|
136
|
+
readonly recovery: 'old-state-retained' | 'rebuild-required';
|
|
137
|
+
}
|
|
138
|
+
/** Public projection of an active local shape. */
|
|
139
|
+
export interface DerivedShapeState {
|
|
140
|
+
readonly id: string;
|
|
141
|
+
readonly revision: number;
|
|
142
|
+
readonly entity: number;
|
|
143
|
+
readonly voxelSize: PhysicsVector;
|
|
144
|
+
readonly origin: PhysicsVector;
|
|
145
|
+
readonly rotation: PhysicsQuaternion;
|
|
146
|
+
readonly generation: number;
|
|
147
|
+
}
|
|
148
|
+
/** Real backend contact observation, including stable shape identity when known. */
|
|
149
|
+
export interface PhysicsContactObservation {
|
|
150
|
+
readonly phase: 'started' | 'stopped';
|
|
151
|
+
readonly fixedStep: number;
|
|
152
|
+
readonly entityA: number;
|
|
153
|
+
readonly entityB: number;
|
|
154
|
+
readonly shapeA?: string;
|
|
155
|
+
readonly shapeB?: string;
|
|
156
|
+
readonly point?: PhysicsVector;
|
|
157
|
+
readonly normal?: PhysicsVector;
|
|
158
|
+
}
|
|
159
|
+
/** Portable recovery input produced from a committed derived state. */
|
|
160
|
+
export interface DerivedPhysicsSnapshot {
|
|
161
|
+
readonly generation: number;
|
|
162
|
+
readonly fixedStep: number;
|
|
163
|
+
readonly bodies: readonly {
|
|
164
|
+
readonly entity: number;
|
|
165
|
+
readonly revision: number;
|
|
166
|
+
readonly sourceKey: string;
|
|
167
|
+
readonly shapes: readonly VoxelShapeInput[];
|
|
168
|
+
readonly seams?: readonly DerivedShapeSeamInput[];
|
|
169
|
+
readonly bodyType?: 'static' | 'dynamic' | 'kinematic';
|
|
170
|
+
readonly massProperties?: PhysicsMassProperties;
|
|
171
|
+
readonly velocityPolicy?: PhysicsVelocityPolicy;
|
|
172
|
+
/** Committed world-space COM and velocities at capture time. */
|
|
173
|
+
readonly motion?: DerivedPhysicsMotion;
|
|
174
|
+
readonly constraints: readonly PhysicsConstraintInput[];
|
|
175
|
+
}[];
|
|
176
|
+
}
|
|
177
|
+
export type DerivedPhysicsErrorCode = 'derived-physics-disposed' | 'derived-body-not-found' | 'derived-world-mismatch' | 'derived-candidate-not-found' | 'derived-candidate-stale' | 'derived-candidate-pending' | 'derived-candidate-cancelled' | 'derived-candidate-invalid' | 'derived-candidate-budget-exceeded' | 'derived-shape-invalid' | 'derived-shape-duplicate' | 'derived-seam-invalid' | 'derived-mass-invalid' | 'derived-constraint-invalid' | 'derived-constraint-not-found' | 'derived-constraint-stale' | 'derived-backend-failed' | 'derived-recovery-invalid';
|
|
178
|
+
/** Bounded derived-physics preparation envelope. */
|
|
179
|
+
export declare const DERIVED_PHYSICS_LIMITS: Readonly<{
|
|
180
|
+
maxCandidates: 32;
|
|
181
|
+
maxShapesPerCandidate: 64;
|
|
182
|
+
maxConstraintsPerCandidate: 64;
|
|
183
|
+
maxCellsPerCandidate: 262144;
|
|
184
|
+
maxCandidateBytes: number;
|
|
185
|
+
}>;
|
|
186
|
+
export interface DerivedPhysicsErrorDetail {
|
|
187
|
+
readonly code: DerivedPhysicsErrorCode;
|
|
188
|
+
readonly entity?: number;
|
|
189
|
+
readonly candidateId?: string;
|
|
190
|
+
readonly shapeId?: string;
|
|
191
|
+
readonly constraintId?: string;
|
|
192
|
+
readonly expected?: string;
|
|
193
|
+
readonly actual?: unknown;
|
|
194
|
+
readonly reason?: string;
|
|
195
|
+
}
|
|
196
|
+
/** Closed, structured failure for the public derived-physics surface. */
|
|
197
|
+
export declare class DerivedPhysicsError extends Error {
|
|
198
|
+
readonly code: DerivedPhysicsErrorCode;
|
|
199
|
+
readonly expected: string;
|
|
200
|
+
readonly hint: string;
|
|
201
|
+
readonly detail: DerivedPhysicsErrorDetail;
|
|
202
|
+
constructor(code: DerivedPhysicsErrorCode, expected: string, hint: string, detail?: Omit<DerivedPhysicsErrorDetail, 'code'>);
|
|
203
|
+
}
|
|
204
|
+
/** Validate and snapshot one voxel input before native resources are created. */
|
|
205
|
+
export declare function normalizeVoxelShapeInput(input: VoxelShapeInput): Result<VoxelShapeInput & {
|
|
206
|
+
readonly cells: Int32Array;
|
|
207
|
+
readonly origin: PhysicsVector;
|
|
208
|
+
readonly rotation: PhysicsQuaternion;
|
|
209
|
+
}, DerivedPhysicsError>;
|
|
210
|
+
/** Validate explicit mass/inertia values before touching the backend. */
|
|
211
|
+
export declare function validateMassProperties(properties: PhysicsMassProperties | undefined): Result<PhysicsMassProperties | undefined, DerivedPhysicsError>;
|
|
212
|
+
/** The required linear velocity correction for a committed COM change. */
|
|
213
|
+
export declare function preserveCenterOfMassVelocity(linearVelocity: PhysicsVector, angularVelocity: PhysicsVector, previousWorldCom: PhysicsVector, nextWorldCom: PhysicsVector): PhysicsVector;
|
|
214
|
+
/** Snapshot an input without retaining caller-owned typed-array references. */
|
|
215
|
+
export declare function cloneDerivedPhysicsInput(input: DerivedPhysicsCandidateInput): Result<DerivedPhysicsCandidateInput, DerivedPhysicsError>;
|
|
216
|
+
/** Estimate staged CPU/native input bytes for the bounded admission budget. */
|
|
217
|
+
export declare function estimateDerivedPhysicsInputBytes(input: DerivedPhysicsCandidateInput): number;
|
|
218
|
+
//# sourceMappingURL=derived-physics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derived-physics.d.ts","sourceRoot":"","sources":["../src/derived-physics.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export type { CollisionEventPayload } from './collision-event';
|
|
|
2
2
|
export { CollisionEvent } from './collision-event';
|
|
3
3
|
export type { ColliderShape, RigidBodyType } from './components';
|
|
4
4
|
export { CharacterController, COLLIDER_SHAPE_CAPSULE, COLLIDER_SHAPE_CUBOID, COLLIDER_SHAPE_SPHERE, Collider, ColliderShapeValue, CollidingEntities, colliderShapeFromF32, RIGID_BODY_TYPE_DYNAMIC, RIGID_BODY_TYPE_KINEMATIC, RIGID_BODY_TYPE_STATIC, RigidBody, RigidBodyTypeValue, registerPhysicsComponents, rigidBodyTypeFromF32, } from './components';
|
|
5
|
+
export type { DerivedPhysicsCandidate, DerivedPhysicsCandidateInput, DerivedPhysicsCandidateState, DerivedPhysicsErrorCode, DerivedPhysicsErrorDetail, DerivedPhysicsFailure, DerivedPhysicsMotion, DerivedPhysicsPublication, DerivedPhysicsSnapshot, DerivedShapeSeamInput, DerivedShapeState, PhysicsConstraintBodyDependency, PhysicsConstraintInput, PhysicsContactObservation, PhysicsMassProperties, PhysicsQuaternion, PhysicsVector, PhysicsVelocityPolicy, VoxelCell, VoxelShapeInput, } from './derived-physics';
|
|
6
|
+
export { cloneDerivedPhysicsInput, DERIVED_PHYSICS_LIMITS, DerivedPhysicsError, estimateDerivedPhysicsInputBytes, normalizeVoxelShapeInput, preserveCenterOfMassVelocity, validateMassProperties, } from './derived-physics';
|
|
5
7
|
export type { PhysicsErrorCode, PhysicsErrorDetail } from './errors';
|
|
6
8
|
export { PHYSICS_ERROR_HINTS, PhysicsError } from './errors';
|
|
7
9
|
export type { PhysicsWorld, PhysicsWorld2D, RaycastHit, RaycastHit2D } from './physics-world';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,SAAS,EACT,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC9F,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,YAAY,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,SAAS,EACT,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,uBAAuB,EACvB,4BAA4B,EAC5B,4BAA4B,EAC5B,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,EACrB,oBAAoB,EACpB,yBAAyB,EACzB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,+BAA+B,EAC/B,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,SAAS,EACT,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,gCAAgC,EAChC,wBAAwB,EACxB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC9F,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|