@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.
@@ -8,6 +8,7 @@ var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
10
  var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
11
+ var MathUtils = require('three/src/math/MathUtils');
11
12
  var threeStdlib = require('three-stdlib');
12
13
 
13
14
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -49,7 +50,7 @@ const rapierVector3ToVector3 = ({
49
50
  x,
50
51
  y,
51
52
  z
52
- }) => _vector3.set(x, y, z).clone();
53
+ }) => _vector3.set(x, y, z);
53
54
  const rapierQuaternionToQuaternion = ({
54
55
  x,
55
56
  y,
@@ -95,6 +96,12 @@ const scaleColliderArgs = (shape, args, scale) => {
95
96
  const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
96
97
  return newArgs.map((arg, index) => scaleArray[index] * arg);
97
98
  };
99
+
100
+ const applyColliderOptions = (collider, options) => {
101
+ if (options.collisionGroups !== undefined) collider.setCollisionGroups(options.collisionGroups);
102
+ if (options.solverGroups !== undefined) collider.setSolverGroups(options.solverGroups);
103
+ };
104
+
98
105
  const createColliderFromOptions = ({
99
106
  options,
100
107
  world,
@@ -122,10 +129,6 @@ const createColliderFromOptions = ({
122
129
  w: qRotation.w
123
130
  }).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);
124
131
 
125
- if (colliderShape === "heightfield") {
126
- console.log(colliderDesc);
127
- }
128
-
129
132
  if (hasCollisionEvents) {
130
133
  colliderDesc = colliderDesc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
131
134
  } // If any of the mass properties are specified, add mass properties
@@ -152,6 +155,7 @@ const createColliderFromOptions = ({
152
155
  }
153
156
 
154
157
  const collider = world.createCollider(colliderDesc, rigidBody);
158
+ applyColliderOptions(collider, options);
155
159
  return collider;
156
160
  };
157
161
 
@@ -172,7 +176,6 @@ const createCollidersFromChildren = ({
172
176
  }) => {
173
177
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
174
178
  const colliders = [];
175
- new three.Vector3();
176
179
  object.traverseVisible(child => {
177
180
  if ("isMesh" in child) {
178
181
  if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
@@ -218,6 +221,7 @@ const createCollidersFromChildren = ({
218
221
  });
219
222
  const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
220
223
  const collider = world.createCollider(desc, actualRigidBody);
224
+ applyColliderOptions(collider, options);
221
225
  colliders.push(collider);
222
226
  }
223
227
  });
@@ -328,12 +332,7 @@ const createRigidBodyApi = ref => {
328
332
  addTorque: torque => ref.current().addTorque(torque, true),
329
333
 
330
334
  translation() {
331
- const {
332
- x,
333
- y,
334
- z
335
- } = ref.current().translation();
336
- return new three.Vector3(x, y, z);
335
+ return rapierVector3ToVector3(ref.current().translation());
337
336
  },
338
337
 
339
338
  setTranslation: translation => ref.current().setTranslation(translation, true),
@@ -348,18 +347,8 @@ const createRigidBodyApi = ref => {
348
347
  return new three.Quaternion(x, y, z, w);
349
348
  },
350
349
 
351
- setRotation: ({
352
- x,
353
- y,
354
- z
355
- }) => {
356
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
357
- ref.current().setRotation({
358
- x: q.x,
359
- y: q.y,
360
- z: q.z,
361
- w: q.w
362
- }, true);
350
+ setRotation: rotation => {
351
+ ref.current().setRotation(rotation, true);
363
352
  },
364
353
 
365
354
  linvel() {
@@ -395,18 +384,8 @@ const createRigidBodyApi = ref => {
395
384
  },
396
385
 
397
386
  setAngularDamping: factor => ref.current().setAngularDamping(factor),
398
- setNextKinematicRotation: ({
399
- x,
400
- y,
401
- z
402
- }) => {
403
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
404
- ref.current().setNextKinematicRotation({
405
- x: q.x,
406
- y: q.y,
407
- z: q.z,
408
- w: q.w
409
- });
387
+ setNextKinematicRotation: rotation => {
388
+ ref.current().setNextKinematicRotation(rotation);
410
389
  },
411
390
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
412
391
  resetForces: () => ref.current().resetForces(true),
@@ -480,7 +459,8 @@ const Physics = ({
480
459
  children,
481
460
  timeStep: _timeStep = 1 / 60,
482
461
  maxSubSteps: _maxSubSteps = 10,
483
- paused: _paused = false
462
+ paused: _paused = false,
463
+ updatePriority
484
464
  }) => {
485
465
  const rapier = useAsset.useAsset(importRapier);
486
466
  const [isPaused, setIsPaused] = React.useState(_paused);
@@ -496,9 +476,9 @@ const Physics = ({
496
476
 
497
477
  return worldRef.current;
498
478
  });
499
- const [colliderMeshes] = React.useState(() => new Map());
500
479
  const [rigidBodyStates] = React.useState(() => new Map());
501
480
  const [rigidBodyEvents] = React.useState(() => new Map());
481
+ const [colliderEvents] = React.useState(() => new Map());
502
482
  const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
503
483
 
504
484
  React.useEffect(() => {
@@ -528,12 +508,12 @@ const Physics = ({
528
508
  world.timestep = _timeStep;
529
509
  /**
530
510
  * Fixed timeStep simulation progression
531
- * @see https://gafferongames.com/post/fix_your_timestep/
511
+ * @see https://gafferongames.com/post/fix_your_timestep/
532
512
  */
533
513
 
534
514
  let previousTranslations = {}; // don't step time forwards if paused
535
515
 
536
- const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
516
+ const nowTime = steppingState.time += _paused ? 0 : MathUtils.clamp(delta, 0, 1) * 1000;
537
517
  const timeStepMs = _timeStep * 1000;
538
518
  const timeSinceLast = nowTime - steppingState.lastTime;
539
519
  steppingState.lastTime = nowTime;
@@ -583,7 +563,7 @@ const Physics = ({
583
563
  }
584
564
 
585
565
  let oldState = previousTranslations[rigidBody.handle];
586
- let newTranslation = rapierVector3ToVector3(rigidBody.translation());
566
+ let newTranslation = rigidBody.translation();
587
567
  let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
588
568
  let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
589
569
  let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
@@ -602,42 +582,71 @@ const Physics = ({
602
582
  const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
603
583
  const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
604
584
 
605
- if (!collider1 || !collider2 || !rigidBodyHandle1 || !rigidBodyHandle2) {
585
+ if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
606
586
  return;
607
587
  }
608
588
 
609
589
  const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
610
590
  const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
611
- const events1 = rigidBodyEvents.get(rigidBodyHandle1);
612
- const events2 = rigidBodyEvents.get(rigidBodyHandle2);
591
+ const rigidBody1Events = rigidBodyEvents.get(rigidBodyHandle1);
592
+ const rigidBoyd2Events = rigidBodyEvents.get(rigidBodyHandle2);
593
+ const collider1Events = colliderEvents.get(collider1.handle);
594
+ const collider2Events = colliderEvents.get(collider2.handle);
613
595
 
614
596
  if (started) {
615
597
  world.contactPair(collider1, collider2, (manifold, flipped) => {
616
- var _events1$onCollisionE, _events2$onCollisionE;
598
+ var _rigidBody1Events$onC, _rigidBoyd2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
599
+
600
+ /* RigidBody events */
601
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
602
+ target: rigidBody2,
603
+ collider: collider2,
604
+ manifold,
605
+ flipped
606
+ });
607
+ rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC = rigidBoyd2Events.onCollisionEnter) === null || _rigidBoyd2Events$onC === void 0 ? void 0 : _rigidBoyd2Events$onC.call(rigidBoyd2Events, {
608
+ target: rigidBody1,
609
+ collider: collider1,
610
+ manifold,
611
+ flipped
612
+ });
613
+ /* Collider events */
617
614
 
618
- events1 === null || events1 === void 0 ? void 0 : (_events1$onCollisionE = events1.onCollisionEnter) === null || _events1$onCollisionE === void 0 ? void 0 : _events1$onCollisionE.call(events1, {
615
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
619
616
  target: rigidBody2,
617
+ collider: collider2,
620
618
  manifold,
621
619
  flipped
622
620
  });
623
- events2 === null || events2 === void 0 ? void 0 : (_events2$onCollisionE = events2.onCollisionEnter) === null || _events2$onCollisionE === void 0 ? void 0 : _events2$onCollisionE.call(events2, {
621
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
624
622
  target: rigidBody1,
623
+ collider: collider1,
625
624
  manifold,
626
625
  flipped
627
626
  });
628
627
  });
629
628
  } else {
630
- var _events1$onCollisionE2, _events2$onCollisionE2;
629
+ var _rigidBody1Events$onC2, _rigidBoyd2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
631
630
 
632
- events1 === null || events1 === void 0 ? void 0 : (_events1$onCollisionE2 = events1.onCollisionExit) === null || _events1$onCollisionE2 === void 0 ? void 0 : _events1$onCollisionE2.call(events1, {
633
- target: rigidBody2
631
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
632
+ target: rigidBody2,
633
+ collider: collider2
634
+ });
635
+ rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC2 = rigidBoyd2Events.onCollisionExit) === null || _rigidBoyd2Events$onC2 === void 0 ? void 0 : _rigidBoyd2Events$onC2.call(rigidBoyd2Events, {
636
+ target: rigidBody1,
637
+ collider: collider1
634
638
  });
635
- events2 === null || events2 === void 0 ? void 0 : (_events2$onCollisionE2 = events2.onCollisionExit) === null || _events2$onCollisionE2 === void 0 ? void 0 : _events2$onCollisionE2.call(events2, {
636
- target: rigidBody1
639
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
640
+ target: rigidBody2,
641
+ collider: collider2
642
+ });
643
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
644
+ target: rigidBody1,
645
+ collider: collider1
637
646
  });
638
647
  }
639
648
  });
640
- });
649
+ }, updatePriority);
641
650
  const api = React.useMemo(() => createWorldApi(getWorldRef), []);
642
651
  const context = React.useMemo(() => ({
643
652
  rapier,
@@ -646,9 +655,9 @@ const Physics = ({
646
655
  colliders: _colliders,
647
656
  gravity: _gravity
648
657
  },
649
- colliderMeshes,
650
658
  rigidBodyStates,
651
659
  rigidBodyEvents,
660
+ colliderEvents,
652
661
  isPaused
653
662
  }), [isPaused]);
654
663
  return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
@@ -1314,22 +1323,26 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1314
1323
  }, props.children));
1315
1324
  });
1316
1325
 
1317
- const _excluded = ["children"];
1326
+ const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
1318
1327
 
1319
1328
  const AnyCollider = _ref => {
1320
1329
  let {
1321
- children
1330
+ children,
1331
+ onCollisionEnter,
1332
+ onCollisionExit
1322
1333
  } = _ref,
1323
1334
  props = _objectWithoutProperties(_ref, _excluded);
1324
1335
 
1325
1336
  const {
1326
- world
1337
+ world,
1338
+ colliderEvents
1327
1339
  } = useRapier();
1328
1340
  const rigidBodyContext = useRigidBodyContext();
1329
1341
  const ref = React.useRef(null);
1330
1342
  React.useEffect(() => {
1331
1343
  const scale = ref.current.getWorldScale(new three.Vector3());
1332
- const colliders = []; // If this is an InstancedRigidBody api
1344
+ const colliders = [];
1345
+ const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
1333
1346
 
1334
1347
  if (rigidBodyContext && "at" in rigidBodyContext.api) {
1335
1348
  rigidBodyContext.api.forEach((body, index) => {
@@ -1342,26 +1355,41 @@ const AnyCollider = _ref => {
1342
1355
  }
1343
1356
 
1344
1357
  colliders.push(createColliderFromOptions({
1345
- options: props,
1358
+ options: _objectSpread2({
1359
+ solverGroups: rigidBodyContext.options.solverGroups,
1360
+ collisionGroups: rigidBodyContext.options.collisionGroups
1361
+ }, props),
1346
1362
  world,
1347
1363
  rigidBody: body.raw(),
1348
1364
  scale: instanceScale,
1349
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1365
+ hasCollisionEvents
1350
1366
  }));
1351
1367
  });
1352
1368
  } else {
1353
1369
  colliders.push(createColliderFromOptions({
1354
- options: props,
1370
+ options: _objectSpread2({
1371
+ solverGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.solverGroups) || props.solverGroups,
1372
+ collisionGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.collisionGroups) || props.collisionGroups
1373
+ }, props),
1355
1374
  world,
1356
1375
  // Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
1357
1376
  rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
1358
1377
  scale,
1359
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1378
+ hasCollisionEvents
1360
1379
  }));
1361
1380
  }
1381
+ /* Register collision events. */
1362
1382
 
1383
+
1384
+ colliders.forEach(collider => colliderEvents.set(collider.handle, {
1385
+ onCollisionEnter,
1386
+ onCollisionExit
1387
+ }));
1363
1388
  return () => {
1364
- colliders.forEach(collider => world.removeCollider(collider));
1389
+ colliders.forEach(collider => {
1390
+ colliderEvents.delete(collider.handle);
1391
+ world.removeCollider(collider);
1392
+ });
1365
1393
  };
1366
1394
  }, []);
1367
1395
  return /*#__PURE__*/React__default["default"].createElement("object3D", {
@@ -1415,6 +1443,42 @@ const ConvexHullCollider = props => {
1415
1443
  }));
1416
1444
  };
1417
1445
 
1446
+ /**
1447
+ * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
1448
+ * properties of RigidBody or Collider components. The first argument represents a list of
1449
+ * groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
1450
+ * of groups that will be filtered against. When it is omitted, all groups are filtered against.
1451
+ *
1452
+ * @example
1453
+ * A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
1454
+ *
1455
+ * ```tsx
1456
+ * <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
1457
+ * ```
1458
+ *
1459
+ * A RigidBody that is member of groups 0 and 1 and will collide with everything else:
1460
+ *
1461
+ * ```tsx
1462
+ * <RigidBody collisionGroups={interactionGroups([0, 1])} />
1463
+ * ```
1464
+ *
1465
+ * A RigidBody that is member of groups 0 and 1 and will not collide with anything:
1466
+ *
1467
+ * ```tsx
1468
+ * <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
1469
+ * ```
1470
+ *
1471
+ * Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
1472
+ * entities for collision events to trigger.
1473
+ *
1474
+ * @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
1475
+ * @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
1476
+ * @returns An InteractionGroup bitmask.
1477
+ */
1478
+ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
1479
+
1480
+ const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1481
+
1418
1482
  Object.defineProperty(exports, 'CoefficientCombineRule', {
1419
1483
  enumerable: true,
1420
1484
  get: function () { return rapier3dCompat.CoefficientCombineRule; }
@@ -1441,6 +1505,7 @@ exports.Physics = Physics;
1441
1505
  exports.RigidBody = RigidBody;
1442
1506
  exports.RoundCuboidCollider = RoundCuboidCollider;
1443
1507
  exports.TrimeshCollider = TrimeshCollider;
1508
+ exports.interactionGroups = interactionGroups;
1444
1509
  exports.useFixedJoint = useFixedJoint;
1445
1510
  exports.useImpulseJoint = useImpulseJoint;
1446
1511
  exports.usePrismaticJoint = usePrismaticJoint;