@react-three/rapier 0.14.0-rc.1 → 0.14.0-rc.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.
- package/dist/declarations/src/components/FrameStepper.d.ts +9 -0
- package/dist/declarations/src/components/Physics.d.ts +24 -0
- package/dist/react-three-rapier.cjs.dev.js +69 -27
- package/dist/react-three-rapier.cjs.prod.js +69 -27
- package/dist/react-three-rapier.esm.js +71 -29
- package/package.json +1 -1
- package/readme.md +11 -1
@@ -0,0 +1,9 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import { PhysicsProps } from "./Physics";
|
3
|
+
interface FrameStepperProps {
|
4
|
+
type?: PhysicsProps["updateLoop"];
|
5
|
+
onStep: (dt: number) => void;
|
6
|
+
updatePriority?: number;
|
7
|
+
}
|
8
|
+
declare const _default: React.MemoExoticComponent<({ onStep, type, updatePriority }: FrameStepperProps) => JSX.Element>;
|
9
|
+
export default _default;
|
@@ -147,6 +147,30 @@ export interface PhysicsProps {
|
|
147
147
|
* @defaultValue true
|
148
148
|
**/
|
149
149
|
interpolate?: boolean;
|
150
|
+
/**
|
151
|
+
* The update priority at which the physics simulation should run.
|
152
|
+
* Only used when `updateLoop` is set to "follow".
|
153
|
+
*
|
154
|
+
* @see https://docs.pmnd.rs/react-three-fiber/api/hooks#taking-over-the-render-loop
|
155
|
+
* @defaultValue undefined
|
156
|
+
*/
|
157
|
+
updatePriority?: number;
|
158
|
+
/**
|
159
|
+
* Set the update loop strategy for the physics world.
|
160
|
+
*
|
161
|
+
* If set to "follow", the physics world will be stepped
|
162
|
+
* in a `useFrame` callback, managed by @react-three/fiber.
|
163
|
+
* You can use `updatePriority` prop to manage the scheduling.
|
164
|
+
*
|
165
|
+
* If set to "independent", the physics world will be stepped
|
166
|
+
* in a separate loop, not tied to the render loop.
|
167
|
+
* This is useful when using the "demand" `frameloop` strategy for the
|
168
|
+
* @react-three/fiber `<Canvas />`.
|
169
|
+
*
|
170
|
+
* @see https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#on-demand-rendering
|
171
|
+
* @defaultValue "follow"
|
172
|
+
*/
|
173
|
+
updateLoop?: "follow" | "independent";
|
150
174
|
}
|
151
175
|
/**
|
152
176
|
* The main physics component used to create a physics world.
|
@@ -178,27 +178,6 @@ 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
|
-
|
202
181
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
203
182
|
if (source == null) return {};
|
204
183
|
var target = {};
|
@@ -712,6 +691,61 @@ const Attractor = /*#__PURE__*/React.memo(props => {
|
|
712
691
|
});
|
713
692
|
});
|
714
693
|
|
694
|
+
const useRaf = callback => {
|
695
|
+
const cb = React.useRef(callback);
|
696
|
+
const raf = React.useRef(0);
|
697
|
+
const lastFrame = React.useRef(0);
|
698
|
+
React.useEffect(() => {
|
699
|
+
cb.current = callback;
|
700
|
+
}, [callback]);
|
701
|
+
React.useEffect(() => {
|
702
|
+
const loop = () => {
|
703
|
+
const now = performance.now();
|
704
|
+
const delta = now - lastFrame.current;
|
705
|
+
raf.current = requestAnimationFrame(loop);
|
706
|
+
cb.current(delta / 1000);
|
707
|
+
lastFrame.current = now;
|
708
|
+
};
|
709
|
+
|
710
|
+
raf.current = requestAnimationFrame(loop);
|
711
|
+
return () => cancelAnimationFrame(raf.current);
|
712
|
+
}, []);
|
713
|
+
};
|
714
|
+
|
715
|
+
const UseFrameStepper = ({
|
716
|
+
onStep,
|
717
|
+
updatePriority
|
718
|
+
}) => {
|
719
|
+
fiber.useFrame((_, dt) => {
|
720
|
+
onStep(dt);
|
721
|
+
}, updatePriority);
|
722
|
+
return null;
|
723
|
+
};
|
724
|
+
|
725
|
+
const RafStepper = ({
|
726
|
+
onStep
|
727
|
+
}) => {
|
728
|
+
useRaf(dt => {
|
729
|
+
onStep(dt);
|
730
|
+
});
|
731
|
+
return null;
|
732
|
+
};
|
733
|
+
|
734
|
+
const FrameStepper = ({
|
735
|
+
onStep,
|
736
|
+
type,
|
737
|
+
updatePriority
|
738
|
+
}) => {
|
739
|
+
return type === "independent" ? /*#__PURE__*/React__default["default"].createElement(RafStepper, {
|
740
|
+
onStep: onStep
|
741
|
+
}) : /*#__PURE__*/React__default["default"].createElement(UseFrameStepper, {
|
742
|
+
onStep: onStep,
|
743
|
+
updatePriority: updatePriority
|
744
|
+
});
|
745
|
+
};
|
746
|
+
|
747
|
+
var FrameStepper$1 = /*#__PURE__*/React.memo(FrameStepper);
|
748
|
+
|
715
749
|
const rapierContext = /*#__PURE__*/React.createContext(undefined);
|
716
750
|
|
717
751
|
const getCollisionPayloadFromSource = (target, other) => {
|
@@ -753,7 +787,9 @@ const Physics = ({
|
|
753
787
|
children,
|
754
788
|
timeStep: _timeStep = 1 / 60,
|
755
789
|
paused: _paused = false,
|
756
|
-
interpolate: _interpolate = true
|
790
|
+
interpolate: _interpolate = true,
|
791
|
+
updatePriority,
|
792
|
+
updateLoop: _updateLoop = "follow"
|
757
793
|
}) => {
|
758
794
|
const rapier = useAsset.useAsset(importRapier);
|
759
795
|
const {
|
@@ -1039,13 +1075,10 @@ const Physics = ({
|
|
1039
1075
|
maxForceMagnitude: event.maxForceMagnitude()
|
1040
1076
|
}));
|
1041
1077
|
});
|
1042
|
-
world.forEachActiveRigidBody(
|
1078
|
+
world.forEachActiveRigidBody(() => {
|
1043
1079
|
invalidate();
|
1044
1080
|
});
|
1045
1081
|
}, [_paused, _timeStep, _interpolate]);
|
1046
|
-
useRaf(dt => {
|
1047
|
-
if (!_paused) step(dt);
|
1048
|
-
});
|
1049
1082
|
const context = React.useMemo(() => ({
|
1050
1083
|
rapier,
|
1051
1084
|
world: api,
|
@@ -1063,9 +1096,18 @@ const Physics = ({
|
|
1063
1096
|
isPaused: _paused,
|
1064
1097
|
step
|
1065
1098
|
}), [_paused, step]);
|
1099
|
+
const stepCallback = React.useCallback(delta => {
|
1100
|
+
if (!_paused) {
|
1101
|
+
step(delta);
|
1102
|
+
}
|
1103
|
+
}, [_paused, step]);
|
1066
1104
|
return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
|
1067
1105
|
value: context
|
1068
|
-
},
|
1106
|
+
}, /*#__PURE__*/React__default["default"].createElement(FrameStepper$1, {
|
1107
|
+
onStep: stepCallback,
|
1108
|
+
type: _updateLoop,
|
1109
|
+
updatePriority: updatePriority
|
1110
|
+
}), children);
|
1069
1111
|
};
|
1070
1112
|
|
1071
1113
|
function _extends() {
|
@@ -178,27 +178,6 @@ 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
|
-
|
202
181
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
203
182
|
if (source == null) return {};
|
204
183
|
var target = {};
|
@@ -712,6 +691,61 @@ const Attractor = /*#__PURE__*/React.memo(props => {
|
|
712
691
|
});
|
713
692
|
});
|
714
693
|
|
694
|
+
const useRaf = callback => {
|
695
|
+
const cb = React.useRef(callback);
|
696
|
+
const raf = React.useRef(0);
|
697
|
+
const lastFrame = React.useRef(0);
|
698
|
+
React.useEffect(() => {
|
699
|
+
cb.current = callback;
|
700
|
+
}, [callback]);
|
701
|
+
React.useEffect(() => {
|
702
|
+
const loop = () => {
|
703
|
+
const now = performance.now();
|
704
|
+
const delta = now - lastFrame.current;
|
705
|
+
raf.current = requestAnimationFrame(loop);
|
706
|
+
cb.current(delta / 1000);
|
707
|
+
lastFrame.current = now;
|
708
|
+
};
|
709
|
+
|
710
|
+
raf.current = requestAnimationFrame(loop);
|
711
|
+
return () => cancelAnimationFrame(raf.current);
|
712
|
+
}, []);
|
713
|
+
};
|
714
|
+
|
715
|
+
const UseFrameStepper = ({
|
716
|
+
onStep,
|
717
|
+
updatePriority
|
718
|
+
}) => {
|
719
|
+
fiber.useFrame((_, dt) => {
|
720
|
+
onStep(dt);
|
721
|
+
}, updatePriority);
|
722
|
+
return null;
|
723
|
+
};
|
724
|
+
|
725
|
+
const RafStepper = ({
|
726
|
+
onStep
|
727
|
+
}) => {
|
728
|
+
useRaf(dt => {
|
729
|
+
onStep(dt);
|
730
|
+
});
|
731
|
+
return null;
|
732
|
+
};
|
733
|
+
|
734
|
+
const FrameStepper = ({
|
735
|
+
onStep,
|
736
|
+
type,
|
737
|
+
updatePriority
|
738
|
+
}) => {
|
739
|
+
return type === "independent" ? /*#__PURE__*/React__default["default"].createElement(RafStepper, {
|
740
|
+
onStep: onStep
|
741
|
+
}) : /*#__PURE__*/React__default["default"].createElement(UseFrameStepper, {
|
742
|
+
onStep: onStep,
|
743
|
+
updatePriority: updatePriority
|
744
|
+
});
|
745
|
+
};
|
746
|
+
|
747
|
+
var FrameStepper$1 = /*#__PURE__*/React.memo(FrameStepper);
|
748
|
+
|
715
749
|
const rapierContext = /*#__PURE__*/React.createContext(undefined);
|
716
750
|
|
717
751
|
const getCollisionPayloadFromSource = (target, other) => {
|
@@ -753,7 +787,9 @@ const Physics = ({
|
|
753
787
|
children,
|
754
788
|
timeStep: _timeStep = 1 / 60,
|
755
789
|
paused: _paused = false,
|
756
|
-
interpolate: _interpolate = true
|
790
|
+
interpolate: _interpolate = true,
|
791
|
+
updatePriority,
|
792
|
+
updateLoop: _updateLoop = "follow"
|
757
793
|
}) => {
|
758
794
|
const rapier = useAsset.useAsset(importRapier);
|
759
795
|
const {
|
@@ -1039,13 +1075,10 @@ const Physics = ({
|
|
1039
1075
|
maxForceMagnitude: event.maxForceMagnitude()
|
1040
1076
|
}));
|
1041
1077
|
});
|
1042
|
-
world.forEachActiveRigidBody(
|
1078
|
+
world.forEachActiveRigidBody(() => {
|
1043
1079
|
invalidate();
|
1044
1080
|
});
|
1045
1081
|
}, [_paused, _timeStep, _interpolate]);
|
1046
|
-
useRaf(dt => {
|
1047
|
-
if (!_paused) step(dt);
|
1048
|
-
});
|
1049
1082
|
const context = React.useMemo(() => ({
|
1050
1083
|
rapier,
|
1051
1084
|
world: api,
|
@@ -1063,9 +1096,18 @@ const Physics = ({
|
|
1063
1096
|
isPaused: _paused,
|
1064
1097
|
step
|
1065
1098
|
}), [_paused, step]);
|
1099
|
+
const stepCallback = React.useCallback(delta => {
|
1100
|
+
if (!_paused) {
|
1101
|
+
step(delta);
|
1102
|
+
}
|
1103
|
+
}, [_paused, step]);
|
1066
1104
|
return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
|
1067
1105
|
value: context
|
1068
|
-
},
|
1106
|
+
}, /*#__PURE__*/React__default["default"].createElement(FrameStepper$1, {
|
1107
|
+
onStep: stepCallback,
|
1108
|
+
type: _updateLoop,
|
1109
|
+
updatePriority: updatePriority
|
1110
|
+
}), children);
|
1069
1111
|
};
|
1070
1112
|
|
1071
1113
|
function _extends() {
|
@@ -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 { useFrame, useThree } from '@react-three/fiber';
|
4
|
+
import React, { useRef, useMemo, useEffect, 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,27 +153,6 @@ 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
|
-
|
177
156
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
178
157
|
if (source == null) return {};
|
179
158
|
var target = {};
|
@@ -687,6 +666,61 @@ const Attractor = /*#__PURE__*/memo(props => {
|
|
687
666
|
});
|
688
667
|
});
|
689
668
|
|
669
|
+
const useRaf = callback => {
|
670
|
+
const cb = useRef(callback);
|
671
|
+
const raf = useRef(0);
|
672
|
+
const lastFrame = useRef(0);
|
673
|
+
useEffect(() => {
|
674
|
+
cb.current = callback;
|
675
|
+
}, [callback]);
|
676
|
+
useEffect(() => {
|
677
|
+
const loop = () => {
|
678
|
+
const now = performance.now();
|
679
|
+
const delta = now - lastFrame.current;
|
680
|
+
raf.current = requestAnimationFrame(loop);
|
681
|
+
cb.current(delta / 1000);
|
682
|
+
lastFrame.current = now;
|
683
|
+
};
|
684
|
+
|
685
|
+
raf.current = requestAnimationFrame(loop);
|
686
|
+
return () => cancelAnimationFrame(raf.current);
|
687
|
+
}, []);
|
688
|
+
};
|
689
|
+
|
690
|
+
const UseFrameStepper = ({
|
691
|
+
onStep,
|
692
|
+
updatePriority
|
693
|
+
}) => {
|
694
|
+
useFrame((_, dt) => {
|
695
|
+
onStep(dt);
|
696
|
+
}, updatePriority);
|
697
|
+
return null;
|
698
|
+
};
|
699
|
+
|
700
|
+
const RafStepper = ({
|
701
|
+
onStep
|
702
|
+
}) => {
|
703
|
+
useRaf(dt => {
|
704
|
+
onStep(dt);
|
705
|
+
});
|
706
|
+
return null;
|
707
|
+
};
|
708
|
+
|
709
|
+
const FrameStepper = ({
|
710
|
+
onStep,
|
711
|
+
type,
|
712
|
+
updatePriority
|
713
|
+
}) => {
|
714
|
+
return type === "independent" ? /*#__PURE__*/React.createElement(RafStepper, {
|
715
|
+
onStep: onStep
|
716
|
+
}) : /*#__PURE__*/React.createElement(UseFrameStepper, {
|
717
|
+
onStep: onStep,
|
718
|
+
updatePriority: updatePriority
|
719
|
+
});
|
720
|
+
};
|
721
|
+
|
722
|
+
var FrameStepper$1 = /*#__PURE__*/memo(FrameStepper);
|
723
|
+
|
690
724
|
const rapierContext = /*#__PURE__*/createContext(undefined);
|
691
725
|
|
692
726
|
const getCollisionPayloadFromSource = (target, other) => {
|
@@ -728,7 +762,9 @@ const Physics = ({
|
|
728
762
|
children,
|
729
763
|
timeStep: _timeStep = 1 / 60,
|
730
764
|
paused: _paused = false,
|
731
|
-
interpolate: _interpolate = true
|
765
|
+
interpolate: _interpolate = true,
|
766
|
+
updatePriority,
|
767
|
+
updateLoop: _updateLoop = "follow"
|
732
768
|
}) => {
|
733
769
|
const rapier = useAsset(importRapier);
|
734
770
|
const {
|
@@ -1014,13 +1050,10 @@ const Physics = ({
|
|
1014
1050
|
maxForceMagnitude: event.maxForceMagnitude()
|
1015
1051
|
}));
|
1016
1052
|
});
|
1017
|
-
world.forEachActiveRigidBody(
|
1053
|
+
world.forEachActiveRigidBody(() => {
|
1018
1054
|
invalidate();
|
1019
1055
|
});
|
1020
1056
|
}, [_paused, _timeStep, _interpolate]);
|
1021
|
-
useRaf(dt => {
|
1022
|
-
if (!_paused) step(dt);
|
1023
|
-
});
|
1024
1057
|
const context = useMemo(() => ({
|
1025
1058
|
rapier,
|
1026
1059
|
world: api,
|
@@ -1038,9 +1071,18 @@ const Physics = ({
|
|
1038
1071
|
isPaused: _paused,
|
1039
1072
|
step
|
1040
1073
|
}), [_paused, step]);
|
1074
|
+
const stepCallback = useCallback(delta => {
|
1075
|
+
if (!_paused) {
|
1076
|
+
step(delta);
|
1077
|
+
}
|
1078
|
+
}, [_paused, step]);
|
1041
1079
|
return /*#__PURE__*/React.createElement(rapierContext.Provider, {
|
1042
1080
|
value: context
|
1043
|
-
},
|
1081
|
+
}, /*#__PURE__*/React.createElement(FrameStepper$1, {
|
1082
|
+
onStep: stepCallback,
|
1083
|
+
type: _updateLoop,
|
1084
|
+
updatePriority: updatePriority
|
1085
|
+
}), children);
|
1044
1086
|
};
|
1045
1087
|
|
1046
1088
|
function _extends() {
|
package/package.json
CHANGED
package/readme.md
CHANGED
@@ -838,4 +838,14 @@ step(1 / 60);
|
|
838
838
|
```
|
839
839
|
|
840
840
|
### On-demand rendering
|
841
|
-
`@react-three/rapier`
|
841
|
+
By default `@react-three/rapier` will update the physics simulation when a frame renders. This is fine for most cases, but if you want to only render the scene when things have changed, you need to run the physics simulation independently from the render loop.
|
842
|
+
|
843
|
+
- See https://docs.pmnd.rs/react-three-fiber/advanced/scaling-performance#on-demand-rendering, for info on on-demand rendering in `@react-tree/fiber`.
|
844
|
+
|
845
|
+
Setting `<Physics updateLoop="independent" />` will make the physics simulation run in it's own `requestAnimationFrame` loop, and call `invalidate` on the canvas only when there are active (moving) bodies.
|
846
|
+
|
847
|
+
```tsx
|
848
|
+
<Canvas frameloop="demand">
|
849
|
+
<Physics updateLoop="independent">...</Physics>
|
850
|
+
</Canvas>
|
851
|
+
```
|