@ludra/physics 0.9.0 → 0.91.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/dist/index.d.ts +5 -0
- package/dist/index.js +10 -1
- package/dist/rapier3d.d.ts +83 -0
- package/dist/rapier3d.js +608 -0
- package/package.json +3 -2
- package/src/index.ts +12 -2
- package/src/rapier3d.ts +680 -0
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ import { type Entity, type PhysicsEngine, type PhysicsHost, type PhysicsSettings
|
|
|
5
5
|
* `"physics": "rapier"` can be created. Safe to call more than once.
|
|
6
6
|
*/
|
|
7
7
|
export declare function loadRapierPhysics(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Loads Rapier 3D and registers the "rapier3d" engine, which scenes with `"dimensions": 3`
|
|
10
|
+
* run on. It is a separate module, so 2D games never download its WebAssembly.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadRapier3DPhysics(): Promise<void>;
|
|
8
13
|
/**
|
|
9
14
|
* Ludra's real physics engine: Rapier's deterministic build, so a simulation is
|
|
10
15
|
* bit-for-bit identical on every machine and in the browser, and tests stay valid.
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,13 @@ export function loadRapierPhysics() {
|
|
|
44
44
|
loading ??= RAPIER.init().then(() => registerPhysics("rapier", (settings) => new RapierPhysics(settings)));
|
|
45
45
|
return loading;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Loads Rapier 3D and registers the "rapier3d" engine, which scenes with `"dimensions": 3`
|
|
49
|
+
* run on. It is a separate module, so 2D games never download its WebAssembly.
|
|
50
|
+
*/
|
|
51
|
+
export async function loadRapier3DPhysics() {
|
|
52
|
+
await (await import("./rapier3d.js")).loadRapier3DPhysics();
|
|
53
|
+
}
|
|
47
54
|
// Rapier's memory lives in WebAssembly; free it when a world is garbage collected.
|
|
48
55
|
const cleanup = new FinalizationRegistry((world) => world.free());
|
|
49
56
|
/**
|
|
@@ -156,8 +163,10 @@ export class RapierPhysics {
|
|
|
156
163
|
const baseAnchor = localPoint(base, there);
|
|
157
164
|
const ownAnchor = toRapier(spec.anchor.x, spec.anchor.y);
|
|
158
165
|
const length = spec.length || Math.hypot(there.x - here.x, there.y - here.y);
|
|
166
|
+
// In 2D the axis is degrees (validation rejects a 3D vector here).
|
|
167
|
+
const axis = typeof spec.axis === "number" ? spec.axis : 0;
|
|
159
168
|
const data = spec.type === "prismatic"
|
|
160
|
-
? RAPIER.JointData.prismatic(baseAnchor, ownAnchor, rotateBack(base, toRapier(Math.cos(
|
|
169
|
+
? RAPIER.JointData.prismatic(baseAnchor, ownAnchor, rotateBack(base, toRapier(Math.cos(axis * DEGREES), Math.sin(axis * DEGREES))))
|
|
161
170
|
: spec.type === "fixed"
|
|
162
171
|
? RAPIER.JointData.fixed(baseAnchor, 0, ownAnchor, base.rotation() - link.body.rotation())
|
|
163
172
|
: spec.type === "rope"
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { type World as RapierWorld } from "@dimforge/rapier3d-deterministic-compat";
|
|
2
|
+
import { type Entity, type PhysicsEngine, type PhysicsHost, type PhysicsSettings, type RayHit, type RayOptions } from "@ludra/core";
|
|
3
|
+
/**
|
|
4
|
+
* Ludra's 3D worlds use Rapier's own conventions: metres, +y up, right-handed (+z toward
|
|
5
|
+
* the viewer). Nothing is mirrored, unlike 2D. Rotations are degrees in Ludra, applied
|
|
6
|
+
* y (turn), then x (tilt), then z (roll), and quaternions in Rapier.
|
|
7
|
+
*/
|
|
8
|
+
interface Vec3 {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
z: number;
|
|
12
|
+
}
|
|
13
|
+
interface Quat extends Vec3 {
|
|
14
|
+
w: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Loads Rapier 3D's WebAssembly and registers the "rapier3d" engine, which every scene with
|
|
18
|
+
* `"dimensions": 3` runs on. Safe to call more than once.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadRapier3DPhysics(): Promise<void>;
|
|
21
|
+
/** Degrees (applied y, then x, then z) to a quaternion. */
|
|
22
|
+
export declare function quaternionFromDegrees(x: number, y: number, z: number): Quat;
|
|
23
|
+
/** A quaternion back to degrees (y, then x, then z), as three.js's "YXZ" order reads it. */
|
|
24
|
+
export declare function degreesFromQuaternion(q: Quat): Vec3;
|
|
25
|
+
/**
|
|
26
|
+
* Ludra's 3D physics engine: Rapier 3D's deterministic build, so a simulation is bit-for-bit
|
|
27
|
+
* the same on every machine and in the browser. Bodies rotate in 3D, can be boxes, spheres,
|
|
28
|
+
* capsules, cylinders or convex hulls, and have friction and mass; players walk through
|
|
29
|
+
* Rapier's character controller.
|
|
30
|
+
*/
|
|
31
|
+
export declare class Rapier3DPhysics implements PhysicsEngine {
|
|
32
|
+
readonly name = "rapier3d";
|
|
33
|
+
readonly world: RapierWorld;
|
|
34
|
+
private readonly events;
|
|
35
|
+
private readonly links;
|
|
36
|
+
private readonly byCollider;
|
|
37
|
+
private pendingJoints;
|
|
38
|
+
constructor(settings: PhysicsSettings);
|
|
39
|
+
add(entity: Entity): void;
|
|
40
|
+
remove(entity: Entity): void;
|
|
41
|
+
/** Creates the joints whose two ends now both exist. */
|
|
42
|
+
private connectJoints;
|
|
43
|
+
private createController;
|
|
44
|
+
step(host: PhysicsHost): void;
|
|
45
|
+
/**
|
|
46
|
+
* Moves a player by its velocity (plus gravity, and the platform it stands on) through the
|
|
47
|
+
* character controller, which resolves slopes, steps and walls.
|
|
48
|
+
*/
|
|
49
|
+
private moveCharacter;
|
|
50
|
+
/** A body is grounded when a solid touches it from below; it then stands on that solid. */
|
|
51
|
+
private updateGround;
|
|
52
|
+
mass(e: Entity): number;
|
|
53
|
+
applyImpulse(e: Entity, x: number, y: number, at?: {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
z?: number;
|
|
57
|
+
}, z?: number): void;
|
|
58
|
+
/** Spin around z, in degrees per second (the axis the screen faces). */
|
|
59
|
+
angularVelocity(e: Entity): number;
|
|
60
|
+
setAngularVelocity(e: Entity, value: number): void;
|
|
61
|
+
spin(e: Entity): {
|
|
62
|
+
x: number;
|
|
63
|
+
y: number;
|
|
64
|
+
z: number;
|
|
65
|
+
};
|
|
66
|
+
setSpin(e: Entity, value: {
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
z: number;
|
|
70
|
+
}): void;
|
|
71
|
+
raycast(_host: PhysicsHost, from: {
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
z?: number;
|
|
75
|
+
}, to: {
|
|
76
|
+
x: number;
|
|
77
|
+
y: number;
|
|
78
|
+
z?: number;
|
|
79
|
+
}, options?: RayOptions): RayHit | undefined;
|
|
80
|
+
raw(resolve: (target: unknown) => Entity | undefined): unknown;
|
|
81
|
+
overlaps(a: Entity, b: Entity, margin?: number): boolean;
|
|
82
|
+
}
|
|
83
|
+
export {};
|