@react-three/rapier 0.6.7 → 0.6.9
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 +18 -9
- package/dist/declarations/src/InstancedRigidBodies.d.ts +1 -1
- package/dist/declarations/src/Physics.d.ts +11 -11
- package/dist/declarations/src/RigidBody.d.ts +2 -3
- package/dist/declarations/src/api.d.ts +2 -2
- package/dist/declarations/src/bitmasks.d.ts +34 -0
- package/dist/declarations/src/index.d.ts +4 -0
- package/dist/declarations/src/types.d.ts +41 -9
- package/dist/declarations/src/utils.d.ts +1 -1
- package/dist/react-three-rapier.cjs.dev.js +128 -63
- package/dist/react-three-rapier.cjs.prod.js +128 -63
- package/dist/react-three-rapier.esm.js +128 -64
- package/package.json +4 -4
- package/readme.md +63 -9
@@ -5,6 +5,7 @@ import { useAsset } from 'use-asset';
|
|
5
5
|
import { useFrame } from '@react-three/fiber';
|
6
6
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeBufferGeometry, CapsuleBufferGeometry, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
|
7
7
|
import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils';
|
8
|
+
import { clamp } from 'three/src/math/MathUtils';
|
8
9
|
import { RoundedBoxGeometry } from 'three-stdlib';
|
9
10
|
|
10
11
|
const _quaternion = new Quaternion();
|
@@ -24,7 +25,7 @@ const rapierVector3ToVector3 = ({
|
|
24
25
|
x,
|
25
26
|
y,
|
26
27
|
z
|
27
|
-
}) => _vector3.set(x, y, z)
|
28
|
+
}) => _vector3.set(x, y, z);
|
28
29
|
const rapierQuaternionToQuaternion = ({
|
29
30
|
x,
|
30
31
|
y,
|
@@ -70,6 +71,12 @@ const scaleColliderArgs = (shape, args, scale) => {
|
|
70
71
|
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
71
72
|
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
72
73
|
};
|
74
|
+
|
75
|
+
const applyColliderOptions = (collider, options) => {
|
76
|
+
if (options.collisionGroups !== undefined) collider.setCollisionGroups(options.collisionGroups);
|
77
|
+
if (options.solverGroups !== undefined) collider.setSolverGroups(options.solverGroups);
|
78
|
+
};
|
79
|
+
|
73
80
|
const createColliderFromOptions = ({
|
74
81
|
options,
|
75
82
|
world,
|
@@ -97,10 +104,6 @@ const createColliderFromOptions = ({
|
|
97
104
|
w: qRotation.w
|
98
105
|
}).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 : 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 : CoefficientCombineRule.Average);
|
99
106
|
|
100
|
-
if (colliderShape === "heightfield") {
|
101
|
-
console.log(colliderDesc);
|
102
|
-
}
|
103
|
-
|
104
107
|
if (hasCollisionEvents) {
|
105
108
|
colliderDesc = colliderDesc.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
|
106
109
|
} // If any of the mass properties are specified, add mass properties
|
@@ -127,6 +130,7 @@ const createColliderFromOptions = ({
|
|
127
130
|
}
|
128
131
|
|
129
132
|
const collider = world.createCollider(colliderDesc, rigidBody);
|
133
|
+
applyColliderOptions(collider, options);
|
130
134
|
return collider;
|
131
135
|
};
|
132
136
|
|
@@ -147,7 +151,6 @@ const createCollidersFromChildren = ({
|
|
147
151
|
}) => {
|
148
152
|
const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
|
149
153
|
const colliders = [];
|
150
|
-
new Vector3();
|
151
154
|
object.traverseVisible(child => {
|
152
155
|
if ("isMesh" in child) {
|
153
156
|
if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
|
@@ -193,6 +196,7 @@ const createCollidersFromChildren = ({
|
|
193
196
|
});
|
194
197
|
const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
|
195
198
|
const collider = world.createCollider(desc, actualRigidBody);
|
199
|
+
applyColliderOptions(collider, options);
|
196
200
|
colliders.push(collider);
|
197
201
|
}
|
198
202
|
});
|
@@ -303,12 +307,7 @@ const createRigidBodyApi = ref => {
|
|
303
307
|
addTorque: torque => ref.current().addTorque(torque, true),
|
304
308
|
|
305
309
|
translation() {
|
306
|
-
|
307
|
-
x,
|
308
|
-
y,
|
309
|
-
z
|
310
|
-
} = ref.current().translation();
|
311
|
-
return new Vector3(x, y, z);
|
310
|
+
return rapierVector3ToVector3(ref.current().translation());
|
312
311
|
},
|
313
312
|
|
314
313
|
setTranslation: translation => ref.current().setTranslation(translation, true),
|
@@ -323,18 +322,8 @@ const createRigidBodyApi = ref => {
|
|
323
322
|
return new Quaternion(x, y, z, w);
|
324
323
|
},
|
325
324
|
|
326
|
-
setRotation:
|
327
|
-
|
328
|
-
y,
|
329
|
-
z
|
330
|
-
}) => {
|
331
|
-
const q = vector3ToQuaternion(new Vector3(x, y, z));
|
332
|
-
ref.current().setRotation({
|
333
|
-
x: q.x,
|
334
|
-
y: q.y,
|
335
|
-
z: q.z,
|
336
|
-
w: q.w
|
337
|
-
}, true);
|
325
|
+
setRotation: rotation => {
|
326
|
+
ref.current().setRotation(rotation, true);
|
338
327
|
},
|
339
328
|
|
340
329
|
linvel() {
|
@@ -370,18 +359,8 @@ const createRigidBodyApi = ref => {
|
|
370
359
|
},
|
371
360
|
|
372
361
|
setAngularDamping: factor => ref.current().setAngularDamping(factor),
|
373
|
-
setNextKinematicRotation:
|
374
|
-
|
375
|
-
y,
|
376
|
-
z
|
377
|
-
}) => {
|
378
|
-
const q = vector3ToQuaternion(new Vector3(x, y, z));
|
379
|
-
ref.current().setNextKinematicRotation({
|
380
|
-
x: q.x,
|
381
|
-
y: q.y,
|
382
|
-
z: q.z,
|
383
|
-
w: q.w
|
384
|
-
});
|
362
|
+
setNextKinematicRotation: rotation => {
|
363
|
+
ref.current().setNextKinematicRotation(rotation);
|
385
364
|
},
|
386
365
|
setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
|
387
366
|
resetForces: () => ref.current().resetForces(true),
|
@@ -455,7 +434,8 @@ const Physics = ({
|
|
455
434
|
children,
|
456
435
|
timeStep: _timeStep = 1 / 60,
|
457
436
|
maxSubSteps: _maxSubSteps = 10,
|
458
|
-
paused: _paused = false
|
437
|
+
paused: _paused = false,
|
438
|
+
updatePriority
|
459
439
|
}) => {
|
460
440
|
const rapier = useAsset(importRapier);
|
461
441
|
const [isPaused, setIsPaused] = useState(_paused);
|
@@ -471,9 +451,9 @@ const Physics = ({
|
|
471
451
|
|
472
452
|
return worldRef.current;
|
473
453
|
});
|
474
|
-
const [colliderMeshes] = useState(() => new Map());
|
475
454
|
const [rigidBodyStates] = useState(() => new Map());
|
476
455
|
const [rigidBodyEvents] = useState(() => new Map());
|
456
|
+
const [colliderEvents] = useState(() => new Map());
|
477
457
|
const [eventQueue] = useState(() => new EventQueue(false)); // Init world
|
478
458
|
|
479
459
|
useEffect(() => {
|
@@ -503,12 +483,12 @@ const Physics = ({
|
|
503
483
|
world.timestep = _timeStep;
|
504
484
|
/**
|
505
485
|
* Fixed timeStep simulation progression
|
506
|
-
* @see https://gafferongames.com/post/fix_your_timestep/
|
486
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
507
487
|
*/
|
508
488
|
|
509
489
|
let previousTranslations = {}; // don't step time forwards if paused
|
510
490
|
|
511
|
-
const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
|
491
|
+
const nowTime = steppingState.time += _paused ? 0 : clamp(delta, 0, 1) * 1000;
|
512
492
|
const timeStepMs = _timeStep * 1000;
|
513
493
|
const timeSinceLast = nowTime - steppingState.lastTime;
|
514
494
|
steppingState.lastTime = nowTime;
|
@@ -558,7 +538,7 @@ const Physics = ({
|
|
558
538
|
}
|
559
539
|
|
560
540
|
let oldState = previousTranslations[rigidBody.handle];
|
561
|
-
let newTranslation =
|
541
|
+
let newTranslation = rigidBody.translation();
|
562
542
|
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
563
543
|
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
564
544
|
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
@@ -577,42 +557,71 @@ const Physics = ({
|
|
577
557
|
const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
|
578
558
|
const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
|
579
559
|
|
580
|
-
if (!collider1 || !collider2 ||
|
560
|
+
if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
|
581
561
|
return;
|
582
562
|
}
|
583
563
|
|
584
564
|
const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
|
585
565
|
const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
|
586
|
-
const
|
587
|
-
const
|
566
|
+
const rigidBody1Events = rigidBodyEvents.get(rigidBodyHandle1);
|
567
|
+
const rigidBoyd2Events = rigidBodyEvents.get(rigidBodyHandle2);
|
568
|
+
const collider1Events = colliderEvents.get(collider1.handle);
|
569
|
+
const collider2Events = colliderEvents.get(collider2.handle);
|
588
570
|
|
589
571
|
if (started) {
|
590
572
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
591
|
-
var
|
573
|
+
var _rigidBody1Events$onC, _rigidBoyd2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
|
574
|
+
|
575
|
+
/* RigidBody events */
|
576
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
|
577
|
+
target: rigidBody2,
|
578
|
+
collider: collider2,
|
579
|
+
manifold,
|
580
|
+
flipped
|
581
|
+
});
|
582
|
+
rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC = rigidBoyd2Events.onCollisionEnter) === null || _rigidBoyd2Events$onC === void 0 ? void 0 : _rigidBoyd2Events$onC.call(rigidBoyd2Events, {
|
583
|
+
target: rigidBody1,
|
584
|
+
collider: collider1,
|
585
|
+
manifold,
|
586
|
+
flipped
|
587
|
+
});
|
588
|
+
/* Collider events */
|
592
589
|
|
593
|
-
|
590
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
|
594
591
|
target: rigidBody2,
|
592
|
+
collider: collider2,
|
595
593
|
manifold,
|
596
594
|
flipped
|
597
595
|
});
|
598
|
-
|
596
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
|
599
597
|
target: rigidBody1,
|
598
|
+
collider: collider1,
|
600
599
|
manifold,
|
601
600
|
flipped
|
602
601
|
});
|
603
602
|
});
|
604
603
|
} else {
|
605
|
-
var
|
604
|
+
var _rigidBody1Events$onC2, _rigidBoyd2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
|
606
605
|
|
607
|
-
|
608
|
-
target: rigidBody2
|
606
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
|
607
|
+
target: rigidBody2,
|
608
|
+
collider: collider2
|
609
|
+
});
|
610
|
+
rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC2 = rigidBoyd2Events.onCollisionExit) === null || _rigidBoyd2Events$onC2 === void 0 ? void 0 : _rigidBoyd2Events$onC2.call(rigidBoyd2Events, {
|
611
|
+
target: rigidBody1,
|
612
|
+
collider: collider1
|
609
613
|
});
|
610
|
-
|
611
|
-
target:
|
614
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
|
615
|
+
target: rigidBody2,
|
616
|
+
collider: collider2
|
617
|
+
});
|
618
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
|
619
|
+
target: rigidBody1,
|
620
|
+
collider: collider1
|
612
621
|
});
|
613
622
|
}
|
614
623
|
});
|
615
|
-
});
|
624
|
+
}, updatePriority);
|
616
625
|
const api = useMemo(() => createWorldApi(getWorldRef), []);
|
617
626
|
const context = useMemo(() => ({
|
618
627
|
rapier,
|
@@ -621,9 +630,9 @@ const Physics = ({
|
|
621
630
|
colliders: _colliders,
|
622
631
|
gravity: _gravity
|
623
632
|
},
|
624
|
-
colliderMeshes,
|
625
633
|
rigidBodyStates,
|
626
634
|
rigidBodyEvents,
|
635
|
+
colliderEvents,
|
627
636
|
isPaused
|
628
637
|
}), [isPaused]);
|
629
638
|
return /*#__PURE__*/React.createElement(RapierContext.Provider, {
|
@@ -1289,22 +1298,26 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
|
1289
1298
|
}, props.children));
|
1290
1299
|
});
|
1291
1300
|
|
1292
|
-
const _excluded = ["children"];
|
1301
|
+
const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
|
1293
1302
|
|
1294
1303
|
const AnyCollider = _ref => {
|
1295
1304
|
let {
|
1296
|
-
children
|
1305
|
+
children,
|
1306
|
+
onCollisionEnter,
|
1307
|
+
onCollisionExit
|
1297
1308
|
} = _ref,
|
1298
1309
|
props = _objectWithoutProperties(_ref, _excluded);
|
1299
1310
|
|
1300
1311
|
const {
|
1301
|
-
world
|
1312
|
+
world,
|
1313
|
+
colliderEvents
|
1302
1314
|
} = useRapier();
|
1303
1315
|
const rigidBodyContext = useRigidBodyContext();
|
1304
1316
|
const ref = useRef(null);
|
1305
1317
|
useEffect(() => {
|
1306
1318
|
const scale = ref.current.getWorldScale(new Vector3());
|
1307
|
-
const colliders = [];
|
1319
|
+
const colliders = [];
|
1320
|
+
const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
|
1308
1321
|
|
1309
1322
|
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1310
1323
|
rigidBodyContext.api.forEach((body, index) => {
|
@@ -1317,26 +1330,41 @@ const AnyCollider = _ref => {
|
|
1317
1330
|
}
|
1318
1331
|
|
1319
1332
|
colliders.push(createColliderFromOptions({
|
1320
|
-
options:
|
1333
|
+
options: _objectSpread2({
|
1334
|
+
solverGroups: rigidBodyContext.options.solverGroups,
|
1335
|
+
collisionGroups: rigidBodyContext.options.collisionGroups
|
1336
|
+
}, props),
|
1321
1337
|
world,
|
1322
1338
|
rigidBody: body.raw(),
|
1323
1339
|
scale: instanceScale,
|
1324
|
-
hasCollisionEvents
|
1340
|
+
hasCollisionEvents
|
1325
1341
|
}));
|
1326
1342
|
});
|
1327
1343
|
} else {
|
1328
1344
|
colliders.push(createColliderFromOptions({
|
1329
|
-
options:
|
1345
|
+
options: _objectSpread2({
|
1346
|
+
solverGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.solverGroups) || props.solverGroups,
|
1347
|
+
collisionGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.collisionGroups) || props.collisionGroups
|
1348
|
+
}, props),
|
1330
1349
|
world,
|
1331
1350
|
// Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
|
1332
1351
|
rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
|
1333
1352
|
scale,
|
1334
|
-
hasCollisionEvents
|
1353
|
+
hasCollisionEvents
|
1335
1354
|
}));
|
1336
1355
|
}
|
1356
|
+
/* Register collision events. */
|
1337
1357
|
|
1358
|
+
|
1359
|
+
colliders.forEach(collider => colliderEvents.set(collider.handle, {
|
1360
|
+
onCollisionEnter,
|
1361
|
+
onCollisionExit
|
1362
|
+
}));
|
1338
1363
|
return () => {
|
1339
|
-
colliders.forEach(collider =>
|
1364
|
+
colliders.forEach(collider => {
|
1365
|
+
colliderEvents.delete(collider.handle);
|
1366
|
+
world.removeCollider(collider);
|
1367
|
+
});
|
1340
1368
|
};
|
1341
1369
|
}, []);
|
1342
1370
|
return /*#__PURE__*/React.createElement("object3D", {
|
@@ -1390,4 +1418,40 @@ const ConvexHullCollider = props => {
|
|
1390
1418
|
}));
|
1391
1419
|
};
|
1392
1420
|
|
1393
|
-
|
1421
|
+
/**
|
1422
|
+
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
1423
|
+
* properties of RigidBody or Collider components. The first argument represents a list of
|
1424
|
+
* groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
|
1425
|
+
* of groups that will be filtered against. When it is omitted, all groups are filtered against.
|
1426
|
+
*
|
1427
|
+
* @example
|
1428
|
+
* A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
|
1429
|
+
*
|
1430
|
+
* ```tsx
|
1431
|
+
* <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
|
1432
|
+
* ```
|
1433
|
+
*
|
1434
|
+
* A RigidBody that is member of groups 0 and 1 and will collide with everything else:
|
1435
|
+
*
|
1436
|
+
* ```tsx
|
1437
|
+
* <RigidBody collisionGroups={interactionGroups([0, 1])} />
|
1438
|
+
* ```
|
1439
|
+
*
|
1440
|
+
* A RigidBody that is member of groups 0 and 1 and will not collide with anything:
|
1441
|
+
*
|
1442
|
+
* ```tsx
|
1443
|
+
* <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
|
1444
|
+
* ```
|
1445
|
+
*
|
1446
|
+
* Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
|
1447
|
+
* entities for collision events to trigger.
|
1448
|
+
*
|
1449
|
+
* @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
|
1450
|
+
* @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
|
1451
|
+
* @returns An InteractionGroup bitmask.
|
1452
|
+
*/
|
1453
|
+
const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
|
1454
|
+
|
1455
|
+
const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
|
1456
|
+
|
1457
|
+
export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, interactionGroups, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useSphericalJoint };
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@react-three/rapier",
|
3
|
-
"version": "0.6.
|
3
|
+
"version": "0.6.9",
|
4
4
|
"source": "src/index.ts",
|
5
5
|
"main": "dist/react-three-rapier.cjs.js",
|
6
6
|
"module": "dist/react-three-rapier.esm.js",
|
@@ -20,12 +20,12 @@
|
|
20
20
|
"peerDependencies": {
|
21
21
|
"@react-three/fiber": "^8.0.12",
|
22
22
|
"react": "^18.0.0",
|
23
|
-
"three": "
|
24
|
-
"three-stdlib": "^2.15.0"
|
23
|
+
"three": ">=0.139.2"
|
25
24
|
},
|
26
25
|
"dependencies": {
|
27
26
|
"@dimforge/rapier3d-compat": "0.9.0",
|
28
|
-
"use-asset": "^1.0.4"
|
27
|
+
"use-asset": "^1.0.4",
|
28
|
+
"three-stdlib": "^2.15.0"
|
29
29
|
},
|
30
30
|
"repository": "https://github.com/pmndrs/react-three-rapier/tree/master/packages/react-three-rapier"
|
31
31
|
}
|
package/readme.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
<p align="center">
|
2
|
-
<img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/hero.svg" alt="@react-three/rapier"
|
2
|
+
<a href="#"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/hero.svg" alt="@react-three/rapier" /></a>
|
3
3
|
</p>
|
4
4
|
|
5
5
|
<p align="center">
|
6
|
-
<img src="https://img.shields.io/npm/v/@react-three/rapier?style=for-the-badge&colorA=0099DA&colorB=ffffff"
|
7
|
-
<img src="https://img.shields.io/discord/740090768164651008?style=for-the-badge&colorA=0099DA&colorB=ffffff&label=discord&logo=discord&logoColor=ffffff
|
6
|
+
<a href="https://www.npmjs.com/package/@react-three/rapier"><img src="https://img.shields.io/npm/v/@react-three/rapier?style=for-the-badge&colorA=0099DA&colorB=ffffff" /></a>
|
7
|
+
<a href="https://discord.gg/ZZjjNvJ"><img src="https://img.shields.io/discord/740090768164651008?style=for-the-badge&colorA=0099DA&colorB=ffffff&label=discord&logo=discord&logoColor=ffffff" /></a>
|
8
8
|
</p>
|
9
9
|
|
10
10
|
<p align="center">⚠️ Under heavy development. All APIs are subject to change. ⚠️</p>
|
@@ -141,7 +141,7 @@ const Scene = () => {
|
|
141
141
|
instancedApi.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
|
142
142
|
|
143
143
|
// Or update all instances as if they were in an array
|
144
|
-
instancedApi.forEach(
|
144
|
+
instancedApi.forEach(api => {
|
145
145
|
api.applyImpulse({ x: 0, y: 10, z: 0 });
|
146
146
|
});
|
147
147
|
}, []);
|
@@ -153,13 +153,13 @@ const Scene = () => {
|
|
153
153
|
const rotations = Array.from({ length: COUNT }, (_, index) => [
|
154
154
|
Math.random(),
|
155
155
|
Math.random(),
|
156
|
-
Math.random()
|
156
|
+
Math.random()
|
157
157
|
]);
|
158
158
|
|
159
159
|
const scales = Array.from({ length: COUNT }, (_, index) => [
|
160
160
|
Math.random(),
|
161
161
|
Math.random(),
|
162
|
-
Math.random()
|
162
|
+
Math.random()
|
163
163
|
]);
|
164
164
|
|
165
165
|
return (
|
@@ -212,7 +212,7 @@ const Scene = () => {
|
|
212
212
|
|
213
213
|
## Events
|
214
214
|
|
215
|
-
You can subscribe collision and state events on the RigidBody
|
215
|
+
You can subscribe to collision and state events on the RigidBody:
|
216
216
|
|
217
217
|
```tsx
|
218
218
|
const RigidBottle = () => {
|
@@ -235,6 +235,60 @@ return (
|
|
235
235
|
}
|
236
236
|
```
|
237
237
|
|
238
|
+
You may also subscribe to collision events on individual colliders:
|
239
|
+
|
240
|
+
```tsx
|
241
|
+
<CuboidCollider
|
242
|
+
onCollisionEnter={payload => {
|
243
|
+
/* ... */
|
244
|
+
}}
|
245
|
+
onCollisionExit={payload => {
|
246
|
+
/* ... */
|
247
|
+
}}
|
248
|
+
/>
|
249
|
+
```
|
250
|
+
|
251
|
+
The `payload` object for all collision callbacks contains the following properties:
|
252
|
+
|
253
|
+
- `target`
|
254
|
+
The other rigidbody that was involved in the collision event.
|
255
|
+
- `collider`
|
256
|
+
The other collider that was involved in the collision event.
|
257
|
+
- `manifold` (enter only)
|
258
|
+
The [contact manifold](https://rapier.rs/javascript3d/classes/TempContactManifold.html) generated by the collision event.
|
259
|
+
- `flipped` (enter only)
|
260
|
+
`true` if the data in the `manifold` [is flipped](https://rapier.rs/javascript3d/classes/World.html#contactPair).
|
261
|
+
|
262
|
+
### Configuring collision and solver groups
|
263
|
+
|
264
|
+
Both `<RigidBody>` as well as all collider components allow you to configure `collisionsGroups` and `solverGroups` properties that configures which groups the colliders are in, and what other groups they should interact with in potential collision and solving events (you will find more details on this in the [Rapier documentation](https://rapier.rs/docs/user_guides/javascript/colliders/#collision-groups-and-solver-groups).)
|
265
|
+
|
266
|
+
Since these are set as bitmasks and bitmasks can get a bit unwieldy to generate, this library provides a helper called `interactionGroups` that can be used to generate bitmasks from numbers and arrays of groups, where groups are identified using numbers from 0 to 15.
|
267
|
+
|
268
|
+
The first argument is the group, or an array of groups, that the collider is a member of; the second argument is the group, or an array of groups, that the collider should interact with.
|
269
|
+
|
270
|
+
Here the collider is in group 0, and interacts with colliders from groups 0, 1 and 2:
|
271
|
+
|
272
|
+
```tsx
|
273
|
+
<CapsuleCollider collisionGroups={interactionGroups(0, [0, 1, 2])} />
|
274
|
+
```
|
275
|
+
|
276
|
+
This collider is in multiple groups, but only interacts with colliders from a single group:
|
277
|
+
|
278
|
+
```tsx
|
279
|
+
<CapsuleCollider collisionGroups={interactionGroups([0, 5], 7)} />
|
280
|
+
```
|
281
|
+
|
282
|
+
When the second argument is omitted, the collider will interact with all groups:
|
283
|
+
|
284
|
+
```tsx
|
285
|
+
<CapsuleCollider collisionGroups={interactionGroups(12)} />
|
286
|
+
```
|
287
|
+
|
288
|
+
> **Note** Please remember that in Rapier, for a collision (or solving) event to occur, both colliders involved in the event must match the related interaction groups -- a one-way match will be ignored.
|
289
|
+
|
290
|
+
> **Note** By default, colliders are members of all groups, and will interact with all other groups.
|
291
|
+
|
238
292
|
## Joints
|
239
293
|
|
240
294
|
WIP
|
@@ -255,7 +309,7 @@ In order, but also not necessarily:
|
|
255
309
|
- [x] Colliders outside RigidBodies
|
256
310
|
- [x] InstancedMesh support
|
257
311
|
- [x] Timestep improvements for determinism
|
258
|
-
- [
|
312
|
+
- [x] Normalize and improve collision events (add events to single Colliders)
|
313
|
+
- [ ] Add collision events to InstancedRigidBodies
|
259
314
|
- [ ] Docs
|
260
315
|
- [ ] CodeSandbox examples
|
261
|
-
- [ ] Helpers, for things like Vehicle, Rope, Player, etc
|