@react-three/rapier 1.4.0 → 2.0.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.
@@ -31,45 +31,51 @@ function _interopNamespace(e) {
31
31
 
32
32
  var React__default = /*#__PURE__*/_interopDefault(React);
33
33
 
34
- function _defineProperty(obj, key, value) {
35
- if (key in obj) {
36
- Object.defineProperty(obj, key, {
37
- value: value,
38
- enumerable: true,
39
- configurable: true,
40
- writable: true
41
- });
42
- } else {
43
- obj[key] = value;
34
+ function _toPrimitive(t, r) {
35
+ if ("object" != typeof t || !t) return t;
36
+ var e = t[Symbol.toPrimitive];
37
+ if (void 0 !== e) {
38
+ var i = e.call(t, r || "default");
39
+ if ("object" != typeof i) return i;
40
+ throw new TypeError("@@toPrimitive must return a primitive value.");
44
41
  }
42
+ return ("string" === r ? String : Number)(t);
43
+ }
45
44
 
46
- return obj;
45
+ function _toPropertyKey(t) {
46
+ var i = _toPrimitive(t, "string");
47
+ return "symbol" == typeof i ? i : i + "";
47
48
  }
48
49
 
49
- function ownKeys(object, enumerableOnly) {
50
- var keys = Object.keys(object);
50
+ function _defineProperty(e, r, t) {
51
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
52
+ value: t,
53
+ enumerable: !0,
54
+ configurable: !0,
55
+ writable: !0
56
+ }) : e[r] = t, e;
57
+ }
51
58
 
59
+ function ownKeys(e, r) {
60
+ var t = Object.keys(e);
52
61
  if (Object.getOwnPropertySymbols) {
53
- var symbols = Object.getOwnPropertySymbols(object);
54
- enumerableOnly && (symbols = symbols.filter(function (sym) {
55
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
56
- })), keys.push.apply(keys, symbols);
62
+ var o = Object.getOwnPropertySymbols(e);
63
+ r && (o = o.filter(function (r) {
64
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
65
+ })), t.push.apply(t, o);
57
66
  }
58
-
59
- return keys;
67
+ return t;
60
68
  }
61
-
62
- function _objectSpread2(target) {
63
- for (var i = 1; i < arguments.length; i++) {
64
- var source = null != arguments[i] ? arguments[i] : {};
65
- i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
66
- _defineProperty(target, key, source[key]);
67
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
68
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
69
+ function _objectSpread2(e) {
70
+ for (var r = 1; r < arguments.length; r++) {
71
+ var t = null != arguments[r] ? arguments[r] : {};
72
+ r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
73
+ _defineProperty(e, r, t[r]);
74
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
75
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
69
76
  });
70
77
  }
71
-
72
- return target;
78
+ return e;
73
79
  }
74
80
 
75
81
  const _quaternion = new three.Quaternion();
@@ -117,41 +123,33 @@ const rigidBodyTypeMap = {
117
123
  const rigidBodyTypeFromString = type => rigidBodyTypeMap[type];
118
124
  const scaleVertices = (vertices, scale) => {
119
125
  const scaledVerts = Array.from(vertices);
120
-
121
126
  for (let i = 0; i < vertices.length / 3; i++) {
122
127
  scaledVerts[i * 3] *= scale.x;
123
128
  scaledVerts[i * 3 + 1] *= scale.y;
124
129
  scaledVerts[i * 3 + 2] *= scale.z;
125
130
  }
126
-
127
131
  return scaledVerts;
128
132
  };
129
133
  const vectorToTuple = v => {
130
134
  if (!v) return [0];
131
-
132
135
  if (v instanceof three.Quaternion) {
133
136
  return [v.x, v.y, v.z, v.w];
134
137
  }
135
-
136
138
  if (v instanceof three.Vector3 || v instanceof three.Euler) {
137
139
  return [v.x, v.y, v.z];
138
140
  }
139
-
140
141
  if (Array.isArray(v)) {
141
142
  return v;
142
143
  }
143
-
144
144
  return [v];
145
145
  };
146
146
  function useConst(initialValue) {
147
- const ref = React.useRef();
148
-
147
+ const ref = React.useRef(undefined);
149
148
  if (ref.current === undefined) {
150
149
  ref.current = {
151
150
  value: typeof initialValue === "function" ? initialValue() : initialValue
152
151
  };
153
152
  }
154
-
155
153
  return ref.current.value;
156
154
  }
157
155
 
@@ -170,7 +168,6 @@ const useRaf = callback => {
170
168
  cb.current(delta / 1000);
171
169
  lastFrame.current = now;
172
170
  };
173
-
174
171
  raf.current = requestAnimationFrame(loop);
175
172
  return () => cancelAnimationFrame(raf.current);
176
173
  }, []);
@@ -185,7 +182,6 @@ const UseFrameStepper = ({
185
182
  }, updatePriority);
186
183
  return null;
187
184
  };
188
-
189
185
  const RafStepper = ({
190
186
  onStep
191
187
  }) => {
@@ -194,7 +190,6 @@ const RafStepper = ({
194
190
  });
195
191
  return null;
196
192
  };
197
-
198
193
  const FrameStepper = ({
199
194
  onStep,
200
195
  type,
@@ -207,98 +202,80 @@ const FrameStepper = ({
207
202
  updatePriority: updatePriority
208
203
  });
209
204
  };
210
-
211
205
  var FrameStepper$1 = /*#__PURE__*/React.memo(FrameStepper);
212
206
 
213
- function _objectWithoutPropertiesLoose(source, excluded) {
214
- if (source == null) return {};
215
- var target = {};
216
- var sourceKeys = Object.keys(source);
217
- var key, i;
218
-
219
- for (i = 0; i < sourceKeys.length; i++) {
220
- key = sourceKeys[i];
221
- if (excluded.indexOf(key) >= 0) continue;
222
- target[key] = source[key];
207
+ function _objectWithoutPropertiesLoose(r, e) {
208
+ if (null == r) return {};
209
+ var t = {};
210
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
211
+ if (-1 !== e.indexOf(n)) continue;
212
+ t[n] = r[n];
223
213
  }
224
-
225
- return target;
214
+ return t;
226
215
  }
227
216
 
228
- function _objectWithoutProperties(source, excluded) {
229
- if (source == null) return {};
230
- var target = _objectWithoutPropertiesLoose(source, excluded);
231
- var key, i;
232
-
217
+ function _objectWithoutProperties(e, t) {
218
+ if (null == e) return {};
219
+ var o,
220
+ r,
221
+ i = _objectWithoutPropertiesLoose(e, t);
233
222
  if (Object.getOwnPropertySymbols) {
234
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
235
-
236
- for (i = 0; i < sourceSymbolKeys.length; i++) {
237
- key = sourceSymbolKeys[i];
238
- if (excluded.indexOf(key) >= 0) continue;
239
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
240
- target[key] = source[key];
241
- }
223
+ var n = Object.getOwnPropertySymbols(e);
224
+ for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
242
225
  }
243
-
244
- return target;
226
+ return i;
245
227
  }
246
228
 
247
- const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale", "softCcdPrediction"];
229
+ const _excluded$2 = ["mass", "linearDamping", "angularDamping", "type", "onCollisionEnter", "onCollisionExit", "onIntersectionEnter", "onIntersectionExit", "onContactForce", "children", "canSleep", "ccd", "gravityScale", "softCcdPrediction", "ref"];
248
230
  const scaleColliderArgs = (shape, args, scale) => {
249
- const newArgs = args.slice(); // Heightfield uses a vector
231
+ const newArgs = args.slice();
250
232
 
233
+ // Heightfield uses a vector
251
234
  if (shape === "heightfield") {
252
235
  const s = newArgs[3];
253
236
  s.x *= scale.x;
254
237
  s.x *= scale.y;
255
238
  s.x *= scale.z;
256
239
  return newArgs;
257
- } // Trimesh and convex scale the vertices
258
-
240
+ }
259
241
 
242
+ // Trimesh and convex scale the vertices
260
243
  if (shape === "trimesh" || shape === "convexHull") {
261
244
  newArgs[0] = scaleVertices(newArgs[0], scale);
262
245
  return newArgs;
263
- } // Prepfill with some extra
264
-
246
+ }
265
247
 
248
+ // Prepfill with some extra
266
249
  const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
267
250
  return newArgs.map((arg, index) => scaleArray[index] * arg);
268
251
  };
269
252
  const createColliderFromOptions = (options, world, scale, getRigidBody) => {
270
- const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
271
-
253
+ const scaledArgs = scaleColliderArgs(options.shape, options.args, scale);
254
+ // @ts-ignore
272
255
  const desc = rapier3dCompat.ColliderDesc[options.shape](...scaledArgs);
273
256
  return world.createCollider(desc, getRigidBody === null || getRigidBody === void 0 ? void 0 : getRigidBody());
274
257
  };
275
258
  const immutableColliderOptions = ["shape", "args"];
276
259
  const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
277
-
278
260
  const setColliderMassOptions = (collider, options) => {
279
261
  if (options.density !== undefined) {
280
262
  if (options.mass !== undefined || options.massProperties !== undefined) {
281
263
  throw new Error(massPropertiesConflictError);
282
264
  }
283
-
284
265
  collider.setDensity(options.density);
285
266
  return;
286
267
  }
287
-
288
268
  if (options.mass !== undefined) {
289
269
  if (options.massProperties !== undefined) {
290
270
  throw new Error(massPropertiesConflictError);
291
271
  }
292
-
293
272
  collider.setMass(options.mass);
294
273
  return;
295
274
  }
296
-
297
275
  if (options.massProperties !== undefined) {
298
276
  collider.setMassProperties(options.massProperties.mass, options.massProperties.centerOfMass, options.massProperties.principalAngularInertia, options.massProperties.angularInertiaLocalFrame);
299
277
  }
300
278
  };
301
-
302
279
  const mutableColliderOptions = {
303
280
  sensor: (collider, value) => {
304
281
  collider.setSensor(value);
@@ -336,23 +313,17 @@ const mutableColliderOptions = {
336
313
  const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
337
314
  const setColliderOptions = (collider, options, states) => {
338
315
  const state = states.get(collider.handle);
339
-
340
316
  if (state) {
341
317
  var _state$worldParent;
342
-
343
318
  // Update collider position based on the object's position
344
319
  const parentWorldScale = state.object.parent.getWorldScale(_vector3);
345
320
  const parentInvertedWorldMatrix = (_state$worldParent = state.worldParent) === null || _state$worldParent === void 0 ? void 0 : _state$worldParent.matrixWorld.clone().invert();
346
321
  state.object.updateWorldMatrix(true, false);
347
-
348
322
  _matrix4.copy(state.object.matrixWorld);
349
-
350
323
  if (parentInvertedWorldMatrix) {
351
324
  _matrix4.premultiply(parentInvertedWorldMatrix);
352
325
  }
353
-
354
326
  _matrix4.decompose(_position, _rotation, _scale);
355
-
356
327
  if (collider.parent()) {
357
328
  collider.setTranslationWrtParent({
358
329
  x: _position.x * parentWorldScale.x,
@@ -368,16 +339,17 @@ const setColliderOptions = (collider, options, states) => {
368
339
  });
369
340
  collider.setRotation(_rotation);
370
341
  }
371
-
372
342
  mutableColliderOptionKeys.forEach(key => {
373
343
  if (key in options) {
374
344
  const option = options[key];
375
- mutableColliderOptions[key](collider, // @ts-ignore Option does not want to fit into the function, but it will
345
+ mutableColliderOptions[key](collider,
346
+ // @ts-ignore Option does not want to fit into the function, but it will
376
347
  option, options);
377
348
  }
378
- }); // handle mass separately, because the assignments
379
- // are exclusive.
349
+ });
380
350
 
351
+ // handle mass separately, because the assignments
352
+ // are exclusive.
381
353
  setColliderMassOptions(collider, options);
382
354
  }
383
355
  };
@@ -391,7 +363,6 @@ const useUpdateColliderOptions = (getCollider, props, states) => {
391
363
  setColliderOptions(collider, props, states);
392
364
  }, [...mutablePropsAsFlatArray, getCollider]);
393
365
  };
394
-
395
366
  const isChildOfMeshCollider = child => {
396
367
  let flag = false;
397
368
  child.traverseAncestors(a => {
@@ -399,7 +370,6 @@ const isChildOfMeshCollider = child => {
399
370
  });
400
371
  return flag;
401
372
  };
402
-
403
373
  const createColliderState = (collider, object, rigidBodyObject) => {
404
374
  return {
405
375
  collider,
@@ -421,16 +391,13 @@ const createColliderPropsFromChildren = ({
421
391
  const childColliderProps = [];
422
392
  object.updateWorldMatrix(true, false);
423
393
  const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
424
-
425
394
  const colliderFromChild = child => {
426
395
  if ("isMesh" in child) {
427
396
  if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
428
397
  const worldScale = child.getWorldScale(_scale);
429
398
  const shape = autoColliderMap[options.colliders || "cuboid"];
430
399
  child.updateWorldMatrix(true, false);
431
-
432
400
  _matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
433
-
434
401
  const rotationEuler = new three.Euler().setFromQuaternion(_rotation, "XYZ");
435
402
  const {
436
403
  geometry
@@ -439,7 +406,6 @@ const createColliderPropsFromChildren = ({
439
406
  args,
440
407
  offset
441
408
  } = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
442
-
443
409
  const colliderProps = _objectSpread2(_objectSpread2({}, cleanRigidBodyPropsForCollider(options)), {}, {
444
410
  args: args,
445
411
  shape: shape,
@@ -447,17 +413,14 @@ const createColliderPropsFromChildren = ({
447
413
  position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
448
414
  scale: [worldScale.x, worldScale.y, worldScale.z]
449
415
  });
450
-
451
416
  childColliderProps.push(colliderProps);
452
417
  }
453
418
  };
454
-
455
419
  if (options.includeInvisible) {
456
420
  object.traverse(colliderFromChild);
457
421
  } else {
458
422
  object.traverseVisible(colliderFromChild);
459
423
  }
460
-
461
424
  return childColliderProps;
462
425
  };
463
426
  const getColliderArgsFromGeometry = (geometry, colliders) => {
@@ -474,7 +437,6 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
474
437
  offset: boundingBox.getCenter(new three.Vector3())
475
438
  };
476
439
  }
477
-
478
440
  case "ball":
479
441
  {
480
442
  geometry.computeBoundingSphere();
@@ -487,18 +449,15 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
487
449
  offset: boundingSphere.center
488
450
  };
489
451
  }
490
-
491
452
  case "trimesh":
492
453
  {
493
454
  var _clonedGeometry$index;
494
-
495
455
  const clonedGeometry = geometry.index ? geometry.clone() : threeStdlib.mergeVertices(geometry);
496
456
  return {
497
457
  args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
498
458
  offset: new three.Vector3()
499
459
  };
500
460
  }
501
-
502
461
  case "hull":
503
462
  {
504
463
  const g = geometry.clone();
@@ -508,7 +467,6 @@ const getColliderArgsFromGeometry = (geometry, colliders) => {
508
467
  };
509
468
  }
510
469
  }
511
-
512
470
  return {
513
471
  args: [],
514
472
  offset: new three.Vector3()
@@ -534,7 +492,6 @@ activeEvents = {}) => {
534
492
  } = props;
535
493
  React.useEffect(() => {
536
494
  const collider = getCollider();
537
-
538
495
  if (collider) {
539
496
  const {
540
497
  collision: collisionEventsActive,
@@ -542,7 +499,6 @@ activeEvents = {}) => {
542
499
  } = getActiveCollisionEventsFromProps(props);
543
500
  const hasCollisionEvent = collisionEventsActive || activeEvents.collision;
544
501
  const hasContactForceEvent = contactForceEventsActive || activeEvents.contactForce;
545
-
546
502
  if (hasCollisionEvent && hasContactForceEvent) {
547
503
  collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS | rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
548
504
  } else if (hasCollisionEvent) {
@@ -550,7 +506,6 @@ activeEvents = {}) => {
550
506
  } else if (hasContactForceEvent) {
551
507
  collider.setActiveEvents(rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
552
508
  }
553
-
554
509
  events.set(collider.handle, {
555
510
  onCollisionEnter,
556
511
  onCollisionExit,
@@ -559,7 +514,6 @@ activeEvents = {}) => {
559
514
  onContactForce
560
515
  });
561
516
  }
562
-
563
517
  return () => {
564
518
  if (collider) {
565
519
  events.delete(collider.handle);
@@ -569,34 +523,33 @@ activeEvents = {}) => {
569
523
  };
570
524
  const cleanRigidBodyPropsForCollider = (props = {}) => {
571
525
  const rest = _objectWithoutProperties(props, _excluded$2);
572
-
573
526
  return rest;
574
527
  };
575
528
 
529
+ // Utils
576
530
  const useMutableCallback = fn => {
577
531
  const ref = React.useRef(fn);
578
532
  React.useEffect(() => {
579
533
  ref.current = fn;
580
534
  }, [fn]);
581
535
  return ref;
582
- }; // External hooks
536
+ };
583
537
 
538
+ // External hooks
584
539
  /**
585
540
  * Exposes the Rapier context, and world
586
541
  * @category Hooks
587
542
  */
588
-
589
-
590
543
  const useRapier = () => {
591
544
  const rapier = React.useContext(rapierContext);
592
545
  if (!rapier) throw new Error("react-three-rapier: useRapier must be used within <Physics />!");
593
546
  return rapier;
594
547
  };
548
+
595
549
  /**
596
550
  * Registers a callback to be called before the physics step
597
551
  * @category Hooks
598
552
  */
599
-
600
553
  const useBeforePhysicsStep = callback => {
601
554
  const {
602
555
  beforeStepCallbacks
@@ -609,11 +562,11 @@ const useBeforePhysicsStep = callback => {
609
562
  };
610
563
  }, []);
611
564
  };
565
+
612
566
  /**
613
567
  * Registers a callback to be called after the physics step
614
568
  * @category Hooks
615
569
  */
616
-
617
570
  const useAfterPhysicsStep = callback => {
618
571
  const {
619
572
  afterStepCallbacks
@@ -625,17 +578,16 @@ const useAfterPhysicsStep = callback => {
625
578
  afterStepCallbacks.delete(ref);
626
579
  };
627
580
  }, []);
628
- }; // Internal hooks
581
+ };
629
582
 
583
+ // Internal hooks
630
584
  /**
631
585
  * @internal
632
586
  */
633
-
634
587
  const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
635
588
  const [colliderProps, setColliderProps] = React.useState([]);
636
589
  React.useEffect(() => {
637
590
  const object = ref.current;
638
-
639
591
  if (object && options.colliders !== false) {
640
592
  setColliderProps(createColliderPropsFromChildren({
641
593
  object: ref.current,
@@ -681,33 +633,26 @@ const createSingletonProxy = createInstance => {
681
633
  if (!instance) {
682
634
  instance = createInstance();
683
635
  }
684
-
685
636
  return Reflect.get(instance, prop);
686
637
  },
687
-
688
638
  set(target, prop, value) {
689
639
  if (!instance) {
690
640
  instance = createInstance();
691
641
  }
692
-
693
642
  return Reflect.set(instance, prop, value);
694
643
  }
695
-
696
644
  };
697
645
  const proxy = new Proxy({}, handler);
698
-
699
646
  const reset = () => {
700
647
  instance = undefined;
701
648
  };
702
-
703
649
  const set = newInstance => {
704
650
  instance = newInstance;
705
651
  };
652
+
706
653
  /**
707
654
  * Return the proxy and a reset function
708
655
  */
709
-
710
-
711
656
  return {
712
657
  proxy,
713
658
  reset,
@@ -716,10 +661,8 @@ const createSingletonProxy = createInstance => {
716
661
  };
717
662
 
718
663
  const rapierContext = /*#__PURE__*/React.createContext(undefined);
719
-
720
664
  const getCollisionPayloadFromSource = (target, other) => {
721
665
  var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
722
-
723
666
  return {
724
667
  target: {
725
668
  rigidBody: target.rigidBody.object,
@@ -739,13 +682,11 @@ const getCollisionPayloadFromSource = (target, other) => {
739
682
  rigidBodyObject: (_other$rigidBody$stat2 = other.rigidBody.state) === null || _other$rigidBody$stat2 === void 0 ? void 0 : _other$rigidBody$stat2.object
740
683
  };
741
684
  };
742
-
743
685
  const importRapier = async () => {
744
686
  let r = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@dimforge/rapier3d-compat')); });
745
687
  await r.init();
746
688
  return r;
747
689
  };
748
-
749
690
  /**
750
691
  * The main physics component used to create a physics world.
751
692
  * @category Components
@@ -768,7 +709,7 @@ const Physics = props => {
768
709
  numInternalPgsIterations = 1,
769
710
  minIslandSize = 128,
770
711
  maxCcdSubsteps = 1,
771
- erp = 0.8,
712
+ contactNaturalFrequency = 30,
772
713
  lengthUnit = 1
773
714
  } = props;
774
715
  const rapier = suspendReact.suspend(importRapier, ["@react-thee/rapier", importRapier]);
@@ -782,12 +723,12 @@ const Physics = props => {
782
723
  const eventQueue = useConst(() => new rapier3dCompat.EventQueue(false));
783
724
  const beforeStepCallbacks = useConst(() => new Set());
784
725
  const afterStepCallbacks = useConst(() => new Set());
726
+
785
727
  /**
786
728
  * Initiate the world
787
729
  * This creates a singleton proxy, so that the world is only created when
788
730
  * something within it is accessed.
789
731
  */
790
-
791
732
  const {
792
733
  proxy: worldProxy,
793
734
  reset: resetWorldProxy,
@@ -798,8 +739,9 @@ const Physics = props => {
798
739
  worldProxy.free();
799
740
  resetWorldProxy();
800
741
  };
801
- }, []); // Update mutable props
742
+ }, []);
802
743
 
744
+ // Update mutable props
803
745
  React.useEffect(() => {
804
746
  worldProxy.gravity = vector3ToRapierVector(gravity);
805
747
  worldProxy.integrationParameters.numSolverIterations = numSolverIterations;
@@ -809,12 +751,11 @@ const Physics = props => {
809
751
  worldProxy.integrationParameters.minIslandSize = minIslandSize;
810
752
  worldProxy.integrationParameters.maxCcdSubsteps = maxCcdSubsteps;
811
753
  worldProxy.integrationParameters.normalizedPredictionDistance = predictionDistance;
812
- worldProxy.integrationParameters.erp = erp;
813
754
  worldProxy.lengthUnit = lengthUnit;
814
- }, [worldProxy, ...gravity, numSolverIterations, numAdditionalFrictionIterations, numInternalPgsIterations, allowedLinearError, minIslandSize, maxCcdSubsteps, predictionDistance, erp, lengthUnit]);
755
+ worldProxy.integrationParameters.contact_natural_frequency = contactNaturalFrequency;
756
+ }, [worldProxy, ...gravity, numSolverIterations, numAdditionalFrictionIterations, numInternalPgsIterations, allowedLinearError, minIslandSize, maxCcdSubsteps, predictionDistance, lengthUnit, contactNaturalFrequency]);
815
757
  const getSourceFromColliderHandle = React.useCallback(handle => {
816
758
  var _collider$parent;
817
-
818
759
  const collider = worldProxy.getCollider(handle);
819
760
  const colEvents = colliderEvents.get(handle);
820
761
  const colliderState = colliderStates.get(handle);
@@ -842,37 +783,36 @@ const Physics = props => {
842
783
  });
843
784
  const step = React.useCallback(dt => {
844
785
  const world = worldProxy;
786
+
845
787
  /* Check if the timestep is supposed to be variable. We'll do this here
846
788
  once so we don't have to string-check every frame. */
847
-
848
789
  const timeStepVariable = timeStep === "vary";
790
+
849
791
  /**
850
792
  * Fixed timeStep simulation progression
851
793
  * @see https://gafferongames.com/post/fix_your_timestep/
852
794
  */
853
795
 
854
796
  const clampedDelta = three.MathUtils.clamp(dt, 0, 0.5);
855
-
856
797
  const stepWorld = delta => {
857
798
  // Trigger beforeStep callbacks
858
799
  beforeStepCallbacks.forEach(callback => {
859
800
  callback.current(world);
860
801
  });
861
802
  world.timestep = delta;
862
- world.step(eventQueue); // Trigger afterStep callbacks
803
+ world.step(eventQueue);
863
804
 
805
+ // Trigger afterStep callbacks
864
806
  afterStepCallbacks.forEach(callback => {
865
807
  callback.current(world);
866
808
  });
867
809
  };
868
-
869
810
  if (timeStepVariable) {
870
811
  stepWorld(clampedDelta);
871
812
  } else {
872
813
  // don't step time forwards if paused
873
814
  // Increase accumulator
874
815
  steppingState.accumulator += clampedDelta;
875
-
876
816
  while (steppingState.accumulator >= timeStep) {
877
817
  // Set up previous state
878
818
  // needed for accurate interpolations if the world steps more than once
@@ -885,57 +825,48 @@ const Physics = props => {
885
825
  };
886
826
  });
887
827
  }
888
-
889
828
  stepWorld(timeStep);
890
829
  steppingState.accumulator -= timeStep;
891
830
  }
892
831
  }
832
+ const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep;
893
833
 
894
- const interpolationAlpha = timeStepVariable || !interpolate || paused ? 1 : steppingState.accumulator / timeStep; // Update meshes
895
-
834
+ // Update meshes
896
835
  rigidBodyStates.forEach((state, handle) => {
897
836
  const rigidBody = world.getRigidBody(handle);
898
837
  const events = rigidBodyEvents.get(handle);
899
-
900
838
  if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
901
839
  if (rigidBody.isSleeping() && !state.isSleeping) {
902
840
  var _events$onSleep;
903
-
904
841
  events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
905
842
  }
906
-
907
843
  if (!rigidBody.isSleeping() && state.isSleeping) {
908
844
  var _events$onWake;
909
-
910
845
  events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
911
846
  }
912
-
913
847
  state.isSleeping = rigidBody.isSleeping();
914
848
  }
915
-
916
849
  if (!rigidBody || rigidBody.isSleeping() && !("isInstancedMesh" in state.object) || !state.setMatrix) {
917
850
  return;
918
- } // New states
919
-
851
+ }
920
852
 
853
+ // New states
921
854
  let t = rigidBody.translation();
922
855
  let r = rigidBody.rotation();
923
856
  let previousState = steppingState.previousState[handle];
924
-
925
857
  if (previousState) {
926
858
  // Get previous simulated world position
927
- _matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale); // Apply previous tick position
928
-
859
+ _matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
929
860
 
861
+ // Apply previous tick position
930
862
  if (state.meshType == "mesh") {
931
863
  state.object.position.copy(_position);
932
864
  state.object.quaternion.copy(_rotation);
933
865
  }
934
- } // Get new position
935
-
866
+ }
936
867
 
868
+ // Get new position
937
869
  _matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
938
-
939
870
  if (state.meshType == "instancedMesh") {
940
871
  state.setMatrix(_matrix4);
941
872
  } else {
@@ -946,19 +877,17 @@ const Physics = props => {
946
877
  });
947
878
  eventQueue.drainCollisionEvents((handle1, handle2, started) => {
948
879
  const source1 = getSourceFromColliderHandle(handle1);
949
- const source2 = getSourceFromColliderHandle(handle2); // Collision Events
880
+ const source2 = getSourceFromColliderHandle(handle2);
950
881
 
882
+ // Collision Events
951
883
  if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
952
884
  return;
953
885
  }
954
-
955
886
  const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
956
887
  const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
957
-
958
888
  if (started) {
959
889
  world.contactPair(source1.collider.object, source2.collider.object, (manifold, flipped) => {
960
890
  var _source1$rigidBody$ev, _source1$rigidBody$ev2, _source2$rigidBody$ev, _source2$rigidBody$ev2, _source1$collider$eve, _source1$collider$eve2, _source2$collider$eve, _source2$collider$eve2;
961
-
962
891
  /* RigidBody events */
963
892
  (_source1$rigidBody$ev = source1.rigidBody.events) === null || _source1$rigidBody$ev === void 0 ? void 0 : (_source1$rigidBody$ev2 = _source1$rigidBody$ev.onCollisionEnter) === null || _source1$rigidBody$ev2 === void 0 ? void 0 : _source1$rigidBody$ev2.call(_source1$rigidBody$ev, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
964
893
  manifold,
@@ -968,8 +897,8 @@ const Physics = props => {
968
897
  manifold,
969
898
  flipped
970
899
  }));
971
- /* Collider events */
972
900
 
901
+ /* Collider events */
973
902
  (_source1$collider$eve = source1.collider.events) === null || _source1$collider$eve === void 0 ? void 0 : (_source1$collider$eve2 = _source1$collider$eve.onCollisionEnter) === null || _source1$collider$eve2 === void 0 ? void 0 : _source1$collider$eve2.call(_source1$collider$eve, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
974
903
  manifold,
975
904
  flipped
@@ -981,18 +910,16 @@ const Physics = props => {
981
910
  });
982
911
  } else {
983
912
  var _source1$rigidBody$ev3, _source1$rigidBody$ev4, _source2$rigidBody$ev3, _source2$rigidBody$ev4, _source1$collider$eve3, _source1$collider$eve4, _source2$collider$eve3, _source2$collider$eve4;
984
-
985
913
  (_source1$rigidBody$ev3 = source1.rigidBody.events) === null || _source1$rigidBody$ev3 === void 0 ? void 0 : (_source1$rigidBody$ev4 = _source1$rigidBody$ev3.onCollisionExit) === null || _source1$rigidBody$ev4 === void 0 ? void 0 : _source1$rigidBody$ev4.call(_source1$rigidBody$ev3, collisionPayload1);
986
914
  (_source2$rigidBody$ev3 = source2.rigidBody.events) === null || _source2$rigidBody$ev3 === void 0 ? void 0 : (_source2$rigidBody$ev4 = _source2$rigidBody$ev3.onCollisionExit) === null || _source2$rigidBody$ev4 === void 0 ? void 0 : _source2$rigidBody$ev4.call(_source2$rigidBody$ev3, collisionPayload2);
987
915
  (_source1$collider$eve3 = source1.collider.events) === null || _source1$collider$eve3 === void 0 ? void 0 : (_source1$collider$eve4 = _source1$collider$eve3.onCollisionExit) === null || _source1$collider$eve4 === void 0 ? void 0 : _source1$collider$eve4.call(_source1$collider$eve3, collisionPayload1);
988
916
  (_source2$collider$eve3 = source2.collider.events) === null || _source2$collider$eve3 === void 0 ? void 0 : (_source2$collider$eve4 = _source2$collider$eve3.onCollisionExit) === null || _source2$collider$eve4 === void 0 ? void 0 : _source2$collider$eve4.call(_source2$collider$eve3, collisionPayload2);
989
- } // Sensor Intersections
990
-
917
+ }
991
918
 
919
+ // Sensor Intersections
992
920
  if (started) {
993
921
  if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
994
922
  var _source1$rigidBody$ev5, _source1$rigidBody$ev6, _source2$rigidBody$ev5, _source2$rigidBody$ev6, _source1$collider$eve5, _source1$collider$eve6, _source2$collider$eve5, _source2$collider$eve6;
995
-
996
923
  (_source1$rigidBody$ev5 = source1.rigidBody.events) === null || _source1$rigidBody$ev5 === void 0 ? void 0 : (_source1$rigidBody$ev6 = _source1$rigidBody$ev5.onIntersectionEnter) === null || _source1$rigidBody$ev6 === void 0 ? void 0 : _source1$rigidBody$ev6.call(_source1$rigidBody$ev5, collisionPayload1);
997
924
  (_source2$rigidBody$ev5 = source2.rigidBody.events) === null || _source2$rigidBody$ev5 === void 0 ? void 0 : (_source2$rigidBody$ev6 = _source2$rigidBody$ev5.onIntersectionEnter) === null || _source2$rigidBody$ev6 === void 0 ? void 0 : _source2$rigidBody$ev6.call(_source2$rigidBody$ev5, collisionPayload2);
998
925
  (_source1$collider$eve5 = source1.collider.events) === null || _source1$collider$eve5 === void 0 ? void 0 : (_source1$collider$eve6 = _source1$collider$eve5.onIntersectionEnter) === null || _source1$collider$eve6 === void 0 ? void 0 : _source1$collider$eve6.call(_source1$collider$eve5, collisionPayload1);
@@ -1000,7 +927,6 @@ const Physics = props => {
1000
927
  }
1001
928
  } else {
1002
929
  var _source1$rigidBody$ev7, _source1$rigidBody$ev8, _source2$rigidBody$ev7, _source2$rigidBody$ev8, _source1$collider$eve7, _source1$collider$eve8, _source2$collider$eve7, _source2$collider$eve8;
1003
-
1004
930
  (_source1$rigidBody$ev7 = source1.rigidBody.events) === null || _source1$rigidBody$ev7 === void 0 ? void 0 : (_source1$rigidBody$ev8 = _source1$rigidBody$ev7.onIntersectionExit) === null || _source1$rigidBody$ev8 === void 0 ? void 0 : _source1$rigidBody$ev8.call(_source1$rigidBody$ev7, collisionPayload1);
1005
931
  (_source2$rigidBody$ev7 = source2.rigidBody.events) === null || _source2$rigidBody$ev7 === void 0 ? void 0 : (_source2$rigidBody$ev8 = _source2$rigidBody$ev7.onIntersectionExit) === null || _source2$rigidBody$ev8 === void 0 ? void 0 : _source2$rigidBody$ev8.call(_source2$rigidBody$ev7, collisionPayload2);
1006
932
  (_source1$collider$eve7 = source1.collider.events) === null || _source1$collider$eve7 === void 0 ? void 0 : (_source1$collider$eve8 = _source1$collider$eve7.onIntersectionExit) === null || _source1$collider$eve8 === void 0 ? void 0 : _source1$collider$eve8.call(_source1$collider$eve7, collisionPayload1);
@@ -1009,14 +935,13 @@ const Physics = props => {
1009
935
  });
1010
936
  eventQueue.drainContactForceEvents(event => {
1011
937
  var _source1$rigidBody$ev9, _source1$rigidBody$ev10, _source2$rigidBody$ev9, _source2$rigidBody$ev10, _source1$collider$eve9, _source1$collider$eve10, _source2$collider$eve9, _source2$collider$eve10;
1012
-
1013
938
  const source1 = getSourceFromColliderHandle(event.collider1());
1014
- const source2 = getSourceFromColliderHandle(event.collider2()); // Collision Events
939
+ const source2 = getSourceFromColliderHandle(event.collider2());
1015
940
 
941
+ // Collision Events
1016
942
  if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
1017
943
  return;
1018
944
  }
1019
-
1020
945
  const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
1021
946
  const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
1022
947
  (_source1$rigidBody$ev9 = source1.rigidBody.events) === null || _source1$rigidBody$ev9 === void 0 ? void 0 : (_source1$rigidBody$ev10 = _source1$rigidBody$ev9.onContactForce) === null || _source1$rigidBody$ev10 === void 0 ? void 0 : _source1$rigidBody$ev10.call(_source1$rigidBody$ev9, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
@@ -1083,41 +1008,44 @@ const Physics = props => {
1083
1008
  };
1084
1009
 
1085
1010
  function _extends() {
1086
- _extends = Object.assign ? Object.assign.bind() : function (target) {
1087
- for (var i = 1; i < arguments.length; i++) {
1088
- var source = arguments[i];
1089
-
1090
- for (var key in source) {
1091
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1092
- target[key] = source[key];
1093
- }
1094
- }
1011
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
1012
+ for (var e = 1; e < arguments.length; e++) {
1013
+ var t = arguments[e];
1014
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
1095
1015
  }
1096
-
1097
- return target;
1098
- };
1099
- return _extends.apply(this, arguments);
1016
+ return n;
1017
+ }, _extends.apply(null, arguments);
1100
1018
  }
1101
1019
 
1020
+ // Need to catch the case where forwardedRef is a function... how to do that?
1021
+ const useForwardedRef = (forwardedRef, defaultValue = null) => {
1022
+ const innerRef = React.useRef(defaultValue);
1023
+
1024
+ // Update the forwarded ref when the inner ref changes
1025
+ if (forwardedRef && typeof forwardedRef !== "function") {
1026
+ if (!forwardedRef.current) {
1027
+ forwardedRef.current = innerRef.current;
1028
+ }
1029
+ return forwardedRef;
1030
+ }
1031
+ return innerRef;
1032
+ };
1033
+
1102
1034
  /**
1103
1035
  * Initiate an instance and return a safe getter
1104
1036
  */
1105
-
1106
1037
  const useImperativeInstance = (createFn, destroyFn, dependencyList) => {
1107
- const ref = React.useRef();
1038
+ const ref = React.useRef(undefined);
1108
1039
  const getInstance = React.useCallback(() => {
1109
1040
  if (!ref.current) {
1110
1041
  ref.current = createFn();
1111
1042
  }
1112
-
1113
1043
  return ref.current;
1114
1044
  }, dependencyList);
1115
1045
  React.useEffect(() => {
1116
1046
  // Save the destroy function and instance
1117
1047
  const instance = getInstance();
1118
-
1119
1048
  const destroy = () => destroyFn(instance);
1120
-
1121
1049
  return () => {
1122
1050
  destroy();
1123
1051
  ref.current = undefined;
@@ -1126,102 +1054,238 @@ const useImperativeInstance = (createFn, destroyFn, dependencyList) => {
1126
1054
  return getInstance;
1127
1055
  };
1128
1056
 
1129
- /**
1130
- * Takes an object resembling a Vector3 and returs a Three.Vector3
1131
- * @category Math helpers
1132
- */
1133
-
1134
- const vec3 = ({
1135
- x,
1136
- y,
1137
- z
1138
- } = {
1139
- x: 0,
1140
- y: 0,
1141
- z: 0
1142
- }) => {
1143
- return new three.Vector3(x, y, z);
1144
- };
1145
- /**
1146
- * Takes an object resembling a Quaternion and returs a Three.Quaternion
1147
- * @category Math helpers
1148
- */
1057
+ const rigidBodyDescFromOptions = options => {
1058
+ var _options$canSleep;
1059
+ const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
1060
+ const desc = new rapier3dCompat.RigidBodyDesc(type);
1149
1061
 
1150
- const quat = ({
1151
- x,
1152
- y,
1153
- z,
1154
- w
1155
- } = {
1156
- x: 0,
1157
- y: 0,
1158
- z: 0,
1159
- w: 1
1160
- }) => {
1161
- return new three.Quaternion(x, y, z, w);
1062
+ // Apply immutable options
1063
+ desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
1064
+ return desc;
1162
1065
  };
1163
- /**
1164
- * Takes an object resembling an Euler and returs a Three.Euler
1165
- * @category Math helpers
1166
- */
1167
-
1168
- const euler = ({
1169
- x,
1170
- y,
1171
- z
1172
- } = {
1173
- x: 0,
1174
- y: 0,
1175
- z: 0
1066
+ const createRigidBodyState = ({
1067
+ rigidBody,
1068
+ object,
1069
+ setMatrix,
1070
+ getMatrix,
1071
+ worldScale,
1072
+ meshType: _meshType = "mesh"
1176
1073
  }) => {
1177
- return new three.Euler(x, y, z);
1178
- };
1179
-
1180
- const useForwardedRef = (forwardedRef, defaultValue = null) => {
1181
- const innerRef = React.useRef(defaultValue); // Update the forwarded ref when the inner ref changes
1182
-
1183
- if (forwardedRef && typeof forwardedRef !== "function") {
1184
- if (!forwardedRef.current) {
1185
- forwardedRef.current = innerRef.current;
1186
- }
1187
-
1188
- return forwardedRef;
1189
- }
1190
-
1191
- return innerRef;
1074
+ object.updateWorldMatrix(true, false);
1075
+ const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
1076
+ return {
1077
+ object,
1078
+ rigidBody,
1079
+ invertedWorldMatrix,
1080
+ setMatrix: setMatrix ? setMatrix : matrix => {
1081
+ object.matrix.copy(matrix);
1082
+ },
1083
+ getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
1084
+ scale: worldScale || object.getWorldScale(_scale).clone(),
1085
+ isSleeping: false,
1086
+ meshType: _meshType
1087
+ };
1192
1088
  };
1193
-
1194
- /**
1195
- * A collider is a shape that can be attached to a rigid body to define its physical properties.
1196
- * @internal
1197
- */
1198
- const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
1199
- const {
1200
- children,
1201
- position,
1202
- rotation,
1203
- quaternion,
1204
- scale,
1205
- name
1206
- } = props;
1207
- const {
1208
- world,
1209
- colliderEvents,
1210
- colliderStates
1211
- } = useRapier();
1212
- const rigidBodyContext = useRigidBodyContext();
1213
- const colliderRef = useForwardedRef(forwardedRef);
1214
- const objectRef = React.useRef(null); // We spread the props out here to make sure that the ref is updated when the props change.
1215
-
1216
- const immutablePropArray = immutableColliderOptions.flatMap(key => Array.isArray(props[key]) ? [...props[key]] : props[key]);
1217
- const getInstance = useImperativeInstance(() => {
1218
- const worldScale = objectRef.current.getWorldScale(vec3());
1219
- const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
1220
-
1221
- if (typeof forwardedRef == "function") {
1222
- forwardedRef(collider);
1223
- }
1224
-
1089
+ const immutableRigidBodyOptions = ["args", "colliders", "canSleep"];
1090
+ const mutableRigidBodyOptions = {
1091
+ gravityScale: (rb, value) => {
1092
+ rb.setGravityScale(value, true);
1093
+ },
1094
+ additionalSolverIterations(rb, value) {
1095
+ rb.setAdditionalSolverIterations(value);
1096
+ },
1097
+ linearDamping: (rb, value) => {
1098
+ rb.setLinearDamping(value);
1099
+ },
1100
+ angularDamping: (rb, value) => {
1101
+ rb.setAngularDamping(value);
1102
+ },
1103
+ dominanceGroup: (rb, value) => {
1104
+ rb.setDominanceGroup(value);
1105
+ },
1106
+ enabledRotations: (rb, [x, y, z]) => {
1107
+ rb.setEnabledRotations(x, y, z, true);
1108
+ },
1109
+ enabledTranslations: (rb, [x, y, z]) => {
1110
+ rb.setEnabledTranslations(x, y, z, true);
1111
+ },
1112
+ lockRotations: (rb, value) => {
1113
+ rb.lockRotations(value, true);
1114
+ },
1115
+ lockTranslations: (rb, value) => {
1116
+ rb.lockTranslations(value, true);
1117
+ },
1118
+ angularVelocity: (rb, [x, y, z]) => {
1119
+ rb.setAngvel({
1120
+ x,
1121
+ y,
1122
+ z
1123
+ }, true);
1124
+ },
1125
+ linearVelocity: (rb, [x, y, z]) => {
1126
+ rb.setLinvel({
1127
+ x,
1128
+ y,
1129
+ z
1130
+ }, true);
1131
+ },
1132
+ ccd: (rb, value) => {
1133
+ rb.enableCcd(value);
1134
+ },
1135
+ softCcdPrediction: (rb, value) => {
1136
+ rb.setSoftCcdPrediction(value);
1137
+ },
1138
+ userData: (rb, value) => {
1139
+ rb.userData = value;
1140
+ },
1141
+ type(rb, value) {
1142
+ rb.setBodyType(rigidBodyTypeFromString(value), true);
1143
+ },
1144
+ position: () => {},
1145
+ rotation: () => {},
1146
+ quaternion: () => {},
1147
+ scale: () => {}
1148
+ };
1149
+ const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
1150
+ const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
1151
+ if (!rigidBody) {
1152
+ return;
1153
+ }
1154
+ const state = states.get(rigidBody.handle);
1155
+ if (state) {
1156
+ if (updateTranslations) {
1157
+ state.object.updateWorldMatrix(true, false);
1158
+ _matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
1159
+ rigidBody.setTranslation(_position, false);
1160
+ rigidBody.setRotation(_rotation, false);
1161
+ }
1162
+ mutableRigidBodyOptionKeys.forEach(key => {
1163
+ if (key in options) {
1164
+ mutableRigidBodyOptions[key](rigidBody, options[key]);
1165
+ }
1166
+ });
1167
+ }
1168
+ };
1169
+ const useUpdateRigidBodyOptions = (getRigidBody, props, states, updateTranslations = true) => {
1170
+ // TODO: Improve this, split each prop into its own effect
1171
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
1172
+ return vectorToTuple(props[key]);
1173
+ }), [props]);
1174
+ React.useEffect(() => {
1175
+ const rigidBody = getRigidBody();
1176
+ setRigidBodyOptions(rigidBody, props, states, updateTranslations);
1177
+ }, mutablePropsAsFlatArray);
1178
+ };
1179
+ const useRigidBodyEvents = (getRigidBody, props, events) => {
1180
+ const {
1181
+ onWake,
1182
+ onSleep,
1183
+ onCollisionEnter,
1184
+ onCollisionExit,
1185
+ onIntersectionEnter,
1186
+ onIntersectionExit,
1187
+ onContactForce
1188
+ } = props;
1189
+ const eventHandlers = {
1190
+ onWake,
1191
+ onSleep,
1192
+ onCollisionEnter,
1193
+ onCollisionExit,
1194
+ onIntersectionEnter,
1195
+ onIntersectionExit,
1196
+ onContactForce
1197
+ };
1198
+ React.useEffect(() => {
1199
+ const rigidBody = getRigidBody();
1200
+ events.set(rigidBody.handle, eventHandlers);
1201
+ return () => {
1202
+ events.delete(rigidBody.handle);
1203
+ };
1204
+ }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
1205
+ };
1206
+
1207
+ /**
1208
+ * Takes an object resembling a Vector3 and returs a Three.Vector3
1209
+ * @category Math helpers
1210
+ */
1211
+ const vec3 = ({
1212
+ x,
1213
+ y,
1214
+ z
1215
+ } = {
1216
+ x: 0,
1217
+ y: 0,
1218
+ z: 0
1219
+ }) => {
1220
+ return new three.Vector3(x, y, z);
1221
+ };
1222
+
1223
+ /**
1224
+ * Takes an object resembling a Quaternion and returs a Three.Quaternion
1225
+ * @category Math helpers
1226
+ */
1227
+ const quat = ({
1228
+ x,
1229
+ y,
1230
+ z,
1231
+ w
1232
+ } = {
1233
+ x: 0,
1234
+ y: 0,
1235
+ z: 0,
1236
+ w: 1
1237
+ }) => {
1238
+ return new three.Quaternion(x, y, z, w);
1239
+ };
1240
+
1241
+ /**
1242
+ * Takes an object resembling an Euler and returs a Three.Euler
1243
+ * @category Math helpers
1244
+ */
1245
+ const euler = ({
1246
+ x,
1247
+ y,
1248
+ z
1249
+ } = {
1250
+ x: 0,
1251
+ y: 0,
1252
+ z: 0
1253
+ }) => {
1254
+ return new three.Euler(x, y, z);
1255
+ };
1256
+
1257
+ /**
1258
+ * A collider is a shape that can be attached to a rigid body to define its physical properties.
1259
+ * @internal
1260
+ */
1261
+ const AnyCollider = /*#__PURE__*/React.memo(props => {
1262
+ const {
1263
+ children,
1264
+ position,
1265
+ rotation,
1266
+ quaternion,
1267
+ scale,
1268
+ name
1269
+ } = props;
1270
+ const {
1271
+ world,
1272
+ colliderEvents,
1273
+ colliderStates
1274
+ } = useRapier();
1275
+ const rigidBodyContext = useRigidBodyContext();
1276
+ const colliderRef = useForwardedRef(props.ref);
1277
+ const objectRef = React.useRef(null);
1278
+
1279
+ // We spread the props out here to make sure that the ref is updated when the props change.
1280
+ const immutablePropArray = immutableColliderOptions.flatMap(key =>
1281
+ // Array.isArray(props[key]) ? [...props[key]] : props[key]
1282
+ Array.isArray(props[key]) ? props[key] : [props[key]]);
1283
+ const getInstance = useImperativeInstance(() => {
1284
+ const worldScale = objectRef.current.getWorldScale(vec3());
1285
+ const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.getRigidBody);
1286
+ if (typeof props.ref == "function") {
1287
+ props.ref(collider);
1288
+ }
1225
1289
  colliderRef.current = collider;
1226
1290
  return collider;
1227
1291
  }, collider => {
@@ -1249,8 +1313,7 @@ const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((prop
1249
1313
  ref: objectRef,
1250
1314
  name: name
1251
1315
  }, children);
1252
- }));
1253
-
1316
+ });
1254
1317
  /**
1255
1318
  * A cuboid collider shape
1256
1319
  * @category Colliders
@@ -1262,7 +1325,6 @@ const CuboidCollider = /*#__PURE__*/React__default["default"].forwardRef((props,
1262
1325
  }));
1263
1326
  });
1264
1327
  CuboidCollider.displayName = "CuboidCollider";
1265
-
1266
1328
  /**
1267
1329
  * A round cuboid collider shape
1268
1330
  * @category Colliders
@@ -1272,7 +1334,6 @@ const RoundCuboidCollider = /*#__PURE__*/React__default["default"].forwardRef((p
1272
1334
  ref: ref
1273
1335
  })));
1274
1336
  RoundCuboidCollider.displayName = "RoundCuboidCollider";
1275
-
1276
1337
  /**
1277
1338
  * A ball collider shape
1278
1339
  * @category Colliders
@@ -1282,7 +1343,6 @@ const BallCollider = /*#__PURE__*/React__default["default"].forwardRef((props, r
1282
1343
  ref: ref
1283
1344
  })));
1284
1345
  BallCollider.displayName = "BallCollider";
1285
-
1286
1346
  /**
1287
1347
  * A capsule collider shape
1288
1348
  * @category Colliders
@@ -1292,7 +1352,6 @@ const CapsuleCollider = /*#__PURE__*/React__default["default"].forwardRef((props
1292
1352
  ref: ref
1293
1353
  })));
1294
1354
  CapsuleCollider.displayName = "CapsuleCollider";
1295
-
1296
1355
  /**
1297
1356
  * A heightfield collider shape
1298
1357
  * @category Colliders
@@ -1302,7 +1361,6 @@ const HeightfieldCollider = /*#__PURE__*/React__default["default"].forwardRef((p
1302
1361
  ref: ref
1303
1362
  })));
1304
1363
  HeightfieldCollider.displayName = "HeightfieldCollider";
1305
-
1306
1364
  /**
1307
1365
  * A trimesh collider shape
1308
1366
  * @category Colliders
@@ -1312,7 +1370,6 @@ const TrimeshCollider = /*#__PURE__*/React__default["default"].forwardRef((props
1312
1370
  ref: ref
1313
1371
  })));
1314
1372
  TrimeshCollider.displayName = "TrimeshCollider";
1315
-
1316
1373
  /**
1317
1374
  * A cone collider shape
1318
1375
  * @category Colliders
@@ -1322,7 +1379,6 @@ const ConeCollider = /*#__PURE__*/React__default["default"].forwardRef((props, r
1322
1379
  ref: ref
1323
1380
  })));
1324
1381
  ConeCollider.displayName = "ConeCollider";
1325
-
1326
1382
  /**
1327
1383
  * A round cylinder collider shape
1328
1384
  * @category Colliders
@@ -1332,7 +1388,6 @@ const RoundConeCollider = /*#__PURE__*/React__default["default"].forwardRef((pro
1332
1388
  ref: ref
1333
1389
  })));
1334
1390
  RoundConeCollider.displayName = "RoundConeCollider";
1335
-
1336
1391
  /**
1337
1392
  * A cylinder collider shape
1338
1393
  * @category Colliders
@@ -1342,7 +1397,6 @@ const CylinderCollider = /*#__PURE__*/React__default["default"].forwardRef((prop
1342
1397
  ref: ref
1343
1398
  })));
1344
1399
  CylinderCollider.displayName = "CylinderCollider";
1345
-
1346
1400
  /**
1347
1401
  * A round cylinder collider shape
1348
1402
  * @category Colliders
@@ -1352,7 +1406,6 @@ const RoundCylinderCollider = /*#__PURE__*/React__default["default"].forwardRef(
1352
1406
  ref: ref
1353
1407
  })));
1354
1408
  CylinderCollider.displayName = "RoundCylinderCollider";
1355
-
1356
1409
  /**
1357
1410
  * A convex hull collider shape
1358
1411
  * @category Colliders
@@ -1363,187 +1416,27 @@ const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((pr
1363
1416
  })));
1364
1417
  ConvexHullCollider.displayName = "ConvexHullCollider";
1365
1418
 
1366
- const rigidBodyDescFromOptions = options => {
1367
- var _options$canSleep;
1368
-
1369
- const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
1370
- const desc = new rapier3dCompat.RigidBodyDesc(type); // Apply immutable options
1371
-
1372
- desc.canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
1373
- return desc;
1374
- };
1375
- const createRigidBodyState = ({
1376
- rigidBody,
1377
- object,
1378
- setMatrix,
1379
- getMatrix,
1380
- worldScale,
1381
- meshType: _meshType = "mesh"
1382
- }) => {
1383
- object.updateWorldMatrix(true, false);
1384
- const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
1385
- return {
1386
- object,
1387
- rigidBody,
1388
- invertedWorldMatrix,
1389
- setMatrix: setMatrix ? setMatrix : matrix => {
1390
- object.matrix.copy(matrix);
1391
- },
1392
- getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
1393
- scale: worldScale || object.getWorldScale(_scale).clone(),
1394
- isSleeping: false,
1395
- meshType: _meshType
1396
- };
1397
- };
1398
- const immutableRigidBodyOptions = ["args", "colliders", "canSleep"];
1399
- const mutableRigidBodyOptions = {
1400
- gravityScale: (rb, value) => {
1401
- rb.setGravityScale(value, true);
1402
- },
1403
-
1404
- additionalSolverIterations(rb, value) {
1405
- rb.setAdditionalSolverIterations(value);
1406
- },
1407
-
1408
- linearDamping: (rb, value) => {
1409
- rb.setLinearDamping(value);
1410
- },
1411
- angularDamping: (rb, value) => {
1412
- rb.setAngularDamping(value);
1413
- },
1414
- dominanceGroup: (rb, value) => {
1415
- rb.setDominanceGroup(value);
1416
- },
1417
- enabledRotations: (rb, [x, y, z]) => {
1418
- rb.setEnabledRotations(x, y, z, true);
1419
- },
1420
- enabledTranslations: (rb, [x, y, z]) => {
1421
- rb.setEnabledTranslations(x, y, z, true);
1422
- },
1423
- lockRotations: (rb, value) => {
1424
- rb.lockRotations(value, true);
1425
- },
1426
- lockTranslations: (rb, value) => {
1427
- rb.lockTranslations(value, true);
1428
- },
1429
- angularVelocity: (rb, [x, y, z]) => {
1430
- rb.setAngvel({
1431
- x,
1432
- y,
1433
- z
1434
- }, true);
1435
- },
1436
- linearVelocity: (rb, [x, y, z]) => {
1437
- rb.setLinvel({
1438
- x,
1439
- y,
1440
- z
1441
- }, true);
1442
- },
1443
- ccd: (rb, value) => {
1444
- rb.enableCcd(value);
1445
- },
1446
- softCcdPrediction: (rb, value) => {
1447
- rb.setSoftCcdPrediction(value);
1448
- },
1449
- userData: (rb, value) => {
1450
- rb.userData = value;
1451
- },
1452
-
1453
- type(rb, value) {
1454
- rb.setBodyType(rigidBodyTypeFromString(value), true);
1455
- },
1456
-
1457
- position: () => {},
1458
- rotation: () => {},
1459
- quaternion: () => {},
1460
- scale: () => {}
1461
- };
1462
- const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
1463
- const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
1464
- if (!rigidBody) {
1465
- return;
1466
- }
1467
-
1468
- const state = states.get(rigidBody.handle);
1469
-
1470
- if (state) {
1471
- if (updateTranslations) {
1472
- state.object.updateWorldMatrix(true, false);
1473
-
1474
- _matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
1475
-
1476
- rigidBody.setTranslation(_position, false);
1477
- rigidBody.setRotation(_rotation, false);
1478
- }
1479
-
1480
- mutableRigidBodyOptionKeys.forEach(key => {
1481
- if (key in options) {
1482
- mutableRigidBodyOptions[key](rigidBody, options[key]);
1483
- }
1484
- });
1485
- }
1486
- };
1487
- const useUpdateRigidBodyOptions = (getRigidBody, props, states, updateTranslations = true) => {
1488
- // TODO: Improve this, split each prop into its own effect
1489
- const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
1490
- return vectorToTuple(props[key]);
1491
- }), [props]);
1492
- React.useEffect(() => {
1493
- const rigidBody = getRigidBody();
1494
- setRigidBodyOptions(rigidBody, props, states, updateTranslations);
1495
- }, mutablePropsAsFlatArray);
1496
- };
1497
- const useRigidBodyEvents = (getRigidBody, props, events) => {
1498
- const {
1499
- onWake,
1500
- onSleep,
1501
- onCollisionEnter,
1502
- onCollisionExit,
1503
- onIntersectionEnter,
1504
- onIntersectionExit,
1505
- onContactForce
1506
- } = props;
1507
- const eventHandlers = {
1508
- onWake,
1509
- onSleep,
1510
- onCollisionEnter,
1511
- onCollisionExit,
1512
- onIntersectionEnter,
1513
- onIntersectionExit,
1514
- onContactForce
1515
- };
1516
- React.useEffect(() => {
1517
- const rigidBody = getRigidBody();
1518
- events.set(rigidBody.handle, eventHandlers);
1519
- return () => {
1520
- events.delete(rigidBody.handle);
1521
- };
1522
- }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
1523
- };
1524
-
1525
- const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
1419
+ const _excluded$1 = ["ref", "children", "type", "position", "rotation", "scale", "quaternion", "transformState"];
1526
1420
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
1527
1421
  const useRigidBodyContext = () => React.useContext(RigidBodyContext);
1528
-
1529
1422
  /**
1530
1423
  * A rigid body is a physical object that can be simulated by the physics engine.
1531
1424
  * @category Components
1532
1425
  */
1533
- const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
1426
+ const RigidBody = /*#__PURE__*/React.memo(props => {
1534
1427
  const {
1535
- children,
1536
- type,
1537
- position,
1538
- rotation,
1539
- scale,
1540
- quaternion,
1541
- transformState
1542
- } = props,
1543
- objectProps = _objectWithoutProperties(props, _excluded$1);
1544
-
1428
+ ref,
1429
+ children,
1430
+ type,
1431
+ position,
1432
+ rotation,
1433
+ scale,
1434
+ quaternion,
1435
+ transformState
1436
+ } = props,
1437
+ objectProps = _objectWithoutProperties(props, _excluded$1);
1545
1438
  const objectRef = React.useRef(null);
1546
- const rigidBodyRef = useForwardedRef(forwardedRef);
1439
+ const rigidBodyRef = useForwardedRef(ref);
1547
1440
  const {
1548
1441
  world,
1549
1442
  rigidBodyStates,
@@ -1558,24 +1451,24 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1558
1451
  const immutablePropArray = immutableRigidBodyOptions.flatMap(key => {
1559
1452
  return Array.isArray(mergedOptions[key]) ? [...mergedOptions[key]] : mergedOptions[key];
1560
1453
  });
1561
- const childColliderProps = useChildColliderProps(objectRef, mergedOptions); // Provide a way to eagerly create rigidbody
1454
+ const childColliderProps = useChildColliderProps(objectRef, mergedOptions);
1562
1455
 
1456
+ // Provide a way to eagerly create rigidbody
1563
1457
  const getRigidBody = useImperativeInstance(() => {
1564
1458
  const desc = rigidBodyDescFromOptions(mergedOptions);
1565
1459
  const rigidBody = world.createRigidBody(desc);
1566
-
1567
- if (typeof forwardedRef === "function") {
1568
- forwardedRef(rigidBody);
1460
+ if (typeof ref === "function") {
1461
+ ref(rigidBody);
1569
1462
  }
1570
-
1571
1463
  rigidBodyRef.current = rigidBody;
1572
1464
  return rigidBody;
1573
1465
  }, rigidBody => {
1574
1466
  if (world.getRigidBody(rigidBody.handle)) {
1575
1467
  world.removeRigidBody(rigidBody);
1576
1468
  }
1577
- }, immutablePropArray); // Only provide a object state after the ref has been set
1469
+ }, immutablePropArray);
1578
1470
 
1471
+ // Only provide a object state after the ref has been set
1579
1472
  React.useEffect(() => {
1580
1473
  const rigidBody = getRigidBody();
1581
1474
  const state = createRigidBodyState({
@@ -1608,7 +1501,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1608
1501
  }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1609
1502
  key: index
1610
1503
  }, colliderProps)))));
1611
- }));
1504
+ });
1612
1505
  RigidBody.displayName = "RigidBody";
1613
1506
 
1614
1507
  /**
@@ -1645,52 +1538,52 @@ const MeshCollider = /*#__PURE__*/React.memo(props => {
1645
1538
  });
1646
1539
  MeshCollider.displayName = "MeshCollider";
1647
1540
 
1648
- const _excluded = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
1649
- const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props, forwardedRef) => {
1650
- const rigidBodiesRef = useForwardedRef(forwardedRef, []);
1541
+ const _excluded = ["ref"],
1542
+ _excluded2 = ["children", "instances", "colliderNodes", "position", "rotation", "quaternion", "scale"];
1543
+ const InstancedRigidBodies = /*#__PURE__*/React.memo(_ref => {
1544
+ let {
1545
+ ref
1546
+ } = _ref,
1547
+ props = _objectWithoutProperties(_ref, _excluded);
1548
+ const rigidBodiesRef = useForwardedRef(ref, []);
1651
1549
  const objectRef = React.useRef(null);
1652
1550
  const instanceWrapperRef = React.useRef(null);
1653
-
1654
1551
  const {
1655
- // instanced props
1656
- children,
1657
- instances,
1658
- colliderNodes = [],
1659
- // wrapper object props
1660
- position,
1661
- rotation,
1662
- quaternion,
1663
- scale
1664
- } = props,
1665
- rigidBodyProps = _objectWithoutProperties(props, _excluded);
1666
-
1552
+ // instanced props
1553
+ children,
1554
+ instances,
1555
+ colliderNodes = [],
1556
+ // wrapper object props
1557
+ position,
1558
+ rotation,
1559
+ quaternion,
1560
+ scale
1561
+
1562
+ // rigid body specific props, and r3f-object props
1563
+ } = props,
1564
+ rigidBodyProps = _objectWithoutProperties(props, _excluded2);
1667
1565
  const childColliderProps = useChildColliderProps(objectRef, _objectSpread2(_objectSpread2({}, props), {}, {
1668
1566
  children: undefined
1669
1567
  }));
1670
-
1671
1568
  const getInstancedMesh = () => {
1672
1569
  const firstChild = instanceWrapperRef.current.children[0];
1673
-
1674
1570
  if (firstChild && "isInstancedMesh" in firstChild) {
1675
1571
  return firstChild;
1676
1572
  }
1677
-
1678
1573
  return undefined;
1679
1574
  };
1680
-
1681
1575
  React.useEffect(() => {
1682
1576
  const instancedMesh = getInstancedMesh();
1683
-
1684
1577
  if (instancedMesh) {
1685
1578
  instancedMesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
1686
1579
  } else {
1687
1580
  console.warn("InstancedRigidBodies expects exactly one child, which must be an InstancedMesh");
1688
1581
  }
1689
- }, []); // Update the RigidBodyStates whenever the instances change
1582
+ }, []);
1690
1583
 
1584
+ // Update the RigidBodyStates whenever the instances change
1691
1585
  const applyInstancedState = (state, index) => {
1692
1586
  const instancedMesh = getInstancedMesh();
1693
-
1694
1587
  if (instancedMesh) {
1695
1588
  return _objectSpread2(_objectSpread2({}, state), {}, {
1696
1589
  getMatrix: matrix => {
@@ -1704,10 +1597,8 @@ const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forward
1704
1597
  meshType: "instancedMesh"
1705
1598
  });
1706
1599
  }
1707
-
1708
1600
  return state;
1709
1601
  };
1710
-
1711
1602
  return /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
1712
1603
  ref: objectRef
1713
1604
  }, rigidBodyProps, {
@@ -1718,25 +1609,26 @@ const InstancedRigidBodies = /*#__PURE__*/React.memo( /*#__PURE__*/React.forward
1718
1609
  }), /*#__PURE__*/React__default["default"].createElement("object3D", {
1719
1610
  ref: instanceWrapperRef
1720
1611
  }, children), instances === null || instances === void 0 ? void 0 : instances.map((instance, index) => /*#__PURE__*/React__default["default"].createElement(RigidBody, _extends({}, rigidBodyProps, instance, {
1721
- ref: body => rigidBodiesRef.current[index] = body,
1612
+ ref: body => {
1613
+ rigidBodiesRef.current[index] = body;
1614
+ },
1722
1615
  transformState: state => applyInstancedState(state, index)
1723
1616
  }), /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, colliderNodes.map((node, index) => /*#__PURE__*/React__default["default"].createElement(React.Fragment, {
1724
1617
  key: index
1725
1618
  }, node)), childColliderProps.map((colliderProps, colliderIndex) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1726
1619
  key: colliderIndex
1727
1620
  }, colliderProps)))))));
1728
- }));
1621
+ });
1729
1622
  InstancedRigidBodies.displayName = "InstancedRigidBodies";
1730
1623
 
1731
1624
  /**
1732
1625
  * @internal
1733
1626
  */
1734
-
1735
1627
  const useImpulseJoint = (body1, body2, params) => {
1736
1628
  const {
1737
1629
  world
1738
1630
  } = useRapier();
1739
- const jointRef = React.useRef();
1631
+ const jointRef = React.useRef(undefined);
1740
1632
  useImperativeInstance(() => {
1741
1633
  if (body1.current && body2.current) {
1742
1634
  const newJoint = world.createImpulseJoint(params, body1.current, body2.current, true);
@@ -1746,7 +1638,6 @@ const useImpulseJoint = (body1, body2, params) => {
1746
1638
  }, joint => {
1747
1639
  if (joint) {
1748
1640
  jointRef.current = undefined;
1749
-
1750
1641
  if (world.getImpulseJoint(joint.handle)) {
1751
1642
  world.removeImpulseJoint(joint, true);
1752
1643
  }
@@ -1754,6 +1645,7 @@ const useImpulseJoint = (body1, body2, params) => {
1754
1645
  }, []);
1755
1646
  return jointRef;
1756
1647
  };
1648
+
1757
1649
  /**
1758
1650
  * A fixed joint ensures that two rigid-bodies don't move relative to each other.
1759
1651
  * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
@@ -1761,13 +1653,13 @@ const useImpulseJoint = (body1, body2, params) => {
1761
1653
  *
1762
1654
  * @category Hooks - Joints
1763
1655
  */
1764
-
1765
1656
  const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
1766
1657
  const {
1767
1658
  rapier
1768
1659
  } = useRapier();
1769
1660
  return useImpulseJoint(body1, body2, rapier.JointData.fixed(vector3ToRapierVector(body1Anchor), quaternionToRapierQuaternion(body1LocalFrame), vector3ToRapierVector(body2Anchor), quaternionToRapierQuaternion(body2LocalFrame)));
1770
1661
  };
1662
+
1771
1663
  /**
1772
1664
  * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
1773
1665
  * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
@@ -1776,13 +1668,13 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
1776
1668
  *
1777
1669
  * @category Hooks - Joints
1778
1670
  */
1779
-
1780
1671
  const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
1781
1672
  const {
1782
1673
  rapier
1783
1674
  } = useRapier();
1784
1675
  return useImpulseJoint(body1, body2, rapier.JointData.spherical(vector3ToRapierVector(body1Anchor), vector3ToRapierVector(body2Anchor)));
1785
1676
  };
1677
+
1786
1678
  /**
1787
1679
  * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
1788
1680
  * rotations along one axis. This is typically used to simulate wheels, fans, etc.
@@ -1790,20 +1682,18 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
1790
1682
  *
1791
1683
  * @category Hooks - Joints
1792
1684
  */
1793
-
1794
1685
  const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
1795
1686
  const {
1796
1687
  rapier
1797
1688
  } = useRapier();
1798
1689
  const params = rapier.JointData.revolute(vector3ToRapierVector(body1Anchor), vector3ToRapierVector(body2Anchor), vector3ToRapierVector(axis));
1799
-
1800
1690
  if (limits) {
1801
1691
  params.limitsEnabled = true;
1802
1692
  params.limits = limits;
1803
1693
  }
1804
-
1805
1694
  return useImpulseJoint(body1, body2, params);
1806
1695
  };
1696
+
1807
1697
  /**
1808
1698
  * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
1809
1699
  * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
@@ -1811,25 +1701,22 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]
1811
1701
  *
1812
1702
  * @category Hooks - Joints
1813
1703
  */
1814
-
1815
1704
  const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis, limits]) => {
1816
1705
  const {
1817
1706
  rapier
1818
1707
  } = useRapier();
1819
1708
  const params = rapier.JointData.prismatic(vector3ToRapierVector(body1Anchor), vector3ToRapierVector(body2Anchor), vector3ToRapierVector(axis));
1820
-
1821
1709
  if (limits) {
1822
1710
  params.limitsEnabled = true;
1823
1711
  params.limits = limits;
1824
1712
  }
1825
-
1826
1713
  return useImpulseJoint(body1, body2, params);
1827
1714
  };
1715
+
1828
1716
  /**
1829
1717
  * The rope joint limits the max distance between two bodies.
1830
1718
  * @category Hooks - Joints
1831
1719
  */
1832
-
1833
1720
  const useRopeJoint = (body1, body2, [body1Anchor, body2Anchor, length]) => {
1834
1721
  const {
1835
1722
  rapier
@@ -1839,11 +1726,11 @@ const useRopeJoint = (body1, body2, [body1Anchor, body2Anchor, length]) => {
1839
1726
  const params = rapier.JointData.rope(length, vBody1Anchor, vBody2Anchor);
1840
1727
  return useImpulseJoint(body1, body2, params);
1841
1728
  };
1729
+
1842
1730
  /**
1843
1731
  * The spring joint applies a force proportional to the distance between two objects.
1844
1732
  * @category Hooks - Joints
1845
1733
  */
1846
-
1847
1734
  const useSpringJoint = (body1, body2, [body1Anchor, body2Anchor, restLength, stiffness, damping]) => {
1848
1735
  const {
1849
1736
  rapier
@@ -1887,7 +1774,6 @@ const useSpringJoint = (body1, body2, [body1Anchor, body2Anchor, restLength, sti
1887
1774
  * @returns An InteractionGroup bitmask.
1888
1775
  */
1889
1776
  const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
1890
-
1891
1777
  const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1892
1778
 
1893
1779
  Object.defineProperty(exports, 'CoefficientCombineRule', {