@react-three/rapier 0.11.3 → 0.12.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.
- package/dist/declarations/src/AnyCollider.d.ts +21 -22
- package/dist/declarations/src/Attractor.d.ts +3 -4
- package/dist/declarations/src/Debug.d.ts +2 -5
- package/dist/declarations/src/MeshCollider.d.ts +3 -7
- package/dist/declarations/src/Physics.d.ts +37 -7
- package/dist/declarations/src/RigidBody.d.ts +6 -6
- package/dist/declarations/src/api.d.ts +16 -9
- package/dist/declarations/src/hooks.d.ts +7 -37
- package/dist/declarations/src/index.d.ts +7 -3
- package/dist/declarations/src/joints.d.ts +30 -0
- package/dist/declarations/src/types.d.ts +9 -8
- package/dist/react-three-rapier.cjs.dev.js +151 -113
- package/dist/react-three-rapier.cjs.prod.js +151 -113
- package/dist/react-three-rapier.esm.js +150 -112
- package/package.json +1 -1
- package/readme.md +137 -63
@@ -248,7 +248,7 @@ const createInstancedRigidBodiesApi = bodiesGetter => ({
|
|
248
248
|
return bodiesGetter.current().length;
|
249
249
|
}
|
250
250
|
|
251
|
-
});
|
251
|
+
});
|
252
252
|
const createWorldApi = ref => {
|
253
253
|
return {
|
254
254
|
raw: () => ref.current(),
|
@@ -281,8 +281,7 @@ const createWorldApi = ref => {
|
|
281
281
|
},
|
282
282
|
debugRender: () => ref.current().debugRender()
|
283
283
|
};
|
284
|
-
};
|
285
|
-
|
284
|
+
};
|
286
285
|
const createJointApi = ref => {
|
287
286
|
return {
|
288
287
|
raw: () => ref.current(),
|
@@ -756,8 +755,31 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
|
756
755
|
};
|
757
756
|
|
758
757
|
const useRapier = () => {
|
759
|
-
return React.useContext(
|
758
|
+
return React.useContext(rapierContext);
|
759
|
+
};
|
760
|
+
const useBeforePhysicsStep = callback => {
|
761
|
+
const {
|
762
|
+
beforeStepCallbacks
|
763
|
+
} = useRapier();
|
764
|
+
React.useEffect(() => {
|
765
|
+
beforeStepCallbacks.add(callback);
|
766
|
+
return () => {
|
767
|
+
beforeStepCallbacks.delete(callback);
|
768
|
+
};
|
769
|
+
}, []);
|
760
770
|
};
|
771
|
+
const useAfterPhysicsStep = callback => {
|
772
|
+
const {
|
773
|
+
afterStepCallbacks
|
774
|
+
} = useRapier();
|
775
|
+
React.useEffect(() => {
|
776
|
+
afterStepCallbacks.add(callback);
|
777
|
+
return () => {
|
778
|
+
afterStepCallbacks.delete(callback);
|
779
|
+
};
|
780
|
+
}, []);
|
781
|
+
}; // Internal hooks
|
782
|
+
|
761
783
|
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
762
784
|
const [colliderProps, setColliderProps] = React.useState([]);
|
763
785
|
React.useEffect(() => {
|
@@ -821,103 +843,6 @@ const useRigidBody = (options = {}) => {
|
|
821
843
|
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
822
844
|
const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
823
845
|
return [ref, api, childColliderProps];
|
824
|
-
}; // Joints
|
825
|
-
|
826
|
-
const useImpulseJoint = (body1, body2, params) => {
|
827
|
-
const {
|
828
|
-
world
|
829
|
-
} = useRapier();
|
830
|
-
const jointRef = React.useRef();
|
831
|
-
const getJointRef = React.useRef(() => {
|
832
|
-
if (!jointRef.current) {
|
833
|
-
let rb1;
|
834
|
-
let rb2;
|
835
|
-
|
836
|
-
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
837
|
-
rb1 = world.getRigidBody(body1.current.handle);
|
838
|
-
rb2 = world.getRigidBody(body2.current.handle);
|
839
|
-
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
840
|
-
jointRef.current = newJoint;
|
841
|
-
}
|
842
|
-
}
|
843
|
-
|
844
|
-
return jointRef.current;
|
845
|
-
});
|
846
|
-
React.useEffect(() => {
|
847
|
-
const joint = getJointRef.current();
|
848
|
-
return () => {
|
849
|
-
if (joint) {
|
850
|
-
world.removeImpulseJoint(joint);
|
851
|
-
jointRef.current = undefined;
|
852
|
-
}
|
853
|
-
};
|
854
|
-
}, []);
|
855
|
-
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
856
|
-
return api;
|
857
|
-
};
|
858
|
-
/**
|
859
|
-
*
|
860
|
-
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
861
|
-
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
862
|
-
* The fixed-joint makes these frames coincide in world-space.
|
863
|
-
*/
|
864
|
-
|
865
|
-
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
866
|
-
const {
|
867
|
-
rapier
|
868
|
-
} = useRapier();
|
869
|
-
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
870
|
-
};
|
871
|
-
/**
|
872
|
-
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
873
|
-
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
874
|
-
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
875
|
-
* points that need to coincide on the local-space of each rigid-body.
|
876
|
-
*/
|
877
|
-
|
878
|
-
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
879
|
-
const {
|
880
|
-
rapier
|
881
|
-
} = useRapier();
|
882
|
-
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
883
|
-
};
|
884
|
-
/**
|
885
|
-
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
886
|
-
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
887
|
-
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
888
|
-
*/
|
889
|
-
|
890
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
891
|
-
const {
|
892
|
-
rapier
|
893
|
-
} = useRapier();
|
894
|
-
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
895
|
-
|
896
|
-
if (limits) {
|
897
|
-
params.limitsEnabled = true;
|
898
|
-
params.limits = limits;
|
899
|
-
}
|
900
|
-
|
901
|
-
return useImpulseJoint(body1, body2, params);
|
902
|
-
};
|
903
|
-
/**
|
904
|
-
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
905
|
-
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
906
|
-
* local tangent axis can be specified for each rigid-body.
|
907
|
-
*/
|
908
|
-
|
909
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
910
|
-
const {
|
911
|
-
rapier
|
912
|
-
} = useRapier();
|
913
|
-
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
914
|
-
|
915
|
-
if (limits) {
|
916
|
-
params.limitsEnabled = true;
|
917
|
-
params.limits = limits;
|
918
|
-
}
|
919
|
-
|
920
|
-
return useImpulseJoint(body1, body2, params);
|
921
846
|
};
|
922
847
|
|
923
848
|
const calcForceByType = {
|
@@ -1005,7 +930,7 @@ const Attractor = /*#__PURE__*/React.memo(props => {
|
|
1005
930
|
});
|
1006
931
|
});
|
1007
932
|
|
1008
|
-
const
|
933
|
+
const rapierContext = /*#__PURE__*/React.createContext(undefined);
|
1009
934
|
|
1010
935
|
const getCollisionPayloadFromSource = (target, other) => {
|
1011
936
|
var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
|
@@ -1060,7 +985,9 @@ const Physics = ({
|
|
1060
985
|
const rigidBodyEvents = useConst(() => new Map());
|
1061
986
|
const colliderEvents = useConst(() => new Map());
|
1062
987
|
const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
|
1063
|
-
const attractorStates = useConst(() => new Map());
|
988
|
+
const attractorStates = useConst(() => new Map());
|
989
|
+
const beforeStepCallbacks = useConst(() => new Set());
|
990
|
+
const afterStepCallbacks = useConst(() => new Set()); // Init world
|
1064
991
|
|
1065
992
|
React.useEffect(() => {
|
1066
993
|
const world = getWorldRef.current();
|
@@ -1079,6 +1006,7 @@ const Physics = ({
|
|
1079
1006
|
world.gravity = vectorArrayToVector3(_gravity);
|
1080
1007
|
}
|
1081
1008
|
}, [_gravity]);
|
1009
|
+
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
1082
1010
|
const getSourceFromColliderHandle = React.useCallback(handle => {
|
1083
1011
|
const world = worldRef.current;
|
1084
1012
|
|
@@ -1125,9 +1053,21 @@ const Physics = ({
|
|
1125
1053
|
|
1126
1054
|
const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
|
1127
1055
|
|
1056
|
+
const stepWorld = () => {
|
1057
|
+
// Trigger beforeStep callbacks
|
1058
|
+
beforeStepCallbacks.forEach(callback => {
|
1059
|
+
callback(api);
|
1060
|
+
});
|
1061
|
+
world.step(eventQueue); // Trigger afterStep callbacks
|
1062
|
+
|
1063
|
+
afterStepCallbacks.forEach(callback => {
|
1064
|
+
callback(api);
|
1065
|
+
});
|
1066
|
+
};
|
1067
|
+
|
1128
1068
|
if (timeStepVariable) {
|
1129
1069
|
world.timestep = clampedDelta;
|
1130
|
-
|
1070
|
+
stepWorld();
|
1131
1071
|
} else {
|
1132
1072
|
world.timestep = _timeStep; // don't step time forwards if paused
|
1133
1073
|
// Increase accumulator
|
@@ -1151,7 +1091,7 @@ const Physics = ({
|
|
1151
1091
|
applyAttractorForceOnRigidBody(body, attractorState);
|
1152
1092
|
});
|
1153
1093
|
});
|
1154
|
-
|
1094
|
+
stepWorld();
|
1155
1095
|
steppingState.accumulator -= _timeStep;
|
1156
1096
|
}
|
1157
1097
|
}
|
@@ -1314,7 +1254,6 @@ const Physics = ({
|
|
1314
1254
|
fiber.useFrame((_, dt) => {
|
1315
1255
|
if (!_paused) step(dt);
|
1316
1256
|
}, updatePriority);
|
1317
|
-
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
1318
1257
|
const context = React.useMemo(() => ({
|
1319
1258
|
rapier,
|
1320
1259
|
world: api,
|
@@ -1327,10 +1266,12 @@ const Physics = ({
|
|
1327
1266
|
rigidBodyEvents,
|
1328
1267
|
colliderEvents,
|
1329
1268
|
attractorStates,
|
1269
|
+
beforeStepCallbacks,
|
1270
|
+
afterStepCallbacks,
|
1330
1271
|
isPaused: _paused,
|
1331
1272
|
step
|
1332
1273
|
}), [_paused, step]);
|
1333
|
-
return /*#__PURE__*/React__default["default"].createElement(
|
1274
|
+
return /*#__PURE__*/React__default["default"].createElement(rapierContext.Provider, {
|
1334
1275
|
value: context
|
1335
1276
|
}, children);
|
1336
1277
|
};
|
@@ -1558,7 +1499,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
|
|
1558
1499
|
}));
|
1559
1500
|
RigidBody.displayName = "RigidBody";
|
1560
1501
|
|
1561
|
-
const MeshCollider = props => {
|
1502
|
+
const MeshCollider = /*#__PURE__*/React.memo(props => {
|
1562
1503
|
const {
|
1563
1504
|
children,
|
1564
1505
|
type
|
@@ -1586,7 +1527,7 @@ const MeshCollider = props => {
|
|
1586
1527
|
}, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
|
1587
1528
|
key: index
|
1588
1529
|
}, colliderProps))));
|
1589
|
-
};
|
1530
|
+
});
|
1590
1531
|
MeshCollider.displayName = "MeshCollider";
|
1591
1532
|
|
1592
1533
|
function mapsEqual(map1, map2) {
|
@@ -1648,7 +1589,7 @@ const AttractorHelper = props => {
|
|
1648
1589
|
}));
|
1649
1590
|
};
|
1650
1591
|
|
1651
|
-
const Debug = () => {
|
1592
|
+
const Debug = /*#__PURE__*/React.memo(() => {
|
1652
1593
|
const {
|
1653
1594
|
world,
|
1654
1595
|
attractorStates
|
@@ -1677,7 +1618,7 @@ const Debug = () => {
|
|
1677
1618
|
}), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React__default["default"].createElement(AttractorHelper, _extends({
|
1678
1619
|
key: attractor.object.uuid
|
1679
1620
|
}, attractor))));
|
1680
|
-
};
|
1621
|
+
});
|
1681
1622
|
|
1682
1623
|
const _excluded = ["positions", "rotations", "children"];
|
1683
1624
|
const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
@@ -1791,6 +1732,103 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1791
1732
|
});
|
1792
1733
|
InstancedRigidBodies.displayName = "InstancedRigidBodies";
|
1793
1734
|
|
1735
|
+
const useImpulseJoint = (body1, body2, params) => {
|
1736
|
+
const {
|
1737
|
+
world
|
1738
|
+
} = useRapier();
|
1739
|
+
const jointRef = React.useRef();
|
1740
|
+
const getJointRef = React.useRef(() => {
|
1741
|
+
if (!jointRef.current) {
|
1742
|
+
let rb1;
|
1743
|
+
let rb2;
|
1744
|
+
|
1745
|
+
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
1746
|
+
rb1 = world.getRigidBody(body1.current.handle);
|
1747
|
+
rb2 = world.getRigidBody(body2.current.handle);
|
1748
|
+
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
1749
|
+
jointRef.current = newJoint;
|
1750
|
+
}
|
1751
|
+
}
|
1752
|
+
|
1753
|
+
return jointRef.current;
|
1754
|
+
});
|
1755
|
+
React.useEffect(() => {
|
1756
|
+
const joint = getJointRef.current();
|
1757
|
+
return () => {
|
1758
|
+
if (joint) {
|
1759
|
+
world.removeImpulseJoint(joint);
|
1760
|
+
jointRef.current = undefined;
|
1761
|
+
}
|
1762
|
+
};
|
1763
|
+
}, []);
|
1764
|
+
const api = React.useMemo(() => createJointApi(getJointRef), []);
|
1765
|
+
return api;
|
1766
|
+
};
|
1767
|
+
/**
|
1768
|
+
*
|
1769
|
+
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
1770
|
+
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
1771
|
+
* The fixed-joint makes these frames coincide in world-space.
|
1772
|
+
*/
|
1773
|
+
|
1774
|
+
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
1775
|
+
const {
|
1776
|
+
rapier
|
1777
|
+
} = useRapier();
|
1778
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
1779
|
+
};
|
1780
|
+
/**
|
1781
|
+
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
1782
|
+
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
1783
|
+
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
1784
|
+
* points that need to coincide on the local-space of each rigid-body.
|
1785
|
+
*/
|
1786
|
+
|
1787
|
+
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
1788
|
+
const {
|
1789
|
+
rapier
|
1790
|
+
} = useRapier();
|
1791
|
+
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
1792
|
+
};
|
1793
|
+
/**
|
1794
|
+
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
1795
|
+
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
1796
|
+
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
1797
|
+
*/
|
1798
|
+
|
1799
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
1800
|
+
const {
|
1801
|
+
rapier
|
1802
|
+
} = useRapier();
|
1803
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
1804
|
+
|
1805
|
+
if (limits) {
|
1806
|
+
params.limitsEnabled = true;
|
1807
|
+
params.limits = limits;
|
1808
|
+
}
|
1809
|
+
|
1810
|
+
return useImpulseJoint(body1, body2, params);
|
1811
|
+
};
|
1812
|
+
/**
|
1813
|
+
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
1814
|
+
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
1815
|
+
* local tangent axis can be specified for each rigid-body.
|
1816
|
+
*/
|
1817
|
+
|
1818
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
1819
|
+
const {
|
1820
|
+
rapier
|
1821
|
+
} = useRapier();
|
1822
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
1823
|
+
|
1824
|
+
if (limits) {
|
1825
|
+
params.limitsEnabled = true;
|
1826
|
+
params.limits = limits;
|
1827
|
+
}
|
1828
|
+
|
1829
|
+
return useImpulseJoint(body1, body2, params);
|
1830
|
+
};
|
1831
|
+
|
1794
1832
|
/**
|
1795
1833
|
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
1796
1834
|
* properties of RigidBody or Collider components. The first argument represents a list of
|
@@ -1856,11 +1894,11 @@ exports.RigidBody = RigidBody;
|
|
1856
1894
|
exports.RoundCuboidCollider = RoundCuboidCollider;
|
1857
1895
|
exports.TrimeshCollider = TrimeshCollider;
|
1858
1896
|
exports.interactionGroups = interactionGroups;
|
1859
|
-
exports.
|
1897
|
+
exports.useAfterPhysicsStep = useAfterPhysicsStep;
|
1898
|
+
exports.useBeforePhysicsStep = useBeforePhysicsStep;
|
1860
1899
|
exports.useFixedJoint = useFixedJoint;
|
1861
1900
|
exports.useImpulseJoint = useImpulseJoint;
|
1862
1901
|
exports.usePrismaticJoint = usePrismaticJoint;
|
1863
1902
|
exports.useRapier = useRapier;
|
1864
1903
|
exports.useRevoluteJoint = useRevoluteJoint;
|
1865
|
-
exports.useRigidBody = useRigidBody;
|
1866
1904
|
exports.useSphericalJoint = useSphericalJoint;
|