@react-three/rapier 1.0.0-canary.2 → 1.0.1

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.
@@ -115,6 +115,43 @@ export interface PhysicsProps {
115
115
  * @defaultValue [0, -9.81, 0]
116
116
  */
117
117
  gravity?: Vector3Tuple;
118
+ /**
119
+ * The maximum velocity iterations the velocity-based constraint solver can make to attempt
120
+ * to remove the energy introduced by constraint stabilization.
121
+ *
122
+ * @defaultValue 1
123
+ */
124
+ maxStabilizationIterations?: number;
125
+ /**
126
+ * The maximum velocity iterations the velocity-based friction constraint solver can make.
127
+ *
128
+ * The greater this value is, the most realistic friction will be.
129
+ * However a greater number of iterations is more computationally intensive.
130
+ *
131
+ * @defaultValue 8
132
+ */
133
+ maxVelocityFrictionIterations?: number;
134
+ /**
135
+ * The maximum velocity iterations the velocity-based force constraint solver can make.
136
+ *
137
+ * The greater this value is, the most rigid and realistic the physics simulation will be.
138
+ * However a greater number of iterations is more computationally intensive.
139
+ *
140
+ * @defaultValue 4
141
+ */
142
+ maxVelocityIterations?: number;
143
+ /**
144
+ * The maximal distance separating two objects that will generate predictive contacts
145
+ *
146
+ * @defaultValue 0.002
147
+ *
148
+ */
149
+ predictionDistance?: number;
150
+ /**
151
+ * The Error Reduction Parameter in between 0 and 1, is the proportion of the positional error to be corrected at each time step
152
+ * @defaultValue 0.8
153
+ */
154
+ erp?: number;
118
155
  /**
119
156
  * Set the base automatic colliders for this physics world
120
157
  * All Meshes inside RigidBodies will generate a collider
@@ -664,6 +664,14 @@ const createSingletonProxy = createInstance => {
664
664
  }
665
665
 
666
666
  return Reflect.get(instance, prop);
667
+ },
668
+
669
+ set(target, prop, value) {
670
+ if (!instance) {
671
+ instance = createInstance();
672
+ }
673
+
674
+ return Reflect.set(instance, prop, value);
667
675
  }
668
676
 
669
677
  };
@@ -718,17 +726,23 @@ const importRapier = async () => {
718
726
  * The main physics component used to create a physics world.
719
727
  * @category Components
720
728
  */
721
- const Physics = ({
722
- colliders: _colliders = "cuboid",
723
- gravity: _gravity = [0, -9.81, 0],
724
- children,
725
- timeStep: _timeStep = 1 / 60,
726
- paused: _paused = false,
727
- interpolate: _interpolate = true,
728
- updatePriority,
729
- updateLoop: _updateLoop = "follow",
730
- debug: _debug = false
731
- }) => {
729
+ const Physics = props => {
730
+ const {
731
+ colliders = "cuboid",
732
+ children,
733
+ timeStep = 1 / 60,
734
+ paused = false,
735
+ interpolate = true,
736
+ updatePriority,
737
+ updateLoop = "follow",
738
+ debug = false,
739
+ gravity = [0, -9.81, 0],
740
+ maxStabilizationIterations = 1,
741
+ maxVelocityFrictionIterations = 8,
742
+ maxVelocityIterations = 4,
743
+ predictionDistance = 0.002,
744
+ erp = 0.8
745
+ } = props;
732
746
  const rapier = useAsset.useAsset(importRapier);
733
747
  const {
734
748
  invalidate
@@ -749,17 +763,22 @@ const Physics = ({
749
763
  const {
750
764
  proxy: worldProxy,
751
765
  reset: resetWorldProxy
752
- } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(_gravity))));
766
+ } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
753
767
  React.useEffect(() => {
754
768
  return () => {
755
769
  worldProxy.free();
756
770
  resetWorldProxy();
757
771
  };
758
- }, []); // Update gravity
772
+ }, []); // Update mutable props
759
773
 
760
774
  React.useEffect(() => {
761
- worldProxy.gravity = vectorArrayToVector3(_gravity);
762
- }, [_gravity]);
775
+ worldProxy.gravity = vectorArrayToVector3(gravity);
776
+ worldProxy.integrationParameters.maxStabilizationIterations = maxStabilizationIterations;
777
+ worldProxy.integrationParameters.maxVelocityFrictionIterations = maxVelocityFrictionIterations;
778
+ worldProxy.integrationParameters.maxVelocityIterations = maxVelocityIterations;
779
+ worldProxy.integrationParameters.predictionDistance = predictionDistance;
780
+ worldProxy.integrationParameters.erp = erp;
781
+ }, [worldProxy, ...gravity, maxStabilizationIterations, maxVelocityIterations, maxVelocityFrictionIterations, predictionDistance, erp]);
763
782
  const getSourceFromColliderHandle = React.useCallback(handle => {
764
783
  var _collider$parent;
765
784
 
@@ -793,39 +812,38 @@ const Physics = ({
793
812
  /* Check if the timestep is supposed to be variable. We'll do this here
794
813
  once so we don't have to string-check every frame. */
795
814
 
796
- const timeStepVariable = _timeStep === "vary";
815
+ const timeStepVariable = timeStep === "vary";
797
816
  /**
798
817
  * Fixed timeStep simulation progression
799
818
  * @see https://gafferongames.com/post/fix_your_timestep/
800
819
  */
801
820
 
802
- const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
821
+ const clampedDelta = three.MathUtils.clamp(dt, 0, 0.5);
803
822
 
804
- const stepWorld = () => {
823
+ const stepWorld = delta => {
805
824
  // Trigger beforeStep callbacks
806
825
  beforeStepCallbacks.forEach(callback => {
807
- callback.current(worldProxy);
826
+ callback.current(world);
808
827
  });
828
+ world.timestep = delta;
809
829
  world.step(eventQueue); // Trigger afterStep callbacks
810
830
 
811
831
  afterStepCallbacks.forEach(callback => {
812
- callback.current(worldProxy);
832
+ callback.current(world);
813
833
  });
814
834
  };
815
835
 
816
836
  if (timeStepVariable) {
817
- world.timestep = clampedDelta;
818
- stepWorld();
837
+ stepWorld(clampedDelta);
819
838
  } else {
820
- world.timestep = _timeStep; // don't step time forwards if paused
839
+ // don't step time forwards if paused
821
840
  // Increase accumulator
822
-
823
841
  steppingState.accumulator += clampedDelta;
824
842
 
825
- while (steppingState.accumulator >= _timeStep) {
843
+ while (steppingState.accumulator >= timeStep) {
826
844
  // Set up previous state
827
845
  // needed for accurate interpolations if the world steps more than once
828
- if (_interpolate) {
846
+ if (interpolate) {
829
847
  steppingState.previousState = {};
830
848
  world.forEachRigidBody(body => {
831
849
  steppingState.previousState[body.handle] = {
@@ -835,12 +853,12 @@ const Physics = ({
835
853
  });
836
854
  }
837
855
 
838
- stepWorld();
839
- steppingState.accumulator -= _timeStep;
856
+ stepWorld(timeStep);
857
+ steppingState.accumulator -= timeStep;
840
858
  }
841
859
  }
842
860
 
843
- const interpolationAlpha = timeStepVariable || !_interpolate || _paused ? 1 : steppingState.accumulator / _timeStep; // Update meshes
861
+ const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
844
862
 
845
863
  rigidBodyStates.forEach((state, handle) => {
846
864
  const rigidBody = world.getRigidBody(handle);
@@ -996,13 +1014,13 @@ const Physics = ({
996
1014
  world.forEachActiveRigidBody(() => {
997
1015
  invalidate();
998
1016
  });
999
- }, [_paused, _timeStep, _interpolate]);
1017
+ }, [paused, timeStep, interpolate, worldProxy]);
1000
1018
  const context = React.useMemo(() => ({
1001
1019
  rapier,
1002
1020
  world: worldProxy,
1003
1021
  physicsOptions: {
1004
- colliders: _colliders,
1005
- gravity: _gravity
1022
+ colliders,
1023
+ gravity
1006
1024
  },
1007
1025
  rigidBodyStates,
1008
1026
  colliderStates,
@@ -1010,22 +1028,22 @@ const Physics = ({
1010
1028
  colliderEvents,
1011
1029
  beforeStepCallbacks,
1012
1030
  afterStepCallbacks,
1013
- isPaused: _paused,
1014
- isDebug: _debug,
1031
+ isPaused: paused,
1032
+ isDebug: debug,
1015
1033
  step
1016
- }), [_paused, step, _debug, _colliders, _gravity]);
1034
+ }), [paused, step, debug, colliders, gravity]);
1017
1035
  const stepCallback = React.useCallback(delta => {
1018
- if (!_paused) {
1036
+ if (!paused) {
1019
1037
  step(delta);
1020
1038
  }
1021
- }, [_paused, step]);
1039
+ }, [paused, step]);
1022
1040
  return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
1023
1041
  value: context
1024
1042
  }, /*#__PURE__*/React__default["default"].createElement(FrameStepper$1, {
1025
1043
  onStep: stepCallback,
1026
- type: _updateLoop,
1044
+ type: updateLoop,
1027
1045
  updatePriority: updatePriority
1028
- }), _debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
1046
+ }), debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
1029
1047
  };
1030
1048
 
1031
1049
  function _extends() {
@@ -1171,7 +1189,9 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
1171
1189
  colliderRef.current = collider;
1172
1190
  return collider;
1173
1191
  }, collider => {
1174
- world.removeCollider(collider, true);
1192
+ if (world.getCollider(collider.handle)) {
1193
+ world.removeCollider(collider, true);
1194
+ }
1175
1195
  }, [...immutablePropArray, rigidBodyContext]);
1176
1196
  React.useEffect(() => {
1177
1197
  const collider = getInstance();
@@ -1507,7 +1527,9 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1507
1527
  rigidBodyRef.current = rigidBody;
1508
1528
  return rigidBody;
1509
1529
  }, rigidBody => {
1510
- world.removeRigidBody(rigidBody);
1530
+ if (world.getRigidBody(rigidBody.handle)) {
1531
+ world.removeRigidBody(rigidBody);
1532
+ }
1511
1533
  }, immutablePropArray); // Only provide a object state after the ref has been set
1512
1534
 
1513
1535
  React.useEffect(() => {
@@ -1674,14 +1696,16 @@ const useImpulseJoint = (body1, body2, params) => {
1674
1696
  useImperativeInstance(() => {
1675
1697
  if (body1.current && body2.current) {
1676
1698
  const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
1677
- jointRef.current = newJoint; // console.log(body1.current, body2.current, newJoint);
1678
-
1699
+ jointRef.current = newJoint;
1679
1700
  return newJoint;
1680
1701
  }
1681
1702
  }, joint => {
1682
1703
  if (joint) {
1683
1704
  jointRef.current = undefined;
1684
- world.removeImpulseJoint(joint, true);
1705
+
1706
+ if (world.getImpulseJoint(joint.handle)) {
1707
+ world.removeImpulseJoint(joint, true);
1708
+ }
1685
1709
  }
1686
1710
  }, []);
1687
1711
  return jointRef;
@@ -664,6 +664,14 @@ const createSingletonProxy = createInstance => {
664
664
  }
665
665
 
666
666
  return Reflect.get(instance, prop);
667
+ },
668
+
669
+ set(target, prop, value) {
670
+ if (!instance) {
671
+ instance = createInstance();
672
+ }
673
+
674
+ return Reflect.set(instance, prop, value);
667
675
  }
668
676
 
669
677
  };
@@ -718,17 +726,23 @@ const importRapier = async () => {
718
726
  * The main physics component used to create a physics world.
719
727
  * @category Components
720
728
  */
721
- const Physics = ({
722
- colliders: _colliders = "cuboid",
723
- gravity: _gravity = [0, -9.81, 0],
724
- children,
725
- timeStep: _timeStep = 1 / 60,
726
- paused: _paused = false,
727
- interpolate: _interpolate = true,
728
- updatePriority,
729
- updateLoop: _updateLoop = "follow",
730
- debug: _debug = false
731
- }) => {
729
+ const Physics = props => {
730
+ const {
731
+ colliders = "cuboid",
732
+ children,
733
+ timeStep = 1 / 60,
734
+ paused = false,
735
+ interpolate = true,
736
+ updatePriority,
737
+ updateLoop = "follow",
738
+ debug = false,
739
+ gravity = [0, -9.81, 0],
740
+ maxStabilizationIterations = 1,
741
+ maxVelocityFrictionIterations = 8,
742
+ maxVelocityIterations = 4,
743
+ predictionDistance = 0.002,
744
+ erp = 0.8
745
+ } = props;
732
746
  const rapier = useAsset.useAsset(importRapier);
733
747
  const {
734
748
  invalidate
@@ -749,17 +763,22 @@ const Physics = ({
749
763
  const {
750
764
  proxy: worldProxy,
751
765
  reset: resetWorldProxy
752
- } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(_gravity))));
766
+ } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
753
767
  React.useEffect(() => {
754
768
  return () => {
755
769
  worldProxy.free();
756
770
  resetWorldProxy();
757
771
  };
758
- }, []); // Update gravity
772
+ }, []); // Update mutable props
759
773
 
760
774
  React.useEffect(() => {
761
- worldProxy.gravity = vectorArrayToVector3(_gravity);
762
- }, [_gravity]);
775
+ worldProxy.gravity = vectorArrayToVector3(gravity);
776
+ worldProxy.integrationParameters.maxStabilizationIterations = maxStabilizationIterations;
777
+ worldProxy.integrationParameters.maxVelocityFrictionIterations = maxVelocityFrictionIterations;
778
+ worldProxy.integrationParameters.maxVelocityIterations = maxVelocityIterations;
779
+ worldProxy.integrationParameters.predictionDistance = predictionDistance;
780
+ worldProxy.integrationParameters.erp = erp;
781
+ }, [worldProxy, ...gravity, maxStabilizationIterations, maxVelocityIterations, maxVelocityFrictionIterations, predictionDistance, erp]);
763
782
  const getSourceFromColliderHandle = React.useCallback(handle => {
764
783
  var _collider$parent;
765
784
 
@@ -793,39 +812,38 @@ const Physics = ({
793
812
  /* Check if the timestep is supposed to be variable. We'll do this here
794
813
  once so we don't have to string-check every frame. */
795
814
 
796
- const timeStepVariable = _timeStep === "vary";
815
+ const timeStepVariable = timeStep === "vary";
797
816
  /**
798
817
  * Fixed timeStep simulation progression
799
818
  * @see https://gafferongames.com/post/fix_your_timestep/
800
819
  */
801
820
 
802
- const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
821
+ const clampedDelta = three.MathUtils.clamp(dt, 0, 0.5);
803
822
 
804
- const stepWorld = () => {
823
+ const stepWorld = delta => {
805
824
  // Trigger beforeStep callbacks
806
825
  beforeStepCallbacks.forEach(callback => {
807
- callback.current(worldProxy);
826
+ callback.current(world);
808
827
  });
828
+ world.timestep = delta;
809
829
  world.step(eventQueue); // Trigger afterStep callbacks
810
830
 
811
831
  afterStepCallbacks.forEach(callback => {
812
- callback.current(worldProxy);
832
+ callback.current(world);
813
833
  });
814
834
  };
815
835
 
816
836
  if (timeStepVariable) {
817
- world.timestep = clampedDelta;
818
- stepWorld();
837
+ stepWorld(clampedDelta);
819
838
  } else {
820
- world.timestep = _timeStep; // don't step time forwards if paused
839
+ // don't step time forwards if paused
821
840
  // Increase accumulator
822
-
823
841
  steppingState.accumulator += clampedDelta;
824
842
 
825
- while (steppingState.accumulator >= _timeStep) {
843
+ while (steppingState.accumulator >= timeStep) {
826
844
  // Set up previous state
827
845
  // needed for accurate interpolations if the world steps more than once
828
- if (_interpolate) {
846
+ if (interpolate) {
829
847
  steppingState.previousState = {};
830
848
  world.forEachRigidBody(body => {
831
849
  steppingState.previousState[body.handle] = {
@@ -835,12 +853,12 @@ const Physics = ({
835
853
  });
836
854
  }
837
855
 
838
- stepWorld();
839
- steppingState.accumulator -= _timeStep;
856
+ stepWorld(timeStep);
857
+ steppingState.accumulator -= timeStep;
840
858
  }
841
859
  }
842
860
 
843
- const interpolationAlpha = timeStepVariable || !_interpolate || _paused ? 1 : steppingState.accumulator / _timeStep; // Update meshes
861
+ const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
844
862
 
845
863
  rigidBodyStates.forEach((state, handle) => {
846
864
  const rigidBody = world.getRigidBody(handle);
@@ -996,13 +1014,13 @@ const Physics = ({
996
1014
  world.forEachActiveRigidBody(() => {
997
1015
  invalidate();
998
1016
  });
999
- }, [_paused, _timeStep, _interpolate]);
1017
+ }, [paused, timeStep, interpolate, worldProxy]);
1000
1018
  const context = React.useMemo(() => ({
1001
1019
  rapier,
1002
1020
  world: worldProxy,
1003
1021
  physicsOptions: {
1004
- colliders: _colliders,
1005
- gravity: _gravity
1022
+ colliders,
1023
+ gravity
1006
1024
  },
1007
1025
  rigidBodyStates,
1008
1026
  colliderStates,
@@ -1010,22 +1028,22 @@ const Physics = ({
1010
1028
  colliderEvents,
1011
1029
  beforeStepCallbacks,
1012
1030
  afterStepCallbacks,
1013
- isPaused: _paused,
1014
- isDebug: _debug,
1031
+ isPaused: paused,
1032
+ isDebug: debug,
1015
1033
  step
1016
- }), [_paused, step, _debug, _colliders, _gravity]);
1034
+ }), [paused, step, debug, colliders, gravity]);
1017
1035
  const stepCallback = React.useCallback(delta => {
1018
- if (!_paused) {
1036
+ if (!paused) {
1019
1037
  step(delta);
1020
1038
  }
1021
- }, [_paused, step]);
1039
+ }, [paused, step]);
1022
1040
  return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
1023
1041
  value: context
1024
1042
  }, /*#__PURE__*/React__default["default"].createElement(FrameStepper$1, {
1025
1043
  onStep: stepCallback,
1026
- type: _updateLoop,
1044
+ type: updateLoop,
1027
1045
  updatePriority: updatePriority
1028
- }), _debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
1046
+ }), debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
1029
1047
  };
1030
1048
 
1031
1049
  function _extends() {
@@ -1171,7 +1189,9 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
1171
1189
  colliderRef.current = collider;
1172
1190
  return collider;
1173
1191
  }, collider => {
1174
- world.removeCollider(collider, true);
1192
+ if (world.getCollider(collider.handle)) {
1193
+ world.removeCollider(collider, true);
1194
+ }
1175
1195
  }, [...immutablePropArray, rigidBodyContext]);
1176
1196
  React.useEffect(() => {
1177
1197
  const collider = getInstance();
@@ -1507,7 +1527,9 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1507
1527
  rigidBodyRef.current = rigidBody;
1508
1528
  return rigidBody;
1509
1529
  }, rigidBody => {
1510
- world.removeRigidBody(rigidBody);
1530
+ if (world.getRigidBody(rigidBody.handle)) {
1531
+ world.removeRigidBody(rigidBody);
1532
+ }
1511
1533
  }, immutablePropArray); // Only provide a object state after the ref has been set
1512
1534
 
1513
1535
  React.useEffect(() => {
@@ -1674,14 +1696,16 @@ const useImpulseJoint = (body1, body2, params) => {
1674
1696
  useImperativeInstance(() => {
1675
1697
  if (body1.current && body2.current) {
1676
1698
  const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
1677
- jointRef.current = newJoint; // console.log(body1.current, body2.current, newJoint);
1678
-
1699
+ jointRef.current = newJoint;
1679
1700
  return newJoint;
1680
1701
  }
1681
1702
  }, joint => {
1682
1703
  if (joint) {
1683
1704
  jointRef.current = undefined;
1684
- world.removeImpulseJoint(joint, true);
1705
+
1706
+ if (world.getImpulseJoint(joint.handle)) {
1707
+ world.removeImpulseJoint(joint, true);
1708
+ }
1685
1709
  }
1686
1710
  }, []);
1687
1711
  return jointRef;
@@ -639,6 +639,14 @@ const createSingletonProxy = createInstance => {
639
639
  }
640
640
 
641
641
  return Reflect.get(instance, prop);
642
+ },
643
+
644
+ set(target, prop, value) {
645
+ if (!instance) {
646
+ instance = createInstance();
647
+ }
648
+
649
+ return Reflect.set(instance, prop, value);
642
650
  }
643
651
 
644
652
  };
@@ -693,17 +701,23 @@ const importRapier = async () => {
693
701
  * The main physics component used to create a physics world.
694
702
  * @category Components
695
703
  */
696
- const Physics = ({
697
- colliders: _colliders = "cuboid",
698
- gravity: _gravity = [0, -9.81, 0],
699
- children,
700
- timeStep: _timeStep = 1 / 60,
701
- paused: _paused = false,
702
- interpolate: _interpolate = true,
703
- updatePriority,
704
- updateLoop: _updateLoop = "follow",
705
- debug: _debug = false
706
- }) => {
704
+ const Physics = props => {
705
+ const {
706
+ colliders = "cuboid",
707
+ children,
708
+ timeStep = 1 / 60,
709
+ paused = false,
710
+ interpolate = true,
711
+ updatePriority,
712
+ updateLoop = "follow",
713
+ debug = false,
714
+ gravity = [0, -9.81, 0],
715
+ maxStabilizationIterations = 1,
716
+ maxVelocityFrictionIterations = 8,
717
+ maxVelocityIterations = 4,
718
+ predictionDistance = 0.002,
719
+ erp = 0.8
720
+ } = props;
707
721
  const rapier = useAsset(importRapier);
708
722
  const {
709
723
  invalidate
@@ -724,17 +738,22 @@ const Physics = ({
724
738
  const {
725
739
  proxy: worldProxy,
726
740
  reset: resetWorldProxy
727
- } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(_gravity))));
741
+ } = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
728
742
  useEffect(() => {
729
743
  return () => {
730
744
  worldProxy.free();
731
745
  resetWorldProxy();
732
746
  };
733
- }, []); // Update gravity
747
+ }, []); // Update mutable props
734
748
 
735
749
  useEffect(() => {
736
- worldProxy.gravity = vectorArrayToVector3(_gravity);
737
- }, [_gravity]);
750
+ worldProxy.gravity = vectorArrayToVector3(gravity);
751
+ worldProxy.integrationParameters.maxStabilizationIterations = maxStabilizationIterations;
752
+ worldProxy.integrationParameters.maxVelocityFrictionIterations = maxVelocityFrictionIterations;
753
+ worldProxy.integrationParameters.maxVelocityIterations = maxVelocityIterations;
754
+ worldProxy.integrationParameters.predictionDistance = predictionDistance;
755
+ worldProxy.integrationParameters.erp = erp;
756
+ }, [worldProxy, ...gravity, maxStabilizationIterations, maxVelocityIterations, maxVelocityFrictionIterations, predictionDistance, erp]);
738
757
  const getSourceFromColliderHandle = useCallback(handle => {
739
758
  var _collider$parent;
740
759
 
@@ -768,39 +787,38 @@ const Physics = ({
768
787
  /* Check if the timestep is supposed to be variable. We'll do this here
769
788
  once so we don't have to string-check every frame. */
770
789
 
771
- const timeStepVariable = _timeStep === "vary";
790
+ const timeStepVariable = timeStep === "vary";
772
791
  /**
773
792
  * Fixed timeStep simulation progression
774
793
  * @see https://gafferongames.com/post/fix_your_timestep/
775
794
  */
776
795
 
777
- const clampedDelta = MathUtils.clamp(dt, 0, 0.2);
796
+ const clampedDelta = MathUtils.clamp(dt, 0, 0.5);
778
797
 
779
- const stepWorld = () => {
798
+ const stepWorld = delta => {
780
799
  // Trigger beforeStep callbacks
781
800
  beforeStepCallbacks.forEach(callback => {
782
- callback.current(worldProxy);
801
+ callback.current(world);
783
802
  });
803
+ world.timestep = delta;
784
804
  world.step(eventQueue); // Trigger afterStep callbacks
785
805
 
786
806
  afterStepCallbacks.forEach(callback => {
787
- callback.current(worldProxy);
807
+ callback.current(world);
788
808
  });
789
809
  };
790
810
 
791
811
  if (timeStepVariable) {
792
- world.timestep = clampedDelta;
793
- stepWorld();
812
+ stepWorld(clampedDelta);
794
813
  } else {
795
- world.timestep = _timeStep; // don't step time forwards if paused
814
+ // don't step time forwards if paused
796
815
  // Increase accumulator
797
-
798
816
  steppingState.accumulator += clampedDelta;
799
817
 
800
- while (steppingState.accumulator >= _timeStep) {
818
+ while (steppingState.accumulator >= timeStep) {
801
819
  // Set up previous state
802
820
  // needed for accurate interpolations if the world steps more than once
803
- if (_interpolate) {
821
+ if (interpolate) {
804
822
  steppingState.previousState = {};
805
823
  world.forEachRigidBody(body => {
806
824
  steppingState.previousState[body.handle] = {
@@ -810,12 +828,12 @@ const Physics = ({
810
828
  });
811
829
  }
812
830
 
813
- stepWorld();
814
- steppingState.accumulator -= _timeStep;
831
+ stepWorld(timeStep);
832
+ steppingState.accumulator -= timeStep;
815
833
  }
816
834
  }
817
835
 
818
- const interpolationAlpha = timeStepVariable || !_interpolate || _paused ? 1 : steppingState.accumulator / _timeStep; // Update meshes
836
+ const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
819
837
 
820
838
  rigidBodyStates.forEach((state, handle) => {
821
839
  const rigidBody = world.getRigidBody(handle);
@@ -971,13 +989,13 @@ const Physics = ({
971
989
  world.forEachActiveRigidBody(() => {
972
990
  invalidate();
973
991
  });
974
- }, [_paused, _timeStep, _interpolate]);
992
+ }, [paused, timeStep, interpolate, worldProxy]);
975
993
  const context = useMemo(() => ({
976
994
  rapier,
977
995
  world: worldProxy,
978
996
  physicsOptions: {
979
- colliders: _colliders,
980
- gravity: _gravity
997
+ colliders,
998
+ gravity
981
999
  },
982
1000
  rigidBodyStates,
983
1001
  colliderStates,
@@ -985,22 +1003,22 @@ const Physics = ({
985
1003
  colliderEvents,
986
1004
  beforeStepCallbacks,
987
1005
  afterStepCallbacks,
988
- isPaused: _paused,
989
- isDebug: _debug,
1006
+ isPaused: paused,
1007
+ isDebug: debug,
990
1008
  step
991
- }), [_paused, step, _debug, _colliders, _gravity]);
1009
+ }), [paused, step, debug, colliders, gravity]);
992
1010
  const stepCallback = useCallback(delta => {
993
- if (!_paused) {
1011
+ if (!paused) {
994
1012
  step(delta);
995
1013
  }
996
- }, [_paused, step]);
1014
+ }, [paused, step]);
997
1015
  return /*#__PURE__*/React.createElement(rapierContext.Provider, {
998
1016
  value: context
999
1017
  }, /*#__PURE__*/React.createElement(FrameStepper$1, {
1000
1018
  onStep: stepCallback,
1001
- type: _updateLoop,
1019
+ type: updateLoop,
1002
1020
  updatePriority: updatePriority
1003
- }), _debug && /*#__PURE__*/React.createElement(Debug, null), children);
1021
+ }), debug && /*#__PURE__*/React.createElement(Debug, null), children);
1004
1022
  };
1005
1023
 
1006
1024
  function _extends() {
@@ -1146,7 +1164,9 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
1146
1164
  colliderRef.current = collider;
1147
1165
  return collider;
1148
1166
  }, collider => {
1149
- world.removeCollider(collider, true);
1167
+ if (world.getCollider(collider.handle)) {
1168
+ world.removeCollider(collider, true);
1169
+ }
1150
1170
  }, [...immutablePropArray, rigidBodyContext]);
1151
1171
  useEffect(() => {
1152
1172
  const collider = getInstance();
@@ -1482,7 +1502,9 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
1482
1502
  rigidBodyRef.current = rigidBody;
1483
1503
  return rigidBody;
1484
1504
  }, rigidBody => {
1485
- world.removeRigidBody(rigidBody);
1505
+ if (world.getRigidBody(rigidBody.handle)) {
1506
+ world.removeRigidBody(rigidBody);
1507
+ }
1486
1508
  }, immutablePropArray); // Only provide a object state after the ref has been set
1487
1509
 
1488
1510
  useEffect(() => {
@@ -1649,14 +1671,16 @@ const useImpulseJoint = (body1, body2, params) => {
1649
1671
  useImperativeInstance(() => {
1650
1672
  if (body1.current && body2.current) {
1651
1673
  const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
1652
- jointRef.current = newJoint; // console.log(body1.current, body2.current, newJoint);
1653
-
1674
+ jointRef.current = newJoint;
1654
1675
  return newJoint;
1655
1676
  }
1656
1677
  }, joint => {
1657
1678
  if (joint) {
1658
1679
  jointRef.current = undefined;
1659
- world.removeImpulseJoint(joint, true);
1680
+
1681
+ if (world.getImpulseJoint(joint.handle)) {
1682
+ world.removeImpulseJoint(joint, true);
1683
+ }
1660
1684
  }
1661
1685
  }, []);
1662
1686
  return jointRef;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "1.0.0-canary.2",
3
+ "version": "1.0.1",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
@@ -17,11 +17,11 @@
17
17
  "@types/three": "0.139.0",
18
18
  "@vitejs/plugin-react": "^2.1.0",
19
19
  "@vitest/ui": "0.29.7",
20
- "happy-dom": "7.5.5",
20
+ "happy-dom": "9.19.2",
21
21
  "react": "18.2.0",
22
22
  "react-dom": "18.2.0",
23
23
  "three": "0.146.0",
24
- "vitest": "0.29.7"
24
+ "vitest": "0.31.1"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "@react-three/fiber": ">=8.9.0",
package/readme.md CHANGED
@@ -27,7 +27,7 @@ The goal of this library to is to provide a fast physics engine with minimal fri
27
27
  ```tsx
28
28
  import { Box, Torus } from "@react-three/drei";
29
29
  import { Canvas } from "@react-three/fiber";
30
- import { Physics, RigidBody, Debug, CuboidCollider } from "@react-three/rapier";
30
+ import { Physics, RigidBody, CuboidCollider } from "@react-three/rapier";
31
31
 
32
32
  const App = () => {
33
33
  return (