@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
@@ -223,7 +223,7 @@ const createInstancedRigidBodiesApi = bodiesGetter => ({
|
|
223
223
|
return bodiesGetter.current().length;
|
224
224
|
}
|
225
225
|
|
226
|
-
});
|
226
|
+
});
|
227
227
|
const createWorldApi = ref => {
|
228
228
|
return {
|
229
229
|
raw: () => ref.current(),
|
@@ -256,8 +256,7 @@ const createWorldApi = ref => {
|
|
256
256
|
},
|
257
257
|
debugRender: () => ref.current().debugRender()
|
258
258
|
};
|
259
|
-
};
|
260
|
-
|
259
|
+
};
|
261
260
|
const createJointApi = ref => {
|
262
261
|
return {
|
263
262
|
raw: () => ref.current(),
|
@@ -731,8 +730,31 @@ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
|
|
731
730
|
};
|
732
731
|
|
733
732
|
const useRapier = () => {
|
734
|
-
return useContext(
|
733
|
+
return useContext(rapierContext);
|
734
|
+
};
|
735
|
+
const useBeforePhysicsStep = callback => {
|
736
|
+
const {
|
737
|
+
beforeStepCallbacks
|
738
|
+
} = useRapier();
|
739
|
+
useEffect(() => {
|
740
|
+
beforeStepCallbacks.add(callback);
|
741
|
+
return () => {
|
742
|
+
beforeStepCallbacks.delete(callback);
|
743
|
+
};
|
744
|
+
}, []);
|
735
745
|
};
|
746
|
+
const useAfterPhysicsStep = callback => {
|
747
|
+
const {
|
748
|
+
afterStepCallbacks
|
749
|
+
} = useRapier();
|
750
|
+
useEffect(() => {
|
751
|
+
afterStepCallbacks.add(callback);
|
752
|
+
return () => {
|
753
|
+
afterStepCallbacks.delete(callback);
|
754
|
+
};
|
755
|
+
}, []);
|
756
|
+
}; // Internal hooks
|
757
|
+
|
736
758
|
const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
|
737
759
|
const [colliderProps, setColliderProps] = useState([]);
|
738
760
|
useEffect(() => {
|
@@ -796,103 +818,6 @@ const useRigidBody = (options = {}) => {
|
|
796
818
|
useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
|
797
819
|
const api = useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
|
798
820
|
return [ref, api, childColliderProps];
|
799
|
-
}; // Joints
|
800
|
-
|
801
|
-
const useImpulseJoint = (body1, body2, params) => {
|
802
|
-
const {
|
803
|
-
world
|
804
|
-
} = useRapier();
|
805
|
-
const jointRef = useRef();
|
806
|
-
const getJointRef = useRef(() => {
|
807
|
-
if (!jointRef.current) {
|
808
|
-
let rb1;
|
809
|
-
let rb2;
|
810
|
-
|
811
|
-
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
812
|
-
rb1 = world.getRigidBody(body1.current.handle);
|
813
|
-
rb2 = world.getRigidBody(body2.current.handle);
|
814
|
-
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
815
|
-
jointRef.current = newJoint;
|
816
|
-
}
|
817
|
-
}
|
818
|
-
|
819
|
-
return jointRef.current;
|
820
|
-
});
|
821
|
-
useEffect(() => {
|
822
|
-
const joint = getJointRef.current();
|
823
|
-
return () => {
|
824
|
-
if (joint) {
|
825
|
-
world.removeImpulseJoint(joint);
|
826
|
-
jointRef.current = undefined;
|
827
|
-
}
|
828
|
-
};
|
829
|
-
}, []);
|
830
|
-
const api = useMemo(() => createJointApi(getJointRef), []);
|
831
|
-
return api;
|
832
|
-
};
|
833
|
-
/**
|
834
|
-
*
|
835
|
-
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
836
|
-
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
837
|
-
* The fixed-joint makes these frames coincide in world-space.
|
838
|
-
*/
|
839
|
-
|
840
|
-
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
841
|
-
const {
|
842
|
-
rapier
|
843
|
-
} = useRapier();
|
844
|
-
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
845
|
-
};
|
846
|
-
/**
|
847
|
-
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
848
|
-
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
849
|
-
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
850
|
-
* points that need to coincide on the local-space of each rigid-body.
|
851
|
-
*/
|
852
|
-
|
853
|
-
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
854
|
-
const {
|
855
|
-
rapier
|
856
|
-
} = useRapier();
|
857
|
-
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
858
|
-
};
|
859
|
-
/**
|
860
|
-
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
861
|
-
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
862
|
-
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
863
|
-
*/
|
864
|
-
|
865
|
-
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
866
|
-
const {
|
867
|
-
rapier
|
868
|
-
} = useRapier();
|
869
|
-
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
870
|
-
|
871
|
-
if (limits) {
|
872
|
-
params.limitsEnabled = true;
|
873
|
-
params.limits = limits;
|
874
|
-
}
|
875
|
-
|
876
|
-
return useImpulseJoint(body1, body2, params);
|
877
|
-
};
|
878
|
-
/**
|
879
|
-
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
880
|
-
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
881
|
-
* local tangent axis can be specified for each rigid-body.
|
882
|
-
*/
|
883
|
-
|
884
|
-
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
885
|
-
const {
|
886
|
-
rapier
|
887
|
-
} = useRapier();
|
888
|
-
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
889
|
-
|
890
|
-
if (limits) {
|
891
|
-
params.limitsEnabled = true;
|
892
|
-
params.limits = limits;
|
893
|
-
}
|
894
|
-
|
895
|
-
return useImpulseJoint(body1, body2, params);
|
896
821
|
};
|
897
822
|
|
898
823
|
const calcForceByType = {
|
@@ -980,7 +905,7 @@ const Attractor = /*#__PURE__*/memo(props => {
|
|
980
905
|
});
|
981
906
|
});
|
982
907
|
|
983
|
-
const
|
908
|
+
const rapierContext = /*#__PURE__*/createContext(undefined);
|
984
909
|
|
985
910
|
const getCollisionPayloadFromSource = (target, other) => {
|
986
911
|
var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
|
@@ -1035,7 +960,9 @@ const Physics = ({
|
|
1035
960
|
const rigidBodyEvents = useConst(() => new Map());
|
1036
961
|
const colliderEvents = useConst(() => new Map());
|
1037
962
|
const eventQueue = useConst(() => new EventQueue(false));
|
1038
|
-
const attractorStates = useConst(() => new Map());
|
963
|
+
const attractorStates = useConst(() => new Map());
|
964
|
+
const beforeStepCallbacks = useConst(() => new Set());
|
965
|
+
const afterStepCallbacks = useConst(() => new Set()); // Init world
|
1039
966
|
|
1040
967
|
useEffect(() => {
|
1041
968
|
const world = getWorldRef.current();
|
@@ -1054,6 +981,7 @@ const Physics = ({
|
|
1054
981
|
world.gravity = vectorArrayToVector3(_gravity);
|
1055
982
|
}
|
1056
983
|
}, [_gravity]);
|
984
|
+
const api = useMemo(() => createWorldApi(getWorldRef), []);
|
1057
985
|
const getSourceFromColliderHandle = useCallback(handle => {
|
1058
986
|
const world = worldRef.current;
|
1059
987
|
|
@@ -1100,9 +1028,21 @@ const Physics = ({
|
|
1100
1028
|
|
1101
1029
|
const clampedDelta = MathUtils.clamp(dt, 0, 0.2);
|
1102
1030
|
|
1031
|
+
const stepWorld = () => {
|
1032
|
+
// Trigger beforeStep callbacks
|
1033
|
+
beforeStepCallbacks.forEach(callback => {
|
1034
|
+
callback(api);
|
1035
|
+
});
|
1036
|
+
world.step(eventQueue); // Trigger afterStep callbacks
|
1037
|
+
|
1038
|
+
afterStepCallbacks.forEach(callback => {
|
1039
|
+
callback(api);
|
1040
|
+
});
|
1041
|
+
};
|
1042
|
+
|
1103
1043
|
if (timeStepVariable) {
|
1104
1044
|
world.timestep = clampedDelta;
|
1105
|
-
|
1045
|
+
stepWorld();
|
1106
1046
|
} else {
|
1107
1047
|
world.timestep = _timeStep; // don't step time forwards if paused
|
1108
1048
|
// Increase accumulator
|
@@ -1126,7 +1066,7 @@ const Physics = ({
|
|
1126
1066
|
applyAttractorForceOnRigidBody(body, attractorState);
|
1127
1067
|
});
|
1128
1068
|
});
|
1129
|
-
|
1069
|
+
stepWorld();
|
1130
1070
|
steppingState.accumulator -= _timeStep;
|
1131
1071
|
}
|
1132
1072
|
}
|
@@ -1289,7 +1229,6 @@ const Physics = ({
|
|
1289
1229
|
useFrame((_, dt) => {
|
1290
1230
|
if (!_paused) step(dt);
|
1291
1231
|
}, updatePriority);
|
1292
|
-
const api = useMemo(() => createWorldApi(getWorldRef), []);
|
1293
1232
|
const context = useMemo(() => ({
|
1294
1233
|
rapier,
|
1295
1234
|
world: api,
|
@@ -1302,10 +1241,12 @@ const Physics = ({
|
|
1302
1241
|
rigidBodyEvents,
|
1303
1242
|
colliderEvents,
|
1304
1243
|
attractorStates,
|
1244
|
+
beforeStepCallbacks,
|
1245
|
+
afterStepCallbacks,
|
1305
1246
|
isPaused: _paused,
|
1306
1247
|
step
|
1307
1248
|
}), [_paused, step]);
|
1308
|
-
return /*#__PURE__*/React.createElement(
|
1249
|
+
return /*#__PURE__*/React.createElement(rapierContext.Provider, {
|
1309
1250
|
value: context
|
1310
1251
|
}, children);
|
1311
1252
|
};
|
@@ -1533,7 +1474,7 @@ const RigidBody = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, ref) => {
|
|
1533
1474
|
}));
|
1534
1475
|
RigidBody.displayName = "RigidBody";
|
1535
1476
|
|
1536
|
-
const MeshCollider = props => {
|
1477
|
+
const MeshCollider = /*#__PURE__*/memo(props => {
|
1537
1478
|
const {
|
1538
1479
|
children,
|
1539
1480
|
type
|
@@ -1561,7 +1502,7 @@ const MeshCollider = props => {
|
|
1561
1502
|
}, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React.createElement(AnyCollider, _extends({
|
1562
1503
|
key: index
|
1563
1504
|
}, colliderProps))));
|
1564
|
-
};
|
1505
|
+
});
|
1565
1506
|
MeshCollider.displayName = "MeshCollider";
|
1566
1507
|
|
1567
1508
|
function mapsEqual(map1, map2) {
|
@@ -1623,7 +1564,7 @@ const AttractorHelper = props => {
|
|
1623
1564
|
}));
|
1624
1565
|
};
|
1625
1566
|
|
1626
|
-
const Debug = () => {
|
1567
|
+
const Debug = /*#__PURE__*/memo(() => {
|
1627
1568
|
const {
|
1628
1569
|
world,
|
1629
1570
|
attractorStates
|
@@ -1652,7 +1593,7 @@ const Debug = () => {
|
|
1652
1593
|
}), /*#__PURE__*/React.createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React.createElement(AttractorHelper, _extends({
|
1653
1594
|
key: attractor.object.uuid
|
1654
1595
|
}, attractor))));
|
1655
|
-
};
|
1596
|
+
});
|
1656
1597
|
|
1657
1598
|
const _excluded = ["positions", "rotations", "children"];
|
1658
1599
|
const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
@@ -1766,6 +1707,103 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
|
1766
1707
|
});
|
1767
1708
|
InstancedRigidBodies.displayName = "InstancedRigidBodies";
|
1768
1709
|
|
1710
|
+
const useImpulseJoint = (body1, body2, params) => {
|
1711
|
+
const {
|
1712
|
+
world
|
1713
|
+
} = useRapier();
|
1714
|
+
const jointRef = useRef();
|
1715
|
+
const getJointRef = useRef(() => {
|
1716
|
+
if (!jointRef.current) {
|
1717
|
+
let rb1;
|
1718
|
+
let rb2;
|
1719
|
+
|
1720
|
+
if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
|
1721
|
+
rb1 = world.getRigidBody(body1.current.handle);
|
1722
|
+
rb2 = world.getRigidBody(body2.current.handle);
|
1723
|
+
const newJoint = world.createImpulseJoint(params, rb1, rb2);
|
1724
|
+
jointRef.current = newJoint;
|
1725
|
+
}
|
1726
|
+
}
|
1727
|
+
|
1728
|
+
return jointRef.current;
|
1729
|
+
});
|
1730
|
+
useEffect(() => {
|
1731
|
+
const joint = getJointRef.current();
|
1732
|
+
return () => {
|
1733
|
+
if (joint) {
|
1734
|
+
world.removeImpulseJoint(joint);
|
1735
|
+
jointRef.current = undefined;
|
1736
|
+
}
|
1737
|
+
};
|
1738
|
+
}, []);
|
1739
|
+
const api = useMemo(() => createJointApi(getJointRef), []);
|
1740
|
+
return api;
|
1741
|
+
};
|
1742
|
+
/**
|
1743
|
+
*
|
1744
|
+
* A fixed joint ensures that two rigid-bodies don't move relative to each other.
|
1745
|
+
* Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
|
1746
|
+
* The fixed-joint makes these frames coincide in world-space.
|
1747
|
+
*/
|
1748
|
+
|
1749
|
+
const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
|
1750
|
+
const {
|
1751
|
+
rapier
|
1752
|
+
} = useRapier();
|
1753
|
+
return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), tupleToObject(body1LocalFrame, ["x", "y", "z", "w"]), vectorArrayToVector3(body2Anchor), tupleToObject(body2LocalFrame, ["x", "y", "z", "w"])));
|
1754
|
+
};
|
1755
|
+
/**
|
1756
|
+
* The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
|
1757
|
+
* translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
|
1758
|
+
* They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
|
1759
|
+
* points that need to coincide on the local-space of each rigid-body.
|
1760
|
+
*/
|
1761
|
+
|
1762
|
+
const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
|
1763
|
+
const {
|
1764
|
+
rapier
|
1765
|
+
} = useRapier();
|
1766
|
+
return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
|
1767
|
+
};
|
1768
|
+
/**
|
1769
|
+
* The revolute joint prevents any relative movement between two rigid-bodies, except for relative
|
1770
|
+
* rotations along one axis. This is typically used to simulate wheels, fans, etc.
|
1771
|
+
* They are characterized by one local anchor as well as one local axis on each rigid-body.
|
1772
|
+
*/
|
1773
|
+
|
1774
|
+
const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
1775
|
+
const {
|
1776
|
+
rapier
|
1777
|
+
} = useRapier();
|
1778
|
+
const params = rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
1779
|
+
|
1780
|
+
if (limits) {
|
1781
|
+
params.limitsEnabled = true;
|
1782
|
+
params.limits = limits;
|
1783
|
+
}
|
1784
|
+
|
1785
|
+
return useImpulseJoint(body1, body2, params);
|
1786
|
+
};
|
1787
|
+
/**
|
1788
|
+
* The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
|
1789
|
+
* It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
|
1790
|
+
* local tangent axis can be specified for each rigid-body.
|
1791
|
+
*/
|
1792
|
+
|
1793
|
+
const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
|
1794
|
+
const {
|
1795
|
+
rapier
|
1796
|
+
} = useRapier();
|
1797
|
+
const params = rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis));
|
1798
|
+
|
1799
|
+
if (limits) {
|
1800
|
+
params.limitsEnabled = true;
|
1801
|
+
params.limits = limits;
|
1802
|
+
}
|
1803
|
+
|
1804
|
+
return useImpulseJoint(body1, body2, params);
|
1805
|
+
};
|
1806
|
+
|
1769
1807
|
/**
|
1770
1808
|
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
1771
1809
|
* properties of RigidBody or Collider components. The first argument represents a list of
|
@@ -1802,4 +1840,4 @@ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16)
|
|
1802
1840
|
|
1803
1841
|
const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
|
1804
1842
|
|
1805
|
-
export { AnyCollider, Attractor, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, interactionGroups,
|
1843
|
+
export { AnyCollider, Attractor, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, interactionGroups, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useSphericalJoint };
|