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