@react-three/rapier 0.6.4 → 0.6.7
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/Debug.d.ts +13 -2
- package/dist/declarations/src/InstancedRigidBodies.d.ts +1 -1
- package/dist/declarations/src/Physics.d.ts +8 -6
- package/dist/declarations/src/RigidBody.d.ts +3 -2
- package/dist/declarations/src/types.d.ts +5 -1
- package/dist/declarations/src/utils.d.ts +9 -1
- package/dist/react-three-rapier.cjs.dev.js +163 -58
- package/dist/react-three-rapier.cjs.prod.js +163 -58
- package/dist/react-three-rapier.esm.js +165 -60
- package/package.json +3 -2
- package/readme.md +9 -5
@@ -7,6 +7,8 @@ var React = require('react');
|
|
7
7
|
var useAsset = require('use-asset');
|
8
8
|
var fiber = require('@react-three/fiber');
|
9
9
|
var three = require('three');
|
10
|
+
var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
|
11
|
+
var threeStdlib = require('three-stdlib');
|
10
12
|
|
11
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
12
14
|
|
@@ -73,11 +75,13 @@ const decomposeMatrix4 = m => {
|
|
73
75
|
};
|
74
76
|
};
|
75
77
|
const scaleColliderArgs = (shape, args, scale) => {
|
76
|
-
// Heightfield
|
77
|
-
const newArgs = args.slice();
|
78
|
+
const newArgs = args.slice(); // Heightfield uses a vector
|
78
79
|
|
79
80
|
if (shape === "heightfield") {
|
80
|
-
newArgs[3]
|
81
|
+
const s = newArgs[3];
|
82
|
+
s.x *= scale.x;
|
83
|
+
s.x *= scale.y;
|
84
|
+
s.x *= scale.z;
|
81
85
|
return newArgs;
|
82
86
|
} // Trimesh and convex scale the vertices
|
83
87
|
|
@@ -85,9 +89,10 @@ const scaleColliderArgs = (shape, args, scale) => {
|
|
85
89
|
if (shape === "trimesh" || shape === "convexHull") {
|
86
90
|
newArgs[0] = scaleVertices(newArgs[0], scale);
|
87
91
|
return newArgs;
|
88
|
-
}
|
92
|
+
} // Prepfill with some extra
|
93
|
+
|
89
94
|
|
90
|
-
const scaleArray = [scale.x, scale.y, scale.z];
|
95
|
+
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
91
96
|
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
92
97
|
};
|
93
98
|
const createColliderFromOptions = ({
|
@@ -117,6 +122,10 @@ const createColliderFromOptions = ({
|
|
117
122
|
w: qRotation.w
|
118
123
|
}).setRestitution((_options$restitution = options === null || options === void 0 ? void 0 : options.restitution) !== null && _options$restitution !== void 0 ? _options$restitution : 0).setRestitutionCombineRule((_options$restitutionC = options === null || options === void 0 ? void 0 : options.restitutionCombineRule) !== null && _options$restitutionC !== void 0 ? _options$restitutionC : rapier3dCompat.CoefficientCombineRule.Average).setFriction((_options$friction = options === null || options === void 0 ? void 0 : options.friction) !== null && _options$friction !== void 0 ? _options$friction : 0.7).setFrictionCombineRule((_options$frictionComb = options === null || options === void 0 ? void 0 : options.frictionCombineRule) !== null && _options$frictionComb !== void 0 ? _options$frictionComb : rapier3dCompat.CoefficientCombineRule.Average);
|
119
124
|
|
125
|
+
if (colliderShape === "heightfield") {
|
126
|
+
console.log(colliderDesc);
|
127
|
+
}
|
128
|
+
|
120
129
|
if (hasCollisionEvents) {
|
121
130
|
colliderDesc = colliderDesc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
|
122
131
|
} // If any of the mass properties are specified, add mass properties
|
@@ -244,15 +253,15 @@ const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents
|
|
244
253
|
{
|
245
254
|
var _g$index;
|
246
255
|
|
247
|
-
const
|
248
|
-
|
249
|
-
desc = rapier3dCompat.ColliderDesc.trimesh(
|
256
|
+
const clonedGeometry = geometry.index ? geometry.clone() : BufferGeometryUtils.mergeVertices(geometry);
|
257
|
+
const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
|
258
|
+
desc = rapier3dCompat.ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
|
250
259
|
}
|
251
260
|
break;
|
252
261
|
|
253
262
|
case "hull":
|
254
|
-
const g = geometry.clone().scale(scale.x, scale.y, scale.z);
|
255
263
|
{
|
264
|
+
const g = geometry.clone().scale(scale.x, scale.y, scale.z);
|
256
265
|
desc = rapier3dCompat.ColliderDesc.convexHull(g.attributes.position.array);
|
257
266
|
}
|
258
267
|
break;
|
@@ -469,10 +478,15 @@ const Physics = ({
|
|
469
478
|
colliders: _colliders = "cuboid",
|
470
479
|
gravity: _gravity = [0, -9.81, 0],
|
471
480
|
children,
|
472
|
-
timeStep: _timeStep =
|
481
|
+
timeStep: _timeStep = 1 / 60,
|
482
|
+
maxSubSteps: _maxSubSteps = 10,
|
473
483
|
paused: _paused = false
|
474
484
|
}) => {
|
475
485
|
const rapier = useAsset.useAsset(importRapier);
|
486
|
+
const [isPaused, setIsPaused] = React.useState(_paused);
|
487
|
+
React.useEffect(() => {
|
488
|
+
setIsPaused(_paused);
|
489
|
+
}, [_paused]);
|
476
490
|
const worldRef = React.useRef();
|
477
491
|
const getWorldRef = React.useRef(() => {
|
478
492
|
if (!worldRef.current) {
|
@@ -492,7 +506,6 @@ const Physics = ({
|
|
492
506
|
return () => {
|
493
507
|
if (world) {
|
494
508
|
world.free();
|
495
|
-
worldRef.current = undefined;
|
496
509
|
}
|
497
510
|
};
|
498
511
|
}, []); // Update gravity
|
@@ -504,22 +517,46 @@ const Physics = ({
|
|
504
517
|
world.gravity = vectorArrayToVector3(_gravity);
|
505
518
|
}
|
506
519
|
}, [_gravity]);
|
507
|
-
const
|
508
|
-
|
520
|
+
const [steppingState] = React.useState({
|
521
|
+
time: 0,
|
522
|
+
lastTime: 0,
|
523
|
+
accumulator: 0
|
524
|
+
});
|
525
|
+
fiber.useFrame((_, delta) => {
|
509
526
|
const world = worldRef.current;
|
510
|
-
if (!world) return;
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
527
|
+
if (!world) return;
|
528
|
+
world.timestep = _timeStep;
|
529
|
+
/**
|
530
|
+
* Fixed timeStep simulation progression
|
531
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
532
|
+
*/
|
533
|
+
|
534
|
+
let previousTranslations = {}; // don't step time forwards if paused
|
535
|
+
|
536
|
+
const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
|
537
|
+
const timeStepMs = _timeStep * 1000;
|
538
|
+
const timeSinceLast = nowTime - steppingState.lastTime;
|
539
|
+
steppingState.lastTime = nowTime;
|
540
|
+
steppingState.accumulator += timeSinceLast;
|
541
|
+
|
542
|
+
if (!_paused) {
|
543
|
+
let subSteps = 0;
|
544
|
+
|
545
|
+
while (steppingState.accumulator >= timeStepMs && subSteps < _maxSubSteps) {
|
546
|
+
// Collect previous state
|
547
|
+
world.bodies.forEach(b => {
|
548
|
+
previousTranslations[b.handle] = {
|
549
|
+
rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
|
550
|
+
translation: rapierVector3ToVector3(b.translation())
|
551
|
+
};
|
552
|
+
});
|
553
|
+
world.step(eventQueue);
|
554
|
+
subSteps++;
|
555
|
+
steppingState.accumulator -= timeStepMs;
|
556
|
+
}
|
520
557
|
}
|
521
558
|
|
522
|
-
|
559
|
+
const interpolationAlpha = steppingState.accumulator % timeStepMs / timeStepMs; // Update meshes
|
523
560
|
|
524
561
|
rigidBodyStates.forEach((state, handle) => {
|
525
562
|
const rigidBody = world.getRigidBody(handle);
|
@@ -541,11 +578,16 @@ const Physics = ({
|
|
541
578
|
state.isSleeping = rigidBody.isSleeping();
|
542
579
|
}
|
543
580
|
|
544
|
-
if (!rigidBody || rigidBody.isSleeping() ||
|
581
|
+
if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
|
545
582
|
return;
|
546
583
|
}
|
547
584
|
|
548
|
-
|
585
|
+
let oldState = previousTranslations[rigidBody.handle];
|
586
|
+
let newTranslation = rapierVector3ToVector3(rigidBody.translation());
|
587
|
+
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
588
|
+
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
589
|
+
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
590
|
+
state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
|
549
591
|
|
550
592
|
if (state.mesh instanceof three.InstancedMesh) {
|
551
593
|
state.mesh.instanceMatrix.needsUpdate = true;
|
@@ -595,7 +637,6 @@ const Physics = ({
|
|
595
637
|
});
|
596
638
|
}
|
597
639
|
});
|
598
|
-
time.current = now;
|
599
640
|
});
|
600
641
|
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
601
642
|
const context = React.useMemo(() => ({
|
@@ -607,13 +648,32 @@ const Physics = ({
|
|
607
648
|
},
|
608
649
|
colliderMeshes,
|
609
650
|
rigidBodyStates,
|
610
|
-
rigidBodyEvents
|
611
|
-
|
651
|
+
rigidBodyEvents,
|
652
|
+
isPaused
|
653
|
+
}), [isPaused]);
|
612
654
|
return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
|
613
655
|
value: context
|
614
656
|
}, children);
|
615
657
|
};
|
616
658
|
|
659
|
+
function _extends() {
|
660
|
+
_extends = Object.assign || function (target) {
|
661
|
+
for (var i = 1; i < arguments.length; i++) {
|
662
|
+
var source = arguments[i];
|
663
|
+
|
664
|
+
for (var key in source) {
|
665
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
666
|
+
target[key] = source[key];
|
667
|
+
}
|
668
|
+
}
|
669
|
+
}
|
670
|
+
|
671
|
+
return target;
|
672
|
+
};
|
673
|
+
|
674
|
+
return _extends.apply(this, arguments);
|
675
|
+
}
|
676
|
+
|
617
677
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
618
678
|
if (source == null) return {};
|
619
679
|
var target = {};
|
@@ -880,7 +940,8 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
|
|
880
940
|
return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
|
881
941
|
};
|
882
942
|
|
883
|
-
const _excluded$1 = ["children"]
|
943
|
+
const _excluded$1 = ["children"],
|
944
|
+
_excluded2 = ["type", "position", "rotation"];
|
884
945
|
const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
|
885
946
|
const useRigidBodyContext = () => React.useContext(RigidBodyContext); // RigidBody
|
886
947
|
|
@@ -891,6 +952,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
891
952
|
props = _objectWithoutProperties(_ref, _excluded$1);
|
892
953
|
|
893
954
|
const [object, api] = useRigidBody(props);
|
955
|
+
|
956
|
+
const objectProps = _objectWithoutProperties(props, _excluded2);
|
957
|
+
|
894
958
|
React.useImperativeHandle(ref, () => api);
|
895
959
|
return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
|
896
960
|
value: {
|
@@ -899,9 +963,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
899
963
|
hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
|
900
964
|
options: props
|
901
965
|
}
|
902
|
-
}, /*#__PURE__*/React__default["default"].createElement("object3D", {
|
966
|
+
}, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
|
903
967
|
ref: object
|
904
|
-
}, children));
|
968
|
+
}, objectProps), children));
|
905
969
|
});
|
906
970
|
|
907
971
|
const MeshCollider = ({
|
@@ -964,6 +1028,17 @@ const geometryFromCollider = collider => {
|
|
964
1028
|
return new three.BoxBufferGeometry(x * 2 + 0.01, y * 2 + 0.01, z * 2 + 0.01);
|
965
1029
|
}
|
966
1030
|
|
1031
|
+
case rapier3dCompat.ShapeType.RoundCuboid:
|
1032
|
+
{
|
1033
|
+
const {
|
1034
|
+
x,
|
1035
|
+
y,
|
1036
|
+
z
|
1037
|
+
} = collider.shape.halfExtents;
|
1038
|
+
const radius = collider.shape.borderRadius;
|
1039
|
+
return new threeStdlib.RoundedBoxGeometry(x * 2 + radius * 2, y * 2 + radius * 2, z * 2 + radius * 2, 8, radius);
|
1040
|
+
}
|
1041
|
+
|
967
1042
|
case rapier3dCompat.ShapeType.Ball:
|
968
1043
|
{
|
969
1044
|
const r = collider.shape.radius;
|
@@ -999,7 +1074,38 @@ const geometryFromCollider = collider => {
|
|
999
1074
|
{
|
1000
1075
|
const r = collider.shape.radius;
|
1001
1076
|
const h = collider.shape.halfHeight;
|
1002
|
-
const g = new three.CylinderBufferGeometry(r, r, h);
|
1077
|
+
const g = new three.CylinderBufferGeometry(r, r, h * 2);
|
1078
|
+
return g;
|
1079
|
+
}
|
1080
|
+
|
1081
|
+
case rapier3dCompat.ShapeType.Capsule:
|
1082
|
+
{
|
1083
|
+
const r = collider.shape.radius;
|
1084
|
+
const h = collider.shape.halfHeight;
|
1085
|
+
const g = new three.CapsuleBufferGeometry(r, h * 2, 4, 8);
|
1086
|
+
return g;
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
case rapier3dCompat.ShapeType.Cone:
|
1090
|
+
{
|
1091
|
+
const r = collider.shape.radius;
|
1092
|
+
const h = collider.shape.halfHeight;
|
1093
|
+
const g = new three.ConeBufferGeometry(r, h * 2, 16);
|
1094
|
+
return g;
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
case rapier3dCompat.ShapeType.HeightField:
|
1098
|
+
{
|
1099
|
+
const rows = collider.shape.nrows;
|
1100
|
+
const cols = collider.shape.ncols;
|
1101
|
+
const heights = collider.shape.heights;
|
1102
|
+
const scale = collider.shape.scale;
|
1103
|
+
const g = new three.PlaneGeometry(scale.x, scale.z, cols, rows);
|
1104
|
+
const verts = g.attributes.position.array;
|
1105
|
+
verts.forEach((v, index) => verts[index * 3 + 2] = heights[index] * scale.y);
|
1106
|
+
g.scale(1, -1, 1);
|
1107
|
+
g.rotateX(-Math.PI / 2);
|
1108
|
+
g.rotateY(-Math.PI / 2);
|
1003
1109
|
return g;
|
1004
1110
|
}
|
1005
1111
|
}
|
@@ -1008,12 +1114,18 @@ const geometryFromCollider = collider => {
|
|
1008
1114
|
};
|
1009
1115
|
|
1010
1116
|
const DebugShape = /*#__PURE__*/React.memo(({
|
1011
|
-
colliderHandle
|
1117
|
+
colliderHandle,
|
1118
|
+
color,
|
1119
|
+
sleepColor
|
1012
1120
|
}) => {
|
1013
1121
|
const {
|
1014
1122
|
world
|
1015
1123
|
} = useRapier();
|
1016
1124
|
const ref = React.useRef(null);
|
1125
|
+
const [material] = React.useState(new three.MeshBasicMaterial({
|
1126
|
+
color,
|
1127
|
+
wireframe: true
|
1128
|
+
}));
|
1017
1129
|
fiber.useFrame(() => {
|
1018
1130
|
const collider = world.getCollider(colliderHandle);
|
1019
1131
|
|
@@ -1029,6 +1141,14 @@ const DebugShape = /*#__PURE__*/React.memo(({
|
|
1029
1141
|
y,
|
1030
1142
|
z
|
1031
1143
|
} = collider.translation();
|
1144
|
+
const parent = collider.parent();
|
1145
|
+
|
1146
|
+
if (parent !== null && parent !== void 0 && parent.isSleeping() || parent !== null && parent !== void 0 && parent.isFixed() || parent !== null && parent !== void 0 && parent.isKinematic()) {
|
1147
|
+
material.color = new three.Color(sleepColor);
|
1148
|
+
} else {
|
1149
|
+
material.color = new three.Color(color);
|
1150
|
+
}
|
1151
|
+
|
1032
1152
|
ref.current.position.set(x, y, z);
|
1033
1153
|
ref.current.rotation.setFromQuaternion(new three.Quaternion(rx, ry, rz, rw));
|
1034
1154
|
}
|
@@ -1038,16 +1158,17 @@ const DebugShape = /*#__PURE__*/React.memo(({
|
|
1038
1158
|
return geometryFromCollider(collider);
|
1039
1159
|
}, [colliderHandle]);
|
1040
1160
|
return /*#__PURE__*/React__default["default"].createElement("mesh", {
|
1041
|
-
ref: ref
|
1161
|
+
ref: ref,
|
1162
|
+
material: material
|
1042
1163
|
}, /*#__PURE__*/React__default["default"].createElement("primitive", {
|
1043
1164
|
object: geometry,
|
1044
1165
|
attach: "geometry"
|
1045
|
-
}), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
|
1046
|
-
color: "red",
|
1047
|
-
wireframe: true
|
1048
1166
|
}));
|
1049
1167
|
});
|
1050
|
-
const Debug = (
|
1168
|
+
const Debug = ({
|
1169
|
+
color: _color = "red",
|
1170
|
+
sleepColor: _sleepColor = "blue"
|
1171
|
+
}) => {
|
1051
1172
|
const {
|
1052
1173
|
world
|
1053
1174
|
} = useRapier();
|
@@ -1063,7 +1184,9 @@ const Debug = () => {
|
|
1063
1184
|
});
|
1064
1185
|
return /*#__PURE__*/React__default["default"].createElement("group", null, colliders.map(handle => /*#__PURE__*/React__default["default"].createElement(DebugShape, {
|
1065
1186
|
key: handle,
|
1066
|
-
colliderHandle: handle
|
1187
|
+
colliderHandle: handle,
|
1188
|
+
color: _color,
|
1189
|
+
sleepColor: _sleepColor
|
1067
1190
|
})));
|
1068
1191
|
};
|
1069
1192
|
|
@@ -1191,24 +1314,6 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1191
1314
|
}, props.children));
|
1192
1315
|
});
|
1193
1316
|
|
1194
|
-
function _extends() {
|
1195
|
-
_extends = Object.assign || function (target) {
|
1196
|
-
for (var i = 1; i < arguments.length; i++) {
|
1197
|
-
var source = arguments[i];
|
1198
|
-
|
1199
|
-
for (var key in source) {
|
1200
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
1201
|
-
target[key] = source[key];
|
1202
|
-
}
|
1203
|
-
}
|
1204
|
-
}
|
1205
|
-
|
1206
|
-
return target;
|
1207
|
-
};
|
1208
|
-
|
1209
|
-
return _extends.apply(this, arguments);
|
1210
|
-
}
|
1211
|
-
|
1212
1317
|
const _excluded = ["children"];
|
1213
1318
|
|
1214
1319
|
const AnyCollider = _ref => {
|