@react-three/rapier 0.6.8 → 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.
- package/dist/declarations/src/AnyCollider.d.ts +18 -9
- package/dist/declarations/src/InstancedRigidBodies.d.ts +1 -1
- package/dist/declarations/src/Physics.d.ts +11 -10
- package/dist/declarations/src/RigidBody.d.ts +2 -3
- package/dist/declarations/src/bitmasks.d.ts +34 -0
- package/dist/declarations/src/index.d.ts +4 -0
- package/dist/declarations/src/types.d.ts +41 -9
- package/dist/declarations/src/utils.d.ts +1 -1
- package/dist/react-three-rapier.cjs.dev.js +122 -25
- package/dist/react-three-rapier.cjs.prod.js +122 -25
- package/dist/react-three-rapier.esm.js +122 -26
- package/package.json +4 -4
- package/readme.md +63 -9
@@ -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
|
8
|
-
export declare
|
9
|
-
export declare
|
10
|
-
export declare
|
11
|
-
export declare
|
12
|
-
export declare
|
13
|
-
export declare
|
14
|
-
export declare
|
15
|
-
export declare
|
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<
|
10
|
+
export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<InstancedRigidBodiesProps & React.RefAttributes<InstancedRigidBodyApi>>;
|
@@ -1,7 +1,7 @@
|
|
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,
|
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;
|
@@ -18,20 +18,15 @@ export interface RapierContext {
|
|
18
18
|
colliders: RigidBodyAutoCollider;
|
19
19
|
};
|
20
20
|
rigidBodyEvents: EventMap;
|
21
|
+
colliderEvents: EventMap;
|
21
22
|
isPaused: boolean;
|
22
23
|
}
|
23
24
|
export declare const RapierContext: React.Context<RapierContext | undefined>;
|
24
25
|
declare type EventMap = Map<ColliderHandle | RigidBodyHandle, {
|
25
26
|
onSleep?(): void;
|
26
27
|
onWake?(): void;
|
27
|
-
onCollisionEnter
|
28
|
-
|
29
|
-
manifold: TempContactManifold;
|
30
|
-
flipped: boolean;
|
31
|
-
}): void;
|
32
|
-
onCollisionExit?({ target }: {
|
33
|
-
target: RigidBody;
|
34
|
-
}): void;
|
28
|
+
onCollisionEnter?: CollisionEnterHandler;
|
29
|
+
onCollisionExit?: CollisionExitHandler;
|
35
30
|
}>;
|
36
31
|
interface RapierWorldProps {
|
37
32
|
children: ReactNode;
|
@@ -66,6 +61,12 @@ interface RapierWorldProps {
|
|
66
61
|
* @defaultValue false
|
67
62
|
*/
|
68
63
|
paused?: boolean;
|
64
|
+
/**
|
65
|
+
* The update priority at which the physics simulation should run.
|
66
|
+
*
|
67
|
+
* @defaultValue undefined
|
68
|
+
*/
|
69
|
+
updatePriority?: number;
|
69
70
|
}
|
70
71
|
export declare const Physics: FC<RapierWorldProps>;
|
71
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
|
19
|
+
export interface RigidBodyProps extends UseRigidBodyOptions {
|
21
20
|
children?: ReactNode;
|
22
21
|
}
|
23
|
-
export declare const RigidBody: React.ForwardRefExoticComponent<
|
22
|
+
export declare const RigidBody: React.ForwardRefExoticComponent<RigidBodyProps & React.RefAttributes<import("./api").RigidBodyApi>>;
|
@@ -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
|
-
|
197
|
-
|
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
|
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)
|
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,
|
@@ -148,6 +155,7 @@ const createColliderFromOptions = ({
|
|
148
155
|
}
|
149
156
|
|
150
157
|
const collider = world.createCollider(colliderDesc, rigidBody);
|
158
|
+
applyColliderOptions(collider, options);
|
151
159
|
return collider;
|
152
160
|
};
|
153
161
|
|
@@ -213,6 +221,7 @@ const createCollidersFromChildren = ({
|
|
213
221
|
});
|
214
222
|
const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
|
215
223
|
const collider = world.createCollider(desc, actualRigidBody);
|
224
|
+
applyColliderOptions(collider, options);
|
216
225
|
colliders.push(collider);
|
217
226
|
}
|
218
227
|
});
|
@@ -450,7 +459,8 @@ const Physics = ({
|
|
450
459
|
children,
|
451
460
|
timeStep: _timeStep = 1 / 60,
|
452
461
|
maxSubSteps: _maxSubSteps = 10,
|
453
|
-
paused: _paused = false
|
462
|
+
paused: _paused = false,
|
463
|
+
updatePriority
|
454
464
|
}) => {
|
455
465
|
const rapier = useAsset.useAsset(importRapier);
|
456
466
|
const [isPaused, setIsPaused] = React.useState(_paused);
|
@@ -468,6 +478,7 @@ const Physics = ({
|
|
468
478
|
});
|
469
479
|
const [rigidBodyStates] = React.useState(() => new Map());
|
470
480
|
const [rigidBodyEvents] = React.useState(() => new Map());
|
481
|
+
const [colliderEvents] = React.useState(() => new Map());
|
471
482
|
const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
|
472
483
|
|
473
484
|
React.useEffect(() => {
|
@@ -497,12 +508,12 @@ const Physics = ({
|
|
497
508
|
world.timestep = _timeStep;
|
498
509
|
/**
|
499
510
|
* Fixed timeStep simulation progression
|
500
|
-
* @see https://gafferongames.com/post/fix_your_timestep/
|
511
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
501
512
|
*/
|
502
513
|
|
503
514
|
let previousTranslations = {}; // don't step time forwards if paused
|
504
515
|
|
505
|
-
const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
|
516
|
+
const nowTime = steppingState.time += _paused ? 0 : MathUtils.clamp(delta, 0, 1) * 1000;
|
506
517
|
const timeStepMs = _timeStep * 1000;
|
507
518
|
const timeSinceLast = nowTime - steppingState.lastTime;
|
508
519
|
steppingState.lastTime = nowTime;
|
@@ -552,7 +563,7 @@ const Physics = ({
|
|
552
563
|
}
|
553
564
|
|
554
565
|
let oldState = previousTranslations[rigidBody.handle];
|
555
|
-
let newTranslation =
|
566
|
+
let newTranslation = rigidBody.translation();
|
556
567
|
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
557
568
|
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
558
569
|
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
@@ -577,36 +588,65 @@ const Physics = ({
|
|
577
588
|
|
578
589
|
const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
|
579
590
|
const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
|
580
|
-
const
|
581
|
-
const
|
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);
|
582
595
|
|
583
596
|
if (started) {
|
584
597
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
585
|
-
var
|
598
|
+
var _rigidBody1Events$onC, _rigidBoyd2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
|
586
599
|
|
587
|
-
|
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, {
|
588
602
|
target: rigidBody2,
|
603
|
+
collider: collider2,
|
589
604
|
manifold,
|
590
605
|
flipped
|
591
606
|
});
|
592
|
-
|
607
|
+
rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC = rigidBoyd2Events.onCollisionEnter) === null || _rigidBoyd2Events$onC === void 0 ? void 0 : _rigidBoyd2Events$onC.call(rigidBoyd2Events, {
|
593
608
|
target: rigidBody1,
|
609
|
+
collider: collider1,
|
610
|
+
manifold,
|
611
|
+
flipped
|
612
|
+
});
|
613
|
+
/* Collider events */
|
614
|
+
|
615
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
|
616
|
+
target: rigidBody2,
|
617
|
+
collider: collider2,
|
618
|
+
manifold,
|
619
|
+
flipped
|
620
|
+
});
|
621
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
|
622
|
+
target: rigidBody1,
|
623
|
+
collider: collider1,
|
594
624
|
manifold,
|
595
625
|
flipped
|
596
626
|
});
|
597
627
|
});
|
598
628
|
} else {
|
599
|
-
var
|
629
|
+
var _rigidBody1Events$onC2, _rigidBoyd2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
|
600
630
|
|
601
|
-
|
602
|
-
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
|
603
638
|
});
|
604
|
-
|
605
|
-
target:
|
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
|
606
646
|
});
|
607
647
|
}
|
608
648
|
});
|
609
|
-
});
|
649
|
+
}, updatePriority);
|
610
650
|
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
611
651
|
const context = React.useMemo(() => ({
|
612
652
|
rapier,
|
@@ -617,6 +657,7 @@ const Physics = ({
|
|
617
657
|
},
|
618
658
|
rigidBodyStates,
|
619
659
|
rigidBodyEvents,
|
660
|
+
colliderEvents,
|
620
661
|
isPaused
|
621
662
|
}), [isPaused]);
|
622
663
|
return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
|
@@ -1282,22 +1323,26 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1282
1323
|
}, props.children));
|
1283
1324
|
});
|
1284
1325
|
|
1285
|
-
const _excluded = ["children"];
|
1326
|
+
const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
|
1286
1327
|
|
1287
1328
|
const AnyCollider = _ref => {
|
1288
1329
|
let {
|
1289
|
-
children
|
1330
|
+
children,
|
1331
|
+
onCollisionEnter,
|
1332
|
+
onCollisionExit
|
1290
1333
|
} = _ref,
|
1291
1334
|
props = _objectWithoutProperties(_ref, _excluded);
|
1292
1335
|
|
1293
1336
|
const {
|
1294
|
-
world
|
1337
|
+
world,
|
1338
|
+
colliderEvents
|
1295
1339
|
} = useRapier();
|
1296
1340
|
const rigidBodyContext = useRigidBodyContext();
|
1297
1341
|
const ref = React.useRef(null);
|
1298
1342
|
React.useEffect(() => {
|
1299
1343
|
const scale = ref.current.getWorldScale(new three.Vector3());
|
1300
|
-
const colliders = [];
|
1344
|
+
const colliders = [];
|
1345
|
+
const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
|
1301
1346
|
|
1302
1347
|
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1303
1348
|
rigidBodyContext.api.forEach((body, index) => {
|
@@ -1310,26 +1355,41 @@ const AnyCollider = _ref => {
|
|
1310
1355
|
}
|
1311
1356
|
|
1312
1357
|
colliders.push(createColliderFromOptions({
|
1313
|
-
options:
|
1358
|
+
options: _objectSpread2({
|
1359
|
+
solverGroups: rigidBodyContext.options.solverGroups,
|
1360
|
+
collisionGroups: rigidBodyContext.options.collisionGroups
|
1361
|
+
}, props),
|
1314
1362
|
world,
|
1315
1363
|
rigidBody: body.raw(),
|
1316
1364
|
scale: instanceScale,
|
1317
|
-
hasCollisionEvents
|
1365
|
+
hasCollisionEvents
|
1318
1366
|
}));
|
1319
1367
|
});
|
1320
1368
|
} else {
|
1321
1369
|
colliders.push(createColliderFromOptions({
|
1322
|
-
options:
|
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),
|
1323
1374
|
world,
|
1324
1375
|
// Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
|
1325
1376
|
rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
|
1326
1377
|
scale,
|
1327
|
-
hasCollisionEvents
|
1378
|
+
hasCollisionEvents
|
1328
1379
|
}));
|
1329
1380
|
}
|
1381
|
+
/* Register collision events. */
|
1382
|
+
|
1330
1383
|
|
1384
|
+
colliders.forEach(collider => colliderEvents.set(collider.handle, {
|
1385
|
+
onCollisionEnter,
|
1386
|
+
onCollisionExit
|
1387
|
+
}));
|
1331
1388
|
return () => {
|
1332
|
-
colliders.forEach(collider =>
|
1389
|
+
colliders.forEach(collider => {
|
1390
|
+
colliderEvents.delete(collider.handle);
|
1391
|
+
world.removeCollider(collider);
|
1392
|
+
});
|
1333
1393
|
};
|
1334
1394
|
}, []);
|
1335
1395
|
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
@@ -1383,6 +1443,42 @@ const ConvexHullCollider = props => {
|
|
1383
1443
|
}));
|
1384
1444
|
};
|
1385
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
|
+
|
1386
1482
|
Object.defineProperty(exports, 'CoefficientCombineRule', {
|
1387
1483
|
enumerable: true,
|
1388
1484
|
get: function () { return rapier3dCompat.CoefficientCombineRule; }
|
@@ -1409,6 +1505,7 @@ exports.Physics = Physics;
|
|
1409
1505
|
exports.RigidBody = RigidBody;
|
1410
1506
|
exports.RoundCuboidCollider = RoundCuboidCollider;
|
1411
1507
|
exports.TrimeshCollider = TrimeshCollider;
|
1508
|
+
exports.interactionGroups = interactionGroups;
|
1412
1509
|
exports.useFixedJoint = useFixedJoint;
|
1413
1510
|
exports.useImpulseJoint = useImpulseJoint;
|
1414
1511
|
exports.usePrismaticJoint = usePrismaticJoint;
|
@@ -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)
|
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,
|
@@ -148,6 +155,7 @@ const createColliderFromOptions = ({
|
|
148
155
|
}
|
149
156
|
|
150
157
|
const collider = world.createCollider(colliderDesc, rigidBody);
|
158
|
+
applyColliderOptions(collider, options);
|
151
159
|
return collider;
|
152
160
|
};
|
153
161
|
|
@@ -213,6 +221,7 @@ const createCollidersFromChildren = ({
|
|
213
221
|
});
|
214
222
|
const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
|
215
223
|
const collider = world.createCollider(desc, actualRigidBody);
|
224
|
+
applyColliderOptions(collider, options);
|
216
225
|
colliders.push(collider);
|
217
226
|
}
|
218
227
|
});
|
@@ -450,7 +459,8 @@ const Physics = ({
|
|
450
459
|
children,
|
451
460
|
timeStep: _timeStep = 1 / 60,
|
452
461
|
maxSubSteps: _maxSubSteps = 10,
|
453
|
-
paused: _paused = false
|
462
|
+
paused: _paused = false,
|
463
|
+
updatePriority
|
454
464
|
}) => {
|
455
465
|
const rapier = useAsset.useAsset(importRapier);
|
456
466
|
const [isPaused, setIsPaused] = React.useState(_paused);
|
@@ -468,6 +478,7 @@ const Physics = ({
|
|
468
478
|
});
|
469
479
|
const [rigidBodyStates] = React.useState(() => new Map());
|
470
480
|
const [rigidBodyEvents] = React.useState(() => new Map());
|
481
|
+
const [colliderEvents] = React.useState(() => new Map());
|
471
482
|
const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
|
472
483
|
|
473
484
|
React.useEffect(() => {
|
@@ -497,12 +508,12 @@ const Physics = ({
|
|
497
508
|
world.timestep = _timeStep;
|
498
509
|
/**
|
499
510
|
* Fixed timeStep simulation progression
|
500
|
-
* @see https://gafferongames.com/post/fix_your_timestep/
|
511
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
501
512
|
*/
|
502
513
|
|
503
514
|
let previousTranslations = {}; // don't step time forwards if paused
|
504
515
|
|
505
|
-
const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
|
516
|
+
const nowTime = steppingState.time += _paused ? 0 : MathUtils.clamp(delta, 0, 1) * 1000;
|
506
517
|
const timeStepMs = _timeStep * 1000;
|
507
518
|
const timeSinceLast = nowTime - steppingState.lastTime;
|
508
519
|
steppingState.lastTime = nowTime;
|
@@ -552,7 +563,7 @@ const Physics = ({
|
|
552
563
|
}
|
553
564
|
|
554
565
|
let oldState = previousTranslations[rigidBody.handle];
|
555
|
-
let newTranslation =
|
566
|
+
let newTranslation = rigidBody.translation();
|
556
567
|
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
557
568
|
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
558
569
|
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
@@ -577,36 +588,65 @@ const Physics = ({
|
|
577
588
|
|
578
589
|
const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
|
579
590
|
const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
|
580
|
-
const
|
581
|
-
const
|
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);
|
582
595
|
|
583
596
|
if (started) {
|
584
597
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
585
|
-
var
|
598
|
+
var _rigidBody1Events$onC, _rigidBoyd2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
|
586
599
|
|
587
|
-
|
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, {
|
588
602
|
target: rigidBody2,
|
603
|
+
collider: collider2,
|
589
604
|
manifold,
|
590
605
|
flipped
|
591
606
|
});
|
592
|
-
|
607
|
+
rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC = rigidBoyd2Events.onCollisionEnter) === null || _rigidBoyd2Events$onC === void 0 ? void 0 : _rigidBoyd2Events$onC.call(rigidBoyd2Events, {
|
593
608
|
target: rigidBody1,
|
609
|
+
collider: collider1,
|
610
|
+
manifold,
|
611
|
+
flipped
|
612
|
+
});
|
613
|
+
/* Collider events */
|
614
|
+
|
615
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
|
616
|
+
target: rigidBody2,
|
617
|
+
collider: collider2,
|
618
|
+
manifold,
|
619
|
+
flipped
|
620
|
+
});
|
621
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
|
622
|
+
target: rigidBody1,
|
623
|
+
collider: collider1,
|
594
624
|
manifold,
|
595
625
|
flipped
|
596
626
|
});
|
597
627
|
});
|
598
628
|
} else {
|
599
|
-
var
|
629
|
+
var _rigidBody1Events$onC2, _rigidBoyd2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
|
600
630
|
|
601
|
-
|
602
|
-
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
|
603
638
|
});
|
604
|
-
|
605
|
-
target:
|
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
|
606
646
|
});
|
607
647
|
}
|
608
648
|
});
|
609
|
-
});
|
649
|
+
}, updatePriority);
|
610
650
|
const api = React.useMemo(() => createWorldApi(getWorldRef), []);
|
611
651
|
const context = React.useMemo(() => ({
|
612
652
|
rapier,
|
@@ -617,6 +657,7 @@ const Physics = ({
|
|
617
657
|
},
|
618
658
|
rigidBodyStates,
|
619
659
|
rigidBodyEvents,
|
660
|
+
colliderEvents,
|
620
661
|
isPaused
|
621
662
|
}), [isPaused]);
|
622
663
|
return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
|
@@ -1282,22 +1323,26 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
1282
1323
|
}, props.children));
|
1283
1324
|
});
|
1284
1325
|
|
1285
|
-
const _excluded = ["children"];
|
1326
|
+
const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
|
1286
1327
|
|
1287
1328
|
const AnyCollider = _ref => {
|
1288
1329
|
let {
|
1289
|
-
children
|
1330
|
+
children,
|
1331
|
+
onCollisionEnter,
|
1332
|
+
onCollisionExit
|
1290
1333
|
} = _ref,
|
1291
1334
|
props = _objectWithoutProperties(_ref, _excluded);
|
1292
1335
|
|
1293
1336
|
const {
|
1294
|
-
world
|
1337
|
+
world,
|
1338
|
+
colliderEvents
|
1295
1339
|
} = useRapier();
|
1296
1340
|
const rigidBodyContext = useRigidBodyContext();
|
1297
1341
|
const ref = React.useRef(null);
|
1298
1342
|
React.useEffect(() => {
|
1299
1343
|
const scale = ref.current.getWorldScale(new three.Vector3());
|
1300
|
-
const colliders = [];
|
1344
|
+
const colliders = [];
|
1345
|
+
const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
|
1301
1346
|
|
1302
1347
|
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1303
1348
|
rigidBodyContext.api.forEach((body, index) => {
|
@@ -1310,26 +1355,41 @@ const AnyCollider = _ref => {
|
|
1310
1355
|
}
|
1311
1356
|
|
1312
1357
|
colliders.push(createColliderFromOptions({
|
1313
|
-
options:
|
1358
|
+
options: _objectSpread2({
|
1359
|
+
solverGroups: rigidBodyContext.options.solverGroups,
|
1360
|
+
collisionGroups: rigidBodyContext.options.collisionGroups
|
1361
|
+
}, props),
|
1314
1362
|
world,
|
1315
1363
|
rigidBody: body.raw(),
|
1316
1364
|
scale: instanceScale,
|
1317
|
-
hasCollisionEvents
|
1365
|
+
hasCollisionEvents
|
1318
1366
|
}));
|
1319
1367
|
});
|
1320
1368
|
} else {
|
1321
1369
|
colliders.push(createColliderFromOptions({
|
1322
|
-
options:
|
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),
|
1323
1374
|
world,
|
1324
1375
|
// Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
|
1325
1376
|
rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
|
1326
1377
|
scale,
|
1327
|
-
hasCollisionEvents
|
1378
|
+
hasCollisionEvents
|
1328
1379
|
}));
|
1329
1380
|
}
|
1381
|
+
/* Register collision events. */
|
1382
|
+
|
1330
1383
|
|
1384
|
+
colliders.forEach(collider => colliderEvents.set(collider.handle, {
|
1385
|
+
onCollisionEnter,
|
1386
|
+
onCollisionExit
|
1387
|
+
}));
|
1331
1388
|
return () => {
|
1332
|
-
colliders.forEach(collider =>
|
1389
|
+
colliders.forEach(collider => {
|
1390
|
+
colliderEvents.delete(collider.handle);
|
1391
|
+
world.removeCollider(collider);
|
1392
|
+
});
|
1333
1393
|
};
|
1334
1394
|
}, []);
|
1335
1395
|
return /*#__PURE__*/React__default["default"].createElement("object3D", {
|
@@ -1383,6 +1443,42 @@ const ConvexHullCollider = props => {
|
|
1383
1443
|
}));
|
1384
1444
|
};
|
1385
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
|
+
|
1386
1482
|
Object.defineProperty(exports, 'CoefficientCombineRule', {
|
1387
1483
|
enumerable: true,
|
1388
1484
|
get: function () { return rapier3dCompat.CoefficientCombineRule; }
|
@@ -1409,6 +1505,7 @@ exports.Physics = Physics;
|
|
1409
1505
|
exports.RigidBody = RigidBody;
|
1410
1506
|
exports.RoundCuboidCollider = RoundCuboidCollider;
|
1411
1507
|
exports.TrimeshCollider = TrimeshCollider;
|
1508
|
+
exports.interactionGroups = interactionGroups;
|
1412
1509
|
exports.useFixedJoint = useFixedJoint;
|
1413
1510
|
exports.useImpulseJoint = useImpulseJoint;
|
1414
1511
|
exports.usePrismaticJoint = usePrismaticJoint;
|
@@ -5,6 +5,7 @@ import { useAsset } from 'use-asset';
|
|
5
5
|
import { useFrame } from '@react-three/fiber';
|
6
6
|
import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeBufferGeometry, CapsuleBufferGeometry, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
|
7
7
|
import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils';
|
8
|
+
import { clamp } from 'three/src/math/MathUtils';
|
8
9
|
import { RoundedBoxGeometry } from 'three-stdlib';
|
9
10
|
|
10
11
|
const _quaternion = new Quaternion();
|
@@ -24,7 +25,7 @@ const rapierVector3ToVector3 = ({
|
|
24
25
|
x,
|
25
26
|
y,
|
26
27
|
z
|
27
|
-
}) => _vector3.set(x, y, z)
|
28
|
+
}) => _vector3.set(x, y, z);
|
28
29
|
const rapierQuaternionToQuaternion = ({
|
29
30
|
x,
|
30
31
|
y,
|
@@ -70,6 +71,12 @@ const scaleColliderArgs = (shape, args, scale) => {
|
|
70
71
|
const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
|
71
72
|
return newArgs.map((arg, index) => scaleArray[index] * arg);
|
72
73
|
};
|
74
|
+
|
75
|
+
const applyColliderOptions = (collider, options) => {
|
76
|
+
if (options.collisionGroups !== undefined) collider.setCollisionGroups(options.collisionGroups);
|
77
|
+
if (options.solverGroups !== undefined) collider.setSolverGroups(options.solverGroups);
|
78
|
+
};
|
79
|
+
|
73
80
|
const createColliderFromOptions = ({
|
74
81
|
options,
|
75
82
|
world,
|
@@ -123,6 +130,7 @@ const createColliderFromOptions = ({
|
|
123
130
|
}
|
124
131
|
|
125
132
|
const collider = world.createCollider(colliderDesc, rigidBody);
|
133
|
+
applyColliderOptions(collider, options);
|
126
134
|
return collider;
|
127
135
|
};
|
128
136
|
|
@@ -188,6 +196,7 @@ const createCollidersFromChildren = ({
|
|
188
196
|
});
|
189
197
|
const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
|
190
198
|
const collider = world.createCollider(desc, actualRigidBody);
|
199
|
+
applyColliderOptions(collider, options);
|
191
200
|
colliders.push(collider);
|
192
201
|
}
|
193
202
|
});
|
@@ -425,7 +434,8 @@ const Physics = ({
|
|
425
434
|
children,
|
426
435
|
timeStep: _timeStep = 1 / 60,
|
427
436
|
maxSubSteps: _maxSubSteps = 10,
|
428
|
-
paused: _paused = false
|
437
|
+
paused: _paused = false,
|
438
|
+
updatePriority
|
429
439
|
}) => {
|
430
440
|
const rapier = useAsset(importRapier);
|
431
441
|
const [isPaused, setIsPaused] = useState(_paused);
|
@@ -443,6 +453,7 @@ const Physics = ({
|
|
443
453
|
});
|
444
454
|
const [rigidBodyStates] = useState(() => new Map());
|
445
455
|
const [rigidBodyEvents] = useState(() => new Map());
|
456
|
+
const [colliderEvents] = useState(() => new Map());
|
446
457
|
const [eventQueue] = useState(() => new EventQueue(false)); // Init world
|
447
458
|
|
448
459
|
useEffect(() => {
|
@@ -472,12 +483,12 @@ const Physics = ({
|
|
472
483
|
world.timestep = _timeStep;
|
473
484
|
/**
|
474
485
|
* Fixed timeStep simulation progression
|
475
|
-
* @see https://gafferongames.com/post/fix_your_timestep/
|
486
|
+
* @see https://gafferongames.com/post/fix_your_timestep/
|
476
487
|
*/
|
477
488
|
|
478
489
|
let previousTranslations = {}; // don't step time forwards if paused
|
479
490
|
|
480
|
-
const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
|
491
|
+
const nowTime = steppingState.time += _paused ? 0 : clamp(delta, 0, 1) * 1000;
|
481
492
|
const timeStepMs = _timeStep * 1000;
|
482
493
|
const timeSinceLast = nowTime - steppingState.lastTime;
|
483
494
|
steppingState.lastTime = nowTime;
|
@@ -527,7 +538,7 @@ const Physics = ({
|
|
527
538
|
}
|
528
539
|
|
529
540
|
let oldState = previousTranslations[rigidBody.handle];
|
530
|
-
let newTranslation =
|
541
|
+
let newTranslation = rigidBody.translation();
|
531
542
|
let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
|
532
543
|
let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
|
533
544
|
let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
|
@@ -552,36 +563,65 @@ const Physics = ({
|
|
552
563
|
|
553
564
|
const rigidBody1 = world.getRigidBody(rigidBodyHandle1);
|
554
565
|
const rigidBody2 = world.getRigidBody(rigidBodyHandle2);
|
555
|
-
const
|
556
|
-
const
|
566
|
+
const rigidBody1Events = rigidBodyEvents.get(rigidBodyHandle1);
|
567
|
+
const rigidBoyd2Events = rigidBodyEvents.get(rigidBodyHandle2);
|
568
|
+
const collider1Events = colliderEvents.get(collider1.handle);
|
569
|
+
const collider2Events = colliderEvents.get(collider2.handle);
|
557
570
|
|
558
571
|
if (started) {
|
559
572
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
560
|
-
var
|
573
|
+
var _rigidBody1Events$onC, _rigidBoyd2Events$onC, _collider1Events$onCo, _collider2Events$onCo;
|
561
574
|
|
562
|
-
|
575
|
+
/* RigidBody events */
|
576
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC = rigidBody1Events.onCollisionEnter) === null || _rigidBody1Events$onC === void 0 ? void 0 : _rigidBody1Events$onC.call(rigidBody1Events, {
|
563
577
|
target: rigidBody2,
|
578
|
+
collider: collider2,
|
564
579
|
manifold,
|
565
580
|
flipped
|
566
581
|
});
|
567
|
-
|
582
|
+
rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC = rigidBoyd2Events.onCollisionEnter) === null || _rigidBoyd2Events$onC === void 0 ? void 0 : _rigidBoyd2Events$onC.call(rigidBoyd2Events, {
|
568
583
|
target: rigidBody1,
|
584
|
+
collider: collider1,
|
585
|
+
manifold,
|
586
|
+
flipped
|
587
|
+
});
|
588
|
+
/* Collider events */
|
589
|
+
|
590
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo = collider1Events.onCollisionEnter) === null || _collider1Events$onCo === void 0 ? void 0 : _collider1Events$onCo.call(collider1Events, {
|
591
|
+
target: rigidBody2,
|
592
|
+
collider: collider2,
|
593
|
+
manifold,
|
594
|
+
flipped
|
595
|
+
});
|
596
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo = collider2Events.onCollisionEnter) === null || _collider2Events$onCo === void 0 ? void 0 : _collider2Events$onCo.call(collider2Events, {
|
597
|
+
target: rigidBody1,
|
598
|
+
collider: collider1,
|
569
599
|
manifold,
|
570
600
|
flipped
|
571
601
|
});
|
572
602
|
});
|
573
603
|
} else {
|
574
|
-
var
|
604
|
+
var _rigidBody1Events$onC2, _rigidBoyd2Events$onC2, _collider1Events$onCo2, _collider2Events$onCo2;
|
575
605
|
|
576
|
-
|
577
|
-
target: rigidBody2
|
606
|
+
rigidBody1Events === null || rigidBody1Events === void 0 ? void 0 : (_rigidBody1Events$onC2 = rigidBody1Events.onCollisionExit) === null || _rigidBody1Events$onC2 === void 0 ? void 0 : _rigidBody1Events$onC2.call(rigidBody1Events, {
|
607
|
+
target: rigidBody2,
|
608
|
+
collider: collider2
|
609
|
+
});
|
610
|
+
rigidBoyd2Events === null || rigidBoyd2Events === void 0 ? void 0 : (_rigidBoyd2Events$onC2 = rigidBoyd2Events.onCollisionExit) === null || _rigidBoyd2Events$onC2 === void 0 ? void 0 : _rigidBoyd2Events$onC2.call(rigidBoyd2Events, {
|
611
|
+
target: rigidBody1,
|
612
|
+
collider: collider1
|
578
613
|
});
|
579
|
-
|
580
|
-
target:
|
614
|
+
collider1Events === null || collider1Events === void 0 ? void 0 : (_collider1Events$onCo2 = collider1Events.onCollisionExit) === null || _collider1Events$onCo2 === void 0 ? void 0 : _collider1Events$onCo2.call(collider1Events, {
|
615
|
+
target: rigidBody2,
|
616
|
+
collider: collider2
|
617
|
+
});
|
618
|
+
collider2Events === null || collider2Events === void 0 ? void 0 : (_collider2Events$onCo2 = collider2Events.onCollisionExit) === null || _collider2Events$onCo2 === void 0 ? void 0 : _collider2Events$onCo2.call(collider2Events, {
|
619
|
+
target: rigidBody1,
|
620
|
+
collider: collider1
|
581
621
|
});
|
582
622
|
}
|
583
623
|
});
|
584
|
-
});
|
624
|
+
}, updatePriority);
|
585
625
|
const api = useMemo(() => createWorldApi(getWorldRef), []);
|
586
626
|
const context = useMemo(() => ({
|
587
627
|
rapier,
|
@@ -592,6 +632,7 @@ const Physics = ({
|
|
592
632
|
},
|
593
633
|
rigidBodyStates,
|
594
634
|
rigidBodyEvents,
|
635
|
+
colliderEvents,
|
595
636
|
isPaused
|
596
637
|
}), [isPaused]);
|
597
638
|
return /*#__PURE__*/React.createElement(RapierContext.Provider, {
|
@@ -1257,22 +1298,26 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
|
|
1257
1298
|
}, props.children));
|
1258
1299
|
});
|
1259
1300
|
|
1260
|
-
const _excluded = ["children"];
|
1301
|
+
const _excluded = ["children", "onCollisionEnter", "onCollisionExit"];
|
1261
1302
|
|
1262
1303
|
const AnyCollider = _ref => {
|
1263
1304
|
let {
|
1264
|
-
children
|
1305
|
+
children,
|
1306
|
+
onCollisionEnter,
|
1307
|
+
onCollisionExit
|
1265
1308
|
} = _ref,
|
1266
1309
|
props = _objectWithoutProperties(_ref, _excluded);
|
1267
1310
|
|
1268
1311
|
const {
|
1269
|
-
world
|
1312
|
+
world,
|
1313
|
+
colliderEvents
|
1270
1314
|
} = useRapier();
|
1271
1315
|
const rigidBodyContext = useRigidBodyContext();
|
1272
1316
|
const ref = useRef(null);
|
1273
1317
|
useEffect(() => {
|
1274
1318
|
const scale = ref.current.getWorldScale(new Vector3());
|
1275
|
-
const colliders = [];
|
1319
|
+
const colliders = [];
|
1320
|
+
const hasCollisionEvents = (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents) || !!onCollisionEnter || !!onCollisionExit; // If this is an InstancedRigidBody api
|
1276
1321
|
|
1277
1322
|
if (rigidBodyContext && "at" in rigidBodyContext.api) {
|
1278
1323
|
rigidBodyContext.api.forEach((body, index) => {
|
@@ -1285,26 +1330,41 @@ const AnyCollider = _ref => {
|
|
1285
1330
|
}
|
1286
1331
|
|
1287
1332
|
colliders.push(createColliderFromOptions({
|
1288
|
-
options:
|
1333
|
+
options: _objectSpread2({
|
1334
|
+
solverGroups: rigidBodyContext.options.solverGroups,
|
1335
|
+
collisionGroups: rigidBodyContext.options.collisionGroups
|
1336
|
+
}, props),
|
1289
1337
|
world,
|
1290
1338
|
rigidBody: body.raw(),
|
1291
1339
|
scale: instanceScale,
|
1292
|
-
hasCollisionEvents
|
1340
|
+
hasCollisionEvents
|
1293
1341
|
}));
|
1294
1342
|
});
|
1295
1343
|
} else {
|
1296
1344
|
colliders.push(createColliderFromOptions({
|
1297
|
-
options:
|
1345
|
+
options: _objectSpread2({
|
1346
|
+
solverGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.solverGroups) || props.solverGroups,
|
1347
|
+
collisionGroups: (rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.options.collisionGroups) || props.collisionGroups
|
1348
|
+
}, props),
|
1298
1349
|
world,
|
1299
1350
|
// Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
|
1300
1351
|
rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
|
1301
1352
|
scale,
|
1302
|
-
hasCollisionEvents
|
1353
|
+
hasCollisionEvents
|
1303
1354
|
}));
|
1304
1355
|
}
|
1356
|
+
/* Register collision events. */
|
1357
|
+
|
1305
1358
|
|
1359
|
+
colliders.forEach(collider => colliderEvents.set(collider.handle, {
|
1360
|
+
onCollisionEnter,
|
1361
|
+
onCollisionExit
|
1362
|
+
}));
|
1306
1363
|
return () => {
|
1307
|
-
colliders.forEach(collider =>
|
1364
|
+
colliders.forEach(collider => {
|
1365
|
+
colliderEvents.delete(collider.handle);
|
1366
|
+
world.removeCollider(collider);
|
1367
|
+
});
|
1308
1368
|
};
|
1309
1369
|
}, []);
|
1310
1370
|
return /*#__PURE__*/React.createElement("object3D", {
|
@@ -1358,4 +1418,40 @@ const ConvexHullCollider = props => {
|
|
1358
1418
|
}));
|
1359
1419
|
};
|
1360
1420
|
|
1361
|
-
|
1421
|
+
/**
|
1422
|
+
* Calculates an InteractionGroup bitmask for use in the `collisionGroups` or `solverGroups`
|
1423
|
+
* properties of RigidBody or Collider components. The first argument represents a list of
|
1424
|
+
* groups the entity is in (expressed as numbers from 0 to 15). The second argument is a list
|
1425
|
+
* of groups that will be filtered against. When it is omitted, all groups are filtered against.
|
1426
|
+
*
|
1427
|
+
* @example
|
1428
|
+
* A RigidBody that is member of group 0 and will collide with everything from groups 0 and 1:
|
1429
|
+
*
|
1430
|
+
* ```tsx
|
1431
|
+
* <RigidBody collisionGroups={interactionGroups([0], [0, 1])} />
|
1432
|
+
* ```
|
1433
|
+
*
|
1434
|
+
* A RigidBody that is member of groups 0 and 1 and will collide with everything else:
|
1435
|
+
*
|
1436
|
+
* ```tsx
|
1437
|
+
* <RigidBody collisionGroups={interactionGroups([0, 1])} />
|
1438
|
+
* ```
|
1439
|
+
*
|
1440
|
+
* A RigidBody that is member of groups 0 and 1 and will not collide with anything:
|
1441
|
+
*
|
1442
|
+
* ```tsx
|
1443
|
+
* <RigidBody collisionGroups={interactionGroups([0, 1], [])} />
|
1444
|
+
* ```
|
1445
|
+
*
|
1446
|
+
* Please note that Rapier needs interaction filters to evaluate to true between _both_ colliding
|
1447
|
+
* entities for collision events to trigger.
|
1448
|
+
*
|
1449
|
+
* @param memberships Groups the collider is a member of. (Values can range from 0 to 15.)
|
1450
|
+
* @param filters Groups the interaction group should filter against. (Values can range from 0 to 15.)
|
1451
|
+
* @returns An InteractionGroup bitmask.
|
1452
|
+
*/
|
1453
|
+
const interactionGroups = (memberships, filters) => (bitmask(memberships) << 16) + (filters !== undefined ? bitmask(filters) : 0b1111111111111111);
|
1454
|
+
|
1455
|
+
const bitmask = groups => [groups].flat().reduce((acc, layer) => acc | 1 << layer, 0);
|
1456
|
+
|
1457
|
+
export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, InstancedRigidBodies, MeshCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, interactionGroups, useFixedJoint, useImpulseJoint, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useSphericalJoint };
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@react-three/rapier",
|
3
|
-
"version": "0.6.
|
3
|
+
"version": "0.6.9",
|
4
4
|
"source": "src/index.ts",
|
5
5
|
"main": "dist/react-three-rapier.cjs.js",
|
6
6
|
"module": "dist/react-three-rapier.esm.js",
|
@@ -20,12 +20,12 @@
|
|
20
20
|
"peerDependencies": {
|
21
21
|
"@react-three/fiber": "^8.0.12",
|
22
22
|
"react": "^18.0.0",
|
23
|
-
"three": "
|
24
|
-
"three-stdlib": "^2.15.0"
|
23
|
+
"three": ">=0.139.2"
|
25
24
|
},
|
26
25
|
"dependencies": {
|
27
26
|
"@dimforge/rapier3d-compat": "0.9.0",
|
28
|
-
"use-asset": "^1.0.4"
|
27
|
+
"use-asset": "^1.0.4",
|
28
|
+
"three-stdlib": "^2.15.0"
|
29
29
|
},
|
30
30
|
"repository": "https://github.com/pmndrs/react-three-rapier/tree/master/packages/react-three-rapier"
|
31
31
|
}
|
package/readme.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
<p align="center">
|
2
|
-
<img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/hero.svg" alt="@react-three/rapier"
|
2
|
+
<a href="#"><img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/hero.svg" alt="@react-three/rapier" /></a>
|
3
3
|
</p>
|
4
4
|
|
5
5
|
<p align="center">
|
6
|
-
<img src="https://img.shields.io/npm/v/@react-three/rapier?style=for-the-badge&colorA=0099DA&colorB=ffffff"
|
7
|
-
<img src="https://img.shields.io/discord/740090768164651008?style=for-the-badge&colorA=0099DA&colorB=ffffff&label=discord&logo=discord&logoColor=ffffff
|
6
|
+
<a href="https://www.npmjs.com/package/@react-three/rapier"><img src="https://img.shields.io/npm/v/@react-three/rapier?style=for-the-badge&colorA=0099DA&colorB=ffffff" /></a>
|
7
|
+
<a href="https://discord.gg/ZZjjNvJ"><img src="https://img.shields.io/discord/740090768164651008?style=for-the-badge&colorA=0099DA&colorB=ffffff&label=discord&logo=discord&logoColor=ffffff" /></a>
|
8
8
|
</p>
|
9
9
|
|
10
10
|
<p align="center">⚠️ Under heavy development. All APIs are subject to change. ⚠️</p>
|
@@ -141,7 +141,7 @@ const Scene = () => {
|
|
141
141
|
instancedApi.at(40).applyImpulse({ x: 0, y: 10, z: 0 });
|
142
142
|
|
143
143
|
// Or update all instances as if they were in an array
|
144
|
-
instancedApi.forEach(
|
144
|
+
instancedApi.forEach(api => {
|
145
145
|
api.applyImpulse({ x: 0, y: 10, z: 0 });
|
146
146
|
});
|
147
147
|
}, []);
|
@@ -153,13 +153,13 @@ const Scene = () => {
|
|
153
153
|
const rotations = Array.from({ length: COUNT }, (_, index) => [
|
154
154
|
Math.random(),
|
155
155
|
Math.random(),
|
156
|
-
Math.random()
|
156
|
+
Math.random()
|
157
157
|
]);
|
158
158
|
|
159
159
|
const scales = Array.from({ length: COUNT }, (_, index) => [
|
160
160
|
Math.random(),
|
161
161
|
Math.random(),
|
162
|
-
Math.random()
|
162
|
+
Math.random()
|
163
163
|
]);
|
164
164
|
|
165
165
|
return (
|
@@ -212,7 +212,7 @@ const Scene = () => {
|
|
212
212
|
|
213
213
|
## Events
|
214
214
|
|
215
|
-
You can subscribe collision and state events on the RigidBody
|
215
|
+
You can subscribe to collision and state events on the RigidBody:
|
216
216
|
|
217
217
|
```tsx
|
218
218
|
const RigidBottle = () => {
|
@@ -235,6 +235,60 @@ return (
|
|
235
235
|
}
|
236
236
|
```
|
237
237
|
|
238
|
+
You may also subscribe to collision events on individual colliders:
|
239
|
+
|
240
|
+
```tsx
|
241
|
+
<CuboidCollider
|
242
|
+
onCollisionEnter={payload => {
|
243
|
+
/* ... */
|
244
|
+
}}
|
245
|
+
onCollisionExit={payload => {
|
246
|
+
/* ... */
|
247
|
+
}}
|
248
|
+
/>
|
249
|
+
```
|
250
|
+
|
251
|
+
The `payload` object for all collision callbacks contains the following properties:
|
252
|
+
|
253
|
+
- `target`
|
254
|
+
The other rigidbody that was involved in the collision event.
|
255
|
+
- `collider`
|
256
|
+
The other collider that was involved in the collision event.
|
257
|
+
- `manifold` (enter only)
|
258
|
+
The [contact manifold](https://rapier.rs/javascript3d/classes/TempContactManifold.html) generated by the collision event.
|
259
|
+
- `flipped` (enter only)
|
260
|
+
`true` if the data in the `manifold` [is flipped](https://rapier.rs/javascript3d/classes/World.html#contactPair).
|
261
|
+
|
262
|
+
### Configuring collision and solver groups
|
263
|
+
|
264
|
+
Both `<RigidBody>` as well as all collider components allow you to configure `collisionsGroups` and `solverGroups` properties that configures which groups the colliders are in, and what other groups they should interact with in potential collision and solving events (you will find more details on this in the [Rapier documentation](https://rapier.rs/docs/user_guides/javascript/colliders/#collision-groups-and-solver-groups).)
|
265
|
+
|
266
|
+
Since these are set as bitmasks and bitmasks can get a bit unwieldy to generate, this library provides a helper called `interactionGroups` that can be used to generate bitmasks from numbers and arrays of groups, where groups are identified using numbers from 0 to 15.
|
267
|
+
|
268
|
+
The first argument is the group, or an array of groups, that the collider is a member of; the second argument is the group, or an array of groups, that the collider should interact with.
|
269
|
+
|
270
|
+
Here the collider is in group 0, and interacts with colliders from groups 0, 1 and 2:
|
271
|
+
|
272
|
+
```tsx
|
273
|
+
<CapsuleCollider collisionGroups={interactionGroups(0, [0, 1, 2])} />
|
274
|
+
```
|
275
|
+
|
276
|
+
This collider is in multiple groups, but only interacts with colliders from a single group:
|
277
|
+
|
278
|
+
```tsx
|
279
|
+
<CapsuleCollider collisionGroups={interactionGroups([0, 5], 7)} />
|
280
|
+
```
|
281
|
+
|
282
|
+
When the second argument is omitted, the collider will interact with all groups:
|
283
|
+
|
284
|
+
```tsx
|
285
|
+
<CapsuleCollider collisionGroups={interactionGroups(12)} />
|
286
|
+
```
|
287
|
+
|
288
|
+
> **Note** Please remember that in Rapier, for a collision (or solving) event to occur, both colliders involved in the event must match the related interaction groups -- a one-way match will be ignored.
|
289
|
+
|
290
|
+
> **Note** By default, colliders are members of all groups, and will interact with all other groups.
|
291
|
+
|
238
292
|
## Joints
|
239
293
|
|
240
294
|
WIP
|
@@ -255,7 +309,7 @@ In order, but also not necessarily:
|
|
255
309
|
- [x] Colliders outside RigidBodies
|
256
310
|
- [x] InstancedMesh support
|
257
311
|
- [x] Timestep improvements for determinism
|
258
|
-
- [
|
312
|
+
- [x] Normalize and improve collision events (add events to single Colliders)
|
313
|
+
- [ ] Add collision events to InstancedRigidBodies
|
259
314
|
- [ ] Docs
|
260
315
|
- [ ] CodeSandbox examples
|
261
|
-
- [ ] Helpers, for things like Vehicle, Rope, Player, etc
|