@react-three/rapier 0.14.0 → 0.15.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.
@@ -4,7 +4,6 @@ import React, { FC, ReactNode } from "react";
4
4
  import { Matrix4, Object3D, Vector3 } from "three";
5
5
  import { CollisionEnterHandler, CollisionExitHandler, ContactForceHandler, IntersectionEnterHandler, IntersectionExitHandler, RigidBodyAutoCollider, Vector3Array } from "../types";
6
6
  import { WorldApi } from "../utils/api";
7
- import { AttractorStateMap } from "./Attractor";
8
7
  export interface RigidBodyState {
9
8
  meshType: "instancedMesh" | "mesh";
10
9
  rigidBody: RigidBody;
@@ -54,11 +53,6 @@ export interface RapierContext {
54
53
  * @internal
55
54
  */
56
55
  colliderEvents: EventMap;
57
- /**
58
- * Used by the world to keep track of Attractor states
59
- * @internal
60
- */
61
- attractorStates: AttractorStateMap;
62
56
  /**
63
57
  * Default options for rigid bodies and colliders
64
58
  * @internal
@@ -99,6 +93,10 @@ export interface RapierContext {
99
93
  * ```
100
94
  */
101
95
  step: (deltaTime: number) => void;
96
+ /**
97
+ * Is debug mode enabled
98
+ */
99
+ isDebug: boolean;
102
100
  }
103
101
  export declare const rapierContext: React.Context<RapierContext | undefined>;
104
102
  export declare type EventMapValue = {
@@ -171,6 +169,11 @@ export interface PhysicsProps {
171
169
  * @defaultValue "follow"
172
170
  */
173
171
  updateLoop?: "follow" | "independent";
172
+ /**
173
+ * Enable debug rendering of the physics world.
174
+ * @defaultValue false
175
+ */
176
+ debug?: boolean;
174
177
  }
175
178
  /**
176
179
  * The main physics component used to create a physics world.
@@ -4,15 +4,12 @@ export type { InstancedRigidBodiesProps, InstancedRigidBodyProps } from "./compo
4
4
  export type { CylinderColliderProps, BallColliderProps, CapsuleColliderProps, ConeColliderProps, ConvexHullColliderProps, CuboidColliderProps, HeightfieldColliderProps, RoundCuboidColliderProps, TrimeshColliderProps, ColliderOptionsRequiredArgs } from "./components/AnyCollider";
5
5
  export type { PhysicsProps, RapierContext, WorldStepCallback } from "./components/Physics";
6
6
  export type { MeshColliderProps } from "./components/MeshCollider";
7
- export type { AttractorProps, AttractorGravityType } from "./components/Attractor";
8
7
  export type { WorldApi } from "./utils/api";
9
8
  export { Physics } from "./components/Physics";
10
9
  export { RigidBody } from "./components/RigidBody";
11
10
  export { MeshCollider } from "./components/MeshCollider";
12
- export { Debug } from "./components/Debug";
13
11
  export { InstancedRigidBodies } from "./components/InstancedRigidBodies";
14
12
  export * from "./components/AnyCollider";
15
- export { Attractor } from "./components/Attractor";
16
13
  export * from "./hooks/joints";
17
14
  export { useRapier, useBeforePhysicsStep, useAfterPhysicsStep } from "./hooks/hooks";
18
15
  export * from "./utils/interaction-groups";
@@ -178,6 +178,61 @@ 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
+ const UseFrameStepper = ({
203
+ onStep,
204
+ updatePriority
205
+ }) => {
206
+ fiber.useFrame((_, dt) => {
207
+ onStep(dt);
208
+ }, updatePriority);
209
+ return null;
210
+ };
211
+
212
+ const RafStepper = ({
213
+ onStep
214
+ }) => {
215
+ useRaf(dt => {
216
+ onStep(dt);
217
+ });
218
+ return null;
219
+ };
220
+
221
+ const FrameStepper = ({
222
+ onStep,
223
+ type,
224
+ updatePriority
225
+ }) => {
226
+ return type === "independent" ? /*#__PURE__*/React__default["default"].createElement(RafStepper, {
227
+ onStep: onStep
228
+ }) : /*#__PURE__*/React__default["default"].createElement(UseFrameStepper, {
229
+ onStep: onStep,
230
+ updatePriority: updatePriority
231
+ });
232
+ };
233
+
234
+ var FrameStepper$1 = /*#__PURE__*/React.memo(FrameStepper);
235
+
181
236
  function _objectWithoutPropertiesLoose(source, excluded) {
182
237
  if (source == null) return {};
183
238
  var target = {};
@@ -606,146 +661,27 @@ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
606
661
  return colliderProps;
607
662
  };
608
663
 
609
- const calcForceByType = {
610
- static: (s, m2, r, d, G) => s,
611
- linear: (s, m2, r, d, G) => s * (d / r),
612
- newtonian: (s, m2, r, d, G) => G * s * m2 / Math.pow(d, 2)
613
- };
614
- const applyAttractorForceOnRigidBody = (rigidBody, {
615
- object,
616
- strength,
617
- range,
618
- gravitationalConstant,
619
- collisionGroups,
620
- type
621
- }) => {
622
- const rbPosition = rigidBody.translation();
623
-
624
- _position.set(rbPosition.x, rbPosition.y, rbPosition.z);
625
-
626
- const worldPosition = object.getWorldPosition(new three.Vector3());
627
- const distance = worldPosition.distanceTo(_position);
628
-
629
- if (distance < range) {
630
- let force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant); // Prevent wild forces when Attractors collide
631
-
632
- force = force === Infinity ? strength : force; // Naively test if the rigidBody contains a collider in one of the collision groups
633
-
634
- let isRigidBodyInCollisionGroup = collisionGroups === undefined ? true : false;
635
-
636
- if (collisionGroups !== undefined) {
637
- for (let i = 0; i < rigidBody.numColliders(); i++) {
638
- const collider = rigidBody.collider(i);
639
- const colliderCollisionGroups = collider.collisionGroups();
640
-
641
- if ((collisionGroups >> 16 & colliderCollisionGroups) != 0 && (colliderCollisionGroups >> 16 & collisionGroups) != 0) {
642
- isRigidBodyInCollisionGroup = true;
643
- break;
644
- }
645
- }
646
- }
647
-
648
- if (isRigidBodyInCollisionGroup) {
649
- _vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);
650
-
651
- rigidBody.applyImpulse(_vector3, true);
652
- }
653
- }
654
- };
655
- const Attractor = /*#__PURE__*/React.memo(props => {
656
- const {
657
- position = [0, 0, 0],
658
- strength = 1,
659
- range = 10,
660
- type = "static",
661
- gravitationalConstant = 6.673e-11,
662
- collisionGroups
663
- } = props;
664
+ const Debug = /*#__PURE__*/React.memo(() => {
664
665
  const {
665
- attractorStates
666
+ world
666
667
  } = useRapier();
667
- const object = React.useRef(null);
668
- React.useEffect(() => {
669
- var _object$current;
670
-
671
- let uuid = ((_object$current = object.current) === null || _object$current === void 0 ? void 0 : _object$current.uuid) || "_";
672
-
673
- if (object.current) {
674
- attractorStates.set(uuid, {
675
- object: object.current,
676
- strength,
677
- range,
678
- type,
679
- gravitationalConstant,
680
- collisionGroups
681
- });
682
- }
683
-
684
- return () => {
685
- attractorStates.delete(uuid);
686
- };
687
- }, [props]);
688
- return /*#__PURE__*/React__default["default"].createElement("object3D", {
689
- ref: object,
690
- position: position
668
+ const ref = React.useRef(null);
669
+ fiber.useFrame(() => {
670
+ const mesh = ref.current;
671
+ if (!mesh) return;
672
+ const buffers = world.debugRender();
673
+ mesh.geometry.setAttribute("position", new three.BufferAttribute(buffers.vertices, 3));
674
+ mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4));
691
675
  });
676
+ return /*#__PURE__*/React__default["default"].createElement("group", null, /*#__PURE__*/React__default["default"].createElement("lineSegments", {
677
+ ref: ref,
678
+ frustumCulled: false
679
+ }, /*#__PURE__*/React__default["default"].createElement("lineBasicMaterial", {
680
+ color: 0xffffff,
681
+ vertexColors: true
682
+ }), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)));
692
683
  });
693
684
 
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
-
749
685
  const rapierContext = /*#__PURE__*/React.createContext(undefined);
750
686
 
751
687
  const getCollisionPayloadFromSource = (target, other) => {
@@ -789,7 +725,8 @@ const Physics = ({
789
725
  paused: _paused = false,
790
726
  interpolate: _interpolate = true,
791
727
  updatePriority,
792
- updateLoop: _updateLoop = "follow"
728
+ updateLoop: _updateLoop = "follow",
729
+ debug: _debug = false
793
730
  }) => {
794
731
  const rapier = useAsset.useAsset(importRapier);
795
732
  const {
@@ -809,7 +746,6 @@ const Physics = ({
809
746
  const rigidBodyEvents = useConst(() => new Map());
810
747
  const colliderEvents = useConst(() => new Map());
811
748
  const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
812
- const attractorStates = useConst(() => new Map());
813
749
  const beforeStepCallbacks = useConst(() => new Set());
814
750
  const afterStepCallbacks = useConst(() => new Set()); // Init world
815
751
 
@@ -878,13 +814,7 @@ const Physics = ({
878
814
  const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
879
815
 
880
816
  const stepWorld = () => {
881
- // Apply attractors
882
- world.forEachRigidBody(body => {
883
- attractorStates.forEach(attractorState => {
884
- applyAttractorForceOnRigidBody(body, attractorState);
885
- });
886
- }); // Trigger beforeStep callbacks
887
-
817
+ // Trigger beforeStep callbacks
888
818
  beforeStepCallbacks.forEach(callback => {
889
819
  callback.current(api);
890
820
  });
@@ -1090,12 +1020,12 @@ const Physics = ({
1090
1020
  colliderStates,
1091
1021
  rigidBodyEvents,
1092
1022
  colliderEvents,
1093
- attractorStates,
1094
1023
  beforeStepCallbacks,
1095
1024
  afterStepCallbacks,
1096
1025
  isPaused: _paused,
1026
+ isDebug: _debug,
1097
1027
  step
1098
- }), [_paused, step]);
1028
+ }), [_paused, step, _debug, _colliders, _gravity]);
1099
1029
  const stepCallback = React.useCallback(delta => {
1100
1030
  if (!_paused) {
1101
1031
  step(delta);
@@ -1107,7 +1037,7 @@ const Physics = ({
1107
1037
  onStep: stepCallback,
1108
1038
  type: _updateLoop,
1109
1039
  updatePriority: updatePriority
1110
- }), children);
1040
+ }), _debug && /*#__PURE__*/React__default["default"].createElement(Debug, null), children);
1111
1041
  };
1112
1042
 
1113
1043
  function _extends() {
@@ -1623,96 +1553,6 @@ const MeshCollider = /*#__PURE__*/React.memo(props => {
1623
1553
  });
1624
1554
  MeshCollider.displayName = "MeshCollider";
1625
1555
 
1626
- function mapsEqual(map1, map2) {
1627
- var testVal;
1628
-
1629
- if (map1.size !== map2.size) {
1630
- return false;
1631
- }
1632
-
1633
- for (var [key, val] of map1) {
1634
- testVal = map2.get(key);
1635
-
1636
- if (testVal !== val || testVal === undefined && !map2.has(key)) {
1637
- return false;
1638
- }
1639
- }
1640
-
1641
- return true;
1642
- }
1643
-
1644
- const AttractorHelper = props => {
1645
- const {
1646
- scene
1647
- } = fiber.useThree();
1648
- const ref = React.useRef(null);
1649
- const normalsHelper = React.useRef();
1650
- const color = props.strength > 0 ? 0x0000ff : 0xff0000;
1651
- React.useEffect(() => {
1652
- if (ref.current) {
1653
- normalsHelper.current = new threeStdlib.VertexNormalsHelper(ref.current, props.range, color);
1654
- normalsHelper.current.frustumCulled = false;
1655
- scene.add(normalsHelper.current);
1656
- }
1657
-
1658
- return () => {
1659
- if (normalsHelper.current) {
1660
- scene.remove(normalsHelper.current);
1661
- }
1662
- };
1663
- }, [props]);
1664
- fiber.useFrame(() => {
1665
- if (ref.current) {
1666
- var _normalsHelper$curren;
1667
-
1668
- const worldPosition = props.object.getWorldPosition(_vector3);
1669
- ref.current.position.copy(worldPosition);
1670
- (_normalsHelper$curren = normalsHelper.current) === null || _normalsHelper$curren === void 0 ? void 0 : _normalsHelper$curren.update();
1671
- }
1672
- });
1673
- return /*#__PURE__*/React__default["default"].createElement("mesh", {
1674
- ref: ref,
1675
- position: props.object.position,
1676
- frustumCulled: false
1677
- }, /*#__PURE__*/React__default["default"].createElement("sphereGeometry", {
1678
- args: [0.2, 6, 6]
1679
- }), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
1680
- color: color,
1681
- wireframe: true
1682
- }));
1683
- };
1684
-
1685
- const Debug = /*#__PURE__*/React.memo(() => {
1686
- const {
1687
- world,
1688
- attractorStates
1689
- } = useRapier();
1690
- const ref = React.useRef(null);
1691
- const [attractors, setAttractors] = React.useState([]);
1692
- const currMap = React.useRef(new Map());
1693
- fiber.useFrame(() => {
1694
- const mesh = ref.current;
1695
- if (!mesh) return;
1696
- const buffers = world.debugRender();
1697
- mesh.geometry.setAttribute("position", new three.BufferAttribute(buffers.vertices, 3));
1698
- mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4)); // Update attractors
1699
-
1700
- if (!mapsEqual(currMap.current, attractorStates)) {
1701
- setAttractors([...attractorStates.values()]);
1702
- currMap.current = new Map(attractorStates);
1703
- }
1704
- });
1705
- return /*#__PURE__*/React__default["default"].createElement("group", null, /*#__PURE__*/React__default["default"].createElement("lineSegments", {
1706
- ref: ref,
1707
- frustumCulled: false
1708
- }, /*#__PURE__*/React__default["default"].createElement("lineBasicMaterial", {
1709
- color: 0xffffff,
1710
- vertexColors: true
1711
- }), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React__default["default"].createElement(AttractorHelper, _extends({
1712
- key: attractor.object.uuid
1713
- }, attractor))));
1714
- });
1715
-
1716
1556
  const _excluded = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
1717
1557
  const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, ref) => {
1718
1558
  const object = React.useRef(null);
@@ -1941,14 +1781,12 @@ Object.defineProperty(exports, 'RapierRigidBody', {
1941
1781
  get: function () { return rapier3dCompat.RigidBody; }
1942
1782
  });
1943
1783
  exports.AnyCollider = AnyCollider;
1944
- exports.Attractor = Attractor;
1945
1784
  exports.BallCollider = BallCollider;
1946
1785
  exports.CapsuleCollider = CapsuleCollider;
1947
1786
  exports.ConeCollider = ConeCollider;
1948
1787
  exports.ConvexHullCollider = ConvexHullCollider;
1949
1788
  exports.CuboidCollider = CuboidCollider;
1950
1789
  exports.CylinderCollider = CylinderCollider;
1951
- exports.Debug = Debug;
1952
1790
  exports.HeightfieldCollider = HeightfieldCollider;
1953
1791
  exports.InstancedRigidBodies = InstancedRigidBodies;
1954
1792
  exports.MeshCollider = MeshCollider;