@react-three/rapier 0.11.2 → 0.12.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 CHANGED
@@ -7,9 +7,19 @@
7
7
  <a href="https://discord.gg/ZZjjNvJ"><img src="https://img.shields.io/discord/740090768164651008?style=for-the-badge&colorA=0099DA&colorB=ffffff&label=discord&logo=discord&logoColor=ffffff" /></a>
8
8
  </p>
9
9
 
10
- <p align="center">⚠️ Under heavy development. All APIs are subject to change. ⚠️</p>
10
+ <p align="center">
11
+ ⚠️ This library is under development. All APIs are subject to change. ⚠️
12
+ <br />
13
+ For contributions, please read the <a href="https://github.com/pmndrs/react-three-rapier/blob/main/packages/react-three-rapier/CONTRIBUTING.md">🪧 Contribution Guide</a>.
14
+ <br/>
15
+ For available APIs, see <a href="https://pmndrs.github.io/react-three-rapier/>">🧩 API Docs</a>
16
+ </p>
17
+
18
+ ---
11
19
 
12
- For contributions, please read the [contributing guide](https://github.com/pmndrs/react-three-rapier/blob/main/packages/react-three-rapier/CONTRIBUTING.md).
20
+ `react-three/rapier` (or `r3/rapier`) is a wrapper library around the Rapier (https://rapier.rs/docs/user_guides/javascript) WASM-based physics engine, designed to slot seamlessly into a `react-three/fiber` pipeline.
21
+
22
+ The goal of this library to is to provide a fast physics engine with minimal friction and small, straight forward API.
13
23
 
14
24
  ## Basic Usage
15
25
 
@@ -27,7 +37,7 @@ const App = () => {
27
37
  <Torus />
28
38
  </RigidBody>
29
39
 
30
- <CuboidCollider position={[0, -2, 0]} args={[20, .5, 20]}>
40
+ <CuboidCollider position={[0, -2, 0]} args={[20, .5, 20]} />
31
41
 
32
42
  <Debug />
33
43
  </Physics>
@@ -39,54 +49,81 @@ const App = () => {
39
49
 
40
50
  ---
41
51
 
52
+ ## 📝 Readme note
53
+ Below follows a guide on core concepts for `react-three/rapier`.
54
+ For full API outline and documentation, see 🧩 [API Docs](https://pmndrs.github.io/react-three-rapier/).
55
+
56
+ ---
57
+
42
58
  ## Readme Topics
43
59
 
44
60
  - [Basic Usage](#basic-usage)
61
+ - [📝 Readme note](#-readme-note)
45
62
  - [Readme Topics](#readme-topics)
46
63
  - [The Physics Component](#the-physics-component)
47
- - [Automatic colliders](#automatic-colliders)
48
- - [Collider Examples](#collider-examples)
64
+ - [The RigidBody Component](#the-rigidbody-component)
65
+ - [Automatic Colliders](#automatic-colliders)
66
+ - [Collider Components](#collider-components)
67
+ - [🖼 Collider Examples](#-collider-examples)
49
68
  - [Instanced Meshes](#instanced-meshes)
50
69
  - [Debug](#debug)
51
70
  - [Collision Events](#collision-events)
52
71
  - [Configuring collision and solver groups](#configuring-collision-and-solver-groups)
53
72
  - [Contact force events](#contact-force-events)
54
73
  - [Sensors](#sensors)
55
- - [Sensors Example](#sensors-example)
74
+ - [🖼 Sensors Example](#-sensors-example)
56
75
  - [Attractors](#attractors)
57
- - [Attractors Example](#attractors-example)
76
+ - [🖼 Attractors Example](#-attractors-example)
58
77
  - [Configuring Time Step Size](#configuring-time-step-size)
59
- - [Manual stepping](#manual-stepping)
60
78
  - [Joints](#joints)
61
- - [Joints Example](#joints-example)
79
+ - [Fixed Joint](#fixed-joint)
80
+ - [Spherical Joint](#spherical-joint)
81
+ - [Revolute Joint](#revolute-joint)
82
+ - [Prismatic Joint](#prismatic-joint)
83
+ - [Joint APIs](#joint-apis)
84
+ - [🖼 Joints Example](#-joints-example)
85
+ - [Advanced hooks usage](#advanced-hooks-usage)
86
+ - [Manual stepping](#manual-stepping)
62
87
 
63
88
  ---
64
89
 
65
90
  ## The Physics Component
66
91
  The `<Physics />` component is the root component of your physics world. It is responsible for creating the physics world and managing the simulation. It relies on lazily initiating `Rapier` and needs to be wrapped in `<Suspense />`.
67
92
 
68
- ```tsx
69
- // The gravity of the physics workd
70
- gravity?: Vector3Array; // default [0, -9.81, 0]
71
-
72
- // Which collider shape to generate for meshes by default
73
- colliders?: RigidBodyAutoCollider; // default "cuboid"
93
+ 🧩 See [PhysicsProps docs](https://pmndrs.github.io/react-three-rapier/interfaces/PhysicsProps.html) for available props.
74
94
 
75
- // The number of physics steps per second
76
- timeStep?: number | "vary"; // default 1/60
95
+ ```tsx
96
+ const Scene = () => {
97
+ return (
98
+ <Canvas>
99
+ <Suspense>
100
+ <Physics
101
+ gravity={[0,1,0]}
102
+ interpolation={false}
103
+ colliders={false}
104
+ >
105
+ ...
106
+ </Physics>
107
+ </Suspense>
108
+ </Canvas>
109
+ );
110
+ }
111
+ ```
77
112
 
78
- // Pause the physic simulation
79
- paused?: boolean; // default false
113
+ ## The RigidBody Component
114
+ The `<RigidBody />` component is used to add a `mesh` into the physics world. You use it by wrapping one or more `meshes` and setting desired props. By default, this will automatically generate `Colliders` based on the shape of the wrapped `meshes` (see [Automatic colliders](#automatic-colliders)).
80
115
 
81
- // Which order to run the physics simulation
82
- updatePriority?: number;
116
+ 🧩 See [RigidBodyProps docs](https://pmndrs.github.io/react-three-rapier/interfaces/RigidBodyProps.html) for available props.
83
117
 
84
- // If the physics updates slower than the monitor refreshes,
85
- // interpolation will smooth out the steps between frames
86
- interpolate?: boolean; // default true
118
+ ```tsx
119
+ const RigidBodyMesh = () => (
120
+ <RigidBody>
121
+ <mesh />
122
+ </RigidBody>
123
+ );
87
124
  ```
88
125
 
89
- ## Automatic colliders
126
+ ## Automatic Colliders
90
127
 
91
128
  RigidBodies generate automatic colliders by default for all meshes that it contains. You can control the default collider by setting the `colliders` prop on a `<RigidBody />`, or change it globally by setting `colliders` on `<Physics />`. Setting `colliders={false}` disables auto-generation.
92
129
 
@@ -127,35 +164,47 @@ const Scene = () => (
127
164
  <RigidBody position={[0, 10, 0]} colliders="ball">
128
165
  <Sphere />
129
166
  </RigidBody>
167
+ </Physics>
168
+ );
169
+ ```
130
170
 
131
- {/* Make a compound shape with two custom BallColliders */}
132
- <RigidBody position={[0, 10, 0]}>
133
- <Sphere />
134
- <BallCollider args={[0.5]} />
135
- <BallCollider args={[0.5]} position={[1, 0, 0]} />
136
- </RigidBody>
137
-
138
- {/* Make a compound shape with two custom BallColliders, an automatic BallCollider,
139
- Two automatic MeshColliders, based on two different shape strategies */}
140
- <RigidBody position={[0, 10, 0]} colliders='ball'>
141
- <MeshCollider type="trimesh">
142
- <mesh ... />
143
- </MeshCollider>
171
+ ## Collider Components
144
172
 
145
- <MeshCollider type="hull">
146
- <mesh ... />
147
- </MeshCollider>
173
+ You can also create `Colliders` by hand and add them to a `RigidBody` to create compound colliders. This is useful for creating more complex shapes, for creating simplified shapes for performance reasons, or for detecting collisions on specific parts of a mesh.
148
174
 
149
- <Sphere />
175
+ 🧩 See [ColliderProps docs](https://pmndrs.github.io/react-three-rapier/interfaces/ColliderProps.html) for available props.
150
176
 
151
- <BallCollider args={[0.5]} />
152
- <BallCollider args={[0.5]} position={[1, 0, 0]} />
153
- </RigidBody>
154
- </Physics>
155
- );
177
+ ```tsx
178
+ const Scene = () => (<>
179
+ {/* Make a compound shape with two custom BallColliders */}
180
+ <RigidBody position={[0, 10, 0]}>
181
+ <Sphere />
182
+ <BallCollider args={[0.5]} />
183
+ <BallCollider args={[0.5]} position={[1, 0, 0]} />
184
+ </RigidBody>
185
+
186
+ {/* Make a compound shape with two custom BallColliders, an automatic BallCollider,
187
+ Two automatic MeshColliders, based on two different shape types */}
188
+ <RigidBody position={[0, 10, 0]} colliders='ball'>
189
+ <MeshCollider type="trimesh">
190
+ <mesh ... />
191
+ </MeshCollider>
192
+
193
+ <MeshCollider type="hull">
194
+ <mesh ... />
195
+ </MeshCollider>
196
+
197
+ <Sphere />
198
+
199
+ <BallCollider args={[0.5]} />
200
+ <BallCollider args={[0.5]} position={[1, 0, 0]} />
201
+ </RigidBody>
202
+ <>)
156
203
  ```
157
204
 
158
- Objects work inside other transformed objects as well. Simulation runs in world space and is transformed to the objects local space, so that things act as you'd expect.
205
+ RigidBodies work inside other transformed objects as well. Simulation runs in world space and is transformed to the objects local space, so that things act as you'd expect.
206
+
207
+ > **Note** It's always best to create RigidBodies where the center of gravity is in the center of the object, otherwise you might get some unexpected behavior during simulation interpolation.
159
208
 
160
209
  ```tsx
161
210
  import { Box } from "@react-three/drei";
@@ -181,7 +230,7 @@ If part of our meshes are invisible and you want to include them in the collider
181
230
  </RigidBody>
182
231
  ```
183
232
 
184
- ### Collider Examples
233
+ ### 🖼 Collider Examples
185
234
  <a href="https://codesandbox.io/s/react-three-rapier-auto-colliders-b4coz1"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-auto-colliders.jpg" width="240" /></a>
186
235
  <a href="https://codesandbox.io/s/react-three-rapier-compound-colliders-ol5ybn"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-compound-shapes.jpg" width="240" /></a>
187
236
 
@@ -191,6 +240,8 @@ Instanced meshes can also be used and have automatic colliders generated from th
191
240
 
192
241
  By wrapping the `InstancedMesh` in `<InstancedRigidBodies />`, each instance will be attached to an individual `RigidBody`.
193
242
 
243
+ 🧩 See [InstancedRigidBodiesProps docs](https://pmndrs.github.io/react-three-rapier/interfaces/InstancedRigidBodiesProps.html) for available props.
244
+
194
245
  ```tsx
195
246
  import { InstancedRigidBodies } from "@react-three/rapier";
196
247
 
@@ -200,11 +251,15 @@ const Scene = () => {
200
251
  const instancedApi = useRef<InstancedRigidBodyApi>(null);
201
252
 
202
253
  useEffect(() => {
254
+ if (!instancedApi.current) {
255
+ return
256
+ }
257
+
203
258
  // You can access individual instanced by their index
204
- instancedApi.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
259
+ instancedApi.current.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
205
260
 
206
261
  // Or update all instances as if they were in an array
207
- instancedApi.forEach((api) => {
262
+ instancedApi.current.forEach((api) => {
208
263
  api.applyImpulse({ x: 0, y: 10, z: 0 });
209
264
  });
210
265
  }, []);
@@ -272,6 +327,8 @@ const Scene = () => {
272
327
 
273
328
  You can subscribe to collision and state events on a RigidBody:
274
329
 
330
+ 🧩 See [onCollisionEnter / onCollisionExit docs](https://pmndrs.github.io/react-three-rapier/interfaces/RigidBodyProps.html#onCollisionEnter) for more information.
331
+
275
332
  ```tsx
276
333
  const RigidBottle = () => {
277
334
  const [isAsleep, setIsAsleep] = useState(false);
@@ -379,7 +436,7 @@ Contact force events are triggered on `<RigidBody>` and any collider components
379
436
  console.log(`The total force generated was: ${payload.totalForce}`);
380
437
  }}>
381
438
  <Sphere>
382
- <meshPhysicalMaterial color={'grey'}>
439
+ <meshPhysicalMaterial color={'grey'} />
383
440
  </Sphere>
384
441
  </RigidBody>
385
442
  ```
@@ -417,6 +474,10 @@ A Collider can be set to be a sensor, which means that it will not generate any
417
474
 
418
475
  To detect when a collider enters or leaves another collider, you can use the `onIntersectionEnter` and `onIntersectionExit` events on the collider.
419
476
 
477
+ 🧩 See [onIntersectionEnter / onIntersectionExit docs](https://pmndrs.github.io/react-three-rapier/interfaces/RigidBodyProps.html#onIntersectionEnter) for more information.
478
+
479
+ ```tsx
480
+
420
481
  ```tsx
421
482
  <RigidBody>
422
483
  <GoalPosts />
@@ -429,7 +490,7 @@ To detect when a collider enters or leaves another collider, you can use the `on
429
490
  </RigidBody>
430
491
  ```
431
492
 
432
- ### Sensors Example
493
+ ### 🖼 Sensors Example
433
494
  <a href="https://codesandbox.io/s/react-three-rapier-sensors-byjmsk"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-sensors.jpg" width="240" /></a>
434
495
 
435
496
  ## Attractors
@@ -439,6 +500,8 @@ Setting the `strength` to a negative value will cause the `RigidBody` to be _pus
439
500
 
440
501
  The force applied to rigid-bodies within range is calculated differently depending on the `type`.
441
502
 
503
+ 🧩 See [Attractor docs](https://pmndrs.github.io/react-three-rapier/interfaces/AttractorProps.html) for all available props.
504
+
442
505
  ```tsx
443
506
  // Standard attractor
444
507
  <Attractor range={10} strength={5} type="linear" position={[5, -5, 0]} />
@@ -466,7 +529,7 @@ Gravity types:
466
529
  - `mass2` is the mass of the rigid-body at the time of calculation. Note that rigid-bodies with colliders will use the mass provided to the collider. This is not a value you can control from the attractor, only from wherever you're creating rigid-body components in the scene.
467
530
  - `distance` is the distance between the attractor and rigid-body at the time of calculation
468
531
 
469
- ### Attractors Example
532
+ ### 🖼 Attractors Example
470
533
  <a href="https://codesandbox.io/s/react-three-rapier-attractors-oyj640"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-attractors.jpg" width="240" /></a>
471
534
 
472
535
  ## Configuring Time Step Size
@@ -485,19 +548,182 @@ The `timeStep` prop may also be set to `"vary"`, which will cause the simulation
485
548
 
486
549
  > **Note** This is useful for games that run at variable frame rates, but may cause instability in the simulation. It also prevents the physics simulation from being fully deterministic. Please use with care!
487
550
 
488
- ## Manual stepping
551
+ ## Joints
552
+ Joints can be made between two `RigidBodies` to provide a way to restrict a motion of a body in relation to another.
553
+ > Read more about joints in Rapier: https://rapier.rs/docs/user_guides/javascript/joints
554
+
555
+ Joints are available in `r3/rapier` as hooks.
489
556
 
490
- You can also manually step the physics simulation by calling the `step` method from the `useRapier` hook.
557
+ There are 4 different joint types available:
558
+ - Fixed (two bodies are fixed together)
559
+ - Spherical (two bodies are connected by a ball and socket, for things like arms or chains)
560
+ - Revolute (two bodies are connected by a hinge, for things like doors or wheels)
561
+ - Prismatic (two bodies are connected by a sliding joint, for things like pistons or sliders)
562
+
563
+ ### Fixed Joint
564
+ 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
+
566
+ 🧩 See [FixedJoint docs](https://pmndrs.github.io/react-three-rapier/functions/useFixedJoint.html) for available options.
491
567
 
492
568
  ```tsx
493
- const { step } = useRapier();
569
+ const JointedThing = () => {
570
+ const joint = useFixedJoint(
571
+ bodyA,
572
+ bodyB,
573
+ [
574
+ [0, 0, 0], // Position of the joint in bodyA's local space
575
+ [0, 0, 0, 1], // Orientation of the joint in bodyA's local space
576
+ [0, 0, 0], // Position of the joint in bodyB's local space
577
+ [0, 0, 0, 1], // Orientation of the joint in bodyB's local space
578
+ ]);
494
579
 
495
- step(1 / 60);
580
+ return (
581
+ <group>
582
+ <RigidBody ref={bodyA}>
583
+ <mesh />
584
+ </RigidBody>
585
+ <RigidBody ref={bodyB}>
586
+ <mesh />
587
+ </RigidBody>
588
+ </group>
589
+ );
590
+ }
496
591
  ```
497
592
 
498
- ## Joints
593
+ ### Spherical Joint
594
+ The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative translational motion at this points).
499
595
 
500
- - WIP
596
+ 🧩 See [SphericalJoint docs](https://pmndrs.github.io/react-three-rapier/functions/useSphericalJoint.html) for available options.
501
597
 
502
- ### Joints Example
503
- <a href="https://codesandbox.io/s/react-three-rapier-joints-mhhbd4"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-joints.jpg" width="240" /></a>
598
+ ```tsx
599
+
600
+ ```tsx
601
+ const JointedThing = () => {
602
+ const joint = useSphericalJoint(
603
+ bodyA,
604
+ bodyB,
605
+ [
606
+ [0, 0, 0], // Position of the joint in bodyA's local space
607
+ [0, 0, 0], // Position of the joint in bodyB's local space
608
+ ]);
609
+
610
+ return (
611
+ <group>
612
+ <RigidBody ref={bodyA}>
613
+ <mesh />
614
+ </RigidBody>
615
+ <RigidBody ref={bodyB}>
616
+ <mesh />
617
+ </RigidBody>
618
+ </group>
619
+ );
620
+ }
621
+ ```
622
+
623
+ ### Revolute Joint
624
+ The revolute joint prevents any relative movement between two rigid-bodies, except for relative rotations along one axis. This is typically used to simulate wheels, fans, etc.
625
+
626
+ 🧩 See [RevoluteJoint docs](https://pmndrs.github.io/react-three-rapier/functions/useRevoluteJoint.html) for available options.
627
+
628
+ ```tsx
629
+ const JointedThing = () => {
630
+ const joint = useRevoluteJoint(
631
+ bodyA,
632
+ bodyB,
633
+ [
634
+ [0, 0, 0], // Position of the joint in bodyA's local space
635
+ [0, 0, 0], // Position of the joint in bodyB's local space
636
+ [0, 0, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
637
+ ]);
638
+
639
+ return (
640
+ <group>
641
+ <RigidBody ref={bodyA}>
642
+ <mesh />
643
+ </RigidBody>
644
+ <RigidBody ref={bodyB}>
645
+ <mesh />
646
+ </RigidBody>
647
+ </group>
648
+ );
649
+ }
650
+ ```
651
+
652
+ ### Prismatic Joint
653
+ The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
654
+
655
+ 🧩 See [PrismaticJoint docs](https://pmndrs.github.io/react-three-rapier/functions/usePrismaticJoint.html) for available options.
656
+
657
+ ```tsx
658
+
659
+ ```tsx
660
+ const JointedThing = () => {
661
+ const joint = usePrismaticJoint(
662
+ bodyA,
663
+ bodyB,
664
+ [
665
+ [0, 0, 0], // Position of the joint in bodyA's local space
666
+ [0, 0, 0], // Position of the joint in bodyB's local space
667
+ [0, 0, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
668
+ ]);
669
+
670
+ return (
671
+ <group>
672
+ <RigidBody ref={bodyA}>
673
+ <mesh />
674
+ </RigidBody>
675
+ <RigidBody ref={bodyB}>
676
+ <mesh />
677
+ </RigidBody>
678
+ </group>
679
+ );
680
+ }
681
+ ```
682
+
683
+ ### Joint APIs
684
+ Joints can be controlled imperatively similarily to how `RigidBody` components can be controlled.
685
+
686
+ 🧩 See [Joint API docs](https://pmndrs.github.io/react-three-rapier/interfaces/JointApi.html) for more information.
687
+
688
+ ```tsx
689
+ const JointedThing = () => {
690
+ const joint = useSphericalJoint(...)
691
+
692
+ useEffect(() => {
693
+ joint.configureMotorVelocity(1, 0)
694
+
695
+ // Disable contacts between the two joint bodies
696
+ joint.raw().setContactsEnabled(false)
697
+ }, [])
698
+
699
+ return ...
700
+ }
701
+ ```
702
+
703
+
704
+ ### 🖼 Joints Example
705
+ <a href="https://codesandbox.io/s/react-three-rapier-joints-mhhbd4"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-joints.jpg" width="240" /></a>
706
+
707
+ ## Advanced hooks usage
708
+
709
+ Advanced users might need granular access to the physics loop and direct access to the `world` instance. This can be done by using the following hooks:
710
+
711
+ - `useRapier`
712
+ Gives you access to the `world`, direct access to `rapier`, and more.
713
+ 🧩 See [useRapier docs](https://pmndrs.github.io/react-three-rapier/interfaces/RapierContext.html) for more information.
714
+ - `useBeforePhysicsStep`
715
+ Allows you to run code before the physics simulation is stepped.
716
+ 🧩 See [useBeforePhysicsStep docs](https://pmndrs.github.io/react-three-rapier/functions/useBeforePhysicsStep.html) for more information.
717
+ - `useAfterPhysicsStep`
718
+ Allows you to run code after the physics simulation is stepped.
719
+ 🧩 See [useAfterPhysicsStep docs](https://pmndrs.github.io/react-three-rapier/functions/useAfterPhysicsStep.html) for more information.
720
+
721
+ ### Manual stepping
722
+
723
+ You can manually step the physics simulation by calling the `step` method from the `useRapier` hook.
724
+
725
+ ```tsx
726
+ const { step } = useRapier();
727
+
728
+ step(1 / 60);
729
+ ```