@react-three/rapier 0.5.2 → 0.6.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.
@@ -1,9 +1,15 @@
1
- import React, { useRef, useState, useEffect, useMemo, createContext, useContext, forwardRef, useImperativeHandle, memo } from 'react';
1
+ import { ColliderDesc, ActiveEvents, RigidBodyDesc, CoefficientCombineRule, EventQueue, ShapeType } from '@dimforge/rapier3d-compat';
2
+ export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
3
+ import React$1, { useRef, useState, useEffect, useMemo, createContext, useContext, forwardRef, useImperativeHandle, memo } from 'react';
2
4
  import { useAsset } from 'use-asset';
3
5
  import { useFrame } from '@react-three/fiber';
4
- import { ColliderDesc, CoefficientCombineRule, ActiveEvents, EventQueue, ShapeType } from '@dimforge/rapier3d-compat';
5
- export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
6
- import { Quaternion, Euler, Vector3, Object3D, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry } from 'three';
6
+ import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
7
+
8
+ const _quaternion = new Quaternion();
9
+ const _euler = new Euler();
10
+ const _vector3 = new Vector3();
11
+ new Object3D();
12
+ const _matrix4 = new Matrix4();
7
13
 
8
14
  const vectorArrayToObject = arr => {
9
15
  const [x, y, z] = arr;
@@ -13,11 +19,20 @@ const vectorArrayToObject = arr => {
13
19
  z
14
20
  };
15
21
  };
16
- const quaternion = new Quaternion();
17
- const euler = new Euler();
18
22
  const vector3ToQuaternion = v => {
19
- return quaternion.setFromEuler(euler.setFromVector3(v));
23
+ return _quaternion.setFromEuler(_euler.setFromVector3(v));
20
24
  };
25
+ const rapierVector3ToVector3 = ({
26
+ x,
27
+ y,
28
+ z
29
+ }) => _vector3.set(x, y, z).clone();
30
+ const rapierQuaternionToQuaternion = ({
31
+ x,
32
+ y,
33
+ z,
34
+ w
35
+ }) => _quaternion.set(x, y, z, w);
21
36
  const rigidBodyTypeMap = {
22
37
  fixed: 1,
23
38
  dynamic: 0,
@@ -25,6 +40,17 @@ const rigidBodyTypeMap = {
25
40
  kinematicVelocity: 3
26
41
  };
27
42
  const rigidBodyTypeFromString = type => rigidBodyTypeMap[type];
43
+ const decomposeMatrix4 = m => {
44
+ const position = new Vector3();
45
+ const rotation = new Quaternion();
46
+ const scale = new Vector3();
47
+ m.decompose(position, rotation, scale);
48
+ return {
49
+ position,
50
+ rotation,
51
+ scale
52
+ };
53
+ };
28
54
  const scaleColliderArgs = (shape, args, scale) => {
29
55
  // Heightfield only scales the last arg
30
56
  const newArgs = args.slice();
@@ -110,8 +136,7 @@ const isChildOfMeshCollider = child => {
110
136
  const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMeshColliders = true) => {
111
137
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
112
138
  const colliders = [];
113
- let desc;
114
- let offset = new Vector3();
139
+ new Vector3();
115
140
  object.traverse(child => {
116
141
  if ("isMesh" in child) {
117
142
  if (ignoreMeshColliders && isChildOfMeshCollider(child)) return;
@@ -129,62 +154,32 @@ const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMe
129
154
  z: rz,
130
155
  w: rw
131
156
  } = new Quaternion().setFromEuler(child.rotation);
132
- const scale = child.getWorldScale(new Vector3());
133
-
134
- switch (options.colliders) {
135
- case "cuboid":
136
- {
137
- geometry.computeBoundingBox();
138
- const {
139
- boundingBox
140
- } = geometry;
141
- const size = boundingBox.getSize(new Vector3());
142
- boundingBox.getCenter(offset);
143
- desc = ColliderDesc.cuboid(size.x / 2 * scale.x, size.y / 2 * scale.y, size.z / 2 * scale.z);
144
- }
145
- break;
157
+ const scale = child.getWorldScale(new Vector3()); // We translate the colliders based on the parent's world scale
146
158
 
147
- case "ball":
148
- {
149
- geometry.computeBoundingSphere();
150
- const {
151
- boundingSphere
152
- } = geometry;
153
- const radius = boundingSphere.radius * scale.x;
154
- offset.copy(boundingSphere.center);
155
- desc = ColliderDesc.ball(radius);
156
- }
157
- break;
158
-
159
- case "trimesh":
160
- {
161
- var _g$index;
162
-
163
- const _g = geometry.clone().scale(scale.x, scale.y, scale.z);
159
+ const parentWorldScale = child.parent.getWorldScale(new Vector3());
160
+ const desc = colliderDescFromGeometry(geometry, options.colliders, scale, hasCollisionEvents);
161
+ const offset = new Vector3(0, 0, 0);
164
162
 
165
- desc = ColliderDesc.trimesh(_g.attributes.position.array, (_g$index = _g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
166
- }
167
- break;
163
+ if (options.colliders === "cuboid") {
164
+ var _geometry$boundingBox;
168
165
 
169
- case "hull":
170
- const g = geometry.clone().scale(scale.x, scale.y, scale.z);
171
- {
172
- desc = ColliderDesc.convexHull(g.attributes.position.array);
173
- }
174
- break;
175
- } // We translate the colliders based on the parent's world scale
166
+ geometry.computeBoundingBox();
167
+ (_geometry$boundingBox = geometry.boundingBox) === null || _geometry$boundingBox === void 0 ? void 0 : _geometry$boundingBox.getCenter(offset);
168
+ }
176
169
 
170
+ if (options.colliders === "ball") {
171
+ geometry.computeBoundingSphere();
172
+ offset.copy(geometry.boundingSphere.center);
173
+ }
177
174
 
178
- const parentWorldScale = child.parent.getWorldScale(new Vector3());
175
+ if (Number.isFinite(options.friction)) desc.setFriction(options.friction);
176
+ if (Number.isFinite(options.restitution)) desc.setRestitution(options.restitution);
179
177
  desc.setTranslation((x + offset.x) * parentWorldScale.x, (y + offset.y) * parentWorldScale.y, (z + offset.z) * parentWorldScale.z).setRotation({
180
178
  x: rx,
181
179
  y: ry,
182
180
  z: rz,
183
181
  w: rw
184
182
  });
185
- if (hasCollisionEvents) desc.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
186
- if (Number.isFinite(options.friction)) desc.setFriction(options.friction);
187
- if (Number.isFinite(options.restitution)) desc.setRestitution(options.restitution);
188
183
  const actualRigidBody = world.getRigidBody(rigidBody === null || rigidBody === void 0 ? void 0 : rigidBody.handle);
189
184
  const collider = world.createCollider(desc, actualRigidBody);
190
185
  colliders.push(collider);
@@ -192,6 +187,53 @@ const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMe
192
187
  });
193
188
  return colliders;
194
189
  };
190
+ const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents) => {
191
+ let desc;
192
+
193
+ switch (colliders) {
194
+ case "cuboid":
195
+ {
196
+ geometry.computeBoundingBox();
197
+ const {
198
+ boundingBox
199
+ } = geometry;
200
+ const size = boundingBox.getSize(new Vector3());
201
+ desc = ColliderDesc.cuboid(size.x / 2 * scale.x, size.y / 2 * scale.y, size.z / 2 * scale.z);
202
+ }
203
+ break;
204
+
205
+ case "ball":
206
+ {
207
+ geometry.computeBoundingSphere();
208
+ const {
209
+ boundingSphere
210
+ } = geometry;
211
+ const radius = boundingSphere.radius * scale.x;
212
+ desc = ColliderDesc.ball(radius);
213
+ }
214
+ break;
215
+
216
+ case "trimesh":
217
+ {
218
+ var _g$index;
219
+
220
+ const _g = geometry.clone().scale(scale.x, scale.y, scale.z);
221
+
222
+ desc = ColliderDesc.trimesh(_g.attributes.position.array, (_g$index = _g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
223
+ }
224
+ break;
225
+
226
+ case "hull":
227
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
228
+ {
229
+ desc = ColliderDesc.convexHull(g.attributes.position.array);
230
+ }
231
+ break;
232
+ }
233
+
234
+ if (hasCollisionEvents) desc.setActiveEvents(ActiveEvents.COLLISION_EVENTS);
235
+ return desc;
236
+ };
195
237
  const scaleVertices = (vertices, scale) => {
196
238
  const scaledVerts = Array.from(vertices);
197
239
 
@@ -203,6 +245,26 @@ const scaleVertices = (vertices, scale) => {
203
245
 
204
246
  return scaledVerts;
205
247
  };
248
+ const rigidBodyDescFromOptions = options => {
249
+ var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
250
+
251
+ const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
252
+ const [lvx, lvy, lvz] = (_options$linearVeloci = options === null || options === void 0 ? void 0 : options.linearVelocity) !== null && _options$linearVeloci !== void 0 ? _options$linearVeloci : [0, 0, 0];
253
+ const [avx, avy, avz] = (_options$angularVeloc = options === null || options === void 0 ? void 0 : options.angularVelocity) !== null && _options$angularVeloc !== void 0 ? _options$angularVeloc : [0, 0, 0];
254
+ const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
255
+ const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
256
+ const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
257
+ const [erx, ery, erz] = (_options$enabledRotat = options === null || options === void 0 ? void 0 : options.enabledRotations) !== null && _options$enabledRotat !== void 0 ? _options$enabledRotat : [true, true, true];
258
+ const [etx, ety, etz] = (_options$enabledTrans = options === null || options === void 0 ? void 0 : options.enabledTranslations) !== null && _options$enabledTrans !== void 0 ? _options$enabledTrans : [true, true, true];
259
+ const desc = new RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
260
+ x: avx,
261
+ y: avy,
262
+ z: avz
263
+ }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
264
+ if (options.lockRotations) desc.lockRotations();
265
+ if (options.lockTranslations) desc.lockTranslations();
266
+ return desc;
267
+ };
206
268
 
207
269
  const createRigidBodyApi = ref => {
208
270
  return {
@@ -304,18 +366,19 @@ const createRigidBodyApi = ref => {
304
366
  setEnabledRotations: (x, y, z) => ref.current().setEnabledRotations(x, y, z, true),
305
367
  setEnabledTranslations: (x, y, z) => ref.current().setEnabledTranslations(x, y, z, true)
306
368
  };
307
- }; // TODO: Flesh this out
369
+ };
370
+ const createInstancedRigidBodiesApi = bodiesGetter => ({
371
+ at: index => bodiesGetter.current()[index].api,
308
372
 
309
- const createColliderApi = ref => {
310
- return {
311
- raw: () => ref.current(),
373
+ forEach(callback) {
374
+ return bodiesGetter.current().map(b => b.api).forEach(callback);
375
+ },
312
376
 
313
- get handle() {
314
- return ref.current().handle;
315
- }
377
+ get count() {
378
+ return bodiesGetter.current().length;
379
+ }
316
380
 
317
- };
318
- };
381
+ }); // TODO: Flesh this out
319
382
  const createWorldApi = ref => {
320
383
  return {
321
384
  raw: () => ref.current(),
@@ -362,10 +425,10 @@ const importRapier = async () => {
362
425
  };
363
426
 
364
427
  const Physics = ({
365
- colliders: _colliders = 'cuboid',
428
+ colliders: _colliders = "cuboid",
366
429
  gravity: _gravity = [0, -9.81, 0],
367
430
  children,
368
- timeStep: _timeStep = 'vary'
431
+ timeStep: _timeStep = "vary"
369
432
  }) => {
370
433
  const rapier = useAsset(importRapier);
371
434
  const worldRef = useRef();
@@ -378,7 +441,7 @@ const Physics = ({
378
441
  return worldRef.current;
379
442
  });
380
443
  const [colliderMeshes] = useState(() => new Map());
381
- const [rigidBodyMeshes] = useState(() => new Map());
444
+ const [rigidBodyStates] = useState(() => new Map());
382
445
  const [rigidBodyEvents] = useState(() => new Map());
383
446
  const [eventQueue] = useState(() => new EventQueue(false)); // Init world
384
447
 
@@ -408,7 +471,7 @@ const Physics = ({
408
471
  const now = performance.now();
409
472
  const delta = Math.min(100, now - time.current);
410
473
 
411
- if (_timeStep === 'vary') {
474
+ if (_timeStep === "vary") {
412
475
  world.timestep = delta / 1000;
413
476
  } else {
414
477
  world.timestep = _timeStep;
@@ -416,52 +479,35 @@ const Physics = ({
416
479
 
417
480
  world.step(eventQueue); // Update meshes
418
481
 
419
- rigidBodyMeshes.forEach((mesh, handle) => {
482
+ rigidBodyStates.forEach((state, handle) => {
420
483
  const rigidBody = world.getRigidBody(handle);
421
484
  const events = rigidBodyEvents.get(handle);
422
485
 
423
486
  if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
424
- if (rigidBody.isSleeping() && !mesh.userData.isSleeping) {
487
+ if (rigidBody.isSleeping() && !state.isSleeping) {
425
488
  var _events$onSleep;
426
489
 
427
490
  events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
428
491
  }
429
492
 
430
- if (!rigidBody.isSleeping() && mesh.userData.isSleeping) {
493
+ if (!rigidBody.isSleeping() && state.isSleeping) {
431
494
  var _events$onWake;
432
495
 
433
496
  events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
434
497
  }
435
498
 
436
- mesh.userData.isSleeping = rigidBody.isSleeping();
499
+ state.isSleeping = rigidBody.isSleeping();
437
500
  }
438
501
 
439
- if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !mesh.parent) {
502
+ if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !state.setMatrix) {
440
503
  return;
441
504
  }
442
505
 
443
- const {
444
- x,
445
- y,
446
- z
447
- } = rigidBody.translation();
448
- const {
449
- x: rx,
450
- y: ry,
451
- z: rz,
452
- w: rw
453
- } = rigidBody.rotation();
454
- const scale = mesh.getWorldScale(new Vector3()); // haha matrixes I have no idea what I'm doing :)
455
-
456
- const o = new Object3D();
457
- o.position.set(x, y, z);
458
- o.rotation.setFromQuaternion(new Quaternion(rx, ry, rz, rw));
459
- o.scale.set(scale.x, scale.y, scale.z);
460
- o.updateMatrix();
461
- o.applyMatrix4(mesh.parent.matrixWorld.clone().invert());
462
- o.updateMatrix();
463
- mesh.position.setFromMatrixPosition(o.matrix);
464
- mesh.rotation.setFromRotationMatrix(o.matrix);
506
+ state.setMatrix(_matrix4.compose(rapierVector3ToVector3(rigidBody.translation()), rapierQuaternionToQuaternion(rigidBody.rotation()), state.worldScale).premultiply(state.invertedMatrixWorld));
507
+
508
+ if (state.mesh instanceof InstancedMesh) {
509
+ state.mesh.instanceMatrix.needsUpdate = true;
510
+ }
465
511
  }); // Collision events
466
512
 
467
513
  eventQueue.drainCollisionEvents((handle1, handle2, started) => {
@@ -518,14 +564,48 @@ const Physics = ({
518
564
  gravity: _gravity
519
565
  },
520
566
  colliderMeshes,
521
- rigidBodyMeshes,
567
+ rigidBodyStates,
522
568
  rigidBodyEvents
523
569
  }), []);
524
- return /*#__PURE__*/React.createElement(RapierContext.Provider, {
570
+ return /*#__PURE__*/React$1.createElement(RapierContext.Provider, {
525
571
  value: context
526
572
  }, children);
527
573
  };
528
574
 
575
+ function _objectWithoutPropertiesLoose(source, excluded) {
576
+ if (source == null) return {};
577
+ var target = {};
578
+ var sourceKeys = Object.keys(source);
579
+ var key, i;
580
+
581
+ for (i = 0; i < sourceKeys.length; i++) {
582
+ key = sourceKeys[i];
583
+ if (excluded.indexOf(key) >= 0) continue;
584
+ target[key] = source[key];
585
+ }
586
+
587
+ return target;
588
+ }
589
+
590
+ function _objectWithoutProperties(source, excluded) {
591
+ if (source == null) return {};
592
+ var target = _objectWithoutPropertiesLoose(source, excluded);
593
+ var key, i;
594
+
595
+ if (Object.getOwnPropertySymbols) {
596
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
597
+
598
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
599
+ key = sourceSymbolKeys[i];
600
+ if (excluded.indexOf(key) >= 0) continue;
601
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
602
+ target[key] = source[key];
603
+ }
604
+ }
605
+
606
+ return target;
607
+ }
608
+
529
609
  function _defineProperty(obj, key, value) {
530
610
  if (key in obj) {
531
611
  Object.defineProperty(obj, key, {
@@ -572,9 +652,8 @@ const useRapier = () => {
572
652
  };
573
653
  const useRigidBody = (options = {}) => {
574
654
  const {
575
- rapier,
576
655
  world,
577
- rigidBodyMeshes,
656
+ rigidBodyStates,
578
657
  physicsOptions,
579
658
  rigidBodyEvents
580
659
  } = useRapier();
@@ -583,23 +662,7 @@ const useRigidBody = (options = {}) => {
583
662
  const rigidBodyRef = useRef();
584
663
  const getRigidBodyRef = useRef(() => {
585
664
  if (!rigidBodyRef.current) {
586
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
587
-
588
- const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
589
- const [lvx, lvy, lvz] = (_options$linearVeloci = options === null || options === void 0 ? void 0 : options.linearVelocity) !== null && _options$linearVeloci !== void 0 ? _options$linearVeloci : [0, 0, 0];
590
- const [avx, avy, avz] = (_options$angularVeloc = options === null || options === void 0 ? void 0 : options.angularVelocity) !== null && _options$angularVeloc !== void 0 ? _options$angularVeloc : [0, 0, 0];
591
- const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
592
- const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
593
- const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
594
- const [erx, ery, erz] = (_options$enabledRotat = options === null || options === void 0 ? void 0 : options.enabledRotations) !== null && _options$enabledRotat !== void 0 ? _options$enabledRotat : [true, true, true];
595
- const [etx, ety, etz] = (_options$enabledTrans = options === null || options === void 0 ? void 0 : options.enabledTranslations) !== null && _options$enabledTrans !== void 0 ? _options$enabledTrans : [true, true, true];
596
- const desc = new rapier.RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
597
- x: avx,
598
- y: avy,
599
- z: avz
600
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
601
- if (options.lockRotations) desc.lockRotations();
602
- if (options.lockTranslations) desc.lockTranslations();
665
+ const desc = rigidBodyDescFromOptions(options);
603
666
  const rigidBody = world.createRigidBody(desc);
604
667
  rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
605
668
  }
@@ -636,8 +699,7 @@ const useRigidBody = (options = {}) => {
636
699
  y: worldPosition.y + y * scale.y,
637
700
  z: worldPosition.z + z * scale.z
638
701
  }, false);
639
- const eulerAngles = new Euler(rx, ry, rz, 'XYZ');
640
- const rotation = new Quaternion().setFromEuler(eulerAngles).multiply(worldRotation);
702
+ const rotation = vector3ToQuaternion(new Vector3(rx, ry, rz)).multiply(worldRotation);
641
703
  rigidBody.setRotation({
642
704
  x: rotation.x,
643
705
  y: rotation.y,
@@ -650,12 +712,19 @@ const useRigidBody = (options = {}) => {
650
712
  const autoColliders = colliderSetting !== false ? createCollidersFromChildren(ref.current, rigidBody, _objectSpread2(_objectSpread2({}, options), {}, {
651
713
  colliders: colliderSetting
652
714
  }), world) : [];
653
- rigidBodyMeshes.set(rigidBody.handle, ref.current);
715
+ rigidBodyStates.set(rigidBody.handle, {
716
+ mesh: ref.current,
717
+ invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
718
+ isSleeping: false,
719
+ worldScale: ref.current.getWorldScale(_vector3).clone(),
720
+ setMatrix: mat => ref.current.matrix.copy(mat)
721
+ });
722
+ ref.current.matrixAutoUpdate = false;
654
723
  return () => {
655
724
  world.removeRigidBody(rigidBody);
656
725
  autoColliders.forEach(collider => world.removeCollider(collider));
657
726
  rigidBodyRef.current = undefined;
658
- rigidBodyMeshes.delete(rigidBody.handle);
727
+ rigidBodyStates.delete(rigidBody.handle);
659
728
  };
660
729
  }, []); // Events
661
730
 
@@ -673,29 +742,6 @@ const useRigidBody = (options = {}) => {
673
742
  }, [options.onCollisionEnter, options.onCollisionExit]);
674
743
  const api = useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
675
744
  return [ref, api];
676
- };
677
- const useCollider = (body, options = {}) => {
678
- const {
679
- world
680
- } = useRapier();
681
- const colliderRef = useRef();
682
- const objectRef = useRef();
683
- const getColliderRef = useRef(() => {
684
- if (!colliderRef.current) {
685
- colliderRef.current = createColliderFromOptions(options, world, world.getRigidBody(body.handle));
686
- }
687
-
688
- return colliderRef.current;
689
- });
690
- useEffect(() => {
691
- const collider = getColliderRef.current();
692
- return () => {
693
- if (collider) world.removeCollider(collider);
694
- colliderRef.current = undefined;
695
- };
696
- }, []);
697
- const api = useMemo(() => createColliderApi(getColliderRef), []);
698
- return [objectRef, api];
699
745
  }; // Joints
700
746
 
701
747
  const useImpulseJoint = (body1, body2, params) => {
@@ -708,7 +754,7 @@ const useImpulseJoint = (body1, body2, params) => {
708
754
  let rb1;
709
755
  let rb2;
710
756
 
711
- if ('current' in body1 && body1.current && 'current' in body2 && body2.current) {
757
+ if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
712
758
  rb1 = world.getRigidBody(body1.current.handle);
713
759
  rb2 = world.getRigidBody(body2.current.handle);
714
760
  const newJoint = world.createImpulseJoint(params, rb1, rb2);
@@ -785,84 +831,30 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
785
831
  return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
786
832
  };
787
833
 
788
- function _extends() {
789
- _extends = Object.assign || function (target) {
790
- for (var i = 1; i < arguments.length; i++) {
791
- var source = arguments[i];
792
-
793
- for (var key in source) {
794
- if (Object.prototype.hasOwnProperty.call(source, key)) {
795
- target[key] = source[key];
796
- }
797
- }
798
- }
799
-
800
- return target;
801
- };
802
-
803
- return _extends.apply(this, arguments);
804
- }
805
-
806
- function _objectWithoutPropertiesLoose(source, excluded) {
807
- if (source == null) return {};
808
- var target = {};
809
- var sourceKeys = Object.keys(source);
810
- var key, i;
811
-
812
- for (i = 0; i < sourceKeys.length; i++) {
813
- key = sourceKeys[i];
814
- if (excluded.indexOf(key) >= 0) continue;
815
- target[key] = source[key];
816
- }
817
-
818
- return target;
819
- }
820
-
821
- function _objectWithoutProperties(source, excluded) {
822
- if (source == null) return {};
823
- var target = _objectWithoutPropertiesLoose(source, excluded);
824
- var key, i;
825
-
826
- if (Object.getOwnPropertySymbols) {
827
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
828
-
829
- for (i = 0; i < sourceSymbolKeys.length; i++) {
830
- key = sourceSymbolKeys[i];
831
- if (excluded.indexOf(key) >= 0) continue;
832
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
833
- target[key] = source[key];
834
- }
835
- }
836
-
837
- return target;
838
- }
839
-
840
- const _excluded = ["children"],
841
- _excluded2 = ["children"];
834
+ const _excluded$1 = ["children"];
842
835
  const RigidBodyContext = /*#__PURE__*/createContext(undefined);
843
-
844
836
  const useRigidBodyContext = () => useContext(RigidBodyContext); // RigidBody
845
837
 
846
-
847
838
  const RigidBody = /*#__PURE__*/forwardRef((_ref, ref) => {
848
839
  let {
849
840
  children
850
841
  } = _ref,
851
- props = _objectWithoutProperties(_ref, _excluded);
842
+ props = _objectWithoutProperties(_ref, _excluded$1);
852
843
 
853
844
  const [object, api] = useRigidBody(props);
854
845
  useImperativeHandle(ref, () => api);
855
- return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
846
+ return /*#__PURE__*/React$1.createElement(RigidBodyContext.Provider, {
856
847
  value: {
857
848
  ref: object,
858
849
  api,
859
850
  hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
860
851
  options: props
861
852
  }
862
- }, /*#__PURE__*/React.createElement("object3D", {
853
+ }, /*#__PURE__*/React$1.createElement("object3D", {
863
854
  ref: object
864
855
  }, children));
865
856
  });
857
+
866
858
  const MeshCollider = ({
867
859
  children,
868
860
  type
@@ -880,9 +872,9 @@ const MeshCollider = ({
880
872
  let autoColliders = [];
881
873
 
882
874
  if (object.current) {
883
- var _ref2;
875
+ var _ref;
884
876
 
885
- const colliderSetting = (_ref2 = type !== null && type !== void 0 ? type : physicsOptions.colliders) !== null && _ref2 !== void 0 ? _ref2 : false;
877
+ const colliderSetting = (_ref = type !== null && type !== void 0 ? type : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
886
878
  autoColliders = colliderSetting !== false ? createCollidersFromChildren(object.current, api, _objectSpread2(_objectSpread2({}, options), {}, {
887
879
  colliders: colliderSetting
888
880
  }), world, false) : [];
@@ -900,83 +892,6 @@ const MeshCollider = ({
900
892
  r3RapierType: "MeshCollider"
901
893
  }
902
894
  }, children);
903
- }; // Colliders
904
-
905
- const AnyCollider = _ref3 => {
906
- let {
907
- children
908
- } = _ref3,
909
- props = _objectWithoutProperties(_ref3, _excluded2);
910
-
911
- const {
912
- world
913
- } = useRapier();
914
- const rigidBodyContext = useRigidBodyContext();
915
- const ref = useRef(null);
916
- useEffect(() => {
917
- var _rigidBodyContext$api;
918
-
919
- const scale = ref.current.getWorldScale(new Vector3());
920
- const collider = createColliderFromOptions({
921
- options: props,
922
- world,
923
- rigidBody: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : (_rigidBodyContext$api = rigidBodyContext.api) === null || _rigidBodyContext$api === void 0 ? void 0 : _rigidBodyContext$api.raw(),
924
- scale,
925
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
926
- });
927
- return () => {
928
- world.removeCollider(collider);
929
- };
930
- }, []);
931
- return /*#__PURE__*/React.createElement("object3D", {
932
- ref: ref
933
- }, children);
934
- };
935
-
936
- const CuboidCollider = props => {
937
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
938
- shape: "cuboid"
939
- }));
940
- };
941
- const RoundCuboidCollider = props => {
942
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
943
- shape: "roundCuboid"
944
- }));
945
- };
946
- const BallCollider = props => {
947
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
948
- shape: "ball"
949
- }));
950
- };
951
- const CapsuleCollider = props => {
952
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
953
- shape: "capsule"
954
- }));
955
- };
956
- const HeightfieldCollider = props => {
957
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
958
- shape: "heightfield"
959
- }));
960
- };
961
- const TrimeshCollider = props => {
962
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
963
- shape: "trimesh"
964
- }));
965
- };
966
- const ConeCollider = props => {
967
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
968
- shape: "cone"
969
- }));
970
- };
971
- const CylinderCollider = props => {
972
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
973
- shape: "cylinder"
974
- }));
975
- };
976
- const ConvexHullCollider = props => {
977
- return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
978
- shape: "convexHull"
979
- }));
980
895
  };
981
896
 
982
897
  const geometryFromCollider = collider => {
@@ -1064,12 +979,12 @@ const DebugShape = /*#__PURE__*/memo(({
1064
979
  const collider = world.getCollider(colliderHandle);
1065
980
  return geometryFromCollider(collider);
1066
981
  }, [colliderHandle]);
1067
- return /*#__PURE__*/React.createElement("mesh", {
982
+ return /*#__PURE__*/React$1.createElement("mesh", {
1068
983
  ref: ref
1069
- }, /*#__PURE__*/React.createElement("primitive", {
984
+ }, /*#__PURE__*/React$1.createElement("primitive", {
1070
985
  object: geometry,
1071
986
  attach: "geometry"
1072
- }), /*#__PURE__*/React.createElement("meshBasicMaterial", {
987
+ }), /*#__PURE__*/React$1.createElement("meshBasicMaterial", {
1073
988
  color: "red",
1074
989
  wireframe: true
1075
990
  }));
@@ -1088,10 +1003,204 @@ const Debug = () => {
1088
1003
  });
1089
1004
  setColliders(newColliders);
1090
1005
  });
1091
- return /*#__PURE__*/React.createElement("group", null, colliders.map(handle => /*#__PURE__*/React.createElement(DebugShape, {
1006
+ return /*#__PURE__*/React$1.createElement("group", null, colliders.map(handle => /*#__PURE__*/React$1.createElement(DebugShape, {
1092
1007
  key: handle,
1093
1008
  colliderHandle: handle
1094
1009
  })));
1095
1010
  };
1096
1011
 
1097
- export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, useCollider, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useSphericalJoint };
1012
+ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1013
+ const {
1014
+ world,
1015
+ rigidBodyStates,
1016
+ physicsOptions
1017
+ } = useRapier();
1018
+ const object = useRef(null);
1019
+ const instancesRef = useRef();
1020
+ const instancesRefGetter = useRef(() => {
1021
+ if (!instancesRef.current) {
1022
+ instancesRef.current = [];
1023
+ }
1024
+
1025
+ return instancesRef.current;
1026
+ });
1027
+ useEffect(() => {
1028
+ const colliders = [];
1029
+ const rigidBodies = instancesRefGetter.current();
1030
+
1031
+ if (object.current) {
1032
+ const scale = object.current.getWorldScale(new Vector3());
1033
+ let hasOneMesh = false;
1034
+ object.current.traverse(mesh => {
1035
+ if (mesh instanceof InstancedMesh) {
1036
+ if (hasOneMesh) {
1037
+ console.warn("Can only use a single InstancedMesh inside <InstancedRigidBodies />, more InstancedMeshes will be ignored.");
1038
+ return;
1039
+ }
1040
+
1041
+ hasOneMesh = true;
1042
+ mesh.instanceMatrix.setUsage(DynamicDrawUsage);
1043
+ const rigidBodyDesc = rigidBodyDescFromOptions(props);
1044
+ const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders || physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1045
+ );
1046
+
1047
+ for (let index = 0; index < mesh.count; index++) {
1048
+ const rigidBody = world.createRigidBody(rigidBodyDesc);
1049
+ const matrix = new Matrix4();
1050
+ mesh.getMatrixAt(index, matrix);
1051
+ const {
1052
+ position,
1053
+ rotation
1054
+ } = decomposeMatrix4(matrix); // Set positions
1055
+
1056
+ if (props.positions && props.positions[index]) {
1057
+ rigidBody.setTranslation(vectorArrayToObject(props.positions[index]), true);
1058
+ } else {
1059
+ rigidBody.setTranslation(position, true);
1060
+ } // Set rotations
1061
+
1062
+
1063
+ if (props.rotations && props.rotations[index]) {
1064
+ const [x, y, z] = props.rotations[index];
1065
+ rigidBody.setRotation(vector3ToQuaternion(new Vector3(x, y, z)), true);
1066
+ } else {
1067
+ rigidBody.setRotation(rotation, true);
1068
+ }
1069
+
1070
+ const collider = world.createCollider(colliderDesc, rigidBody);
1071
+ rigidBodyStates.set(rigidBody.handle, {
1072
+ mesh: mesh,
1073
+ isSleeping: false,
1074
+ invertedMatrixWorld: object.current.matrixWorld.clone().invert(),
1075
+ setMatrix: matrix => mesh.setMatrixAt(index, matrix),
1076
+ worldScale: object.current.getWorldScale(new Vector3())
1077
+ });
1078
+ const api = createRigidBodyApi({
1079
+ current() {
1080
+ return rigidBody;
1081
+ }
1082
+
1083
+ });
1084
+ colliders.push(collider);
1085
+ rigidBodies.push({
1086
+ rigidBody,
1087
+ api
1088
+ });
1089
+ }
1090
+ }
1091
+
1092
+ if (mesh.type === "Mesh" && !("isInstancedMesh" in mesh)) {
1093
+ console.warn("Can only use InstancedMesh inside <InstancedRigidBodies />, Mesh will be ignored.");
1094
+ }
1095
+ });
1096
+ return () => {
1097
+ rigidBodies.forEach(rb => world.removeRigidBody(rb.rigidBody));
1098
+ colliders.forEach(coll => world.removeCollider(coll));
1099
+ instancesRef.current = undefined;
1100
+ };
1101
+ }
1102
+ }, []);
1103
+ useImperativeHandle(ref, () => createInstancedRigidBodiesApi(instancesRefGetter));
1104
+ return /*#__PURE__*/React.createElement("object3D", {
1105
+ ref: object
1106
+ }, props.children);
1107
+ });
1108
+
1109
+ function _extends() {
1110
+ _extends = Object.assign || function (target) {
1111
+ for (var i = 1; i < arguments.length; i++) {
1112
+ var source = arguments[i];
1113
+
1114
+ for (var key in source) {
1115
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1116
+ target[key] = source[key];
1117
+ }
1118
+ }
1119
+ }
1120
+
1121
+ return target;
1122
+ };
1123
+
1124
+ return _extends.apply(this, arguments);
1125
+ }
1126
+
1127
+ const _excluded = ["children"];
1128
+
1129
+ const AnyCollider = _ref => {
1130
+ let {
1131
+ children
1132
+ } = _ref,
1133
+ props = _objectWithoutProperties(_ref, _excluded);
1134
+
1135
+ const {
1136
+ world
1137
+ } = useRapier();
1138
+ const rigidBodyContext = useRigidBodyContext();
1139
+ const ref = useRef(null);
1140
+ useEffect(() => {
1141
+ var _rigidBodyContext$api;
1142
+
1143
+ const scale = ref.current.getWorldScale(new Vector3());
1144
+ const collider = createColliderFromOptions({
1145
+ options: props,
1146
+ world,
1147
+ rigidBody: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : (_rigidBodyContext$api = rigidBodyContext.api) === null || _rigidBodyContext$api === void 0 ? void 0 : _rigidBodyContext$api.raw(),
1148
+ scale,
1149
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1150
+ });
1151
+ return () => {
1152
+ world.removeCollider(collider);
1153
+ };
1154
+ }, []);
1155
+ return /*#__PURE__*/React.createElement("object3D", {
1156
+ ref: ref
1157
+ }, children);
1158
+ };
1159
+
1160
+ const CuboidCollider = props => {
1161
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1162
+ shape: "cuboid"
1163
+ }));
1164
+ };
1165
+ const RoundCuboidCollider = props => {
1166
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1167
+ shape: "roundCuboid"
1168
+ }));
1169
+ };
1170
+ const BallCollider = props => {
1171
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1172
+ shape: "ball"
1173
+ }));
1174
+ };
1175
+ const CapsuleCollider = props => {
1176
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1177
+ shape: "capsule"
1178
+ }));
1179
+ };
1180
+ const HeightfieldCollider = props => {
1181
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1182
+ shape: "heightfield"
1183
+ }));
1184
+ };
1185
+ const TrimeshCollider = props => {
1186
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1187
+ shape: "trimesh"
1188
+ }));
1189
+ };
1190
+ const ConeCollider = props => {
1191
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1192
+ shape: "cone"
1193
+ }));
1194
+ };
1195
+ const CylinderCollider = props => {
1196
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1197
+ shape: "cylinder"
1198
+ }));
1199
+ };
1200
+ const ConvexHullCollider = props => {
1201
+ return /*#__PURE__*/React.createElement(AnyCollider, _extends({}, props, {
1202
+ shape: "convexHull"
1203
+ }));
1204
+ };
1205
+
1206
+ export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useSphericalJoint };