@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.
- package/dist/declarations/src/components/Physics.d.ts +9 -6
- package/dist/declarations/src/index.d.ts +0 -3
- package/dist/react-three-rapier.cjs.dev.js +77 -239
- package/dist/react-three-rapier.cjs.prod.js +77 -239
- package/dist/react-three-rapier.esm.js +81 -241
- package/package.json +3 -3
- package/readme.md +7 -52
- package/dist/declarations/src/components/Attractor.d.ts +0 -50
@@ -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,
|
5
|
-
import { Quaternion, Euler, Vector3, Object3D, Matrix4,
|
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
|
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
|
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
|
-
|
641
|
+
world
|
641
642
|
} = useRapier();
|
642
|
-
const
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
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
|
-
//
|
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,
|
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.
|
3
|
+
"version": "0.15.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.
|
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.
|
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
|
-
|
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
|
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>;
|