@react-three/rapier 0.14.0 → 0.15.0-canary.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.
@@ -1,10 +1,10 @@
1
1
  import { ActiveEvents, ColliderDesc, EventQueue, RigidBodyDesc } from '@dimforge/rapier3d-compat';
2
2
  export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
3
3
  import { useFrame, useThree } from '@react-three/fiber';
4
- import React, { useRef, useMemo, useEffect, useContext, useState, memo, createContext, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
5
- import { Quaternion, Euler, Vector3, Object3D, Matrix4, MathUtils, BufferAttribute, DynamicDrawUsage } from 'three';
4
+ import React, { useRef, useEffect, memo, useMemo, useContext, useState, createContext, useCallback, forwardRef, useImperativeHandle, Fragment } from 'react';
5
+ import { Quaternion, Euler, Vector3, Object3D, Matrix4, BufferAttribute, MathUtils, DynamicDrawUsage } from 'three';
6
6
  import { useAsset } from 'use-asset';
7
- import { mergeVertices, VertexNormalsHelper } from 'three-stdlib';
7
+ import { mergeVertices } from 'three-stdlib';
8
8
 
9
9
  function _defineProperty(obj, key, value) {
10
10
  if (key in obj) {
@@ -153,6 +153,61 @@ function useConst(initialValue) {
153
153
  return ref.current.value;
154
154
  }
155
155
 
156
+ const useRaf = callback => {
157
+ const cb = useRef(callback);
158
+ const raf = useRef(0);
159
+ const lastFrame = useRef(0);
160
+ useEffect(() => {
161
+ cb.current = callback;
162
+ }, [callback]);
163
+ useEffect(() => {
164
+ const loop = () => {
165
+ const now = performance.now();
166
+ const delta = now - lastFrame.current;
167
+ raf.current = requestAnimationFrame(loop);
168
+ cb.current(delta / 1000);
169
+ lastFrame.current = now;
170
+ };
171
+
172
+ raf.current = requestAnimationFrame(loop);
173
+ return () => cancelAnimationFrame(raf.current);
174
+ }, []);
175
+ };
176
+
177
+ const UseFrameStepper = ({
178
+ onStep,
179
+ updatePriority
180
+ }) => {
181
+ useFrame((_, dt) => {
182
+ onStep(dt);
183
+ }, updatePriority);
184
+ return null;
185
+ };
186
+
187
+ const RafStepper = ({
188
+ onStep
189
+ }) => {
190
+ useRaf(dt => {
191
+ onStep(dt);
192
+ });
193
+ return null;
194
+ };
195
+
196
+ const FrameStepper = ({
197
+ onStep,
198
+ type,
199
+ updatePriority
200
+ }) => {
201
+ return type === "independent" ? /*#__PURE__*/React.createElement(RafStepper, {
202
+ onStep: onStep
203
+ }) : /*#__PURE__*/React.createElement(UseFrameStepper, {
204
+ onStep: onStep,
205
+ updatePriority: updatePriority
206
+ });
207
+ };
208
+
209
+ var FrameStepper$1 = /*#__PURE__*/memo(FrameStepper);
210
+
156
211
  function _objectWithoutPropertiesLoose(source, excluded) {
157
212
  if (source == null) return {};
158
213
  var target = {};
@@ -581,146 +636,27 @@ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
581
636
  return colliderProps;
582
637
  };
583
638
 
584
- const calcForceByType = {
585
- static: (s, m2, r, d, G) => s,
586
- linear: (s, m2, r, d, G) => s * (d / r),
587
- newtonian: (s, m2, r, d, G) => G * s * m2 / Math.pow(d, 2)
588
- };
589
- const applyAttractorForceOnRigidBody = (rigidBody, {
590
- object,
591
- strength,
592
- range,
593
- gravitationalConstant,
594
- collisionGroups,
595
- type
596
- }) => {
597
- const rbPosition = rigidBody.translation();
598
-
599
- _position.set(rbPosition.x, rbPosition.y, rbPosition.z);
600
-
601
- const worldPosition = object.getWorldPosition(new Vector3());
602
- const distance = worldPosition.distanceTo(_position);
603
-
604
- if (distance < range) {
605
- let force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant); // Prevent wild forces when Attractors collide
606
-
607
- force = force === Infinity ? strength : force; // Naively test if the rigidBody contains a collider in one of the collision groups
608
-
609
- let isRigidBodyInCollisionGroup = collisionGroups === undefined ? true : false;
610
-
611
- if (collisionGroups !== undefined) {
612
- for (let i = 0; i < rigidBody.numColliders(); i++) {
613
- const collider = rigidBody.collider(i);
614
- const colliderCollisionGroups = collider.collisionGroups();
615
-
616
- if ((collisionGroups >> 16 & colliderCollisionGroups) != 0 && (colliderCollisionGroups >> 16 & collisionGroups) != 0) {
617
- isRigidBodyInCollisionGroup = true;
618
- break;
619
- }
620
- }
621
- }
622
-
623
- if (isRigidBodyInCollisionGroup) {
624
- _vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);
625
-
626
- rigidBody.applyImpulse(_vector3, true);
627
- }
628
- }
629
- };
630
- const Attractor = /*#__PURE__*/memo(props => {
631
- const {
632
- position = [0, 0, 0],
633
- strength = 1,
634
- range = 10,
635
- type = "static",
636
- gravitationalConstant = 6.673e-11,
637
- collisionGroups
638
- } = props;
639
+ const Debug = /*#__PURE__*/memo(() => {
639
640
  const {
640
- attractorStates
641
+ world
641
642
  } = useRapier();
642
- const object = useRef(null);
643
- useEffect(() => {
644
- var _object$current;
645
-
646
- let uuid = ((_object$current = object.current) === null || _object$current === void 0 ? void 0 : _object$current.uuid) || "_";
647
-
648
- if (object.current) {
649
- attractorStates.set(uuid, {
650
- object: object.current,
651
- strength,
652
- range,
653
- type,
654
- gravitationalConstant,
655
- collisionGroups
656
- });
657
- }
658
-
659
- return () => {
660
- attractorStates.delete(uuid);
661
- };
662
- }, [props]);
663
- return /*#__PURE__*/React.createElement("object3D", {
664
- ref: object,
665
- position: position
643
+ const ref = useRef(null);
644
+ useFrame(() => {
645
+ const mesh = ref.current;
646
+ if (!mesh) return;
647
+ const buffers = world.debugRender();
648
+ mesh.geometry.setAttribute("position", new BufferAttribute(buffers.vertices, 3));
649
+ mesh.geometry.setAttribute("color", new BufferAttribute(buffers.colors, 4));
666
650
  });
651
+ return /*#__PURE__*/React.createElement("group", null, /*#__PURE__*/React.createElement("lineSegments", {
652
+ ref: ref,
653
+ frustumCulled: false
654
+ }, /*#__PURE__*/React.createElement("lineBasicMaterial", {
655
+ color: 0xffffff,
656
+ vertexColors: true
657
+ }), /*#__PURE__*/React.createElement("bufferGeometry", null)));
667
658
  });
668
659
 
669
- const useRaf = callback => {
670
- const cb = useRef(callback);
671
- const raf = useRef(0);
672
- const lastFrame = useRef(0);
673
- useEffect(() => {
674
- cb.current = callback;
675
- }, [callback]);
676
- useEffect(() => {
677
- const loop = () => {
678
- const now = performance.now();
679
- const delta = now - lastFrame.current;
680
- raf.current = requestAnimationFrame(loop);
681
- cb.current(delta / 1000);
682
- lastFrame.current = now;
683
- };
684
-
685
- raf.current = requestAnimationFrame(loop);
686
- return () => cancelAnimationFrame(raf.current);
687
- }, []);
688
- };
689
-
690
- const UseFrameStepper = ({
691
- onStep,
692
- updatePriority
693
- }) => {
694
- useFrame((_, dt) => {
695
- onStep(dt);
696
- }, updatePriority);
697
- return null;
698
- };
699
-
700
- const RafStepper = ({
701
- onStep
702
- }) => {
703
- useRaf(dt => {
704
- onStep(dt);
705
- });
706
- return null;
707
- };
708
-
709
- const FrameStepper = ({
710
- onStep,
711
- type,
712
- updatePriority
713
- }) => {
714
- return type === "independent" ? /*#__PURE__*/React.createElement(RafStepper, {
715
- onStep: onStep
716
- }) : /*#__PURE__*/React.createElement(UseFrameStepper, {
717
- onStep: onStep,
718
- updatePriority: updatePriority
719
- });
720
- };
721
-
722
- var FrameStepper$1 = /*#__PURE__*/memo(FrameStepper);
723
-
724
660
  const rapierContext = /*#__PURE__*/createContext(undefined);
725
661
 
726
662
  const getCollisionPayloadFromSource = (target, other) => {
@@ -764,7 +700,8 @@ const Physics = ({
764
700
  paused: _paused = false,
765
701
  interpolate: _interpolate = true,
766
702
  updatePriority,
767
- updateLoop: _updateLoop = "follow"
703
+ updateLoop: _updateLoop = "follow",
704
+ debug: _debug = false
768
705
  }) => {
769
706
  const rapier = useAsset(importRapier);
770
707
  const {
@@ -784,7 +721,6 @@ const Physics = ({
784
721
  const rigidBodyEvents = useConst(() => new Map());
785
722
  const colliderEvents = useConst(() => new Map());
786
723
  const eventQueue = useConst(() => new EventQueue(false));
787
- const attractorStates = useConst(() => new Map());
788
724
  const beforeStepCallbacks = useConst(() => new Set());
789
725
  const afterStepCallbacks = useConst(() => new Set()); // Init world
790
726
 
@@ -853,13 +789,7 @@ const Physics = ({
853
789
  const clampedDelta = MathUtils.clamp(dt, 0, 0.2);
854
790
 
855
791
  const stepWorld = () => {
856
- // Apply attractors
857
- world.forEachRigidBody(body => {
858
- attractorStates.forEach(attractorState => {
859
- applyAttractorForceOnRigidBody(body, attractorState);
860
- });
861
- }); // Trigger beforeStep callbacks
862
-
792
+ // Trigger beforeStep callbacks
863
793
  beforeStepCallbacks.forEach(callback => {
864
794
  callback.current(api);
865
795
  });
@@ -1065,12 +995,12 @@ const Physics = ({
1065
995
  colliderStates,
1066
996
  rigidBodyEvents,
1067
997
  colliderEvents,
1068
- attractorStates,
1069
998
  beforeStepCallbacks,
1070
999
  afterStepCallbacks,
1071
1000
  isPaused: _paused,
1001
+ isDebug: _debug,
1072
1002
  step
1073
- }), [_paused, step]);
1003
+ }), [_paused, step, _debug, _colliders, _gravity]);
1074
1004
  const stepCallback = useCallback(delta => {
1075
1005
  if (!_paused) {
1076
1006
  step(delta);
@@ -1082,7 +1012,7 @@ const Physics = ({
1082
1012
  onStep: stepCallback,
1083
1013
  type: _updateLoop,
1084
1014
  updatePriority: updatePriority
1085
- }), children);
1015
+ }), _debug && /*#__PURE__*/React.createElement(Debug, null), children);
1086
1016
  };
1087
1017
 
1088
1018
  function _extends() {
@@ -1598,96 +1528,6 @@ const MeshCollider = /*#__PURE__*/memo(props => {
1598
1528
  });
1599
1529
  MeshCollider.displayName = "MeshCollider";
1600
1530
 
1601
- function mapsEqual(map1, map2) {
1602
- var testVal;
1603
-
1604
- if (map1.size !== map2.size) {
1605
- return false;
1606
- }
1607
-
1608
- for (var [key, val] of map1) {
1609
- testVal = map2.get(key);
1610
-
1611
- if (testVal !== val || testVal === undefined && !map2.has(key)) {
1612
- return false;
1613
- }
1614
- }
1615
-
1616
- return true;
1617
- }
1618
-
1619
- const AttractorHelper = props => {
1620
- const {
1621
- scene
1622
- } = useThree();
1623
- const ref = useRef(null);
1624
- const normalsHelper = useRef();
1625
- const color = props.strength > 0 ? 0x0000ff : 0xff0000;
1626
- useEffect(() => {
1627
- if (ref.current) {
1628
- normalsHelper.current = new VertexNormalsHelper(ref.current, props.range, color);
1629
- normalsHelper.current.frustumCulled = false;
1630
- scene.add(normalsHelper.current);
1631
- }
1632
-
1633
- return () => {
1634
- if (normalsHelper.current) {
1635
- scene.remove(normalsHelper.current);
1636
- }
1637
- };
1638
- }, [props]);
1639
- useFrame(() => {
1640
- if (ref.current) {
1641
- var _normalsHelper$curren;
1642
-
1643
- const worldPosition = props.object.getWorldPosition(_vector3);
1644
- ref.current.position.copy(worldPosition);
1645
- (_normalsHelper$curren = normalsHelper.current) === null || _normalsHelper$curren === void 0 ? void 0 : _normalsHelper$curren.update();
1646
- }
1647
- });
1648
- return /*#__PURE__*/React.createElement("mesh", {
1649
- ref: ref,
1650
- position: props.object.position,
1651
- frustumCulled: false
1652
- }, /*#__PURE__*/React.createElement("sphereGeometry", {
1653
- args: [0.2, 6, 6]
1654
- }), /*#__PURE__*/React.createElement("meshBasicMaterial", {
1655
- color: color,
1656
- wireframe: true
1657
- }));
1658
- };
1659
-
1660
- const Debug = /*#__PURE__*/memo(() => {
1661
- const {
1662
- world,
1663
- attractorStates
1664
- } = useRapier();
1665
- const ref = useRef(null);
1666
- const [attractors, setAttractors] = useState([]);
1667
- const currMap = useRef(new Map());
1668
- useFrame(() => {
1669
- const mesh = ref.current;
1670
- if (!mesh) return;
1671
- const buffers = world.debugRender();
1672
- mesh.geometry.setAttribute("position", new BufferAttribute(buffers.vertices, 3));
1673
- mesh.geometry.setAttribute("color", new BufferAttribute(buffers.colors, 4)); // Update attractors
1674
-
1675
- if (!mapsEqual(currMap.current, attractorStates)) {
1676
- setAttractors([...attractorStates.values()]);
1677
- currMap.current = new Map(attractorStates);
1678
- }
1679
- });
1680
- return /*#__PURE__*/React.createElement("group", null, /*#__PURE__*/React.createElement("lineSegments", {
1681
- ref: ref,
1682
- frustumCulled: false
1683
- }, /*#__PURE__*/React.createElement("lineBasicMaterial", {
1684
- color: 0xffffff,
1685
- vertexColors: true
1686
- }), /*#__PURE__*/React.createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React.createElement(AttractorHelper, _extends({
1687
- key: attractor.object.uuid
1688
- }, attractor))));
1689
- });
1690
-
1691
1531
  const _excluded = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
1692
1532
  const InstancedRigidBodies = /*#__PURE__*/memo( /*#__PURE__*/forwardRef((props, ref) => {
1693
1533
  const object = useRef(null);
@@ -1903,4 +1743,4 @@ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16)
1903
1743
 
1904
1744
  const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1905
1745
 
1906
- export { AnyCollider, Attractor, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, euler, interactionGroups, quat, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useSphericalJoint, vec3 };
1746
+ export { AnyCollider, BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, euler, interactionGroups, quat, useAfterPhysicsStep, useBeforePhysicsStep, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useSphericalJoint, vec3 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.14.0",
3
+ "version": "0.15.0-canary.0",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
@@ -18,12 +18,12 @@
18
18
  "@types/react-dom": "18.0.2",
19
19
  "@types/three": "0.139.0",
20
20
  "@vitejs/plugin-react": "^2.1.0",
21
- "@vitest/ui": "0.25.2",
21
+ "@vitest/ui": "0.29.7",
22
22
  "happy-dom": "7.5.5",
23
23
  "react": "18.2.0",
24
24
  "react-dom": "18.2.0",
25
25
  "three": "0.146.0",
26
- "vitest": "0.25.2"
26
+ "vitest": "0.29.7"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@react-three/fiber": "8.9.1",
package/readme.md CHANGED
@@ -21,6 +21,7 @@ For available APIs, see <a href="https://pmndrs.github.io/react-three-rapier/">
21
21
 
22
22
  The goal of this library to is to provide a fast physics engine with minimal friction and small, straight forward API.
23
23
 
24
+ <!-- omit from toc -->
24
25
  ## Basic Usage
25
26
 
26
27
  ```tsx
@@ -32,14 +33,12 @@ const App = () => {
32
33
  return (
33
34
  <Canvas>
34
35
  <Suspense>
35
- <Physics>
36
+ <Physics debug>
36
37
  <RigidBody colliders={"hull"} restitution={2}>
37
38
  <Torus />
38
39
  </RigidBody>
39
40
 
40
41
  <CuboidCollider position={[0, -2, 0]} args={[20, .5, 20]} />
41
-
42
- <Debug />
43
42
  </Physics>
44
43
  </Suspense>
45
44
  </Canvas>
@@ -49,17 +48,16 @@ const App = () => {
49
48
 
50
49
  ---
51
50
 
51
+ <!-- omit from toc -->
52
52
  ## 📝 Readme note
53
53
  Below follows a guide on core concepts for `react-three/rapier`.
54
54
  For full API outline and documentation, see 🧩 [API Docs](https://pmndrs.github.io/react-three-rapier/).
55
55
 
56
56
  ---
57
57
 
58
+ <!-- omit from toc -->
58
59
  ## Readme Topics
59
60
 
60
- - [Basic Usage](#basic-usage)
61
- - [📝 Readme note](#-readme-note)
62
- - [Readme Topics](#readme-topics)
63
61
  - [The Physics Component](#the-physics-component)
64
62
  - [The RigidBody Component](#the-rigidbody-component)
65
63
  - [Automatic Colliders](#automatic-colliders)
@@ -73,8 +71,6 @@ For full API outline and documentation, see 🧩 [API Docs](https://pmndrs.githu
73
71
  - [Contact force events](#contact-force-events)
74
72
  - [Sensors](#sensors)
75
73
  - [🖼 Sensors Example](#-sensors-example)
76
- - [Attractors](#attractors)
77
- - [🖼 Attractors Example](#-attractors-example)
78
74
  - [Configuring Time Step Size](#configuring-time-step-size)
79
75
  - [Joints](#joints)
80
76
  - [Fixed Joint](#fixed-joint)
@@ -334,17 +330,15 @@ const Scene = () => {
334
330
 
335
331
  ## Debug
336
332
 
337
- Use the Debug component to see live representations of all colliders in a scene, using the live debug buffer from the physics engine.
333
+ Set the `debug` prop on `<Physics />` to see live representations of all colliders in a scene, using the live debug buffer from the physics engine.
338
334
 
339
335
  ```tsx
340
336
  import { Box, Sphere } from "@react-three/drei";
341
- import { RigidBody, Debug } from "@react-three/rapier";
337
+ import { RigidBody } from "@react-three/rapier";
342
338
 
343
339
  const Scene = () => {
344
340
  return (
345
- <Physics>
346
- <Debug />
347
-
341
+ <Physics debug>
348
342
  <RigidBody>
349
343
  <Box />
350
344
  </RigidBody>
@@ -605,45 +599,6 @@ To detect when a collider enters or leaves another collider, you can use the `on
605
599
  ### 🖼 Sensors Example
606
600
  <a href="https://codesandbox.io/s/react-three-rapier-sensors-byjmsk"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-sensors.jpg" width="240" /></a>
607
601
 
608
- ## Attractors
609
-
610
- An attractor simulates a source of gravity. Any `RigidBody` within range will be _pulled_ (attracted) toward the attractor.
611
- Setting the `strength` to a negative value will cause the `RigidBody` to be _pushed_ (repelled) away from the attractor.
612
-
613
- The force applied to rigid-bodies within range is calculated differently depending on the `type`.
614
-
615
- 🧩 See [Attractor docs](https://pmndrs.github.io/react-three-rapier/interfaces/AttractorProps.html) for all available props.
616
-
617
- ```tsx
618
- // Standard attractor
619
- <Attractor range={10} strength={5} type="linear" position={[5, -5, 0]} />
620
-
621
- // An attractor with negative strength, repels RigidBodies
622
- <Attractor range={10} strength={-5} position={[5, -5, 0]} />
623
-
624
- // You can also assign InteractionGroups.
625
- // An attractor belonging to group 0 only affecting bodies in group 2, and 3
626
- <Attractor range={10} strength={10} position={[5, -5, 0]} collisionGroups={interactionGroups(0, [2,3])} />
627
- ```
628
-
629
- Gravity types:
630
-
631
- - "static" (Default)
632
- Static gravity means that the same force (`strength`) is applied on all rigid-bodies within range, regardless of distance.
633
-
634
- - "linear"
635
- Linear gravity means that force is calculated as `strength * distance / range`. That means the force applied decreases the farther a rigid-body is from the attractor position.
636
-
637
- - "newtonian"
638
- Newtonian gravity uses the traditional method of calculating gravitational force (`F = GMm/r^2`) and as such force is calculated as `gravitationalConstant * mass1 * mass2 / Math.pow(distance, 2)`.
639
- - `gravitationalConstant` defaults to 6.673e-11 but you can provide your own
640
- - `mass1` here is the "mass" of the Attractor, which is just the `strength` property
641
- - `mass2` is the mass of the rigid-body at the time of calculation. Note that rigid-bodies with colliders will use the mass provided to the collider. This is not a value you can control from the attractor, only from wherever you're creating rigid-body components in the scene.
642
- - `distance` is the distance between the attractor and rigid-body at the time of calculation
643
-
644
- ### 🖼 Attractors Example
645
- <a href="https://codesandbox.io/s/react-three-rapier-attractors-oyj640"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/example-attractors.jpg" width="240" /></a>
646
-
647
602
  ## Configuring Time Step Size
648
603
 
649
604
  By default, `<Physics>` will simulate the physics world at a fixed rate of 60 frames per second. This can be changed by setting the `timeStep` prop on `<Physics>`:
@@ -1,50 +0,0 @@
1
- import { InteractionGroups, RigidBody } from "@dimforge/rapier3d-compat";
2
- import { FC } from "react";
3
- import { Object3D } from "three";
4
- import { Object3DProps } from "@react-three/fiber";
5
- export declare type AttractorGravityType = "static" | "linear" | "newtonian";
6
- export interface AttractorProps {
7
- /**
8
- * The relative position of this attractor
9
- */
10
- position?: Object3DProps["position"];
11
- /**
12
- * The strength of the attractor.
13
- * Positive values attract, negative values repel.
14
- *
15
- * @defaultValue 1
16
- */
17
- strength?: number;
18
- /**
19
- * The range of the attractor. Will not affect objects outside of this range.
20
- *
21
- * @defaultValue 10
22
- * @min 0
23
- */
24
- range?: number;
25
- /**
26
- * The type of gravity to use.
27
- * - static: The gravity is constant and does not change over time.
28
- * - linear: The gravity is linearly interpolated the closer the object is to the attractor.
29
- * - newtonian: The gravity is calculated using the newtonian gravity formula.
30
- * @defaultValue "static"
31
- */
32
- type?: AttractorGravityType;
33
- /**
34
- * The mass of the attractor. Used when type is `newtonian`.
35
- * @defaultValue 6.673e-11
36
- */
37
- gravitationalConstant?: number;
38
- /**
39
- * The collision groups that this attractor will apply effects to. If a RigidBody contains one or more colliders that are in one of the mask group, it will be affected by this attractor.
40
- * If not specified, the attractor will apply effects to all RigidBodies.
41
- */
42
- collisionGroups?: InteractionGroups;
43
- }
44
- export interface AttractorState extends Required<Omit<AttractorProps, "position" | "collisionGroups">> {
45
- object: Object3D;
46
- collisionGroups?: InteractionGroups;
47
- }
48
- export declare type AttractorStateMap = Map<Object3D["uuid"], AttractorState>;
49
- export declare const applyAttractorForceOnRigidBody: (rigidBody: RigidBody, { object, strength, range, gravitationalConstant, collisionGroups, type }: AttractorState) => void;
50
- export declare const Attractor: FC<AttractorProps>;