@react-three/rapier 0.12.1 → 0.13.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.
Files changed (26) hide show
  1. package/dist/declarations/src/{AnyCollider.d.ts → components/AnyCollider.d.ts} +51 -11
  2. package/dist/declarations/src/{Attractor.d.ts → components/Attractor.d.ts} +0 -0
  3. package/dist/declarations/src/{Debug.d.ts → components/Debug.d.ts} +0 -0
  4. package/dist/declarations/src/components/InstancedRigidBodies.d.ts +12 -0
  5. package/dist/declarations/src/{MeshCollider.d.ts → components/MeshCollider.d.ts} +5 -1
  6. package/dist/declarations/src/{Physics.d.ts → components/Physics.d.ts} +7 -2
  7. package/dist/declarations/src/{RigidBody.d.ts → components/RigidBody.d.ts} +10 -8
  8. package/dist/declarations/src/{hooks.d.ts → hooks/hooks.d.ts} +17 -5
  9. package/dist/declarations/src/{joints.d.ts → hooks/joints.d.ts} +19 -8
  10. package/dist/declarations/src/hooks/use-imperative-instance.d.ts +4 -0
  11. package/dist/declarations/src/index.d.ts +18 -17
  12. package/dist/declarations/src/types.d.ts +10 -10
  13. package/dist/declarations/src/utils/api.d.ts +18 -0
  14. package/dist/declarations/src/{interaction-groups.d.ts → utils/interaction-groups.d.ts} +0 -0
  15. package/dist/declarations/src/{shared-objects.d.ts → utils/shared-objects.d.ts} +0 -0
  16. package/dist/declarations/src/utils/three-object-helpers.d.ts +29 -0
  17. package/dist/declarations/src/{utils-collider.d.ts → utils/utils-collider.d.ts} +6 -7
  18. package/dist/declarations/src/{utils-rigidbody.d.ts → utils/utils-rigidbody.d.ts} +6 -6
  19. package/dist/declarations/src/{utils.d.ts → utils/utils.d.ts} +2 -2
  20. package/dist/react-three-rapier.cjs.dev.js +548 -600
  21. package/dist/react-three-rapier.cjs.prod.js +548 -600
  22. package/dist/react-three-rapier.esm.js +549 -604
  23. package/package.json +12 -12
  24. package/readme.md +165 -30
  25. package/dist/declarations/src/InstancedRigidBodies.d.ts +0 -10
  26. package/dist/declarations/src/api.d.ts +0 -179
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
@@ -14,26 +14,26 @@
14
14
  "devDependencies": {
15
15
  "@react-three/drei": "9.45.0",
16
16
  "@react-three/fiber": "8.9.1",
17
- "@react-three/test-renderer": "^8.0.17",
18
- "@types/react-dom": "^18.0.2",
19
- "@types/three": "^0.139.0",
17
+ "@react-three/test-renderer": "8.0.17",
18
+ "@types/react-dom": "18.0.2",
19
+ "@types/three": "0.139.0",
20
20
  "@vitejs/plugin-react": "^2.1.0",
21
- "@vitest/ui": "^0.25.2",
22
- "happy-dom": "^7.5.5",
21
+ "@vitest/ui": "0.25.2",
22
+ "happy-dom": "7.5.5",
23
23
  "react": "18.2.0",
24
24
  "react-dom": "18.2.0",
25
25
  "three": "0.146.0",
26
- "vitest": "^0.25.2"
26
+ "vitest": "0.25.2"
27
27
  },
28
28
  "peerDependencies": {
29
- "@react-three/fiber": "^8.0.12",
30
- "react": "^18.0.0",
29
+ "@react-three/fiber": "8.9.1",
30
+ "react": "18.2.0",
31
31
  "three": ">=0.139.2"
32
32
  },
33
33
  "dependencies": {
34
- "@dimforge/rapier3d-compat": "0.10.0",
35
- "three-stdlib": "^2.15.0",
36
- "use-asset": "^1.0.4"
34
+ "@dimforge/rapier3d-compat": "0.11.1",
35
+ "three-stdlib": "2.21.6",
36
+ "use-asset": "1.0.4"
37
37
  },
38
38
  "repository": "https://github.com/pmndrs/react-three-rapier/tree/master/packages/react-three-rapier"
39
39
  }
package/readme.md CHANGED
@@ -66,7 +66,7 @@ For full API outline and documentation, see 🧩 [API Docs](https://pmndrs.githu
66
66
  - [Collider Components](#collider-components)
67
67
  - [🖼 Collider Examples](#-collider-examples)
68
68
  - [Instanced Meshes](#instanced-meshes)
69
- - [Debug](#debug)
69
+ - [Moving things around, and applying forces](#moving-things-around-and-applying-forces)
70
70
  - [Collision Events](#collision-events)
71
71
  - [Configuring collision and solver groups](#configuring-collision-and-solver-groups)
72
72
  - [Contact force events](#contact-force-events)
@@ -238,66 +238,99 @@ If part of our meshes are invisible and you want to include them in the collider
238
238
 
239
239
  Instanced meshes can also be used and have automatic colliders generated from their mesh.
240
240
 
241
- By wrapping the `InstancedMesh` in `<InstancedRigidBodies />`, each instance will be attached to an individual `RigidBody`.
241
+ By wrapping exactly one `Three.InstancedMesh` in `<InstancedRigidBodies />`, each instance will be attached to an individual `RigidBody`.
242
242
 
243
243
  🧩 See [InstancedRigidBodiesProps docs](https://pmndrs.github.io/react-three-rapier/interfaces/InstancedRigidBodiesProps.html) for available props.
244
244
 
245
245
  ```tsx
246
- import { InstancedRigidBodies } from "@react-three/rapier";
246
+ import { InstancedRigidBodies, RapierRigidBody } from "@react-three/rapier";
247
247
 
248
248
  const COUNT = 1000;
249
249
 
250
250
  const Scene = () => {
251
- const instancedApi = useRef<InstancedRigidBodyApi>(null);
251
+ const rigidBodies = useRef<RapierRigidBody[]>(null);
252
252
 
253
253
  useEffect(() => {
254
- if (!instancedApi.current) {
254
+ if (!rigidBodies.current) {
255
255
  return
256
256
  }
257
257
 
258
258
  // You can access individual instanced by their index
259
- instancedApi.current.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
259
+ rigidBodies.current.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
260
260
 
261
- // Or update all instances as if they were in an array
262
- instancedApi.current.forEach((api) => {
261
+ // Or update all instances
262
+ rigidBodies.current.forEach((api) => {
263
263
  api.applyImpulse({ x: 0, y: 10, z: 0 });
264
264
  });
265
265
  }, []);
266
266
 
267
267
  // We can set the initial positions, and rotations, and scales, of
268
- // the instances by providing an array equal to the instance count
269
- const positions = Array.from({ length: COUNT }, (_, index) => [index, 0, 0]);
270
-
271
- const rotations = Array.from({ length: COUNT }, (_, index) => [
272
- Math.random(),
273
- Math.random(),
274
- Math.random()
275
- ]);
268
+ // the instances by providing an array of InstancedRigidBodyProps
269
+ // which is the same as RigidBodyProps, but with an additional "key" prop.
270
+ const instances = useMemo(() => {
271
+ const instances: InstancedRigidBodyProps[] = [];
272
+
273
+ for (let i = 0; i < COUNT; i++) {
274
+ instances.push({
275
+ key: 'instance_' + Math.random(),
276
+ position: [Math.random() * 10, Math.random() * 10, Math.random() * 10],
277
+ rotation: [Math.random(), Math.random(), Math.random()],
278
+ });
279
+ }
276
280
 
277
- const scales = Array.from({ length: COUNT }, (_, index) => [
278
- Math.random(),
279
- Math.random(),
280
- Math.random()
281
- ]);
281
+ return instances;
282
+ }, []);
282
283
 
283
284
  return (
284
285
  <InstancedRigidBodies
285
286
  ref={instancedApi}
286
- positions={positions}
287
- rotations={rotations}
288
- scales={scales}
287
+ instances={instances}
289
288
  colliders="ball"
290
289
  >
291
- <instancedMesh args={[undefined, undefined, COUNT]}>
292
- <sphereGeometry args={[0.2]} />
293
- <meshPhysicalGeometry color="blue" />
290
+ <instancedMesh args={[undefined, undefined, COUNT]} count={COUNT} />
291
+ </InstancedRigidBodies>
292
+ );
293
+ };
294
+ ```
295
+
296
+ We can also create compound shapes for instanced meshes by providing an array of `Colliders` in the `colliderNodes` prop.
297
+
298
+ ```tsx
299
+ import { InstancedRigidBodies, BoxCollider, SphereCollider } from "@react-three/rapier";
300
+ const COUNT = 500
294
301
 
295
- <CuboidCollider args={[0.1, 0.2, 0.1]} />
296
- </instancedMesh>
302
+ const Scene = () => {
303
+ const instances = useMemo(() => {
304
+ const instances: InstancedRigidBodyProps[] = [];
305
+
306
+ for (let i = 0; i < COUNT; i++) {
307
+ instances.push({
308
+ key: 'instance_' + Math.random(),
309
+ position: [Math.random() * 10, Math.random() * 10, Math.random() * 10],
310
+ rotation: [Math.random(), Math.random(), Math.random()],
311
+ });
312
+ }
313
+
314
+ return instances;
315
+ }, []);
316
+
317
+ return (
318
+ <InstancedRigidBodies
319
+ ref={instancedApi}
320
+ instances={instances}
321
+ colliders="ball"
322
+ colliderNodes={[
323
+ <BoxCollider args={[0.5, 0.5, 0.5]} />,
324
+ <SphereCollider args={[0.5]} />,
325
+ ]}
326
+ >
327
+ <instancedMesh args={[undefined, undefined, COUNT]} count={COUNT} />
297
328
  </InstancedRigidBodies>
298
329
  );
299
330
  };
300
331
  ```
332
+ }
333
+ ```
301
334
 
302
335
  ## Debug
303
336
 
@@ -323,6 +356,87 @@ const Scene = () => {
323
356
  };
324
357
  ```
325
358
 
359
+ ## Moving things around, and applying forces
360
+ You can access the instance for a RigidBody by storing its `ref`. This allows you to perform any operation on the underlying physics object directly.
361
+
362
+ `r3/rapier` exposes a `RapierRigidBody` and `RapierCollider` as aliases for `rapiers` underlying base objects.
363
+
364
+ For all available methods, see the [Rapier docs](https://rapier.rs/javascript3d/classes/RigidBody.html).
365
+
366
+ ```tsx
367
+ import {
368
+ RigidBody,
369
+ RapierRigidBody
370
+ } from "@react-three/rapier";
371
+
372
+ const Scene = () => {
373
+ const rigidBody = useRef<RapierRigidBody>(null);
374
+
375
+ useEffect(() => {
376
+ if (rigidBody.current) {
377
+ // A one-off "push"
378
+ rigidBody.current.applyImpulse({ x: 0, y: 10, z: 0 }, true);
379
+
380
+ // A continuous force
381
+ rigidBody.current.addForce({ x: 0, y: 10, z: 0 }, true);
382
+
383
+ // A one-off torque rotation
384
+ rigidBody.current.applyTorqueImpulse({ x: 0, y: 10, z: 0 }, true);
385
+
386
+ // A continuous torque
387
+ rigidBody.current.addTorque({ x: 0, y: 10, z: 0 }, true);
388
+ }
389
+ }, []);
390
+
391
+ return (
392
+ <RigidBody ref={rigidBody}>
393
+ <mesh>
394
+ <boxBufferGeometry />
395
+ <meshStandardMaterial />
396
+ </mesh>
397
+ </RigidBody>
398
+ );
399
+ };
400
+ ```
401
+
402
+ Rapier's API returns quaternions and vectors that are not compatible with Three.js, `r3/rapier` therefore exposes some helper functions (`vec3`, `quat`, `euler`) for quick type conversions. These helper functions can also be used as a shorthand for creating new objects.
403
+
404
+ ```tsx
405
+ import {
406
+ RapierRigidBody,
407
+ quat,
408
+ vec3,
409
+ euler
410
+ } from "@react-three/rapier";
411
+
412
+ const Scene = () => {
413
+ const rigidBody = useRef<RapierRigidBody>(null)
414
+
415
+ useEffect(() => {
416
+ if (rigidBody.current) {
417
+ const position = vec3(rigidBody.current.translation())
418
+ const quaternion = quat(rigidBody.current.rotation())
419
+ const eulerRot = euler().setFromQuaternion(quat(rigidBody.current.rotation()))
420
+
421
+ // While Rapier's return types need conversion, setting values can be done directly with Three.js types
422
+ rigidBody.current.setTranslation(position, true)
423
+ rigidBody.current.setRotation(quaternion, true)
424
+ rigidBody.current.setAngVel({x: 0, y: 2, z: 0}, true)
425
+ }
426
+ }, [])
427
+
428
+ return (
429
+ <RigidBody ref={rigidBody}>
430
+ <mesh>
431
+ <boxBufferGeometry />
432
+ <meshStandardMaterial />
433
+ </mesh>
434
+ </RigidBody>
435
+ );
436
+ }
437
+
438
+ ```
439
+
326
440
  ## Collision Events
327
441
 
328
442
  You can subscribe to collision and state events on a RigidBody:
@@ -560,6 +674,21 @@ There are 4 different joint types available:
560
674
  - Revolute (two bodies are connected by a hinge, for things like doors or wheels)
561
675
  - Prismatic (two bodies are connected by a sliding joint, for things like pistons or sliders)
562
676
 
677
+ Each joint hook returns a RefObject containing the raw reference to the hook instance.
678
+ ```tsx
679
+ const WheelJoint = ({bodyA, bodyB}) => {
680
+ const joint = useRevoluteJoint(bodyA, bodyB, [[0,0,0],[0,0,0],[0,0,0]])
681
+
682
+ useFrame(() => {
683
+ if (joint.current) {
684
+ joint.current.configureMotorVelocity(10, 2)
685
+ }
686
+ }, [])
687
+
688
+ return null
689
+ }
690
+ ```
691
+
563
692
  ### Fixed Joint
564
693
  A fixed joint ensures that two rigid-bodies don't move relative to each other. Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body. The fixed-joint makes these frames coincide in world-space.
565
694
 
@@ -636,6 +765,12 @@ const JointedThing = () => {
636
765
  [0, 0, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
637
766
  ]);
638
767
 
768
+ useEffect(() => {
769
+ if (joint.current) {
770
+
771
+ }
772
+ }, [])
773
+
639
774
  return (
640
775
  <group>
641
776
  <RigidBody ref={bodyA}>
@@ -693,7 +828,7 @@ const JointedThing = () => {
693
828
  joint.configureMotorVelocity(1, 0)
694
829
 
695
830
  // Disable contacts between the two joint bodies
696
- joint.raw().setContactsEnabled(false)
831
+ joint.setContactsEnabled(false)
697
832
  }, [])
698
833
 
699
834
  return ...
@@ -1,10 +0,0 @@
1
- import React from "react";
2
- import { InstancedRigidBodyApi } from "./api";
3
- import { RigidBodyProps } from "./RigidBody";
4
- import { Vector3Array } from "./types";
5
- export interface InstancedRigidBodiesProps extends Omit<RigidBodyProps, "position" | "rotation"> {
6
- positions?: Vector3Array[];
7
- rotations?: Vector3Array[];
8
- scales?: Vector3Array[];
9
- }
10
- export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<InstancedRigidBodiesProps & React.RefAttributes<InstancedRigidBodyApi>>;
@@ -1,179 +0,0 @@
1
- import { Collider, ColliderDesc, DebugRenderBuffers, ImpulseJoint, JointData, RigidBody, RigidBodyDesc, World } from "@dimforge/rapier3d-compat";
2
- import { Quaternion, Vector3 } from "three";
3
- import { RefGetter, Vector3Object } from "./types";
4
- export interface RigidBodyApi {
5
- /**
6
- * Get the raw RigidBody
7
- * @see https://rapier.rs/javascript3d/classes/RigidBody.html
8
- */
9
- raw(): RigidBody;
10
- /**
11
- * The handle of this RigidBody
12
- */
13
- handle: number;
14
- /**
15
- * The mass of this rigid-body.
16
- */
17
- mass(): number;
18
- /**
19
- * Applies an impulse at the center-of-mass of this rigid-body.
20
- */
21
- applyImpulse(impulseVector: Vector3Object, wakeUp?: boolean): void;
22
- /**
23
- * Applies an impulsive torque at the center-of-mass of this rigid-body.
24
- */
25
- applyTorqueImpulse(torqueVector: Vector3Object, wakeUp?: boolean): void;
26
- /**
27
- * Applies an impulse at the given world-space point of this rigid-body.
28
- */
29
- applyImpulseAtPoint(impulseVector: Vector3Object, impulsePoint: Vector3Object, wakeUp?: boolean): void;
30
- /**
31
- * Adds a force at the center-of-mass of this rigid-body.
32
- */
33
- addForce(force: Vector3Object, wakeUp?: boolean): void;
34
- /**
35
- * Adds a force at the given world-space point of this rigid-body.
36
- */
37
- addForceAtPoint(force: Vector3Object, point: Vector3Object, wakeUp?: boolean): void;
38
- /**
39
- * Adds a torque at the center-of-mass of this rigid-body.
40
- */
41
- addTorque(torque: Vector3Object, wakeUp?: boolean): void;
42
- /**
43
- * The world-space translation of this rigid-body.
44
- */
45
- translation(): Vector3;
46
- /**
47
- * Sets the translation of this rigid-body.
48
- */
49
- setTranslation(translation: Vector3Object, wakeUp?: boolean): void;
50
- /**
51
- * The world-space orientation of this rigid-body.
52
- */
53
- rotation(): Quaternion;
54
- /**
55
- * Sets the rotation quaternion of this rigid-body.
56
- */
57
- setRotation(rotation: Quaternion, wakeUp?: boolean): void;
58
- /**
59
- * The linear velocity of this rigid-body.
60
- */
61
- linvel(): Vector3;
62
- /**
63
- * Sets the linear velocity of this rigid-body.
64
- */
65
- setLinvel(velocity: Vector3Object, wakeUp?: boolean): void;
66
- /**
67
- * The angular velocity of this rigid-body.
68
- */
69
- angvel(): Vector3;
70
- /**
71
- * Sets the angular velocity of this rigid-body.
72
- */
73
- setAngvel(velocity: Vector3Object, wakeUp?: boolean): void;
74
- /**
75
- * The linear damping of this rigid-body.
76
- */
77
- linearDamping(): number;
78
- /**
79
- * Sets the linear damping factor applied to this rigid-body.
80
- */
81
- setLinearDamping(factor: number): void;
82
- /**
83
- * The angular damping of this rigid-body.
84
- */
85
- angularDamping(): number;
86
- /**
87
- * Sets the anugular damping factor applied to this rigid-body.
88
- */
89
- setAngularDamping(factor: number): void;
90
- /**
91
- * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
92
- *
93
- * This should be used instead of rigidBody.setRotation to make the dynamic object interacting with this
94
- * kinematic body behave as expected. Internally, Rapier will compute an artificial velocity for this
95
- * rigid-body from its current position and its next kinematic position. This velocity will be used
96
- * to compute forces on dynamic bodies interacting with this body.
97
- */
98
- setNextKinematicRotation(rotation: Quaternion): void;
99
- /**
100
- * If this rigid body is kinematic, sets its future translation after the next timestep integration.
101
- *
102
- * This should be used instead of rigidBody.setTranslation to make the dynamic object interacting with
103
- * this kinematic body behave as expected. Internally, Rapier will compute an artificial velocity
104
- * for this rigid-body from its current position and its next kinematic position. This velocity
105
- * will be used to compute forces on dynamic bodies interacting with this body.
106
- */
107
- setNextKinematicTranslation(translation: Vector3Object): void;
108
- /**
109
- * Resets to zero the user forces (but not torques) applied to this rigid-body.
110
- */
111
- resetForces(wakeUp?: boolean): void;
112
- /**
113
- * Resets to zero the user torques applied to this rigid-body.
114
- */
115
- resetTorques(wakeUp?: boolean): void;
116
- /**
117
- * Locks or unlocks the ability of this rigid-body to rotate.
118
- */
119
- lockRotations(locked: boolean, wakeUp?: boolean): void;
120
- /**
121
- * Locks or unlocks the ability of this rigid-body to translate.
122
- */
123
- lockTranslations(locked: boolean, wakeUp?: boolean): void;
124
- /**
125
- * Locks or unlocks the ability of this rigid-body to rotate along individual coordinate axes.
126
- */
127
- setEnabledRotations(x: boolean, y: boolean, z: boolean, wakeUp?: boolean): void;
128
- /**
129
- * Locks or unlocks the ability of this rigid-body to translate along individual coordinate axes.
130
- */
131
- setEnabledTranslations(x: boolean, y: boolean, z: boolean, wakeUp?: boolean): void;
132
- }
133
- export declare const createRigidBodyApi: (ref: RefGetter<RigidBody>) => RigidBodyApi;
134
- export interface InstancedRigidBodyApi {
135
- at(index: number): RigidBodyApi;
136
- get count(): number;
137
- forEach(callback: (body: RigidBodyApi, index: number, array: RigidBodyApi[]) => void): void;
138
- }
139
- export declare const createInstancedRigidBodiesApi: (bodiesGetter: RefGetter<{
140
- rigidBody: RigidBody;
141
- api: RigidBodyApi;
142
- }[]>) => InstancedRigidBodyApi;
143
- export interface ColliderApi {
144
- /**
145
- * The Collider
146
- * @see https://rapier.rs/javascript3d/classes/Collider.html
147
- */
148
- raw: () => Collider | undefined;
149
- readonly handle: number;
150
- }
151
- export declare const createColliderApi: (ref: RefGetter<Collider>) => {
152
- raw: () => Collider | undefined;
153
- readonly handle: number;
154
- };
155
- export interface WorldApi {
156
- raw(): World;
157
- getCollider(handle: number): Collider | undefined;
158
- getRigidBody(handle: number): RigidBody | undefined;
159
- createRigidBody(desc: RigidBodyDesc): RigidBody;
160
- createCollider(desc: ColliderDesc, parent?: RigidBody): Collider;
161
- removeRigidBody(rigidBody: RigidBody): void;
162
- removeCollider(collider: Collider, wakeUp?: boolean): void;
163
- createImpulseJoint(params: JointData, rigidBodyA: RigidBody, rigidBodyB: RigidBody, wakeUp?: boolean): ImpulseJoint;
164
- removeImpulseJoint(joint: ImpulseJoint, wakeUp?: boolean): void;
165
- forEachCollider(callback: (collider: Collider) => void): void;
166
- setGravity(gravity: Vector3): void;
167
- debugRender(): DebugRenderBuffers;
168
- }
169
- export declare const createWorldApi: (ref: RefGetter<World>) => WorldApi;
170
- export interface JointApi {
171
- /**
172
- * @see https://rapier.rs/javascript3d/classes/ImpulseJoint.html
173
- */
174
- raw: () => ImpulseJoint | undefined;
175
- readonly handle: number;
176
- configureMotorPosition: (targetPos: number, stiffness: number, damping: number) => void;
177
- configureMotorVelocity: (targetVel: number, damping: number) => void;
178
- }
179
- export declare const createJointApi: (ref: RefGetter<ImpulseJoint>) => JointApi;