@orillusion/physics-rapier 0.1.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 +158 -0
- package/dist/Physics.d.ts +114 -0
- package/dist/character/CharacterController.d.ts +54 -0
- package/dist/debug/PhysicsDebugDrawer.d.ts +38 -0
- package/dist/index.d.ts +19 -0
- package/dist/joint/ConstraintBase.d.ts +26 -0
- package/dist/joint/FixedJoint.d.ts +14 -0
- package/dist/joint/GenericJoint.d.ts +31 -0
- package/dist/joint/HingeJoint.d.ts +28 -0
- package/dist/joint/RopeJoint.d.ts +13 -0
- package/dist/joint/SliderJoint.d.ts +19 -0
- package/dist/joint/SphericalJoint.d.ts +14 -0
- package/dist/joint/SpringJoint.d.ts +15 -0
- package/dist/physics-rapier.es.js +6353 -0
- package/dist/physics-rapier.umd.js +2 -0
- package/dist/query/PhysicsQuery.d.ts +55 -0
- package/dist/rigidbody/Rigidbody.d.ts +118 -0
- package/dist/rigidbody/RigidbodyEnum.d.ts +13 -0
- package/dist/shape/CollisionShapeUtil.d.ts +95 -0
- package/dist/utils/PhysicsDragger.d.ts +33 -0
- package/dist/utils/TempPhyMath.d.ts +65 -0
- package/dist/vehicle/VehicleController.d.ts +60 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# @orillusion/physics-rapier
|
|
2
|
+
|
|
3
|
+
Rapier-backed physics plugin for Orillusion (WebGPU engine).
|
|
4
|
+
|
|
5
|
+
Independent of `@orillusion/physics` (which uses Bullet/ammo). Both packages
|
|
6
|
+
can coexist in one project — `physics-rapier` is the recommended path for new
|
|
7
|
+
work; `physics` remains supported for soft-body cases until a GPU XPBD plugin
|
|
8
|
+
ships.
|
|
9
|
+
|
|
10
|
+
## Why Rapier
|
|
11
|
+
|
|
12
|
+
| | `@orillusion/physics` (ammo) | `@orillusion/physics-rapier` |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Backend | Bullet 2.x via Emscripten asm.js | Rapier (Rust → WASM) |
|
|
15
|
+
| Bundle size | ~1.95 MB | ~600 KB (compat) |
|
|
16
|
+
| TypeScript | Community .d.ts | Official .d.ts |
|
|
17
|
+
| Determinism | No | Yes |
|
|
18
|
+
| Public raycast / sweep / overlap | Missing | `PhysicsQuery.*` |
|
|
19
|
+
| Character controller | Missing | `CharacterController` |
|
|
20
|
+
| Vehicle | Bare `btRaycastVehicle` | `VehicleController` |
|
|
21
|
+
| Soft body | Yes (cloth, rope) | No (use ammo, or future XPBD) |
|
|
22
|
+
| Snapshots / replay | Partial | `Physics.snapshot/restore` |
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { Engine3D, Object3D, MeshRenderer, BoxGeometry, LitMaterial, Vector3 } from '@orillusion/core';
|
|
28
|
+
import { Physics, Rigidbody, BodyType, CollisionShapeUtil } from '@orillusion/physics-rapier';
|
|
29
|
+
|
|
30
|
+
await Physics.init();
|
|
31
|
+
const engine = await Engine3D.init({ renderLoop: () => Physics.update() });
|
|
32
|
+
|
|
33
|
+
const cube = new Object3D();
|
|
34
|
+
cube.y = 5;
|
|
35
|
+
const mr = cube.addComponent(MeshRenderer);
|
|
36
|
+
mr.geometry = new BoxGeometry(1, 1, 1);
|
|
37
|
+
mr.material = new LitMaterial();
|
|
38
|
+
|
|
39
|
+
const rb = cube.addComponent(Rigidbody);
|
|
40
|
+
rb.bodyType = BodyType.Dynamic;
|
|
41
|
+
rb.mass = 1;
|
|
42
|
+
rb.shape = CollisionShapeUtil.createBoxShape(cube, new Vector3(1, 1, 1));
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Module map
|
|
46
|
+
|
|
47
|
+
| Path | Class | Purpose |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `Physics` | `Physics` (singleton) | World, step, snapshot, gravity |
|
|
50
|
+
| `rigidbody/Rigidbody` | `Rigidbody` | Dynamic/Static/Kinematic body component |
|
|
51
|
+
| `rigidbody/RigidbodyEnum` | `BodyType` | Body kind enum |
|
|
52
|
+
| `shape/CollisionShapeUtil` | `CollisionShapeUtil` | Box / Sphere / Capsule / Cylinder / Cone / Plane / ConvexHull / Trimesh / Heightfield / Compound |
|
|
53
|
+
| `joint/HingeJoint` | `HingeJoint` | 1 angular DOF (revolute) |
|
|
54
|
+
| `joint/SliderJoint` | `SliderJoint` | 1 linear DOF (prismatic) |
|
|
55
|
+
| `joint/FixedJoint` | `FixedJoint` | All 6 DOFs locked |
|
|
56
|
+
| `joint/SphericalJoint` | `SphericalJoint` | Ball-and-socket (replaces P2P + ConeTwist) |
|
|
57
|
+
| `joint/GenericJoint` | `GenericJoint` | 6-DOF, axis mask |
|
|
58
|
+
| `joint/RopeJoint` | `RopeJoint` | Max distance constraint |
|
|
59
|
+
| `joint/SpringJoint` | `SpringJoint` | Hooke's law spring |
|
|
60
|
+
| `character/CharacterController` | `CharacterController` | Kinematic character with slope/step/snap |
|
|
61
|
+
| `vehicle/VehicleController` | `VehicleController` | Raycast vehicle (chassis + N wheels) |
|
|
62
|
+
| `query/PhysicsQuery` | `PhysicsQuery` | `raycast / raycastAll / sweep / overlap / closestPoint` |
|
|
63
|
+
| `debug/PhysicsDebugDrawer` | `PhysicsDebugDrawer` | Live wireframe via `Graphic3D` |
|
|
64
|
+
| `utils/PhysicsDragger` | `PhysicsDragger` | Mouse drag for dynamic bodies |
|
|
65
|
+
| `utils/TempPhyMath` | `TempPhyMath` | `Vector3`/`Quaternion` ↔ Rapier POJO helpers |
|
|
66
|
+
|
|
67
|
+
## Triggers and events
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const sensor = obj.addComponent(Rigidbody);
|
|
71
|
+
sensor.bodyType = BodyType.Static;
|
|
72
|
+
sensor.shape = CollisionShapeUtil.createBoxShape(obj, new Vector3(2, 2, 2));
|
|
73
|
+
sensor.isSensor = true; // must be set before start()
|
|
74
|
+
sensor.enableEvents = true; // must be set before start()
|
|
75
|
+
sensor.onTriggerEnter = (other) => console.log('entered', other.object3D.name);
|
|
76
|
+
sensor.onTriggerExit = (other) => console.log('left', other.object3D.name);
|
|
77
|
+
|
|
78
|
+
// On a dynamic body, the same flag plus contact callbacks:
|
|
79
|
+
const rb = body.addComponent(Rigidbody);
|
|
80
|
+
rb.enableEvents = true;
|
|
81
|
+
rb.onContactBegin = (other) => { /* one-shot */ };
|
|
82
|
+
rb.onContactStay = (other) => { /* every frame while touching */ };
|
|
83
|
+
rb.onContactEnd = (other) => { /* one-shot */ };
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Queries
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { PhysicsQuery } from '@orillusion/physics-rapier';
|
|
90
|
+
|
|
91
|
+
const hit = PhysicsQuery.raycast(origin, dir, { maxDistance: 100 });
|
|
92
|
+
if (hit) console.log(hit.rigidbody, hit.point, hit.normal);
|
|
93
|
+
|
|
94
|
+
const overlapping = PhysicsQuery.overlap(
|
|
95
|
+
CollisionShapeUtil.createBoxShape(obj, new Vector3(2, 2, 2)),
|
|
96
|
+
pos, rot, { excludeSensors: true },
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Snapshot / replay
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const blob = Physics.snapshot(); // Uint8Array
|
|
104
|
+
// ... time passes ...
|
|
105
|
+
Physics.restore(blob); // world rewound
|
|
106
|
+
// NOTE: engine-side Rigidbody bindings are not restored automatically.
|
|
107
|
+
// See samples/physics-rapier/Sample_RapierSnapshot.ts for the pattern.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Migration from `@orillusion/physics` (ammo)
|
|
111
|
+
|
|
112
|
+
For most projects:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
- import { Physics, Rigidbody, ColliderComponent, BoxColliderShape, ... } from '@orillusion/physics';
|
|
116
|
+
+ import { Physics, Rigidbody, BodyType, CollisionShapeUtil } from '@orillusion/physics-rapier';
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Behavioral differences:
|
|
120
|
+
|
|
121
|
+
| ammo | physics-rapier |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `rb.mass = 0` for static | `rb.bodyType = BodyType.Static` *(or `mass = 0`, both work)* |
|
|
124
|
+
| `ColliderComponent` + `BoxColliderShape` | `rb.shape = CollisionShapeUtil.createBoxShape(obj)` (no separate collider component) |
|
|
125
|
+
| `setCcdMotionThreshold(t) + setCcdSweptSphereRadius(r)` | `rb.enableCcd(true)` |
|
|
126
|
+
| `setLinearFactor(x, y, z)` | `rb.lockTranslations(x === 0, y === 0, z === 0)` |
|
|
127
|
+
| `Physics.world.rayTest(...)` (private) | `PhysicsQuery.raycast(origin, dir, { ... })` |
|
|
128
|
+
| `Ammo.btRaycastVehicle` raw API | `VehicleController` component |
|
|
129
|
+
| Soft body (`ClothSoftbody`, `RopeSoftbody`) | NOT SUPPORTED — keep using `@orillusion/physics` |
|
|
130
|
+
| Joints: `HingeConstraint`, `SliderConstraint`, ... | Renamed to `HingeJoint`, `SliderJoint`, ... |
|
|
131
|
+
| `PointToPointConstraint` + `ConeTwistConstraint` | Both replaced by `SphericalJoint` |
|
|
132
|
+
| `Generic6DofConstraint` + `Generic6DofSpringConstraint` | Replaced by `GenericJoint` (spring built-in) + `SpringJoint` |
|
|
133
|
+
|
|
134
|
+
## Escape hatches
|
|
135
|
+
|
|
136
|
+
When you need a Rapier-only feature that the engine wrapper doesn't expose:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
140
|
+
|
|
141
|
+
const native = rb.native; // Rapier RigidBody
|
|
142
|
+
native.setEnabledRotations(true, false, true, true);
|
|
143
|
+
|
|
144
|
+
const world = Physics.world; // Rapier World
|
|
145
|
+
world.integrationParameters.numSolverIterations = 8;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Touching `.native` or `Physics.world` opts out of cross-backend portability.
|
|
149
|
+
|
|
150
|
+
## Roadmap
|
|
151
|
+
|
|
152
|
+
- **Done (P0–P2):** rigid bodies, 7 joints, character, vehicle, queries, events, debug, dragger, snapshot, deterministic flag.
|
|
153
|
+
- **Future:** Web Worker mode (`Physics.init({ worker: true })` is API-stable; landing pending COOP/COEP infrastructure).
|
|
154
|
+
- **Future:** GPU XPBD soft body / cloth / fluid as a separate `@orillusion/physics-xpbd` package.
|
|
155
|
+
|
|
156
|
+
## License
|
|
157
|
+
|
|
158
|
+
MIT
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { Vector3, View3D } from '@orillusion/core';
|
|
3
|
+
import { PhysicsDebugDrawer, DebugDrawerOptions } from './debug/PhysicsDebugDrawer';
|
|
4
|
+
import { PhysicsDragger } from './utils/PhysicsDragger';
|
|
5
|
+
import type { Rigidbody } from './rigidbody/Rigidbody';
|
|
6
|
+
declare class _Physics {
|
|
7
|
+
private _world;
|
|
8
|
+
private _eventQueue;
|
|
9
|
+
private _isInited;
|
|
10
|
+
private _isStop;
|
|
11
|
+
private _gravity;
|
|
12
|
+
/** Maximum number of internal physics sub-steps per update tick. */
|
|
13
|
+
maxSubSteps: number;
|
|
14
|
+
/** Fixed simulation timestep used to clamp variable frame deltas. */
|
|
15
|
+
fixedTimeStep: number;
|
|
16
|
+
/** @internal Collider handle → Rigidbody component. */
|
|
17
|
+
private _handleToRigidbody;
|
|
18
|
+
/** @internal Vehicle controllers needing per-frame `updateVehicle()`. */
|
|
19
|
+
private _preStepCallbacks;
|
|
20
|
+
private _debugDrawer;
|
|
21
|
+
private _dragger;
|
|
22
|
+
/**
|
|
23
|
+
* Initialize Rapier physics world.
|
|
24
|
+
*
|
|
25
|
+
* @param options.gravity - Default `(0, -9.8, 0)`.
|
|
26
|
+
* @param options.deterministic - When `true`, force a single-thread serial
|
|
27
|
+
* solver path so simulation is bit-exact across runs / machines (cost:
|
|
28
|
+
* ~10-20% perf). Rapier is largely deterministic by default within the
|
|
29
|
+
* same WASM build; this flag pins additional knobs for cross-machine
|
|
30
|
+
* reproducibility.
|
|
31
|
+
* @param options.worker - Reserved for future use. When set, the world
|
|
32
|
+
* would be marshalled into a Web Worker via SharedArrayBuffer. Currently
|
|
33
|
+
* logs a one-time warning and falls back to main-thread execution; the
|
|
34
|
+
* API is stable enough that user code passing this flag will Just Work
|
|
35
|
+
* when worker mode lands.
|
|
36
|
+
*/
|
|
37
|
+
init(options?: {
|
|
38
|
+
gravity?: Vector3;
|
|
39
|
+
deterministic?: boolean;
|
|
40
|
+
worker?: boolean;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Step the physics world. Drains the event queue and dispatches contact /
|
|
44
|
+
* trigger callbacks back onto registered Rigidbody components.
|
|
45
|
+
*
|
|
46
|
+
* @param timeStep - Default `Time.delta * 0.001`. Clamped against
|
|
47
|
+
* `fixedTimeStep * maxSubSteps` to avoid spiral-of-death.
|
|
48
|
+
*/
|
|
49
|
+
update(timeStep?: number): void;
|
|
50
|
+
/**
|
|
51
|
+
* Enable physics debug drawing. Pass a `Graphic3D` instance attached to your scene.
|
|
52
|
+
*/
|
|
53
|
+
initDebugDrawer(graphic3D: any, options?: DebugDrawerOptions): PhysicsDebugDrawer;
|
|
54
|
+
get debugDrawer(): PhysicsDebugDrawer;
|
|
55
|
+
/**
|
|
56
|
+
* Enable mouse drag of dynamic rigid bodies. Safe to call at any point
|
|
57
|
+
* after `Physics.init`; if `view.engine3D` is not yet bound (i.e. called
|
|
58
|
+
* before `engine.startRenderView`), the dragger defers event registration
|
|
59
|
+
* to the next animation frame and picks up the input system once
|
|
60
|
+
* `startRenderView` runs.
|
|
61
|
+
*/
|
|
62
|
+
enableDragger(view: View3D): PhysicsDragger;
|
|
63
|
+
get dragger(): PhysicsDragger;
|
|
64
|
+
/**
|
|
65
|
+
* Serialize the entire physics world to a transferable byte array.
|
|
66
|
+
*
|
|
67
|
+
* Use this for replay / network rollback / save-game state. Rapier
|
|
68
|
+
* snapshots preserve body/collider handle indices, which lets `restore`
|
|
69
|
+
* re-attach existing `Rigidbody` components to the rebuilt world without
|
|
70
|
+
* tearing down Object3Ds.
|
|
71
|
+
*
|
|
72
|
+
* Caveats: snapshots do NOT round-trip Rapier-side controllers (vehicle,
|
|
73
|
+
* character) or engine-only metadata (`onContactBegin` callbacks, sensor
|
|
74
|
+
* flags rebuilt at collider-create time). If you use those, recreate them
|
|
75
|
+
* after `restore`.
|
|
76
|
+
*/
|
|
77
|
+
snapshot(): Uint8Array;
|
|
78
|
+
/**
|
|
79
|
+
* Replace the active world with a previously taken snapshot.
|
|
80
|
+
*
|
|
81
|
+
* Re-binds existing `Rigidbody` components to wrappers in the new world
|
|
82
|
+
* using preserved handle indices, so components stay live after restore.
|
|
83
|
+
* Any Rigidbody whose body handle is not present in the snapshot (e.g.
|
|
84
|
+
* spawned after the snapshot was taken) is detached and emits a warning.
|
|
85
|
+
*/
|
|
86
|
+
restore(data: Uint8Array): void;
|
|
87
|
+
get world(): RAPIER.World;
|
|
88
|
+
get eventQueue(): RAPIER.EventQueue;
|
|
89
|
+
get isInited(): boolean;
|
|
90
|
+
set isStop(value: boolean);
|
|
91
|
+
get isStop(): boolean;
|
|
92
|
+
set gravity(value: Vector3);
|
|
93
|
+
get gravity(): Vector3;
|
|
94
|
+
/** @internal Used by Rigidbody.start to register all colliders for events. */
|
|
95
|
+
_registerRigidbody(rb: Rigidbody): void;
|
|
96
|
+
/** @internal */
|
|
97
|
+
_unregisterRigidbody(rb: Rigidbody): void;
|
|
98
|
+
/** @internal Lookup the Rigidbody component owning a Rapier collider handle. */
|
|
99
|
+
_rigidbodyOfHandle(handle: number): Rigidbody | undefined;
|
|
100
|
+
/** Register a callback to run before every world.step (used by VehicleController). */
|
|
101
|
+
addPreStep(cb: (dt: number) => void): void;
|
|
102
|
+
removePreStep(cb: (dt: number) => void): void;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Single physics instance, mirroring `@orillusion/physics` Physics symbol.
|
|
106
|
+
*
|
|
107
|
+
* ```ts
|
|
108
|
+
* await Physics.init();
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @group Plugin
|
|
112
|
+
*/
|
|
113
|
+
export declare let Physics: _Physics;
|
|
114
|
+
export { RAPIER };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ComponentBase, Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
/**
|
|
4
|
+
* Kinematic character controller — Rapier-only, no ammo equivalent.
|
|
5
|
+
*
|
|
6
|
+
* Owns its own kinematic-position-based body and collider; user calls `move()`
|
|
7
|
+
* each frame with a desired translation, controller resolves penetration,
|
|
8
|
+
* slope climbing, snap-to-ground.
|
|
9
|
+
*
|
|
10
|
+
* @group Components
|
|
11
|
+
*/
|
|
12
|
+
export declare class CharacterController extends ComponentBase {
|
|
13
|
+
private _initResolve;
|
|
14
|
+
private _initializationPromise;
|
|
15
|
+
private _body;
|
|
16
|
+
private _collider;
|
|
17
|
+
private _controller;
|
|
18
|
+
private _bodyInited;
|
|
19
|
+
private _grounded;
|
|
20
|
+
/** Collider descriptor (typically a capsule). Set BEFORE `start()`. */
|
|
21
|
+
shape: RAPIER.ColliderDesc;
|
|
22
|
+
/** Penetration prediction offset. Default `0.01`. */
|
|
23
|
+
offset: number;
|
|
24
|
+
/** Maximum slope angle the character can walk up (radians). */
|
|
25
|
+
maxSlopeClimbAngle: number;
|
|
26
|
+
/** Below this slope angle the character starts sliding (radians). */
|
|
27
|
+
minSlopeSlideAngle: number;
|
|
28
|
+
/** Snap-to-ground distance. `0` disables snapping. */
|
|
29
|
+
snapToGround: number;
|
|
30
|
+
/** Whether character pushes dynamic bodies it collides with. */
|
|
31
|
+
applyImpulsesToDynamicBodies: boolean;
|
|
32
|
+
/** Auto-step config: `null` to disable. */
|
|
33
|
+
autoStep: {
|
|
34
|
+
maxHeight: number;
|
|
35
|
+
minWidth: number;
|
|
36
|
+
includeDynamic: boolean;
|
|
37
|
+
} | null;
|
|
38
|
+
start(): void;
|
|
39
|
+
/**
|
|
40
|
+
* Compute and apply a movement step. Internal pipeline:
|
|
41
|
+
* 1. computeColliderMovement(desired) → resolves penetration / slopes
|
|
42
|
+
* 2. read computedMovement() & computedGrounded()
|
|
43
|
+
* 3. setNextKinematicTranslation to apply
|
|
44
|
+
*/
|
|
45
|
+
move(desiredTranslation: Vector3): void;
|
|
46
|
+
onUpdate(): void;
|
|
47
|
+
destroy(force?: boolean): void;
|
|
48
|
+
wait(): Promise<void>;
|
|
49
|
+
/** Whether the character is touching the ground after the last `move()`. */
|
|
50
|
+
isGrounded(): boolean;
|
|
51
|
+
get body(): RAPIER.RigidBody;
|
|
52
|
+
get collider(): RAPIER.Collider;
|
|
53
|
+
get native(): RAPIER.KinematicCharacterController;
|
|
54
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface DebugDrawerOptions {
|
|
2
|
+
enable?: boolean;
|
|
3
|
+
/** Draw every N frames. Default 1 = every frame. */
|
|
4
|
+
updateFreq?: number;
|
|
5
|
+
/** Hard cap on rendered segments to prevent UI freeze on huge scenes. */
|
|
6
|
+
maxLineCount?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Visualize the physics world via `world.debugRender()`. Wraps the
|
|
10
|
+
* `Graphic3D` line renderer.
|
|
11
|
+
*
|
|
12
|
+
* Mirrors `@orillusion/physics`'s `PhysicsDebugDrawer` shape, but uses Rapier's
|
|
13
|
+
* built-in debug renderer (returns line buffer + color buffer in one call).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const g = new Graphic3D();
|
|
18
|
+
* scene.addChild(g);
|
|
19
|
+
* Physics.initDebugDrawer(g);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class PhysicsDebugDrawer {
|
|
23
|
+
private _enable;
|
|
24
|
+
private _frameCount;
|
|
25
|
+
private _drawnUuids;
|
|
26
|
+
/** A `Graphic3D` instance (typed loosely so this package doesn't hard-depend on `@orillusion/graphic`). */
|
|
27
|
+
graphic3D: any;
|
|
28
|
+
updateFreq: number;
|
|
29
|
+
maxLineCount: number;
|
|
30
|
+
private readonly _tmpA;
|
|
31
|
+
private readonly _tmpB;
|
|
32
|
+
constructor(graphic3D: any, options?: DebugDrawerOptions);
|
|
33
|
+
set enable(value: boolean);
|
|
34
|
+
get enable(): boolean;
|
|
35
|
+
/** Called once per frame from `Physics.update`. */
|
|
36
|
+
update(): void;
|
|
37
|
+
private _clearLines;
|
|
38
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './Physics';
|
|
2
|
+
export * from './utils/TempPhyMath';
|
|
3
|
+
export * from './utils/PhysicsDragger';
|
|
4
|
+
export * from './rigidbody/RigidbodyEnum';
|
|
5
|
+
export * from './rigidbody/Rigidbody';
|
|
6
|
+
export * from './shape/CollisionShapeUtil';
|
|
7
|
+
export * from './joint/ConstraintBase';
|
|
8
|
+
export * from './joint/HingeJoint';
|
|
9
|
+
export * from './joint/SliderJoint';
|
|
10
|
+
export * from './joint/FixedJoint';
|
|
11
|
+
export * from './joint/SphericalJoint';
|
|
12
|
+
export * from './joint/GenericJoint';
|
|
13
|
+
export * from './joint/RopeJoint';
|
|
14
|
+
export * from './joint/SpringJoint';
|
|
15
|
+
export * from './character/CharacterController';
|
|
16
|
+
export * from './vehicle/VehicleController';
|
|
17
|
+
export * from './query/PhysicsQuery';
|
|
18
|
+
export * from './debug/PhysicsDebugDrawer';
|
|
19
|
+
export * from '@dimforge/rapier3d-compat';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ComponentBase } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { Rigidbody } from '../rigidbody/Rigidbody';
|
|
4
|
+
/**
|
|
5
|
+
* Shared base for all joint components.
|
|
6
|
+
*
|
|
7
|
+
* Subclasses set `connectedBody` (the second body, with this Object3D's body
|
|
8
|
+
* being the first) and override `buildJointData()` to return a `RAPIER.JointData`.
|
|
9
|
+
*/
|
|
10
|
+
export declare abstract class ConstraintBase<T extends RAPIER.ImpulseJoint = RAPIER.ImpulseJoint> extends ComponentBase {
|
|
11
|
+
protected _joint: T;
|
|
12
|
+
/** The other body of the constraint. */
|
|
13
|
+
connectedBody: Rigidbody;
|
|
14
|
+
/** Whether contacts are computed between the two connected bodies. Default: false. */
|
|
15
|
+
collisionsEnabled: boolean;
|
|
16
|
+
/** Whether to wake up the bodies when the joint is created. Default: true. */
|
|
17
|
+
wakeUpOnCreate: boolean;
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
/** Subclasses build their JointData (revolute, fixed, etc.). */
|
|
20
|
+
protected abstract buildJointData(): RAPIER.JointData;
|
|
21
|
+
/** Hook for subclasses to apply per-joint settings (limits, motor) post-creation. */
|
|
22
|
+
protected afterStart(): void;
|
|
23
|
+
destroy(force?: boolean): void;
|
|
24
|
+
/** Native impulse joint. Touching this opts out of cross-backend portability. */
|
|
25
|
+
get native(): T;
|
|
26
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Vector3, Quaternion } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Fixed joint — locks all 6 DOFs between two bodies. Mirrors
|
|
6
|
+
* `@orillusion/physics`'s `FixedConstraint`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class FixedJoint extends ConstraintBase<RAPIER.FixedImpulseJoint> {
|
|
9
|
+
anchorSelf: Vector3;
|
|
10
|
+
anchorTarget: Vector3;
|
|
11
|
+
frameSelf: Quaternion;
|
|
12
|
+
frameTarget: Quaternion;
|
|
13
|
+
protected buildJointData(): RAPIER.JointData;
|
|
14
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Bit-mask of joint axes to lock. Combine with `|`. Each unset axis remains
|
|
6
|
+
* free; each set axis is locked. Default `LockAll - LinX` would lock 5 axes
|
|
7
|
+
* leaving X translation free.
|
|
8
|
+
*/
|
|
9
|
+
export declare const JointAxis: {
|
|
10
|
+
readonly LinX: 1;
|
|
11
|
+
readonly LinY: 2;
|
|
12
|
+
readonly LinZ: 4;
|
|
13
|
+
readonly AngX: 8;
|
|
14
|
+
readonly AngY: 16;
|
|
15
|
+
readonly AngZ: 32;
|
|
16
|
+
readonly LockAll: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Generic 6-DOF joint — pick which axes to lock via `lockedAxes` mask.
|
|
20
|
+
*
|
|
21
|
+
* Replaces `Generic6DofConstraint` and `Generic6DofSpringConstraint` from
|
|
22
|
+
* the ammo plugin (Rapier's `GenericJoint` natively supports both).
|
|
23
|
+
*/
|
|
24
|
+
export declare class GenericJoint extends ConstraintBase<RAPIER.GenericImpulseJoint> {
|
|
25
|
+
anchorSelf: Vector3;
|
|
26
|
+
anchorTarget: Vector3;
|
|
27
|
+
axis: Vector3;
|
|
28
|
+
/** Which axes are locked. Default: all 5 except LinX (slider-like). */
|
|
29
|
+
lockedAxes: number;
|
|
30
|
+
protected buildJointData(): RAPIER.JointData;
|
|
31
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Hinge (revolute) joint — 1 angular DOF around `axis`.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors `@orillusion/physics`'s `HingeConstraint` symbol and method names.
|
|
8
|
+
*/
|
|
9
|
+
export declare class HingeJoint extends ConstraintBase<RAPIER.RevoluteImpulseJoint> {
|
|
10
|
+
/** Anchor point on body A (own Object3D's Rigidbody), in local space. */
|
|
11
|
+
anchorSelf: Vector3;
|
|
12
|
+
/** Anchor point on body B (`connectedBody`), in local space. */
|
|
13
|
+
anchorTarget: Vector3;
|
|
14
|
+
/** Hinge axis, defaults to world up. */
|
|
15
|
+
axis: Vector3;
|
|
16
|
+
private _limits;
|
|
17
|
+
private _motor;
|
|
18
|
+
protected buildJointData(): RAPIER.JointData;
|
|
19
|
+
protected afterStart(): void;
|
|
20
|
+
/** Set rotation limits (radians). */
|
|
21
|
+
setLimit(low: number, high: number): void;
|
|
22
|
+
/**
|
|
23
|
+
* Configure the angular motor for velocity control.
|
|
24
|
+
* @param targetVel - Target angular velocity (rad/s).
|
|
25
|
+
* @param factor - Damping/strength factor.
|
|
26
|
+
*/
|
|
27
|
+
setMotor(targetVel: number, factor?: number): void;
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Rope joint — bodies cannot drift further apart than `length`, but may
|
|
6
|
+
* approach freely. Rapier-specific (not present in ammo plugin).
|
|
7
|
+
*/
|
|
8
|
+
export declare class RopeJoint extends ConstraintBase<RAPIER.ImpulseJoint> {
|
|
9
|
+
anchorSelf: Vector3;
|
|
10
|
+
anchorTarget: Vector3;
|
|
11
|
+
length: number;
|
|
12
|
+
protected buildJointData(): RAPIER.JointData;
|
|
13
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Slider (prismatic) joint — 1 linear DOF along `axis`.
|
|
6
|
+
*
|
|
7
|
+
* Mirrors `@orillusion/physics`'s `SliderConstraint`.
|
|
8
|
+
*/
|
|
9
|
+
export declare class SliderJoint extends ConstraintBase<RAPIER.PrismaticImpulseJoint> {
|
|
10
|
+
anchorSelf: Vector3;
|
|
11
|
+
anchorTarget: Vector3;
|
|
12
|
+
axis: Vector3;
|
|
13
|
+
private _limits;
|
|
14
|
+
private _motor;
|
|
15
|
+
protected buildJointData(): RAPIER.JointData;
|
|
16
|
+
protected afterStart(): void;
|
|
17
|
+
setLimit(low: number, high: number): void;
|
|
18
|
+
setMotor(targetVel: number, factor?: number): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Spherical (ball-and-socket) joint — 3 angular DOFs free, position locked.
|
|
6
|
+
*
|
|
7
|
+
* Replaces both `PointToPointConstraint` and `ConeTwistConstraint` from the
|
|
8
|
+
* ammo plugin (Rapier folds them into one primitive).
|
|
9
|
+
*/
|
|
10
|
+
export declare class SphericalJoint extends ConstraintBase<RAPIER.SphericalImpulseJoint> {
|
|
11
|
+
anchorSelf: Vector3;
|
|
12
|
+
anchorTarget: Vector3;
|
|
13
|
+
protected buildJointData(): RAPIER.JointData;
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Vector3 } from '@orillusion/core';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import { ConstraintBase } from './ConstraintBase';
|
|
4
|
+
/**
|
|
5
|
+
* Spring joint — Hooke's law spring connecting two anchors with a rest length.
|
|
6
|
+
* Replaces ammo plugin's `Generic6DofSpringConstraint` for the simple case.
|
|
7
|
+
*/
|
|
8
|
+
export declare class SpringJoint extends ConstraintBase<RAPIER.ImpulseJoint> {
|
|
9
|
+
anchorSelf: Vector3;
|
|
10
|
+
anchorTarget: Vector3;
|
|
11
|
+
restLength: number;
|
|
12
|
+
stiffness: number;
|
|
13
|
+
damping: number;
|
|
14
|
+
protected buildJointData(): RAPIER.JointData;
|
|
15
|
+
}
|