avbd-babylon 0.4.4 → 0.4.5

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.
@@ -1,314 +1,347 @@
1
- import type { Vector3, Quaternion } from "@babylonjs/core/Maths/math.vector.js";
2
- import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
3
- import type { Scene } from "@babylonjs/core/scene.js";
4
- import type { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js";
5
- import type {
6
- AvbdSleepOptions,
7
- AvbdHeightfieldOptions,
8
- AvbdCookedTerrain,
9
- AvbdTerrainMaterial,
10
- } from "./nativeScenes.js";
11
- export interface AvbdTerrain {
12
- readonly bodies: AvbdPhysicsBody[];
13
- readonly triangleCount: number;
14
- readonly kind: "heightfield" | "static-mesh";
15
- dispose(): void;
16
- }
17
- export const AvbdShapeType: Readonly<{
18
- BOX: "box";
19
- SPHERE: "sphere";
20
- CAPSULE: "capsule";
21
- CYLINDER: "cylinder";
22
- CONVEX_HULL: "convex-hull";
23
- }>;
24
- export type AvbdShape = (typeof AvbdShapeType)[keyof typeof AvbdShapeType];
25
- export type AvbdSolverMode = "auto" | "standard" | "optimized" | "points";
26
- export interface AvbdSolverDecision {
27
- requested: AvbdSolverMode;
28
- selected: Exclude<AvbdSolverMode, "auto"> | "custom";
29
- reason: string;
30
- bodyCount: number;
31
- constraintCount: number;
32
- }
33
- export interface AvbdWorldOptions {
34
- device?: GPUDevice;
35
- scene?: Scene;
36
- gravity?: Vector3 | readonly [number, number, number];
37
- /** Attach fixed-step simulation and disposal to the scene. Defaults to true. */
38
- autoAttach?: boolean;
39
- timeStep?: number;
40
- iterations?: number;
41
- capacity?: number;
42
- syncMeshes?: boolean;
43
- maxSyncedBodies?: number;
44
- broadphase?: "auto" | "grid" | "hploc";
45
- solverMode?: AvbdSolverMode;
46
- /** Automatically batch a closed jointless world of up to 32 bodies. */
47
- smallGroups?: boolean;
48
- /** Advanced: reserve 0–64 parallel solve groups for dense or waking contacts. */
49
- minimumColors?: number;
50
- /** Advanced: minimum coloring rounds, an even integer from 0–32. */
51
- minimumColorRounds?: number;
52
- bvh?: { rebuildInterval?: number };
53
- /** Optional GPU sleeping. Large worlds wake conservative connected groups on impact. */
54
- sleeping?: boolean | AvbdSleepOptions;
55
- maxContactPairs?: number;
56
- maxContactEvents?: number;
57
- }
58
- export interface AvbdAggregateOptions {
59
- mass?: number;
60
- friction?: number;
61
- /** Bounce coefficient 0..1; pair uses the larger coefficient. Defaults to 0. */
62
- restitution?: number;
63
- /** Defaults to true when world sleeping is enabled. Explicit true enables sleeping. */
64
- allowSleep?: boolean;
65
- isTrigger?: boolean;
66
- sync?: boolean;
67
- group?: number;
68
- collidesWith?: number;
69
- }
70
- export type AvbdVector = Vector3 | readonly [number, number, number];
71
- export interface AvbdConstraintOptions {
72
- type?: "ball" | "fixed" | "spring" | "motor" | "limit";
73
- axisA?: AvbdVector;
74
- axisB?: AvbdVector;
75
- speed?: number;
76
- maxTorque?: number;
77
- minAngle?: number;
78
- maxAngle?: number;
79
- anchorA?: AvbdVector;
80
- anchorB?: AvbdVector;
81
- stiffness?: number;
82
- angularStiffness?: number;
83
- /** Spring tension in newtons; joints use the angular/optional linear break test. */
84
- breakForce?: number;
85
- /** Springs only: 0.75 permits 75% tensile extension before breaking. */
86
- breakStrain?: number;
87
- breakOnPull?: boolean;
88
- rest?: number;
89
- }
90
- export interface AvbdContactEvent {
91
- isTrigger: boolean;
92
- type: "begin" | "end";
93
- a: AvbdPhysicsBody;
94
- b: AvbdPhysicsBody;
95
- step: number;
96
- point: [number, number, number];
97
- normal: [number, number, number];
98
- impulse: number;
99
- }
100
- export interface AvbdRaycastOptions {
101
- includeTriggers?: boolean;
102
- maxDistance?: number;
103
- ignore?: AvbdPhysicsBody[];
104
- collidesWith?: number;
105
- }
106
- export interface AvbdRayHit {
107
- body: AvbdPhysicsBody | null;
108
- index: number;
109
- distance: number;
110
- point: [number, number, number];
111
- normal: [number, number, number];
112
- }
113
- export interface AvbdSphereCastHit extends AvbdRayHit {
114
- center: [number, number, number];
115
- }
116
- export class AvbdPhysicsConstraint {
117
- constructor(
118
- world: AvbdPhysics,
119
- a: AvbdPhysicsBody | null,
120
- b: AvbdPhysicsBody,
121
- options?: AvbdConstraintOptions,
122
- );
123
- readonly type: "ball" | "fixed" | "spring" | "motor" | "limit";
124
- readonly bodyA: AvbdPhysicsBody | null;
125
- readonly bodyB: AvbdPhysicsBody;
126
- readonly disposed: boolean;
127
- setWorldAnchor(point: AvbdVector): this;
128
- setMotor(options: { speed?: number; maxTorque?: number }): this;
129
- readState(): Promise<{
130
- broken: boolean;
131
- linearForce: number[];
132
- angularForce: number[];
133
- }>;
134
- dispose(): void;
135
- }
136
- export class AvbdPhysics {
137
- /** Register static collision pieces before initialize(); reserve body capacity. */
138
- addHeightfield(options: AvbdHeightfieldOptions): AvbdTerrain;
139
- /** Captures the mesh world transform; later mesh edits do not move terrain. */
140
- addStaticMesh(
141
- mesh: AbstractMesh,
142
- options?: AvbdTerrainMaterial & { thickness?: number },
143
- ): AvbdTerrain;
144
- addTerrain(
145
- cooked: AvbdCookedTerrain,
146
- options?: AvbdTerrainMaterial,
147
- ): AvbdTerrain;
148
- sphereCast(
149
- origin: AvbdVector,
150
- radius: number,
151
- direction: AvbdVector,
152
- options?: AvbdRaycastOptions,
153
- ): Promise<AvbdSphereCastHit | null>;
154
- sphereCastAll(
155
- casts: Array<{
156
- origin: AvbdVector;
157
- radius: number;
158
- direction: AvbdVector;
159
- maxDistance?: number;
160
- }>,
161
- options?: AvbdRaycastOptions,
162
- ): Promise<Array<AvbdSphereCastHit | null>>;
163
- addMotor(
164
- a: AvbdPhysicsBody | null,
165
- b: AvbdPhysicsBody,
166
- options?: AvbdConstraintOptions,
167
- ): AvbdPhysicsConstraint;
168
- addHinge(
169
- a: AvbdPhysicsBody | null,
170
- b: AvbdPhysicsBody,
171
- options?: AvbdHingeOptions,
172
- ): AvbdPhysicsHinge;
173
- static create(options?: AvbdWorldOptions): Promise<AvbdPhysics>;
174
- readonly device: GPUDevice;
175
- readonly bodyBuffer: GPUBuffer;
176
- readonly steps: number;
177
- readonly errors: string[];
178
- /** Unexpected device loss stops the scene loop and releases the world. Create a new world/device to resume. */
179
- readonly deviceLost: { reason: string; message: string } | null;
180
- readonly solverDecision: AvbdSolverDecision;
181
- setSolverMode(mode: AvbdSolverMode): AvbdSolverDecision;
182
- setGravity(gravity: AvbdVector): void;
183
- enableSleeping(options?: AvbdSleepOptions): this;
184
- /** Wake all sleeping bodies and disable automatic sleeping. */
185
- disableSleeping(): this;
186
- initialize(): void;
187
- step(): void;
188
- flushCommands(): void;
189
- addAggregate(
190
- mesh: AbstractMesh,
191
- type: AvbdShape | PhysicsShapeType,
192
- options?: AvbdAggregateOptions,
193
- ): AvbdPhysicsAggregate;
194
- addAggregates(
195
- entries: Array<{
196
- mesh: AbstractMesh;
197
- type: AvbdShape | PhysicsShapeType;
198
- options?: AvbdAggregateOptions;
199
- }>,
200
- ): AvbdPhysicsAggregate[];
201
- attachToScene(scene?: Scene): this;
202
- addConstraint(
203
- a: AvbdPhysicsBody | null,
204
- b: AvbdPhysicsBody,
205
- options?: AvbdConstraintOptions,
206
- ): AvbdPhysicsConstraint;
207
- addJoint(
208
- a: AvbdPhysicsBody | null,
209
- b: AvbdPhysicsBody,
210
- options?: AvbdConstraintOptions,
211
- ): AvbdPhysicsConstraint;
212
- addWeld(
213
- a: AvbdPhysicsBody | null,
214
- b: AvbdPhysicsBody,
215
- options?: AvbdConstraintOptions,
216
- ): AvbdPhysicsConstraint;
217
- addSpring(
218
- a: AvbdPhysicsBody,
219
- b: AvbdPhysicsBody,
220
- options?: AvbdConstraintOptions,
221
- ): AvbdPhysicsConstraint;
222
- onContact(callback: (event: AvbdContactEvent) => void): () => void;
223
- readContactEvents(): Promise<{
224
- events: AvbdContactEvent[];
225
- dropped: number;
226
- full: boolean;
227
- }>;
228
- raycast(
229
- origin: AvbdVector,
230
- direction: AvbdVector,
231
- options?: AvbdRaycastOptions,
232
- ): Promise<AvbdRayHit | null>;
233
- raycastAll(
234
- rays: Array<{
235
- origin: AvbdVector;
236
- direction: AvbdVector;
237
- maxDistance?: number;
238
- }>,
239
- options?: AvbdRaycastOptions,
240
- ): Promise<Array<AvbdRayHit | null>>;
241
- getRenderBinding(device?: GPUDevice): {
242
- device: GPUDevice;
243
- buffer: GPUBuffer;
244
- stride: number;
245
- positionOffset: number;
246
- rotationOffset: number;
247
- sizeOffset: number;
248
- count: number;
249
- };
250
- wakeAll(): void;
251
- readSleepStats(): Promise<{ sleeping: number; wakeRequested: boolean }>;
252
- readonly lastSyncBytes: number | undefined;
253
- syncMeshes(): Promise<void>;
254
- /** With bodies: requested order, 40 floats each. Without: GPU slot order. */
255
- readBodies(bodies?: AvbdPhysicsBody[]): Promise<Float32Array>;
256
- dispose(): void;
257
- }
258
- export interface AvbdHingeOptions extends AvbdConstraintOptions {
259
- span?: number;
260
- motor?: { speed?: number; maxTorque?: number };
261
- }
262
- export class AvbdPhysicsHinge {
263
- constructor(
264
- world: AvbdPhysics,
265
- a: AvbdPhysicsBody | null,
266
- b: AvbdPhysicsBody,
267
- options?: AvbdHingeOptions,
268
- );
269
- readonly bodyA: AvbdPhysicsBody | null;
270
- readonly bodyB: AvbdPhysicsBody;
271
- readonly joints: AvbdPhysicsConstraint[];
272
- readonly limit?: AvbdPhysicsConstraint;
273
- readonly motor?: AvbdPhysicsConstraint;
274
- readonly disposed: boolean;
275
- dispose(): void;
276
- }
277
- export class AvbdPhysicsAggregate {
278
- constructor(
279
- mesh: AbstractMesh,
280
- type: AvbdShape | PhysicsShapeType,
281
- options?: AvbdAggregateOptions,
282
- world?: AvbdPhysics | Scene,
283
- );
284
- readonly mesh: AbstractMesh;
285
- readonly body: AvbdPhysicsBody;
286
- readonly type: AvbdShape;
287
- dispose(): void;
288
- }
289
- export class AvbdPhysicsBody {
290
- readonly gpuIndex: number;
291
- setLinearVelocity(velocity: AvbdVector): this;
292
- setAngularVelocity(velocity: AvbdVector): this;
293
- applyImpulse(impulse: AvbdVector, worldPoint?: AvbdVector): this;
294
- applyAngularImpulse(impulse: AvbdVector): this;
295
- /** Apply force for one fixed step (N), optionally at a world point. */
296
- applyForce(force: AvbdVector, worldPoint?: AvbdVector): this;
297
- applyTorque(torque: AvbdVector): this;
298
- setCollisionGroups(group: number, collidesWith?: number): this;
299
- wakeUp(): this;
300
- setSleepEnabled(enabled: boolean): this;
301
- setTrigger(enabled: boolean): this;
302
- setRestitution(value: number): this;
303
- readState(): Promise<{
304
- position: number[];
305
- rotation: number[];
306
- linearVelocity: number[];
307
- angularVelocity: number[];
308
- mass: number;
309
- effectiveMass: number;
310
- sleeping: boolean;
311
- }>;
312
- /** Mesh-origin position; preserves live rotation and velocities when omitted. */
313
- teleport(position: Vector3, rotation?: Quaternion): this;
314
- }
1
+ import type { Vector3, Quaternion } from "@babylonjs/core/Maths/math.vector.js";
2
+ import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
3
+ import type { Scene } from "@babylonjs/core/scene.js";
4
+ import type { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js";
5
+ import type {
6
+ AvbdSleepOptions,
7
+ AvbdHeightfieldOptions,
8
+ AvbdCookedTerrain,
9
+ AvbdTerrainMaterial,
10
+ } from "./nativeScenes.js";
11
+ export interface AvbdTerrain {
12
+ readonly bodies: AvbdPhysicsBody[];
13
+ readonly triangleCount: number;
14
+ readonly kind: "heightfield" | "static-mesh";
15
+ dispose(): void;
16
+ }
17
+ export const AvbdShapeType: Readonly<{
18
+ BOX: "box";
19
+ SPHERE: "sphere";
20
+ CAPSULE: "capsule";
21
+ CYLINDER: "cylinder";
22
+ CONVEX_HULL: "convex-hull";
23
+ }>;
24
+ export type AvbdShape = (typeof AvbdShapeType)[keyof typeof AvbdShapeType];
25
+ export type AvbdSolverMode = "auto" | "standard" | "optimized" | "points";
26
+ export interface AvbdSolverDecision {
27
+ requested: AvbdSolverMode;
28
+ selected: Exclude<AvbdSolverMode, "auto"> | "custom";
29
+ reason: string;
30
+ bodyCount: number;
31
+ constraintCount: number;
32
+ }
33
+ /**
34
+ * GPU world setup. Build aggregates before initialization and reserve enough
35
+ * capacity for later additions. A supplied GPUDevice remains caller-owned.
36
+ */
37
+ export interface AvbdWorldOptions {
38
+ device?: GPUDevice;
39
+ scene?: Scene;
40
+ gravity?: Vector3 | readonly [number, number, number];
41
+ /** Attach fixed-step simulation and disposal to the scene. Defaults to true. */
42
+ autoAttach?: boolean;
43
+ timeStep?: number;
44
+ iterations?: number;
45
+ /** Maximum body slots reserved at initialization; default 4096. */
46
+ capacity?: number;
47
+ /** Mirror selected poses for ordinary Babylon meshes. Use false with direct GPU drawing. */
48
+ syncMeshes?: boolean;
49
+ /** Guard against accidental large pose downloads; default 2048. */
50
+ maxSyncedBodies?: number;
51
+ broadphase?: "auto" | "grid" | "hploc";
52
+ solverMode?: AvbdSolverMode;
53
+ /** Automatically batch a closed jointless world of up to 32 bodies. */
54
+ smallGroups?: boolean;
55
+ /** Advanced: reserve 0–64 parallel solve groups for dense or waking contacts. */
56
+ minimumColors?: number;
57
+ /** Advanced: minimum coloring rounds, an even integer from 0–32. */
58
+ minimumColorRounds?: number;
59
+ bvh?: { rebuildInterval?: number };
60
+ /** Optional GPU sleeping. Large worlds wake conservative connected groups on impact. */
61
+ sleeping?: boolean | AvbdSleepOptions;
62
+ maxContactPairs?: number;
63
+ maxContactEvents?: number;
64
+ }
65
+ export interface AvbdAggregateOptions {
66
+ mass?: number;
67
+ friction?: number;
68
+ /** Bounce coefficient 0..1; pair uses the larger coefficient. Defaults to 0. */
69
+ restitution?: number;
70
+ /** Defaults to true when world sleeping is enabled. Explicit true enables sleeping. */
71
+ allowSleep?: boolean;
72
+ /** Overlap sensor: contact events without physical contact response. */
73
+ isTrigger?: boolean;
74
+ /** Include this aggregate in pose mirroring when world syncMeshes is enabled. */
75
+ sync?: boolean;
76
+ group?: number;
77
+ collidesWith?: number;
78
+ }
79
+ export type AvbdVector = Vector3 | readonly [number, number, number];
80
+ export interface AvbdConstraintOptions {
81
+ type?: "ball" | "fixed" | "spring" | "motor" | "limit";
82
+ axisA?: AvbdVector;
83
+ axisB?: AvbdVector;
84
+ /** Motor target angular speed in radians/second. */
85
+ speed?: number;
86
+ maxTorque?: number;
87
+ /** Lower relative hinge angle in radians. */
88
+ minAngle?: number;
89
+ /** Upper relative hinge angle in radians. */
90
+ maxAngle?: number;
91
+ /** Mesh-local anchor, or world-space when body A is null. */
92
+ anchorA?: AvbdVector;
93
+ /** Anchor in body B's mesh-local coordinates. */
94
+ anchorB?: AvbdVector;
95
+ stiffness?: number;
96
+ angularStiffness?: number;
97
+ /** Spring tension in newtons; joints use the angular/optional linear break test. */
98
+ breakForce?: number;
99
+ /** Springs only: 0.75 permits 75% tensile extension before breaking. */
100
+ breakStrain?: number;
101
+ breakOnPull?: boolean;
102
+ rest?: number;
103
+ }
104
+ export interface AvbdContactEvent {
105
+ isTrigger: boolean;
106
+ type: "begin" | "end";
107
+ a: AvbdPhysicsBody;
108
+ b: AvbdPhysicsBody;
109
+ step: number;
110
+ point: [number, number, number];
111
+ normal: [number, number, number];
112
+ impulse: number;
113
+ }
114
+ export interface AvbdRaycastOptions {
115
+ includeTriggers?: boolean;
116
+ maxDistance?: number;
117
+ ignore?: AvbdPhysicsBody[];
118
+ collidesWith?: number;
119
+ }
120
+ export interface AvbdRayHit {
121
+ body: AvbdPhysicsBody | null;
122
+ index: number;
123
+ distance: number;
124
+ point: [number, number, number];
125
+ normal: [number, number, number];
126
+ }
127
+ export interface AvbdSphereCastHit extends AvbdRayHit {
128
+ center: [number, number, number];
129
+ }
130
+ export class AvbdPhysicsConstraint {
131
+ constructor(
132
+ world: AvbdPhysics,
133
+ a: AvbdPhysicsBody | null,
134
+ b: AvbdPhysicsBody,
135
+ options?: AvbdConstraintOptions,
136
+ );
137
+ readonly type: "ball" | "fixed" | "spring" | "motor" | "limit";
138
+ readonly bodyA: AvbdPhysicsBody | null;
139
+ readonly bodyB: AvbdPhysicsBody;
140
+ readonly disposed: boolean;
141
+ setWorldAnchor(point: AvbdVector): this;
142
+ setMotor(options: { speed?: number; maxTorque?: number }): this;
143
+ readState(): Promise<{
144
+ broken: boolean;
145
+ linearForce: number[];
146
+ angularForce: number[];
147
+ }>;
148
+ dispose(): void;
149
+ }
150
+ export class AvbdPhysics {
151
+ /** Register static collision pieces before initialize(); reserve body capacity. */
152
+ addHeightfield(options: AvbdHeightfieldOptions): AvbdTerrain;
153
+ /** Captures the mesh world transform; later mesh edits do not move terrain. */
154
+ addStaticMesh(
155
+ mesh: AbstractMesh,
156
+ options?: AvbdTerrainMaterial & { thickness?: number },
157
+ ): AvbdTerrain;
158
+ addTerrain(
159
+ cooked: AvbdCookedTerrain,
160
+ options?: AvbdTerrainMaterial,
161
+ ): AvbdTerrain;
162
+ sphereCast(
163
+ origin: AvbdVector,
164
+ radius: number,
165
+ direction: AvbdVector,
166
+ options?: AvbdRaycastOptions,
167
+ ): Promise<AvbdSphereCastHit | null>;
168
+ /** Batch swept-sphere queries; one nearest hit or null per input cast. */
169
+ sphereCastAll(
170
+ casts: Array<{
171
+ origin: AvbdVector;
172
+ radius: number;
173
+ direction: AvbdVector;
174
+ maxDistance?: number;
175
+ }>,
176
+ options?: AvbdRaycastOptions,
177
+ ): Promise<Array<AvbdSphereCastHit | null>>;
178
+ addMotor(
179
+ a: AvbdPhysicsBody | null,
180
+ b: AvbdPhysicsBody,
181
+ options?: AvbdConstraintOptions,
182
+ ): AvbdPhysicsConstraint;
183
+ addHinge(
184
+ a: AvbdPhysicsBody | null,
185
+ b: AvbdPhysicsBody,
186
+ options?: AvbdHingeOptions,
187
+ ): AvbdPhysicsHinge;
188
+ /** Create the GPU world; attaches to a supplied Babylon scene by default. */
189
+ static create(options?: AvbdWorldOptions): Promise<AvbdPhysics>;
190
+ readonly device: GPUDevice;
191
+ readonly bodyBuffer: GPUBuffer;
192
+ readonly steps: number;
193
+ readonly errors: string[];
194
+ /** Unexpected device loss stops the scene loop and releases the world. Create a new world/device to resume. */
195
+ readonly deviceLost: { reason: string; message: string } | null;
196
+ readonly solverDecision: AvbdSolverDecision;
197
+ setSolverMode(mode: AvbdSolverMode): AvbdSolverDecision;
198
+ setGravity(gravity: AvbdVector): void;
199
+ enableSleeping(options?: AvbdSleepOptions): this;
200
+ /** Wake all sleeping bodies and disable automatic sleeping. */
201
+ disableSleeping(): this;
202
+ /** Upload initial topology once; step(), queries and buffer access initialize lazily. */
203
+ initialize(): void;
204
+ /** Submit one fixed step; do not also call manually when automatic scene stepping is attached. */
205
+ step(): void;
206
+ /** Apply queued edits without stepping or waiting. step() also flushes them automatically. */
207
+ flushCommands(): void;
208
+ addAggregate(
209
+ mesh: AbstractMesh,
210
+ type: AvbdShape | PhysicsShapeType,
211
+ options?: AvbdAggregateOptions,
212
+ ): AvbdPhysicsAggregate;
213
+ /** Convenience construction of multiple aggregates; each retains its own body. */
214
+ addAggregates(
215
+ entries: Array<{
216
+ mesh: AbstractMesh;
217
+ type: AvbdShape | PhysicsShapeType;
218
+ options?: AvbdAggregateOptions;
219
+ }>,
220
+ ): AvbdPhysicsAggregate[];
221
+ /** Attach fixed-step updates and disposal to the scene; reuse the same scene idempotently. */
222
+ attachToScene(scene?: Scene): this;
223
+ addConstraint(
224
+ a: AvbdPhysicsBody | null,
225
+ b: AvbdPhysicsBody,
226
+ options?: AvbdConstraintOptions,
227
+ ): AvbdPhysicsConstraint;
228
+ addJoint(
229
+ a: AvbdPhysicsBody | null,
230
+ b: AvbdPhysicsBody,
231
+ options?: AvbdConstraintOptions,
232
+ ): AvbdPhysicsConstraint;
233
+ addWeld(
234
+ a: AvbdPhysicsBody | null,
235
+ b: AvbdPhysicsBody,
236
+ options?: AvbdConstraintOptions,
237
+ ): AvbdPhysicsConstraint;
238
+ addSpring(
239
+ a: AvbdPhysicsBody,
240
+ b: AvbdPhysicsBody,
241
+ options?: AvbdConstraintOptions,
242
+ ): AvbdPhysicsConstraint;
243
+ /** Receive asynchronously downloaded begin/end events; returns an unsubscribe function. */
244
+ onContact(callback: (event: AvbdContactEvent) => void): () => void;
245
+ readContactEvents(): Promise<{
246
+ events: AvbdContactEvent[];
247
+ dropped: number;
248
+ full: boolean;
249
+ }>;
250
+ raycast(
251
+ origin: AvbdVector,
252
+ direction: AvbdVector,
253
+ options?: AvbdRaycastOptions,
254
+ ): Promise<AvbdRayHit | null>;
255
+ /** Batch rays in one query; returns the nearest hit or null for each input, in input order. */
256
+ raycastAll(
257
+ rays: Array<{
258
+ origin: AvbdVector;
259
+ direction: AvbdVector;
260
+ maxDistance?: number;
261
+ }>,
262
+ options?: AvbdRaycastOptions,
263
+ ): Promise<Array<AvbdRayHit | null>>;
264
+ /**
265
+ * Borrow live poses on the same GPUDevice. Stride and offsets are bytes.
266
+ * The world owns this buffer; it is invalid after disposal.
267
+ */
268
+ getRenderBinding(device?: GPUDevice): {
269
+ device: GPUDevice;
270
+ buffer: GPUBuffer;
271
+ stride: number;
272
+ positionOffset: number;
273
+ rotationOffset: number;
274
+ sizeOffset: number;
275
+ count: number;
276
+ };
277
+ wakeAll(): void;
278
+ readSleepStats(): Promise<{ sleeping: number; wakeRequested: boolean }>;
279
+ readonly lastSyncBytes: number | undefined;
280
+ /** Explicitly mirror only sync-enabled aggregate poses; asynchronous GPU readback. */
281
+ syncMeshes(): Promise<void>;
282
+ /** With bodies: requested order, 40 floats each. Without: GPU slot order. */
283
+ readBodies(bodies?: AvbdPhysicsBody[]): Promise<Float32Array>;
284
+ dispose(): void;
285
+ }
286
+ export interface AvbdHingeOptions extends AvbdConstraintOptions {
287
+ span?: number;
288
+ motor?: { speed?: number; maxTorque?: number };
289
+ }
290
+ export class AvbdPhysicsHinge {
291
+ constructor(
292
+ world: AvbdPhysics,
293
+ a: AvbdPhysicsBody | null,
294
+ b: AvbdPhysicsBody,
295
+ options?: AvbdHingeOptions,
296
+ );
297
+ readonly bodyA: AvbdPhysicsBody | null;
298
+ readonly bodyB: AvbdPhysicsBody;
299
+ readonly joints: AvbdPhysicsConstraint[];
300
+ readonly limit?: AvbdPhysicsConstraint;
301
+ readonly motor?: AvbdPhysicsConstraint;
302
+ readonly disposed: boolean;
303
+ dispose(): void;
304
+ }
305
+ export class AvbdPhysicsAggregate {
306
+ constructor(
307
+ mesh: AbstractMesh,
308
+ type: AvbdShape | PhysicsShapeType,
309
+ options?: AvbdAggregateOptions,
310
+ world?: AvbdPhysics | Scene,
311
+ );
312
+ readonly mesh: AbstractMesh;
313
+ readonly body: AvbdPhysicsBody;
314
+ readonly type: AvbdShape;
315
+ dispose(): void;
316
+ }
317
+ export class AvbdPhysicsBody {
318
+ readonly gpuIndex: number;
319
+ /** Queue world-space velocity replacement; repeated calls before flush keep the last value. */
320
+ setLinearVelocity(velocity: AvbdVector): this;
321
+ setAngularVelocity(velocity: AvbdVector): this;
322
+ /** Queue an additive world-space impulse; optional worldPoint also applies torque. */
323
+ applyImpulse(impulse: AvbdVector, worldPoint?: AvbdVector): this;
324
+ applyAngularImpulse(impulse: AvbdVector): this;
325
+ /** Apply force for one fixed step (N), optionally at a world point. */
326
+ applyForce(force: AvbdVector, worldPoint?: AvbdVector): this;
327
+ applyTorque(torque: AvbdVector): this;
328
+ /** Unsigned bitmasks; both bodies must accept the other's group to interact. */
329
+ setCollisionGroups(group: number, collidesWith?: number): this;
330
+ wakeUp(): this;
331
+ /** Opt this body into/out of resting detection; true enables world sleeping if needed. */
332
+ setSleepEnabled(enabled: boolean): this;
333
+ setTrigger(enabled: boolean): this;
334
+ /** Bounce coefficient in [0, 1]. Zero retains ordinary solid contact response. */
335
+ setRestitution(value: number): this;
336
+ readState(): Promise<{
337
+ position: number[];
338
+ rotation: number[];
339
+ linearVelocity: number[];
340
+ angularVelocity: number[];
341
+ mass: number;
342
+ effectiveMass: number;
343
+ sleeping: boolean;
344
+ }>;
345
+ /** Mesh-origin position; preserves live rotation and velocities when omitted. */
346
+ teleport(position: Vector3, rotation?: Quaternion): this;
347
+ }