@react-three/rapier 0.11.0 → 0.11.2
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/declarations/src/Physics.d.ts +1 -0
- package/dist/declarations/src/types.d.ts +4 -2
- package/dist/declarations/src/utils.d.ts +1 -0
- package/dist/react-three-rapier.cjs.dev.js +45 -11
- package/dist/react-three-rapier.cjs.prod.js +45 -11
- package/dist/react-three-rapier.esm.js +46 -12
- package/package.json +6 -6
- package/readme.md +50 -5
@@ -109,6 +109,7 @@ interface RapierWorldProps {
|
|
109
109
|
/**
|
110
110
|
* The update priority at which the physics simulation should run.
|
111
111
|
*
|
112
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop
|
112
113
|
* @defaultValue undefined
|
113
114
|
*/
|
114
115
|
updatePriority?: number;
|
@@ -332,12 +332,14 @@ export declare type PrismaticJointParams = [
|
|
332
332
|
body1Anchor: Vector3Array,
|
333
333
|
body1LocalFrame: Vector3Array,
|
334
334
|
body2Anchor: Vector3Array,
|
335
|
-
body2LocalFrame: Vector3Array
|
335
|
+
body2LocalFrame: Vector3Array,
|
336
|
+
limits?: [min: number, max: number]
|
336
337
|
];
|
337
338
|
export declare type RevoluteJointParams = [
|
338
339
|
body1Anchor: Vector3Array,
|
339
340
|
body2Anchor: Vector3Array,
|
340
|
-
axis: Vector3Array
|
341
|
+
axis: Vector3Array,
|
342
|
+
limits?: [min: number, max: number]
|
341
343
|
];
|
342
344
|
export declare type RigidBodyApiRef = MutableRefObject<undefined | null | RigidBodyApi>;
|
343
345
|
export interface UseImpulseJoint<P> {
|
@@ -8,3 +8,4 @@ export declare const rapierQuaternionToQuaternion: ({ x, y, z, w }: RapierQuater
|
|
8
8
|
export declare const rigidBodyTypeFromString: (type: RigidBodyTypeString) => number;
|
9
9
|
export declare const scaleVertices: (vertices: ArrayLike<number>, scale: Vector3) => number[];
|
10
10
|
export declare const vectorToTuple: (v: Vector3 | Quaternion | any[] | undefined | number | Euler) => any[];
|
11
|
+
export declare function useConst<T>(initialValue: T | (() => T)): T;
|
@@ -131,6 +131,17 @@ const vectorToTuple = v => {
|
|
131
131
|
|
132
132
|
return [v];
|
133
133
|
};
|
134
|
+
function useConst(initialValue) {
|
135
|
+
const ref = React.useRef();
|
136
|
+
|
137
|
+
if (ref.current === undefined) {
|
138
|
+
ref.current = {
|
139
|
+
value: typeof initialValue === "function" ? initialValue() : initialValue
|
140
|
+
};
|
141
|
+
}
|
142
|
+
|
143
|
+
return ref.current.value;
|
144
|
+
}
|
134
145
|
|
135
146
|
const createRigidBodyApi = ref => {
|
136
147
|
return {
|
@@ -579,8 +590,12 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
579
590
|
};
|
580
591
|
|
581
592
|
const rigidBodyDescFromOptions = options => {
|
593
|
+
var _options$canSleep;
|
594
|
+
|
582
595
|
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
583
|
-
const desc = new rapier3dCompat.RigidBodyDesc(type);
|
596
|
+
const desc = new rapier3dCompat.RigidBodyDesc(type); // Apply immutable options
|
597
|
+
|
598
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
584
599
|
return desc;
|
585
600
|
};
|
586
601
|
const createRigidBodyState = ({
|
@@ -646,6 +661,11 @@ const mutableRigidBodyOptions = {
|
|
646
661
|
userData: (rb, value) => {
|
647
662
|
rb.userData = value;
|
648
663
|
},
|
664
|
+
|
665
|
+
type(rb, value) {
|
666
|
+
rb.setBodyType(rigidBodyTypeFromString(value));
|
667
|
+
},
|
668
|
+
|
649
669
|
position: () => {},
|
650
670
|
rotation: () => {},
|
651
671
|
quaternion: () => {},
|
@@ -865,11 +885,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
865
885
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
866
886
|
*/
|
867
887
|
|
868
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
888
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
869
889
|
const {
|
870
890
|
rapier
|
871
891
|
} = useRapier();
|
872
|
-
|
892
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
893
|
+
|
894
|
+
if (limits) {
|
895
|
+
params.limitsEnabled = true;
|
896
|
+
params.limits = limits;
|
897
|
+
}
|
898
|
+
|
899
|
+
return useImpulseJoint(body1, body2, params);
|
873
900
|
};
|
874
901
|
/**
|
875
902
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
@@ -877,11 +904,18 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
877
904
|
* local tangent axis can be specified for each rigid-body.
|
878
905
|
*/
|
879
906
|
|
880
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
907
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
881
908
|
const {
|
882
909
|
rapier
|
883
910
|
} = useRapier();
|
884
|
-
|
911
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
912
|
+
|
913
|
+
if (limits) {
|
914
|
+
params.limitsEnabled = true;
|
915
|
+
params.limits = limits;
|
916
|
+
}
|
917
|
+
|
918
|
+
return useImpulseJoint(body1, body2, params);
|
885
919
|
};
|
886
920
|
|
887
921
|
const calcForceByType = {
|
@@ -1019,12 +1053,12 @@ const Physics = ({
|
|
1019
1053
|
|
1020
1054
|
return worldRef.current;
|
1021
1055
|
});
|
1022
|
-
const
|
1023
|
-
const
|
1024
|
-
const
|
1025
|
-
const
|
1026
|
-
const
|
1027
|
-
const
|
1056
|
+
const rigidBodyStates = useConst(() => new Map());
|
1057
|
+
const colliderStates = useConst(() => new Map());
|
1058
|
+
const rigidBodyEvents = useConst(() => new Map());
|
1059
|
+
const colliderEvents = useConst(() => new Map());
|
1060
|
+
const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
|
1061
|
+
const attractorStates = useConst(() => new Map()); // Init world
|
1028
1062
|
|
1029
1063
|
React.useEffect(() => {
|
1030
1064
|
const world = getWorldRef.current();
|
@@ -131,6 +131,17 @@ const vectorToTuple = v => {
|
|
131
131
|
|
132
132
|
return [v];
|
133
133
|
};
|
134
|
+
function useConst(initialValue) {
|
135
|
+
const ref = React.useRef();
|
136
|
+
|
137
|
+
if (ref.current === undefined) {
|
138
|
+
ref.current = {
|
139
|
+
value: typeof initialValue === "function" ? initialValue() : initialValue
|
140
|
+
};
|
141
|
+
}
|
142
|
+
|
143
|
+
return ref.current.value;
|
144
|
+
}
|
134
145
|
|
135
146
|
const createRigidBodyApi = ref => {
|
136
147
|
return {
|
@@ -579,8 +590,12 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
579
590
|
};
|
580
591
|
|
581
592
|
const rigidBodyDescFromOptions = options => {
|
593
|
+
var _options$canSleep;
|
594
|
+
|
582
595
|
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
583
|
-
const desc = new rapier3dCompat.RigidBodyDesc(type);
|
596
|
+
const desc = new rapier3dCompat.RigidBodyDesc(type); // Apply immutable options
|
597
|
+
|
598
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
584
599
|
return desc;
|
585
600
|
};
|
586
601
|
const createRigidBodyState = ({
|
@@ -646,6 +661,11 @@ const mutableRigidBodyOptions = {
|
|
646
661
|
userData: (rb, value) => {
|
647
662
|
rb.userData = value;
|
648
663
|
},
|
664
|
+
|
665
|
+
type(rb, value) {
|
666
|
+
rb.setBodyType(rigidBodyTypeFromString(value));
|
667
|
+
},
|
668
|
+
|
649
669
|
position: () => {},
|
650
670
|
rotation: () => {},
|
651
671
|
quaternion: () => {},
|
@@ -865,11 +885,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
865
885
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
866
886
|
*/
|
867
887
|
|
868
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
888
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
869
889
|
const {
|
870
890
|
rapier
|
871
891
|
} = useRapier();
|
872
|
-
|
892
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
893
|
+
|
894
|
+
if (limits) {
|
895
|
+
params.limitsEnabled = true;
|
896
|
+
params.limits = limits;
|
897
|
+
}
|
898
|
+
|
899
|
+
return useImpulseJoint(body1, body2, params);
|
873
900
|
};
|
874
901
|
/**
|
875
902
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
@@ -877,11 +904,18 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
877
904
|
* local tangent axis can be specified for each rigid-body.
|
878
905
|
*/
|
879
906
|
|
880
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
907
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
881
908
|
const {
|
882
909
|
rapier
|
883
910
|
} = useRapier();
|
884
|
-
|
911
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
912
|
+
|
913
|
+
if (limits) {
|
914
|
+
params.limitsEnabled = true;
|
915
|
+
params.limits = limits;
|
916
|
+
}
|
917
|
+
|
918
|
+
return useImpulseJoint(body1, body2, params);
|
885
919
|
};
|
886
920
|
|
887
921
|
const calcForceByType = {
|
@@ -1019,12 +1053,12 @@ const Physics = ({
|
|
1019
1053
|
|
1020
1054
|
return worldRef.current;
|
1021
1055
|
});
|
1022
|
-
const
|
1023
|
-
const
|
1024
|
-
const
|
1025
|
-
const
|
1026
|
-
const
|
1027
|
-
const
|
1056
|
+
const rigidBodyStates = useConst(() => new Map());
|
1057
|
+
const colliderStates = useConst(() => new Map());
|
1058
|
+
const rigidBodyEvents = useConst(() => new Map());
|
1059
|
+
const colliderEvents = useConst(() => new Map());
|
1060
|
+
const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
|
1061
|
+
const attractorStates = useConst(() => new Map()); // Init world
|
1028
1062
|
|
1029
1063
|
React.useEffect(() => {
|
1030
1064
|
const world = getWorldRef.current();
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { ColliderDesc, ActiveEvents, RigidBodyDesc, EventQueue } from '@dimforge/rapier3d-compat';
|
2
2
|
export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
|
3
3
|
import { useFrame, useThree } from '@react-three/fiber';
|
4
|
-
import React, { useMemo, useEffect, useContext, useState,
|
4
|
+
import React, { useRef, useMemo, useEffect, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, useLayoutEffect } from 'react';
|
5
5
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, InstancedMesh, BufferAttribute, DynamicDrawUsage } from 'three';
|
6
6
|
import { useAsset } from 'use-asset';
|
7
7
|
import { mergeVertices, VertexNormalsHelper } from 'three-stdlib';
|
@@ -106,6 +106,17 @@ const vectorToTuple = v => {
|
|
106
106
|
|
107
107
|
return [v];
|
108
108
|
};
|
109
|
+
function useConst(initialValue) {
|
110
|
+
const ref = useRef();
|
111
|
+
|
112
|
+
if (ref.current === undefined) {
|
113
|
+
ref.current = {
|
114
|
+
value: typeof initialValue === "function" ? initialValue() : initialValue
|
115
|
+
};
|
116
|
+
}
|
117
|
+
|
118
|
+
return ref.current.value;
|
119
|
+
}
|
109
120
|
|
110
121
|
const createRigidBodyApi = ref => {
|
111
122
|
return {
|
@@ -554,8 +565,12 @@ const useColliderEvents = (collidersRef, props, events) => {
|
|
554
565
|
};
|
555
566
|
|
556
567
|
const rigidBodyDescFromOptions = options => {
|
568
|
+
var _options$canSleep;
|
569
|
+
|
557
570
|
const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
|
558
|
-
const desc = new RigidBodyDesc(type);
|
571
|
+
const desc = new RigidBodyDesc(type); // Apply immutable options
|
572
|
+
|
573
|
+
desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
|
559
574
|
return desc;
|
560
575
|
};
|
561
576
|
const createRigidBodyState = ({
|
@@ -621,6 +636,11 @@ const mutableRigidBodyOptions = {
|
|
621
636
|
userData: (rb, value) => {
|
622
637
|
rb.userData = value;
|
623
638
|
},
|
639
|
+
|
640
|
+
type(rb, value) {
|
641
|
+
rb.setBodyType(rigidBodyTypeFromString(value));
|
642
|
+
},
|
643
|
+
|
624
644
|
position: () => {},
|
625
645
|
rotation: () => {},
|
626
646
|
quaternion: () => {},
|
@@ -840,11 +860,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
|
840
860
|
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
841
861
|
*/
|
842
862
|
|
843
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
863
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
844
864
|
const {
|
845
865
|
rapier
|
846
866
|
} = useRapier();
|
847
|
-
|
867
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
868
|
+
|
869
|
+
if (limits) {
|
870
|
+
params.limitsEnabled = true;
|
871
|
+
params.limits = limits;
|
872
|
+
}
|
873
|
+
|
874
|
+
return useImpulseJoint(body1, body2, params);
|
848
875
|
};
|
849
876
|
/**
|
850
877
|
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
@@ -852,11 +879,18 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
852
879
|
* local tangent axis can be specified for each rigid-body.
|
853
880
|
*/
|
854
881
|
|
855
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
882
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
856
883
|
const {
|
857
884
|
rapier
|
858
885
|
} = useRapier();
|
859
|
-
|
886
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
887
|
+
|
888
|
+
if (limits) {
|
889
|
+
params.limitsEnabled = true;
|
890
|
+
params.limits = limits;
|
891
|
+
}
|
892
|
+
|
893
|
+
return useImpulseJoint(body1, body2, params);
|
860
894
|
};
|
861
895
|
|
862
896
|
const calcForceByType = {
|
@@ -994,12 +1028,12 @@ const Physics = ({
|
|
994
1028
|
|
995
1029
|
return worldRef.current;
|
996
1030
|
});
|
997
|
-
const
|
998
|
-
const
|
999
|
-
const
|
1000
|
-
const
|
1001
|
-
const
|
1002
|
-
const
|
1031
|
+
const rigidBodyStates = useConst(() => new Map());
|
1032
|
+
const colliderStates = useConst(() => new Map());
|
1033
|
+
const rigidBodyEvents = useConst(() => new Map());
|
1034
|
+
const colliderEvents = useConst(() => new Map());
|
1035
|
+
const eventQueue = useConst(() => new EventQueue(false));
|
1036
|
+
const attractorStates = useConst(() => new Map()); // Init world
|
1003
1037
|
|
1004
1038
|
useEffect(() => {
|
1005
1039
|
const world = getWorldRef.current();
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@react-three/rapier",
|
3
|
-
"version": "0.11.
|
3
|
+
"version": "0.11.2",
|
4
4
|
"source": "src/index.ts",
|
5
5
|
"main": "dist/react-three-rapier.cjs.js",
|
6
6
|
"module": "dist/react-three-rapier.esm.js",
|
@@ -12,17 +12,17 @@
|
|
12
12
|
"ts": "tsc -w"
|
13
13
|
},
|
14
14
|
"devDependencies": {
|
15
|
-
"@react-three/drei": "
|
16
|
-
"@react-three/fiber": "
|
15
|
+
"@react-three/drei": "9.45.0",
|
16
|
+
"@react-three/fiber": "8.9.1",
|
17
17
|
"@react-three/test-renderer": "^8.0.17",
|
18
18
|
"@types/react-dom": "^18.0.2",
|
19
19
|
"@types/three": "^0.139.0",
|
20
20
|
"@vitejs/plugin-react": "^2.1.0",
|
21
21
|
"@vitest/ui": "^0.25.2",
|
22
22
|
"happy-dom": "^7.5.5",
|
23
|
-
"react": "
|
24
|
-
"react-dom": "
|
25
|
-
"three": "
|
23
|
+
"react": "18.2.0",
|
24
|
+
"react-dom": "18.2.0",
|
25
|
+
"three": "0.146.0",
|
26
26
|
"vitest": "^0.25.2"
|
27
27
|
},
|
28
28
|
"peerDependencies": {
|
package/readme.md
CHANGED
@@ -41,19 +41,51 @@ const App = () => {
|
|
41
41
|
|
42
42
|
## Readme Topics
|
43
43
|
|
44
|
-
- [
|
44
|
+
- [Basic Usage](#basic-usage)
|
45
|
+
- [Readme Topics](#readme-topics)
|
46
|
+
- [The Physics Component](#the-physics-component)
|
47
|
+
- [Automatic colliders](#automatic-colliders)
|
48
|
+
- [Collider Examples](#collider-examples)
|
45
49
|
- [Instanced Meshes](#instanced-meshes)
|
46
50
|
- [Debug](#debug)
|
47
51
|
- [Collision Events](#collision-events)
|
48
|
-
- [
|
49
|
-
- [Contact
|
52
|
+
- [Configuring collision and solver groups](#configuring-collision-and-solver-groups)
|
53
|
+
- [Contact force events](#contact-force-events)
|
50
54
|
- [Sensors](#sensors)
|
55
|
+
- [Sensors Example](#sensors-example)
|
51
56
|
- [Attractors](#attractors)
|
52
|
-
- [
|
57
|
+
- [Attractors Example](#attractors-example)
|
58
|
+
- [Configuring Time Step Size](#configuring-time-step-size)
|
53
59
|
- [Manual stepping](#manual-stepping)
|
60
|
+
- [Joints](#joints)
|
61
|
+
- [Joints Example](#joints-example)
|
54
62
|
|
55
63
|
---
|
56
64
|
|
65
|
+
## The Physics Component
|
66
|
+
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
|
+
|
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"
|
74
|
+
|
75
|
+
// The number of physics steps per second
|
76
|
+
timeStep?: number | "vary"; // default 1/60
|
77
|
+
|
78
|
+
// Pause the physic simulation
|
79
|
+
paused?: boolean; // default false
|
80
|
+
|
81
|
+
// Which order to run the physics simulation
|
82
|
+
updatePriority?: number;
|
83
|
+
|
84
|
+
// If the physics updates slower than the monitor refreshes,
|
85
|
+
// interpolation will smooth out the steps between frames
|
86
|
+
interpolate?: boolean; // default true
|
87
|
+
```
|
88
|
+
|
57
89
|
## Automatic colliders
|
58
90
|
|
59
91
|
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.
|
@@ -149,6 +181,10 @@ If part of our meshes are invisible and you want to include them in the collider
|
|
149
181
|
</RigidBody>
|
150
182
|
```
|
151
183
|
|
184
|
+
### Collider Examples
|
185
|
+
<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
|
+
<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
|
+
|
152
188
|
## Instanced Meshes
|
153
189
|
|
154
190
|
Instanced meshes can also be used and have automatic colliders generated from their mesh.
|
@@ -393,6 +429,9 @@ To detect when a collider enters or leaves another collider, you can use the `on
|
|
393
429
|
</RigidBody>
|
394
430
|
```
|
395
431
|
|
432
|
+
### Sensors Example
|
433
|
+
<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
|
+
|
396
435
|
## Attractors
|
397
436
|
|
398
437
|
An attractor simulates a source of gravity. Any `RigidBody` within range will be _pulled_ (attracted) toward the attractor.
|
@@ -427,6 +466,9 @@ Gravity types:
|
|
427
466
|
- `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.
|
428
467
|
- `distance` is the distance between the attractor and rigid-body at the time of calculation
|
429
468
|
|
469
|
+
### Attractors Example
|
470
|
+
<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
|
+
|
430
472
|
## Configuring Time Step Size
|
431
473
|
|
432
474
|
By default, `<Physics>` will simulate the physics world at a fixed rate of 60 frames per second. This can be changed by setting the `timeStep` prop on `<Physics>`:
|
@@ -455,4 +497,7 @@ step(1 / 60);
|
|
455
497
|
|
456
498
|
## Joints
|
457
499
|
|
458
|
-
WIP
|
500
|
+
- WIP
|
501
|
+
|
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>
|