@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.
@@ -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(body => {
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
- }, children);
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(body => {
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
- }, children);
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 { useThree, useFrame } from '@react-three/fiber';
4
- import React, { useRef, useEffect, useMemo, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
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(body => {
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
- }, children);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.14.0-rc.1",
3
+ "version": "0.14.0-rc.3",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
package/readme.md CHANGED
@@ -838,4 +838,14 @@ step(1 / 60);
838
838
  ```
839
839
 
840
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.
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
+ ```