@react-three/rapier 0.6.8 → 0.7.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.
@@ -7,7 +7,7 @@ var React = require('react');
7
7
  var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
- var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
10
+ var MathUtils = require('three/src/math/MathUtils');
11
11
  var threeStdlib = require('three-stdlib');
12
12
 
13
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -33,23 +33,23 @@ function _interopNamespace(e) {
33
33
  var React__default = /*#__PURE__*/_interopDefault(React);
34
34
 
35
35
  const _quaternion = new three.Quaternion();
36
- const _euler = new three.Euler();
36
+ new three.Euler();
37
37
  const _vector3 = new three.Vector3();
38
- new three.Object3D();
38
+ const _object3d = new three.Object3D();
39
39
  const _matrix4 = new three.Matrix4();
40
+ const _position = new three.Vector3();
41
+ const _rotation = new three.Quaternion();
42
+ const _scale = new three.Vector3();
40
43
 
41
44
  const vectorArrayToVector3 = arr => {
42
45
  const [x, y, z] = arr;
43
46
  return new three.Vector3(x, y, z);
44
47
  };
45
- const vector3ToQuaternion = v => {
46
- return _quaternion.setFromEuler(_euler.setFromVector3(v));
47
- };
48
48
  const rapierVector3ToVector3 = ({
49
49
  x,
50
50
  y,
51
51
  z
52
- }) => _vector3.set(x, y, z).clone();
52
+ }) => _vector3.set(x, y, z);
53
53
  const rapierQuaternionToQuaternion = ({
54
54
  x,
55
55
  y,
@@ -63,208 +63,6 @@ const rigidBodyTypeMap = {
63
63
  kinematicVelocity: 3
64
64
  };
65
65
  const rigidBodyTypeFromString = type => rigidBodyTypeMap[type];
66
- const decomposeMatrix4 = m => {
67
- const position = new three.Vector3();
68
- const rotation = new three.Quaternion();
69
- const scale = new three.Vector3();
70
- m.decompose(position, rotation, scale);
71
- return {
72
- position,
73
- rotation,
74
- scale
75
- };
76
- };
77
- const scaleColliderArgs = (shape, args, scale) => {
78
- const newArgs = args.slice(); // Heightfield uses a vector
79
-
80
- if (shape === "heightfield") {
81
- const s = newArgs[3];
82
- s.x *= scale.x;
83
- s.x *= scale.y;
84
- s.x *= scale.z;
85
- return newArgs;
86
- } // Trimesh and convex scale the vertices
87
-
88
-
89
- if (shape === "trimesh" || shape === "convexHull") {
90
- newArgs[0] = scaleVertices(newArgs[0], scale);
91
- return newArgs;
92
- } // Prepfill with some extra
93
-
94
-
95
- const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
96
- return newArgs.map((arg, index) => scaleArray[index] * arg);
97
- };
98
- const createColliderFromOptions = ({
99
- options,
100
- world,
101
- rigidBody,
102
- scale,
103
- hasCollisionEvents
104
- }) => {
105
- var _options$shape, _options$args, _options$restitution, _options$restitutionC, _options$friction, _options$frictionComb;
106
-
107
- const mass = (options === null || options === void 0 ? void 0 : options.mass) || 1;
108
- const colliderShape = (_options$shape = options === null || options === void 0 ? void 0 : options.shape) !== null && _options$shape !== void 0 ? _options$shape : "cuboid";
109
- const colliderArgs = (_options$args = options === null || options === void 0 ? void 0 : options.args) !== null && _options$args !== void 0 ? _options$args : [];
110
- const [cmx, cmy, cmz] = (options === null || options === void 0 ? void 0 : options.centerOfMass) || [0, 0, 0];
111
- const [pix, piy, piz] = (options === null || options === void 0 ? void 0 : options.principalAngularInertia) || [mass * 0.2, mass * 0.2, mass * 0.2];
112
- const [x, y, z] = (options === null || options === void 0 ? void 0 : options.position) || [0, 0, 0];
113
- const [rx, ry, rz] = (options === null || options === void 0 ? void 0 : options.rotation) || [0, 0, 0];
114
- const qRotation = vector3ToQuaternion(new three.Vector3(rx, ry, rz)); // @ts-ignore
115
-
116
- const scaledArgs = scaleColliderArgs(options.shape, colliderArgs, scale);
117
- let colliderDesc = rapier3dCompat.ColliderDesc[colliderShape]( // @ts-ignore
118
- ...scaledArgs).setTranslation(x * scale.x, y * scale.y, z * scale.z).setRotation({
119
- x: qRotation.x,
120
- y: qRotation.y,
121
- z: qRotation.z,
122
- w: qRotation.w
123
- }).setRestitution((_options$restitution = options === null || options === void 0 ? void 0 : options.restitution) !== null && _options$restitution !== void 0 ? _options$restitution : 0).setRestitutionCombineRule((_options$restitutionC = options === null || options === void 0 ? void 0 : options.restitutionCombineRule) !== null && _options$restitutionC !== void 0 ? _options$restitutionC : rapier3dCompat.CoefficientCombineRule.Average).setFriction((_options$friction = options === null || options === void 0 ? void 0 : options.friction) !== null && _options$friction !== void 0 ? _options$friction : 0.7).setFrictionCombineRule((_options$frictionComb = options === null || options === void 0 ? void 0 : options.frictionCombineRule) !== null && _options$frictionComb !== void 0 ? _options$frictionComb : rapier3dCompat.CoefficientCombineRule.Average);
124
-
125
- if (hasCollisionEvents) {
126
- colliderDesc = colliderDesc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
127
- } // If any of the mass properties are specified, add mass properties
128
-
129
-
130
- const qMassRot = vector3ToQuaternion(new three.Vector3(0, 0, 0));
131
-
132
- if (options !== null && options !== void 0 && options.mass || options !== null && options !== void 0 && options.centerOfMass || options !== null && options !== void 0 && options.principalAngularInertia) {
133
- colliderDesc.setDensity(0);
134
- colliderDesc.setMassProperties(mass, {
135
- x: cmx,
136
- y: cmy,
137
- z: cmz
138
- }, {
139
- x: pix,
140
- y: piy,
141
- z: piz
142
- }, {
143
- x: qMassRot.x,
144
- y: qMassRot.y,
145
- z: qMassRot.z,
146
- w: qMassRot.w
147
- });
148
- }
149
-
150
- const collider = world.createCollider(colliderDesc, rigidBody);
151
- return collider;
152
- };
153
-
154
- const isChildOfMeshCollider = child => {
155
- let flag = false;
156
- child.traverseAncestors(a => {
157
- if (a.userData.r3RapierType === "MeshCollider") flag = true;
158
- });
159
- return flag;
160
- };
161
-
162
- const createCollidersFromChildren = ({
163
- object,
164
- rigidBody,
165
- options,
166
- world,
167
- ignoreMeshColliders: _ignoreMeshColliders = true
168
- }) => {
169
- const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
170
- const colliders = [];
171
- object.traverseVisible(child => {
172
- if ("isMesh" in child) {
173
- if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
174
- const {
175
- geometry
176
- } = child;
177
- const {
178
- x,
179
- y,
180
- z
181
- } = child.position;
182
- const {
183
- x: rx,
184
- y: ry,
185
- z: rz,
186
- w: rw
187
- } = new three.Quaternion().setFromEuler(child.rotation);
188
- const scale = child.getWorldScale(new three.Vector3()); // We translate the colliders based on the parent's world scale
189
-
190
- const parentWorldScale = child.parent.getWorldScale(new three.Vector3());
191
- const desc = colliderDescFromGeometry(geometry, options.colliders, scale, hasCollisionEvents);
192
- const offset = new three.Vector3(0, 0, 0);
193
-
194
- if (options.colliders === "cuboid") {
195
- var _geometry$boundingBox;
196
-
197
- geometry.computeBoundingBox();
198
- (_geometry$boundingBox = geometry.boundingBox) === null || _geometry$boundingBox === void 0 ? void 0 : _geometry$boundingBox.getCenter(offset);
199
- }
200
-
201
- if (options.colliders === "ball") {
202
- geometry.computeBoundingSphere();
203
- offset.copy(geometry.boundingSphere.center);
204
- }
205
-
206
- if (Number.isFinite(options.friction)) desc.setFriction(options.friction);
207
- if (Number.isFinite(options.restitution)) desc.setRestitution(options.restitution);
208
- desc.setTranslation((x + offset.x) * parentWorldScale.x, (y + offset.y) * parentWorldScale.y, (z + offset.z) * parentWorldScale.z).setRotation({
209
- x: rx,
210
- y: ry,
211
- z: rz,
212
- w: rw
213
- });
214
- const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
215
- const collider = world.createCollider(desc, actualRigidBody);
216
- colliders.push(collider);
217
- }
218
- });
219
- return colliders;
220
- };
221
- const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents) => {
222
- let desc;
223
-
224
- switch (colliders) {
225
- case "cuboid":
226
- {
227
- geometry.computeBoundingBox();
228
- const {
229
- boundingBox
230
- } = geometry;
231
- const size = boundingBox.getSize(new three.Vector3());
232
- desc = rapier3dCompat.ColliderDesc.cuboid(size.x / 2 * scale.x, size.y / 2 * scale.y, size.z / 2 * scale.z);
233
- }
234
- break;
235
-
236
- case "ball":
237
- {
238
- geometry.computeBoundingSphere();
239
- const {
240
- boundingSphere
241
- } = geometry;
242
- const radius = boundingSphere.radius * scale.x;
243
- desc = rapier3dCompat.ColliderDesc.ball(radius);
244
- }
245
- break;
246
-
247
- case "trimesh":
248
- {
249
- var _g$index;
250
-
251
- const clonedGeometry = geometry.index ? geometry.clone() : BufferGeometryUtils.mergeVertices(geometry);
252
- const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
253
- desc = rapier3dCompat.ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
254
- }
255
- break;
256
-
257
- case "hull":
258
- {
259
- const g = geometry.clone().scale(scale.x, scale.y, scale.z);
260
- desc = rapier3dCompat.ColliderDesc.convexHull(g.attributes.position.array);
261
- }
262
- break;
263
- }
264
-
265
- if (hasCollisionEvents) desc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
266
- return desc;
267
- };
268
66
  const scaleVertices = (vertices, scale) => {
269
67
  const scaledVerts = Array.from(vertices);
270
68
 
@@ -276,28 +74,6 @@ const scaleVertices = (vertices, scale) => {
276
74
 
277
75
  return scaledVerts;
278
76
  };
279
- const rigidBodyDescFromOptions = options => {
280
- var _options$linearVeloci, _options$angularVeloc, _options$angularDampi, _options$linearDampin, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
281
-
282
- const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
283
- 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];
284
- 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];
285
- const angularDamping = (_options$angularDampi = options === null || options === void 0 ? void 0 : options.angularDamping) !== null && _options$angularDampi !== void 0 ? _options$angularDampi : 0;
286
- const linearDamping = (_options$linearDampin = options === null || options === void 0 ? void 0 : options.linearDamping) !== null && _options$linearDampin !== void 0 ? _options$linearDampin : 0;
287
- const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
288
- const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
289
- const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
290
- 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];
291
- 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];
292
- const desc = new rapier3dCompat.RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
293
- x: avx,
294
- y: avy,
295
- z: avz
296
- }).setLinearDamping(linearDamping).setAngularDamping(angularDamping).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
297
- if (options.lockRotations) desc.lockRotations();
298
- if (options.lockTranslations) desc.lockTranslations();
299
- return desc;
300
- };
301
77
 
302
78
  const createRigidBodyApi = ref => {
303
79
  return {
@@ -449,8 +225,8 @@ const Physics = ({
449
225
  gravity: _gravity = [0, -9.81, 0],
450
226
  children,
451
227
  timeStep: _timeStep = 1 / 60,
452
- maxSubSteps: _maxSubSteps = 10,
453
- paused: _paused = false
228
+ paused: _paused = false,
229
+ updatePriority
454
230
  }) => {
455
231
  const rapier = useAsset.useAsset(importRapier);
456
232
  const [isPaused, setIsPaused] = React.useState(_paused);
@@ -467,7 +243,9 @@ const Physics = ({
467
243
  return worldRef.current;
468
244
  });
469
245
  const [rigidBodyStates] = React.useState(() => new Map());
246
+ const [colliderStates] = React.useState(() => new Map());
470
247
  const [rigidBodyEvents] = React.useState(() => new Map());
248
+ const [colliderEvents] = React.useState(() => new Map());
471
249
  const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
472
250
 
473
251
  React.useEffect(() => {
@@ -487,45 +265,29 @@ const Physics = ({
487
265
  }
488
266
  }, [_gravity]);
489
267
  const [steppingState] = React.useState({
490
- time: 0,
491
- lastTime: 0,
492
268
  accumulator: 0
493
269
  });
494
- fiber.useFrame((_, delta) => {
270
+ fiber.useFrame((_, dt) => {
495
271
  const world = worldRef.current;
496
272
  if (!world) return;
497
273
  world.timestep = _timeStep;
498
274
  /**
499
275
  * Fixed timeStep simulation progression
500
- * @see https://gafferongames.com/post/fix_your_timestep/
276
+ * @see https://gafferongames.com/post/fix_your_timestep/
501
277
  */
278
+ // don't step time forwards if paused
279
+ // Increase accumulator
502
280
 
503
- let previousTranslations = {}; // don't step time forwards if paused
504
-
505
- const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
506
- const timeStepMs = _timeStep * 1000;
507
- const timeSinceLast = nowTime - steppingState.lastTime;
508
- steppingState.lastTime = nowTime;
509
- steppingState.accumulator += timeSinceLast;
281
+ steppingState.accumulator += _paused ? 0 : MathUtils.clamp(dt, 0, 0.2);
510
282
 
511
283
  if (!_paused) {
512
- let subSteps = 0;
513
-
514
- while (steppingState.accumulator >= timeStepMs && subSteps < _maxSubSteps) {
515
- // Collect previous state
516
- world.bodies.forEach(b => {
517
- previousTranslations[b.handle] = {
518
- rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
519
- translation: rapierVector3ToVector3(b.translation())
520
- };
521
- });
284
+ while (steppingState.accumulator >= _timeStep) {
522
285
  world.step(eventQueue);
523
- subSteps++;
524
- steppingState.accumulator -= timeStepMs;
286
+ steppingState.accumulator -= _timeStep;
525
287
  }
526
288
  }
527
289
 
528
- const interpolationAlpha = steppingState.accumulator % timeStepMs / timeStepMs; // Update meshes
290
+ const interpolationAlpha = steppingState.accumulator % _timeStep / _timeStep; // Update meshes
529
291
 
530
292
  rigidBodyStates.forEach((state, handle) => {
531
293
  const rigidBody = world.getRigidBody(handle);
@@ -551,62 +313,156 @@ const Physics = ({
551
313
  return;
552
314
  }
553
315
 
554
- let oldState = previousTranslations[rigidBody.handle];
555
- let newTranslation = rapierVector3ToVector3(rigidBody.translation());
556
- let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
557
- let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
558
- let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
559
- state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
316
+ let t = rigidBody.translation();
317
+ let r = rigidBody.rotation(); // Get new position
560
318
 
561
- if (state.mesh instanceof three.InstancedMesh) {
562
- state.mesh.instanceMatrix.needsUpdate = true;
563
- }
564
- }); // Collision events
319
+ _matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
565
320
 
321
+ if (state.object instanceof three.InstancedMesh) {
322
+ state.setMatrix(_matrix4);
323
+ state.object.instanceMatrix.needsUpdate = true;
324
+ } else {
325
+ // Interpolate from last position
326
+ state.object.position.lerp(_position, interpolationAlpha);
327
+ state.object.quaternion.slerp(_rotation, interpolationAlpha);
328
+ }
329
+ });
566
330
  eventQueue.drainCollisionEvents((handle1, handle2, started) => {
567
331
  var _collider1$parent, _collider2$parent;
568
332
 
569
333
  const collider1 = world.getCollider(handle1);
570
334
  const collider2 = world.getCollider(handle2);
571
335
  const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
572
- const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
336
+ const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle; // Collision Events
573
337
 
574
- if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
338
+ if (!collider1 || !collider2) {
575
339
  return;
576
340
  }
577
341
 
578
- const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
579
- const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
580
- const events1 = rigidBodyEvents.get(rigidBodyHandle1);
581
- const events2 = rigidBodyEvents.get(rigidBodyHandle2);
342
+ const collider1Events = colliderEvents.get(collider1.handle);
343
+ const collider2Events = colliderEvents.get(collider2.handle);
344
+ const rigidBody1 = rigidBodyHandle1 ? world.getRigidBody(rigidBodyHandle1) : undefined;
345
+ const rigidBody2 = rigidBodyHandle2 ? world.getRigidBody(rigidBodyHandle2) : undefined;
346
+ const rigidBody1Events = rigidBodyHandle1 ? rigidBodyEvents.get(rigidBodyHandle1) : undefined;
347
+ const rigidBody2Events = rigidBodyHandle2 ? rigidBodyEvents.get(rigidBodyHandle2) : undefined;
348
+ const collider1State = colliderStates.get(collider1.handle);
349
+ const collider2State = colliderStates.get(collider2.handle);
350
+ const rigidBody1State = rigidBodyHandle1 ? rigidBodyStates.get(rigidBodyHandle1) : undefined;
351
+ const rigidBody2State = rigidBodyHandle2 ? rigidBodyStates.get(rigidBodyHandle2) : undefined;
582
352
 
583
353
  if (started) {
584
354
  world.contactPair(collider1, collider2, (manifold, flipped) => {
585
- var _events1$onCollisionE, _events2$onCollisionE;
355
+ var _rigidBody1Events$onC, _rigidBody2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
356
+
357
+ /* RigidBody events */
358
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
359
+ rigidBody: rigidBody2,
360
+ collider: collider2,
361
+ colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
362
+ rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object,
363
+ manifold,
364
+ flipped
365
+ });
366
+ rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onC = rigidBody2Events.onCollisionEnter) === null || _rigidBody2Events$onC === void 0 ? void 0 : _rigidBody2Events$onC.call(rigidBody2Events, {
367
+ rigidBody: rigidBody1,
368
+ collider: collider1,
369
+ colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
370
+ rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object,
371
+ manifold,
372
+ flipped
373
+ });
374
+ /* Collider events */
586
375
 
587
- events1 === null || events1 === void 0 ? void 0 : (_events1$onCollisionE = events1.onCollisionEnter) === null || _events1$onCollisionE === void 0 ? void 0 : _events1$onCollisionE.call(events1, {
588
- target: rigidBody2,
376
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
377
+ rigidBody: rigidBody2,
378
+ collider: collider2,
379
+ colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
380
+ rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object,
589
381
  manifold,
590
382
  flipped
591
383
  });
592
- events2 === null || events2 === void 0 ? void 0 : (_events2$onCollisionE = events2.onCollisionEnter) === null || _events2$onCollisionE === void 0 ? void 0 : _events2$onCollisionE.call(events2, {
593
- target: rigidBody1,
384
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
385
+ rigidBody: rigidBody1,
386
+ collider: collider1,
387
+ colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
388
+ rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object,
594
389
  manifold,
595
390
  flipped
596
391
  });
597
392
  });
598
393
  } else {
599
- var _events1$onCollisionE2, _events2$onCollisionE2;
394
+ var _rigidBody1Events$onC2, _rigidBody2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
600
395
 
601
- events1 === null || events1 === void 0 ? void 0 : (_events1$onCollisionE2 = events1.onCollisionExit) === null || _events1$onCollisionE2 === void 0 ? void 0 : _events1$onCollisionE2.call(events1, {
602
- target: rigidBody2
396
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
397
+ rigidBody: rigidBody2,
398
+ collider: collider2
603
399
  });
604
- events2 === null || events2 === void 0 ? void 0 : (_events2$onCollisionE2 = events2.onCollisionExit) === null || _events2$onCollisionE2 === void 0 ? void 0 : _events2$onCollisionE2.call(events2, {
605
- target: rigidBody1
400
+ rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onC2 = rigidBody2Events.onCollisionExit) === null || _rigidBody2Events$onC2 === void 0 ? void 0 : _rigidBody2Events$onC2.call(rigidBody2Events, {
401
+ rigidBody: rigidBody1,
402
+ collider: collider1
403
+ });
404
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
405
+ rigidBody: rigidBody2,
406
+ collider: collider2
407
+ });
408
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
409
+ rigidBody: rigidBody1,
410
+ collider: collider1
411
+ });
412
+ } // Sensor Intersections
413
+
414
+
415
+ if (started) {
416
+ if (world.intersectionPair(collider1, collider2)) {
417
+ var _rigidBody1Events$onI, _rigidBody2Events$onI, _collider1Events$onIn, _collider2Events$onIn;
418
+
419
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onI = rigidBody1Events.onIntersectionEnter) === null || _rigidBody1Events$onI === void 0 ? void 0 : _rigidBody1Events$onI.call(rigidBody1Events, {
420
+ rigidBody: rigidBody2,
421
+ collider: collider2,
422
+ colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
423
+ rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object
424
+ });
425
+ rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onI = rigidBody2Events.onIntersectionEnter) === null || _rigidBody2Events$onI === void 0 ? void 0 : _rigidBody2Events$onI.call(rigidBody2Events, {
426
+ rigidBody: rigidBody1,
427
+ collider: collider1,
428
+ colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
429
+ rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object
430
+ });
431
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onIn = collider1Events.onIntersectionEnter) === null || _collider1Events$onIn === void 0 ? void 0 : _collider1Events$onIn.call(collider1Events, {
432
+ rigidBody: rigidBody2,
433
+ collider: collider2,
434
+ colliderObject: collider2State === null || collider2State === void 0 ? void 0 : collider2State.object,
435
+ rigidBodyObject: rigidBody2State === null || rigidBody2State === void 0 ? void 0 : rigidBody2State.object
436
+ });
437
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onIn = collider2Events.onIntersectionEnter) === null || _collider2Events$onIn === void 0 ? void 0 : _collider2Events$onIn.call(collider2Events, {
438
+ rigidBody: rigidBody1,
439
+ collider: collider1,
440
+ colliderObject: collider1State === null || collider1State === void 0 ? void 0 : collider1State.object,
441
+ rigidBodyObject: rigidBody1State === null || rigidBody1State === void 0 ? void 0 : rigidBody1State.object
442
+ });
443
+ }
444
+ } else {
445
+ var _rigidBody1Events$onI2, _rigidBody2Events$onI2, _collider1Events$onIn2, _collider2Events$onIn2;
446
+
447
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onI2 = rigidBody1Events.onIntersectionExit) === null || _rigidBody1Events$onI2 === void 0 ? void 0 : _rigidBody1Events$onI2.call(rigidBody1Events, {
448
+ rigidBody: rigidBody2,
449
+ collider: collider2
450
+ });
451
+ rigidBody2Events === null || rigidBody2Events === void 0 ? void 0 : (_rigidBody2Events$onI2 = rigidBody2Events.onIntersectionExit) === null || _rigidBody2Events$onI2 === void 0 ? void 0 : _rigidBody2Events$onI2.call(rigidBody2Events, {
452
+ rigidBody: rigidBody1,
453
+ collider: collider1
454
+ });
455
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onIn2 = collider1Events.onIntersectionExit) === null || _collider1Events$onIn2 === void 0 ? void 0 : _collider1Events$onIn2.call(collider1Events, {
456
+ rigidBody: rigidBody2,
457
+ collider: collider2
458
+ });
459
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onIn2 = collider2Events.onIntersectionExit) === null || _collider2Events$onIn2 === void 0 ? void 0 : _collider2Events$onIn2.call(collider2Events, {
460
+ rigidBody: rigidBody1,
461
+ collider: collider1
606
462
  });
607
463
  }
608
464
  });
609
- });
465
+ }, updatePriority);
610
466
  const api = React.useMemo(() => createWorldApi(getWorldRef), []);
611
467
  const context = React.useMemo(() => ({
612
468
  rapier,
@@ -616,7 +472,9 @@ const Physics = ({
616
472
  gravity: _gravity
617
473
  },
618
474
  rigidBodyStates,
475
+ colliderStates,
619
476
  rigidBodyEvents,
477
+ colliderEvents,
620
478
  isPaused
621
479
  }), [isPaused]);
622
480
  return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
@@ -717,156 +575,455 @@ function _objectSpread2(target) {
717
575
  return target;
718
576
  }
719
577
 
720
- const useRapier = () => {
721
- return React.useContext(RapierContext);
578
+ const rigidBodyDescFromOptions = options => {
579
+ const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
580
+ const desc = new rapier3dCompat.RigidBodyDesc(type);
581
+ return desc;
722
582
  };
723
- const useRigidBody = (options = {}) => {
724
- const {
725
- world,
726
- rigidBodyStates,
727
- physicsOptions,
728
- rigidBodyEvents
729
- } = useRapier();
730
- const ref = React.useRef(); // Create rigidbody
731
-
732
- const rigidBodyRef = React.useRef();
733
- const getRigidBodyRef = React.useRef(() => {
734
- if (!rigidBodyRef.current) {
735
- const desc = rigidBodyDescFromOptions(options);
736
- const rigidBody = world.createRigidBody(desc);
737
- rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
738
- }
739
-
740
- return rigidBodyRef.current;
741
- }); // Setup
742
-
743
- React.useEffect(() => {
744
- var _ref$current$parent, _ref, _options$colliders;
583
+ const createRigidBodyState = ({
584
+ rigidBody,
585
+ object,
586
+ setMatrix,
587
+ getMatrix,
588
+ worldScale
589
+ }) => {
590
+ object.updateWorldMatrix(true, false);
591
+ const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
592
+ return {
593
+ object,
594
+ rigidBody,
595
+ invertedWorldMatrix,
596
+ setMatrix: setMatrix ? setMatrix : matrix => {
597
+ object.matrix.copy(matrix);
598
+ },
599
+ getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
600
+ scale: worldScale || object.getWorldScale(_scale).clone(),
601
+ isSleeping: false
602
+ };
603
+ };
604
+ const mutableRigidBodyOptions = {
605
+ gravityScale: (rb, value) => {
606
+ rb.setGravityScale(value, true);
607
+ },
608
+ linearDamping: (rb, value) => {
609
+ rb.setLinearDamping(value);
610
+ },
611
+ angularDamping: (rb, value) => {
612
+ rb.setAngularDamping(value);
613
+ },
614
+ enabledRotations: (rb, [x, y, z]) => {
615
+ rb.setEnabledRotations(x, y, z, true);
616
+ },
617
+ enabledTranslations: (rb, [x, y, z]) => {
618
+ rb.setEnabledTranslations(x, y, z, true);
619
+ },
620
+ angularVelocity: (rb, [x, y, z]) => {
621
+ rb.setAngvel({
622
+ x,
623
+ y,
624
+ z
625
+ }, true);
626
+ },
627
+ linearVelocity: (rb, [x, y, z]) => {
628
+ rb.setLinvel({
629
+ x,
630
+ y,
631
+ z
632
+ }, true);
633
+ },
634
+ ccd: (rb, value) => {
635
+ rb.enableCcd(value);
636
+ }
637
+ };
638
+ const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
639
+ const setRigidBodyOptions = (rigidBody, options, states) => {
640
+ if (!rigidBody) {
641
+ return;
642
+ }
745
643
 
746
- const rigidBody = getRigidBodyRef.current();
747
- rigidBodyRef.current = rigidBody;
644
+ const state = states.get(rigidBody.handle);
748
645
 
749
- if (!ref.current) {
750
- ref.current = new three.Object3D();
751
- } // isSleeping used for onSleep and onWake events
646
+ if (state) {
647
+ state.object.updateWorldMatrix(true, false);
752
648
 
649
+ _matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
753
650
 
754
- ref.current.userData.isSleeping = false; // Get intitial world transforms
755
-
756
- const worldPosition = ref.current.getWorldPosition(new three.Vector3());
757
- const worldRotation = ref.current.getWorldQuaternion(new three.Quaternion());
758
- const scale = ((_ref$current$parent = ref.current.parent) === null || _ref$current$parent === void 0 ? void 0 : _ref$current$parent.getWorldScale(new three.Vector3())) || {
759
- x: 1,
760
- y: 1,
761
- z: 1
762
- }; // Transforms from options
763
-
764
- const [x, y, z] = (options === null || options === void 0 ? void 0 : options.position) || [0, 0, 0];
765
- const [rx, ry, rz] = (options === null || options === void 0 ? void 0 : options.rotation) || [0, 0, 0]; // Set initial transforms based on world transforms
766
-
767
- rigidBody.setTranslation({
768
- x: worldPosition.x + x * scale.x,
769
- y: worldPosition.y + y * scale.y,
770
- z: worldPosition.z + z * scale.z
771
- }, false);
772
- const rotation = vector3ToQuaternion(new three.Vector3(rx, ry, rz)).multiply(worldRotation);
773
- rigidBody.setRotation({
774
- x: rotation.x,
775
- y: rotation.y,
776
- z: rotation.z,
777
- w: rotation.w
778
- }, false);
779
- rigidBody.resetForces(false);
780
- rigidBody.resetTorques(false);
781
- const colliderSetting = (_ref = (_options$colliders = options === null || options === void 0 ? void 0 : options.colliders) !== null && _options$colliders !== void 0 ? _options$colliders : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
782
- const autoColliders = colliderSetting !== false ? createCollidersFromChildren({
783
- object: ref.current,
784
- rigidBody,
785
- options: _objectSpread2(_objectSpread2({}, options), {}, {
786
- colliders: colliderSetting
787
- }),
788
- world,
789
- ignoreMeshColliders: true
790
- }) : [];
791
- rigidBodyStates.set(rigidBody.handle, {
792
- mesh: ref.current,
793
- invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
794
- isSleeping: false,
795
- worldScale: ref.current.getWorldScale(_vector3).clone(),
796
- setMatrix: mat => ref.current.matrix.copy(mat),
797
- getMatrix: () => ref.current.matrix
651
+ rigidBody.setTranslation(_position, false);
652
+ rigidBody.setRotation(_rotation, false);
653
+ mutableRigidBodyOptionKeys.forEach(key => {
654
+ if (key in options) {
655
+ mutableRigidBodyOptions[key](rigidBody, options[key]);
656
+ }
798
657
  });
799
- ref.current.matrixAutoUpdate = false;
800
- return () => {
801
- world.removeRigidBody(rigidBody);
802
- autoColliders.forEach(collider => world.removeCollider(collider));
803
- rigidBodyRef.current = undefined;
804
- rigidBodyStates.delete(rigidBody.handle);
805
- };
806
- }, []); // Events
807
-
658
+ }
659
+ };
660
+ const useUpdateRigidBodyOptions = (rigidBodyRef, props, states) => {
808
661
  React.useEffect(() => {
809
- const rigidBody = getRigidBodyRef.current();
810
- rigidBodyEvents.set(rigidBody.handle, {
811
- onCollisionEnter: options === null || options === void 0 ? void 0 : options.onCollisionEnter,
812
- onCollisionExit: options === null || options === void 0 ? void 0 : options.onCollisionExit,
813
- onSleep: options === null || options === void 0 ? void 0 : options.onSleep,
814
- onWake: options === null || options === void 0 ? void 0 : options.onWake
815
- });
816
- return () => {
817
- rigidBodyEvents.delete(rigidBody.handle);
818
- };
819
- }, [options.onCollisionEnter, options.onCollisionExit]);
820
- const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
821
- return [ref, api];
822
- }; // Joints
823
-
824
- const useImpulseJoint = (body1, body2, params) => {
662
+ setRigidBodyOptions(rigidBodyRef.current, props, states);
663
+ }, [props]);
664
+ };
665
+ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
825
666
  const {
826
- world
827
- } = useRapier();
828
- const jointRef = React.useRef();
829
- const getJointRef = React.useRef(() => {
830
- if (!jointRef.current) {
831
- let rb1;
832
- let rb2;
833
-
834
- if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
835
- rb1 = world.getRigidBody(body1.current.handle);
836
- rb2 = world.getRigidBody(body2.current.handle);
837
- const newJoint = world.createImpulseJoint(params, rb1, rb2);
838
- jointRef.current = newJoint;
839
- }
840
- }
841
-
842
- return jointRef.current;
843
- });
667
+ onWake,
668
+ onSleep,
669
+ onCollisionEnter,
670
+ onCollisionExit,
671
+ onIntersectionEnter,
672
+ onIntersectionExit
673
+ } = props;
844
674
  React.useEffect(() => {
845
- const joint = getJointRef.current();
675
+ events.set(rigidBodyRef.current.handle, {
676
+ onWake,
677
+ onSleep,
678
+ onCollisionEnter,
679
+ onCollisionExit,
680
+ onIntersectionEnter,
681
+ onIntersectionExit
682
+ });
846
683
  return () => {
847
- if (joint) {
848
- world.removeImpulseJoint(joint);
849
- jointRef.current = undefined;
850
- }
684
+ events.delete(rigidBodyRef.current.handle);
851
685
  };
852
- }, []);
853
- const api = React.useMemo(() => createJointApi(getJointRef), []);
854
- return api;
686
+ }, [onWake, onSleep, onCollisionEnter, onCollisionExit]);
855
687
  };
856
- /**
857
- *
858
- * A fixed joint ensures that two rigid-bodies don't move relative to each other.
859
- * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
860
- * The fixed-joint makes these frames coincide in world-space.
861
- */
862
688
 
863
- const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
864
- const {
865
- rapier
866
- } = useRapier();
867
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
868
- w: 1
869
- }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
689
+ const scaleColliderArgs = (shape, args, scale) => {
690
+ const newArgs = args.slice(); // Heightfield uses a vector
691
+
692
+ if (shape === "heightfield") {
693
+ const s = newArgs[3];
694
+ s.x *= scale.x;
695
+ s.x *= scale.y;
696
+ s.x *= scale.z;
697
+ return newArgs;
698
+ } // Trimesh and convex scale the vertices
699
+
700
+
701
+ if (shape === "trimesh" || shape === "convexHull") {
702
+ newArgs[0] = scaleVertices(newArgs[0], scale);
703
+ return newArgs;
704
+ } // Prepfill with some extra
705
+
706
+
707
+ const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
708
+ return newArgs.map((arg, index) => scaleArray[index] * arg);
709
+ };
710
+ const createColliderFromOptions = (options, world, scale, rigidBody) => {
711
+ const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
712
+
713
+ const desc = rapier3dCompat.ColliderDesc[options.shape](...scaledArgs);
714
+ return world.createCollider(desc, rigidBody);
715
+ };
716
+ const mutableColliderOptions = {
717
+ sensor: (collider, value) => {
718
+ collider.setSensor(value);
719
+ },
720
+ collisionGroups: (collider, value) => {
721
+ collider.setCollisionGroups(value);
722
+ },
723
+ solverGroups: (collider, value) => {
724
+ collider.setSolverGroups(value);
725
+ },
726
+ friction: (collider, value) => {
727
+ collider.setFriction(value);
728
+ },
729
+ restitution: (collider, value) => {
730
+ collider.setRestitution(value);
731
+ },
732
+ density: (collider, value) => {
733
+ collider.setDensity(value);
734
+ },
735
+ mass: (collider, value) => {
736
+ collider.setMass(value);
737
+ }
738
+ };
739
+ const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
740
+ const setColliderOptions = (collider, options, states) => {
741
+ const state = states.get(collider.handle);
742
+
743
+ if (state) {
744
+ // Update collider position based on the object's position
745
+ const parentWorldScale = state.object.parent.getWorldScale(_vector3);
746
+ state.object.updateWorldMatrix(true, false);
747
+
748
+ _matrix4.copy(state.object.matrixWorld).premultiply(state.worldParent.matrixWorld.clone().invert()).decompose(_position, _rotation, _scale);
749
+
750
+ collider.setTranslationWrtParent({
751
+ x: _position.x * parentWorldScale.x,
752
+ y: _position.y * parentWorldScale.y,
753
+ z: _position.z * parentWorldScale.z
754
+ });
755
+ collider.setRotationWrtParent(_rotation);
756
+ mutableColliderOptionKeys.forEach(key => {
757
+ if (key in options) {
758
+ mutableColliderOptions[key](collider, options[key]);
759
+ }
760
+ });
761
+ }
762
+ };
763
+ const useUpdateColliderOptions = (collidersRef, props, states) => {
764
+ React.useEffect(() => {
765
+ collidersRef.current.forEach(collider => {
766
+ setColliderOptions(collider, props, states);
767
+ });
768
+ }, [props]);
769
+ };
770
+
771
+ const isChildOfMeshCollider = child => {
772
+ let flag = false;
773
+ child.traverseAncestors(a => {
774
+ if (a.userData.r3RapierType === "MeshCollider") flag = true;
775
+ });
776
+ return flag;
777
+ };
778
+
779
+ const createColliderState = (collider, object, rigidBodyObject) => {
780
+ return {
781
+ collider,
782
+ worldParent: rigidBodyObject || object.parent,
783
+ object
784
+ };
785
+ };
786
+ const autoColliderMap = {
787
+ cuboid: "cuboid",
788
+ ball: "ball",
789
+ hull: "convexHull",
790
+ trimesh: "trimesh"
791
+ };
792
+ const createColliderPropsFromChildren = ({
793
+ object,
794
+ ignoreMeshColliders: _ignoreMeshColliders = true,
795
+ options
796
+ }) => {
797
+ const colliderProps = [];
798
+ object.updateWorldMatrix(true, false);
799
+ const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
800
+ object.traverseVisible(child => {
801
+ if ("isMesh" in child) {
802
+ if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
803
+ const worldScale = child.getWorldScale(_scale);
804
+ const shape = autoColliderMap[options.colliders || "cuboid"];
805
+ child.updateWorldMatrix(true, false);
806
+
807
+ _matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
808
+
809
+ const rotationEuler = new three.Euler().setFromQuaternion(_rotation, "XYZ");
810
+ const {
811
+ geometry
812
+ } = child;
813
+ const {
814
+ args,
815
+ offset
816
+ } = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
817
+ colliderProps.push(_objectSpread2(_objectSpread2({}, options), {}, {
818
+ args: args,
819
+ shape: shape,
820
+ rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
821
+ position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
822
+ scale: [worldScale.x, worldScale.y, worldScale.z]
823
+ }));
824
+ }
825
+ });
826
+ return colliderProps;
827
+ };
828
+ const getColliderArgsFromGeometry = (geometry, colliders) => {
829
+ switch (colliders) {
830
+ case "cuboid":
831
+ {
832
+ geometry.computeBoundingBox();
833
+ const {
834
+ boundingBox
835
+ } = geometry;
836
+ const size = boundingBox.getSize(new three.Vector3());
837
+ return {
838
+ args: [size.x / 2, size.y / 2, size.z / 2],
839
+ offset: boundingBox.getCenter(new three.Vector3())
840
+ };
841
+ }
842
+
843
+ case "ball":
844
+ {
845
+ geometry.computeBoundingSphere();
846
+ const {
847
+ boundingSphere
848
+ } = geometry;
849
+ const radius = boundingSphere.radius;
850
+ return {
851
+ args: [radius],
852
+ offset: boundingSphere.center
853
+ };
854
+ }
855
+
856
+ case "trimesh":
857
+ {
858
+ var _clonedGeometry$index;
859
+
860
+ const clonedGeometry = geometry.index ? geometry.clone() : threeStdlib.mergeVertices(geometry);
861
+ return {
862
+ args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
863
+ offset: new three.Vector3()
864
+ };
865
+ }
866
+
867
+ case "hull":
868
+ {
869
+ const g = geometry.clone();
870
+ return {
871
+ args: [g.attributes.position.array],
872
+ offset: new three.Vector3()
873
+ };
874
+ }
875
+ }
876
+
877
+ return {
878
+ args: [],
879
+ offset: new three.Vector3()
880
+ };
881
+ };
882
+ const useColliderEvents = (collidersRef, props, events) => {
883
+ const {
884
+ onCollisionEnter,
885
+ onCollisionExit,
886
+ onIntersectionEnter,
887
+ onIntersectionExit
888
+ } = props;
889
+ React.useEffect(() => {
890
+ var _collidersRef$current;
891
+
892
+ (_collidersRef$current = collidersRef.current) === null || _collidersRef$current === void 0 ? void 0 : _collidersRef$current.forEach(collider => {
893
+ if (onCollisionEnter || onCollisionExit || onIntersectionEnter || onIntersectionExit) {
894
+ collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
895
+ }
896
+
897
+ events.set(collider.handle, {
898
+ onCollisionEnter,
899
+ onCollisionExit,
900
+ onIntersectionEnter,
901
+ onIntersectionExit
902
+ });
903
+ });
904
+ return () => {
905
+ var _collidersRef$current2;
906
+
907
+ (_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
908
+ };
909
+ }, [onCollisionEnter, onCollisionExit]);
910
+ };
911
+
912
+ const useRapier = () => {
913
+ return React.useContext(RapierContext);
914
+ };
915
+ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
916
+ const [colliderProps, setColliderProps] = React.useState([]);
917
+ React.useEffect(() => {
918
+ const object = ref.current;
919
+
920
+ if (object && options.colliders !== false) {
921
+ setColliderProps(createColliderPropsFromChildren({
922
+ object: ref.current,
923
+ options,
924
+ ignoreMeshColliders
925
+ }));
926
+ }
927
+ }, [options]);
928
+ return colliderProps;
929
+ };
930
+ const useRigidBody = (options = {}) => {
931
+ const {
932
+ world,
933
+ rigidBodyStates,
934
+ physicsOptions,
935
+ rigidBodyEvents
936
+ } = useRapier();
937
+ const ref = React.useRef();
938
+ const mergedOptions = React.useMemo(() => {
939
+ return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
940
+ children: undefined
941
+ });
942
+ }, [physicsOptions, options]);
943
+ const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
944
+
945
+ const rigidBodyRef = React.useRef();
946
+ const getRigidBodyRef = React.useRef(() => {
947
+ if (!rigidBodyRef.current) {
948
+ const desc = rigidBodyDescFromOptions(options);
949
+ const rigidBody = world.createRigidBody(desc);
950
+ rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
951
+ }
952
+
953
+ return rigidBodyRef.current;
954
+ }); // Setup
955
+
956
+ React.useEffect(() => {
957
+ const rigidBody = getRigidBodyRef.current();
958
+ rigidBodyRef.current = rigidBody;
959
+
960
+ if (!ref.current) {
961
+ ref.current = new three.Object3D();
962
+ } // isSleeping used for onSleep and onWake events
963
+
964
+
965
+ ref.current.userData.isSleeping = false;
966
+ rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
967
+ rigidBody,
968
+ object: ref.current
969
+ }));
970
+ return () => {
971
+ world.removeRigidBody(rigidBody);
972
+ rigidBodyStates.delete(rigidBody.handle);
973
+ };
974
+ }, []);
975
+ useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
976
+ useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
977
+ const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
978
+ return [ref, api, childColliderProps];
979
+ }; // Joints
980
+
981
+ const useImpulseJoint = (body1, body2, params) => {
982
+ const {
983
+ world
984
+ } = useRapier();
985
+ const jointRef = React.useRef();
986
+ const getJointRef = React.useRef(() => {
987
+ if (!jointRef.current) {
988
+ let rb1;
989
+ let rb2;
990
+
991
+ if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
992
+ rb1 = world.getRigidBody(body1.current.handle);
993
+ rb2 = world.getRigidBody(body2.current.handle);
994
+ const newJoint = world.createImpulseJoint(params, rb1, rb2);
995
+ jointRef.current = newJoint;
996
+ }
997
+ }
998
+
999
+ return jointRef.current;
1000
+ });
1001
+ React.useEffect(() => {
1002
+ const joint = getJointRef.current();
1003
+ return () => {
1004
+ if (joint) {
1005
+ world.removeImpulseJoint(joint);
1006
+ jointRef.current = undefined;
1007
+ }
1008
+ };
1009
+ }, []);
1010
+ const api = React.useMemo(() => createJointApi(getJointRef), []);
1011
+ return api;
1012
+ };
1013
+ /**
1014
+ *
1015
+ * A fixed joint ensures that two rigid-bodies don't move relative to each other.
1016
+ * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
1017
+ * The fixed-joint makes these frames coincide in world-space.
1018
+ */
1019
+
1020
+ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
1021
+ const {
1022
+ rapier
1023
+ } = useRapier();
1024
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
1025
+ w: 1
1026
+ }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
870
1027
  w: 1
871
1028
  })));
872
1029
  };
@@ -908,80 +1065,173 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
908
1065
  return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
909
1066
  };
910
1067
 
911
- const _excluded$1 = ["children"],
912
- _excluded2 = ["type", "position", "rotation"];
913
- const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
914
- const useRigidBodyContext = () => React.useContext(RigidBodyContext); // RigidBody
1068
+ // Colliders
1069
+ const AnyCollider = /*#__PURE__*/React.memo(props => {
1070
+ const {
1071
+ children,
1072
+ position,
1073
+ rotation,
1074
+ quaternion,
1075
+ scale
1076
+ } = props;
1077
+ const {
1078
+ world,
1079
+ colliderEvents,
1080
+ colliderStates
1081
+ } = useRapier();
1082
+ const rigidBodyContext = useRigidBodyContext();
1083
+ const ref = React.useRef(null);
1084
+ const collidersRef = React.useRef([]);
1085
+ React.useEffect(() => {
1086
+ const object = ref.current;
1087
+ const worldScale = object.getWorldScale(new three.Vector3());
1088
+ const colliders = []; // If this is an InstancedRigidBody api
915
1089
 
916
- const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
917
- let {
918
- children
919
- } = _ref,
920
- props = _objectWithoutProperties(_ref, _excluded$1);
1090
+ if (rigidBodyContext && "at" in rigidBodyContext.api) {
1091
+ rigidBodyContext.api.forEach((body, index) => {
1092
+ var _rigidBodyContext$opt, _rigidBodyContext$opt2;
1093
+
1094
+ let instanceScale = worldScale;
1095
+
1096
+ if ("scales" in rigidBodyContext.options && rigidBodyContext !== null && rigidBodyContext !== void 0 && (_rigidBodyContext$opt = rigidBodyContext.options) !== null && _rigidBodyContext$opt !== void 0 && (_rigidBodyContext$opt2 = _rigidBodyContext$opt.scales) !== null && _rigidBodyContext$opt2 !== void 0 && _rigidBodyContext$opt2[index]) {
1097
+ instanceScale = instanceScale.clone().multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
1098
+ }
1099
+
1100
+ const collider = createColliderFromOptions(props, world, instanceScale, body.raw());
1101
+ colliderStates.set(collider.handle, createColliderState(collider, object, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
1102
+ colliders.push(collider);
1103
+ });
1104
+ } else {
1105
+ const collider = createColliderFromOptions(props, world, worldScale, rigidBodyContext && (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.api).raw());
1106
+ colliderStates.set(collider.handle, createColliderState(collider, object, rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.ref.current));
1107
+ colliders.push(collider);
1108
+ }
921
1109
 
922
- const [object, api] = useRigidBody(props);
1110
+ collidersRef.current = colliders;
1111
+ return () => {
1112
+ colliders.forEach(collider => {
1113
+ world.removeCollider(collider);
1114
+ });
1115
+ };
1116
+ }, []);
1117
+ useUpdateColliderOptions(collidersRef, props, colliderStates);
1118
+ useColliderEvents(collidersRef, props, colliderEvents);
1119
+ return /*#__PURE__*/React__default["default"].createElement("object3D", {
1120
+ position: position,
1121
+ rotation: rotation,
1122
+ quaternion: quaternion,
1123
+ scale: scale,
1124
+ ref: ref
1125
+ }, children);
1126
+ });
1127
+ const CuboidCollider = props => {
1128
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1129
+ shape: "cuboid"
1130
+ }));
1131
+ };
1132
+ const RoundCuboidCollider = props => {
1133
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1134
+ shape: "roundCuboid"
1135
+ }));
1136
+ };
1137
+ const BallCollider = props => {
1138
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1139
+ shape: "ball"
1140
+ }));
1141
+ };
1142
+ const CapsuleCollider = props => {
1143
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1144
+ shape: "capsule"
1145
+ }));
1146
+ };
1147
+ const HeightfieldCollider = props => {
1148
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1149
+ shape: "heightfield"
1150
+ }));
1151
+ };
1152
+ const TrimeshCollider = props => {
1153
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1154
+ shape: "trimesh"
1155
+ }));
1156
+ };
1157
+ const ConeCollider = props => {
1158
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1159
+ shape: "cone"
1160
+ }));
1161
+ };
1162
+ const CylinderCollider = props => {
1163
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1164
+ shape: "cylinder"
1165
+ }));
1166
+ };
1167
+ const ConvexHullCollider = props => {
1168
+ return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1169
+ shape: "convexHull"
1170
+ }));
1171
+ };
923
1172
 
924
- const objectProps = _objectWithoutProperties(props, _excluded2);
1173
+ const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
1174
+ const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
1175
+ const useRigidBodyContext = () => React.useContext(RigidBodyContext);
1176
+ const RigidBody = /*#__PURE__*/React.forwardRef((props, ref) => {
1177
+ const {
1178
+ children,
1179
+ type,
1180
+ position,
1181
+ rotation,
1182
+ scale,
1183
+ quaternion
1184
+ } = props,
1185
+ objectProps = _objectWithoutProperties(props, _excluded$1);
925
1186
 
1187
+ const [object, api, childColliderProps] = useRigidBody(props);
926
1188
  React.useImperativeHandle(ref, () => api);
927
1189
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
928
1190
  value: {
929
1191
  ref: object,
930
1192
  api,
931
- hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
932
1193
  options: props
933
1194
  }
934
1195
  }, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
935
1196
  ref: object
936
- }, objectProps), children));
1197
+ }, objectProps, {
1198
+ position: position,
1199
+ rotation: rotation,
1200
+ quaternion: quaternion,
1201
+ scale: scale
1202
+ }), children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1203
+ key: index
1204
+ }, colliderProps)))));
937
1205
  });
938
1206
 
939
- const MeshCollider = ({
940
- children,
941
- type
942
- }) => {
1207
+ const MeshCollider = props => {
1208
+ const {
1209
+ children,
1210
+ type
1211
+ } = props;
943
1212
  const {
944
1213
  physicsOptions,
945
1214
  world
946
1215
  } = useRapier();
947
1216
  const object = React.useRef(null);
948
1217
  const {
949
- api,
950
1218
  options
951
1219
  } = useRigidBodyContext();
952
- React.useEffect(() => {
953
- let autoColliders = [];
954
-
955
- if (object.current) {
956
- var _ref;
957
-
958
- const colliderSetting = (_ref = type !== null && type !== void 0 ? type : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
959
-
960
- if ("raw" in api) {
961
- autoColliders = createCollidersFromChildren({
962
- object: object.current,
963
- rigidBody: api,
964
- options: _objectSpread2(_objectSpread2({}, options), {}, {
965
- colliders: colliderSetting
966
- }),
967
- world,
968
- ignoreMeshColliders: false
969
- });
970
- }
971
- }
972
-
973
- return () => {
974
- autoColliders.forEach(collider => {
975
- world.removeCollider(collider);
976
- });
977
- };
978
- }, []);
1220
+ const mergedOptions = React.useMemo(() => {
1221
+ return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
1222
+ children: undefined,
1223
+ colliders: type
1224
+ });
1225
+ }, [physicsOptions, options]);
1226
+ const childColliderProps = useChildColliderProps(object, mergedOptions, false);
979
1227
  return /*#__PURE__*/React__default["default"].createElement("object3D", {
980
1228
  ref: object,
981
1229
  userData: {
982
1230
  r3RapierType: "MeshCollider"
983
1231
  }
984
- }, children);
1232
+ }, children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1233
+ key: index
1234
+ }, colliderProps))));
985
1235
  };
986
1236
 
987
1237
  const geometryFromCollider = collider => {
@@ -1158,6 +1408,7 @@ const Debug = ({
1158
1408
  })));
1159
1409
  };
1160
1410
 
1411
+ const _excluded = ["positions", "rotations", "children"];
1161
1412
  const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1162
1413
  const {
1163
1414
  world,
@@ -1165,6 +1416,14 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1165
1416
  physicsOptions
1166
1417
  } = useRapier();
1167
1418
  const object = React.useRef(null);
1419
+
1420
+ const {
1421
+ positions,
1422
+ rotations,
1423
+ children
1424
+ } = props,
1425
+ options = _objectWithoutProperties(props, _excluded);
1426
+
1168
1427
  const instancesRef = React.useRef();
1169
1428
  const instancesRefGetter = React.useRef(() => {
1170
1429
  if (!instancesRef.current) {
@@ -1173,215 +1432,120 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1173
1432
 
1174
1433
  return instancesRef.current;
1175
1434
  });
1435
+ const mergedOptions = React.useMemo(() => {
1436
+ return _objectSpread2(_objectSpread2({}, physicsOptions), options);
1437
+ }, [physicsOptions, options]);
1438
+ const childColliderProps = useChildColliderProps(object, mergedOptions);
1176
1439
  React.useLayoutEffect(() => {
1177
- const colliders = [];
1440
+ object.current.updateWorldMatrix(true, false);
1178
1441
  const rigidBodies = instancesRefGetter.current();
1179
-
1180
- if (object.current) {
1181
- const worldScale = object.current.getWorldScale(new three.Vector3());
1182
- let hasOneMesh = false;
1183
- object.current.traverse(mesh => {
1184
- if (mesh instanceof three.InstancedMesh) {
1185
- if (hasOneMesh) {
1186
- console.warn("Can only use a single InstancedMesh inside <InstancedRigidBodies />, more InstancedMeshes will be ignored.");
1187
- return;
1188
- }
1189
-
1190
- hasOneMesh = true;
1191
- mesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
1192
-
1193
- for (let index = 0; index < mesh.count; index++) {
1194
- const scale = worldScale.clone();
1195
- const rigidBodyDesc = rigidBodyDescFromOptions(props);
1196
-
1197
- if (props.scales && props.scales[index]) {
1198
- const s = vectorArrayToVector3(props.scales[index]);
1199
- scale.multiply(s);
1200
- }
1201
-
1202
- const rigidBody = world.createRigidBody(rigidBodyDesc);
1203
- const matrix = new three.Matrix4();
1204
- mesh.getMatrixAt(index, matrix);
1205
- const {
1206
- position,
1207
- rotation
1208
- } = decomposeMatrix4(matrix);
1209
-
1210
- if (props.colliders !== false) {
1211
- const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders !== undefined ? props.colliders : physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1212
- );
1213
- const collider = world.createCollider(colliderDesc, rigidBody);
1214
- colliders.push(collider);
1215
- } // Set positions
1216
-
1217
-
1218
- if (props.positions && props.positions[index]) {
1219
- rigidBody.setTranslation(vectorArrayToVector3(props.positions[index]), true);
1220
- } else {
1221
- rigidBody.setTranslation(position, true);
1222
- } // Set rotations
1223
-
1224
-
1225
- if (props.rotations && props.rotations[index]) {
1226
- const [x, y, z] = props.rotations[index];
1227
- rigidBody.setRotation(vector3ToQuaternion(new three.Vector3(x, y, z)), true);
1228
- } else {
1229
- rigidBody.setRotation(rotation, true);
1442
+ const invertedWorld = object.current.matrixWorld.clone().invert();
1443
+ object.current.traverseVisible(mesh => {
1444
+ if (mesh instanceof three.InstancedMesh) {
1445
+ mesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
1446
+ const worldScale = mesh.getWorldScale(_scale);
1447
+
1448
+ for (let index = 0; index < mesh.count; index++) {
1449
+ var _options$scales;
1450
+
1451
+ const desc = rigidBodyDescFromOptions(props);
1452
+ const rigidBody = world.createRigidBody(desc);
1453
+ const scale = ((_options$scales = options.scales) === null || _options$scales === void 0 ? void 0 : _options$scales[index]) || [1, 1, 1];
1454
+ const instanceScale = worldScale.clone().multiply(vectorArrayToVector3(scale));
1455
+ rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
1456
+ rigidBody,
1457
+ object: mesh,
1458
+ setMatrix: matrix => mesh.setMatrixAt(index, matrix),
1459
+ getMatrix: matrix => {
1460
+ mesh.getMatrixAt(index, matrix);
1461
+ return matrix;
1462
+ },
1463
+ worldScale: instanceScale
1464
+ }));
1465
+ const [x, y, z] = (positions === null || positions === void 0 ? void 0 : positions[index]) || [0, 0, 0];
1466
+ const [rx, ry, rz] = (rotations === null || rotations === void 0 ? void 0 : rotations[index]) || [0, 0, 0];
1467
+
1468
+ _object3d.position.set(x, y, z);
1469
+
1470
+ _object3d.rotation.set(rx, ry, rz);
1471
+
1472
+ _object3d.applyMatrix4(invertedWorld); // Set initial transforms based on world transforms
1473
+ // will be replaced by the setRigidBodyOption below
1474
+
1475
+
1476
+ rigidBody.setTranslation(_object3d.position, false);
1477
+ rigidBody.setRotation(_object3d.quaternion, false);
1478
+ const api = createRigidBodyApi({
1479
+ current() {
1480
+ return rigidBody;
1230
1481
  }
1231
1482
 
1232
- rigidBodyStates.set(rigidBody.handle, {
1233
- mesh: mesh,
1234
- isSleeping: false,
1235
- invertedMatrixWorld: object.current.matrixWorld.clone().invert(),
1236
- setMatrix: matrix => mesh.setMatrixAt(index, matrix),
1237
- getMatrix: () => {
1238
- const m = new three.Matrix4();
1239
- mesh.getMatrixAt(index, m);
1240
- return m;
1241
- },
1242
- // Setting the world scale to the scale here, because
1243
- // we want the scales to be reflected by instance
1244
- worldScale: scale
1245
- });
1246
- const api = createRigidBodyApi({
1247
- current() {
1248
- return rigidBody;
1249
- }
1250
-
1251
- });
1252
- rigidBodies.push({
1253
- rigidBody,
1254
- api
1255
- });
1256
- }
1257
- }
1258
-
1259
- if (mesh.type === "Mesh" && !("isInstancedMesh" in mesh)) {
1260
- console.warn("Can only use InstancedMesh inside <InstancedRigidBodies />, Mesh will be ignored.");
1483
+ });
1484
+ rigidBodies.push({
1485
+ rigidBody,
1486
+ api
1487
+ });
1261
1488
  }
1489
+ }
1490
+ });
1491
+ return () => {
1492
+ rigidBodies.forEach(rb => {
1493
+ world.removeRigidBody(rb.rigidBody);
1494
+ rigidBodyStates.delete(rb.rigidBody.handle);
1262
1495
  });
1263
- return () => {
1264
- rigidBodies.forEach(rb => world.removeRigidBody(rb.rigidBody));
1265
- colliders.forEach(coll => world.removeCollider(coll));
1266
- instancesRef.current = undefined;
1267
- };
1268
- }
1496
+ instancesRef.current = undefined;
1497
+ };
1269
1498
  }, []);
1270
1499
  const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1271
- React.useImperativeHandle(ref, () => api); // console.log(api);
1272
-
1500
+ React.useImperativeHandle(ref, () => api);
1273
1501
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1274
1502
  value: {
1275
1503
  ref: object,
1276
1504
  api,
1277
- hasCollisionEvents: false,
1278
1505
  options: props
1279
1506
  }
1280
1507
  }, /*#__PURE__*/React__default["default"].createElement("object3D", {
1281
1508
  ref: object
1282
- }, props.children));
1509
+ }, props.children, childColliderProps.map((colliderProps, index) => /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({
1510
+ key: index
1511
+ }, colliderProps)))));
1283
1512
  });
1284
1513
 
1285
- const _excluded = ["children"];
1286
-
1287
- const AnyCollider = _ref => {
1288
- let {
1289
- children
1290
- } = _ref,
1291
- props = _objectWithoutProperties(_ref, _excluded);
1292
-
1293
- const {
1294
- world
1295
- } = useRapier();
1296
- const rigidBodyContext = useRigidBodyContext();
1297
- const ref = React.useRef(null);
1298
- React.useEffect(() => {
1299
- const scale = ref.current.getWorldScale(new three.Vector3());
1300
- const colliders = []; // If this is an InstancedRigidBody api
1301
-
1302
- if (rigidBodyContext && "at" in rigidBodyContext.api) {
1303
- rigidBodyContext.api.forEach((body, index) => {
1304
- var _rigidBodyContext$opt, _rigidBodyContext$opt2;
1305
-
1306
- let instanceScale = scale.clone();
1307
-
1308
- if ("scales" in rigidBodyContext.options && rigidBodyContext !== null && rigidBodyContext !== void 0 && (_rigidBodyContext$opt = rigidBodyContext.options) !== null && _rigidBodyContext$opt !== void 0 && (_rigidBodyContext$opt2 = _rigidBodyContext$opt.scales) !== null && _rigidBodyContext$opt2 !== void 0 && _rigidBodyContext$opt2[index]) {
1309
- instanceScale.multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
1310
- }
1311
-
1312
- colliders.push(createColliderFromOptions({
1313
- options: props,
1314
- world,
1315
- rigidBody: body.raw(),
1316
- scale: instanceScale,
1317
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1318
- }));
1319
- });
1320
- } else {
1321
- colliders.push(createColliderFromOptions({
1322
- options: props,
1323
- world,
1324
- // Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
1325
- rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
1326
- scale,
1327
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1328
- }));
1329
- }
1330
-
1331
- return () => {
1332
- colliders.forEach(collider => world.removeCollider(collider));
1333
- };
1334
- }, []);
1335
- return /*#__PURE__*/React__default["default"].createElement("object3D", {
1336
- ref: ref
1337
- }, children);
1338
- };
1514
+ /**
1515
+ * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
1516
+ * properties of RigidBody or Collider components. The first argument represents a list of
1517
+ * groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
1518
+ * of groups that will be filtered against. When it is omitted, all groups are filtered against.
1519
+ *
1520
+ * @example
1521
+ * A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
1522
+ *
1523
+ * ```tsx
1524
+ * <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
1525
+ * ```
1526
+ *
1527
+ * A RigidBody that is member of groups 0 and 1 and will collide with everything else:
1528
+ *
1529
+ * ```tsx
1530
+ * <RigidBody collisionGroups={interactionGroups([0, 1])} />
1531
+ * ```
1532
+ *
1533
+ * A RigidBody that is member of groups 0 and 1 and will not collide with anything:
1534
+ *
1535
+ * ```tsx
1536
+ * <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
1537
+ * ```
1538
+ *
1539
+ * Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
1540
+ * entities for collision events to trigger.
1541
+ *
1542
+ * @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
1543
+ * @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
1544
+ * @returns An InteractionGroup bitmask.
1545
+ */
1546
+ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
1339
1547
 
1340
- const CuboidCollider = props => {
1341
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1342
- shape: "cuboid"
1343
- }));
1344
- };
1345
- const RoundCuboidCollider = props => {
1346
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1347
- shape: "roundCuboid"
1348
- }));
1349
- };
1350
- const BallCollider = props => {
1351
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1352
- shape: "ball"
1353
- }));
1354
- };
1355
- const CapsuleCollider = props => {
1356
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1357
- shape: "capsule"
1358
- }));
1359
- };
1360
- const HeightfieldCollider = props => {
1361
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1362
- shape: "heightfield"
1363
- }));
1364
- };
1365
- const TrimeshCollider = props => {
1366
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1367
- shape: "trimesh"
1368
- }));
1369
- };
1370
- const ConeCollider = props => {
1371
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1372
- shape: "cone"
1373
- }));
1374
- };
1375
- const CylinderCollider = props => {
1376
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1377
- shape: "cylinder"
1378
- }));
1379
- };
1380
- const ConvexHullCollider = props => {
1381
- return /*#__PURE__*/React__default["default"].createElement(AnyCollider, _extends({}, props, {
1382
- shape: "convexHull"
1383
- }));
1384
- };
1548
+ const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1385
1549
 
1386
1550
  Object.defineProperty(exports, 'CoefficientCombineRule', {
1387
1551
  enumerable: true,
@@ -1395,6 +1559,7 @@ Object.defineProperty(exports, 'RapierRigidBody', {
1395
1559
  enumerable: true,
1396
1560
  get: function () { return rapier3dCompat.RigidBody; }
1397
1561
  });
1562
+ exports.AnyCollider = AnyCollider;
1398
1563
  exports.BallCollider = BallCollider;
1399
1564
  exports.CapsuleCollider = CapsuleCollider;
1400
1565
  exports.ConeCollider = ConeCollider;
@@ -1409,6 +1574,8 @@ exports.Physics = Physics;
1409
1574
  exports.RigidBody = RigidBody;
1410
1575
  exports.RoundCuboidCollider = RoundCuboidCollider;
1411
1576
  exports.TrimeshCollider = TrimeshCollider;
1577
+ exports.interactionGroups = interactionGroups;
1578
+ exports.useChildColliderProps = useChildColliderProps;
1412
1579
  exports.useFixedJoint = useFixedJoint;
1413
1580
  exports.useImpulseJoint = useImpulseJoint;
1414
1581
  exports.usePrismaticJoint = usePrismaticJoint;