@react-three/rapier 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,6 +31,47 @@ function _interopNamespace(e) {
31
31
 
32
32
  var React__default = /*#__PURE__*/_interopDefault(React);
33
33
 
34
+ function _defineProperty(obj, key, value) {
35
+ if (key in obj) {
36
+ Object.defineProperty(obj, key, {
37
+ value: value,
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true
41
+ });
42
+ } else {
43
+ obj[key] = value;
44
+ }
45
+
46
+ return obj;
47
+ }
48
+
49
+ function ownKeys(object, enumerableOnly) {
50
+ var keys = Object.keys(object);
51
+
52
+ if (Object.getOwnPropertySymbols) {
53
+ var symbols = Object.getOwnPropertySymbols(object);
54
+ enumerableOnly && (symbols = symbols.filter(function (sym) {
55
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
56
+ })), keys.push.apply(keys, symbols);
57
+ }
58
+
59
+ return keys;
60
+ }
61
+
62
+ function _objectSpread2(target) {
63
+ for (var i = 1; i < arguments.length; i++) {
64
+ var source = null != arguments[i] ? arguments[i] : {};
65
+ i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
66
+ _defineProperty(target, key, source[key]);
67
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
68
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
69
+ });
70
+ }
71
+
72
+ return target;
73
+ }
74
+
34
75
  const _quaternion = new three.Quaternion();
35
76
  new three.Euler();
36
77
  const _vector3 = new three.Vector3();
@@ -238,1055 +279,1070 @@ const createJointApi = ref => {
238
279
  };
239
280
  };
240
281
 
241
- const RapierContext = /*#__PURE__*/React.createContext(undefined);
282
+ const scaleColliderArgs = (shape, args, scale) => {
283
+ const newArgs = args.slice(); // Heightfield uses a vector
242
284
 
243
- const importRapier = async () => {
244
- let r = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@dimforge/rapier3d-compat')); });
245
- await r.init();
246
- return r;
247
- };
285
+ if (shape === "heightfield") {
286
+ const s = newArgs[3];
287
+ s.x *= scale.x;
288
+ s.x *= scale.y;
289
+ s.x *= scale.z;
290
+ return newArgs;
291
+ } // Trimesh and convex scale the vertices
248
292
 
249
- const Physics = ({
250
- colliders: _colliders = "cuboid",
251
- gravity: _gravity = [0, -9.81, 0],
252
- children,
253
- timeStep: _timeStep = 1 / 60,
254
- paused: _paused = false,
255
- updatePriority,
256
- interpolate: _interpolate = true
257
- }) => {
258
- const rapier = useAsset.useAsset(importRapier);
259
- const worldRef = React.useRef();
260
- const getWorldRef = React.useRef(() => {
261
- if (!worldRef.current) {
262
- const world = new rapier.World(vectorArrayToVector3(_gravity));
263
- worldRef.current = world;
264
- }
265
293
 
266
- return worldRef.current;
267
- });
268
- const [rigidBodyStates] = React.useState(() => new Map());
269
- const [colliderStates] = React.useState(() => new Map());
270
- const [rigidBodyEvents] = React.useState(() => new Map());
271
- const [colliderEvents] = React.useState(() => new Map());
272
- const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
294
+ if (shape === "trimesh" || shape === "convexHull") {
295
+ newArgs[0] = scaleVertices(newArgs[0], scale);
296
+ return newArgs;
297
+ } // Prepfill with some extra
273
298
 
274
- React.useEffect(() => {
275
- const world = getWorldRef.current();
276
- return () => {
277
- if (world) {
278
- world.free();
279
- worldRef.current = undefined;
280
- }
281
- };
282
- }, []); // Update gravity
283
299
 
284
- React.useEffect(() => {
285
- const world = worldRef.current;
300
+ const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
301
+ return newArgs.map((arg, index) => scaleArray[index] * arg);
302
+ };
303
+ const createColliderFromOptions = (options, world, scale, rigidBody) => {
304
+ const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
286
305
 
287
- if (world) {
288
- world.gravity = vectorArrayToVector3(_gravity);
289
- }
290
- }, [_gravity]);
291
- const [steppingState] = React.useState({
292
- previousState: {},
293
- accumulator: 0
294
- });
295
- /* Check if the timestep is supposed to be variable. We'll do this here
296
- once so we don't have to string-check every frame. */
306
+ const desc = rapier3dCompat.ColliderDesc[options.shape](...scaledArgs);
307
+ return world.createCollider(desc, rigidBody);
308
+ };
309
+ const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
297
310
 
298
- const timeStepVariable = _timeStep === "vary";
299
- const getSourceFromColliderHandle = React.useCallback(handle => {
300
- const world = worldRef.current;
311
+ const setColliderMassOptions = (collider, options) => {
312
+ if (options.density !== undefined) {
313
+ if (options.mass !== undefined || options.massProperties !== undefined) {
314
+ throw new Error(massPropertiesConflictError);
315
+ }
301
316
 
302
- if (world) {
303
- var _collider$parent;
317
+ collider.setDensity(options.density);
318
+ return;
319
+ }
304
320
 
305
- const collider = world.getCollider(handle);
306
- const colEvents = colliderEvents.get(handle);
307
- const colliderState = colliderStates.get(handle);
308
- const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
309
- const rigidBody = rigidBodyHandle ? world.getRigidBody(rigidBodyHandle) : undefined;
310
- const rbEvents = rigidBody && rigidBodyHandle ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
311
- const rigidBodyState = rigidBodyHandle ? rigidBodyStates.get(rigidBodyHandle) : undefined;
312
- return {
313
- collider: {
314
- object: collider,
315
- events: colEvents,
316
- state: colliderState
317
- },
318
- rigidBody: {
319
- object: rigidBody,
320
- events: rbEvents,
321
- state: rigidBodyState
322
- }
323
- };
321
+ if (options.mass !== undefined) {
322
+ if (options.massProperties !== undefined) {
323
+ throw new Error(massPropertiesConflictError);
324
324
  }
325
- }, []);
326
- fiber.useFrame((_, dt) => {
327
- const world = worldRef.current;
328
- if (!world) return;
329
- /**
330
- * Fixed timeStep simulation progression
331
- * @see https://gafferongames.com/post/fix_your_timestep/
332
- */
333
325
 
334
- const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
335
-
336
- if (timeStepVariable) {
337
- world.timestep = clampedDelta;
338
- if (!_paused) world.step(eventQueue);
339
- } else {
340
- world.timestep = _timeStep; // don't step time forwards if paused
341
- // Increase accumulator
326
+ collider.setMass(options.mass);
327
+ return;
328
+ }
342
329
 
343
- steppingState.accumulator += _paused ? 0 : clampedDelta;
330
+ if (options.massProperties !== undefined) {
331
+ collider.setMassProperties(options.massProperties.mass, options.massProperties.centerOfMass, options.massProperties.principalAngularInertia, options.massProperties.angularInertiaLocalFrame);
332
+ }
333
+ };
344
334
 
345
- if (!_paused) {
346
- while (steppingState.accumulator >= _timeStep) {
347
- if (_interpolate) {
348
- // Set up previous state
349
- // needed for accurate interpolations if the world steps more than once
350
- steppingState.previousState = {};
351
- world.forEachRigidBody(body => {
352
- steppingState.previousState[body.handle] = {
353
- position: body.translation(),
354
- rotation: body.rotation()
355
- };
356
- });
357
- }
358
-
359
- world.step(eventQueue);
360
- steppingState.accumulator -= _timeStep;
361
- }
362
- }
363
- }
335
+ const mutableColliderOptions = {
336
+ sensor: (collider, value) => {
337
+ collider.setSensor(value);
338
+ },
339
+ collisionGroups: (collider, value) => {
340
+ collider.setCollisionGroups(value);
341
+ },
342
+ solverGroups: (collider, value) => {
343
+ collider.setSolverGroups(value);
344
+ },
345
+ friction: (collider, value) => {
346
+ collider.setFriction(value);
347
+ },
348
+ frictionCombineRule: (collider, value) => {
349
+ collider.setFrictionCombineRule(value);
350
+ },
351
+ restitution: (collider, value) => {
352
+ collider.setRestitution(value);
353
+ },
354
+ restitutionCombineRule: (collider, value) => {
355
+ collider.setRestitutionCombineRule(value);
356
+ },
357
+ // To make sure the options all mutalbe options are listed
358
+ quaternion: () => {},
359
+ position: () => {},
360
+ rotation: () => {},
361
+ scale: () => {}
362
+ };
363
+ const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
364
+ const setColliderOptions = (collider, options, states) => {
365
+ const state = states.get(collider.handle);
364
366
 
365
- const interpolationAlpha = timeStepVariable || !_interpolate ? 1 : steppingState.accumulator / _timeStep; // Update meshes
367
+ if (state) {
368
+ var _state$worldParent;
366
369
 
367
- rigidBodyStates.forEach((state, handle) => {
368
- const rigidBody = world.getRigidBody(handle);
369
- const events = rigidBodyEvents.get(handle);
370
+ // Update collider position based on the object's position
371
+ const parentWorldScale = state.object.parent.getWorldScale(_vector3);
372
+ const parentInvertedWorldMatrix = (_state$worldParent = state.worldParent) === null || _state$worldParent === void 0 ? void 0 : _state$worldParent.matrixWorld.clone().invert();
373
+ state.object.updateWorldMatrix(true, false);
370
374
 
371
- if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
372
- if (rigidBody.isSleeping() && !state.isSleeping) {
373
- var _events$onSleep;
375
+ _matrix4.copy(state.object.matrixWorld);
374
376
 
375
- events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
376
- }
377
+ if (parentInvertedWorldMatrix) {
378
+ _matrix4.premultiply(parentInvertedWorldMatrix);
379
+ }
377
380
 
378
- if (!rigidBody.isSleeping() && state.isSleeping) {
379
- var _events$onWake;
381
+ _matrix4.decompose(_position, _rotation, _scale);
380
382
 
381
- events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
382
- }
383
+ if (collider.parent()) {
384
+ collider.setTranslationWrtParent({
385
+ x: _position.x * parentWorldScale.x,
386
+ y: _position.y * parentWorldScale.y,
387
+ z: _position.z * parentWorldScale.z
388
+ });
389
+ collider.setRotationWrtParent(_rotation);
390
+ } else {
391
+ collider.setTranslation({
392
+ x: _position.x * parentWorldScale.x,
393
+ y: _position.y * parentWorldScale.y,
394
+ z: _position.z * parentWorldScale.z
395
+ });
396
+ collider.setRotation(_rotation);
397
+ }
383
398
 
384
- state.isSleeping = rigidBody.isSleeping();
399
+ mutableColliderOptionKeys.forEach(key => {
400
+ if (key in options) {
401
+ const option = options[key];
402
+ mutableColliderOptions[key](collider, // @ts-ignore Option does not want to fit into the function, but it will
403
+ option, options);
385
404
  }
405
+ }); // handle mass separately, because the assignments
406
+ // are exclusive.
386
407
 
387
- if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
388
- return;
389
- }
408
+ setColliderMassOptions(collider, options);
409
+ }
410
+ };
411
+ const useUpdateColliderOptions = (collidersRef, props, states) => {
412
+ // TODO: Improve this, split each prop into its own effect
413
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
414
+ return vectorToTuple(props[key]);
415
+ }), [props]);
416
+ React.useEffect(() => {
417
+ collidersRef.current.forEach(collider => {
418
+ setColliderOptions(collider, props, states);
419
+ });
420
+ }, mutablePropsAsFlatArray);
421
+ };
390
422
 
391
- let t = rigidBody.translation();
392
- let r = rigidBody.rotation();
393
- let previousState = steppingState.previousState[handle];
423
+ const isChildOfMeshCollider = child => {
424
+ let flag = false;
425
+ child.traverseAncestors(a => {
426
+ if (a.userData.r3RapierType === "MeshCollider") flag = true;
427
+ });
428
+ return flag;
429
+ };
394
430
 
395
- if (previousState) {
396
- // Get previous simulated world position
397
- _matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale); // Apply previous tick position
431
+ const createColliderState = (collider, object, rigidBodyObject) => {
432
+ return {
433
+ collider,
434
+ worldParent: rigidBodyObject || undefined,
435
+ object
436
+ };
437
+ };
438
+ const autoColliderMap = {
439
+ cuboid: "cuboid",
440
+ ball: "ball",
441
+ hull: "convexHull",
442
+ trimesh: "trimesh"
443
+ };
444
+ const createColliderPropsFromChildren = ({
445
+ object,
446
+ ignoreMeshColliders: _ignoreMeshColliders = true,
447
+ options
448
+ }) => {
449
+ const colliderProps = [];
450
+ object.updateWorldMatrix(true, false);
451
+ const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
398
452
 
453
+ const colliderFromChild = child => {
454
+ if ("isMesh" in child) {
455
+ if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
456
+ const worldScale = child.getWorldScale(_scale);
457
+ const shape = autoColliderMap[options.colliders || "cuboid"];
458
+ child.updateWorldMatrix(true, false);
399
459
 
400
- if (!(state.object instanceof three.InstancedMesh)) {
401
- state.object.position.copy(_position);
402
- state.object.quaternion.copy(_rotation);
403
- }
404
- } // Get new position
460
+ _matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
405
461
 
462
+ const rotationEuler = new three.Euler().setFromQuaternion(_rotation, "XYZ");
463
+ const {
464
+ geometry
465
+ } = child;
466
+ const {
467
+ args,
468
+ offset
469
+ } = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
470
+ colliderProps.push(_objectSpread2(_objectSpread2({}, options), {}, {
471
+ args: args,
472
+ shape: shape,
473
+ rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
474
+ position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
475
+ scale: [worldScale.x, worldScale.y, worldScale.z]
476
+ }));
477
+ }
478
+ };
406
479
 
407
- _matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
480
+ if (options.includeInvisible) {
481
+ object.traverse(colliderFromChild);
482
+ } else {
483
+ object.traverseVisible(colliderFromChild);
484
+ }
408
485
 
409
- if (state.object instanceof three.InstancedMesh) {
410
- state.setMatrix(_matrix4);
411
- state.object.instanceMatrix.needsUpdate = true;
412
- } else {
413
- // Interpolate to new position
414
- state.object.position.lerp(_position, interpolationAlpha);
415
- state.object.quaternion.slerp(_rotation, interpolationAlpha);
486
+ return colliderProps;
487
+ };
488
+ const getColliderArgsFromGeometry = (geometry, colliders) => {
489
+ switch (colliders) {
490
+ case "cuboid":
491
+ {
492
+ geometry.computeBoundingBox();
493
+ const {
494
+ boundingBox
495
+ } = geometry;
496
+ const size = boundingBox.getSize(new three.Vector3());
497
+ return {
498
+ args: [size.x / 2, size.y / 2, size.z / 2],
499
+ offset: boundingBox.getCenter(new three.Vector3())
500
+ };
416
501
  }
417
- });
418
- eventQueue.drainCollisionEvents((handle1, handle2, started) => {
419
- const source1 = getSourceFromColliderHandle(handle1);
420
- const source2 = getSourceFromColliderHandle(handle2); // Collision Events
421
502
 
422
- if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
423
- return;
503
+ case "ball":
504
+ {
505
+ geometry.computeBoundingSphere();
506
+ const {
507
+ boundingSphere
508
+ } = geometry;
509
+ const radius = boundingSphere.radius;
510
+ return {
511
+ args: [radius],
512
+ offset: boundingSphere.center
513
+ };
424
514
  }
425
515
 
426
- if (started) {
427
- world.contactPair(source1.collider.object, source2.collider.object, (manifold, flipped) => {
428
- var _source1$rigidBody$ev, _source1$rigidBody$ev2, _source2$collider$sta, _source2$rigidBody$st, _source2$rigidBody$ev, _source2$rigidBody$ev2, _source1$collider$sta, _source1$rigidBody$st, _source1$collider$eve, _source1$collider$eve2, _source2$collider$sta2, _source2$rigidBody$st2, _source2$collider$eve, _source2$collider$eve2, _source1$collider$sta2, _source1$rigidBody$st2;
429
-
430
- /* RigidBody events */
431
- (_source1$rigidBody$ev = source1.rigidBody.events) === null || _source1$rigidBody$ev === void 0 ? void 0 : (_source1$rigidBody$ev2 = _source1$rigidBody$ev.onCollisionEnter) === null || _source1$rigidBody$ev2 === void 0 ? void 0 : _source1$rigidBody$ev2.call(_source1$rigidBody$ev, {
432
- rigidBody: source2.rigidBody.object,
433
- collider: source2.collider.object,
434
- colliderObject: (_source2$collider$sta = source2.collider.state) === null || _source2$collider$sta === void 0 ? void 0 : _source2$collider$sta.object,
435
- rigidBodyObject: (_source2$rigidBody$st = source2.rigidBody.state) === null || _source2$rigidBody$st === void 0 ? void 0 : _source2$rigidBody$st.object,
436
- manifold,
437
- flipped
438
- });
439
- (_source2$rigidBody$ev = source2.rigidBody.events) === null || _source2$rigidBody$ev === void 0 ? void 0 : (_source2$rigidBody$ev2 = _source2$rigidBody$ev.onCollisionEnter) === null || _source2$rigidBody$ev2 === void 0 ? void 0 : _source2$rigidBody$ev2.call(_source2$rigidBody$ev, {
440
- rigidBody: source1.rigidBody.object,
441
- collider: source1.collider.object,
442
- colliderObject: (_source1$collider$sta = source1.collider.state) === null || _source1$collider$sta === void 0 ? void 0 : _source1$collider$sta.object,
443
- rigidBodyObject: (_source1$rigidBody$st = source1.rigidBody.state) === null || _source1$rigidBody$st === void 0 ? void 0 : _source1$rigidBody$st.object,
444
- manifold,
445
- flipped
446
- });
447
- /* Collider events */
448
-
449
- (_source1$collider$eve = source1.collider.events) === null || _source1$collider$eve === void 0 ? void 0 : (_source1$collider$eve2 = _source1$collider$eve.onCollisionEnter) === null || _source1$collider$eve2 === void 0 ? void 0 : _source1$collider$eve2.call(_source1$collider$eve, {
450
- rigidBody: source2.rigidBody.object,
451
- collider: source2.collider.object,
452
- colliderObject: (_source2$collider$sta2 = source2.collider.state) === null || _source2$collider$sta2 === void 0 ? void 0 : _source2$collider$sta2.object,
453
- rigidBodyObject: (_source2$rigidBody$st2 = source2.rigidBody.state) === null || _source2$rigidBody$st2 === void 0 ? void 0 : _source2$rigidBody$st2.object,
454
- manifold,
455
- flipped
456
- });
457
- (_source2$collider$eve = source2.collider.events) === null || _source2$collider$eve === void 0 ? void 0 : (_source2$collider$eve2 = _source2$collider$eve.onCollisionEnter) === null || _source2$collider$eve2 === void 0 ? void 0 : _source2$collider$eve2.call(_source2$collider$eve, {
458
- rigidBody: source1.rigidBody.object,
459
- collider: source1.collider.object,
460
- colliderObject: (_source1$collider$sta2 = source1.collider.state) === null || _source1$collider$sta2 === void 0 ? void 0 : _source1$collider$sta2.object,
461
- rigidBodyObject: (_source1$rigidBody$st2 = source1.rigidBody.state) === null || _source1$rigidBody$st2 === void 0 ? void 0 : _source1$rigidBody$st2.object,
462
- manifold,
463
- flipped
464
- });
465
- });
466
- } else {
467
- var _source1$rigidBody$ev3, _source1$rigidBody$ev4, _source2$rigidBody$ev3, _source2$rigidBody$ev4, _source1$collider$eve3, _source1$collider$eve4, _source2$collider$eve3, _source2$collider$eve4;
468
-
469
- (_source1$rigidBody$ev3 = source1.rigidBody.events) === null || _source1$rigidBody$ev3 === void 0 ? void 0 : (_source1$rigidBody$ev4 = _source1$rigidBody$ev3.onCollisionExit) === null || _source1$rigidBody$ev4 === void 0 ? void 0 : _source1$rigidBody$ev4.call(_source1$rigidBody$ev3, {
470
- rigidBody: source2.rigidBody.object,
471
- collider: source2.collider.object
472
- });
473
- (_source2$rigidBody$ev3 = source2.rigidBody.events) === null || _source2$rigidBody$ev3 === void 0 ? void 0 : (_source2$rigidBody$ev4 = _source2$rigidBody$ev3.onCollisionExit) === null || _source2$rigidBody$ev4 === void 0 ? void 0 : _source2$rigidBody$ev4.call(_source2$rigidBody$ev3, {
474
- rigidBody: source1.rigidBody.object,
475
- collider: source1.collider.object
476
- });
477
- (_source1$collider$eve3 = source1.collider.events) === null || _source1$collider$eve3 === void 0 ? void 0 : (_source1$collider$eve4 = _source1$collider$eve3.onCollisionExit) === null || _source1$collider$eve4 === void 0 ? void 0 : _source1$collider$eve4.call(_source1$collider$eve3, {
478
- rigidBody: source2.rigidBody.object,
479
- collider: source2.collider.object
480
- });
481
- (_source2$collider$eve3 = source2.collider.events) === null || _source2$collider$eve3 === void 0 ? void 0 : (_source2$collider$eve4 = _source2$collider$eve3.onCollisionExit) === null || _source2$collider$eve4 === void 0 ? void 0 : _source2$collider$eve4.call(_source2$collider$eve3, {
482
- rigidBody: source1.rigidBody.object,
483
- collider: source1.collider.object
484
- });
485
- } // Sensor Intersections
486
-
487
-
488
- if (started) {
489
- if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
490
- var _source1$rigidBody$ev5, _source1$rigidBody$ev6, _source2$collider$sta3, _source2$rigidBody$st3, _source2$rigidBody$ev5, _source2$rigidBody$ev6, _source1$collider$sta3, _source1$rigidBody$st3, _source1$collider$eve5, _source1$collider$eve6, _source2$collider$sta4, _source2$rigidBody$st4, _source2$collider$eve5, _source2$collider$eve6, _source1$collider$sta4, _source1$rigidBody$st4;
491
-
492
- (_source1$rigidBody$ev5 = source1.rigidBody.events) === null || _source1$rigidBody$ev5 === void 0 ? void 0 : (_source1$rigidBody$ev6 = _source1$rigidBody$ev5.onIntersectionEnter) === null || _source1$rigidBody$ev6 === void 0 ? void 0 : _source1$rigidBody$ev6.call(_source1$rigidBody$ev5, {
493
- rigidBody: source2.rigidBody.object,
494
- collider: source2.collider.object,
495
- colliderObject: (_source2$collider$sta3 = source2.collider.state) === null || _source2$collider$sta3 === void 0 ? void 0 : _source2$collider$sta3.object,
496
- rigidBodyObject: (_source2$rigidBody$st3 = source2.rigidBody.state) === null || _source2$rigidBody$st3 === void 0 ? void 0 : _source2$rigidBody$st3.object
497
- });
498
- (_source2$rigidBody$ev5 = source2.rigidBody.events) === null || _source2$rigidBody$ev5 === void 0 ? void 0 : (_source2$rigidBody$ev6 = _source2$rigidBody$ev5.onIntersectionEnter) === null || _source2$rigidBody$ev6 === void 0 ? void 0 : _source2$rigidBody$ev6.call(_source2$rigidBody$ev5, {
499
- rigidBody: source1.rigidBody.object,
500
- collider: source1.collider.object,
501
- colliderObject: (_source1$collider$sta3 = source1.collider.state) === null || _source1$collider$sta3 === void 0 ? void 0 : _source1$collider$sta3.object,
502
- rigidBodyObject: (_source1$rigidBody$st3 = source1.rigidBody.state) === null || _source1$rigidBody$st3 === void 0 ? void 0 : _source1$rigidBody$st3.object
503
- });
504
- (_source1$collider$eve5 = source1.collider.events) === null || _source1$collider$eve5 === void 0 ? void 0 : (_source1$collider$eve6 = _source1$collider$eve5.onIntersectionEnter) === null || _source1$collider$eve6 === void 0 ? void 0 : _source1$collider$eve6.call(_source1$collider$eve5, {
505
- rigidBody: source2.rigidBody.object,
506
- collider: source2.collider.object,
507
- colliderObject: (_source2$collider$sta4 = source2.collider.state) === null || _source2$collider$sta4 === void 0 ? void 0 : _source2$collider$sta4.object,
508
- rigidBodyObject: (_source2$rigidBody$st4 = source2.rigidBody.state) === null || _source2$rigidBody$st4 === void 0 ? void 0 : _source2$rigidBody$st4.object
509
- });
510
- (_source2$collider$eve5 = source2.collider.events) === null || _source2$collider$eve5 === void 0 ? void 0 : (_source2$collider$eve6 = _source2$collider$eve5.onIntersectionEnter) === null || _source2$collider$eve6 === void 0 ? void 0 : _source2$collider$eve6.call(_source2$collider$eve5, {
511
- rigidBody: source1.rigidBody.object,
512
- collider: source1.collider.object,
513
- colliderObject: (_source1$collider$sta4 = source1.collider.state) === null || _source1$collider$sta4 === void 0 ? void 0 : _source1$collider$sta4.object,
514
- rigidBodyObject: (_source1$rigidBody$st4 = source1.rigidBody.state) === null || _source1$rigidBody$st4 === void 0 ? void 0 : _source1$rigidBody$st4.object
515
- });
516
- }
517
- } else {
518
- var _source1$rigidBody$ev7, _source1$rigidBody$ev8, _source2$rigidBody$ev7, _source2$rigidBody$ev8, _source1$collider$eve7, _source1$collider$eve8, _source2$collider$eve7, _source2$collider$eve8;
516
+ case "trimesh":
517
+ {
518
+ var _clonedGeometry$index;
519
519
 
520
- (_source1$rigidBody$ev7 = source1.rigidBody.events) === null || _source1$rigidBody$ev7 === void 0 ? void 0 : (_source1$rigidBody$ev8 = _source1$rigidBody$ev7.onIntersectionExit) === null || _source1$rigidBody$ev8 === void 0 ? void 0 : _source1$rigidBody$ev8.call(_source1$rigidBody$ev7, {
521
- rigidBody: source2.rigidBody.object,
522
- collider: source2.collider.object
523
- });
524
- (_source2$rigidBody$ev7 = source2.rigidBody.events) === null || _source2$rigidBody$ev7 === void 0 ? void 0 : (_source2$rigidBody$ev8 = _source2$rigidBody$ev7.onIntersectionExit) === null || _source2$rigidBody$ev8 === void 0 ? void 0 : _source2$rigidBody$ev8.call(_source2$rigidBody$ev7, {
525
- rigidBody: source1.rigidBody.object,
526
- collider: source1.collider.object
527
- });
528
- (_source1$collider$eve7 = source1.collider.events) === null || _source1$collider$eve7 === void 0 ? void 0 : (_source1$collider$eve8 = _source1$collider$eve7.onIntersectionExit) === null || _source1$collider$eve8 === void 0 ? void 0 : _source1$collider$eve8.call(_source1$collider$eve7, {
529
- rigidBody: source2.rigidBody.object,
530
- collider: source2.collider.object
531
- });
532
- (_source2$collider$eve7 = source2.collider.events) === null || _source2$collider$eve7 === void 0 ? void 0 : (_source2$collider$eve8 = _source2$collider$eve7.onIntersectionExit) === null || _source2$collider$eve8 === void 0 ? void 0 : _source2$collider$eve8.call(_source2$collider$eve7, {
533
- rigidBody: source1.rigidBody.object,
534
- collider: source1.collider.object
535
- });
520
+ const clonedGeometry = geometry.index ? geometry.clone() : threeStdlib.mergeVertices(geometry);
521
+ return {
522
+ args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
523
+ offset: new three.Vector3()
524
+ };
536
525
  }
537
- });
538
- eventQueue.drainContactForceEvents(event => {
539
- var _source1$rigidBody$ev9, _source1$rigidBody$ev10, _source2$collider$sta5, _source2$rigidBody$st5, _source2$rigidBody$ev9, _source2$rigidBody$ev10, _source1$collider$sta5, _source1$rigidBody$st5, _source1$collider$eve9, _source1$collider$eve10, _source2$collider$sta6, _source2$rigidBody$st6, _source2$collider$eve9, _source2$collider$eve10, _source1$collider$sta6, _source1$rigidBody$st6;
540
-
541
- const source1 = getSourceFromColliderHandle(event.collider1());
542
- const source2 = getSourceFromColliderHandle(event.collider2()); // Collision Events
543
526
 
544
- if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
545
- return;
527
+ case "hull":
528
+ {
529
+ const g = geometry.clone();
530
+ return {
531
+ args: [g.attributes.position.array],
532
+ offset: new three.Vector3()
533
+ };
546
534
  }
535
+ }
547
536
 
548
- (_source1$rigidBody$ev9 = source1.rigidBody.events) === null || _source1$rigidBody$ev9 === void 0 ? void 0 : (_source1$rigidBody$ev10 = _source1$rigidBody$ev9.onContactForce) === null || _source1$rigidBody$ev10 === void 0 ? void 0 : _source1$rigidBody$ev10.call(_source1$rigidBody$ev9, {
549
- rigidBody: source2.rigidBody.object,
550
- collider: source2.collider.object,
551
- colliderObject: (_source2$collider$sta5 = source2.collider.state) === null || _source2$collider$sta5 === void 0 ? void 0 : _source2$collider$sta5.object,
552
- rigidBodyObject: (_source2$rigidBody$st5 = source2.rigidBody.state) === null || _source2$rigidBody$st5 === void 0 ? void 0 : _source2$rigidBody$st5.object,
553
- totalForce: event.totalForce(),
554
- totalForceMagnitude: event.totalForceMagnitude(),
555
- maxForceDirection: event.maxForceDirection(),
556
- maxForceMagnitude: event.maxForceMagnitude()
557
- });
558
- (_source2$rigidBody$ev9 = source2.rigidBody.events) === null || _source2$rigidBody$ev9 === void 0 ? void 0 : (_source2$rigidBody$ev10 = _source2$rigidBody$ev9.onContactForce) === null || _source2$rigidBody$ev10 === void 0 ? void 0 : _source2$rigidBody$ev10.call(_source2$rigidBody$ev9, {
559
- rigidBody: source1.rigidBody.object,
560
- collider: source1.collider.object,
561
- colliderObject: (_source1$collider$sta5 = source1.collider.state) === null || _source1$collider$sta5 === void 0 ? void 0 : _source1$collider$sta5.object,
562
- rigidBodyObject: (_source1$rigidBody$st5 = source1.rigidBody.state) === null || _source1$rigidBody$st5 === void 0 ? void 0 : _source1$rigidBody$st5.object,
563
- totalForce: event.totalForce(),
564
- totalForceMagnitude: event.totalForceMagnitude(),
565
- maxForceDirection: event.maxForceDirection(),
566
- maxForceMagnitude: event.maxForceMagnitude()
567
- });
568
- (_source1$collider$eve9 = source1.collider.events) === null || _source1$collider$eve9 === void 0 ? void 0 : (_source1$collider$eve10 = _source1$collider$eve9.onContactForce) === null || _source1$collider$eve10 === void 0 ? void 0 : _source1$collider$eve10.call(_source1$collider$eve9, {
569
- rigidBody: source2.rigidBody.object,
570
- collider: source2.collider.object,
571
- colliderObject: (_source2$collider$sta6 = source2.collider.state) === null || _source2$collider$sta6 === void 0 ? void 0 : _source2$collider$sta6.object,
572
- rigidBodyObject: (_source2$rigidBody$st6 = source2.rigidBody.state) === null || _source2$rigidBody$st6 === void 0 ? void 0 : _source2$rigidBody$st6.object,
573
- totalForce: event.totalForce(),
574
- totalForceMagnitude: event.totalForceMagnitude(),
575
- maxForceDirection: event.maxForceDirection(),
576
- maxForceMagnitude: event.maxForceMagnitude()
577
- });
578
- (_source2$collider$eve9 = source2.collider.events) === null || _source2$collider$eve9 === void 0 ? void 0 : (_source2$collider$eve10 = _source2$collider$eve9.onContactForce) === null || _source2$collider$eve10 === void 0 ? void 0 : _source2$collider$eve10.call(_source2$collider$eve9, {
579
- rigidBody: source1.rigidBody.object,
580
- collider: source1.collider.object,
581
- colliderObject: (_source1$collider$sta6 = source1.collider.state) === null || _source1$collider$sta6 === void 0 ? void 0 : _source1$collider$sta6.object,
582
- rigidBodyObject: (_source1$rigidBody$st6 = source1.rigidBody.state) === null || _source1$rigidBody$st6 === void 0 ? void 0 : _source1$rigidBody$st6.object,
583
- totalForce: event.totalForce(),
584
- totalForceMagnitude: event.totalForceMagnitude(),
585
- maxForceDirection: event.maxForceDirection(),
586
- maxForceMagnitude: event.maxForceMagnitude()
587
- });
588
- });
589
- }, updatePriority);
590
- const api = React.useMemo(() => createWorldApi(getWorldRef), []);
591
- const context = React.useMemo(() => ({
592
- rapier,
593
- world: api,
594
- physicsOptions: {
595
- colliders: _colliders,
596
- gravity: _gravity
597
- },
598
- rigidBodyStates,
599
- colliderStates,
600
- rigidBodyEvents,
601
- colliderEvents,
602
- isPaused: _paused
603
- }), [_paused]);
604
- return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
605
- value: context
606
- }, children);
537
+ return {
538
+ args: [],
539
+ offset: new three.Vector3()
540
+ };
607
541
  };
542
+ const useColliderEvents = (collidersRef, props, events) => {
543
+ const {
544
+ onCollisionEnter,
545
+ onCollisionExit,
546
+ onIntersectionEnter,
547
+ onIntersectionExit,
548
+ onContactForce
549
+ } = props;
550
+ React.useEffect(() => {
551
+ var _collidersRef$current;
608
552
 
609
- function _extends() {
610
- _extends = Object.assign ? Object.assign.bind() : function (target) {
611
- for (var i = 1; i < arguments.length; i++) {
612
- var source = arguments[i];
553
+ (_collidersRef$current = collidersRef.current) === null || _collidersRef$current === void 0 ? void 0 : _collidersRef$current.forEach(collider => {
554
+ const hasCollisionEvent = !!(onCollisionEnter || onCollisionExit || onIntersectionEnter || onIntersectionExit);
555
+ const hasContactForceEvent = !!onContactForce;
613
556
 
614
- for (var key in source) {
615
- if (Object.prototype.hasOwnProperty.call(source, key)) {
616
- target[key] = source[key];
617
- }
557
+ if (hasCollisionEvent && hasContactForceEvent) {
558
+ collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS | rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
559
+ } else if (hasCollisionEvent) {
560
+ collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
561
+ } else if (hasContactForceEvent) {
562
+ collider.setActiveEvents(rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
618
563
  }
619
- }
620
564
 
621
- return target;
622
- };
623
- return _extends.apply(this, arguments);
624
- }
565
+ events.set(collider.handle, {
566
+ onCollisionEnter,
567
+ onCollisionExit,
568
+ onIntersectionEnter,
569
+ onIntersectionExit,
570
+ onContactForce
571
+ });
572
+ });
573
+ return () => {
574
+ var _collidersRef$current2;
625
575
 
626
- function _objectWithoutPropertiesLoose(source, excluded) {
627
- if (source == null) return {};
628
- var target = {};
629
- var sourceKeys = Object.keys(source);
630
- var key, i;
631
-
632
- for (i = 0; i < sourceKeys.length; i++) {
633
- key = sourceKeys[i];
634
- if (excluded.indexOf(key) >= 0) continue;
635
- target[key] = source[key];
636
- }
637
-
638
- return target;
639
- }
640
-
641
- function _objectWithoutProperties(source, excluded) {
642
- if (source == null) return {};
643
- var target = _objectWithoutPropertiesLoose(source, excluded);
644
- var key, i;
645
-
646
- if (Object.getOwnPropertySymbols) {
647
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
648
-
649
- for (i = 0; i < sourceSymbolKeys.length; i++) {
650
- key = sourceSymbolKeys[i];
651
- if (excluded.indexOf(key) >= 0) continue;
652
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
653
- target[key] = source[key];
654
- }
655
- }
656
-
657
- return target;
658
- }
659
-
660
- function _defineProperty(obj, key, value) {
661
- if (key in obj) {
662
- Object.defineProperty(obj, key, {
663
- value: value,
664
- enumerable: true,
665
- configurable: true,
666
- writable: true
667
- });
668
- } else {
669
- obj[key] = value;
670
- }
671
-
672
- return obj;
673
- }
674
-
675
- function ownKeys(object, enumerableOnly) {
676
- var keys = Object.keys(object);
677
-
678
- if (Object.getOwnPropertySymbols) {
679
- var symbols = Object.getOwnPropertySymbols(object);
680
- enumerableOnly && (symbols = symbols.filter(function (sym) {
681
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
682
- })), keys.push.apply(keys, symbols);
683
- }
684
-
685
- return keys;
686
- }
687
-
688
- function _objectSpread2(target) {
689
- for (var i = 1; i < arguments.length; i++) {
690
- var source = null != arguments[i] ? arguments[i] : {};
691
- i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
692
- _defineProperty(target, key, source[key]);
693
- }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
694
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
695
- });
696
- }
697
-
698
- return target;
699
- }
700
-
701
- const scaleColliderArgs = (shape, args, scale) => {
702
- const newArgs = args.slice(); // Heightfield uses a vector
703
-
704
- if (shape === "heightfield") {
705
- const s = newArgs[3];
706
- s.x *= scale.x;
707
- s.x *= scale.y;
708
- s.x *= scale.z;
709
- return newArgs;
710
- } // Trimesh and convex scale the vertices
711
-
712
-
713
- if (shape === "trimesh" || shape === "convexHull") {
714
- newArgs[0] = scaleVertices(newArgs[0], scale);
715
- return newArgs;
716
- } // Prepfill with some extra
717
-
718
-
719
- const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
720
- return newArgs.map((arg, index) => scaleArray[index] * arg);
576
+ (_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
577
+ };
578
+ }, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
721
579
  };
722
- const createColliderFromOptions = (options, world, scale, rigidBody) => {
723
- const scaledArgs = scaleColliderArgs(options.shape, options.args, scale); // @ts-ignore
724
580
 
725
- const desc = rapier3dCompat.ColliderDesc[options.shape](...scaledArgs);
726
- return world.createCollider(desc, rigidBody);
581
+ const rigidBodyDescFromOptions = options => {
582
+ const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
583
+ const desc = new rapier3dCompat.RigidBodyDesc(type);
584
+ return desc;
727
585
  };
728
- const massPropertiesConflictError = "Please pick ONLY ONE of the `density`, `mass` and `massProperties` options.";
729
-
730
- const setColliderMassOptions = (collider, options) => {
731
- if (options.density !== undefined) {
732
- if (options.mass !== undefined || options.massProperties !== undefined) {
733
- throw new Error(massPropertiesConflictError);
734
- }
735
-
736
- collider.setDensity(options.density);
737
- return;
738
- }
739
-
740
- if (options.mass !== undefined) {
741
- if (options.massProperties !== undefined) {
742
- throw new Error(massPropertiesConflictError);
743
- }
744
-
745
- collider.setMass(options.mass);
746
- return;
747
- }
748
-
749
- if (options.massProperties !== undefined) {
750
- collider.setMassProperties(options.massProperties.mass, options.massProperties.centerOfMass, options.massProperties.principalAngularInertia, options.massProperties.angularInertiaLocalFrame);
751
- }
586
+ const createRigidBodyState = ({
587
+ rigidBody,
588
+ object,
589
+ setMatrix,
590
+ getMatrix,
591
+ worldScale
592
+ }) => {
593
+ object.updateWorldMatrix(true, false);
594
+ const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
595
+ return {
596
+ object,
597
+ rigidBody,
598
+ invertedWorldMatrix,
599
+ setMatrix: setMatrix ? setMatrix : matrix => {
600
+ object.matrix.copy(matrix);
601
+ },
602
+ getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
603
+ scale: worldScale || object.getWorldScale(_scale).clone(),
604
+ isSleeping: false
605
+ };
752
606
  };
753
-
754
- const mutableColliderOptions = {
755
- sensor: (collider, value) => {
756
- collider.setSensor(value);
607
+ const mutableRigidBodyOptions = {
608
+ gravityScale: (rb, value) => {
609
+ rb.setGravityScale(value, true);
757
610
  },
758
- collisionGroups: (collider, value) => {
759
- collider.setCollisionGroups(value);
611
+ linearDamping: (rb, value) => {
612
+ rb.setLinearDamping(value);
760
613
  },
761
- solverGroups: (collider, value) => {
762
- collider.setSolverGroups(value);
614
+ angularDamping: (rb, value) => {
615
+ rb.setAngularDamping(value);
763
616
  },
764
- friction: (collider, value) => {
765
- collider.setFriction(value);
617
+ enabledRotations: (rb, [x, y, z]) => {
618
+ rb.setEnabledRotations(x, y, z, true);
766
619
  },
767
- frictionCombineRule: (collider, value) => {
768
- collider.setFrictionCombineRule(value);
620
+ enabledTranslations: (rb, [x, y, z]) => {
621
+ rb.setEnabledTranslations(x, y, z, true);
769
622
  },
770
- restitution: (collider, value) => {
771
- collider.setRestitution(value);
623
+ angularVelocity: (rb, [x, y, z]) => {
624
+ rb.setAngvel({
625
+ x,
626
+ y,
627
+ z
628
+ }, true);
772
629
  },
773
- restitutionCombineRule: (collider, value) => {
774
- collider.setRestitutionCombineRule(value);
630
+ linearVelocity: (rb, [x, y, z]) => {
631
+ rb.setLinvel({
632
+ x,
633
+ y,
634
+ z
635
+ }, true);
636
+ },
637
+ ccd: (rb, value) => {
638
+ rb.enableCcd(value);
639
+ },
640
+ userData: (rb, value) => {
641
+ rb.userData = value;
775
642
  },
776
- // To make sure the options all mutalbe options are listed
777
- quaternion: () => {},
778
643
  position: () => {},
779
644
  rotation: () => {},
645
+ quaternion: () => {},
780
646
  scale: () => {}
781
647
  };
782
- const mutableColliderOptionKeys = Object.keys(mutableColliderOptions);
783
- const setColliderOptions = (collider, options, states) => {
784
- const state = states.get(collider.handle);
648
+ const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
649
+ const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
650
+ if (!rigidBody) {
651
+ return;
652
+ }
653
+
654
+ const state = states.get(rigidBody.handle);
785
655
 
786
656
  if (state) {
787
- // Update collider position based on the object's position
788
- const parentWorldScale = state.object.parent.getWorldScale(_vector3);
789
- state.object.updateWorldMatrix(true, false);
657
+ if (updateTranslations) {
658
+ state.object.updateWorldMatrix(true, false);
790
659
 
791
- _matrix4.copy(state.object.matrixWorld).premultiply(state.worldParent.matrixWorld.clone().invert()).decompose(_position, _rotation, _scale);
660
+ _matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
792
661
 
793
- if (collider.parent()) {
794
- collider.setTranslationWrtParent({
795
- x: _position.x * parentWorldScale.x,
796
- y: _position.y * parentWorldScale.y,
797
- z: _position.z * parentWorldScale.z
798
- });
799
- collider.setRotationWrtParent(_rotation);
800
- } else {
801
- collider.setTranslation({
802
- x: _position.x * parentWorldScale.x,
803
- y: _position.y * parentWorldScale.y,
804
- z: _position.z * parentWorldScale.z
805
- });
806
- collider.setRotation(_rotation);
662
+ rigidBody.setTranslation(_position, false);
663
+ rigidBody.setRotation(_rotation, false);
807
664
  }
808
665
 
809
- mutableColliderOptionKeys.forEach(key => {
666
+ mutableRigidBodyOptionKeys.forEach(key => {
810
667
  if (key in options) {
811
- const option = options[key];
812
- mutableColliderOptions[key](collider, // @ts-ignore Option does not want to fit into the function, but it will
813
- option, options);
668
+ mutableRigidBodyOptions[key](rigidBody, options[key]);
814
669
  }
815
- }); // handle mass separately, because the assignments
816
- // are exclusive.
817
-
818
- setColliderMassOptions(collider, options);
670
+ });
819
671
  }
820
672
  };
821
- const useUpdateColliderOptions = (collidersRef, props, states) => {
673
+ const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
822
674
  // TODO: Improve this, split each prop into its own effect
823
- const mutablePropsAsFlatArray = React.useMemo(() => mutableColliderOptionKeys.flatMap(key => {
675
+ const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
824
676
  return vectorToTuple(props[key]);
825
677
  }), [props]);
826
678
  React.useEffect(() => {
827
- collidersRef.current.forEach(collider => {
828
- setColliderOptions(collider, props, states);
829
- });
679
+ if (Array.isArray(rigidBodyRef.current)) {
680
+ for (const rigidBody of rigidBodyRef.current) {
681
+ setRigidBodyOptions(rigidBody, props, states, updateTranslations);
682
+ }
683
+ } else if (rigidBodyRef.current) {
684
+ setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
685
+ }
830
686
  }, mutablePropsAsFlatArray);
831
687
  };
832
-
833
- const isChildOfMeshCollider = child => {
834
- let flag = false;
835
- child.traverseAncestors(a => {
836
- if (a.userData.r3RapierType === "MeshCollider") flag = true;
837
- });
838
- return flag;
839
- };
840
-
841
- const createColliderState = (collider, object, rigidBodyObject) => {
842
- return {
843
- collider,
844
- worldParent: rigidBodyObject || object.parent,
845
- object
688
+ const useRigidBodyEvents = (rigidBodyRef, props, events) => {
689
+ const {
690
+ onWake,
691
+ onSleep,
692
+ onCollisionEnter,
693
+ onCollisionExit,
694
+ onIntersectionEnter,
695
+ onIntersectionExit
696
+ } = props;
697
+ const eventHandlers = {
698
+ onWake,
699
+ onSleep,
700
+ onCollisionEnter,
701
+ onCollisionExit,
702
+ onIntersectionEnter,
703
+ onIntersectionExit
846
704
  };
847
- };
848
- const autoColliderMap = {
849
- cuboid: "cuboid",
850
- ball: "ball",
851
- hull: "convexHull",
852
- trimesh: "trimesh"
853
- };
854
- const createColliderPropsFromChildren = ({
855
- object,
856
- ignoreMeshColliders: _ignoreMeshColliders = true,
857
- options
858
- }) => {
859
- const colliderProps = [];
860
- object.updateWorldMatrix(true, false);
861
- const invertedParentMatrixWorld = object.matrixWorld.clone().invert();
705
+ React.useEffect(() => {
706
+ if (Array.isArray(rigidBodyRef.current)) {
707
+ for (const rigidBody of rigidBodyRef.current) {
708
+ events.set(rigidBody.handle, eventHandlers);
709
+ }
710
+ } else if (rigidBodyRef.current) {
711
+ events.set(rigidBodyRef.current.handle, eventHandlers);
712
+ }
862
713
 
863
- const colliderFromChild = child => {
864
- if ("isMesh" in child) {
865
- if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
866
- const worldScale = child.getWorldScale(_scale);
867
- const shape = autoColliderMap[options.colliders || "cuboid"];
868
- child.updateWorldMatrix(true, false);
714
+ return () => {
715
+ if (Array.isArray(rigidBodyRef.current)) {
716
+ for (const rigidBody of rigidBodyRef.current) {
717
+ events.delete(rigidBody.handle);
718
+ }
719
+ } else if (rigidBodyRef.current) {
720
+ events.delete(rigidBodyRef.current.handle);
721
+ }
722
+ };
723
+ }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
724
+ };
869
725
 
870
- _matrix4.copy(child.matrixWorld).premultiply(invertedParentMatrixWorld).decompose(_position, _rotation, _scale);
726
+ const useRapier = () => {
727
+ return React.useContext(RapierContext);
728
+ };
729
+ const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
730
+ const [colliderProps, setColliderProps] = React.useState([]);
731
+ React.useEffect(() => {
732
+ const object = ref.current;
871
733
 
872
- const rotationEuler = new three.Euler().setFromQuaternion(_rotation, "XYZ");
873
- const {
874
- geometry
875
- } = child;
876
- const {
877
- args,
878
- offset
879
- } = getColliderArgsFromGeometry(geometry, options.colliders || "cuboid");
880
- colliderProps.push(_objectSpread2(_objectSpread2({}, options), {}, {
881
- args: args,
882
- shape: shape,
883
- rotation: [rotationEuler.x, rotationEuler.y, rotationEuler.z],
884
- position: [_position.x + offset.x * worldScale.x, _position.y + offset.y * worldScale.y, _position.z + offset.z * worldScale.z],
885
- scale: [worldScale.x, worldScale.y, worldScale.z]
734
+ if (object && options.colliders !== false) {
735
+ setColliderProps(createColliderPropsFromChildren({
736
+ object: ref.current,
737
+ options,
738
+ ignoreMeshColliders
886
739
  }));
887
740
  }
888
- };
889
-
890
- if (options.includeInvisible) {
891
- object.traverse(colliderFromChild);
892
- } else {
893
- object.traverseVisible(colliderFromChild);
894
- }
895
-
741
+ }, [options.colliders]);
896
742
  return colliderProps;
897
743
  };
898
- const getColliderArgsFromGeometry = (geometry, colliders) => {
899
- switch (colliders) {
900
- case "cuboid":
901
- {
902
- geometry.computeBoundingBox();
903
- const {
904
- boundingBox
905
- } = geometry;
906
- const size = boundingBox.getSize(new three.Vector3());
907
- return {
908
- args: [size.x / 2, size.y / 2, size.z / 2],
909
- offset: boundingBox.getCenter(new three.Vector3())
910
- };
911
- }
744
+ const useRigidBody = (options = {}) => {
745
+ const {
746
+ world,
747
+ rigidBodyStates,
748
+ physicsOptions,
749
+ rigidBodyEvents
750
+ } = useRapier();
751
+ const ref = React.useRef();
752
+ const mergedOptions = React.useMemo(() => {
753
+ return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
754
+ children: undefined
755
+ });
756
+ }, [physicsOptions, options]);
757
+ const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
912
758
 
913
- case "ball":
914
- {
915
- geometry.computeBoundingSphere();
916
- const {
917
- boundingSphere
918
- } = geometry;
919
- const radius = boundingSphere.radius;
920
- return {
921
- args: [radius],
922
- offset: boundingSphere.center
923
- };
924
- }
759
+ const rigidBodyRef = React.useRef();
760
+ const getRigidBodyRef = React.useRef(() => {
761
+ if (!rigidBodyRef.current) {
762
+ const desc = rigidBodyDescFromOptions(options);
763
+ const rigidBody = world.createRigidBody(desc);
764
+ rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
765
+ }
925
766
 
926
- case "trimesh":
927
- {
928
- var _clonedGeometry$index;
767
+ return rigidBodyRef.current;
768
+ }); // Setup
929
769
 
930
- const clonedGeometry = geometry.index ? geometry.clone() : threeStdlib.mergeVertices(geometry);
931
- return {
932
- args: [clonedGeometry.attributes.position.array, (_clonedGeometry$index = clonedGeometry.index) === null || _clonedGeometry$index === void 0 ? void 0 : _clonedGeometry$index.array],
933
- offset: new three.Vector3()
934
- };
935
- }
770
+ React.useEffect(() => {
771
+ const rigidBody = getRigidBodyRef.current();
772
+ rigidBodyRef.current = rigidBody;
936
773
 
937
- case "hull":
938
- {
939
- const g = geometry.clone();
940
- return {
941
- args: [g.attributes.position.array],
942
- offset: new three.Vector3()
943
- };
944
- }
945
- }
774
+ if (!ref.current) {
775
+ ref.current = new three.Object3D();
776
+ }
946
777
 
947
- return {
948
- args: [],
949
- offset: new three.Vector3()
950
- };
951
- };
952
- const useColliderEvents = (collidersRef, props, events) => {
953
- const {
954
- onCollisionEnter,
955
- onCollisionExit,
956
- onIntersectionEnter,
957
- onIntersectionExit,
958
- onContactForce
959
- } = props;
960
- React.useEffect(() => {
961
- var _collidersRef$current;
778
+ rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
779
+ rigidBody,
780
+ object: ref.current
781
+ }));
782
+ return () => {
783
+ world.removeRigidBody(rigidBody);
784
+ rigidBodyStates.delete(rigidBody.handle);
785
+ rigidBodyRef.current = undefined;
786
+ };
787
+ }, []);
788
+ useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
789
+ useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
790
+ const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
791
+ return [ref, api, childColliderProps];
792
+ }; // Joints
962
793
 
963
- (_collidersRef$current = collidersRef.current) === null || _collidersRef$current === void 0 ? void 0 : _collidersRef$current.forEach(collider => {
964
- const hasCollisionEvent = !!(onCollisionEnter || onCollisionExit || onIntersectionEnter || onIntersectionExit);
965
- const hasContactForceEvent = !!onContactForce;
794
+ const useImpulseJoint = (body1, body2, params) => {
795
+ const {
796
+ world
797
+ } = useRapier();
798
+ const jointRef = React.useRef();
799
+ const getJointRef = React.useRef(() => {
800
+ if (!jointRef.current) {
801
+ let rb1;
802
+ let rb2;
966
803
 
967
- if (hasCollisionEvent && hasContactForceEvent) {
968
- collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS | rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
969
- } else if (hasCollisionEvent) {
970
- collider.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
971
- } else if (hasContactForceEvent) {
972
- collider.setActiveEvents(rapier3dCompat.ActiveEvents.CONTACT_FORCE_EVENTS);
804
+ if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
805
+ rb1 = world.getRigidBody(body1.current.handle);
806
+ rb2 = world.getRigidBody(body2.current.handle);
807
+ const newJoint = world.createImpulseJoint(params, rb1, rb2);
808
+ jointRef.current = newJoint;
973
809
  }
810
+ }
974
811
 
975
- events.set(collider.handle, {
976
- onCollisionEnter,
977
- onCollisionExit,
978
- onIntersectionEnter,
979
- onIntersectionExit,
980
- onContactForce
981
- });
982
- });
812
+ return jointRef.current;
813
+ });
814
+ React.useEffect(() => {
815
+ const joint = getJointRef.current();
983
816
  return () => {
984
- var _collidersRef$current2;
985
-
986
- (_collidersRef$current2 = collidersRef.current) === null || _collidersRef$current2 === void 0 ? void 0 : _collidersRef$current2.forEach(collider => events.delete(collider.handle));
817
+ if (joint) {
818
+ world.removeImpulseJoint(joint);
819
+ jointRef.current = undefined;
820
+ }
987
821
  };
988
- }, [onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit, onContactForce]);
822
+ }, []);
823
+ const api = React.useMemo(() => createJointApi(getJointRef), []);
824
+ return api;
989
825
  };
826
+ /**
827
+ *
828
+ * A fixed joint ensures that two rigid-bodies don't move relative to each other.
829
+ * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
830
+ * The fixed-joint makes these frames coincide in world-space.
831
+ */
990
832
 
991
- const rigidBodyDescFromOptions = options => {
992
- const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
993
- const desc = new rapier3dCompat.RigidBodyDesc(type);
994
- return desc;
833
+ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
834
+ const {
835
+ rapier
836
+ } = useRapier();
837
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
838
+ w: 1
839
+ }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
840
+ w: 1
841
+ })));
995
842
  };
996
- const createRigidBodyState = ({
997
- rigidBody,
998
- object,
999
- setMatrix,
1000
- getMatrix,
1001
- worldScale
1002
- }) => {
1003
- object.updateWorldMatrix(true, false);
1004
- const invertedWorldMatrix = object.parent.matrixWorld.clone().invert();
1005
- return {
1006
- object,
1007
- rigidBody,
1008
- invertedWorldMatrix,
1009
- setMatrix: setMatrix ? setMatrix : matrix => {
1010
- object.matrix.copy(matrix);
1011
- },
1012
- getMatrix: getMatrix ? getMatrix : matrix => matrix.copy(object.matrix),
1013
- scale: worldScale || object.getWorldScale(_scale).clone(),
1014
- isSleeping: false
1015
- };
843
+ /**
844
+ * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
845
+ * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
846
+ * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
847
+ * points that need to coincide on the local-space of each rigid-body.
848
+ */
849
+
850
+ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
851
+ const {
852
+ rapier
853
+ } = useRapier();
854
+ return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
1016
855
  };
1017
- const mutableRigidBodyOptions = {
1018
- gravityScale: (rb, value) => {
1019
- rb.setGravityScale(value, true);
1020
- },
1021
- linearDamping: (rb, value) => {
1022
- rb.setLinearDamping(value);
1023
- },
1024
- angularDamping: (rb, value) => {
1025
- rb.setAngularDamping(value);
1026
- },
1027
- enabledRotations: (rb, [x, y, z]) => {
1028
- rb.setEnabledRotations(x, y, z, true);
1029
- },
1030
- enabledTranslations: (rb, [x, y, z]) => {
1031
- rb.setEnabledTranslations(x, y, z, true);
1032
- },
1033
- angularVelocity: (rb, [x, y, z]) => {
1034
- rb.setAngvel({
1035
- x,
1036
- y,
1037
- z
1038
- }, true);
1039
- },
1040
- linearVelocity: (rb, [x, y, z]) => {
1041
- rb.setLinvel({
1042
- x,
1043
- y,
1044
- z
1045
- }, true);
1046
- },
1047
- ccd: (rb, value) => {
1048
- rb.enableCcd(value);
1049
- },
1050
- userData: (rb, value) => {
1051
- rb.userData = value;
1052
- },
1053
- position: () => {},
1054
- rotation: () => {},
1055
- quaternion: () => {},
1056
- scale: () => {}
856
+ /**
857
+ * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
858
+ * rotations along one axis. This is typically used to simulate wheels, fans, etc.
859
+ * They are characterized by one local anchor as well as one local axis on each rigid-body.
860
+ */
861
+
862
+ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
863
+ const {
864
+ rapier
865
+ } = useRapier();
866
+ return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
1057
867
  };
1058
- const mutableRigidBodyOptionKeys = Object.keys(mutableRigidBodyOptions);
1059
- const setRigidBodyOptions = (rigidBody, options, states, updateTranslations = true) => {
1060
- if (!rigidBody) {
1061
- return;
1062
- }
868
+ /**
869
+ * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
870
+ * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
871
+ * local tangent axis can be specified for each rigid-body.
872
+ */
1063
873
 
1064
- const state = states.get(rigidBody.handle);
874
+ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
875
+ const {
876
+ rapier
877
+ } = useRapier();
878
+ return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
879
+ };
1065
880
 
1066
- if (state) {
1067
- if (updateTranslations) {
1068
- state.object.updateWorldMatrix(true, false);
881
+ const calcForceByType = {
882
+ static: (s, m2, r, d, G) => s,
883
+ linear: (s, m2, r, d, G) => s * (d / r),
884
+ newtonian: (s, m2, r, d, G) => G * s * m2 / Math.pow(d, 2)
885
+ };
886
+ const applyAttractorForceOnRigidBody = (rigidBody, {
887
+ object,
888
+ strength,
889
+ range,
890
+ gravitationalConstant,
891
+ collisionGroups,
892
+ type
893
+ }) => {
894
+ const rbPosition = rigidBody.translation();
895
+
896
+ _position.set(rbPosition.x, rbPosition.y, rbPosition.z);
897
+
898
+ const worldPosition = object.getWorldPosition(new three.Vector3());
899
+ const distance = worldPosition.distanceTo(_position);
900
+
901
+ if (distance < range) {
902
+ let force = calcForceByType[type](strength, rigidBody.mass(), range, distance, gravitationalConstant); // Prevent wild forces when Attractors collide
1069
903
 
1070
- _matrix4.copy(state.object.matrixWorld).decompose(_position, _rotation, _scale);
904
+ force = force === Infinity ? strength : force; // Naively test if the rigidBody contains a collider in one of the collision groups
1071
905
 
1072
- rigidBody.setTranslation(_position, false);
1073
- rigidBody.setRotation(_rotation, false);
1074
- }
906
+ let isRigidBodyInCollisionGroup = collisionGroups === undefined ? true : false;
1075
907
 
1076
- mutableRigidBodyOptionKeys.forEach(key => {
1077
- if (key in options) {
1078
- mutableRigidBodyOptions[key](rigidBody, options[key]);
1079
- }
1080
- });
1081
- }
1082
- };
1083
- const useUpdateRigidBodyOptions = (rigidBodyRef, props, states, updateTranslations = true) => {
1084
- // TODO: Improve this, split each prop into its own effect
1085
- const mutablePropsAsFlatArray = React.useMemo(() => mutableRigidBodyOptionKeys.flatMap(key => {
1086
- return vectorToTuple(props[key]);
1087
- }), [props]);
1088
- React.useEffect(() => {
1089
- if (Array.isArray(rigidBodyRef.current)) {
1090
- for (const rigidBody of rigidBodyRef.current) {
1091
- setRigidBodyOptions(rigidBody, props, states, updateTranslations);
908
+ if (collisionGroups !== undefined) {
909
+ for (let i = 0; i < rigidBody.numColliders(); i++) {
910
+ const collider = rigidBody.collider(i);
911
+ const colliderCollisionGroups = collider.collisionGroups();
912
+
913
+ if ((collisionGroups >> 16 & colliderCollisionGroups) != 0 && (colliderCollisionGroups >> 16 & collisionGroups) != 0) {
914
+ isRigidBodyInCollisionGroup = true;
915
+ break;
916
+ }
1092
917
  }
1093
- } else if (rigidBodyRef.current) {
1094
- setRigidBodyOptions(rigidBodyRef.current, props, states, updateTranslations);
1095
918
  }
1096
- }, mutablePropsAsFlatArray);
919
+
920
+ if (isRigidBodyInCollisionGroup) {
921
+ _vector3.set(0, 0, 0).subVectors(worldPosition, _position).normalize().multiplyScalar(force);
922
+
923
+ rigidBody.applyImpulse(_vector3, true);
924
+ }
925
+ }
1097
926
  };
1098
- const useRigidBodyEvents = (rigidBodyRef, props, events) => {
927
+ const Attractor = /*#__PURE__*/React.memo(props => {
1099
928
  const {
1100
- onWake,
1101
- onSleep,
1102
- onCollisionEnter,
1103
- onCollisionExit,
1104
- onIntersectionEnter,
1105
- onIntersectionExit
929
+ position = [0, 0, 0],
930
+ strength = 1,
931
+ range = 10,
932
+ type = "static",
933
+ gravitationalConstant = 6.673e-11,
934
+ collisionGroups
1106
935
  } = props;
1107
- const eventHandlers = {
1108
- onWake,
1109
- onSleep,
1110
- onCollisionEnter,
1111
- onCollisionExit,
1112
- onIntersectionEnter,
1113
- onIntersectionExit
1114
- };
936
+ const {
937
+ attractorStates
938
+ } = useRapier();
939
+ const object = React.useRef(null);
1115
940
  React.useEffect(() => {
1116
- if (Array.isArray(rigidBodyRef.current)) {
1117
- for (const rigidBody of rigidBodyRef.current) {
1118
- events.set(rigidBody.handle, eventHandlers);
1119
- }
1120
- } else if (rigidBodyRef.current) {
1121
- events.set(rigidBodyRef.current.handle, eventHandlers);
941
+ var _object$current;
942
+
943
+ let uuid = ((_object$current = object.current) === null || _object$current === void 0 ? void 0 : _object$current.uuid) || "_";
944
+
945
+ if (object.current) {
946
+ attractorStates.set(uuid, {
947
+ object: object.current,
948
+ strength,
949
+ range,
950
+ type,
951
+ gravitationalConstant,
952
+ collisionGroups
953
+ });
1122
954
  }
1123
955
 
1124
956
  return () => {
1125
- if (Array.isArray(rigidBodyRef.current)) {
1126
- for (const rigidBody of rigidBodyRef.current) {
1127
- events.delete(rigidBody.handle);
1128
- }
1129
- } else if (rigidBodyRef.current) {
1130
- events.delete(rigidBodyRef.current.handle);
1131
- }
957
+ attractorStates.delete(uuid);
1132
958
  };
1133
- }, [onWake, onSleep, onCollisionEnter, onCollisionExit, onIntersectionEnter, onIntersectionExit]);
959
+ }, [props]);
960
+ return /*#__PURE__*/React__default["default"].createElement("object3D", {
961
+ ref: object,
962
+ position: position
963
+ });
964
+ });
965
+
966
+ const RapierContext = /*#__PURE__*/React.createContext(undefined);
967
+
968
+ const getCollisionPayloadFromSource = (target, other) => {
969
+ var _target$collider$stat, _target$rigidBody$sta, _other$collider$state, _other$rigidBody$stat, _other$collider$state2, _other$rigidBody$stat2;
970
+
971
+ return {
972
+ target: {
973
+ rigidBody: target.rigidBody.object,
974
+ collider: target.collider.object,
975
+ colliderObject: (_target$collider$stat = target.collider.state) === null || _target$collider$stat === void 0 ? void 0 : _target$collider$stat.object,
976
+ rigidBodyObject: (_target$rigidBody$sta = target.rigidBody.state) === null || _target$rigidBody$sta === void 0 ? void 0 : _target$rigidBody$sta.object
977
+ },
978
+ other: {
979
+ rigidBody: other.rigidBody.object,
980
+ collider: other.collider.object,
981
+ colliderObject: (_other$collider$state = other.collider.state) === null || _other$collider$state === void 0 ? void 0 : _other$collider$state.object,
982
+ rigidBodyObject: (_other$rigidBody$stat = other.rigidBody.state) === null || _other$rigidBody$stat === void 0 ? void 0 : _other$rigidBody$stat.object
983
+ },
984
+ rigidBody: other.rigidBody.object,
985
+ collider: other.collider.object,
986
+ colliderObject: (_other$collider$state2 = other.collider.state) === null || _other$collider$state2 === void 0 ? void 0 : _other$collider$state2.object,
987
+ rigidBodyObject: (_other$rigidBody$stat2 = other.rigidBody.state) === null || _other$rigidBody$stat2 === void 0 ? void 0 : _other$rigidBody$stat2.object
988
+ };
1134
989
  };
1135
990
 
1136
- const useRapier = () => {
1137
- return React.useContext(RapierContext);
991
+ const importRapier = async () => {
992
+ let r = await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('@dimforge/rapier3d-compat')); });
993
+ await r.init();
994
+ return r;
1138
995
  };
1139
- const useChildColliderProps = (ref, options, ignoreMeshColliders = true) => {
1140
- const [colliderProps, setColliderProps] = React.useState([]);
996
+
997
+ const Physics = ({
998
+ colliders: _colliders = "cuboid",
999
+ gravity: _gravity = [0, -9.81, 0],
1000
+ children,
1001
+ timeStep: _timeStep = 1 / 60,
1002
+ paused: _paused = false,
1003
+ updatePriority,
1004
+ interpolate: _interpolate = true
1005
+ }) => {
1006
+ const rapier = useAsset.useAsset(importRapier);
1007
+ const worldRef = React.useRef();
1008
+ const getWorldRef = React.useRef(() => {
1009
+ if (!worldRef.current) {
1010
+ const world = new rapier.World(vectorArrayToVector3(_gravity));
1011
+ worldRef.current = world;
1012
+ }
1013
+
1014
+ return worldRef.current;
1015
+ });
1016
+ const [rigidBodyStates] = React.useState(() => new Map());
1017
+ const [colliderStates] = React.useState(() => new Map());
1018
+ const [rigidBodyEvents] = React.useState(() => new Map());
1019
+ const [colliderEvents] = React.useState(() => new Map());
1020
+ const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false));
1021
+ const [attractorStates] = React.useState(() => new Map()); // Init world
1022
+
1141
1023
  React.useEffect(() => {
1142
- const object = ref.current;
1024
+ const world = getWorldRef.current();
1025
+ return () => {
1026
+ if (world) {
1027
+ world.free();
1028
+ worldRef.current = undefined;
1029
+ }
1030
+ };
1031
+ }, []); // Update gravity
1143
1032
 
1144
- if (object && options.colliders !== false) {
1145
- setColliderProps(createColliderPropsFromChildren({
1146
- object: ref.current,
1147
- options,
1148
- ignoreMeshColliders
1149
- }));
1033
+ React.useEffect(() => {
1034
+ const world = worldRef.current;
1035
+
1036
+ if (world) {
1037
+ world.gravity = vectorArrayToVector3(_gravity);
1150
1038
  }
1151
- }, [options.colliders]);
1152
- return colliderProps;
1153
- };
1154
- const useRigidBody = (options = {}) => {
1155
- const {
1156
- world,
1157
- rigidBodyStates,
1158
- physicsOptions,
1159
- rigidBodyEvents
1160
- } = useRapier();
1161
- const ref = React.useRef();
1162
- const mergedOptions = React.useMemo(() => {
1163
- return _objectSpread2(_objectSpread2(_objectSpread2({}, physicsOptions), options), {}, {
1164
- children: undefined
1039
+ }, [_gravity]);
1040
+ const getSourceFromColliderHandle = React.useCallback(handle => {
1041
+ const world = worldRef.current;
1042
+
1043
+ if (world) {
1044
+ var _collider$parent;
1045
+
1046
+ const collider = world.getCollider(handle);
1047
+ const colEvents = colliderEvents.get(handle);
1048
+ const colliderState = colliderStates.get(handle);
1049
+ const rigidBodyHandle = collider === null || collider === void 0 ? void 0 : (_collider$parent = collider.parent()) === null || _collider$parent === void 0 ? void 0 : _collider$parent.handle;
1050
+ const rigidBody = rigidBodyHandle !== undefined ? world.getRigidBody(rigidBodyHandle) : undefined;
1051
+ const rbEvents = rigidBody && rigidBodyHandle !== undefined ? rigidBodyEvents.get(rigidBodyHandle) : undefined;
1052
+ const rigidBodyState = rigidBodyHandle !== undefined ? rigidBodyStates.get(rigidBodyHandle) : undefined;
1053
+ const source = {
1054
+ collider: {
1055
+ object: collider,
1056
+ events: colEvents,
1057
+ state: colliderState
1058
+ },
1059
+ rigidBody: {
1060
+ object: rigidBody,
1061
+ events: rbEvents,
1062
+ state: rigidBodyState
1063
+ }
1064
+ };
1065
+ return source;
1066
+ }
1067
+ }, []);
1068
+ const [steppingState] = React.useState({
1069
+ previousState: {},
1070
+ accumulator: 0
1071
+ });
1072
+ const step = React.useCallback(dt => {
1073
+ const world = worldRef.current;
1074
+ if (!world) return;
1075
+ /* Check if the timestep is supposed to be variable. We'll do this here
1076
+ once so we don't have to string-check every frame. */
1077
+
1078
+ const timeStepVariable = _timeStep === "vary";
1079
+ /**
1080
+ * Fixed timeStep simulation progression
1081
+ * @see https://gafferongames.com/post/fix_your_timestep/
1082
+ */
1083
+
1084
+ const clampedDelta = three.MathUtils.clamp(dt, 0, 0.2);
1085
+
1086
+ if (timeStepVariable) {
1087
+ world.timestep = clampedDelta;
1088
+ world.step(eventQueue);
1089
+ } else {
1090
+ world.timestep = _timeStep; // don't step time forwards if paused
1091
+ // Increase accumulator
1092
+
1093
+ steppingState.accumulator += clampedDelta;
1094
+
1095
+ while (steppingState.accumulator >= _timeStep) {
1096
+ world.forEachRigidBody(body => {
1097
+ // Set up previous state
1098
+ // needed for accurate interpolations if the world steps more than once
1099
+ if (_interpolate) {
1100
+ steppingState.previousState = {};
1101
+ steppingState.previousState[body.handle] = {
1102
+ position: body.translation(),
1103
+ rotation: body.rotation()
1104
+ };
1105
+ } // Apply attractors
1106
+
1107
+
1108
+ attractorStates.forEach(attractorState => {
1109
+ applyAttractorForceOnRigidBody(body, attractorState);
1110
+ });
1111
+ });
1112
+ world.step(eventQueue);
1113
+ steppingState.accumulator -= _timeStep;
1114
+ }
1115
+ }
1116
+
1117
+ const interpolationAlpha = timeStepVariable || !_interpolate || _paused ? 1 : steppingState.accumulator / _timeStep; // Update meshes
1118
+
1119
+ rigidBodyStates.forEach((state, handle) => {
1120
+ const rigidBody = world.getRigidBody(handle);
1121
+ const events = rigidBodyEvents.get(handle);
1122
+
1123
+ if (events !== null && events !== void 0 && events.onSleep || events !== null && events !== void 0 && events.onWake) {
1124
+ if (rigidBody.isSleeping() && !state.isSleeping) {
1125
+ var _events$onSleep;
1126
+
1127
+ events === null || events === void 0 ? void 0 : (_events$onSleep = events.onSleep) === null || _events$onSleep === void 0 ? void 0 : _events$onSleep.call(events);
1128
+ }
1129
+
1130
+ if (!rigidBody.isSleeping() && state.isSleeping) {
1131
+ var _events$onWake;
1132
+
1133
+ events === null || events === void 0 ? void 0 : (_events$onWake = events.onWake) === null || _events$onWake === void 0 ? void 0 : _events$onWake.call(events);
1134
+ }
1135
+
1136
+ state.isSleeping = rigidBody.isSleeping();
1137
+ }
1138
+
1139
+ if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
1140
+ return;
1141
+ } // New states
1142
+
1143
+
1144
+ let t = rigidBody.translation();
1145
+ let r = rigidBody.rotation();
1146
+ let previousState = steppingState.previousState[handle];
1147
+
1148
+ if (previousState) {
1149
+ // Get previous simulated world position
1150
+ _matrix4.compose(previousState.position, rapierQuaternionToQuaternion(previousState.rotation), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale); // Apply previous tick position
1151
+
1152
+
1153
+ if (!(state.object instanceof three.InstancedMesh)) {
1154
+ state.object.position.copy(_position);
1155
+ state.object.quaternion.copy(_rotation);
1156
+ }
1157
+ } // Get new position
1158
+
1159
+
1160
+ _matrix4.compose(t, rapierQuaternionToQuaternion(r), state.scale).premultiply(state.invertedWorldMatrix).decompose(_position, _rotation, _scale);
1161
+
1162
+ if (state.object instanceof three.InstancedMesh) {
1163
+ state.setMatrix(_matrix4);
1164
+ state.object.instanceMatrix.needsUpdate = true;
1165
+ } else {
1166
+ // Interpolate to new position
1167
+ state.object.position.lerp(_position, interpolationAlpha);
1168
+ state.object.quaternion.slerp(_rotation, interpolationAlpha);
1169
+ }
1165
1170
  });
1166
- }, [physicsOptions, options]);
1167
- const childColliderProps = useChildColliderProps(ref, mergedOptions); // Create rigidbody
1171
+ eventQueue.drainCollisionEvents((handle1, handle2, started) => {
1172
+ const source1 = getSourceFromColliderHandle(handle1);
1173
+ const source2 = getSourceFromColliderHandle(handle2); // Collision Events
1174
+
1175
+ if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
1176
+ return;
1177
+ }
1178
+
1179
+ const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
1180
+ const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
1168
1181
 
1169
- const rigidBodyRef = React.useRef();
1170
- const getRigidBodyRef = React.useRef(() => {
1171
- if (!rigidBodyRef.current) {
1172
- const desc = rigidBodyDescFromOptions(options);
1173
- const rigidBody = world.createRigidBody(desc);
1174
- rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
1175
- }
1182
+ if (started) {
1183
+ world.contactPair(source1.collider.object, source2.collider.object, (manifold, flipped) => {
1184
+ var _source1$rigidBody$ev, _source1$rigidBody$ev2, _source2$rigidBody$ev, _source2$rigidBody$ev2, _source1$collider$eve, _source1$collider$eve2, _source2$collider$eve, _source2$collider$eve2;
1176
1185
 
1177
- return rigidBodyRef.current;
1178
- }); // Setup
1186
+ /* RigidBody events */
1187
+ (_source1$rigidBody$ev = source1.rigidBody.events) === null || _source1$rigidBody$ev === void 0 ? void 0 : (_source1$rigidBody$ev2 = _source1$rigidBody$ev.onCollisionEnter) === null || _source1$rigidBody$ev2 === void 0 ? void 0 : _source1$rigidBody$ev2.call(_source1$rigidBody$ev, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
1188
+ manifold,
1189
+ flipped
1190
+ }));
1191
+ (_source2$rigidBody$ev = source2.rigidBody.events) === null || _source2$rigidBody$ev === void 0 ? void 0 : (_source2$rigidBody$ev2 = _source2$rigidBody$ev.onCollisionEnter) === null || _source2$rigidBody$ev2 === void 0 ? void 0 : _source2$rigidBody$ev2.call(_source2$rigidBody$ev, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
1192
+ manifold,
1193
+ flipped
1194
+ }));
1195
+ /* Collider events */
1179
1196
 
1180
- React.useEffect(() => {
1181
- const rigidBody = getRigidBodyRef.current();
1182
- rigidBodyRef.current = rigidBody;
1197
+ (_source1$collider$eve = source1.collider.events) === null || _source1$collider$eve === void 0 ? void 0 : (_source1$collider$eve2 = _source1$collider$eve.onCollisionEnter) === null || _source1$collider$eve2 === void 0 ? void 0 : _source1$collider$eve2.call(_source1$collider$eve, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
1198
+ manifold,
1199
+ flipped
1200
+ }));
1201
+ (_source2$collider$eve = source2.collider.events) === null || _source2$collider$eve === void 0 ? void 0 : (_source2$collider$eve2 = _source2$collider$eve.onCollisionEnter) === null || _source2$collider$eve2 === void 0 ? void 0 : _source2$collider$eve2.call(_source2$collider$eve, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
1202
+ manifold,
1203
+ flipped
1204
+ }));
1205
+ });
1206
+ } else {
1207
+ var _source1$rigidBody$ev3, _source1$rigidBody$ev4, _source2$rigidBody$ev3, _source2$rigidBody$ev4, _source1$collider$eve3, _source1$collider$eve4, _source2$collider$eve3, _source2$collider$eve4;
1183
1208
 
1184
- if (!ref.current) {
1185
- ref.current = new three.Object3D();
1186
- }
1209
+ (_source1$rigidBody$ev3 = source1.rigidBody.events) === null || _source1$rigidBody$ev3 === void 0 ? void 0 : (_source1$rigidBody$ev4 = _source1$rigidBody$ev3.onCollisionExit) === null || _source1$rigidBody$ev4 === void 0 ? void 0 : _source1$rigidBody$ev4.call(_source1$rigidBody$ev3, collisionPayload1);
1210
+ (_source2$rigidBody$ev3 = source2.rigidBody.events) === null || _source2$rigidBody$ev3 === void 0 ? void 0 : (_source2$rigidBody$ev4 = _source2$rigidBody$ev3.onCollisionExit) === null || _source2$rigidBody$ev4 === void 0 ? void 0 : _source2$rigidBody$ev4.call(_source2$rigidBody$ev3, collisionPayload2);
1211
+ (_source1$collider$eve3 = source1.collider.events) === null || _source1$collider$eve3 === void 0 ? void 0 : (_source1$collider$eve4 = _source1$collider$eve3.onCollisionExit) === null || _source1$collider$eve4 === void 0 ? void 0 : _source1$collider$eve4.call(_source1$collider$eve3, collisionPayload1);
1212
+ (_source2$collider$eve3 = source2.collider.events) === null || _source2$collider$eve3 === void 0 ? void 0 : (_source2$collider$eve4 = _source2$collider$eve3.onCollisionExit) === null || _source2$collider$eve4 === void 0 ? void 0 : _source2$collider$eve4.call(_source2$collider$eve3, collisionPayload2);
1213
+ } // Sensor Intersections
1187
1214
 
1188
- rigidBodyStates.set(rigidBody.handle, createRigidBodyState({
1189
- rigidBody,
1190
- object: ref.current
1191
- }));
1192
- return () => {
1193
- world.removeRigidBody(rigidBody);
1194
- rigidBodyStates.delete(rigidBody.handle);
1195
- rigidBodyRef.current = undefined;
1196
- };
1197
- }, []);
1198
- useUpdateRigidBodyOptions(rigidBodyRef, mergedOptions, rigidBodyStates);
1199
- useRigidBodyEvents(rigidBodyRef, mergedOptions, rigidBodyEvents);
1200
- const api = React.useMemo(() => createRigidBodyApi(getRigidBodyRef), []);
1201
- return [ref, api, childColliderProps];
1202
- }; // Joints
1203
1215
 
1204
- const useImpulseJoint = (body1, body2, params) => {
1205
- const {
1206
- world
1207
- } = useRapier();
1208
- const jointRef = React.useRef();
1209
- const getJointRef = React.useRef(() => {
1210
- if (!jointRef.current) {
1211
- let rb1;
1212
- let rb2;
1216
+ if (started) {
1217
+ if (world.intersectionPair(source1.collider.object, source2.collider.object)) {
1218
+ var _source1$rigidBody$ev5, _source1$rigidBody$ev6, _source2$rigidBody$ev5, _source2$rigidBody$ev6, _source1$collider$eve5, _source1$collider$eve6, _source2$collider$eve5, _source2$collider$eve6;
1213
1219
 
1214
- if ("current" in body1 && body1.current && "current" in body2 && body2.current) {
1215
- rb1 = world.getRigidBody(body1.current.handle);
1216
- rb2 = world.getRigidBody(body2.current.handle);
1217
- const newJoint = world.createImpulseJoint(params, rb1, rb2);
1218
- jointRef.current = newJoint;
1220
+ (_source1$rigidBody$ev5 = source1.rigidBody.events) === null || _source1$rigidBody$ev5 === void 0 ? void 0 : (_source1$rigidBody$ev6 = _source1$rigidBody$ev5.onIntersectionEnter) === null || _source1$rigidBody$ev6 === void 0 ? void 0 : _source1$rigidBody$ev6.call(_source1$rigidBody$ev5, collisionPayload1);
1221
+ (_source2$rigidBody$ev5 = source2.rigidBody.events) === null || _source2$rigidBody$ev5 === void 0 ? void 0 : (_source2$rigidBody$ev6 = _source2$rigidBody$ev5.onIntersectionEnter) === null || _source2$rigidBody$ev6 === void 0 ? void 0 : _source2$rigidBody$ev6.call(_source2$rigidBody$ev5, collisionPayload2);
1222
+ (_source1$collider$eve5 = source1.collider.events) === null || _source1$collider$eve5 === void 0 ? void 0 : (_source1$collider$eve6 = _source1$collider$eve5.onIntersectionEnter) === null || _source1$collider$eve6 === void 0 ? void 0 : _source1$collider$eve6.call(_source1$collider$eve5, collisionPayload1);
1223
+ (_source2$collider$eve5 = source2.collider.events) === null || _source2$collider$eve5 === void 0 ? void 0 : (_source2$collider$eve6 = _source2$collider$eve5.onIntersectionEnter) === null || _source2$collider$eve6 === void 0 ? void 0 : _source2$collider$eve6.call(_source2$collider$eve5, collisionPayload2);
1224
+ }
1225
+ } else {
1226
+ var _source1$rigidBody$ev7, _source1$rigidBody$ev8, _source2$rigidBody$ev7, _source2$rigidBody$ev8, _source1$collider$eve7, _source1$collider$eve8, _source2$collider$eve7, _source2$collider$eve8;
1227
+
1228
+ (_source1$rigidBody$ev7 = source1.rigidBody.events) === null || _source1$rigidBody$ev7 === void 0 ? void 0 : (_source1$rigidBody$ev8 = _source1$rigidBody$ev7.onIntersectionExit) === null || _source1$rigidBody$ev8 === void 0 ? void 0 : _source1$rigidBody$ev8.call(_source1$rigidBody$ev7, collisionPayload1);
1229
+ (_source2$rigidBody$ev7 = source2.rigidBody.events) === null || _source2$rigidBody$ev7 === void 0 ? void 0 : (_source2$rigidBody$ev8 = _source2$rigidBody$ev7.onIntersectionExit) === null || _source2$rigidBody$ev8 === void 0 ? void 0 : _source2$rigidBody$ev8.call(_source2$rigidBody$ev7, collisionPayload2);
1230
+ (_source1$collider$eve7 = source1.collider.events) === null || _source1$collider$eve7 === void 0 ? void 0 : (_source1$collider$eve8 = _source1$collider$eve7.onIntersectionExit) === null || _source1$collider$eve8 === void 0 ? void 0 : _source1$collider$eve8.call(_source1$collider$eve7, collisionPayload1);
1231
+ (_source2$collider$eve7 = source2.collider.events) === null || _source2$collider$eve7 === void 0 ? void 0 : (_source2$collider$eve8 = _source2$collider$eve7.onIntersectionExit) === null || _source2$collider$eve8 === void 0 ? void 0 : _source2$collider$eve8.call(_source2$collider$eve7, collisionPayload2);
1219
1232
  }
1220
- }
1233
+ });
1234
+ eventQueue.drainContactForceEvents(event => {
1235
+ var _source1$rigidBody$ev9, _source1$rigidBody$ev10, _source2$rigidBody$ev9, _source2$rigidBody$ev10, _source1$collider$eve9, _source1$collider$eve10, _source2$collider$eve9, _source2$collider$eve10;
1221
1236
 
1222
- return jointRef.current;
1223
- });
1224
- React.useEffect(() => {
1225
- const joint = getJointRef.current();
1226
- return () => {
1227
- if (joint) {
1228
- world.removeImpulseJoint(joint);
1229
- jointRef.current = undefined;
1237
+ const source1 = getSourceFromColliderHandle(event.collider1());
1238
+ const source2 = getSourceFromColliderHandle(event.collider2()); // Collision Events
1239
+
1240
+ if (!(source1 !== null && source1 !== void 0 && source1.collider.object) || !(source2 !== null && source2 !== void 0 && source2.collider.object)) {
1241
+ return;
1230
1242
  }
1231
- };
1232
- }, []);
1233
- const api = React.useMemo(() => createJointApi(getJointRef), []);
1234
- return api;
1235
- };
1236
- /**
1237
- *
1238
- * A fixed joint ensures that two rigid-bodies don't move relative to each other.
1239
- * Fixed joints are characterized by one local frame (represented by an isometry) on each rigid-body.
1240
- * The fixed-joint makes these frames coincide in world-space.
1241
- */
1242
1243
 
1243
- const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor, body2LocalFrame]) => {
1244
- const {
1245
- rapier
1246
- } = useRapier();
1247
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
1248
- w: 1
1249
- }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
1250
- w: 1
1251
- })));
1244
+ const collisionPayload1 = getCollisionPayloadFromSource(source1, source2);
1245
+ const collisionPayload2 = getCollisionPayloadFromSource(source2, source1);
1246
+ (_source1$rigidBody$ev9 = source1.rigidBody.events) === null || _source1$rigidBody$ev9 === void 0 ? void 0 : (_source1$rigidBody$ev10 = _source1$rigidBody$ev9.onContactForce) === null || _source1$rigidBody$ev10 === void 0 ? void 0 : _source1$rigidBody$ev10.call(_source1$rigidBody$ev9, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
1247
+ totalForce: event.totalForce(),
1248
+ totalForceMagnitude: event.totalForceMagnitude(),
1249
+ maxForceDirection: event.maxForceDirection(),
1250
+ maxForceMagnitude: event.maxForceMagnitude()
1251
+ }));
1252
+ (_source2$rigidBody$ev9 = source2.rigidBody.events) === null || _source2$rigidBody$ev9 === void 0 ? void 0 : (_source2$rigidBody$ev10 = _source2$rigidBody$ev9.onContactForce) === null || _source2$rigidBody$ev10 === void 0 ? void 0 : _source2$rigidBody$ev10.call(_source2$rigidBody$ev9, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
1253
+ totalForce: event.totalForce(),
1254
+ totalForceMagnitude: event.totalForceMagnitude(),
1255
+ maxForceDirection: event.maxForceDirection(),
1256
+ maxForceMagnitude: event.maxForceMagnitude()
1257
+ }));
1258
+ (_source1$collider$eve9 = source1.collider.events) === null || _source1$collider$eve9 === void 0 ? void 0 : (_source1$collider$eve10 = _source1$collider$eve9.onContactForce) === null || _source1$collider$eve10 === void 0 ? void 0 : _source1$collider$eve10.call(_source1$collider$eve9, _objectSpread2(_objectSpread2({}, collisionPayload1), {}, {
1259
+ totalForce: event.totalForce(),
1260
+ totalForceMagnitude: event.totalForceMagnitude(),
1261
+ maxForceDirection: event.maxForceDirection(),
1262
+ maxForceMagnitude: event.maxForceMagnitude()
1263
+ }));
1264
+ (_source2$collider$eve9 = source2.collider.events) === null || _source2$collider$eve9 === void 0 ? void 0 : (_source2$collider$eve10 = _source2$collider$eve9.onContactForce) === null || _source2$collider$eve10 === void 0 ? void 0 : _source2$collider$eve10.call(_source2$collider$eve9, _objectSpread2(_objectSpread2({}, collisionPayload2), {}, {
1265
+ totalForce: event.totalForce(),
1266
+ totalForceMagnitude: event.totalForceMagnitude(),
1267
+ maxForceDirection: event.maxForceDirection(),
1268
+ maxForceMagnitude: event.maxForceMagnitude()
1269
+ }));
1270
+ });
1271
+ }, [_paused, _timeStep, _interpolate]);
1272
+ fiber.useFrame((_, dt) => {
1273
+ if (!_paused) step(dt);
1274
+ }, updatePriority);
1275
+ const api = React.useMemo(() => createWorldApi(getWorldRef), []);
1276
+ const context = React.useMemo(() => ({
1277
+ rapier,
1278
+ world: api,
1279
+ physicsOptions: {
1280
+ colliders: _colliders,
1281
+ gravity: _gravity
1282
+ },
1283
+ rigidBodyStates,
1284
+ colliderStates,
1285
+ rigidBodyEvents,
1286
+ colliderEvents,
1287
+ attractorStates,
1288
+ isPaused: _paused,
1289
+ step
1290
+ }), [_paused, step]);
1291
+ return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
1292
+ value: context
1293
+ }, children);
1252
1294
  };
1253
- /**
1254
- * The spherical joint ensures that two points on the local-spaces of two rigid-bodies always coincide (it prevents any relative
1255
- * translational motion at this points). This is typically used to simulate ragdolls arms, pendulums, etc.
1256
- * They are characterized by one local anchor on each rigid-body. Each anchor represents the location of the
1257
- * points that need to coincide on the local-space of each rigid-body.
1258
- */
1259
1295
 
1260
- const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
1261
- const {
1262
- rapier
1263
- } = useRapier();
1264
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
1265
- };
1266
- /**
1267
- * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
1268
- * rotations along one axis. This is typically used to simulate wheels, fans, etc.
1269
- * They are characterized by one local anchor as well as one local axis on each rigid-body.
1270
- */
1296
+ function _extends() {
1297
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
1298
+ for (var i = 1; i < arguments.length; i++) {
1299
+ var source = arguments[i];
1271
1300
 
1272
- const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
1273
- const {
1274
- rapier
1275
- } = useRapier();
1276
- return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
1277
- };
1278
- /**
1279
- * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
1280
- * It is characterized by one local anchor as well as one local axis on each rigid-body. In 3D, an optional
1281
- * local tangent axis can be specified for each rigid-body.
1282
- */
1301
+ for (var key in source) {
1302
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1303
+ target[key] = source[key];
1304
+ }
1305
+ }
1306
+ }
1283
1307
 
1284
- const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
1285
- const {
1286
- rapier
1287
- } = useRapier();
1288
- return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
1289
- };
1308
+ return target;
1309
+ };
1310
+ return _extends.apply(this, arguments);
1311
+ }
1312
+
1313
+ function _objectWithoutPropertiesLoose(source, excluded) {
1314
+ if (source == null) return {};
1315
+ var target = {};
1316
+ var sourceKeys = Object.keys(source);
1317
+ var key, i;
1318
+
1319
+ for (i = 0; i < sourceKeys.length; i++) {
1320
+ key = sourceKeys[i];
1321
+ if (excluded.indexOf(key) >= 0) continue;
1322
+ target[key] = source[key];
1323
+ }
1324
+
1325
+ return target;
1326
+ }
1327
+
1328
+ function _objectWithoutProperties(source, excluded) {
1329
+ if (source == null) return {};
1330
+ var target = _objectWithoutPropertiesLoose(source, excluded);
1331
+ var key, i;
1332
+
1333
+ if (Object.getOwnPropertySymbols) {
1334
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
1335
+
1336
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
1337
+ key = sourceSymbolKeys[i];
1338
+ if (excluded.indexOf(key) >= 0) continue;
1339
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
1340
+ target[key] = source[key];
1341
+ }
1342
+ }
1343
+
1344
+ return target;
1345
+ }
1290
1346
 
1291
1347
  // Colliders
1292
1348
  const AnyCollider = /*#__PURE__*/React.memo( /*#__PURE__*/React__default["default"].forwardRef((props, forwardedRef) => {
@@ -1414,6 +1470,15 @@ const ConvexHullCollider = /*#__PURE__*/React__default["default"].forwardRef((pr
1414
1470
  ref: ref
1415
1471
  }));
1416
1472
  });
1473
+ CuboidCollider.displayName = "CuboidCollider";
1474
+ RoundCuboidCollider.displayName = "RoundCuboidCollider";
1475
+ BallCollider.displayName = "BallCollider";
1476
+ CapsuleCollider.displayName = "CapsuleCollider";
1477
+ HeightfieldCollider.displayName = "HeightfieldCollider";
1478
+ TrimeshCollider.displayName = "TrimeshCollider";
1479
+ ConeCollider.displayName = "ConeCollider";
1480
+ CylinderCollider.displayName = "CylinderCollider";
1481
+ ConvexHullCollider.displayName = "ConvexHullCollider";
1417
1482
 
1418
1483
  const _excluded$1 = ["children", "type", "position", "rotation", "scale", "quaternion"];
1419
1484
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
@@ -1449,6 +1514,7 @@ const RigidBody = /*#__PURE__*/React.memo( /*#__PURE__*/React.forwardRef((props,
1449
1514
  key: index
1450
1515
  }, colliderProps)))));
1451
1516
  }));
1517
+ RigidBody.displayName = "RigidBody";
1452
1518
 
1453
1519
  const MeshCollider = props => {
1454
1520
  const {
@@ -1479,26 +1545,96 @@ const MeshCollider = props => {
1479
1545
  key: index
1480
1546
  }, colliderProps))));
1481
1547
  };
1548
+ MeshCollider.displayName = "MeshCollider";
1549
+
1550
+ function mapsEqual(map1, map2) {
1551
+ var testVal;
1552
+
1553
+ if (map1.size !== map2.size) {
1554
+ return false;
1555
+ }
1556
+
1557
+ for (var [key, val] of map1) {
1558
+ testVal = map2.get(key);
1559
+
1560
+ if (testVal !== val || testVal === undefined && !map2.has(key)) {
1561
+ return false;
1562
+ }
1563
+ }
1564
+
1565
+ return true;
1566
+ }
1567
+
1568
+ const AttractorHelper = props => {
1569
+ const {
1570
+ scene
1571
+ } = fiber.useThree();
1572
+ const ref = React.useRef(null);
1573
+ const normalsHelper = React.useRef();
1574
+ const color = props.strength > 0 ? 0x0000ff : 0xff0000;
1575
+ React.useEffect(() => {
1576
+ if (ref.current) {
1577
+ normalsHelper.current = new threeStdlib.VertexNormalsHelper(ref.current, props.range, color);
1578
+ normalsHelper.current.frustumCulled = false;
1579
+ scene.add(normalsHelper.current);
1580
+ }
1581
+
1582
+ return () => {
1583
+ if (normalsHelper.current) {
1584
+ scene.remove(normalsHelper.current);
1585
+ }
1586
+ };
1587
+ }, [props]);
1588
+ fiber.useFrame(() => {
1589
+ if (ref.current) {
1590
+ var _normalsHelper$curren;
1591
+
1592
+ const worldPosition = props.object.getWorldPosition(_vector3);
1593
+ ref.current.position.copy(worldPosition);
1594
+ (_normalsHelper$curren = normalsHelper.current) === null || _normalsHelper$curren === void 0 ? void 0 : _normalsHelper$curren.update();
1595
+ }
1596
+ });
1597
+ return /*#__PURE__*/React__default["default"].createElement("mesh", {
1598
+ ref: ref,
1599
+ position: props.object.position,
1600
+ frustumCulled: false
1601
+ }, /*#__PURE__*/React__default["default"].createElement("sphereGeometry", {
1602
+ args: [0.2, 6, 6]
1603
+ }), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
1604
+ color: color,
1605
+ wireframe: true
1606
+ }));
1607
+ };
1482
1608
 
1483
1609
  const Debug = () => {
1484
1610
  const {
1485
- world
1611
+ world,
1612
+ attractorStates
1486
1613
  } = useRapier();
1487
1614
  const ref = React.useRef(null);
1615
+ const [attractors, setAttractors] = React.useState([]);
1616
+ const currMap = React.useRef(new Map());
1488
1617
  fiber.useFrame(() => {
1489
1618
  const mesh = ref.current;
1490
1619
  if (!mesh) return;
1491
1620
  const buffers = world.debugRender();
1492
1621
  mesh.geometry.setAttribute("position", new three.BufferAttribute(buffers.vertices, 3));
1493
- mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4));
1622
+ mesh.geometry.setAttribute("color", new three.BufferAttribute(buffers.colors, 4)); // Update attractors
1623
+
1624
+ if (!mapsEqual(currMap.current, attractorStates)) {
1625
+ setAttractors([...attractorStates.values()]);
1626
+ currMap.current = new Map(attractorStates);
1627
+ }
1494
1628
  });
1495
- return /*#__PURE__*/React__default["default"].createElement("lineSegments", {
1629
+ return /*#__PURE__*/React__default["default"].createElement("group", null, /*#__PURE__*/React__default["default"].createElement("lineSegments", {
1496
1630
  ref: ref,
1497
1631
  frustumCulled: false
1498
1632
  }, /*#__PURE__*/React__default["default"].createElement("lineBasicMaterial", {
1499
1633
  color: 0xffffff,
1500
1634
  vertexColors: true
1501
- }), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null));
1635
+ }), /*#__PURE__*/React__default["default"].createElement("bufferGeometry", null)), attractors.map((attractor, i) => /*#__PURE__*/React__default["default"].createElement(AttractorHelper, _extends({
1636
+ key: attractor.object.uuid
1637
+ }, attractor))));
1502
1638
  };
1503
1639
 
1504
1640
  const _excluded = ["positions", "rotations", "children"];
@@ -1611,6 +1747,7 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1611
1747
  key: index
1612
1748
  }, colliderProps)))));
1613
1749
  });
1750
+ InstancedRigidBodies.displayName = "InstancedRigidBodies";
1614
1751
 
1615
1752
  /**
1616
1753
  * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
@@ -1661,6 +1798,7 @@ Object.defineProperty(exports, 'RapierRigidBody', {
1661
1798
  get: function () { return rapier3dCompat.RigidBody; }
1662
1799
  });
1663
1800
  exports.AnyCollider = AnyCollider;
1801
+ exports.Attractor = Attractor;
1664
1802
  exports.BallCollider = BallCollider;
1665
1803
  exports.CapsuleCollider = CapsuleCollider;
1666
1804
  exports.ConeCollider = ConeCollider;