@react-three/rapier 1.0.0-canary.2 → 1.0.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.
@@ -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
|
@@ -718,17 +718,23 @@ const importRapier = async () => {
|
|
718
718
|
* The main physics component used to create a physics world.
|
719
719
|
* @category Components
|
720
720
|
*/
|
721
|
-
const Physics =
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
721
|
+
const Physics = props => {
|
722
|
+
const {
|
723
|
+
colliders = "cuboid",
|
724
|
+
children,
|
725
|
+
timeStep = 1 / 60,
|
726
|
+
paused = false,
|
727
|
+
interpolate = true,
|
728
|
+
updatePriority,
|
729
|
+
updateLoop = "follow",
|
730
|
+
debug = false,
|
731
|
+
gravity = [0, -9.81, 0],
|
732
|
+
maxStabilizationIterations = 1,
|
733
|
+
maxVelocityFrictionIterations = 8,
|
734
|
+
maxVelocityIterations = 4,
|
735
|
+
predictionDistance = 0.002,
|
736
|
+
erp = 0.8
|
737
|
+
} = props;
|
732
738
|
const rapier = useAsset.useAsset(importRapier);
|
733
739
|
const {
|
734
740
|
invalidate
|
@@ -749,17 +755,22 @@ const Physics = ({
|
|
749
755
|
const {
|
750
756
|
proxy: worldProxy,
|
751
757
|
reset: resetWorldProxy
|
752
|
-
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(
|
758
|
+
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
|
753
759
|
React.useEffect(() => {
|
754
760
|
return () => {
|
755
761
|
worldProxy.free();
|
756
762
|
resetWorldProxy();
|
757
763
|
};
|
758
|
-
}, []); // Update
|
764
|
+
}, []); // Update mutable props
|
759
765
|
|
760
766
|
React.useEffect(() => {
|
761
|
-
worldProxy.gravity = vectorArrayToVector3(
|
762
|
-
|
767
|
+
worldProxy.gravity = vectorArrayToVector3(gravity);
|
768
|
+
worldProxy.integrationParameters.maxStabilizationIterations = maxStabilizationIterations;
|
769
|
+
worldProxy.integrationParameters.maxVelocityFrictionIterations = maxVelocityFrictionIterations;
|
770
|
+
worldProxy.integrationParameters.maxVelocityIterations = maxVelocityIterations;
|
771
|
+
worldProxy.integrationParameters.predictionDistance = predictionDistance;
|
772
|
+
worldProxy.integrationParameters.erp = erp;
|
773
|
+
}, [worldProxy, ...gravity, maxStabilizationIterations, maxVelocityIterations, maxVelocityFrictionIterations, predictionDistance, erp]);
|
763
774
|
const getSourceFromColliderHandle = React.useCallback(handle => {
|
764
775
|
var _collider$parent;
|
765
776
|
|
@@ -793,7 +804,7 @@ const Physics = ({
|
|
793
804
|
/* Check if the timestep is supposed to be variable. We'll do this here
|
794
805
|
once so we don't have to string-check every frame. */
|
795
806
|
|
796
|
-
const timeStepVariable =
|
807
|
+
const timeStepVariable = timeStep === "vary";
|
797
808
|
/**
|
798
809
|
* Fixed timeStep simulation progression
|
799
810
|
* @see https://gafferongames.com/post/fix_your_timestep/
|
@@ -817,15 +828,15 @@ const Physics = ({
|
|
817
828
|
world.timestep = clampedDelta;
|
818
829
|
stepWorld();
|
819
830
|
} else {
|
820
|
-
world.timestep =
|
831
|
+
world.timestep = timeStep; // don't step time forwards if paused
|
821
832
|
// Increase accumulator
|
822
833
|
|
823
834
|
steppingState.accumulator += clampedDelta;
|
824
835
|
|
825
|
-
while (steppingState.accumulator >=
|
836
|
+
while (steppingState.accumulator >= timeStep) {
|
826
837
|
// Set up previous state
|
827
838
|
// needed for accurate interpolations if the world steps more than once
|
828
|
-
if (
|
839
|
+
if (interpolate) {
|
829
840
|
steppingState.previousState = {};
|
830
841
|
world.forEachRigidBody(body => {
|
831
842
|
steppingState.previousState[body.handle] = {
|
@@ -836,11 +847,11 @@ const Physics = ({
|
|
836
847
|
}
|
837
848
|
|
838
849
|
stepWorld();
|
839
|
-
steppingState.accumulator -=
|
850
|
+
steppingState.accumulator -= timeStep;
|
840
851
|
}
|
841
852
|
}
|
842
853
|
|
843
|
-
const interpolationAlpha = timeStepVariable || !
|
854
|
+
const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
|
844
855
|
|
845
856
|
rigidBodyStates.forEach((state, handle) => {
|
846
857
|
const rigidBody = world.getRigidBody(handle);
|
@@ -996,13 +1007,13 @@ const Physics = ({
|
|
996
1007
|
world.forEachActiveRigidBody(() => {
|
997
1008
|
invalidate();
|
998
1009
|
});
|
999
|
-
}, [
|
1010
|
+
}, [paused, timeStep, interpolate]);
|
1000
1011
|
const context = React.useMemo(() => ({
|
1001
1012
|
rapier,
|
1002
1013
|
world: worldProxy,
|
1003
1014
|
physicsOptions: {
|
1004
|
-
colliders
|
1005
|
-
gravity
|
1015
|
+
colliders,
|
1016
|
+
gravity
|
1006
1017
|
},
|
1007
1018
|
rigidBodyStates,
|
1008
1019
|
colliderStates,
|
@@ -1010,22 +1021,22 @@ const Physics = ({
|
|
1010
1021
|
colliderEvents,
|
1011
1022
|
beforeStepCallbacks,
|
1012
1023
|
afterStepCallbacks,
|
1013
|
-
isPaused:
|
1014
|
-
isDebug:
|
1024
|
+
isPaused: paused,
|
1025
|
+
isDebug: debug,
|
1015
1026
|
step
|
1016
|
-
}), [
|
1027
|
+
}), [paused, step, debug, colliders, gravity]);
|
1017
1028
|
const stepCallback = React.useCallback(delta => {
|
1018
|
-
if (!
|
1029
|
+
if (!paused) {
|
1019
1030
|
step(delta);
|
1020
1031
|
}
|
1021
|
-
}, [
|
1032
|
+
}, [paused, step]);
|
1022
1033
|
return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
|
1023
1034
|
value: context
|
1024
1035
|
}, /*#__PURE__*/React__default["default"].createElement(FrameStepper$1, {
|
1025
1036
|
onStep: stepCallback,
|
1026
|
-
type:
|
1037
|
+
type: updateLoop,
|
1027
1038
|
updatePriority: updatePriority
|
1028
|
-
}),
|
1039
|
+
}), debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
|
1029
1040
|
};
|
1030
1041
|
|
1031
1042
|
function _extends() {
|
@@ -1171,7 +1182,9 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1171
1182
|
colliderRef.current = collider;
|
1172
1183
|
return collider;
|
1173
1184
|
}, collider => {
|
1174
|
-
world.
|
1185
|
+
if (world.getCollider(collider.handle)) {
|
1186
|
+
world.removeCollider(collider, true);
|
1187
|
+
}
|
1175
1188
|
}, [...immutablePropArray, rigidBodyContext]);
|
1176
1189
|
React.useEffect(() => {
|
1177
1190
|
const collider = getInstance();
|
@@ -1507,7 +1520,9 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1507
1520
|
rigidBodyRef.current = rigidBody;
|
1508
1521
|
return rigidBody;
|
1509
1522
|
}, rigidBody => {
|
1510
|
-
world.
|
1523
|
+
if (world.getRigidBody(rigidBody.handle)) {
|
1524
|
+
world.removeRigidBody(rigidBody);
|
1525
|
+
}
|
1511
1526
|
}, immutablePropArray); // Only provide a object state after the ref has been set
|
1512
1527
|
|
1513
1528
|
React.useEffect(() => {
|
@@ -1674,14 +1689,16 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1674
1689
|
useImperativeInstance(() => {
|
1675
1690
|
if (body1.current && body2.current) {
|
1676
1691
|
const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
|
1677
|
-
jointRef.current = newJoint;
|
1678
|
-
|
1692
|
+
jointRef.current = newJoint;
|
1679
1693
|
return newJoint;
|
1680
1694
|
}
|
1681
1695
|
}, joint => {
|
1682
1696
|
if (joint) {
|
1683
1697
|
jointRef.current = undefined;
|
1684
|
-
|
1698
|
+
|
1699
|
+
if (world.getImpulseJoint(joint.handle)) {
|
1700
|
+
world.removeImpulseJoint(joint, true);
|
1701
|
+
}
|
1685
1702
|
}
|
1686
1703
|
}, []);
|
1687
1704
|
return jointRef;
|
@@ -718,17 +718,23 @@ const importRapier = async () => {
|
|
718
718
|
* The main physics component used to create a physics world.
|
719
719
|
* @category Components
|
720
720
|
*/
|
721
|
-
const Physics =
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
721
|
+
const Physics = props => {
|
722
|
+
const {
|
723
|
+
colliders = "cuboid",
|
724
|
+
children,
|
725
|
+
timeStep = 1 / 60,
|
726
|
+
paused = false,
|
727
|
+
interpolate = true,
|
728
|
+
updatePriority,
|
729
|
+
updateLoop = "follow",
|
730
|
+
debug = false,
|
731
|
+
gravity = [0, -9.81, 0],
|
732
|
+
maxStabilizationIterations = 1,
|
733
|
+
maxVelocityFrictionIterations = 8,
|
734
|
+
maxVelocityIterations = 4,
|
735
|
+
predictionDistance = 0.002,
|
736
|
+
erp = 0.8
|
737
|
+
} = props;
|
732
738
|
const rapier = useAsset.useAsset(importRapier);
|
733
739
|
const {
|
734
740
|
invalidate
|
@@ -749,17 +755,22 @@ const Physics = ({
|
|
749
755
|
const {
|
750
756
|
proxy: worldProxy,
|
751
757
|
reset: resetWorldProxy
|
752
|
-
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(
|
758
|
+
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
|
753
759
|
React.useEffect(() => {
|
754
760
|
return () => {
|
755
761
|
worldProxy.free();
|
756
762
|
resetWorldProxy();
|
757
763
|
};
|
758
|
-
}, []); // Update
|
764
|
+
}, []); // Update mutable props
|
759
765
|
|
760
766
|
React.useEffect(() => {
|
761
|
-
worldProxy.gravity = vectorArrayToVector3(
|
762
|
-
|
767
|
+
worldProxy.gravity = vectorArrayToVector3(gravity);
|
768
|
+
worldProxy.integrationParameters.maxStabilizationIterations = maxStabilizationIterations;
|
769
|
+
worldProxy.integrationParameters.maxVelocityFrictionIterations = maxVelocityFrictionIterations;
|
770
|
+
worldProxy.integrationParameters.maxVelocityIterations = maxVelocityIterations;
|
771
|
+
worldProxy.integrationParameters.predictionDistance = predictionDistance;
|
772
|
+
worldProxy.integrationParameters.erp = erp;
|
773
|
+
}, [worldProxy, ...gravity, maxStabilizationIterations, maxVelocityIterations, maxVelocityFrictionIterations, predictionDistance, erp]);
|
763
774
|
const getSourceFromColliderHandle = React.useCallback(handle => {
|
764
775
|
var _collider$parent;
|
765
776
|
|
@@ -793,7 +804,7 @@ const Physics = ({
|
|
793
804
|
/* Check if the timestep is supposed to be variable. We'll do this here
|
794
805
|
once so we don't have to string-check every frame. */
|
795
806
|
|
796
|
-
const timeStepVariable =
|
807
|
+
const timeStepVariable = timeStep === "vary";
|
797
808
|
/**
|
798
809
|
* Fixed timeStep simulation progression
|
799
810
|
* @see https://gafferongames.com/post/fix_your_timestep/
|
@@ -817,15 +828,15 @@ const Physics = ({
|
|
817
828
|
world.timestep = clampedDelta;
|
818
829
|
stepWorld();
|
819
830
|
} else {
|
820
|
-
world.timestep =
|
831
|
+
world.timestep = timeStep; // don't step time forwards if paused
|
821
832
|
// Increase accumulator
|
822
833
|
|
823
834
|
steppingState.accumulator += clampedDelta;
|
824
835
|
|
825
|
-
while (steppingState.accumulator >=
|
836
|
+
while (steppingState.accumulator >= timeStep) {
|
826
837
|
// Set up previous state
|
827
838
|
// needed for accurate interpolations if the world steps more than once
|
828
|
-
if (
|
839
|
+
if (interpolate) {
|
829
840
|
steppingState.previousState = {};
|
830
841
|
world.forEachRigidBody(body => {
|
831
842
|
steppingState.previousState[body.handle] = {
|
@@ -836,11 +847,11 @@ const Physics = ({
|
|
836
847
|
}
|
837
848
|
|
838
849
|
stepWorld();
|
839
|
-
steppingState.accumulator -=
|
850
|
+
steppingState.accumulator -= timeStep;
|
840
851
|
}
|
841
852
|
}
|
842
853
|
|
843
|
-
const interpolationAlpha = timeStepVariable || !
|
854
|
+
const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
|
844
855
|
|
845
856
|
rigidBodyStates.forEach((state, handle) => {
|
846
857
|
const rigidBody = world.getRigidBody(handle);
|
@@ -996,13 +1007,13 @@ const Physics = ({
|
|
996
1007
|
world.forEachActiveRigidBody(() => {
|
997
1008
|
invalidate();
|
998
1009
|
});
|
999
|
-
}, [
|
1010
|
+
}, [paused, timeStep, interpolate]);
|
1000
1011
|
const context = React.useMemo(() => ({
|
1001
1012
|
rapier,
|
1002
1013
|
world: worldProxy,
|
1003
1014
|
physicsOptions: {
|
1004
|
-
colliders
|
1005
|
-
gravity
|
1015
|
+
colliders,
|
1016
|
+
gravity
|
1006
1017
|
},
|
1007
1018
|
rigidBodyStates,
|
1008
1019
|
colliderStates,
|
@@ -1010,22 +1021,22 @@ const Physics = ({
|
|
1010
1021
|
colliderEvents,
|
1011
1022
|
beforeStepCallbacks,
|
1012
1023
|
afterStepCallbacks,
|
1013
|
-
isPaused:
|
1014
|
-
isDebug:
|
1024
|
+
isPaused: paused,
|
1025
|
+
isDebug: debug,
|
1015
1026
|
step
|
1016
|
-
}), [
|
1027
|
+
}), [paused, step, debug, colliders, gravity]);
|
1017
1028
|
const stepCallback = React.useCallback(delta => {
|
1018
|
-
if (!
|
1029
|
+
if (!paused) {
|
1019
1030
|
step(delta);
|
1020
1031
|
}
|
1021
|
-
}, [
|
1032
|
+
}, [paused, step]);
|
1022
1033
|
return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
|
1023
1034
|
value: context
|
1024
1035
|
}, /*#__PURE__*/React__default["default"].createElement(FrameStepper$1, {
|
1025
1036
|
onStep: stepCallback,
|
1026
|
-
type:
|
1037
|
+
type: updateLoop,
|
1027
1038
|
updatePriority: updatePriority
|
1028
|
-
}),
|
1039
|
+
}), debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
|
1029
1040
|
};
|
1030
1041
|
|
1031
1042
|
function _extends() {
|
@@ -1171,7 +1182,9 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
|
|
1171
1182
|
colliderRef.current = collider;
|
1172
1183
|
return collider;
|
1173
1184
|
}, collider => {
|
1174
|
-
world.
|
1185
|
+
if (world.getCollider(collider.handle)) {
|
1186
|
+
world.removeCollider(collider, true);
|
1187
|
+
}
|
1175
1188
|
}, [...immutablePropArray, rigidBodyContext]);
|
1176
1189
|
React.useEffect(() => {
|
1177
1190
|
const collider = getInstance();
|
@@ -1507,7 +1520,9 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1507
1520
|
rigidBodyRef.current = rigidBody;
|
1508
1521
|
return rigidBody;
|
1509
1522
|
}, rigidBody => {
|
1510
|
-
world.
|
1523
|
+
if (world.getRigidBody(rigidBody.handle)) {
|
1524
|
+
world.removeRigidBody(rigidBody);
|
1525
|
+
}
|
1511
1526
|
}, immutablePropArray); // Only provide a object state after the ref has been set
|
1512
1527
|
|
1513
1528
|
React.useEffect(() => {
|
@@ -1674,14 +1689,16 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1674
1689
|
useImperativeInstance(() => {
|
1675
1690
|
if (body1.current && body2.current) {
|
1676
1691
|
const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
|
1677
|
-
jointRef.current = newJoint;
|
1678
|
-
|
1692
|
+
jointRef.current = newJoint;
|
1679
1693
|
return newJoint;
|
1680
1694
|
}
|
1681
1695
|
}, joint => {
|
1682
1696
|
if (joint) {
|
1683
1697
|
jointRef.current = undefined;
|
1684
|
-
|
1698
|
+
|
1699
|
+
if (world.getImpulseJoint(joint.handle)) {
|
1700
|
+
world.removeImpulseJoint(joint, true);
|
1701
|
+
}
|
1685
1702
|
}
|
1686
1703
|
}, []);
|
1687
1704
|
return jointRef;
|
@@ -693,17 +693,23 @@ const importRapier = async () => {
|
|
693
693
|
* The main physics component used to create a physics world.
|
694
694
|
* @category Components
|
695
695
|
*/
|
696
|
-
const Physics =
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
696
|
+
const Physics = props => {
|
697
|
+
const {
|
698
|
+
colliders = "cuboid",
|
699
|
+
children,
|
700
|
+
timeStep = 1 / 60,
|
701
|
+
paused = false,
|
702
|
+
interpolate = true,
|
703
|
+
updatePriority,
|
704
|
+
updateLoop = "follow",
|
705
|
+
debug = false,
|
706
|
+
gravity = [0, -9.81, 0],
|
707
|
+
maxStabilizationIterations = 1,
|
708
|
+
maxVelocityFrictionIterations = 8,
|
709
|
+
maxVelocityIterations = 4,
|
710
|
+
predictionDistance = 0.002,
|
711
|
+
erp = 0.8
|
712
|
+
} = props;
|
707
713
|
const rapier = useAsset(importRapier);
|
708
714
|
const {
|
709
715
|
invalidate
|
@@ -724,17 +730,22 @@ const Physics = ({
|
|
724
730
|
const {
|
725
731
|
proxy: worldProxy,
|
726
732
|
reset: resetWorldProxy
|
727
|
-
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(
|
733
|
+
} = useConst(() => createSingletonProxy(() => new rapier.World(vectorArrayToVector3(gravity))));
|
728
734
|
useEffect(() => {
|
729
735
|
return () => {
|
730
736
|
worldProxy.free();
|
731
737
|
resetWorldProxy();
|
732
738
|
};
|
733
|
-
}, []); // Update
|
739
|
+
}, []); // Update mutable props
|
734
740
|
|
735
741
|
useEffect(() => {
|
736
|
-
worldProxy.gravity = vectorArrayToVector3(
|
737
|
-
|
742
|
+
worldProxy.gravity = vectorArrayToVector3(gravity);
|
743
|
+
worldProxy.integrationParameters.maxStabilizationIterations = maxStabilizationIterations;
|
744
|
+
worldProxy.integrationParameters.maxVelocityFrictionIterations = maxVelocityFrictionIterations;
|
745
|
+
worldProxy.integrationParameters.maxVelocityIterations = maxVelocityIterations;
|
746
|
+
worldProxy.integrationParameters.predictionDistance = predictionDistance;
|
747
|
+
worldProxy.integrationParameters.erp = erp;
|
748
|
+
}, [worldProxy, ...gravity, maxStabilizationIterations, maxVelocityIterations, maxVelocityFrictionIterations, predictionDistance, erp]);
|
738
749
|
const getSourceFromColliderHandle = useCallback(handle => {
|
739
750
|
var _collider$parent;
|
740
751
|
|
@@ -768,7 +779,7 @@ const Physics = ({
|
|
768
779
|
/* Check if the timestep is supposed to be variable. We'll do this here
|
769
780
|
once so we don't have to string-check every frame. */
|
770
781
|
|
771
|
-
const timeStepVariable =
|
782
|
+
const timeStepVariable = timeStep === "vary";
|
772
783
|
/**
|
773
784
|
* Fixed timeStep simulation progression
|
774
785
|
* @see https://gafferongames.com/post/fix_your_timestep/
|
@@ -792,15 +803,15 @@ const Physics = ({
|
|
792
803
|
world.timestep = clampedDelta;
|
793
804
|
stepWorld();
|
794
805
|
} else {
|
795
|
-
world.timestep =
|
806
|
+
world.timestep = timeStep; // don't step time forwards if paused
|
796
807
|
// Increase accumulator
|
797
808
|
|
798
809
|
steppingState.accumulator += clampedDelta;
|
799
810
|
|
800
|
-
while (steppingState.accumulator >=
|
811
|
+
while (steppingState.accumulator >= timeStep) {
|
801
812
|
// Set up previous state
|
802
813
|
// needed for accurate interpolations if the world steps more than once
|
803
|
-
if (
|
814
|
+
if (interpolate) {
|
804
815
|
steppingState.previousState = {};
|
805
816
|
world.forEachRigidBody(body => {
|
806
817
|
steppingState.previousState[body.handle] = {
|
@@ -811,11 +822,11 @@ const Physics = ({
|
|
811
822
|
}
|
812
823
|
|
813
824
|
stepWorld();
|
814
|
-
steppingState.accumulator -=
|
825
|
+
steppingState.accumulator -= timeStep;
|
815
826
|
}
|
816
827
|
}
|
817
828
|
|
818
|
-
const interpolationAlpha = timeStepVariable || !
|
829
|
+
const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
|
819
830
|
|
820
831
|
rigidBodyStates.forEach((state, handle) => {
|
821
832
|
const rigidBody = world.getRigidBody(handle);
|
@@ -971,13 +982,13 @@ const Physics = ({
|
|
971
982
|
world.forEachActiveRigidBody(() => {
|
972
983
|
invalidate();
|
973
984
|
});
|
974
|
-
}, [
|
985
|
+
}, [paused, timeStep, interpolate]);
|
975
986
|
const context = useMemo(() => ({
|
976
987
|
rapier,
|
977
988
|
world: worldProxy,
|
978
989
|
physicsOptions: {
|
979
|
-
colliders
|
980
|
-
gravity
|
990
|
+
colliders,
|
991
|
+
gravity
|
981
992
|
},
|
982
993
|
rigidBodyStates,
|
983
994
|
colliderStates,
|
@@ -985,22 +996,22 @@ const Physics = ({
|
|
985
996
|
colliderEvents,
|
986
997
|
beforeStepCallbacks,
|
987
998
|
afterStepCallbacks,
|
988
|
-
isPaused:
|
989
|
-
isDebug:
|
999
|
+
isPaused: paused,
|
1000
|
+
isDebug: debug,
|
990
1001
|
step
|
991
|
-
}), [
|
1002
|
+
}), [paused, step, debug, colliders, gravity]);
|
992
1003
|
const stepCallback = useCallback(delta => {
|
993
|
-
if (!
|
1004
|
+
if (!paused) {
|
994
1005
|
step(delta);
|
995
1006
|
}
|
996
|
-
}, [
|
1007
|
+
}, [paused, step]);
|
997
1008
|
return /*#__PURE__*/React.createElement(rapierContext.Provider, {
|
998
1009
|
value: context
|
999
1010
|
}, /*#__PURE__*/React.createElement(FrameStepper$1, {
|
1000
1011
|
onStep: stepCallback,
|
1001
|
-
type:
|
1012
|
+
type: updateLoop,
|
1002
1013
|
updatePriority: updatePriority
|
1003
|
-
}),
|
1014
|
+
}), debug && /*#__PURE__*/React.createElement(Debug, null), children);
|
1004
1015
|
};
|
1005
1016
|
|
1006
1017
|
function _extends() {
|
@@ -1146,7 +1157,9 @@ const AnyCollider = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwarded
|
|
1146
1157
|
colliderRef.current = collider;
|
1147
1158
|
return collider;
|
1148
1159
|
}, collider => {
|
1149
|
-
world.
|
1160
|
+
if (world.getCollider(collider.handle)) {
|
1161
|
+
world.removeCollider(collider, true);
|
1162
|
+
}
|
1150
1163
|
}, [...immutablePropArray, rigidBodyContext]);
|
1151
1164
|
useEffect(() => {
|
1152
1165
|
const collider = getInstance();
|
@@ -1482,7 +1495,9 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, forwardedRe
|
|
1482
1495
|
rigidBodyRef.current = rigidBody;
|
1483
1496
|
return rigidBody;
|
1484
1497
|
}, rigidBody => {
|
1485
|
-
world.
|
1498
|
+
if (world.getRigidBody(rigidBody.handle)) {
|
1499
|
+
world.removeRigidBody(rigidBody);
|
1500
|
+
}
|
1486
1501
|
}, immutablePropArray); // Only provide a object state after the ref has been set
|
1487
1502
|
|
1488
1503
|
useEffect(() => {
|
@@ -1649,14 +1664,16 @@ const useImpulseJoint = (body1, body2, params) => {
|
|
1649
1664
|
useImperativeInstance(() => {
|
1650
1665
|
if (body1.current && body2.current) {
|
1651
1666
|
const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
|
1652
|
-
jointRef.current = newJoint;
|
1653
|
-
|
1667
|
+
jointRef.current = newJoint;
|
1654
1668
|
return newJoint;
|
1655
1669
|
}
|
1656
1670
|
}, joint => {
|
1657
1671
|
if (joint) {
|
1658
1672
|
jointRef.current = undefined;
|
1659
|
-
|
1673
|
+
|
1674
|
+
if (world.getImpulseJoint(joint.handle)) {
|
1675
|
+
world.removeImpulseJoint(joint, true);
|
1676
|
+
}
|
1660
1677
|
}
|
1661
1678
|
}, []);
|
1662
1679
|
return jointRef;
|