avbd-babylon 0.3.0 → 0.4.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/README.md +3355 -2795
- package/dist/avbd.d.ts +1 -0
- package/dist/avbd.global.js +595 -136
- package/dist/avbd.js +595 -136
- package/dist/babylonAvbd.d.ts +31 -6
- package/dist/native.js +1 -1
- package/dist/nativeScenes.d.ts +81 -8
- package/dist/utilities.d.ts +161 -0
- package/dist/utilities.js +1 -0
- package/docs/BABYLON_API.md +34 -5
- package/docs/HPLOC.md +119 -115
- package/docs/README.md +503 -465
- package/docs/RELEASE.md +191 -176
- package/package.json +148 -124
- package/tests/README.md +333 -218
package/dist/babylonAvbd.d.ts
CHANGED
|
@@ -2,6 +2,18 @@ import type { Vector3, Quaternion } from "@babylonjs/core/Maths/math.vector.js";
|
|
|
2
2
|
import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
|
|
3
3
|
import type { Scene } from "@babylonjs/core/scene.js";
|
|
4
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
|
+
}
|
|
5
17
|
export const AvbdShapeType: Readonly<{
|
|
6
18
|
BOX: "box";
|
|
7
19
|
SPHERE: "sphere";
|
|
@@ -31,9 +43,11 @@ export interface AvbdWorldOptions {
|
|
|
31
43
|
maxSyncedBodies?: number;
|
|
32
44
|
broadphase?: "auto" | "grid" | "hploc";
|
|
33
45
|
solverMode?: AvbdSolverMode;
|
|
46
|
+
/** Automatically batch a closed jointless world of up to 32 bodies. */
|
|
47
|
+
smallGroups?: boolean;
|
|
34
48
|
bvh?: { rebuildInterval?: number };
|
|
35
|
-
/** Optional
|
|
36
|
-
sleeping?: boolean |
|
|
49
|
+
/** Optional GPU sleeping. Large worlds wake conservative connected groups on impact. */
|
|
50
|
+
sleeping?: boolean | AvbdSleepOptions;
|
|
37
51
|
maxContactPairs?: number;
|
|
38
52
|
maxContactEvents?: number;
|
|
39
53
|
}
|
|
@@ -116,6 +130,17 @@ export class AvbdPhysicsConstraint {
|
|
|
116
130
|
dispose(): void;
|
|
117
131
|
}
|
|
118
132
|
export class AvbdPhysics {
|
|
133
|
+
/** Register static collision pieces before initialize(); reserve body capacity. */
|
|
134
|
+
addHeightfield(options: AvbdHeightfieldOptions): AvbdTerrain;
|
|
135
|
+
/** Captures the mesh world transform; later mesh edits do not move terrain. */
|
|
136
|
+
addStaticMesh(
|
|
137
|
+
mesh: AbstractMesh,
|
|
138
|
+
options?: AvbdTerrainMaterial & { thickness?: number },
|
|
139
|
+
): AvbdTerrain;
|
|
140
|
+
addTerrain(
|
|
141
|
+
cooked: AvbdCookedTerrain,
|
|
142
|
+
options?: AvbdTerrainMaterial,
|
|
143
|
+
): AvbdTerrain;
|
|
119
144
|
sphereCast(
|
|
120
145
|
origin: AvbdVector,
|
|
121
146
|
radius: number,
|
|
@@ -151,10 +176,9 @@ export class AvbdPhysics {
|
|
|
151
176
|
readonly solverDecision: AvbdSolverDecision;
|
|
152
177
|
setSolverMode(mode: AvbdSolverMode): AvbdSolverDecision;
|
|
153
178
|
setGravity(gravity: AvbdVector): void;
|
|
154
|
-
enableSleeping(options?:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}): this;
|
|
179
|
+
enableSleeping(options?: AvbdSleepOptions): this;
|
|
180
|
+
/** Wake all sleeping bodies and disable automatic sleeping. */
|
|
181
|
+
disableSleeping(): this;
|
|
158
182
|
initialize(): void;
|
|
159
183
|
step(): void;
|
|
160
184
|
flushCommands(): void;
|
|
@@ -281,5 +305,6 @@ export class AvbdPhysicsBody {
|
|
|
281
305
|
effectiveMass: number;
|
|
282
306
|
sleeping: boolean;
|
|
283
307
|
}>;
|
|
308
|
+
/** Mesh-origin position; preserves live rotation and velocities when omitted. */
|
|
284
309
|
teleport(position: Vector3, rotation?: Quaternion): this;
|
|
285
310
|
}
|
package/dist/native.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AvbdScene2D, AvbdScene3D, createWebGPUDevice, prepareWebGPUDevice3D, createSolverPipeline } from "./avbd.js";
|
|
1
|
+
export { AvbdScene2D, AvbdScene3D, createWebGPUDevice, prepareWebGPUDevice3D, createSolverPipeline, cookHeightfield, cookStaticMesh } from "./avbd.js";
|
package/dist/nativeScenes.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AvbdSolverPipeline,
|
|
3
|
+
AvbdSolver2D,
|
|
4
|
+
AvbdSolver3D,
|
|
5
|
+
} from "./solverPipeline.js";
|
|
2
6
|
export type AvbdTuple3 = readonly [number, number, number];
|
|
3
7
|
export type AvbdTuple2 = readonly [number, number];
|
|
4
8
|
export interface AvbdQueryOptions {
|
|
@@ -23,6 +27,55 @@ export interface AvbdQueryHit<V> {
|
|
|
23
27
|
center: V;
|
|
24
28
|
}
|
|
25
29
|
export type AvbdQuaternion = readonly [number, number, number, number];
|
|
30
|
+
export interface AvbdTerrainMaterial {
|
|
31
|
+
friction?: number;
|
|
32
|
+
restitution?: number;
|
|
33
|
+
group?: number;
|
|
34
|
+
collidesWith?: number;
|
|
35
|
+
mass?: 0;
|
|
36
|
+
}
|
|
37
|
+
export interface AvbdHeightfieldOptions extends AvbdTerrainMaterial {
|
|
38
|
+
heights: ArrayLike<number>;
|
|
39
|
+
columns: number;
|
|
40
|
+
rows: number;
|
|
41
|
+
spacing?: number | AvbdTuple2;
|
|
42
|
+
origin?: AvbdTuple3;
|
|
43
|
+
upAxis?: 0 | 1 | 2;
|
|
44
|
+
/** Local height below every sample; defaults to the minimum height minus 2. */
|
|
45
|
+
baseHeight?: number;
|
|
46
|
+
/** Row-major cells; a nonzero entry leaves a hole. */
|
|
47
|
+
holes?: ArrayLike<number>;
|
|
48
|
+
}
|
|
49
|
+
export interface AvbdStaticMeshOptions extends AvbdTerrainMaterial {
|
|
50
|
+
/** World-space xyz triples. */
|
|
51
|
+
positions: ArrayLike<number>;
|
|
52
|
+
indices?: ArrayLike<number>;
|
|
53
|
+
/** Backing behind triangle winding, in world units. Defaults to 0.1. */
|
|
54
|
+
thickness?: number;
|
|
55
|
+
}
|
|
56
|
+
/** Serializable preprocessing output; can be cooked in a separate worker. */
|
|
57
|
+
export interface AvbdCookedTerrain {
|
|
58
|
+
kind: "heightfield" | "static-mesh";
|
|
59
|
+
triangleCount: number;
|
|
60
|
+
pieces: Array<{
|
|
61
|
+
shape: object;
|
|
62
|
+
position: AvbdTuple3;
|
|
63
|
+
rotation: AvbdQuaternion;
|
|
64
|
+
}>;
|
|
65
|
+
}
|
|
66
|
+
export interface AvbdNativeTerrain {
|
|
67
|
+
readonly bodies: AvbdRigid[];
|
|
68
|
+
readonly triangleCount: number;
|
|
69
|
+
readonly kind: "heightfield" | "static-mesh";
|
|
70
|
+
/** Disable collision participation; live indices remain stable. */
|
|
71
|
+
dispose(): void;
|
|
72
|
+
}
|
|
73
|
+
export function cookHeightfield(
|
|
74
|
+
options: AvbdHeightfieldOptions,
|
|
75
|
+
): AvbdCookedTerrain;
|
|
76
|
+
export function cookStaticMesh(
|
|
77
|
+
options: AvbdStaticMeshOptions,
|
|
78
|
+
): AvbdCookedTerrain;
|
|
26
79
|
export interface AvbdNativeState3D {
|
|
27
80
|
position: [number, number, number];
|
|
28
81
|
rotation: [number, number, number, number];
|
|
@@ -187,6 +240,13 @@ export interface AvbdGpuParameters2D extends AvbdGpuParameters {
|
|
|
187
240
|
vbd: boolean;
|
|
188
241
|
vbdStiffness: number;
|
|
189
242
|
}
|
|
243
|
+
/** 3D can retain conservative connected groups between explicit world edits. */
|
|
244
|
+
export interface AvbdSleepOptions {
|
|
245
|
+
speedThreshold?: number;
|
|
246
|
+
timeThreshold?: number;
|
|
247
|
+
/** 3D: automatic for large jointless desktop worlds; false selects whole-world waking. */
|
|
248
|
+
islands?: boolean;
|
|
249
|
+
}
|
|
190
250
|
export interface AvbdGpuOptions {
|
|
191
251
|
bodyBuffer?: GPUBuffer;
|
|
192
252
|
bodyCapacity?: number;
|
|
@@ -194,6 +254,8 @@ export interface AvbdGpuOptions {
|
|
|
194
254
|
spatialSort?: boolean;
|
|
195
255
|
broadphase?: "auto" | "grid" | "hploc";
|
|
196
256
|
solverMode?: "auto" | "standard" | "optimized" | "points";
|
|
257
|
+
/** 3D: automatically fuse closed jointless worlds of at most 32 bodies. */
|
|
258
|
+
smallGroups?: boolean;
|
|
197
259
|
bvh?: { rebuildInterval?: number };
|
|
198
260
|
capacity?: {
|
|
199
261
|
contacts?: number;
|
|
@@ -202,9 +264,10 @@ export interface AvbdGpuOptions {
|
|
|
202
264
|
colors?: number;
|
|
203
265
|
joints?: number;
|
|
204
266
|
};
|
|
267
|
+
/** Reserve coloring capacity when sleeping bodies wake. */
|
|
205
268
|
minimumColors?: number;
|
|
206
269
|
minimumColorRounds?: number;
|
|
207
|
-
sleeping?: boolean |
|
|
270
|
+
sleeping?: boolean | AvbdSleepOptions;
|
|
208
271
|
}
|
|
209
272
|
export interface AvbdGpuSolver {
|
|
210
273
|
readonly bodyBuffer: GPUBuffer;
|
|
@@ -274,10 +337,7 @@ export interface AvbdGpuSolver3D extends AvbdGpuSolver {
|
|
|
274
337
|
rotation?: AvbdQuaternion,
|
|
275
338
|
): this;
|
|
276
339
|
readBodyState(index: number): Promise<AvbdNativeState3D>;
|
|
277
|
-
enableSleeping(options?:
|
|
278
|
-
speedThreshold?: number;
|
|
279
|
-
timeThreshold?: number;
|
|
280
|
-
}): this;
|
|
340
|
+
enableSleeping(options?: AvbdSleepOptions): this;
|
|
281
341
|
disableSleeping(): this;
|
|
282
342
|
setSleepEnabled(index: number, enabled: boolean): this;
|
|
283
343
|
watchContacts(options?: AvbdNativeContactOptions): this;
|
|
@@ -509,6 +569,12 @@ export interface AvbdNativeConstraint {
|
|
|
509
569
|
destroy(): void;
|
|
510
570
|
}
|
|
511
571
|
export class AvbdScene3D {
|
|
572
|
+
addHeightfield(options: AvbdHeightfieldOptions): AvbdNativeTerrain;
|
|
573
|
+
addStaticMesh(options: AvbdStaticMeshOptions): AvbdNativeTerrain;
|
|
574
|
+
addTerrain(
|
|
575
|
+
cooked: AvbdCookedTerrain,
|
|
576
|
+
options?: AvbdTerrainMaterial,
|
|
577
|
+
): AvbdNativeTerrain;
|
|
512
578
|
addMotor(
|
|
513
579
|
a: AvbdRigid | null,
|
|
514
580
|
b: AvbdRigid,
|
|
@@ -621,7 +687,10 @@ export class AvbdScene3D {
|
|
|
621
687
|
},
|
|
622
688
|
): AvbdNativeConstraint;
|
|
623
689
|
createSolver(device: GPUDevice, options?: AvbdGpuOptions): AvbdGpuSolver3D;
|
|
624
|
-
createSolver(
|
|
690
|
+
createSolver(
|
|
691
|
+
pipeline: AvbdSolverPipeline,
|
|
692
|
+
options?: AvbdGpuOptions,
|
|
693
|
+
): AvbdSolver3D;
|
|
625
694
|
}
|
|
626
695
|
export interface AvbdNativeAngularOptions {
|
|
627
696
|
axisA?: AvbdTuple3;
|
|
@@ -731,8 +800,12 @@ export class AvbdScene2D {
|
|
|
731
800
|
bodyBuffer?: GPUBuffer;
|
|
732
801
|
bodyCapacity?: number;
|
|
733
802
|
colorRounds?: number;
|
|
803
|
+
minimumColors?: number;
|
|
734
804
|
sleeping?: boolean | { speedThreshold?: number; timeThreshold?: number };
|
|
735
805
|
},
|
|
736
806
|
): AvbdGpuSolver2D;
|
|
737
|
-
createSolver(
|
|
807
|
+
createSolver(
|
|
808
|
+
pipeline: AvbdSolverPipeline,
|
|
809
|
+
options?: AvbdGpuOptions,
|
|
810
|
+
): AvbdSolver2D;
|
|
738
811
|
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/** Nonblocking GPU pass timestamps; null when timestamp-query is unavailable. */
|
|
2
|
+
export class GpuTimer {
|
|
3
|
+
constructor(device: GPUDevice);
|
|
4
|
+
readonly latestMs: number | null;
|
|
5
|
+
readonly samples: number;
|
|
6
|
+
begin(): object | null;
|
|
7
|
+
descriptor(slot: object | null): {
|
|
8
|
+
timestampWrites?: GPUComputePassTimestampWrites;
|
|
9
|
+
};
|
|
10
|
+
encode(encoder: GPUCommandEncoder, slot: object | null): void;
|
|
11
|
+
resolve(slot: object | null): Promise<void> | undefined;
|
|
12
|
+
settled(): Promise<unknown[]>;
|
|
13
|
+
destroy(): void;
|
|
14
|
+
}
|
|
15
|
+
/** Reuse released buffers with compatible usage, without CPU pose transfers. */
|
|
16
|
+
export class GPUBufferRecycler {
|
|
17
|
+
constructor(device: GPUDevice, options?: { maxFreeBytes?: number });
|
|
18
|
+
readonly freeBytes: number;
|
|
19
|
+
acquire(
|
|
20
|
+
byteSize: number,
|
|
21
|
+
usage: GPUBufferUsageFlags,
|
|
22
|
+
label?: string,
|
|
23
|
+
): GPUBuffer;
|
|
24
|
+
release(
|
|
25
|
+
buffer: GPUBuffer,
|
|
26
|
+
byteSize: number,
|
|
27
|
+
usage: GPUBufferUsageFlags,
|
|
28
|
+
): void;
|
|
29
|
+
trim(maxFreeBytes?: number): void;
|
|
30
|
+
destroy(): void;
|
|
31
|
+
}
|
|
32
|
+
export const PARTICLE_BYTE_STRIDE: 48;
|
|
33
|
+
export interface SurfaceParticleStep {
|
|
34
|
+
dt: number;
|
|
35
|
+
count?: number;
|
|
36
|
+
speed?: number;
|
|
37
|
+
life?: number;
|
|
38
|
+
bulletRadius?: number;
|
|
39
|
+
spawnRadius?: number;
|
|
40
|
+
jitter?: number;
|
|
41
|
+
frame?: number;
|
|
42
|
+
}
|
|
43
|
+
/** Spherical emitter aimed at the origin. Particles hit triangle surfaces and
|
|
44
|
+
* respawn; they ignore each other. Five rays approximate the particle sweep. */
|
|
45
|
+
export class GpuSurfaceParticles {
|
|
46
|
+
constructor(
|
|
47
|
+
device: GPUDevice,
|
|
48
|
+
options: { capacity: number; triangleCount: number; readback?: boolean },
|
|
49
|
+
);
|
|
50
|
+
readonly device: GPUDevice;
|
|
51
|
+
readonly capacity: number;
|
|
52
|
+
readonly triangleCount: number;
|
|
53
|
+
/** 48 bytes: position/life vec4f, velocity/radius vec4f, seed vec4u. */
|
|
54
|
+
readonly particleBuffer: GPUBuffer;
|
|
55
|
+
readonly triangleBuffer: GPUBuffer;
|
|
56
|
+
readonly counterBuffer: GPUBuffer;
|
|
57
|
+
readonly timer: GpuTimer;
|
|
58
|
+
/** 12 float32 values per triangle: [ax,ay,az,0,bx,by,bz,0,cx,cy,cz,0]. */
|
|
59
|
+
writeTriangles(vertices: Float32Array): void;
|
|
60
|
+
/** Returns the latest asynchronous counters, or null with readback disabled. */
|
|
61
|
+
step(options: SurfaceParticleStep): { hits: number; alive: number } | null;
|
|
62
|
+
clear(): void;
|
|
63
|
+
destroy(): void;
|
|
64
|
+
}
|
|
65
|
+
export const sampledContactShader: string;
|
|
66
|
+
/** Gather a bounded GPU contact overlay, without reading the full contact set. */
|
|
67
|
+
export class GpuContactSample {
|
|
68
|
+
constructor(device: GPUDevice, options?: { count?: number });
|
|
69
|
+
readonly count: number;
|
|
70
|
+
readonly buffer: GPUBuffer;
|
|
71
|
+
encode(
|
|
72
|
+
encoder: GPUCommandEncoder,
|
|
73
|
+
resources: {
|
|
74
|
+
bodyBuffer: GPUBuffer;
|
|
75
|
+
/** Native 3D camera uniform: mat4 vp, vec4 eye, vec4 light/viewport. */
|
|
76
|
+
cameraBuffer: GPUBuffer;
|
|
77
|
+
contactStorage: {
|
|
78
|
+
manifolds: GPUBuffer;
|
|
79
|
+
contacts: GPUBuffer;
|
|
80
|
+
counters: GPUBuffer;
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
): void;
|
|
84
|
+
dispose(): void;
|
|
85
|
+
}
|
|
86
|
+
/** Optional one-time native constraint-graph seed; live GPU coloring still checks contacts. */
|
|
87
|
+
export function seedConstraintColoring(
|
|
88
|
+
gpu: {
|
|
89
|
+
device: GPUDevice;
|
|
90
|
+
bodyCapacity: number;
|
|
91
|
+
colorBuffer: GPUBuffer;
|
|
92
|
+
colorCap: number;
|
|
93
|
+
gpuIndex(index: number): number;
|
|
94
|
+
},
|
|
95
|
+
world: {
|
|
96
|
+
bodies: { mass: number }[];
|
|
97
|
+
forces: { bodyA: object | null; bodyB: object | null }[];
|
|
98
|
+
},
|
|
99
|
+
minimum?: number,
|
|
100
|
+
): void;
|
|
101
|
+
export const INPUT_WORDS: 9;
|
|
102
|
+
/** Custom compute/copy work in the solver's existing command encoder. Callbacks
|
|
103
|
+
* are synchronous, end their own passes, and must not submit or finish the encoder.
|
|
104
|
+
* Dispose the registration before destroying its buffers. CPU solvers are rejected. */
|
|
105
|
+
export function addGpuStepPass<
|
|
106
|
+
T extends { bodyBuffer: GPUBuffer; step(): void },
|
|
107
|
+
>(
|
|
108
|
+
solver: T,
|
|
109
|
+
hooks: {
|
|
110
|
+
before?: (encoder: GPUCommandEncoder, solver: T) => void;
|
|
111
|
+
after?: (encoder: GPUCommandEncoder, solver: T) => void;
|
|
112
|
+
},
|
|
113
|
+
): () => void;
|
|
114
|
+
/** DOM-free sizing and event adapter around a caller-owned canvas. */
|
|
115
|
+
export class WorkerCanvas {
|
|
116
|
+
constructor(
|
|
117
|
+
canvas: OffscreenCanvas | HTMLCanvasElement,
|
|
118
|
+
width: number,
|
|
119
|
+
height: number,
|
|
120
|
+
);
|
|
121
|
+
readonly offscreenCanvas: OffscreenCanvas | HTMLCanvasElement;
|
|
122
|
+
readonly clientWidth: number;
|
|
123
|
+
readonly clientHeight: number;
|
|
124
|
+
readonly revision: number;
|
|
125
|
+
width: number;
|
|
126
|
+
height: number;
|
|
127
|
+
resize(width: number, height: number): void;
|
|
128
|
+
getContext(type: "webgpu"): GPUCanvasContext | null;
|
|
129
|
+
getContext(type: string, options?: object): unknown;
|
|
130
|
+
getBoundingClientRect(): {
|
|
131
|
+
left: number;
|
|
132
|
+
top: number;
|
|
133
|
+
width: number;
|
|
134
|
+
height: number;
|
|
135
|
+
};
|
|
136
|
+
addEventListener(type: string, callback: (event: any) => void): void;
|
|
137
|
+
removeEventListener(type: string, callback: (event: any) => void): void;
|
|
138
|
+
setPointerCapture(): void;
|
|
139
|
+
dispatch(type: string, data: object): void;
|
|
140
|
+
}
|
|
141
|
+
export interface SharedPointerState {
|
|
142
|
+
clientX: number;
|
|
143
|
+
clientY: number;
|
|
144
|
+
pointerId?: number;
|
|
145
|
+
buttons?: number;
|
|
146
|
+
altKey?: boolean;
|
|
147
|
+
shiftKey?: boolean;
|
|
148
|
+
ctrlKey?: boolean;
|
|
149
|
+
}
|
|
150
|
+
/** Returns null without cross-origin isolation / SharedArrayBuffer support. */
|
|
151
|
+
export function createSharedInput(): Int32Array<SharedArrayBuffer> | null;
|
|
152
|
+
/** One producer; continuous state only. Send discrete events as ordered messages. */
|
|
153
|
+
export function writeSharedInput(
|
|
154
|
+
view: Int32Array<SharedArrayBuffer>,
|
|
155
|
+
event: SharedPointerState,
|
|
156
|
+
wheel?: number,
|
|
157
|
+
): void;
|
|
158
|
+
export function readSharedInput(
|
|
159
|
+
view: Int32Array<SharedArrayBuffer>,
|
|
160
|
+
previous?: number,
|
|
161
|
+
): { sequence: number; event: SharedPointerState; wheel: number } | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GpuTimer, GPUBufferRecycler, GpuSurfaceParticles, PARTICLE_BYTE_STRIDE, GpuContactSample, sampledContactShader, seedConstraintColoring, addGpuStepPass, WorkerCanvas, INPUT_WORDS, createSharedInput, writeSharedInput, readSharedInput } from "./avbd.js";
|
package/docs/BABYLON_API.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Babylon.js integration
|
|
2
2
|
|
|
3
|
+
Static terrain can be added with `physics.addHeightfield(options)` or
|
|
4
|
+
`physics.addStaticMesh(mesh, { thickness, friction, group, collidesWith })`.
|
|
5
|
+
The mesh helper captures current world-space triangles, including parent transforms.
|
|
6
|
+
Both return `{ bodies, triangleCount, kind, dispose() }`. Add terrain before
|
|
7
|
+
`initialize()` or the first render, and reserve body capacity for its collision
|
|
8
|
+
pieces. These pieces do not synchronize meshes each frame. `dispose()` disables
|
|
9
|
+
their collisions while leaving the caller's mesh intact.
|
|
10
|
+
|
|
11
|
+
Heightfields use two solid prisms per cell. Mesh terrain gives each triangle
|
|
12
|
+
finite backing behind its winding; concavities and overhangs remain open. This
|
|
13
|
+
uses the existing convex contact and grid/HPLOC pipelines. Internal tile edges
|
|
14
|
+
can affect sliding, and a rendering mesh should usually have a simpler collision
|
|
15
|
+
mesh. Terrain is static and does not track subsequent mesh transformations.
|
|
16
|
+
See [terrain examples](../README.md#static-terrain-hills-caves-and-overhangs)
|
|
17
|
+
for the native API, holes, coordinate conventions and worker cooking helpers.
|
|
18
|
+
|
|
3
19
|
Start with the [integration README](README.md) for a complete scene, bundler setup,
|
|
4
20
|
instance rendering examples and reproducible collision/solver benchmarks.
|
|
5
21
|
|
|
@@ -79,8 +95,10 @@ impacts below 1 m/s do not bounce. Use `body.setRestitution()` for live changes.
|
|
|
79
95
|
`isTrigger:true` detects dynamic-body overlaps without contact forces;
|
|
80
96
|
`body.setTrigger()` changes the mode. Events include `isTrigger`, and masks
|
|
81
97
|
apply to sensors too. Static–static pairs are not scanned. CCD,
|
|
82
|
-
|
|
83
|
-
interface are not implemented. Static
|
|
98
|
+
dynamic concave meshes and the full Physics V2 plugin
|
|
99
|
+
interface are not implemented. Static triangle meshes and heightfields use
|
|
100
|
+
`addStaticMesh()` and `addHeightfield()` terrain cooking, including caves and
|
|
101
|
+
overhangs. Static bodies given velocity move kinematically.
|
|
84
102
|
|
|
85
103
|
`addHinge(a,b,{axisA,axisB,anchorA,anchorB,minAngle,maxAngle,motor})` constrains
|
|
86
104
|
rotation to one axis, with optional angle stops and a torque-limited motor.
|
|
@@ -129,18 +147,29 @@ reserve storage; `readContactEvents()` reports dropped events or a full pair
|
|
|
129
147
|
table. End events do not retain an old position. Callbacks run asynchronously.
|
|
130
148
|
|
|
131
149
|
`sleeping: true` or `{ speedThreshold: 0.03, timeThreshold: 0.5 }` enables an
|
|
132
|
-
optional GPU policy. Supported quiet bodies sleep
|
|
133
|
-
|
|
150
|
+
optional GPU policy. Supported quiet bodies sleep. Large jointless desktop 3D worlds
|
|
151
|
+
automatically wake conservative connected groups on impact, keeping unrelated
|
|
152
|
+
piles asleep; the shared static floor does not join them. `islands:true` opts
|
|
153
|
+
into group waking in smaller worlds, and `islands:false` selects whole-world
|
|
154
|
+
waking. Explicit edits wake the world and reset group history. Unsupported bodies
|
|
134
155
|
under gravity stay awake. `wakeAll()`, `body.wakeUp()` and `readSleepStats()` are
|
|
135
156
|
available. Suspended jointed objects are not guaranteed to sleep. Defaults and
|
|
136
157
|
paper-comparison benchmarks keep sleeping disabled.
|
|
137
158
|
|
|
159
|
+
Closed jointless 3D worlds with at most 32 bodies automatically batch movement
|
|
160
|
+
iterations in one GPU workgroup. Body poses stay in shared memory, with the
|
|
161
|
+
same contact order, reductions and equations. Adding a joint or exceeding the
|
|
162
|
+
body limit selects the ordinary pipeline. Qualified mobile compatibility paths
|
|
163
|
+
retain their existing execution policy. `smallGroups:false` disables batching
|
|
164
|
+
for controlled comparisons.
|
|
165
|
+
|
|
138
166
|
`body.setLinearVelocity()`, `setAngularVelocity()`, `applyImpulse()`,
|
|
139
167
|
`applyAngularImpulse()` and `teleport(position, quaternion)` enqueue compact
|
|
140
168
|
GPU commands. Commands for the same body are combined before submission;
|
|
141
169
|
impulses use the current GPU mass, inertia and position. They never replace a
|
|
142
170
|
body with a stale CPU pose. `teleport` retains velocity unless a velocity setter
|
|
143
|
-
is also called.
|
|
171
|
+
is also called. Omitting its quaternion preserves the live GPU rotation and
|
|
172
|
+
places the mesh origin at the requested position. New aggregates can be added within reserved capacity after
|
|
144
173
|
initialization; disposed body slots are not reused. For repeated spawning,
|
|
145
174
|
reserve projectile bodies and teleport them. `applyForce()` and `applyTorque()`
|
|
146
175
|
apply forces for one fixed step, using impulses on live GPU state.
|