@react-three/rapier 0.6.7 → 0.6.9

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.
@@ -4,13 +4,22 @@ declare type UseColliderOptionsRequiredArgs<T> = Omit<UseColliderOptions<T>, "ar
4
4
  args: T;
5
5
  children?: ReactNode;
6
6
  };
7
- export declare const CuboidCollider: (props: UseColliderOptionsRequiredArgs<CuboidArgs>) => JSX.Element;
8
- export declare const RoundCuboidCollider: (props: UseColliderOptionsRequiredArgs<RoundCuboidArgs>) => JSX.Element;
9
- export declare const BallCollider: (props: UseColliderOptionsRequiredArgs<BallArgs>) => JSX.Element;
10
- export declare const CapsuleCollider: (props: UseColliderOptionsRequiredArgs<CapsuleArgs>) => JSX.Element;
11
- export declare const HeightfieldCollider: (props: UseColliderOptionsRequiredArgs<HeightfieldArgs>) => JSX.Element;
12
- export declare const TrimeshCollider: (props: UseColliderOptionsRequiredArgs<TrimeshArgs>) => JSX.Element;
13
- export declare const ConeCollider: (props: UseColliderOptionsRequiredArgs<ConeArgs>) => JSX.Element;
14
- export declare const CylinderCollider: (props: UseColliderOptionsRequiredArgs<CylinderArgs>) => JSX.Element;
15
- export declare const ConvexHullCollider: (props: UseColliderOptionsRequiredArgs<ConvexHullArgs>) => JSX.Element;
7
+ export declare type CuboidColliderProps = UseColliderOptionsRequiredArgs<CuboidArgs>;
8
+ export declare type RoundCuboidColliderProps = UseColliderOptionsRequiredArgs<RoundCuboidArgs>;
9
+ export declare type BallColliderProps = UseColliderOptionsRequiredArgs<BallArgs>;
10
+ export declare type CapsuleColliderProps = UseColliderOptionsRequiredArgs<CapsuleArgs>;
11
+ export declare type HeightfieldColliderProps = UseColliderOptionsRequiredArgs<HeightfieldArgs>;
12
+ export declare type TrimeshColliderProps = UseColliderOptionsRequiredArgs<TrimeshArgs>;
13
+ export declare type ConeColliderProps = UseColliderOptionsRequiredArgs<ConeArgs>;
14
+ export declare type CylinderColliderProps = UseColliderOptionsRequiredArgs<CylinderArgs>;
15
+ export declare type ConvexHullColliderProps = UseColliderOptionsRequiredArgs<ConvexHullArgs>;
16
+ export declare const CuboidCollider: (props: CuboidColliderProps) => JSX.Element;
17
+ export declare const RoundCuboidCollider: (props: RoundCuboidColliderProps) => JSX.Element;
18
+ export declare const BallCollider: (props: BallColliderProps) => JSX.Element;
19
+ export declare const CapsuleCollider: (props: CapsuleColliderProps) => JSX.Element;
20
+ export declare const HeightfieldCollider: (props: HeightfieldColliderProps) => JSX.Element;
21
+ export declare const TrimeshCollider: (props: TrimeshColliderProps) => JSX.Element;
22
+ export declare const ConeCollider: (props: ConeColliderProps) => JSX.Element;
23
+ export declare const CylinderCollider: (props: CylinderColliderProps) => JSX.Element;
24
+ export declare const ConvexHullCollider: (props: ConvexHullColliderProps) => JSX.Element;
16
25
  export {};
@@ -7,4 +7,4 @@ export interface InstancedRigidBodiesProps extends Omit<RigidBodyProps, "positio
7
7
  rotations?: Vector3Array[];
8
8
  scales?: Vector3Array[];
9
9
  }
10
- export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<Pick<InstancedRigidBodiesProps, "type" | "canSleep" | "linearDamping" | "angularDamping" | "linearVelocity" | "angularVelocity" | "gravityScale" | "ccd" | "colliders" | "friction" | "restitution" | "onSleep" | "onWake" | "lockRotations" | "lockTranslations" | "enabledRotations" | "enabledTranslations" | "children" | "quaternion" | "attach" | "args" | "key" | "onUpdate" | "up" | "scale" | "matrix" | "layers" | "dispose" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "visible" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onClick" | "onContextMenu" | "onDoubleClick" | "onPointerUp" | "onPointerDown" | "onPointerOver" | "onPointerOut" | "onPointerEnter" | "onPointerLeave" | "onPointerMove" | "onPointerMissed" | "onPointerCancel" | "onWheel" | "positions" | "rotations" | "scales"> & React.RefAttributes<InstancedRigidBodyApi>>;
10
+ export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<InstancedRigidBodiesProps & React.RefAttributes<InstancedRigidBodyApi>>;
@@ -1,12 +1,11 @@
1
1
  import React, { FC, ReactNode } from "react";
2
2
  import type Rapier from "@dimforge/rapier3d-compat";
3
- import { RigidBodyAutoCollider, Vector3Array, WorldApi } from "./types";
4
- import { ColliderHandle, RigidBody, RigidBodyHandle, TempContactManifold } from "@dimforge/rapier3d-compat";
3
+ import { CollisionEnterHandler, CollisionExitHandler, RigidBodyAutoCollider, Vector3Array, WorldApi } from "./types";
4
+ import { ColliderHandle, RigidBodyHandle } from "@dimforge/rapier3d-compat";
5
5
  import { Matrix4, Object3D, Vector3 } from "three";
6
6
  export interface RapierContext {
7
7
  rapier: typeof Rapier;
8
8
  world: WorldApi;
9
- colliderMeshes: Map<ColliderHandle, Object3D>;
10
9
  rigidBodyStates: Map<RigidBodyHandle, {
11
10
  mesh: Object3D;
12
11
  isSleeping: boolean;
@@ -19,20 +18,15 @@ export interface RapierContext {
19
18
  colliders: RigidBodyAutoCollider;
20
19
  };
21
20
  rigidBodyEvents: EventMap;
21
+ colliderEvents: EventMap;
22
22
  isPaused: boolean;
23
23
  }
24
24
  export declare const RapierContext: React.Context<RapierContext | undefined>;
25
25
  declare type EventMap = Map<ColliderHandle | RigidBodyHandle, {
26
26
  onSleep?(): void;
27
27
  onWake?(): void;
28
- onCollisionEnter?({ target, manifold, flipped, }: {
29
- target: RigidBody;
30
- manifold: TempContactManifold;
31
- flipped: boolean;
32
- }): void;
33
- onCollisionExit?({ target }: {
34
- target: RigidBody;
35
- }): void;
28
+ onCollisionEnter?: CollisionEnterHandler;
29
+ onCollisionExit?: CollisionExitHandler;
36
30
  }>;
37
31
  interface RapierWorldProps {
38
32
  children: ReactNode;
@@ -67,6 +61,12 @@ interface RapierWorldProps {
67
61
  * @defaultValue false
68
62
  */
69
63
  paused?: boolean;
64
+ /**
65
+ * The update priority at which the physics simulation should run.
66
+ *
67
+ * @defaultValue undefined
68
+ */
69
+ updatePriority?: number;
70
70
  }
71
71
  export declare const Physics: FC<RapierWorldProps>;
72
72
  export {};
@@ -1,7 +1,6 @@
1
1
  import React, { MutableRefObject, RefObject } from "react";
2
2
  import { ReactNode } from "react";
3
3
  import { Object3D } from "three";
4
- import { Object3DProps } from "@react-three/fiber";
5
4
  import { InstancedRigidBodyApi } from "./api";
6
5
  import { InstancedRigidBodiesProps } from "./InstancedRigidBodies";
7
6
  import { RigidBodyApi, UseRigidBodyOptions } from "./types";
@@ -17,7 +16,7 @@ export declare const useRigidBodyContext: () => {
17
16
  hasCollisionEvents: boolean;
18
17
  options: UseRigidBodyOptions | InstancedRigidBodiesProps;
19
18
  };
20
- export interface RigidBodyProps extends UseRigidBodyOptions, Omit<Object3DProps, 'type' | 'position' | 'rotation'> {
19
+ export interface RigidBodyProps extends UseRigidBodyOptions {
21
20
  children?: ReactNode;
22
21
  }
23
- export declare const RigidBody: React.ForwardRefExoticComponent<Pick<RigidBodyProps, "type" | "canSleep" | "linearDamping" | "angularDamping" | "linearVelocity" | "angularVelocity" | "gravityScale" | "ccd" | "position" | "rotation" | "colliders" | "friction" | "restitution" | "onCollisionEnter" | "onCollisionExit" | "onSleep" | "onWake" | "lockRotations" | "lockTranslations" | "enabledRotations" | "enabledTranslations" | "children" | "quaternion" | "attach" | "args" | "key" | "onUpdate" | "up" | "scale" | "matrix" | "layers" | "dispose" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "visible" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onClick" | "onContextMenu" | "onDoubleClick" | "onPointerUp" | "onPointerDown" | "onPointerOver" | "onPointerOut" | "onPointerEnter" | "onPointerLeave" | "onPointerMove" | "onPointerMissed" | "onPointerCancel" | "onWheel"> & React.RefAttributes<import("./api").RigidBodyApi>>;
22
+ export declare const RigidBody: React.ForwardRefExoticComponent<RigidBodyProps & React.RefAttributes<import("./api").RigidBodyApi>>;
@@ -58,7 +58,7 @@ export interface RigidBodyApi {
58
58
  /**
59
59
  * Sets the rotation quaternion of this rigid-body.
60
60
  */
61
- setRotation(rotation: Vector3Object): void;
61
+ setRotation(rotation: Quaternion): void;
62
62
  /**
63
63
  * The linear velocity of this rigid-body.
64
64
  */
@@ -99,7 +99,7 @@ export interface RigidBodyApi {
99
99
  * rigid-body from its current position and its next kinematic position. This velocity will be used
100
100
  * to compute forces on dynamic bodies interacting with this body.
101
101
  */
102
- setNextKinematicRotation(rotation: Vector3Object): void;
102
+ setNextKinematicRotation(rotation: Quaternion): void;
103
103
  /**
104
104
  * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
105
105
  *
@@ -0,0 +1,34 @@
1
+ import { InteractionGroups } from "@dimforge/rapier3d-compat";
2
+ /**
3
+ * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
4
+ * properties of RigidBody or Collider components. The first argument represents a list of
5
+ * groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
6
+ * of groups that will be filtered against. When it is omitted, all groups are filtered against.
7
+ *
8
+ * @example
9
+ * A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
10
+ *
11
+ * ```tsx
12
+ * <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
13
+ * ```
14
+ *
15
+ * A RigidBody that is member of groups 0 and 1 and will collide with everything else:
16
+ *
17
+ * ```tsx
18
+ * <RigidBody collisionGroups={interactionGroups([0, 1])} />
19
+ * ```
20
+ *
21
+ * A RigidBody that is member of groups 0 and 1 and will not collide with anything:
22
+ *
23
+ * ```tsx
24
+ * <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
25
+ * ```
26
+ *
27
+ * Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
28
+ * entities for collision events to trigger.
29
+ *
30
+ * @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
31
+ * @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
32
+ * @returns An InteractionGroup bitmask.
33
+ */
34
+ export declare const interactionGroups: (memberships: number | number[], filters?: number | number[] | undefined) => InteractionGroups;
@@ -1,5 +1,8 @@
1
1
  export * from "./types";
2
2
  export type { RigidBodyApi, WorldApi, InstancedRigidBodyApi } from "./api";
3
+ export type { RigidBodyProps } from './RigidBody';
4
+ export type { InstancedRigidBodiesProps } from './InstancedRigidBodies';
5
+ export type { CylinderColliderProps, BallColliderProps, CapsuleColliderProps, ConeColliderProps, ConvexHullColliderProps, CuboidColliderProps, HeightfieldColliderProps, RoundCuboidColliderProps, TrimeshColliderProps } from './AnyCollider';
3
6
  export { Physics } from "./Physics";
4
7
  export { RigidBody } from "./RigidBody";
5
8
  export { MeshCollider } from "./MeshCollider";
@@ -7,3 +10,4 @@ export { Debug } from "./Debug";
7
10
  export { InstancedRigidBodies } from "./InstancedRigidBodies";
8
11
  export * from "./AnyCollider";
9
12
  export * from "./hooks";
13
+ export * from "./bitmasks";
@@ -1,5 +1,5 @@
1
1
  import { MutableRefObject } from "react";
2
- import { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody, TempContactManifold } from "@dimforge/rapier3d-compat";
2
+ import { CoefficientCombineRule, Collider as RapierCollider, InteractionGroups, RigidBody as RapierRigidBody, TempContactManifold } from "@dimforge/rapier3d-compat";
3
3
  import { createColliderApi, createJointApi, createRigidBodyApi, createWorldApi } from "./api";
4
4
  export { CoefficientCombineRule as CoefficientCombineRule } from "@dimforge/rapier3d-compat";
5
5
  export { RapierRigidBody, RapierCollider };
@@ -120,7 +120,35 @@ export interface UseColliderOptions<ColliderArgs> {
120
120
  * The rotation of this collider relative to the rigid body
121
121
  */
122
122
  rotation?: Vector3Array;
123
+ /**
124
+ * Callback when this collider collides with another collider.
125
+ */
126
+ onCollisionEnter?: CollisionEnterHandler;
127
+ /**
128
+ * Callback when this collider stops colliding with another collider.
129
+ */
130
+ onCollisionExit?: CollisionExitHandler;
131
+ /**
132
+ * The bit mask configuring the groups and mask for collision handling.
133
+ */
134
+ collisionGroups?: InteractionGroups;
135
+ /**
136
+ * The bit mask configuring the groups and mask for solver handling.
137
+ */
138
+ solverGroups?: InteractionGroups;
123
139
  }
140
+ export declare type CollisionEnterPayload = {
141
+ target: RapierRigidBody;
142
+ collider: RapierCollider;
143
+ manifold: TempContactManifold;
144
+ flipped: boolean;
145
+ };
146
+ export declare type CollisionExitPayload = {
147
+ target: RapierRigidBody;
148
+ collider: RapierCollider;
149
+ };
150
+ export declare type CollisionEnterHandler = (payload: CollisionEnterPayload) => void;
151
+ export declare type CollisionExitHandler = (payload: CollisionExitPayload) => void;
124
152
  export interface UseRigidBodyOptions {
125
153
  /**
126
154
  * Specify the type of this rigid body
@@ -184,17 +212,21 @@ export interface UseRigidBodyOptions {
184
212
  /**
185
213
  * Callback when this rigidbody collides with another rigidbody
186
214
  */
187
- onCollisionEnter?({}: {
188
- target: RapierRigidBody;
189
- manifold: TempContactManifold;
190
- flipped: boolean;
191
- }): void;
215
+ onCollisionEnter?: CollisionEnterHandler;
192
216
  /**
193
217
  * Callback when this rigidbody stops colliding with another rigidbody
194
218
  */
195
- onCollisionExit?({}: {
196
- target: RapierRigidBody;
197
- }): void;
219
+ onCollisionExit?: CollisionExitHandler;
220
+ /**
221
+ * The default collision groups bitmask for all colliders in this rigid body.
222
+ * Can be customized per-collider.
223
+ */
224
+ collisionGroups?: InteractionGroups;
225
+ /**
226
+ * The default solver groups bitmask for all colliders in this rigid body.
227
+ * Can be customized per-collider.
228
+ */
229
+ solverGroups?: InteractionGroups;
198
230
  onSleep?(): void;
199
231
  onWake?(): void;
200
232
  /**
@@ -4,7 +4,7 @@ import { RigidBodyApi, RigidBodyAutoCollider, RigidBodyShape, RigidBodyTypeStrin
4
4
  export declare const vectorArrayToVector3: (arr: Vector3Array) => Vector3;
5
5
  export declare const vector3ToQuaternion: (v: Vector3) => Quaternion;
6
6
  export declare const rapierVector3ToVector3: ({ x, y, z }: RapierVector3) => Vector3;
7
- export declare const rapierQuaternionToQuaternion: ({ x, y, z, w, }: RapierQuaternion) => Quaternion;
7
+ export declare const rapierQuaternionToQuaternion: ({ x, y, z, w }: RapierQuaternion) => Quaternion;
8
8
  export declare const rigidBodyTypeFromString: (type: RigidBodyTypeString) => number;
9
9
  export declare const decomposeMatrix4: (m: Matrix4) => {
10
10
  position: Vector3;
@@ -8,6 +8,7 @@ var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
10
  var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
11
+ var MathUtils = require('three/src/math/MathUtils');
11
12
  var threeStdlib = require('three-stdlib');
12
13
 
13
14
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -49,7 +50,7 @@ const rapierVector3ToVector3 = ({
49
50
  x,
50
51
  y,
51
52
  z
52
- }) => _vector3.set(x, y, z).clone();
53
+ }) => _vector3.set(x, y, z);
53
54
  const rapierQuaternionToQuaternion = ({
54
55
  x,
55
56
  y,
@@ -95,6 +96,12 @@ const scaleColliderArgs = (shape, args, scale) => {
95
96
  const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
96
97
  return newArgs.map((arg, index) => scaleArray[index] * arg);
97
98
  };
99
+
100
+ const applyColliderOptions = (collider, options) => {
101
+ if (options.collisionGroups !== undefined) collider.setCollisionGroups(options.collisionGroups);
102
+ if (options.solverGroups !== undefined) collider.setSolverGroups(options.solverGroups);
103
+ };
104
+
98
105
  const createColliderFromOptions = ({
99
106
  options,
100
107
  world,
@@ -122,10 +129,6 @@ const createColliderFromOptions = ({
122
129
  w: qRotation.w
123
130
  }).setRestitution((_options$restitution = options === null || options === void 0 ? void 0 : options.restitution) !== null && _options$restitution !== void 0 ? _options$restitution : 0).setRestitutionCombineRule((_options$restitutionC = options === null || options === void 0 ? void 0 : options.restitutionCombineRule) !== null && _options$restitutionC !== void 0 ? _options$restitutionC : rapier3dCompat.CoefficientCombineRule.Average).setFriction((_options$friction = options === null || options === void 0 ? void 0 : options.friction) !== null && _options$friction !== void 0 ? _options$friction : 0.7).setFrictionCombineRule((_options$frictionComb = options === null || options === void 0 ? void 0 : options.frictionCombineRule) !== null && _options$frictionComb !== void 0 ? _options$frictionComb : rapier3dCompat.CoefficientCombineRule.Average);
124
131
 
125
- if (colliderShape === "heightfield") {
126
- console.log(colliderDesc);
127
- }
128
-
129
132
  if (hasCollisionEvents) {
130
133
  colliderDesc = colliderDesc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
131
134
  } // If any of the mass properties are specified, add mass properties
@@ -152,6 +155,7 @@ const createColliderFromOptions = ({
152
155
  }
153
156
 
154
157
  const collider = world.createCollider(colliderDesc, rigidBody);
158
+ applyColliderOptions(collider, options);
155
159
  return collider;
156
160
  };
157
161
 
@@ -172,7 +176,6 @@ const createCollidersFromChildren = ({
172
176
  }) => {
173
177
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
174
178
  const colliders = [];
175
- new three.Vector3();
176
179
  object.traverseVisible(child => {
177
180
  if ("isMesh" in child) {
178
181
  if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
@@ -218,6 +221,7 @@ const createCollidersFromChildren = ({
218
221
  });
219
222
  const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
220
223
  const collider = world.createCollider(desc, actualRigidBody);
224
+ applyColliderOptions(collider, options);
221
225
  colliders.push(collider);
222
226
  }
223
227
  });
@@ -328,12 +332,7 @@ const createRigidBodyApi = ref => {
328
332
  addTorque: torque => ref.current().addTorque(torque, true),
329
333
 
330
334
  translation() {
331
- const {
332
- x,
333
- y,
334
- z
335
- } = ref.current().translation();
336
- return new three.Vector3(x, y, z);
335
+ return rapierVector3ToVector3(ref.current().translation());
337
336
  },
338
337
 
339
338
  setTranslation: translation => ref.current().setTranslation(translation, true),
@@ -348,18 +347,8 @@ const createRigidBodyApi = ref => {
348
347
  return new three.Quaternion(x, y, z, w);
349
348
  },
350
349
 
351
- setRotation: ({
352
- x,
353
- y,
354
- z
355
- }) => {
356
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
357
- ref.current().setRotation({
358
- x: q.x,
359
- y: q.y,
360
- z: q.z,
361
- w: q.w
362
- }, true);
350
+ setRotation: rotation => {
351
+ ref.current().setRotation(rotation, true);
363
352
  },
364
353
 
365
354
  linvel() {
@@ -395,18 +384,8 @@ const createRigidBodyApi = ref => {
395
384
  },
396
385
 
397
386
  setAngularDamping: factor => ref.current().setAngularDamping(factor),
398
- setNextKinematicRotation: ({
399
- x,
400
- y,
401
- z
402
- }) => {
403
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
404
- ref.current().setNextKinematicRotation({
405
- x: q.x,
406
- y: q.y,
407
- z: q.z,
408
- w: q.w
409
- });
387
+ setNextKinematicRotation: rotation => {
388
+ ref.current().setNextKinematicRotation(rotation);
410
389
  },
411
390
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
412
391
  resetForces: () => ref.current().resetForces(true),
@@ -480,7 +459,8 @@ const Physics = ({
480
459
  children,
481
460
  timeStep: _timeStep = 1 / 60,
482
461
  maxSubSteps: _maxSubSteps = 10,
483
- paused: _paused = false
462
+ paused: _paused = false,
463
+ updatePriority
484
464
  }) => {
485
465
  const rapier = useAsset.useAsset(importRapier);
486
466
  const [isPaused, setIsPaused] = React.useState(_paused);
@@ -496,9 +476,9 @@ const Physics = ({
496
476
 
497
477
  return worldRef.current;
498
478
  });
499
- const [colliderMeshes] = React.useState(() => new Map());
500
479
  const [rigidBodyStates] = React.useState(() => new Map());
501
480
  const [rigidBodyEvents] = React.useState(() => new Map());
481
+ const [colliderEvents] = React.useState(() => new Map());
502
482
  const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
503
483
 
504
484
  React.useEffect(() => {
@@ -528,12 +508,12 @@ const Physics = ({
528
508
  world.timestep = _timeStep;
529
509
  /**
530
510
  * Fixed timeStep simulation progression
531
- * @see https://gafferongames.com/post/fix_your_timestep/
511
+ * @see https://gafferongames.com/post/fix_your_timestep/
532
512
  */
533
513
 
534
514
  let previousTranslations = {}; // don't step time forwards if paused
535
515
 
536
- const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
516
+ const nowTime = steppingState.time += _paused ? 0 : MathUtils.clamp(delta, 0, 1) * 1000;
537
517
  const timeStepMs = _timeStep * 1000;
538
518
  const timeSinceLast = nowTime - steppingState.lastTime;
539
519
  steppingState.lastTime = nowTime;
@@ -583,7 +563,7 @@ const Physics = ({
583
563
  }
584
564
 
585
565
  let oldState = previousTranslations[rigidBody.handle];
586
- let newTranslation = rapierVector3ToVector3(rigidBody.translation());
566
+ let newTranslation = rigidBody.translation();
587
567
  let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
588
568
  let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
589
569
  let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
@@ -602,42 +582,71 @@ const Physics = ({
602
582
  const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
603
583
  const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
604
584
 
605
- if (!collider1 || !collider2 || !rigidBodyHandle1 || !rigidBodyHandle2) {
585
+ if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
606
586
  return;
607
587
  }
608
588
 
609
589
  const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
610
590
  const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
611
- const events1 = rigidBodyEvents.get(rigidBodyHandle1);
612
- const events2 = rigidBodyEvents.get(rigidBodyHandle2);
591
+ const rigidBody1Events = rigidBodyEvents.get(rigidBodyHandle1);
592
+ const rigidBoyd2Events = rigidBodyEvents.get(rigidBodyHandle2);
593
+ const collider1Events = colliderEvents.get(collider1.handle);
594
+ const collider2Events = colliderEvents.get(collider2.handle);
613
595
 
614
596
  if (started) {
615
597
  world.contactPair(collider1, collider2, (manifold, flipped) => {
616
- var _events1$onCollisionE, _events2$onCollisionE;
598
+ var _rigidBody1Events$onC, _rigidBoyd2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
599
+
600
+ /* RigidBody events */
601
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
602
+ target: rigidBody2,
603
+ collider: collider2,
604
+ manifold,
605
+ flipped
606
+ });
607
+ rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC = rigidBoyd2Events.onCollisionEnter) === null || _rigidBoyd2Events$onC === void 0 ? void 0 : _rigidBoyd2Events$onC.call(rigidBoyd2Events, {
608
+ target: rigidBody1,
609
+ collider: collider1,
610
+ manifold,
611
+ flipped
612
+ });
613
+ /* Collider events */
617
614
 
618
- events1 === null || events1 === void 0 ? void 0 : (_events1$onCollisionE = events1.onCollisionEnter) === null || _events1$onCollisionE === void 0 ? void 0 : _events1$onCollisionE.call(events1, {
615
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
619
616
  target: rigidBody2,
617
+ collider: collider2,
620
618
  manifold,
621
619
  flipped
622
620
  });
623
- events2 === null || events2 === void 0 ? void 0 : (_events2$onCollisionE = events2.onCollisionEnter) === null || _events2$onCollisionE === void 0 ? void 0 : _events2$onCollisionE.call(events2, {
621
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
624
622
  target: rigidBody1,
623
+ collider: collider1,
625
624
  manifold,
626
625
  flipped
627
626
  });
628
627
  });
629
628
  } else {
630
- var _events1$onCollisionE2, _events2$onCollisionE2;
629
+ var _rigidBody1Events$onC2, _rigidBoyd2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
631
630
 
632
- events1 === null || events1 === void 0 ? void 0 : (_events1$onCollisionE2 = events1.onCollisionExit) === null || _events1$onCollisionE2 === void 0 ? void 0 : _events1$onCollisionE2.call(events1, {
633
- target: rigidBody2
631
+ rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
632
+ target: rigidBody2,
633
+ collider: collider2
634
+ });
635
+ rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC2 = rigidBoyd2Events.onCollisionExit) === null || _rigidBoyd2Events$onC2 === void 0 ? void 0 : _rigidBoyd2Events$onC2.call(rigidBoyd2Events, {
636
+ target: rigidBody1,
637
+ collider: collider1
634
638
  });
635
- events2 === null || events2 === void 0 ? void 0 : (_events2$onCollisionE2 = events2.onCollisionExit) === null || _events2$onCollisionE2 === void 0 ? void 0 : _events2$onCollisionE2.call(events2, {
636
- target: rigidBody1
639
+ collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
640
+ target: rigidBody2,
641
+ collider: collider2
642
+ });
643
+ collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
644
+ target: rigidBody1,
645
+ collider: collider1
637
646
  });
638
647
  }
639
648
  });
640
- });
649
+ }, updatePriority);
641
650
  const api = React.useMemo(() => createWorldApi(getWorldRef), []);
642
651
  const context = React.useMemo(() => ({
643
652
  rapier,
@@ -646,9 +655,9 @@ const Physics = ({
646
655
  colliders: _colliders,
647
656
  gravity: _gravity
648
657
  },
649
- colliderMeshes,
650
658
  rigidBodyStates,
651
659
  rigidBodyEvents,
660
+ colliderEvents,
652
661
  isPaused
653
662
  }), [isPaused]);
654
663
  return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
@@ -1314,22 +1323,26 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1314
1323
  }, props.children));
1315
1324
  });
1316
1325
 
1317
- const _excluded = ["children"];
1326
+ const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
1318
1327
 
1319
1328
  const AnyCollider = _ref => {
1320
1329
  let {
1321
- children
1330
+ children,
1331
+ onCollisionEnter,
1332
+ onCollisionExit
1322
1333
  } = _ref,
1323
1334
  props = _objectWithoutProperties(_ref, _excluded);
1324
1335
 
1325
1336
  const {
1326
- world
1337
+ world,
1338
+ colliderEvents
1327
1339
  } = useRapier();
1328
1340
  const rigidBodyContext = useRigidBodyContext();
1329
1341
  const ref = React.useRef(null);
1330
1342
  React.useEffect(() => {
1331
1343
  const scale = ref.current.getWorldScale(new three.Vector3());
1332
- const colliders = []; // If this is an InstancedRigidBody api
1344
+ const colliders = [];
1345
+ const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
1333
1346
 
1334
1347
  if (rigidBodyContext && "at" in rigidBodyContext.api) {
1335
1348
  rigidBodyContext.api.forEach((body, index) => {
@@ -1342,26 +1355,41 @@ const AnyCollider = _ref => {
1342
1355
  }
1343
1356
 
1344
1357
  colliders.push(createColliderFromOptions({
1345
- options: props,
1358
+ options: _objectSpread2({
1359
+ solverGroups: rigidBodyContext.options.solverGroups,
1360
+ collisionGroups: rigidBodyContext.options.collisionGroups
1361
+ }, props),
1346
1362
  world,
1347
1363
  rigidBody: body.raw(),
1348
1364
  scale: instanceScale,
1349
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1365
+ hasCollisionEvents
1350
1366
  }));
1351
1367
  });
1352
1368
  } else {
1353
1369
  colliders.push(createColliderFromOptions({
1354
- options: props,
1370
+ options: _objectSpread2({
1371
+ solverGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.solverGroups) || props.solverGroups,
1372
+ collisionGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.collisionGroups) || props.collisionGroups
1373
+ }, props),
1355
1374
  world,
1356
1375
  // Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
1357
1376
  rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
1358
1377
  scale,
1359
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1378
+ hasCollisionEvents
1360
1379
  }));
1361
1380
  }
1381
+ /* Register collision events. */
1362
1382
 
1383
+
1384
+ colliders.forEach(collider => colliderEvents.set(collider.handle, {
1385
+ onCollisionEnter,
1386
+ onCollisionExit
1387
+ }));
1363
1388
  return () => {
1364
- colliders.forEach(collider => world.removeCollider(collider));
1389
+ colliders.forEach(collider => {
1390
+ colliderEvents.delete(collider.handle);
1391
+ world.removeCollider(collider);
1392
+ });
1365
1393
  };
1366
1394
  }, []);
1367
1395
  return /*#__PURE__*/React__default["default"].createElement("object3D", {
@@ -1415,6 +1443,42 @@ const ConvexHullCollider = props => {
1415
1443
  }));
1416
1444
  };
1417
1445
 
1446
+ /**
1447
+ * Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
1448
+ * properties of RigidBody or Collider components. The first argument represents a list of
1449
+ * groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
1450
+ * of groups that will be filtered against. When it is omitted, all groups are filtered against.
1451
+ *
1452
+ * @example
1453
+ * A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
1454
+ *
1455
+ * ```tsx
1456
+ * <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
1457
+ * ```
1458
+ *
1459
+ * A RigidBody that is member of groups 0 and 1 and will collide with everything else:
1460
+ *
1461
+ * ```tsx
1462
+ * <RigidBody collisionGroups={interactionGroups([0, 1])} />
1463
+ * ```
1464
+ *
1465
+ * A RigidBody that is member of groups 0 and 1 and will not collide with anything:
1466
+ *
1467
+ * ```tsx
1468
+ * <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
1469
+ * ```
1470
+ *
1471
+ * Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
1472
+ * entities for collision events to trigger.
1473
+ *
1474
+ * @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
1475
+ * @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
1476
+ * @returns An InteractionGroup bitmask.
1477
+ */
1478
+ const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
1479
+
1480
+ const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
1481
+
1418
1482
  Object.defineProperty(exports, 'CoefficientCombineRule', {
1419
1483
  enumerable: true,
1420
1484
  get: function () { return rapier3dCompat.CoefficientCombineRule; }
@@ -1441,6 +1505,7 @@ exports.Physics = Physics;
1441
1505
  exports.RigidBody = RigidBody;
1442
1506
  exports.RoundCuboidCollider = RoundCuboidCollider;
1443
1507
  exports.TrimeshCollider = TrimeshCollider;
1508
+ exports.interactionGroups = interactionGroups;
1444
1509
  exports.useFixedJoint = useFixedJoint;
1445
1510
  exports.useImpulseJoint = useImpulseJoint;
1446
1511
  exports.usePrismaticJoint = usePrismaticJoint;