avbd-babylon 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +2606 -2
- package/dist/NOTICE +145 -0
- package/dist/avbd.d.ts +3 -0
- package/dist/avbd.global.d.ts +2 -0
- package/dist/avbd.global.js +4884 -0
- package/dist/avbd.js +4884 -0
- package/dist/babylonAvbd.d.ts +285 -0
- package/dist/gpuDevice.d.ts +10 -0
- package/dist/native.d.ts +2 -0
- package/dist/native.js +1 -0
- package/dist/nativeScenes.d.ts +735 -0
- package/docs/BABYLON_API.md +356 -0
- package/docs/HPLOC.md +116 -0
- package/docs/README.md +459 -0
- package/docs/RELEASE.md +167 -0
- package/package.json +112 -4
- package/tests/README.md +170 -0
|
@@ -0,0 +1,735 @@
|
|
|
1
|
+
export type AvbdTuple3 = readonly [number, number, number];
|
|
2
|
+
export type AvbdTuple2 = readonly [number, number];
|
|
3
|
+
export interface AvbdQueryOptions {
|
|
4
|
+
maxDistance?: number;
|
|
5
|
+
ignore?: number[];
|
|
6
|
+
collidesWith?: number;
|
|
7
|
+
includeTriggers?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AvbdNativeRay<V> {
|
|
10
|
+
origin: V;
|
|
11
|
+
direction: V;
|
|
12
|
+
maxDistance?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface AvbdNativeCast<V> extends AvbdNativeRay<V> {
|
|
15
|
+
radius: number;
|
|
16
|
+
}
|
|
17
|
+
export interface AvbdQueryHit<V> {
|
|
18
|
+
index: number;
|
|
19
|
+
distance: number;
|
|
20
|
+
normal: V;
|
|
21
|
+
point: V;
|
|
22
|
+
center: V;
|
|
23
|
+
}
|
|
24
|
+
export type AvbdQuaternion = readonly [number, number, number, number];
|
|
25
|
+
export interface AvbdNativeState3D {
|
|
26
|
+
position: [number, number, number];
|
|
27
|
+
rotation: [number, number, number, number];
|
|
28
|
+
linearVelocity: [number, number, number];
|
|
29
|
+
angularVelocity: [number, number, number];
|
|
30
|
+
mass: number;
|
|
31
|
+
effectiveMass: number;
|
|
32
|
+
sleeping: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface AvbdNativeState2D {
|
|
35
|
+
position: [number, number];
|
|
36
|
+
angle: number;
|
|
37
|
+
linearVelocity: [number, number];
|
|
38
|
+
angularVelocity: number;
|
|
39
|
+
mass: number;
|
|
40
|
+
moment: number;
|
|
41
|
+
sleeping: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface AvbdNativeBody<V, A, R, S> {
|
|
44
|
+
/** Live GPU slot, including any initial spatial sorting. */
|
|
45
|
+
readonly gpuIndex: number;
|
|
46
|
+
setLinearVelocity(value: V): this;
|
|
47
|
+
setAngularVelocity(value: A): this;
|
|
48
|
+
applyImpulse(value: V, worldPoint?: V): this;
|
|
49
|
+
/** Force for one simulation step. Call each step for continuous force. */
|
|
50
|
+
applyForce(value: V, worldPoint?: V): this;
|
|
51
|
+
applyAngularImpulse(value: A): this;
|
|
52
|
+
applyTorque(value: A): this;
|
|
53
|
+
/** Centre-of-mass position. Preserves velocity and omitted rotation. */
|
|
54
|
+
teleport(position: V, rotation?: R): this;
|
|
55
|
+
setTrigger(enabled: boolean): this;
|
|
56
|
+
setRestitution(value: number): this;
|
|
57
|
+
setCollisionGroups(group: number, collidesWith?: number): this;
|
|
58
|
+
setSleepEnabled(enabled: boolean): this;
|
|
59
|
+
wakeUp(): this;
|
|
60
|
+
/** Explicit asynchronous download of only this body's live state. */
|
|
61
|
+
readState(): Promise<S>;
|
|
62
|
+
}
|
|
63
|
+
export type AvbdNativeBody3D = AvbdNativeBody<
|
|
64
|
+
AvbdTuple3,
|
|
65
|
+
AvbdTuple3,
|
|
66
|
+
AvbdQuaternion,
|
|
67
|
+
AvbdNativeState3D
|
|
68
|
+
>;
|
|
69
|
+
export type AvbdNativeBody2D = AvbdNativeBody<
|
|
70
|
+
AvbdTuple2,
|
|
71
|
+
number,
|
|
72
|
+
number,
|
|
73
|
+
AvbdNativeState2D
|
|
74
|
+
>;
|
|
75
|
+
export interface AvbdNativeBodyEdit<B, V, A, R> {
|
|
76
|
+
body: B;
|
|
77
|
+
position?: V;
|
|
78
|
+
rotation?: R;
|
|
79
|
+
linearVelocity?: V;
|
|
80
|
+
angularVelocity?: A;
|
|
81
|
+
impulse?: V;
|
|
82
|
+
force?: V;
|
|
83
|
+
worldPoint?: V;
|
|
84
|
+
angularImpulse?: A;
|
|
85
|
+
torque?: A;
|
|
86
|
+
isTrigger?: boolean;
|
|
87
|
+
restitution?: number;
|
|
88
|
+
/** Supply group with collidesWith; omitted collidesWith means all groups. */
|
|
89
|
+
group?: number;
|
|
90
|
+
collidesWith?: number;
|
|
91
|
+
allowSleep?: boolean;
|
|
92
|
+
}
|
|
93
|
+
export interface AvbdAdvanceOptions {
|
|
94
|
+
maxSubSteps?: number;
|
|
95
|
+
maxFrameTime?: number;
|
|
96
|
+
}
|
|
97
|
+
export interface AvbdNativeContactOptions {
|
|
98
|
+
maxPairs?: number;
|
|
99
|
+
maxEvents?: number;
|
|
100
|
+
indices?: number[];
|
|
101
|
+
}
|
|
102
|
+
export interface AvbdNativeContactResult {
|
|
103
|
+
events: Array<{
|
|
104
|
+
type: "begin" | "end";
|
|
105
|
+
a: number;
|
|
106
|
+
b: number;
|
|
107
|
+
isTrigger: boolean;
|
|
108
|
+
point: [number, number, number];
|
|
109
|
+
normal: [number, number, number];
|
|
110
|
+
impulse: number;
|
|
111
|
+
step: number;
|
|
112
|
+
}>;
|
|
113
|
+
dropped: number;
|
|
114
|
+
full: boolean;
|
|
115
|
+
}
|
|
116
|
+
export interface AvbdNativeSceneBinding {
|
|
117
|
+
getEngine(): { getDeltaTime(): number };
|
|
118
|
+
onBeforeRenderObservable: {
|
|
119
|
+
add(callback: () => void): unknown;
|
|
120
|
+
remove(observer: any): unknown;
|
|
121
|
+
};
|
|
122
|
+
onDisposeObservable: {
|
|
123
|
+
addOnce(callback: () => void): unknown;
|
|
124
|
+
remove(observer: any): unknown;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export interface AvbdSceneOptions {
|
|
128
|
+
gravity?: number;
|
|
129
|
+
timeStep?: number;
|
|
130
|
+
iterations?: number;
|
|
131
|
+
up?: AvbdTuple3;
|
|
132
|
+
}
|
|
133
|
+
export interface AvbdNativeBodyOptions {
|
|
134
|
+
group?: number;
|
|
135
|
+
collidesWith?: number;
|
|
136
|
+
allowSleep?: boolean;
|
|
137
|
+
restitution?: number;
|
|
138
|
+
isTrigger?: boolean;
|
|
139
|
+
density?: number;
|
|
140
|
+
mass?: number;
|
|
141
|
+
friction?: number;
|
|
142
|
+
position?: AvbdTuple3;
|
|
143
|
+
rotation?: AvbdQuaternion;
|
|
144
|
+
velocity?: AvbdTuple3;
|
|
145
|
+
angularVelocity?: AvbdTuple3;
|
|
146
|
+
}
|
|
147
|
+
/** Scene-builder handle. Poses in this record are initial CPU data, not live GPU state. */
|
|
148
|
+
export interface AvbdRigid {
|
|
149
|
+
mass: number;
|
|
150
|
+
size: Float64Array;
|
|
151
|
+
moment: Float64Array;
|
|
152
|
+
radius: number;
|
|
153
|
+
positionLin: Float64Array;
|
|
154
|
+
positionAng: Float64Array;
|
|
155
|
+
velocityLin: Float64Array;
|
|
156
|
+
velocityAng: Float64Array;
|
|
157
|
+
}
|
|
158
|
+
export interface AvbdGpuCounters {
|
|
159
|
+
pairs: number;
|
|
160
|
+
contacts: number;
|
|
161
|
+
overflow: number;
|
|
162
|
+
clashes: number;
|
|
163
|
+
colors: number;
|
|
164
|
+
manifolds?: number;
|
|
165
|
+
}
|
|
166
|
+
export interface AvbdGpuParameters {
|
|
167
|
+
dt: number;
|
|
168
|
+
gravity: number;
|
|
169
|
+
iterations: number;
|
|
170
|
+
alpha: number;
|
|
171
|
+
gamma: number;
|
|
172
|
+
}
|
|
173
|
+
export interface AvbdGpuParameters3D extends AvbdGpuParameters {
|
|
174
|
+
betaLin: number;
|
|
175
|
+
betaAng: number;
|
|
176
|
+
up?: number[];
|
|
177
|
+
startAtRest?: boolean;
|
|
178
|
+
massPenalty?: boolean;
|
|
179
|
+
reuseContacts?: boolean;
|
|
180
|
+
}
|
|
181
|
+
export interface AvbdGpuParameters2D extends AvbdGpuParameters {
|
|
182
|
+
beta: number;
|
|
183
|
+
postStabilize: boolean;
|
|
184
|
+
matchNearest: boolean;
|
|
185
|
+
stiffnessRescale: boolean;
|
|
186
|
+
vbd: boolean;
|
|
187
|
+
vbdStiffness: number;
|
|
188
|
+
}
|
|
189
|
+
export interface AvbdGpuOptions {
|
|
190
|
+
bodyBuffer?: GPUBuffer;
|
|
191
|
+
bodyCapacity?: number;
|
|
192
|
+
colorRounds?: number;
|
|
193
|
+
spatialSort?: boolean;
|
|
194
|
+
broadphase?: "auto" | "grid" | "hploc";
|
|
195
|
+
solverMode?: "auto" | "standard" | "optimized" | "points";
|
|
196
|
+
bvh?: { rebuildInterval?: number };
|
|
197
|
+
capacity?: {
|
|
198
|
+
contacts?: number;
|
|
199
|
+
pairs?: number;
|
|
200
|
+
manifolds?: number;
|
|
201
|
+
colors?: number;
|
|
202
|
+
joints?: number;
|
|
203
|
+
};
|
|
204
|
+
minimumColors?: number;
|
|
205
|
+
minimumColorRounds?: number;
|
|
206
|
+
sleeping?: boolean | { speedThreshold?: number; timeThreshold?: number };
|
|
207
|
+
}
|
|
208
|
+
export interface AvbdGpuSolver {
|
|
209
|
+
readonly bodyBuffer: GPUBuffer;
|
|
210
|
+
readonly bodyCount: number;
|
|
211
|
+
readonly jointCount: number;
|
|
212
|
+
readonly params: AvbdGpuParameters;
|
|
213
|
+
step(): void;
|
|
214
|
+
/** Elapsed seconds; fixed timestep with bounded catch-up. Returns steps submitted, never waits for GPU or downloads poses. */
|
|
215
|
+
advance(elapsed: number, options?: AvbdAdvanceOptions): number;
|
|
216
|
+
/** Submit pending edits now; step and queries flush automatically. Does not wait for GPU. */
|
|
217
|
+
flushEdits(): void;
|
|
218
|
+
/** Immediate single GPU dispatch, after queued edits. Unique ascending GPU indices; packed xy (2D) or xyz (3D) Float32 values. Buffers are reused. */
|
|
219
|
+
setLinearVelocities(
|
|
220
|
+
indices: ArrayLike<number>,
|
|
221
|
+
velocities: ArrayLike<number>,
|
|
222
|
+
): this;
|
|
223
|
+
/** Packed radians/sec: one component per 2D body, xyz per 3D body. */
|
|
224
|
+
setAngularVelocities(
|
|
225
|
+
indices: ArrayLike<number>,
|
|
226
|
+
velocities: ArrayLike<number>,
|
|
227
|
+
): this;
|
|
228
|
+
/** Replace either or both velocity fields in one dispatch. Unique ascending GPU slots. */
|
|
229
|
+
setVelocities(
|
|
230
|
+
indices: ArrayLike<number>,
|
|
231
|
+
values: { linear?: ArrayLike<number>; angular?: ArrayLike<number> },
|
|
232
|
+
): this;
|
|
233
|
+
/** GPU indices in, packed records out: 40 floats/body in 3D, 24 in 2D. posesOnly: 8 floats in 3D, 4 in 2D. */
|
|
234
|
+
readSelectedBodies(
|
|
235
|
+
indices: ArrayLike<number>,
|
|
236
|
+
options?: { posesOnly?: boolean },
|
|
237
|
+
): Promise<Float32Array>;
|
|
238
|
+
readBodies(): Promise<Float32Array>;
|
|
239
|
+
readJoints(): Promise<Float32Array>;
|
|
240
|
+
readCounters(): Promise<AvbdGpuCounters>;
|
|
241
|
+
adapt(counters: AvbdGpuCounters): void;
|
|
242
|
+
disableConstraint(slot: number): void;
|
|
243
|
+
destroy(): void;
|
|
244
|
+
}
|
|
245
|
+
export interface AvbdGpuSolver3D extends AvbdGpuSolver {
|
|
246
|
+
/** Prefer a scene-builder body; numeric arguments are GPU slots, not reference indices. Handles are created on demand. */
|
|
247
|
+
body(body: AvbdRigid | number): AvbdNativeBody3D;
|
|
248
|
+
bodyIndex(body: AvbdRigid | AvbdNativeBody3D | number): number;
|
|
249
|
+
/** Validates before enqueueing. Within a record: teleport, velocity setters, then impulses/forces. Records execute in order per body. */
|
|
250
|
+
editBodies(
|
|
251
|
+
edits: Iterable<
|
|
252
|
+
AvbdNativeBodyEdit<
|
|
253
|
+
AvbdRigid | AvbdNativeBody3D | number,
|
|
254
|
+
AvbdTuple3,
|
|
255
|
+
AvbdTuple3,
|
|
256
|
+
AvbdQuaternion
|
|
257
|
+
>
|
|
258
|
+
>,
|
|
259
|
+
): this;
|
|
260
|
+
setLinearVelocity(index: number, velocity: AvbdTuple3): this;
|
|
261
|
+
setAngularVelocity(index: number, velocity: AvbdTuple3): this;
|
|
262
|
+
applyImpulse(
|
|
263
|
+
index: number,
|
|
264
|
+
impulse: AvbdTuple3,
|
|
265
|
+
worldPoint?: AvbdTuple3,
|
|
266
|
+
): this;
|
|
267
|
+
applyForce(index: number, force: AvbdTuple3, worldPoint?: AvbdTuple3): this;
|
|
268
|
+
applyAngularImpulse(index: number, impulse: AvbdTuple3): this;
|
|
269
|
+
applyTorque(index: number, torque: AvbdTuple3): this;
|
|
270
|
+
teleport(
|
|
271
|
+
index: number,
|
|
272
|
+
position: AvbdTuple3,
|
|
273
|
+
rotation?: AvbdQuaternion,
|
|
274
|
+
): this;
|
|
275
|
+
readBodyState(index: number): Promise<AvbdNativeState3D>;
|
|
276
|
+
enableSleeping(options?: {
|
|
277
|
+
speedThreshold?: number;
|
|
278
|
+
timeThreshold?: number;
|
|
279
|
+
}): this;
|
|
280
|
+
disableSleeping(): this;
|
|
281
|
+
setSleepEnabled(index: number, enabled: boolean): this;
|
|
282
|
+
watchContacts(options?: AvbdNativeContactOptions): this;
|
|
283
|
+
readContactEvents(): Promise<AvbdNativeContactResult>;
|
|
284
|
+
attachToScene(
|
|
285
|
+
scene: AvbdNativeSceneBinding,
|
|
286
|
+
options?: AvbdAdvanceOptions & {
|
|
287
|
+
afterStep?: (solver: AvbdGpuSolver3D) => void;
|
|
288
|
+
},
|
|
289
|
+
): this;
|
|
290
|
+
detachFromScene(): this;
|
|
291
|
+
setFilters(
|
|
292
|
+
indices: ArrayLike<number>,
|
|
293
|
+
groups: ArrayLike<number>,
|
|
294
|
+
collidesWith: ArrayLike<number>,
|
|
295
|
+
): void;
|
|
296
|
+
raycast(
|
|
297
|
+
origin: AvbdTuple3,
|
|
298
|
+
direction: AvbdTuple3,
|
|
299
|
+
options?: AvbdQueryOptions,
|
|
300
|
+
): Promise<AvbdQueryHit<AvbdTuple3> | null>;
|
|
301
|
+
raycastAll(
|
|
302
|
+
rays: AvbdNativeRay<AvbdTuple3>[],
|
|
303
|
+
options?: AvbdQueryOptions,
|
|
304
|
+
): Promise<Array<AvbdQueryHit<AvbdTuple3> | null>>;
|
|
305
|
+
sphereCast(
|
|
306
|
+
origin: AvbdTuple3,
|
|
307
|
+
radius: number,
|
|
308
|
+
direction: AvbdTuple3,
|
|
309
|
+
options?: AvbdQueryOptions,
|
|
310
|
+
): Promise<AvbdQueryHit<AvbdTuple3> | null>;
|
|
311
|
+
sphereCastAll(
|
|
312
|
+
casts: AvbdNativeCast<AvbdTuple3>[],
|
|
313
|
+
options?: AvbdQueryOptions,
|
|
314
|
+
): Promise<Array<AvbdQueryHit<AvbdTuple3> | null>>;
|
|
315
|
+
setMotor(slot: number, options: { speed?: number; maxTorque?: number }): void;
|
|
316
|
+
readonly params: AvbdGpuParameters3D;
|
|
317
|
+
gpuIndex(referenceIndex: number): number;
|
|
318
|
+
releaseJoints(slots: ArrayLike<number>): void;
|
|
319
|
+
setWorldAnchor(slot: number, point: ArrayLike<number>): void;
|
|
320
|
+
captureConstraintFrames(
|
|
321
|
+
entries: Array<{ slot: number; spring?: boolean }>,
|
|
322
|
+
): void;
|
|
323
|
+
wakeAll(): void;
|
|
324
|
+
setSpringMaterial(
|
|
325
|
+
slot: number,
|
|
326
|
+
options?: { breakStrain?: number; breakForce?: number },
|
|
327
|
+
): void;
|
|
328
|
+
setSensor(index: number, enabled: boolean): void;
|
|
329
|
+
setRestitution(index: number, value: number): void;
|
|
330
|
+
readSleepStats(): Promise<{ sleeping: number; wakeRequested: boolean }>;
|
|
331
|
+
}
|
|
332
|
+
export interface AvbdGpuSolver2D extends AvbdGpuSolver {
|
|
333
|
+
body(index: number): AvbdNativeBody2D;
|
|
334
|
+
bodyIndex(body: AvbdNativeBody2D | number): number;
|
|
335
|
+
editBodies(
|
|
336
|
+
edits: Iterable<
|
|
337
|
+
AvbdNativeBodyEdit<AvbdNativeBody2D | number, AvbdTuple2, number, number>
|
|
338
|
+
>,
|
|
339
|
+
): this;
|
|
340
|
+
enableSleeping(options?: {
|
|
341
|
+
speedThreshold?: number;
|
|
342
|
+
timeThreshold?: number;
|
|
343
|
+
}): this;
|
|
344
|
+
disableSleeping(): this;
|
|
345
|
+
setSleepEnabled(index: number, enabled: boolean): this;
|
|
346
|
+
wakeAll(): this;
|
|
347
|
+
wakeUp(index: number): this;
|
|
348
|
+
readSleepStats(): Promise<{ sleeping: number; wakeRequested: boolean }>;
|
|
349
|
+
setAngleLimits(slot: number, options: AvbdAngleLimits2D): void;
|
|
350
|
+
/** Optional packed geometry. Hull descriptor: [4, radius, vertex-record offset, count]. Vertices: [x,y,normalX,normalY]. */
|
|
351
|
+
readonly shapeBuffer?: GPUBuffer;
|
|
352
|
+
/** Convex point cloud, 3–32 boundary vertices. Local geometry is centered on its area centroid; position is the center of mass. */
|
|
353
|
+
addHull(
|
|
354
|
+
points: ArrayLike<number> | readonly AvbdTuple2[],
|
|
355
|
+
options?: AvbdNativeBodyOptions2D,
|
|
356
|
+
): number;
|
|
357
|
+
attachToScene(
|
|
358
|
+
scene: {
|
|
359
|
+
getEngine(): { getDeltaTime(): number };
|
|
360
|
+
onBeforeRenderObservable: {
|
|
361
|
+
add(callback: () => void): unknown;
|
|
362
|
+
remove(observer: any): unknown;
|
|
363
|
+
};
|
|
364
|
+
onDisposeObservable: {
|
|
365
|
+
addOnce(callback: () => void): unknown;
|
|
366
|
+
remove(observer: any): unknown;
|
|
367
|
+
};
|
|
368
|
+
},
|
|
369
|
+
options?: {
|
|
370
|
+
maxSubSteps?: number;
|
|
371
|
+
maxFrameTime?: number;
|
|
372
|
+
afterStep?: (solver: AvbdGpuSolver2D) => void;
|
|
373
|
+
},
|
|
374
|
+
): this;
|
|
375
|
+
detachFromScene(): this;
|
|
376
|
+
addBox(size: AvbdTuple2, options?: AvbdNativeBodyOptions2D): number;
|
|
377
|
+
addCircle(radius: number, options?: AvbdNativeBodyOptions2D): number;
|
|
378
|
+
/** Local X axis; length includes both round caps. */
|
|
379
|
+
addCapsule(
|
|
380
|
+
radius: number,
|
|
381
|
+
length: number,
|
|
382
|
+
options?: AvbdNativeBodyOptions2D,
|
|
383
|
+
): number;
|
|
384
|
+
addSegment(
|
|
385
|
+
start: AvbdTuple2,
|
|
386
|
+
end: AvbdTuple2,
|
|
387
|
+
options?: AvbdNativeSegmentOptions2D,
|
|
388
|
+
): number;
|
|
389
|
+
addPlane(
|
|
390
|
+
normal?: AvbdTuple2,
|
|
391
|
+
offset?: number,
|
|
392
|
+
options?: AvbdNativePlaneOptions2D,
|
|
393
|
+
): number;
|
|
394
|
+
setLinearVelocity(
|
|
395
|
+
index: number,
|
|
396
|
+
velocity: AvbdTuple2 | { x: number; y: number },
|
|
397
|
+
): this;
|
|
398
|
+
setAngularVelocity(index: number, velocity: number): this;
|
|
399
|
+
applyImpulse(
|
|
400
|
+
index: number,
|
|
401
|
+
impulse: AvbdTuple2 | { x: number; y: number },
|
|
402
|
+
point?: AvbdTuple2 | { x: number; y: number },
|
|
403
|
+
): this;
|
|
404
|
+
/** Applies force for one simulation step. Call every step for a continuous force. */
|
|
405
|
+
applyForce(
|
|
406
|
+
index: number,
|
|
407
|
+
force: AvbdTuple2 | { x: number; y: number },
|
|
408
|
+
point?: AvbdTuple2 | { x: number; y: number },
|
|
409
|
+
): this;
|
|
410
|
+
applyAngularImpulse(index: number, impulse: number): this;
|
|
411
|
+
applyTorque(index: number, torque: number): this;
|
|
412
|
+
/** Preserves velocity; omitted angle preserves current rotation. */
|
|
413
|
+
teleport(
|
|
414
|
+
index: number,
|
|
415
|
+
position: AvbdTuple2 | { x: number; y: number },
|
|
416
|
+
angle?: number,
|
|
417
|
+
): this;
|
|
418
|
+
readBodyState(index: number): Promise<{
|
|
419
|
+
position: [number, number];
|
|
420
|
+
angle: number;
|
|
421
|
+
linearVelocity: [number, number];
|
|
422
|
+
angularVelocity: number;
|
|
423
|
+
mass: number;
|
|
424
|
+
moment: number;
|
|
425
|
+
sleeping: boolean;
|
|
426
|
+
}>;
|
|
427
|
+
raycast(
|
|
428
|
+
origin: AvbdTuple2,
|
|
429
|
+
direction: AvbdTuple2,
|
|
430
|
+
options?: AvbdQueryOptions,
|
|
431
|
+
): Promise<AvbdQueryHit<AvbdTuple2> | null>;
|
|
432
|
+
raycastAll(
|
|
433
|
+
rays: AvbdNativeRay<AvbdTuple2>[],
|
|
434
|
+
options?: AvbdQueryOptions,
|
|
435
|
+
): Promise<Array<AvbdQueryHit<AvbdTuple2> | null>>;
|
|
436
|
+
circleCast(
|
|
437
|
+
origin: AvbdTuple2,
|
|
438
|
+
radius: number,
|
|
439
|
+
direction: AvbdTuple2,
|
|
440
|
+
options?: AvbdQueryOptions,
|
|
441
|
+
): Promise<AvbdQueryHit<AvbdTuple2> | null>;
|
|
442
|
+
circleCastAll(
|
|
443
|
+
casts: AvbdNativeCast<AvbdTuple2>[],
|
|
444
|
+
options?: AvbdQueryOptions,
|
|
445
|
+
): Promise<Array<AvbdQueryHit<AvbdTuple2> | null>>;
|
|
446
|
+
setRestitution(index: number, value: number): void;
|
|
447
|
+
setSensor(index: number, enabled: boolean): void;
|
|
448
|
+
setFilters(
|
|
449
|
+
indices: ArrayLike<number>,
|
|
450
|
+
groups: ArrayLike<number>,
|
|
451
|
+
collidesWith: ArrayLike<number>,
|
|
452
|
+
): void;
|
|
453
|
+
/** Initially omitting indices watches every body. A supplied list selects pairs touching those bodies; later omissions preserve that selection. */
|
|
454
|
+
watchContacts(options?: {
|
|
455
|
+
maxPairs?: number;
|
|
456
|
+
maxEvents?: number;
|
|
457
|
+
indices?: number[];
|
|
458
|
+
}): this;
|
|
459
|
+
readContactEvents(): Promise<{
|
|
460
|
+
events: Array<{
|
|
461
|
+
type: "begin" | "end";
|
|
462
|
+
a: number;
|
|
463
|
+
b: number;
|
|
464
|
+
isTrigger: boolean;
|
|
465
|
+
point: [number, number, number];
|
|
466
|
+
normal: [number, number, number];
|
|
467
|
+
impulse: number;
|
|
468
|
+
step: number;
|
|
469
|
+
}>;
|
|
470
|
+
dropped: number;
|
|
471
|
+
full: boolean;
|
|
472
|
+
}>;
|
|
473
|
+
readonly params: AvbdGpuParameters2D;
|
|
474
|
+
setMotor(slot: number, options: { speed?: number; maxTorque?: number }): void;
|
|
475
|
+
appendJoint(
|
|
476
|
+
a: number,
|
|
477
|
+
b: number,
|
|
478
|
+
anchorA: AvbdTuple2,
|
|
479
|
+
anchorB: AvbdTuple2,
|
|
480
|
+
stiffness: AvbdTuple3,
|
|
481
|
+
breakForce?: number,
|
|
482
|
+
): number;
|
|
483
|
+
setWorldAnchor(slot: number, x: number, y: number): void;
|
|
484
|
+
}
|
|
485
|
+
export interface AvbdNativeConstraint2D extends AvbdNativeConstraint {
|
|
486
|
+
/** Manual enable/dispose state; fracture state comes from readJoints(). */
|
|
487
|
+
readonly alive: boolean;
|
|
488
|
+
}
|
|
489
|
+
export interface AvbdAngleLimits2D {
|
|
490
|
+
minAngle?: number;
|
|
491
|
+
maxAngle?: number;
|
|
492
|
+
}
|
|
493
|
+
export interface AvbdAngularLimit2D extends AvbdNativeConstraint2D {
|
|
494
|
+
setLimits(options: AvbdAngleLimits2D): this;
|
|
495
|
+
}
|
|
496
|
+
export interface AvbdHinge2D {
|
|
497
|
+
readonly joint: AvbdNativeConstraint2D;
|
|
498
|
+
readonly limits: AvbdAngularLimit2D | null;
|
|
499
|
+
readonly motor: AvbdNativeConstraint2D | null;
|
|
500
|
+
readonly disposed: boolean;
|
|
501
|
+
dispose(): void;
|
|
502
|
+
destroy(): void;
|
|
503
|
+
}
|
|
504
|
+
export interface AvbdNativeConstraint {
|
|
505
|
+
readonly slot: number;
|
|
506
|
+
readonly disposed: boolean;
|
|
507
|
+
dispose(): void;
|
|
508
|
+
destroy(): void;
|
|
509
|
+
}
|
|
510
|
+
export class AvbdScene3D {
|
|
511
|
+
addMotor(
|
|
512
|
+
a: AvbdRigid | null,
|
|
513
|
+
b: AvbdRigid,
|
|
514
|
+
options?: AvbdNativeAngularOptions,
|
|
515
|
+
): AvbdNativeConstraint;
|
|
516
|
+
addHinge(
|
|
517
|
+
a: AvbdRigid | null,
|
|
518
|
+
b: AvbdRigid,
|
|
519
|
+
options?: AvbdNativeAngularOptions & {
|
|
520
|
+
anchorA?: AvbdTuple3;
|
|
521
|
+
anchorB?: AvbdTuple3;
|
|
522
|
+
span?: number;
|
|
523
|
+
motor?: { speed?: number; maxTorque?: number };
|
|
524
|
+
},
|
|
525
|
+
): {
|
|
526
|
+
joints: AvbdNativeConstraint[];
|
|
527
|
+
limit?: AvbdNativeConstraint;
|
|
528
|
+
motor?: AvbdNativeConstraint;
|
|
529
|
+
dispose(): void;
|
|
530
|
+
};
|
|
531
|
+
constructor(options?: AvbdSceneOptions);
|
|
532
|
+
readonly bodies: AvbdRigid[];
|
|
533
|
+
readonly constraints: AvbdNativeConstraint[];
|
|
534
|
+
addBox(size: AvbdTuple3, options?: AvbdNativeBodyOptions): AvbdRigid;
|
|
535
|
+
addSphere(radius: number, options?: AvbdNativeBodyOptions): AvbdRigid;
|
|
536
|
+
/** Exact rounded capsule along local Y; height includes both end caps. */
|
|
537
|
+
addCapsule(
|
|
538
|
+
radius: number,
|
|
539
|
+
height: number,
|
|
540
|
+
options?: AvbdNativeBodyOptions,
|
|
541
|
+
): AvbdRigid;
|
|
542
|
+
/** Builds a centred convex collider aligned to its principal axes.
|
|
543
|
+
* Position/rotation place that principal frame; use aggregates to retain a mesh frame. */
|
|
544
|
+
addHull(
|
|
545
|
+
points: ArrayLike<number>,
|
|
546
|
+
options?: AvbdNativeBodyOptions,
|
|
547
|
+
): AvbdRigid;
|
|
548
|
+
addPoint(
|
|
549
|
+
position: AvbdTuple3,
|
|
550
|
+
options?: { mass?: number; radius?: number; friction?: number },
|
|
551
|
+
): AvbdRigid;
|
|
552
|
+
/** Helpers below build y-up geometry. Fabric lies in the x-z plane. */
|
|
553
|
+
addFabric(options?: {
|
|
554
|
+
columns?: number;
|
|
555
|
+
rows?: number;
|
|
556
|
+
spacing?: number;
|
|
557
|
+
origin?: AvbdTuple3;
|
|
558
|
+
mass?: number;
|
|
559
|
+
stiffness?: number;
|
|
560
|
+
pinEdges?: boolean;
|
|
561
|
+
/** Four corner anchors. When true, pinEdges defaults to false. */
|
|
562
|
+
pinCorners?: boolean;
|
|
563
|
+
/** N/m at pinned attachments; defaults to stiffness. Shear links retain half stiffness. */
|
|
564
|
+
anchorStiffness?: number;
|
|
565
|
+
/** Material at a spring's undeformed midpoint, normalized across the sheet.
|
|
566
|
+
* stiffnessScale multiplies stretch/shear/bending stiffness after anchorStiffness.
|
|
567
|
+
* Unspecified fields keep the fabric defaults. */
|
|
568
|
+
materialAt?: (
|
|
569
|
+
u: number,
|
|
570
|
+
v: number,
|
|
571
|
+
) => {
|
|
572
|
+
stiffnessScale?: number;
|
|
573
|
+
breakStrain?: number;
|
|
574
|
+
breakForce?: number;
|
|
575
|
+
};
|
|
576
|
+
breakStrain?: number;
|
|
577
|
+
breakForce?: number;
|
|
578
|
+
bendingStiffness?: number;
|
|
579
|
+
}): {
|
|
580
|
+
points: AvbdRigid[];
|
|
581
|
+
grid: AvbdRigid[][];
|
|
582
|
+
indices: Uint32Array;
|
|
583
|
+
connections: AvbdNativeConstraint[];
|
|
584
|
+
triangleConnections: Uint32Array;
|
|
585
|
+
};
|
|
586
|
+
addRope(options?: {
|
|
587
|
+
segments?: number;
|
|
588
|
+
length?: number;
|
|
589
|
+
origin?: AvbdTuple3;
|
|
590
|
+
width?: number;
|
|
591
|
+
endMass?: number;
|
|
592
|
+
}): { anchor: AvbdRigid; links: AvbdRigid[] };
|
|
593
|
+
addRagdoll(options?: { origin?: AvbdTuple3; mass?: number }): {
|
|
594
|
+
torso: AvbdRigid;
|
|
595
|
+
head: AvbdRigid;
|
|
596
|
+
bodies: AvbdRigid[];
|
|
597
|
+
};
|
|
598
|
+
addJoint(
|
|
599
|
+
a: AvbdRigid | null,
|
|
600
|
+
b: AvbdRigid,
|
|
601
|
+
anchorA?: AvbdTuple3,
|
|
602
|
+
anchorB?: AvbdTuple3,
|
|
603
|
+
options?: {
|
|
604
|
+
linearStiffness?: number;
|
|
605
|
+
angularStiffness?: number;
|
|
606
|
+
breakForce?: number;
|
|
607
|
+
breakOnPull?: boolean;
|
|
608
|
+
},
|
|
609
|
+
): AvbdNativeConstraint;
|
|
610
|
+
addSpring(
|
|
611
|
+
a: AvbdRigid,
|
|
612
|
+
b: AvbdRigid,
|
|
613
|
+
anchorA?: AvbdTuple3,
|
|
614
|
+
anchorB?: AvbdTuple3,
|
|
615
|
+
options?: {
|
|
616
|
+
stiffness?: number;
|
|
617
|
+
rest?: number;
|
|
618
|
+
breakStrain?: number;
|
|
619
|
+
breakForce?: number;
|
|
620
|
+
},
|
|
621
|
+
): AvbdNativeConstraint;
|
|
622
|
+
createSolver(device: GPUDevice, options?: AvbdGpuOptions): AvbdGpuSolver3D;
|
|
623
|
+
}
|
|
624
|
+
export interface AvbdNativeAngularOptions {
|
|
625
|
+
axisA?: AvbdTuple3;
|
|
626
|
+
axisB?: AvbdTuple3;
|
|
627
|
+
speed?: number;
|
|
628
|
+
maxTorque?: number;
|
|
629
|
+
minAngle?: number;
|
|
630
|
+
maxAngle?: number;
|
|
631
|
+
}
|
|
632
|
+
export interface AvbdNativeBodyOptions2D {
|
|
633
|
+
allowSleep?: boolean;
|
|
634
|
+
density?: number;
|
|
635
|
+
friction?: number;
|
|
636
|
+
position?: AvbdTuple2;
|
|
637
|
+
angle?: number;
|
|
638
|
+
/** [linear X, linear Y, angular radians/second]. */
|
|
639
|
+
velocity?: AvbdTuple3;
|
|
640
|
+
restitution?: number;
|
|
641
|
+
isTrigger?: boolean;
|
|
642
|
+
group?: number;
|
|
643
|
+
collidesWith?: number;
|
|
644
|
+
}
|
|
645
|
+
export interface AvbdNativeSegmentOptions2D extends Omit<
|
|
646
|
+
AvbdNativeBodyOptions2D,
|
|
647
|
+
"position" | "angle"
|
|
648
|
+
> {
|
|
649
|
+
/** Zero by default. Zero-thickness segments must be static. */
|
|
650
|
+
radius?: number;
|
|
651
|
+
}
|
|
652
|
+
export type AvbdNativePlaneOptions2D = Omit<
|
|
653
|
+
AvbdNativeBodyOptions2D,
|
|
654
|
+
"position" | "angle" | "density"
|
|
655
|
+
> & { density?: 0 };
|
|
656
|
+
export class AvbdScene2D {
|
|
657
|
+
constructor(
|
|
658
|
+
options?: Omit<AvbdSceneOptions, "up"> & {
|
|
659
|
+
alpha?: number;
|
|
660
|
+
postStabilize?: boolean;
|
|
661
|
+
matchNearest?: boolean;
|
|
662
|
+
},
|
|
663
|
+
);
|
|
664
|
+
readonly bodyCount: number;
|
|
665
|
+
/** Convex point cloud, 3–32 boundary vertices. Position is the area centroid / center of mass. */
|
|
666
|
+
addHull(
|
|
667
|
+
points: ArrayLike<number> | readonly AvbdTuple2[],
|
|
668
|
+
options?: AvbdNativeBodyOptions2D,
|
|
669
|
+
): number;
|
|
670
|
+
addCircle(radius: number, options?: AvbdNativeBodyOptions2D): number;
|
|
671
|
+
/** Local X axis; length includes both round caps. */
|
|
672
|
+
addCapsule(
|
|
673
|
+
radius: number,
|
|
674
|
+
length: number,
|
|
675
|
+
options?: AvbdNativeBodyOptions2D,
|
|
676
|
+
): number;
|
|
677
|
+
/** Finite two-sided line, or a rounded segment if radius > 0. */
|
|
678
|
+
addSegment(
|
|
679
|
+
start: AvbdTuple2,
|
|
680
|
+
end: AvbdTuple2,
|
|
681
|
+
options?: AvbdNativeSegmentOptions2D,
|
|
682
|
+
): number;
|
|
683
|
+
/** Normal is normalized. Allowed side: dot(normal, point) >= offset. */
|
|
684
|
+
addPlane(
|
|
685
|
+
normal?: AvbdTuple2,
|
|
686
|
+
offset?: number,
|
|
687
|
+
options?: AvbdNativePlaneOptions2D,
|
|
688
|
+
): number;
|
|
689
|
+
addBox(
|
|
690
|
+
size: readonly [number, number],
|
|
691
|
+
options?: AvbdNativeBodyOptions2D,
|
|
692
|
+
): number;
|
|
693
|
+
addJoint(
|
|
694
|
+
a: number,
|
|
695
|
+
b: number,
|
|
696
|
+
anchorA?: readonly [number, number],
|
|
697
|
+
anchorB?: readonly [number, number],
|
|
698
|
+
options?: { stiffness?: AvbdTuple3; breakForce?: number },
|
|
699
|
+
): AvbdNativeConstraint2D;
|
|
700
|
+
addSpring(
|
|
701
|
+
a: number,
|
|
702
|
+
b: number,
|
|
703
|
+
anchorA?: readonly [number, number],
|
|
704
|
+
anchorB?: readonly [number, number],
|
|
705
|
+
options?: { stiffness?: number; rest?: number },
|
|
706
|
+
): AvbdNativeConstraint2D;
|
|
707
|
+
addMotor(
|
|
708
|
+
a: number,
|
|
709
|
+
b: number,
|
|
710
|
+
options?: { speed?: number; maxTorque?: number },
|
|
711
|
+
): AvbdNativeConstraint2D;
|
|
712
|
+
addAngularLimit(
|
|
713
|
+
a: number,
|
|
714
|
+
b: number,
|
|
715
|
+
options?: AvbdAngleLimits2D,
|
|
716
|
+
): AvbdAngularLimit2D;
|
|
717
|
+
addHinge(
|
|
718
|
+
a: number,
|
|
719
|
+
b: number,
|
|
720
|
+
anchorA?: AvbdTuple2,
|
|
721
|
+
anchorB?: AvbdTuple2,
|
|
722
|
+
options?: AvbdAngleLimits2D & {
|
|
723
|
+
motor?: { speed?: number; maxTorque?: number };
|
|
724
|
+
},
|
|
725
|
+
): AvbdHinge2D;
|
|
726
|
+
createSolver(
|
|
727
|
+
device: GPUDevice,
|
|
728
|
+
options?: {
|
|
729
|
+
bodyBuffer?: GPUBuffer;
|
|
730
|
+
bodyCapacity?: number;
|
|
731
|
+
colorRounds?: number;
|
|
732
|
+
sleeping?: boolean | { speedThreshold?: number; timeThreshold?: number };
|
|
733
|
+
},
|
|
734
|
+
): AvbdGpuSolver2D;
|
|
735
|
+
}
|