@react-three/rapier 0.11.1 → 0.11.3
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.
@@ -72,6 +72,7 @@ export declare type UseBodyOptions = Omit<UseRigidBodyOptions, "shape">;
|
|
72
72
|
export declare type RigidBodyTypeString = "fixed" | "dynamic" | "kinematicPosition" | "kinematicVelocity";
|
73
73
|
export declare type ColliderShape = "cuboid" | "trimesh" | "ball" | "capsule" | "convexHull" | "heightfield" | "polyline" | "roundCuboid" | "cylinder" | "roundCylinder" | "cone" | "roundCone" | "convexMesh" | "roundConvexHull" | "roundConvexMesh";
|
74
74
|
export declare type Vector3Array = [x: number, y: number, z: number];
|
75
|
+
export declare type Vector4Array = [x: number, y: number, z: number, w: number];
|
75
76
|
export declare type Boolean3Array = [x: boolean, y: boolean, z: boolean];
|
76
77
|
export interface UseColliderOptions<ColliderArgs extends Array<unknown>> {
|
77
78
|
/**
|
@@ -324,20 +325,22 @@ export declare type SphericalJointParams = [
|
|
324
325
|
];
|
325
326
|
export declare type FixedJointParams = [
|
326
327
|
body1Anchor: Vector3Array,
|
327
|
-
body1LocalFrame:
|
328
|
+
body1LocalFrame: Vector4Array,
|
328
329
|
body2Anchor: Vector3Array,
|
329
|
-
body2LocalFrame:
|
330
|
+
body2LocalFrame: Vector4Array
|
330
331
|
];
|
331
332
|
export declare type PrismaticJointParams = [
|
332
333
|
body1Anchor: Vector3Array,
|
333
334
|
body1LocalFrame: Vector3Array,
|
334
335
|
body2Anchor: Vector3Array,
|
335
|
-
body2LocalFrame: Vector3Array
|
336
|
+
body2LocalFrame: Vector3Array,
|
337
|
+
limits?: [min: number, max: number]
|
336
338
|
];
|
337
339
|
export declare type RevoluteJointParams = [
|
338
340
|
body1Anchor: Vector3Array,
|
339
341
|
body2Anchor: Vector3Array,
|
340
|
-
axis: Vector3Array
|
342
|
+
axis: Vector3Array,
|
343
|
+
limits?: [min: number, max: number]
|
341
344
|
];
|
342
345
|
export declare type RigidBodyApiRef = MutableRefObject<undefined | null | RigidBodyApi>;
|
343
346
|
export interface UseImpulseJoint<P> {
|
@@ -2,6 +2,7 @@ import { Quaternion as RapierQuaternion, Vector3 as RapierVector3 } from "@dimfo
|
|
2
2
|
import { Euler, Quaternion, Vector3 } from "three";
|
3
3
|
import { RigidBodyTypeString, Vector3Array } from "./types";
|
4
4
|
export declare const vectorArrayToVector3: (arr: Vector3Array) => Vector3;
|
5
|
+
export declare const tupleToObject: <T extends readonly any[], K extends readonly string[]>(tuple: T, keys: K) => { [Key in K[number]]: T[number]; };
|
5
6
|
export declare const vector3ToQuaternion: (v: Vector3) => Quaternion;
|
6
7
|
export declare const rapierVector3ToVector3: ({ x, y, z }: RapierVector3) => Vector3;
|
7
8
|
export declare const rapierQuaternionToQuaternion: ({ x, y, z, w }: RapierQuaternion) => Quaternion;
|
@@ -85,6 +85,12 @@ const vectorArrayToVector3 = arr => {
|
|
85
85
|
const [x, y, z] = arr;
|
86
86
|
return new three.Vector3(x, y, z);
|
87
87
|
};
|
88
|
+
const tupleToObject = (tuple, keys) => {
|
89
|
+
return keys.reduce((obj, key, i) => {
|
90
|
+
obj[key] = tuple[i];
|
91
|
+
return obj;
|
92
|
+
}, {});
|
93
|
+
};
|
88
94
|
const rapierVector3ToVector3 = ({
|
89
95
|
x,
|
90
96
|
y,
|
@@ -590,10 +596,12 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
590
596
|
};
|
591
597
|
|
592
598
|
const rigidBodyDescFromOptions = options => {
|
599
|
+
var _options$canSleep;
|
600
|
+
|
593
601
|
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
594
602
|
const desc = new rapier3dCompat.RigidBodyDesc(type); // Apply immutable options
|
595
603
|
|
596
|
-
desc.canSleep = (options === null || options === void 0 ? void 0 : options.canSleep)
|
604
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
597
605
|
return desc;
|
598
606
|
};
|
599
607
|
const createRigidBodyState = ({
|
@@ -858,11 +866,7 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
|
|
858
866
|
const {
|
859
867
|
rapier
|
860
868
|
} = useRapier();
|
861
|
-
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor),
|
862
|
-
w: 1
|
863
|
-
}), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
|
864
|
-
w: 1
|
865
|
-
})));
|
869
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
866
870
|
};
|
867
871
|
/**
|
868
872
|
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
@@ -883,11 +887,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
883
887
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
884
888
|
*/
|
885
889
|
|
886
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
890
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
887
891
|
const {
|
888
892
|
rapier
|
889
893
|
} = useRapier();
|
890
|
-
|
894
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
895
|
+
|
896
|
+
if (limits) {
|
897
|
+
params.limitsEnabled = true;
|
898
|
+
params.limits = limits;
|
899
|
+
}
|
900
|
+
|
901
|
+
return useImpulseJoint(body1, body2, params);
|
891
902
|
};
|
892
903
|
/**
|
893
904
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
@@ -895,11 +906,18 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
895
906
|
* local tangent axis can be specified for each rigid-body.
|
896
907
|
*/
|
897
908
|
|
898
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
909
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
899
910
|
const {
|
900
911
|
rapier
|
901
912
|
} = useRapier();
|
902
|
-
|
913
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
914
|
+
|
915
|
+
if (limits) {
|
916
|
+
params.limitsEnabled = true;
|
917
|
+
params.limits = limits;
|
918
|
+
}
|
919
|
+
|
920
|
+
return useImpulseJoint(body1, body2, params);
|
903
921
|
};
|
904
922
|
|
905
923
|
const calcForceByType = {
|
@@ -85,6 +85,12 @@ const vectorArrayToVector3 = arr => {
|
|
85
85
|
const [x, y, z] = arr;
|
86
86
|
return new three.Vector3(x, y, z);
|
87
87
|
};
|
88
|
+
const tupleToObject = (tuple, keys) => {
|
89
|
+
return keys.reduce((obj, key, i) => {
|
90
|
+
obj[key] = tuple[i];
|
91
|
+
return obj;
|
92
|
+
}, {});
|
93
|
+
};
|
88
94
|
const rapierVector3ToVector3 = ({
|
89
95
|
x,
|
90
96
|
y,
|
@@ -590,10 +596,12 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
590
596
|
};
|
591
597
|
|
592
598
|
const rigidBodyDescFromOptions = options => {
|
599
|
+
var _options$canSleep;
|
600
|
+
|
593
601
|
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
594
602
|
const desc = new rapier3dCompat.RigidBodyDesc(type); // Apply immutable options
|
595
603
|
|
596
|
-
desc.canSleep = (options === null || options === void 0 ? void 0 : options.canSleep)
|
604
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
597
605
|
return desc;
|
598
606
|
};
|
599
607
|
const createRigidBodyState = ({
|
@@ -858,11 +866,7 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
|
|
858
866
|
const {
|
859
867
|
rapier
|
860
868
|
} = useRapier();
|
861
|
-
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor),
|
862
|
-
w: 1
|
863
|
-
}), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
|
864
|
-
w: 1
|
865
|
-
})));
|
869
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
866
870
|
};
|
867
871
|
/**
|
868
872
|
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
@@ -883,11 +887,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
883
887
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
884
888
|
*/
|
885
889
|
|
886
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
890
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
887
891
|
const {
|
888
892
|
rapier
|
889
893
|
} = useRapier();
|
890
|
-
|
894
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
895
|
+
|
896
|
+
if (limits) {
|
897
|
+
params.limitsEnabled = true;
|
898
|
+
params.limits = limits;
|
899
|
+
}
|
900
|
+
|
901
|
+
return useImpulseJoint(body1, body2, params);
|
891
902
|
};
|
892
903
|
/**
|
893
904
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
@@ -895,11 +906,18 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
895
906
|
* local tangent axis can be specified for each rigid-body.
|
896
907
|
*/
|
897
908
|
|
898
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
909
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
899
910
|
const {
|
900
911
|
rapier
|
901
912
|
} = useRapier();
|
902
|
-
|
913
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
914
|
+
|
915
|
+
if (limits) {
|
916
|
+
params.limitsEnabled = true;
|
917
|
+
params.limits = limits;
|
918
|
+
}
|
919
|
+
|
920
|
+
return useImpulseJoint(body1, body2, params);
|
903
921
|
};
|
904
922
|
|
905
923
|
const calcForceByType = {
|
@@ -60,6 +60,12 @@ const vectorArrayToVector3 = arr => {
|
|
60
60
|
const [x, y, z] = arr;
|
61
61
|
return new Vector3(x, y, z);
|
62
62
|
};
|
63
|
+
const tupleToObject = (tuple, keys) => {
|
64
|
+
return keys.reduce((obj, key, i) => {
|
65
|
+
obj[key] = tuple[i];
|
66
|
+
return obj;
|
67
|
+
}, {});
|
68
|
+
};
|
63
69
|
const rapierVector3ToVector3 = ({
|
64
70
|
x,
|
65
71
|
y,
|
@@ -565,10 +571,12 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
565
571
|
};
|
566
572
|
|
567
573
|
const rigidBodyDescFromOptions = options => {
|
574
|
+
var _options$canSleep;
|
575
|
+
|
568
576
|
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
569
577
|
const desc = new RigidBodyDesc(type); // Apply immutable options
|
570
578
|
|
571
|
-
desc.canSleep = (options === null || options === void 0 ? void 0 : options.canSleep)
|
579
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
572
580
|
return desc;
|
573
581
|
};
|
574
582
|
const createRigidBodyState = ({
|
@@ -833,11 +841,7 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
|
|
833
841
|
const {
|
834
842
|
rapier
|
835
843
|
} = useRapier();
|
836
|
-
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor),
|
837
|
-
w: 1
|
838
|
-
}), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
|
839
|
-
w: 1
|
840
|
-
})));
|
844
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
841
845
|
};
|
842
846
|
/**
|
843
847
|
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
@@ -858,11 +862,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
858
862
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
859
863
|
*/
|
860
864
|
|
861
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
865
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
862
866
|
const {
|
863
867
|
rapier
|
864
868
|
} = useRapier();
|
865
|
-
|
869
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
870
|
+
|
871
|
+
if (limits) {
|
872
|
+
params.limitsEnabled = true;
|
873
|
+
params.limits = limits;
|
874
|
+
}
|
875
|
+
|
876
|
+
return useImpulseJoint(body1, body2, params);
|
866
877
|
};
|
867
878
|
/**
|
868
879
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
@@ -870,11 +881,18 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
870
881
|
* local tangent axis can be specified for each rigid-body.
|
871
882
|
*/
|
872
883
|
|
873
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
884
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
874
885
|
const {
|
875
886
|
rapier
|
876
887
|
} = useRapier();
|
877
|
-
|
888
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
889
|
+
|
890
|
+
if (limits) {
|
891
|
+
params.limitsEnabled = true;
|
892
|
+
params.limits = limits;
|
893
|
+
}
|
894
|
+
|
895
|
+
return useImpulseJoint(body1, body2, params);
|
878
896
|
};
|
879
897
|
|
880
898
|
const calcForceByType = {
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -7,9 +7,17 @@
|
|
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.
|
10
|
+
<p align="center">⚠️ Under heavy development. All APIs are subject to change. ⚠️
|
11
|
+
<br />
|
12
|
+
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>.
|
13
|
+
</p>
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
`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.
|
18
|
+
|
19
|
+
The goal of this library to is to provide a fast physics engine with minimal friction and small, straight forward API.
|
11
20
|
|
12
|
-
For contributions, please read the [contributing guide](https://github.com/pmndrs/react-three-rapier/blob/main/packages/react-three-rapier/CONTRIBUTING.md).
|
13
21
|
|
14
22
|
## Basic Usage
|
15
23
|
|
@@ -27,7 +35,7 @@ const App = () => {
|
|
27
35
|
<Torus />
|
28
36
|
</RigidBody>
|
29
37
|
|
30
|
-
<CuboidCollider position={[0, -2, 0]} args={[20, .5, 20]}
|
38
|
+
<CuboidCollider position={[0, -2, 0]} args={[20, .5, 20]} />
|
31
39
|
|
32
40
|
<Debug />
|
33
41
|
</Physics>
|
@@ -58,6 +66,11 @@ const App = () => {
|
|
58
66
|
- [Configuring Time Step Size](#configuring-time-step-size)
|
59
67
|
- [Manual stepping](#manual-stepping)
|
60
68
|
- [Joints](#joints)
|
69
|
+
- [Fixed Joint](#fixed-joint)
|
70
|
+
- [Spherical Joint](#spherical-joint)
|
71
|
+
- [Revolute Joint](#revolute-joint)
|
72
|
+
- [Prismatic Joint](#prismatic-joint)
|
73
|
+
- [Joint APIs](#joint-apis)
|
61
74
|
- [Joints Example](#joints-example)
|
62
75
|
|
63
76
|
---
|
@@ -200,11 +213,15 @@ const Scene = () => {
|
|
200
213
|
const instancedApi = useRef<InstancedRigidBodyApi>(null);
|
201
214
|
|
202
215
|
useEffect(() => {
|
216
|
+
if (!instancedApi.current) {
|
217
|
+
return
|
218
|
+
}
|
219
|
+
|
203
220
|
// You can access individual instanced by their index
|
204
|
-
instancedApi.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
|
221
|
+
instancedApi.current.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
|
205
222
|
|
206
223
|
// Or update all instances as if they were in an array
|
207
|
-
instancedApi.forEach((api) => {
|
224
|
+
instancedApi.current.forEach((api) => {
|
208
225
|
api.applyImpulse({ x: 0, y: 10, z: 0 });
|
209
226
|
});
|
210
227
|
}, []);
|
@@ -379,7 +396,7 @@ Contact force events are triggered on `<RigidBody>` and any collider components
|
|
379
396
|
console.log(`The total force generated was: ${payload.totalForce}`);
|
380
397
|
}}>
|
381
398
|
<Sphere>
|
382
|
-
<meshPhysicalMaterial color={'grey'}
|
399
|
+
<meshPhysicalMaterial color={'grey'} />
|
383
400
|
</Sphere>
|
384
401
|
</RigidBody>
|
385
402
|
```
|
@@ -496,8 +513,143 @@ step(1 / 60);
|
|
496
513
|
```
|
497
514
|
|
498
515
|
## Joints
|
516
|
+
Joints can be made between two `RigidBodies` to provide a way to restrict a motion of a body in relation to another.
|
517
|
+
> Read more about joints in Rapier: https://rapier.rs/docs/user_guides/javascript/joints
|
518
|
+
|
519
|
+
Joints are available in `r3/rapier` as hooks.
|
520
|
+
|
521
|
+
There are 4 different joint types available:
|
522
|
+
- Fixed (two bodies are fixed together)
|
523
|
+
- Spherical (two bodies are connected by a ball and socket, for things like arms or chains)
|
524
|
+
- Revolute (two bodies are connected by a hinge, for things like doors or wheels)
|
525
|
+
- Prismatic (two bodies are connected by a sliding joint, for things like pistons or sliders)
|
526
|
+
|
527
|
+
### Fixed Joint
|
528
|
+
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.
|
529
|
+
|
530
|
+
```tsx
|
531
|
+
const JointedThing = () => {
|
532
|
+
const joint = useFixedJoint(
|
533
|
+
bodyA,
|
534
|
+
bodyB,
|
535
|
+
[
|
536
|
+
[0, 0, 0], // Position of the joint in bodyA's local space
|
537
|
+
[0, 0, 0, 1], // Orientation of the joint in bodyA's local space
|
538
|
+
[0, 0, 0], // Position of the joint in bodyB's local space
|
539
|
+
[0, 0, 0, 1], // Orientation of the joint in bodyB's local space
|
540
|
+
]);
|
541
|
+
|
542
|
+
return (
|
543
|
+
<group>
|
544
|
+
<RigidBody ref={bodyA}>
|
545
|
+
<mesh />
|
546
|
+
</RigidBody>
|
547
|
+
<RigidBody ref={bodyB}>
|
548
|
+
<mesh />
|
549
|
+
</RigidBody>
|
550
|
+
</group>
|
551
|
+
);
|
552
|
+
}
|
553
|
+
```
|
554
|
+
|
555
|
+
### Spherical Joint
|
556
|
+
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).
|
557
|
+
|
558
|
+
```tsx
|
559
|
+
const JointedThing = () => {
|
560
|
+
const joint = useSphericalJoint(
|
561
|
+
bodyA,
|
562
|
+
bodyB,
|
563
|
+
[
|
564
|
+
[0, 0, 0], // Position of the joint in bodyA's local space
|
565
|
+
[0, 0, 0], // Position of the joint in bodyB's local space
|
566
|
+
]);
|
567
|
+
|
568
|
+
return (
|
569
|
+
<group>
|
570
|
+
<RigidBody ref={bodyA}>
|
571
|
+
<mesh />
|
572
|
+
</RigidBody>
|
573
|
+
<RigidBody ref={bodyB}>
|
574
|
+
<mesh />
|
575
|
+
</RigidBody>
|
576
|
+
</group>
|
577
|
+
);
|
578
|
+
}
|
579
|
+
```
|
580
|
+
|
581
|
+
### Revolute Joint
|
582
|
+
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.
|
583
|
+
|
584
|
+
```tsx
|
585
|
+
const JointedThing = () => {
|
586
|
+
const joint = useRevoluteJoint(
|
587
|
+
bodyA,
|
588
|
+
bodyB,
|
589
|
+
[
|
590
|
+
[0, 0, 0], // Position of the joint in bodyA's local space
|
591
|
+
[0, 0, 0], // Position of the joint in bodyB's local space
|
592
|
+
[0, 0, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
|
593
|
+
]);
|
594
|
+
|
595
|
+
return (
|
596
|
+
<group>
|
597
|
+
<RigidBody ref={bodyA}>
|
598
|
+
<mesh />
|
599
|
+
</RigidBody>
|
600
|
+
<RigidBody ref={bodyB}>
|
601
|
+
<mesh />
|
602
|
+
</RigidBody>
|
603
|
+
</group>
|
604
|
+
);
|
605
|
+
}
|
606
|
+
```
|
607
|
+
|
608
|
+
### Prismatic Joint
|
609
|
+
The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
610
|
+
|
611
|
+
```tsx
|
612
|
+
const JointedThing = () => {
|
613
|
+
const joint = usePrismaticJoint(
|
614
|
+
bodyA,
|
615
|
+
bodyB,
|
616
|
+
[
|
617
|
+
[0, 0, 0], // Position of the joint in bodyA's local space
|
618
|
+
[0, 0, 0], // Position of the joint in bodyB's local space
|
619
|
+
[0, 0, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to.
|
620
|
+
]);
|
621
|
+
|
622
|
+
return (
|
623
|
+
<group>
|
624
|
+
<RigidBody ref={bodyA}>
|
625
|
+
<mesh />
|
626
|
+
</RigidBody>
|
627
|
+
<RigidBody ref={bodyB}>
|
628
|
+
<mesh />
|
629
|
+
</RigidBody>
|
630
|
+
</group>
|
631
|
+
);
|
632
|
+
}
|
633
|
+
```
|
634
|
+
|
635
|
+
### Joint APIs
|
636
|
+
Joints can be controlled imperatively similarily to how `RigidBody` components can be controlled.
|
637
|
+
|
638
|
+
```tsx
|
639
|
+
const JointedThing = () => {
|
640
|
+
const joint = useSphericalJoint(...)
|
641
|
+
|
642
|
+
useEffect(() => {
|
643
|
+
joint.configureMotorVelocity(1, 0)
|
644
|
+
|
645
|
+
// Disable contacts between the two joint bodies
|
646
|
+
joint.raw().setContactsEnabled(false)
|
647
|
+
}, [])
|
648
|
+
|
649
|
+
return ...
|
650
|
+
}
|
651
|
+
```
|
499
652
|
|
500
|
-
- WIP
|
501
653
|
|
502
654
|
### Joints Example
|
503
|
-
<a href="https://codesandbox.io/s/react-three-rapier-
|
655
|
+
<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>
|