@react-three/rapier 0.13.1 → 0.14.0-rc.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/declarations/src/components/Attractor.d.ts +4 -4
- package/dist/declarations/src/components/Physics.d.ts +1 -8
- package/dist/declarations/src/types.d.ts +19 -9
- package/dist/declarations/src/utils/utils-physics.d.ts +1 -0
- package/dist/react-three-rapier.cjs.dev.js +51 -11
- package/dist/react-three-rapier.cjs.prod.js +51 -11
- package/dist/react-three-rapier.esm.js +53 -13
- package/package.json +1 -1
- package/readme.md +13 -14
@@ -12,13 +12,13 @@ export interface AttractorProps {
|
|
12
12
|
* The strength of the attractor.
|
13
13
|
* Positive values attract, negative values repel.
|
14
14
|
*
|
15
|
-
* @
|
15
|
+
* @defaultValue 1
|
16
16
|
*/
|
17
17
|
strength?: number;
|
18
18
|
/**
|
19
19
|
* The range of the attractor. Will not affect objects outside of this range.
|
20
20
|
*
|
21
|
-
* @
|
21
|
+
* @defaultValue 10
|
22
22
|
* @min 0
|
23
23
|
*/
|
24
24
|
range?: number;
|
@@ -27,12 +27,12 @@ export interface AttractorProps {
|
|
27
27
|
* - static: The gravity is constant and does not change over time.
|
28
28
|
* - linear: The gravity is linearly interpolated the closer the object is to the attractor.
|
29
29
|
* - newtonian: The gravity is calculated using the newtonian gravity formula.
|
30
|
-
* @
|
30
|
+
* @defaultValue "static"
|
31
31
|
*/
|
32
32
|
type?: AttractorGravityType;
|
33
33
|
/**
|
34
34
|
* The mass of the attractor. Used when type is `newtonian`.
|
35
|
-
* @
|
35
|
+
* @defaultValue 6.673e-11
|
36
36
|
*/
|
37
37
|
gravitationalConstant?: number;
|
38
38
|
/**
|
@@ -140,18 +140,11 @@ export interface PhysicsProps {
|
|
140
140
|
* @defaultValue false
|
141
141
|
*/
|
142
142
|
paused?: boolean;
|
143
|
-
/**
|
144
|
-
* The update priority at which the physics simulation should run.
|
145
|
-
*
|
146
|
-
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop
|
147
|
-
* @defaultValue undefined
|
148
|
-
*/
|
149
|
-
updatePriority?: number;
|
150
143
|
/**
|
151
144
|
* Interpolate the world transform using the frame delta times.
|
152
145
|
* Has no effect if timeStep is set to "vary".
|
153
146
|
*
|
154
|
-
* @
|
147
|
+
* @defaultValue true
|
155
148
|
**/
|
156
149
|
interpolate?: boolean;
|
157
150
|
}
|
@@ -228,31 +228,41 @@ export interface RigidBodyOptions extends ColliderProps {
|
|
228
228
|
* Specify the type of this rigid body
|
229
229
|
*/
|
230
230
|
type?: RigidBodyTypeString;
|
231
|
-
/**
|
232
|
-
*
|
231
|
+
/**
|
232
|
+
* Whether or not this body can sleep.
|
233
|
+
* @defaultValue true
|
233
234
|
*/
|
234
235
|
canSleep?: boolean;
|
235
236
|
/** The linear damping coefficient of this rigid-body.*/
|
236
237
|
linearDamping?: number;
|
237
238
|
/** The angular damping coefficient of this rigid-body.*/
|
238
239
|
angularDamping?: number;
|
239
|
-
/**
|
240
|
-
*
|
240
|
+
/**
|
241
|
+
* The initial linear velocity of this body.
|
242
|
+
* @defaultValue [0,0,0]
|
241
243
|
*/
|
242
244
|
linearVelocity?: Vector3Array;
|
243
|
-
/**
|
244
|
-
*
|
245
|
+
/**
|
246
|
+
* The initial angular velocity of this body.
|
247
|
+
* @defaultValue [0,0,0]
|
245
248
|
*/
|
246
249
|
angularVelocity?: Vector3Array;
|
247
250
|
/**
|
248
251
|
* The scaling factor applied to the gravity affecting the rigid-body.
|
249
|
-
*
|
252
|
+
* @defaultValue 1.0
|
250
253
|
*/
|
251
254
|
gravityScale?: number;
|
255
|
+
/**
|
256
|
+
* The dominance group of this RigidBody. If a rigid body has a higher domiance group,
|
257
|
+
* on collision it will be immune to forces originating from the other bodies.
|
258
|
+
* https://rapier.rs/docs/user_guides/javascript/rigid_bodies#dominance
|
259
|
+
* Default: 0
|
260
|
+
*/
|
261
|
+
dominanceGroup?: number;
|
252
262
|
/**
|
253
263
|
* Whether or not Continous Collision Detection is enabled for this rigid-body.
|
254
264
|
* https://rapier.rs/docs/user_guides/javascript/rigid_bodies#continuous-collision-detection
|
255
|
-
* @
|
265
|
+
* @defaultValue false
|
256
266
|
*/
|
257
267
|
ccd?: boolean;
|
258
268
|
/**
|
@@ -308,7 +318,7 @@ export interface RigidBodyOptions extends ColliderProps {
|
|
308
318
|
*/
|
309
319
|
enabledRotations?: Boolean3Array;
|
310
320
|
/**
|
311
|
-
* Allow
|
321
|
+
* Allow translation of this rigid-body only along specific axes.
|
312
322
|
*/
|
313
323
|
enabledTranslations?: Boolean3Array;
|
314
324
|
/**
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const useRaf: (callback: (dt: number) => void) => void;
|
@@ -178,6 +178,27 @@ function useConst(initialValue) {
|
|
178
178
|
return ref.current.value;
|
179
179
|
}
|
180
180
|
|
181
|
+
const useRaf = callback => {
|
182
|
+
const cb = React.useRef(callback);
|
183
|
+
const raf = React.useRef(0);
|
184
|
+
const lastFrame = React.useRef(0);
|
185
|
+
React.useEffect(() => {
|
186
|
+
cb.current = callback;
|
187
|
+
}, [callback]);
|
188
|
+
React.useEffect(() => {
|
189
|
+
const loop = () => {
|
190
|
+
const now = performance.now();
|
191
|
+
const delta = now - lastFrame.current;
|
192
|
+
raf.current = requestAnimationFrame(loop);
|
193
|
+
cb.current(delta / 1000);
|
194
|
+
lastFrame.current = now;
|
195
|
+
};
|
196
|
+
|
197
|
+
raf.current = requestAnimationFrame(loop);
|
198
|
+
return () => cancelAnimationFrame(raf.current);
|
199
|
+
}, []);
|
200
|
+
};
|
201
|
+
|
181
202
|
const scaleColliderArgs = (shape, args, scale) => {
|
182
203
|
const newArgs = args.slice(); // Heightfield uses a vector
|
183
204
|
|
@@ -675,10 +696,12 @@ const Physics = ({
|
|
675
696
|
children,
|
676
697
|
timeStep: _timeStep = 1 / 60,
|
677
698
|
paused: _paused = false,
|
678
|
-
updatePriority,
|
679
699
|
interpolate: _interpolate = true
|
680
700
|
}) => {
|
681
701
|
const rapier = useAsset.useAsset(importRapier);
|
702
|
+
const {
|
703
|
+
invalidate
|
704
|
+
} = fiber.useThree();
|
682
705
|
const worldRef = React.useRef();
|
683
706
|
const getWorldRef = React.useRef(() => {
|
684
707
|
if (!worldRef.current) {
|
@@ -959,10 +982,13 @@ const Physics = ({
|
|
959
982
|
maxForceMagnitude: event.maxForceMagnitude()
|
960
983
|
}));
|
961
984
|
});
|
985
|
+
world.forEachActiveRigidBody(body => {
|
986
|
+
invalidate();
|
987
|
+
});
|
962
988
|
}, [_paused, _timeStep, _interpolate]);
|
963
|
-
|
989
|
+
useRaf(dt => {
|
964
990
|
if (!_paused) step(dt);
|
965
|
-
}
|
991
|
+
});
|
966
992
|
const context = React.useMemo(() => ({
|
967
993
|
rapier,
|
968
994
|
world: api,
|
@@ -1135,12 +1161,17 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1135
1161
|
const getInstance = useImperativeInstance(() => {
|
1136
1162
|
const worldScale = ref.current.getWorldScale(vec3());
|
1137
1163
|
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
|
1138
|
-
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1139
1164
|
return collider;
|
1140
1165
|
}, collider => {
|
1141
|
-
colliderStates.delete(collider.handle);
|
1142
1166
|
world.removeCollider(collider);
|
1143
1167
|
});
|
1168
|
+
React.useEffect(() => {
|
1169
|
+
const collider = getInstance();
|
1170
|
+
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1171
|
+
return () => {
|
1172
|
+
colliderStates.delete(collider.handle);
|
1173
|
+
};
|
1174
|
+
}, []);
|
1144
1175
|
React.useImperativeHandle(forwardedRef, () => getInstance());
|
1145
1176
|
const mergedProps = React.useMemo(() => {
|
1146
1177
|
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
@@ -1307,6 +1338,9 @@ const mutableRigidBodyOptions = {
|
|
1307
1338
|
angularDamping: (rb, value) => {
|
1308
1339
|
rb.setAngularDamping(value);
|
1309
1340
|
},
|
1341
|
+
dominanceGroup: (rb, value) => {
|
1342
|
+
rb.setDominanceGroup(value);
|
1343
|
+
},
|
1310
1344
|
enabledRotations: (rb, [x, y, z]) => {
|
1311
1345
|
rb.setEnabledRotations(x, y, z, true);
|
1312
1346
|
},
|
@@ -1442,21 +1476,27 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1442
1476
|
children: undefined
|
1443
1477
|
});
|
1444
1478
|
}, [physicsOptions, props]);
|
1445
|
-
const childColliderProps = useChildColliderProps(ref, mergedOptions); //
|
1479
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Provide a way to eagerly create rigidbody
|
1446
1480
|
|
1447
1481
|
const getInstance = useImperativeInstance(() => {
|
1448
1482
|
const desc = rigidBodyDescFromOptions(mergedOptions);
|
1449
1483
|
const rigidBody = world.createRigidBody(desc);
|
1484
|
+
return rigidBody;
|
1485
|
+
}, rigidBody => {
|
1486
|
+
world.removeRigidBody(rigidBody);
|
1487
|
+
}); // Only provide a object state after the ref has been set
|
1488
|
+
|
1489
|
+
React.useEffect(() => {
|
1490
|
+
const rigidBody = getInstance();
|
1450
1491
|
const state = createRigidBodyState({
|
1451
1492
|
rigidBody,
|
1452
1493
|
object: ref.current
|
1453
1494
|
});
|
1454
1495
|
rigidBodyStates.set(rigidBody.handle, props.transformState ? props.transformState(state) : state);
|
1455
|
-
return
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
});
|
1496
|
+
return () => {
|
1497
|
+
rigidBodyStates.delete(rigidBody.handle);
|
1498
|
+
};
|
1499
|
+
}, []);
|
1460
1500
|
useUpdateRigidBodyOptions(getInstance, mergedOptions, rigidBodyStates);
|
1461
1501
|
useRigidBodyEvents(getInstance, mergedOptions, rigidBodyEvents);
|
1462
1502
|
React.useImperativeHandle(forwardedRef, () => getInstance());
|
@@ -178,6 +178,27 @@ function useConst(initialValue) {
|
|
178
178
|
return ref.current.value;
|
179
179
|
}
|
180
180
|
|
181
|
+
const useRaf = callback => {
|
182
|
+
const cb = React.useRef(callback);
|
183
|
+
const raf = React.useRef(0);
|
184
|
+
const lastFrame = React.useRef(0);
|
185
|
+
React.useEffect(() => {
|
186
|
+
cb.current = callback;
|
187
|
+
}, [callback]);
|
188
|
+
React.useEffect(() => {
|
189
|
+
const loop = () => {
|
190
|
+
const now = performance.now();
|
191
|
+
const delta = now - lastFrame.current;
|
192
|
+
raf.current = requestAnimationFrame(loop);
|
193
|
+
cb.current(delta / 1000);
|
194
|
+
lastFrame.current = now;
|
195
|
+
};
|
196
|
+
|
197
|
+
raf.current = requestAnimationFrame(loop);
|
198
|
+
return () => cancelAnimationFrame(raf.current);
|
199
|
+
}, []);
|
200
|
+
};
|
201
|
+
|
181
202
|
const scaleColliderArgs = (shape, args, scale) => {
|
182
203
|
const newArgs = args.slice(); // Heightfield uses a vector
|
183
204
|
|
@@ -675,10 +696,12 @@ const Physics = ({
|
|
675
696
|
children,
|
676
697
|
timeStep: _timeStep = 1 / 60,
|
677
698
|
paused: _paused = false,
|
678
|
-
updatePriority,
|
679
699
|
interpolate: _interpolate = true
|
680
700
|
}) => {
|
681
701
|
const rapier = useAsset.useAsset(importRapier);
|
702
|
+
const {
|
703
|
+
invalidate
|
704
|
+
} = fiber.useThree();
|
682
705
|
const worldRef = React.useRef();
|
683
706
|
const getWorldRef = React.useRef(() => {
|
684
707
|
if (!worldRef.current) {
|
@@ -959,10 +982,13 @@ const Physics = ({
|
|
959
982
|
maxForceMagnitude: event.maxForceMagnitude()
|
960
983
|
}));
|
961
984
|
});
|
985
|
+
world.forEachActiveRigidBody(body => {
|
986
|
+
invalidate();
|
987
|
+
});
|
962
988
|
}, [_paused, _timeStep, _interpolate]);
|
963
|
-
|
989
|
+
useRaf(dt => {
|
964
990
|
if (!_paused) step(dt);
|
965
|
-
}
|
991
|
+
});
|
966
992
|
const context = React.useMemo(() => ({
|
967
993
|
rapier,
|
968
994
|
world: api,
|
@@ -1135,12 +1161,17 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1135
1161
|
const getInstance = useImperativeInstance(() => {
|
1136
1162
|
const worldScale = ref.current.getWorldScale(vec3());
|
1137
1163
|
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
|
1138
|
-
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1139
1164
|
return collider;
|
1140
1165
|
}, collider => {
|
1141
|
-
colliderStates.delete(collider.handle);
|
1142
1166
|
world.removeCollider(collider);
|
1143
1167
|
});
|
1168
|
+
React.useEffect(() => {
|
1169
|
+
const collider = getInstance();
|
1170
|
+
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1171
|
+
return () => {
|
1172
|
+
colliderStates.delete(collider.handle);
|
1173
|
+
};
|
1174
|
+
}, []);
|
1144
1175
|
React.useImperativeHandle(forwardedRef, () => getInstance());
|
1145
1176
|
const mergedProps = React.useMemo(() => {
|
1146
1177
|
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
@@ -1307,6 +1338,9 @@ const mutableRigidBodyOptions = {
|
|
1307
1338
|
angularDamping: (rb, value) => {
|
1308
1339
|
rb.setAngularDamping(value);
|
1309
1340
|
},
|
1341
|
+
dominanceGroup: (rb, value) => {
|
1342
|
+
rb.setDominanceGroup(value);
|
1343
|
+
},
|
1310
1344
|
enabledRotations: (rb, [x, y, z]) => {
|
1311
1345
|
rb.setEnabledRotations(x, y, z, true);
|
1312
1346
|
},
|
@@ -1442,21 +1476,27 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1442
1476
|
children: undefined
|
1443
1477
|
});
|
1444
1478
|
}, [physicsOptions, props]);
|
1445
|
-
const childColliderProps = useChildColliderProps(ref, mergedOptions); //
|
1479
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Provide a way to eagerly create rigidbody
|
1446
1480
|
|
1447
1481
|
const getInstance = useImperativeInstance(() => {
|
1448
1482
|
const desc = rigidBodyDescFromOptions(mergedOptions);
|
1449
1483
|
const rigidBody = world.createRigidBody(desc);
|
1484
|
+
return rigidBody;
|
1485
|
+
}, rigidBody => {
|
1486
|
+
world.removeRigidBody(rigidBody);
|
1487
|
+
}); // Only provide a object state after the ref has been set
|
1488
|
+
|
1489
|
+
React.useEffect(() => {
|
1490
|
+
const rigidBody = getInstance();
|
1450
1491
|
const state = createRigidBodyState({
|
1451
1492
|
rigidBody,
|
1452
1493
|
object: ref.current
|
1453
1494
|
});
|
1454
1495
|
rigidBodyStates.set(rigidBody.handle, props.transformState ? props.transformState(state) : state);
|
1455
|
-
return
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
});
|
1496
|
+
return () => {
|
1497
|
+
rigidBodyStates.delete(rigidBody.handle);
|
1498
|
+
};
|
1499
|
+
}, []);
|
1460
1500
|
useUpdateRigidBodyOptions(getInstance, mergedOptions, rigidBodyStates);
|
1461
1501
|
useRigidBodyEvents(getInstance, mergedOptions, rigidBodyEvents);
|
1462
1502
|
React.useImperativeHandle(forwardedRef, () => getInstance());
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { ActiveEvents, ColliderDesc, EventQueue, RigidBodyDesc } from '@dimforge/rapier3d-compat';
|
2
2
|
export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
|
3
|
-
import {
|
4
|
-
import React, { useRef,
|
3
|
+
import { useThree, useFrame } from '@react-three/fiber';
|
4
|
+
import React, { useRef, useEffect, useMemo, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
|
5
5
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, BufferAttribute, DynamicDrawUsage } from 'three';
|
6
6
|
import { useAsset } from 'use-asset';
|
7
7
|
import { mergeVertices, VertexNormalsHelper } from 'three-stdlib';
|
@@ -153,6 +153,27 @@ function useConst(initialValue) {
|
|
153
153
|
return ref.current.value;
|
154
154
|
}
|
155
155
|
|
156
|
+
const useRaf = callback => {
|
157
|
+
const cb = useRef(callback);
|
158
|
+
const raf = useRef(0);
|
159
|
+
const lastFrame = useRef(0);
|
160
|
+
useEffect(() => {
|
161
|
+
cb.current = callback;
|
162
|
+
}, [callback]);
|
163
|
+
useEffect(() => {
|
164
|
+
const loop = () => {
|
165
|
+
const now = performance.now();
|
166
|
+
const delta = now - lastFrame.current;
|
167
|
+
raf.current = requestAnimationFrame(loop);
|
168
|
+
cb.current(delta / 1000);
|
169
|
+
lastFrame.current = now;
|
170
|
+
};
|
171
|
+
|
172
|
+
raf.current = requestAnimationFrame(loop);
|
173
|
+
return () => cancelAnimationFrame(raf.current);
|
174
|
+
}, []);
|
175
|
+
};
|
176
|
+
|
156
177
|
const scaleColliderArgs = (shape, args, scale) => {
|
157
178
|
const newArgs = args.slice(); // Heightfield uses a vector
|
158
179
|
|
@@ -650,10 +671,12 @@ const Physics = ({
|
|
650
671
|
children,
|
651
672
|
timeStep: _timeStep = 1 / 60,
|
652
673
|
paused: _paused = false,
|
653
|
-
updatePriority,
|
654
674
|
interpolate: _interpolate = true
|
655
675
|
}) => {
|
656
676
|
const rapier = useAsset(importRapier);
|
677
|
+
const {
|
678
|
+
invalidate
|
679
|
+
} = useThree();
|
657
680
|
const worldRef = useRef();
|
658
681
|
const getWorldRef = useRef(() => {
|
659
682
|
if (!worldRef.current) {
|
@@ -934,10 +957,13 @@ const Physics = ({
|
|
934
957
|
maxForceMagnitude: event.maxForceMagnitude()
|
935
958
|
}));
|
936
959
|
});
|
960
|
+
world.forEachActiveRigidBody(body => {
|
961
|
+
invalidate();
|
962
|
+
});
|
937
963
|
}, [_paused, _timeStep, _interpolate]);
|
938
|
-
|
964
|
+
useRaf(dt => {
|
939
965
|
if (!_paused) step(dt);
|
940
|
-
}
|
966
|
+
});
|
941
967
|
const context = useMemo(() => ({
|
942
968
|
rapier,
|
943
969
|
world: api,
|
@@ -1110,12 +1136,17 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
|
|
1110
1136
|
const getInstance = useImperativeInstance(() => {
|
1111
1137
|
const worldScale = ref.current.getWorldScale(vec3());
|
1112
1138
|
const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
|
1113
|
-
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1114
1139
|
return collider;
|
1115
1140
|
}, collider => {
|
1116
|
-
colliderStates.delete(collider.handle);
|
1117
1141
|
world.removeCollider(collider);
|
1118
1142
|
});
|
1143
|
+
useEffect(() => {
|
1144
|
+
const collider = getInstance();
|
1145
|
+
colliderStates.set(collider.handle, createColliderState(collider, ref.current, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
|
1146
|
+
return () => {
|
1147
|
+
colliderStates.delete(collider.handle);
|
1148
|
+
};
|
1149
|
+
}, []);
|
1119
1150
|
useImperativeHandle(forwardedRef, () => getInstance());
|
1120
1151
|
const mergedProps = useMemo(() => {
|
1121
1152
|
return _objectSpread2(_objectSpread2({}, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options), props);
|
@@ -1282,6 +1313,9 @@ const mutableRigidBodyOptions = {
|
|
1282
1313
|
angularDamping: (rb, value) => {
|
1283
1314
|
rb.setAngularDamping(value);
|
1284
1315
|
},
|
1316
|
+
dominanceGroup: (rb, value) => {
|
1317
|
+
rb.setDominanceGroup(value);
|
1318
|
+
},
|
1285
1319
|
enabledRotations: (rb, [x, y, z]) => {
|
1286
1320
|
rb.setEnabledRotations(x, y, z, true);
|
1287
1321
|
},
|
@@ -1417,21 +1451,27 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
|
|
1417
1451
|
children: undefined
|
1418
1452
|
});
|
1419
1453
|
}, [physicsOptions, props]);
|
1420
|
-
const childColliderProps = useChildColliderProps(ref, mergedOptions); //
|
1454
|
+
const childColliderProps = useChildColliderProps(ref, mergedOptions); // Provide a way to eagerly create rigidbody
|
1421
1455
|
|
1422
1456
|
const getInstance = useImperativeInstance(() => {
|
1423
1457
|
const desc = rigidBodyDescFromOptions(mergedOptions);
|
1424
1458
|
const rigidBody = world.createRigidBody(desc);
|
1459
|
+
return rigidBody;
|
1460
|
+
}, rigidBody => {
|
1461
|
+
world.removeRigidBody(rigidBody);
|
1462
|
+
}); // Only provide a object state after the ref has been set
|
1463
|
+
|
1464
|
+
useEffect(() => {
|
1465
|
+
const rigidBody = getInstance();
|
1425
1466
|
const state = createRigidBodyState({
|
1426
1467
|
rigidBody,
|
1427
1468
|
object: ref.current
|
1428
1469
|
});
|
1429
1470
|
rigidBodyStates.set(rigidBody.handle, props.transformState ? props.transformState(state) : state);
|
1430
|
-
return
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
});
|
1471
|
+
return () => {
|
1472
|
+
rigidBodyStates.delete(rigidBody.handle);
|
1473
|
+
};
|
1474
|
+
}, []);
|
1435
1475
|
useUpdateRigidBodyOptions(getInstance, mergedOptions, rigidBodyStates);
|
1436
1476
|
useRigidBodyEvents(getInstance, mergedOptions, rigidBodyEvents);
|
1437
1477
|
useImperativeHandle(forwardedRef, () => getInstance());
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -66,6 +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
70
|
- [Moving things around, and applying forces](#moving-things-around-and-applying-forces)
|
70
71
|
- [Collision Events](#collision-events)
|
71
72
|
- [Configuring collision and solver groups](#configuring-collision-and-solver-groups)
|
@@ -83,6 +84,7 @@ For full API outline and documentation, see 🧩 [API Docs](https://pmndrs.githu
|
|
83
84
|
- [🖼 Joints Example](#-joints-example)
|
84
85
|
- [Advanced hooks usage](#advanced-hooks-usage)
|
85
86
|
- [Manual stepping](#manual-stepping)
|
87
|
+
- [On-demand rendering](#on-demand-rendering)
|
86
88
|
|
87
89
|
---
|
88
90
|
|
@@ -130,7 +132,7 @@ Supported values:
|
|
130
132
|
|
131
133
|
- `"cuboid"`, creates a CuboidCollider based on the bounding box of the mesh
|
132
134
|
- `"ball"`, creates a SphereCollider based on the bounding sphere of the mesh
|
133
|
-
- `"trimesh"`, creates a TrimeshCollider based on the mesh's geometry
|
135
|
+
- `"trimesh"`, creates a TrimeshCollider based on the mesh's geometry
|
134
136
|
- `"hull"`, creates a ConvexHullCollider based on the mesh's geometry
|
135
137
|
- `false`, disables auto-generation
|
136
138
|
|
@@ -255,11 +257,12 @@ const Scene = () => {
|
|
255
257
|
}
|
256
258
|
|
257
259
|
// You can access individual instanced by their index
|
258
|
-
rigidBodies.current
|
260
|
+
rigidBodies.current[40].applyImpulse({ x: 0, y: 10, z: 0 }, true);
|
261
|
+
rigidBodies.at(100).applyImpulse({ x: 0, y: 10, z: 0 }, true);
|
259
262
|
|
260
263
|
// Or update all instances
|
261
264
|
rigidBodies.current.forEach((api) => {
|
262
|
-
api.applyImpulse({ x: 0, y: 10, z: 0 });
|
265
|
+
api.applyImpulse({ x: 0, y: 10, z: 0 }, true);
|
263
266
|
});
|
264
267
|
}, []);
|
265
268
|
|
@@ -328,8 +331,6 @@ const Scene = () => {
|
|
328
331
|
);
|
329
332
|
};
|
330
333
|
```
|
331
|
-
}
|
332
|
-
```
|
333
334
|
|
334
335
|
## Debug
|
335
336
|
|
@@ -589,8 +590,6 @@ To detect when a collider enters or leaves another collider, you can use the `on
|
|
589
590
|
|
590
591
|
🧩 See [onIntersectionEnter / onIntersectionExit docs](https://pmndrs.github.io/react-three-rapier/interfaces/RigidBodyProps.html#onIntersectionEnter) for more information.
|
591
592
|
|
592
|
-
```tsx
|
593
|
-
|
594
593
|
```tsx
|
595
594
|
<RigidBody>
|
596
595
|
<GoalPosts />
|
@@ -674,6 +673,7 @@ There are 4 different joint types available:
|
|
674
673
|
- Prismatic (two bodies are connected by a sliding joint, for things like pistons or sliders)
|
675
674
|
|
676
675
|
Each joint hook returns a RefObject containing the raw reference to the joint instance.
|
676
|
+
|
677
677
|
```tsx
|
678
678
|
const WheelJoint = ({bodyA, bodyB}) => {
|
679
679
|
const joint = useRevoluteJoint(bodyA, bodyB, [[0,0,0],[0,0,0],[0,0,0]])
|
@@ -723,8 +723,6 @@ The spherical joint ensures that two points on the local-spaces of two rigid-bod
|
|
723
723
|
|
724
724
|
🧩 See [SphericalJoint docs](https://pmndrs.github.io/react-three-rapier/functions/useSphericalJoint.html) for available options.
|
725
725
|
|
726
|
-
```tsx
|
727
|
-
|
728
726
|
```tsx
|
729
727
|
const JointedThing = () => {
|
730
728
|
const joint = useSphericalJoint(
|
@@ -761,7 +759,7 @@ const JointedThing = () => {
|
|
761
759
|
[
|
762
760
|
[0, 0, 0], // Position of the joint in bodyA's local space
|
763
761
|
[0, 0, 0], // Position of the joint in bodyB's local space
|
764
|
-
[0,
|
762
|
+
[0, 1, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to. Cannot be [0,0,0].
|
765
763
|
]);
|
766
764
|
|
767
765
|
useEffect(() => {
|
@@ -788,8 +786,6 @@ The prismatic joint prevents any relative movement between two rigid-bodies, exc
|
|
788
786
|
|
789
787
|
🧩 See [PrismaticJoint docs](https://pmndrs.github.io/react-three-rapier/functions/usePrismaticJoint.html) for available options.
|
790
788
|
|
791
|
-
```tsx
|
792
|
-
|
793
789
|
```tsx
|
794
790
|
const JointedThing = () => {
|
795
791
|
const joint = usePrismaticJoint(
|
@@ -798,7 +794,7 @@ const JointedThing = () => {
|
|
798
794
|
[
|
799
795
|
[0, 0, 0], // Position of the joint in bodyA's local space
|
800
796
|
[0, 0, 0], // Position of the joint in bodyB's local space
|
801
|
-
[0,
|
797
|
+
[0, 1, 0], // Axis of the joint, expressed in the local-space of the rigid-bodies it is attached to. Cannot be [0,0,0].
|
802
798
|
]);
|
803
799
|
|
804
800
|
return (
|
@@ -839,4 +835,7 @@ You can manually step the physics simulation by calling the `step` method from t
|
|
839
835
|
const { step } = useRapier();
|
840
836
|
|
841
837
|
step(1 / 60);
|
842
|
-
```
|
838
|
+
```
|
839
|
+
|
840
|
+
### On-demand rendering
|
841
|
+
`@react-three/rapier` runs the physics simulation independently from the render loop, and will tell `@react-three/fiber` to render if the scene has active (non-sleeping) RigidBodies. This allows you to use the `<Canvas frameloop="demand" />` (https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#on-demand-rendering) strategy to only render the scene when needed.
|