@react-three/rapier 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @react-three/rapier
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a3be5f6: Remove hooks api in favor of better fleshed out components
8
+
9
+ ### Patch Changes
10
+
11
+ - a3be5f6: Update types for Joints -- now only allow RefObjects of RigidBodyApi
12
+ - a3be5f6: Fix setKinematicRotation (convert Vector3 to Quaternion)
13
+ - a3be5f6: Update to @dimforge/rapier3d-compat@0.9.0
14
+ - a3be5f6: Allow setting the physics timeStep
15
+ - a3be5f6: Add rotational and transitional constraits to RigidBody
16
+ - a3be5f6: Allow updating the gravity at runtime
17
+
3
18
  ## 0.4.3
4
19
 
5
20
  ### Patch Changes
@@ -27,9 +27,31 @@ declare type EventMap = Map<ColliderHandle | RigidBodyHandle, {
27
27
  }): void;
28
28
  }>;
29
29
  interface RapierWorldProps {
30
+ children: ReactNode;
31
+ /**
32
+ * Set the gravity of the physics world
33
+ * @defaultValue [0, -9.81, 0]
34
+ */
30
35
  gravity?: Vector3Array;
36
+ /**
37
+ * Set the base automatic colliders for this physics world
38
+ * All Meshes inside RigidBodies will generate a collider
39
+ * based on this value, if not overridden.
40
+ */
31
41
  colliders?: RigidBodyAutoCollider;
32
- children: ReactNode;
42
+ /**
43
+ * Set the timestep for the simulation.
44
+ * Setting this to a number (eg. 1/60) will run the
45
+ * simulation at that framerate.
46
+ *
47
+ * "vary" will run the simulation at a delta-value based
48
+ * on the users current framerate. This ensures simulations
49
+ * run at the same percieved speed at all framerates, but
50
+ * can also lead to instability.
51
+ *
52
+ * @defaultValue "vary"
53
+ */
54
+ timeStep?: number | 'vary';
33
55
  }
34
56
  export declare const Physics: FC<RapierWorldProps>;
35
57
  export {};
@@ -101,6 +101,22 @@ export interface RigidBodyApi {
101
101
  * Resets to zero the user torques applied to this rigid-body.
102
102
  */
103
103
  resetTorques(): void;
104
+ /**
105
+ * Locks or unlocks the ability of this rigid-body to rotate.
106
+ */
107
+ lockRotations(locked: boolean): void;
108
+ /**
109
+ * Locks or unlocks the ability of this rigid-body to translate.
110
+ */
111
+ lockTranslations(locked: boolean): void;
112
+ /**
113
+ * Locks or unlocks the ability of this rigid-body to rotate along individual coordinate axes.
114
+ */
115
+ setEnabledRotations(x: boolean, y: boolean, z: boolean): void;
116
+ /**
117
+ * Locks or unlocks the ability of this rigid-body to translate along individual coordinate axes.
118
+ */
119
+ setEnabledTranslations(x: boolean, y: boolean, z: boolean): void;
104
120
  }
105
121
  export declare const createRigidBodyApi: (ref: RefGetter<RigidBody>) => RigidBodyApi;
106
122
  export declare const createColliderApi: (ref: RefGetter<Collider>) => {
@@ -118,6 +134,7 @@ export interface WorldApi {
118
134
  createImpulseJoint(params: JointData, rigidBodyA: RigidBody, rigidBodyB: RigidBody): ImpulseJoint;
119
135
  removeImpulseJoint(joint: ImpulseJoint): void;
120
136
  forEachCollider(callback: (collider: Collider) => void): void;
137
+ setGravity(gravity: Vector3): void;
121
138
  }
122
139
  export declare const createWorldApi: (ref: RefGetter<World>) => WorldApi;
123
140
  export declare const createJointApi: (ref: RefGetter<ImpulseJoint>) => {
@@ -1,47 +1,15 @@
1
1
  import React, { MutableRefObject } from "react";
2
2
  import { RapierContext } from "./Physics";
3
- import { Mesh, Object3D } from "three";
3
+ import { Object3D } from "three";
4
4
  import type Rapier from "@dimforge/rapier3d-compat";
5
5
  export declare const useRapier: () => RapierContext;
6
- import { BallArgs, CapsuleArgs, ConeArgs, ConvexHullArgs, CuboidArgs, CylinderArgs, HeightfieldArgs, PolylineArgs, RoundConvexHullArgs, RoundCuboidArgs, RoundCylinderArgs, TrimeshArgs, UseBodyOptions, UseRigidBodyOptions, UseImpulseJoint, SphericalJointParams, FixedJointParams, PrismaticJointParams, RevoluteJointParams, UseColliderOptions, RapierRigidBody, ConvexMeshArgs, RoundConvexMeshArgs, RigidBodyApi } from "./types";
7
- import { RoundCone } from "@dimforge/rapier3d-compat";
6
+ import { UseRigidBodyOptions, UseImpulseJoint, SphericalJointParams, FixedJointParams, PrismaticJointParams, RevoluteJointParams, UseColliderOptions, RigidBodyApi, RigidBodyApiRef } from "./types";
8
7
  export declare const useRigidBody: <O extends Object3D<import("three").Event>>(options?: UseRigidBodyOptions) => [React.MutableRefObject<O>, import("./api").RigidBodyApi];
9
8
  export declare const useCollider: <A>(body: RigidBodyApi, options?: UseColliderOptions<A>) => (React.MutableRefObject<Object3D<import("three").Event> | undefined> | {
10
9
  raw: () => Rapier.Collider | undefined;
11
10
  readonly handle: number;
12
11
  })[];
13
- export declare const useRigidBodyWithCollider: <A, O extends Object3D<import("three").Event> = Object3D<import("three").Event>>(rigidBodyOptions?: UseRigidBodyOptions | undefined, colliderOptions?: UseColliderOptions<A> | undefined) => [ref: React.MutableRefObject<O>, rigidBody: import("./api").RigidBodyApi];
14
- export declare const useCuboid: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<CuboidArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
15
- export declare const useBall: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<BallArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
16
- export declare const useCapsule: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<CapsuleArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
17
- export declare const useHeightfield: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<HeightfieldArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
18
- /**
19
- * Create a trimesh collider and rigid body.
20
- * Note that Trimeshes don't have mass unless provided.
21
- * See https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
22
- * for available properties.
23
- */
24
- export declare const useTrimesh: {
25
- <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<TrimeshArgs>): [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
26
- fromMesh<T_1 extends Object3D<import("three").Event>>(mesh: Mesh, rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<TrimeshArgs>): [ref: React.MutableRefObject<T_1>, rigidBody: import("./api").RigidBodyApi];
27
- };
28
- export declare const usePolyline: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<PolylineArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
29
- export declare const useRoundCuboid: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<RoundCuboidArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
30
- export declare const useCylinder: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<CylinderArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
31
- export declare const useRoundCylinder: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<RoundCylinderArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
32
- export declare const useCone: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<ConeArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
33
- export declare const useRoundCone: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<RoundCone>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
34
- export declare const useConvexHull: {
35
- <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<ConvexHullArgs>): [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
36
- fromMesh<T_1 extends Object3D<import("three").Event>>(mesh: Mesh, rigidBodyOptions?: UseBodyOptions, colliderOptions?: Omit<UseColliderOptions<ConvexHullArgs>, "colliderArgs">): [ref: React.MutableRefObject<T_1>, rigidBody: import("./api").RigidBodyApi];
37
- };
38
- export declare const useRoundConvexHull: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<RoundConvexHullArgs>) => [ref: React.MutableRefObject<T>, rigidBody: import("./api").RigidBodyApi];
39
- export declare const useConvexMesh: {
40
- <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<ConvexMeshArgs>): [ref: React.MutableRefObject<Object3D<import("three").Event>>, rigidBody: import("./api").RigidBodyApi];
41
- fromMesh<T_1 extends Object3D<import("three").Event>>(mesh: Mesh, rigidBodyOptions?: UseBodyOptions, colliderOptions?: Omit<UseColliderOptions<ConvexMeshArgs>, "colliderArgs">): [ref: React.MutableRefObject<Object3D<import("three").Event>>, rigidBody: import("./api").RigidBodyApi];
42
- };
43
- export declare const useRoundConvexMesh: <T extends Object3D<import("three").Event>>(rigidBodyOptions?: UseBodyOptions, colliderOptions?: UseColliderOptions<RoundConvexMeshArgs>) => [ref: React.MutableRefObject<Object3D<import("three").Event>>, rigidBody: import("./api").RigidBodyApi];
44
- export declare const useImpulseJoint: <T extends Rapier.ImpulseJoint>(body1: MutableRefObject<RapierRigidBody | undefined | null> | RigidBodyApi, body2: MutableRefObject<RapierRigidBody | undefined | null> | RigidBodyApi, params: Rapier.JointData) => {
12
+ export declare const useImpulseJoint: <T extends Rapier.ImpulseJoint>(body1: RigidBodyApiRef, body2: RigidBodyApiRef, params: Rapier.JointData) => {
45
13
  raw: () => Rapier.ImpulseJoint | undefined;
46
14
  readonly handle: number;
47
15
  configureMotorPosition: (targetPos: number, stiffness: number, damping: number) => void;
@@ -64,6 +64,7 @@ export declare type UseBodyOptions = Omit<UseRigidBodyOptions, "shape">;
64
64
  export declare type RigidBodyTypeString = "fixed" | "dynamic" | "kinematicPosition" | "kinematicVelocity";
65
65
  export declare type RigidBodyShape = "cuboid" | "trimesh" | "ball" | "capsule" | "convexHull" | "heightfield" | "polyline" | "roundCuboid" | "cylinder" | "roundCylinder" | "cone" | "roundCone" | "convexMesh" | "roundConvexHull" | "roundConvexMesh";
66
66
  export declare type Vector3Array = [x: number, y: number, z: number];
67
+ export declare type Boolean3Array = [x: boolean, y: boolean, z: boolean];
67
68
  export interface UseColliderOptions<A> {
68
69
  /**
69
70
  * The shape of your collider
@@ -188,6 +189,22 @@ export interface UseRigidBodyOptions {
188
189
  }): void;
189
190
  onSleep?(): void;
190
191
  onWake?(): void;
192
+ /**
193
+ * Locks all rotations that would have resulted from forces on the created rigid-body.
194
+ */
195
+ lockRotations?: boolean;
196
+ /**
197
+ * Locks all translations that would have resulted from forces on the created rigid-body.
198
+ */
199
+ lockTranslations?: boolean;
200
+ /**
201
+ * Allow rotation of this rigid-body only along specific axes.
202
+ */
203
+ enabledRotations?: Boolean3Array;
204
+ /**
205
+ * Allow rotation of this rigid-body only along specific axes.
206
+ */
207
+ enabledTranslations?: Boolean3Array;
191
208
  }
192
209
  export declare type SphericalJointParams = [
193
210
  body1Anchor: Vector3Array,
@@ -207,12 +224,12 @@ export declare type PrismaticJointParams = [
207
224
  ];
208
225
  export declare type RevoluteJointParams = [
209
226
  body1Anchor: Vector3Array,
210
- body1LocalFrame: Vector3Array,
211
227
  body2Anchor: Vector3Array,
212
- body2LocalFrame: Vector3Array
228
+ axis: Vector3Array
213
229
  ];
230
+ export declare type RigidBodyApiRef = MutableRefObject<undefined | null | RigidBodyApi>;
214
231
  export interface UseImpulseJoint<P> {
215
- (body1: MutableRefObject<RapierRigidBody | undefined | null>, body2: MutableRefObject<RapierRigidBody | undefined | null>, params: P): JointApi;
232
+ (body1: RigidBodyApiRef, body2: RigidBodyApiRef, params: P): JointApi;
216
233
  }
217
234
  export declare type RigidBodyApi = ReturnType<typeof createRigidBodyApi>;
218
235
  export declare type ColliderApi = ReturnType<typeof createColliderApi>;
@@ -1,5 +1,5 @@
1
1
  import { Collider, RigidBody } from "@dimforge/rapier3d-compat";
2
- import { Object3D, Vector3 } from "three";
2
+ import { Object3D, Quaternion, Vector3 } from "three";
3
3
  import { RigidBodyShape, RigidBodyTypeString, UseColliderOptions, UseRigidBodyOptions, Vector3Array, WorldApi } from "./types";
4
4
  export declare const vectorArrayToObject: (arr: Vector3Array) => {
5
5
  x: number;
@@ -15,3 +15,4 @@ export declare const createColliderFromOptions: <A>(options: UseColliderOptions<
15
15
  }, hasCollisionEvents?: boolean) => Collider;
16
16
  export declare const createCollidersFromChildren: (object: Object3D, rigidBody: RigidBody, options: UseRigidBodyOptions, world: WorldApi) => Collider[];
17
17
  export declare const scaleVertices: (vertices: ArrayLike<number>, scale: Vector3) => number[];
18
+ export declare const vector3ToQuaternion: (v: Vector3) => Quaternion;
@@ -207,6 +207,11 @@ const scaleVertices = (vertices, scale) => {
207
207
 
208
208
  return scaledVerts;
209
209
  };
210
+ const quaternion = new three.Quaternion();
211
+ const euler = new three.Euler();
212
+ const vector3ToQuaternion = v => {
213
+ return quaternion.setFromEuler(euler.setFromVector3(v));
214
+ };
210
215
 
211
216
  function _defineProperty(obj, key, value) {
212
217
  if (key in obj) {
@@ -318,12 +323,26 @@ const createRigidBodyApi = ref => {
318
323
  },
319
324
 
320
325
  setAngvel: velocity => ref.current().setAngvel(velocity, true),
321
- setNextKinematicRotation: rotation => ref.current().setNextKinematicRotation(_objectSpread2(_objectSpread2({}, rotation), {}, {
322
- w: 1
323
- })),
326
+ setNextKinematicRotation: ({
327
+ x,
328
+ y,
329
+ z
330
+ }) => {
331
+ const q = vector3ToQuaternion(new three.Vector3(x, y, z));
332
+ ref.current().setNextKinematicRotation({
333
+ x: q.x,
334
+ y: q.y,
335
+ z: q.z,
336
+ w: q.w
337
+ });
338
+ },
324
339
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
325
340
  resetForces: () => ref.current().resetForces(true),
326
- resetTorques: () => ref.current().resetTorques(true)
341
+ resetTorques: () => ref.current().resetTorques(true),
342
+ lockRotations: locked => ref.current().lockRotations(locked, true),
343
+ lockTranslations: locked => ref.current().lockTranslations(locked, true),
344
+ setEnabledRotations: (x, y, z) => ref.current().setEnabledRotations(x, y, z, true),
345
+ setEnabledTranslations: (x, y, z) => ref.current().setEnabledTranslations(x, y, z, true)
327
346
  };
328
347
  }; // TODO: Flesh this out
329
348
 
@@ -348,7 +367,16 @@ const createWorldApi = ref => {
348
367
  removeCollider: collider => ref.current().removeCollider(collider, true),
349
368
  createImpulseJoint: (params, rigidBodyA, rigidBodyB) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, true),
350
369
  removeImpulseJoint: joint => ref.current().removeImpulseJoint(joint, true),
351
- forEachCollider: callback => ref.current().forEachCollider(callback)
370
+ forEachCollider: callback => ref.current().forEachCollider(callback),
371
+ setGravity: ({
372
+ x,
373
+ y,
374
+ z
375
+ }) => ref.current().gravity = {
376
+ x,
377
+ y,
378
+ z
379
+ }
352
380
  };
353
381
  }; // TODO: Broken currently, waiting for Rapier3D to fix
354
382
 
@@ -376,7 +404,8 @@ const importRapier = async () => {
376
404
  const Physics = ({
377
405
  colliders: _colliders = 'cuboid',
378
406
  gravity: _gravity = [0, -9.81, 0],
379
- children
407
+ children,
408
+ timeStep: _timeStep = 'vary'
380
409
  }) => {
381
410
  const rapier = useAsset.useAsset(importRapier);
382
411
  const worldRef = React.useRef();
@@ -401,7 +430,15 @@ const Physics = ({
401
430
  worldRef.current = undefined;
402
431
  }
403
432
  };
404
- }, []);
433
+ }, []); // Update gravity
434
+
435
+ React.useEffect(() => {
436
+ const world = worldRef.current;
437
+
438
+ if (world) {
439
+ world.gravity = vectorArrayToObject(_gravity);
440
+ }
441
+ }, [_gravity]);
405
442
  const time = React.useRef(performance.now());
406
443
  fiber.useFrame(context => {
407
444
  const world = worldRef.current;
@@ -410,7 +447,13 @@ const Physics = ({
410
447
 
411
448
  const now = performance.now();
412
449
  const delta = Math.min(100, now - time.current);
413
- world.timestep = delta / 1000;
450
+
451
+ if (_timeStep === 'vary') {
452
+ world.timestep = delta / 1000;
453
+ } else {
454
+ world.timestep = _timeStep;
455
+ }
456
+
414
457
  world.step(eventQueue); // Update meshes
415
458
 
416
459
  rigidBodyMeshes.forEach((mesh, handle) => {
@@ -539,7 +582,7 @@ const useRigidBody = (options = {}) => {
539
582
  const rigidBodyRef = React.useRef();
540
583
  const getRigidBodyRef = React.useRef(() => {
541
584
  if (!rigidBodyRef.current) {
542
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd;
585
+ var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
543
586
 
544
587
  const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
545
588
  const [lvx, lvy, lvz] = (_options$linearVeloci = options === null || options === void 0 ? void 0 : options.linearVelocity) !== null && _options$linearVeloci !== void 0 ? _options$linearVeloci : [0, 0, 0];
@@ -547,11 +590,15 @@ const useRigidBody = (options = {}) => {
547
590
  const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
548
591
  const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
549
592
  const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
593
+ const [erx, ery, erz] = (_options$enabledRotat = options === null || options === void 0 ? void 0 : options.enabledRotations) !== null && _options$enabledRotat !== void 0 ? _options$enabledRotat : [true, true, true];
594
+ const [etx, ety, etz] = (_options$enabledTrans = options === null || options === void 0 ? void 0 : options.enabledTranslations) !== null && _options$enabledTrans !== void 0 ? _options$enabledTrans : [true, true, true];
550
595
  const desc = new rapier.RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
551
596
  x: avx,
552
597
  y: avy,
553
598
  z: avz
554
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled);
599
+ }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
600
+ if (options.lockRotations) desc.lockRotations();
601
+ if (options.lockTranslations) desc.lockTranslations();
555
602
  const rigidBody = world.createRigidBody(desc);
556
603
  rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
557
604
  }
@@ -648,144 +695,6 @@ const useCollider = (body, options = {}) => {
648
695
  }, []);
649
696
  const api = React.useMemo(() => createColliderApi(getColliderRef), []);
650
697
  return [objectRef, api];
651
- };
652
- const useRigidBodyWithCollider = (rigidBodyOptions, colliderOptions) => {
653
- const {
654
- world
655
- } = useRapier();
656
- const [ref, rigidBody] = useRigidBody(_objectSpread2(_objectSpread2({}, rigidBodyOptions), {}, {
657
- colliders: false
658
- }));
659
- React.useEffect(() => {
660
- if (!colliderOptions) {
661
- return;
662
- }
663
-
664
- const scale = ref.current.getWorldScale(new three.Vector3());
665
- const collider = createColliderFromOptions(colliderOptions, world, world.getRigidBody(rigidBody.handle), scale);
666
- return () => {
667
- world.removeCollider(collider);
668
- };
669
- }, []);
670
- return [ref, rigidBody];
671
- };
672
- const useCuboid = (rigidBodyOptions = {}, colliderOptions = {}) => {
673
- var _colliderOptions$args;
674
-
675
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
676
- shape: "cuboid",
677
- args: (_colliderOptions$args = colliderOptions.args) !== null && _colliderOptions$args !== void 0 ? _colliderOptions$args : [0.5, 0.5, 0.5]
678
- }, colliderOptions));
679
- };
680
- const useBall = (rigidBodyOptions = {}, colliderOptions = {}) => {
681
- var _colliderOptions$args2;
682
-
683
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
684
- shape: "ball",
685
- args: (_colliderOptions$args2 = colliderOptions.args) !== null && _colliderOptions$args2 !== void 0 ? _colliderOptions$args2 : [0.5]
686
- }, colliderOptions));
687
- };
688
- const useCapsule = (rigidBodyOptions = {}, colliderOptions = {}) => {
689
- var _colliderOptions$args3;
690
-
691
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
692
- shape: "capsule",
693
- args: (_colliderOptions$args3 = colliderOptions.args) !== null && _colliderOptions$args3 !== void 0 ? _colliderOptions$args3 : [0.5, 0.5]
694
- }, colliderOptions));
695
- };
696
- const useHeightfield = (rigidBodyOptions = {}, colliderOptions = {}) => {
697
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
698
- shape: "heightfield"
699
- }, colliderOptions));
700
- };
701
- /**
702
- * Create a trimesh collider and rigid body.
703
- * Note that Trimeshes don't have mass unless provided.
704
- * See https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
705
- * for available properties.
706
- */
707
-
708
- const useTrimesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
709
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
710
- shape: "trimesh"
711
- }, colliderOptions));
712
- };
713
-
714
- useTrimesh.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
715
- var _mesh$geometry, _mesh$geometry$index;
716
-
717
- return useTrimesh(rigidBodyOptions, _objectSpread2({
718
- args: [mesh.geometry.attributes.position.array, ((_mesh$geometry = mesh.geometry) === null || _mesh$geometry === void 0 ? void 0 : (_mesh$geometry$index = _mesh$geometry.index) === null || _mesh$geometry$index === void 0 ? void 0 : _mesh$geometry$index.array) || []]
719
- }, colliderOptions));
720
- };
721
-
722
- const usePolyline = (rigidBodyOptions = {}, colliderOptions = {}) => {
723
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
724
- shape: "polyline"
725
- }, colliderOptions));
726
- };
727
- const useRoundCuboid = (rigidBodyOptions = {}, colliderOptions = {}) => {
728
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
729
- shape: "roundCuboid"
730
- }, colliderOptions));
731
- };
732
- const useCylinder = (rigidBodyOptions = {}, colliderOptions = {}) => {
733
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
734
- shape: "cylinder"
735
- }, colliderOptions));
736
- };
737
- const useRoundCylinder = (rigidBodyOptions = {}, colliderOptions = {}) => {
738
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
739
- shape: "roundCylinder"
740
- }, colliderOptions));
741
- };
742
- const useCone = (rigidBodyOptions = {}, colliderOptions = {}) => {
743
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
744
- shape: "cone"
745
- }, colliderOptions));
746
- };
747
- const useRoundCone = (rigidBodyOptions = {}, colliderOptions = {}) => {
748
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
749
- shape: "roundCone"
750
- }, colliderOptions));
751
- };
752
- const useConvexHull = (rigidBodyOptions = {}, colliderOptions = {}) => {
753
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
754
- shape: "convexHull"
755
- }, colliderOptions));
756
- };
757
-
758
- useConvexHull.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
759
- var _mesh$geometry2, _mesh$geometry2$attri, _mesh$geometry2$attri2;
760
-
761
- return useConvexHull(rigidBodyOptions, _objectSpread2({
762
- args: [(mesh === null || mesh === void 0 ? void 0 : (_mesh$geometry2 = mesh.geometry) === null || _mesh$geometry2 === void 0 ? void 0 : (_mesh$geometry2$attri = _mesh$geometry2.attributes) === null || _mesh$geometry2$attri === void 0 ? void 0 : (_mesh$geometry2$attri2 = _mesh$geometry2$attri.position) === null || _mesh$geometry2$attri2 === void 0 ? void 0 : _mesh$geometry2$attri2.array) || []]
763
- }, colliderOptions));
764
- };
765
-
766
- const useRoundConvexHull = (rigidBodyOptions = {}, colliderOptions = {}) => {
767
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
768
- shape: "roundConvexHull"
769
- }, colliderOptions));
770
- };
771
- const useConvexMesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
772
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
773
- shape: "convexMesh"
774
- }, colliderOptions));
775
- };
776
-
777
- useConvexMesh.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
778
- var _mesh$geometry3, _mesh$geometry3$attri, _mesh$geometry3$attri2, _mesh$geometry4, _mesh$geometry4$index;
779
-
780
- return useConvexMesh(rigidBodyOptions, _objectSpread2({
781
- args: [mesh === null || mesh === void 0 ? void 0 : (_mesh$geometry3 = mesh.geometry) === null || _mesh$geometry3 === void 0 ? void 0 : (_mesh$geometry3$attri = _mesh$geometry3.attributes) === null || _mesh$geometry3$attri === void 0 ? void 0 : (_mesh$geometry3$attri2 = _mesh$geometry3$attri.position) === null || _mesh$geometry3$attri2 === void 0 ? void 0 : _mesh$geometry3$attri2.array, ((_mesh$geometry4 = mesh.geometry) === null || _mesh$geometry4 === void 0 ? void 0 : (_mesh$geometry4$index = _mesh$geometry4.index) === null || _mesh$geometry4$index === void 0 ? void 0 : _mesh$geometry4$index.array) || []]
782
- }, colliderOptions));
783
- };
784
-
785
- const useRoundConvexMesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
786
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
787
- shape: "convexMesh"
788
- }, colliderOptions));
789
698
  }; // Joints
790
699
 
791
700
  const useImpulseJoint = (body1, body2, params) => {
@@ -798,12 +707,6 @@ const useImpulseJoint = (body1, body2, params) => {
798
707
  let rb1;
799
708
  let rb2;
800
709
 
801
- if ('handle' in body1 && 'handle' in body2) {
802
- rb1 = world.getRigidBody(body1.handle);
803
- rb2 = world.getRigidBody(body2.handle);
804
- jointRef.current = world.createImpulseJoint(params, rb1, rb2);
805
- }
806
-
807
710
  if ('current' in body1 && body1.current && 'current' in body2 && body2.current) {
808
711
  rb1 = world.getRigidBody(body1.current.handle);
809
712
  rb2 = world.getRigidBody(body2.current.handle);
@@ -1163,27 +1066,11 @@ exports.Physics = Physics;
1163
1066
  exports.RigidBody = RigidBody;
1164
1067
  exports.RoundCuboidCollider = RoundCuboidCollider;
1165
1068
  exports.TrimeshCollider = TrimeshCollider;
1166
- exports.useBall = useBall;
1167
- exports.useCapsule = useCapsule;
1168
1069
  exports.useCollider = useCollider;
1169
- exports.useCone = useCone;
1170
- exports.useConvexHull = useConvexHull;
1171
- exports.useConvexMesh = useConvexMesh;
1172
- exports.useCuboid = useCuboid;
1173
- exports.useCylinder = useCylinder;
1174
1070
  exports.useFixedJoint = useFixedJoint;
1175
- exports.useHeightfield = useHeightfield;
1176
1071
  exports.useImpulseJoint = useImpulseJoint;
1177
- exports.usePolyline = usePolyline;
1178
1072
  exports.usePrismaticJoint = usePrismaticJoint;
1179
1073
  exports.useRapier = useRapier;
1180
1074
  exports.useRevoluteJoint = useRevoluteJoint;
1181
1075
  exports.useRigidBody = useRigidBody;
1182
- exports.useRigidBodyWithCollider = useRigidBodyWithCollider;
1183
- exports.useRoundCone = useRoundCone;
1184
- exports.useRoundConvexHull = useRoundConvexHull;
1185
- exports.useRoundConvexMesh = useRoundConvexMesh;
1186
- exports.useRoundCuboid = useRoundCuboid;
1187
- exports.useRoundCylinder = useRoundCylinder;
1188
1076
  exports.useSphericalJoint = useSphericalJoint;
1189
- exports.useTrimesh = useTrimesh;
@@ -207,6 +207,11 @@ const scaleVertices = (vertices, scale) => {
207
207
 
208
208
  return scaledVerts;
209
209
  };
210
+ const quaternion = new three.Quaternion();
211
+ const euler = new three.Euler();
212
+ const vector3ToQuaternion = v => {
213
+ return quaternion.setFromEuler(euler.setFromVector3(v));
214
+ };
210
215
 
211
216
  function _defineProperty(obj, key, value) {
212
217
  if (key in obj) {
@@ -318,12 +323,26 @@ const createRigidBodyApi = ref => {
318
323
  },
319
324
 
320
325
  setAngvel: velocity => ref.current().setAngvel(velocity, true),
321
- setNextKinematicRotation: rotation => ref.current().setNextKinematicRotation(_objectSpread2(_objectSpread2({}, rotation), {}, {
322
- w: 1
323
- })),
326
+ setNextKinematicRotation: ({
327
+ x,
328
+ y,
329
+ z
330
+ }) => {
331
+ const q = vector3ToQuaternion(new three.Vector3(x, y, z));
332
+ ref.current().setNextKinematicRotation({
333
+ x: q.x,
334
+ y: q.y,
335
+ z: q.z,
336
+ w: q.w
337
+ });
338
+ },
324
339
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
325
340
  resetForces: () => ref.current().resetForces(true),
326
- resetTorques: () => ref.current().resetTorques(true)
341
+ resetTorques: () => ref.current().resetTorques(true),
342
+ lockRotations: locked => ref.current().lockRotations(locked, true),
343
+ lockTranslations: locked => ref.current().lockTranslations(locked, true),
344
+ setEnabledRotations: (x, y, z) => ref.current().setEnabledRotations(x, y, z, true),
345
+ setEnabledTranslations: (x, y, z) => ref.current().setEnabledTranslations(x, y, z, true)
327
346
  };
328
347
  }; // TODO: Flesh this out
329
348
 
@@ -348,7 +367,16 @@ const createWorldApi = ref => {
348
367
  removeCollider: collider => ref.current().removeCollider(collider, true),
349
368
  createImpulseJoint: (params, rigidBodyA, rigidBodyB) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, true),
350
369
  removeImpulseJoint: joint => ref.current().removeImpulseJoint(joint, true),
351
- forEachCollider: callback => ref.current().forEachCollider(callback)
370
+ forEachCollider: callback => ref.current().forEachCollider(callback),
371
+ setGravity: ({
372
+ x,
373
+ y,
374
+ z
375
+ }) => ref.current().gravity = {
376
+ x,
377
+ y,
378
+ z
379
+ }
352
380
  };
353
381
  }; // TODO: Broken currently, waiting for Rapier3D to fix
354
382
 
@@ -376,7 +404,8 @@ const importRapier = async () => {
376
404
  const Physics = ({
377
405
  colliders: _colliders = 'cuboid',
378
406
  gravity: _gravity = [0, -9.81, 0],
379
- children
407
+ children,
408
+ timeStep: _timeStep = 'vary'
380
409
  }) => {
381
410
  const rapier = useAsset.useAsset(importRapier);
382
411
  const worldRef = React.useRef();
@@ -401,7 +430,15 @@ const Physics = ({
401
430
  worldRef.current = undefined;
402
431
  }
403
432
  };
404
- }, []);
433
+ }, []); // Update gravity
434
+
435
+ React.useEffect(() => {
436
+ const world = worldRef.current;
437
+
438
+ if (world) {
439
+ world.gravity = vectorArrayToObject(_gravity);
440
+ }
441
+ }, [_gravity]);
405
442
  const time = React.useRef(performance.now());
406
443
  fiber.useFrame(context => {
407
444
  const world = worldRef.current;
@@ -410,7 +447,13 @@ const Physics = ({
410
447
 
411
448
  const now = performance.now();
412
449
  const delta = Math.min(100, now - time.current);
413
- world.timestep = delta / 1000;
450
+
451
+ if (_timeStep === 'vary') {
452
+ world.timestep = delta / 1000;
453
+ } else {
454
+ world.timestep = _timeStep;
455
+ }
456
+
414
457
  world.step(eventQueue); // Update meshes
415
458
 
416
459
  rigidBodyMeshes.forEach((mesh, handle) => {
@@ -539,7 +582,7 @@ const useRigidBody = (options = {}) => {
539
582
  const rigidBodyRef = React.useRef();
540
583
  const getRigidBodyRef = React.useRef(() => {
541
584
  if (!rigidBodyRef.current) {
542
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd;
585
+ var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
543
586
 
544
587
  const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
545
588
  const [lvx, lvy, lvz] = (_options$linearVeloci = options === null || options === void 0 ? void 0 : options.linearVelocity) !== null && _options$linearVeloci !== void 0 ? _options$linearVeloci : [0, 0, 0];
@@ -547,11 +590,15 @@ const useRigidBody = (options = {}) => {
547
590
  const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
548
591
  const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
549
592
  const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
593
+ const [erx, ery, erz] = (_options$enabledRotat = options === null || options === void 0 ? void 0 : options.enabledRotations) !== null && _options$enabledRotat !== void 0 ? _options$enabledRotat : [true, true, true];
594
+ const [etx, ety, etz] = (_options$enabledTrans = options === null || options === void 0 ? void 0 : options.enabledTranslations) !== null && _options$enabledTrans !== void 0 ? _options$enabledTrans : [true, true, true];
550
595
  const desc = new rapier.RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
551
596
  x: avx,
552
597
  y: avy,
553
598
  z: avz
554
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled);
599
+ }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
600
+ if (options.lockRotations) desc.lockRotations();
601
+ if (options.lockTranslations) desc.lockTranslations();
555
602
  const rigidBody = world.createRigidBody(desc);
556
603
  rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
557
604
  }
@@ -648,144 +695,6 @@ const useCollider = (body, options = {}) => {
648
695
  }, []);
649
696
  const api = React.useMemo(() => createColliderApi(getColliderRef), []);
650
697
  return [objectRef, api];
651
- };
652
- const useRigidBodyWithCollider = (rigidBodyOptions, colliderOptions) => {
653
- const {
654
- world
655
- } = useRapier();
656
- const [ref, rigidBody] = useRigidBody(_objectSpread2(_objectSpread2({}, rigidBodyOptions), {}, {
657
- colliders: false
658
- }));
659
- React.useEffect(() => {
660
- if (!colliderOptions) {
661
- return;
662
- }
663
-
664
- const scale = ref.current.getWorldScale(new three.Vector3());
665
- const collider = createColliderFromOptions(colliderOptions, world, world.getRigidBody(rigidBody.handle), scale);
666
- return () => {
667
- world.removeCollider(collider);
668
- };
669
- }, []);
670
- return [ref, rigidBody];
671
- };
672
- const useCuboid = (rigidBodyOptions = {}, colliderOptions = {}) => {
673
- var _colliderOptions$args;
674
-
675
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
676
- shape: "cuboid",
677
- args: (_colliderOptions$args = colliderOptions.args) !== null && _colliderOptions$args !== void 0 ? _colliderOptions$args : [0.5, 0.5, 0.5]
678
- }, colliderOptions));
679
- };
680
- const useBall = (rigidBodyOptions = {}, colliderOptions = {}) => {
681
- var _colliderOptions$args2;
682
-
683
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
684
- shape: "ball",
685
- args: (_colliderOptions$args2 = colliderOptions.args) !== null && _colliderOptions$args2 !== void 0 ? _colliderOptions$args2 : [0.5]
686
- }, colliderOptions));
687
- };
688
- const useCapsule = (rigidBodyOptions = {}, colliderOptions = {}) => {
689
- var _colliderOptions$args3;
690
-
691
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
692
- shape: "capsule",
693
- args: (_colliderOptions$args3 = colliderOptions.args) !== null && _colliderOptions$args3 !== void 0 ? _colliderOptions$args3 : [0.5, 0.5]
694
- }, colliderOptions));
695
- };
696
- const useHeightfield = (rigidBodyOptions = {}, colliderOptions = {}) => {
697
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
698
- shape: "heightfield"
699
- }, colliderOptions));
700
- };
701
- /**
702
- * Create a trimesh collider and rigid body.
703
- * Note that Trimeshes don't have mass unless provided.
704
- * See https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
705
- * for available properties.
706
- */
707
-
708
- const useTrimesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
709
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
710
- shape: "trimesh"
711
- }, colliderOptions));
712
- };
713
-
714
- useTrimesh.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
715
- var _mesh$geometry, _mesh$geometry$index;
716
-
717
- return useTrimesh(rigidBodyOptions, _objectSpread2({
718
- args: [mesh.geometry.attributes.position.array, ((_mesh$geometry = mesh.geometry) === null || _mesh$geometry === void 0 ? void 0 : (_mesh$geometry$index = _mesh$geometry.index) === null || _mesh$geometry$index === void 0 ? void 0 : _mesh$geometry$index.array) || []]
719
- }, colliderOptions));
720
- };
721
-
722
- const usePolyline = (rigidBodyOptions = {}, colliderOptions = {}) => {
723
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
724
- shape: "polyline"
725
- }, colliderOptions));
726
- };
727
- const useRoundCuboid = (rigidBodyOptions = {}, colliderOptions = {}) => {
728
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
729
- shape: "roundCuboid"
730
- }, colliderOptions));
731
- };
732
- const useCylinder = (rigidBodyOptions = {}, colliderOptions = {}) => {
733
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
734
- shape: "cylinder"
735
- }, colliderOptions));
736
- };
737
- const useRoundCylinder = (rigidBodyOptions = {}, colliderOptions = {}) => {
738
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
739
- shape: "roundCylinder"
740
- }, colliderOptions));
741
- };
742
- const useCone = (rigidBodyOptions = {}, colliderOptions = {}) => {
743
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
744
- shape: "cone"
745
- }, colliderOptions));
746
- };
747
- const useRoundCone = (rigidBodyOptions = {}, colliderOptions = {}) => {
748
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
749
- shape: "roundCone"
750
- }, colliderOptions));
751
- };
752
- const useConvexHull = (rigidBodyOptions = {}, colliderOptions = {}) => {
753
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
754
- shape: "convexHull"
755
- }, colliderOptions));
756
- };
757
-
758
- useConvexHull.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
759
- var _mesh$geometry2, _mesh$geometry2$attri, _mesh$geometry2$attri2;
760
-
761
- return useConvexHull(rigidBodyOptions, _objectSpread2({
762
- args: [(mesh === null || mesh === void 0 ? void 0 : (_mesh$geometry2 = mesh.geometry) === null || _mesh$geometry2 === void 0 ? void 0 : (_mesh$geometry2$attri = _mesh$geometry2.attributes) === null || _mesh$geometry2$attri === void 0 ? void 0 : (_mesh$geometry2$attri2 = _mesh$geometry2$attri.position) === null || _mesh$geometry2$attri2 === void 0 ? void 0 : _mesh$geometry2$attri2.array) || []]
763
- }, colliderOptions));
764
- };
765
-
766
- const useRoundConvexHull = (rigidBodyOptions = {}, colliderOptions = {}) => {
767
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
768
- shape: "roundConvexHull"
769
- }, colliderOptions));
770
- };
771
- const useConvexMesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
772
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
773
- shape: "convexMesh"
774
- }, colliderOptions));
775
- };
776
-
777
- useConvexMesh.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
778
- var _mesh$geometry3, _mesh$geometry3$attri, _mesh$geometry3$attri2, _mesh$geometry4, _mesh$geometry4$index;
779
-
780
- return useConvexMesh(rigidBodyOptions, _objectSpread2({
781
- args: [mesh === null || mesh === void 0 ? void 0 : (_mesh$geometry3 = mesh.geometry) === null || _mesh$geometry3 === void 0 ? void 0 : (_mesh$geometry3$attri = _mesh$geometry3.attributes) === null || _mesh$geometry3$attri === void 0 ? void 0 : (_mesh$geometry3$attri2 = _mesh$geometry3$attri.position) === null || _mesh$geometry3$attri2 === void 0 ? void 0 : _mesh$geometry3$attri2.array, ((_mesh$geometry4 = mesh.geometry) === null || _mesh$geometry4 === void 0 ? void 0 : (_mesh$geometry4$index = _mesh$geometry4.index) === null || _mesh$geometry4$index === void 0 ? void 0 : _mesh$geometry4$index.array) || []]
782
- }, colliderOptions));
783
- };
784
-
785
- const useRoundConvexMesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
786
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
787
- shape: "convexMesh"
788
- }, colliderOptions));
789
698
  }; // Joints
790
699
 
791
700
  const useImpulseJoint = (body1, body2, params) => {
@@ -798,12 +707,6 @@ const useImpulseJoint = (body1, body2, params) => {
798
707
  let rb1;
799
708
  let rb2;
800
709
 
801
- if ('handle' in body1 && 'handle' in body2) {
802
- rb1 = world.getRigidBody(body1.handle);
803
- rb2 = world.getRigidBody(body2.handle);
804
- jointRef.current = world.createImpulseJoint(params, rb1, rb2);
805
- }
806
-
807
710
  if ('current' in body1 && body1.current && 'current' in body2 && body2.current) {
808
711
  rb1 = world.getRigidBody(body1.current.handle);
809
712
  rb2 = world.getRigidBody(body2.current.handle);
@@ -1163,27 +1066,11 @@ exports.Physics = Physics;
1163
1066
  exports.RigidBody = RigidBody;
1164
1067
  exports.RoundCuboidCollider = RoundCuboidCollider;
1165
1068
  exports.TrimeshCollider = TrimeshCollider;
1166
- exports.useBall = useBall;
1167
- exports.useCapsule = useCapsule;
1168
1069
  exports.useCollider = useCollider;
1169
- exports.useCone = useCone;
1170
- exports.useConvexHull = useConvexHull;
1171
- exports.useConvexMesh = useConvexMesh;
1172
- exports.useCuboid = useCuboid;
1173
- exports.useCylinder = useCylinder;
1174
1070
  exports.useFixedJoint = useFixedJoint;
1175
- exports.useHeightfield = useHeightfield;
1176
1071
  exports.useImpulseJoint = useImpulseJoint;
1177
- exports.usePolyline = usePolyline;
1178
1072
  exports.usePrismaticJoint = usePrismaticJoint;
1179
1073
  exports.useRapier = useRapier;
1180
1074
  exports.useRevoluteJoint = useRevoluteJoint;
1181
1075
  exports.useRigidBody = useRigidBody;
1182
- exports.useRigidBodyWithCollider = useRigidBodyWithCollider;
1183
- exports.useRoundCone = useRoundCone;
1184
- exports.useRoundConvexHull = useRoundConvexHull;
1185
- exports.useRoundConvexMesh = useRoundConvexMesh;
1186
- exports.useRoundCuboid = useRoundCuboid;
1187
- exports.useRoundCylinder = useRoundCylinder;
1188
1076
  exports.useSphericalJoint = useSphericalJoint;
1189
- exports.useTrimesh = useTrimesh;
@@ -3,7 +3,7 @@ import { useAsset } from 'use-asset';
3
3
  import { useFrame } from '@react-three/fiber';
4
4
  import { ColliderDesc, CoefficientCombineRule, ActiveEvents, EventQueue, ShapeType } from '@dimforge/rapier3d-compat';
5
5
  export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
6
- import { Vector3, Quaternion, Object3D, Euler, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry } from 'three';
6
+ import { Quaternion, Euler, Vector3, Object3D, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry } from 'three';
7
7
 
8
8
  const vectorArrayToObject = arr => {
9
9
  const [x, y, z] = arr;
@@ -182,6 +182,11 @@ const scaleVertices = (vertices, scale) => {
182
182
 
183
183
  return scaledVerts;
184
184
  };
185
+ const quaternion = new Quaternion();
186
+ const euler = new Euler();
187
+ const vector3ToQuaternion = v => {
188
+ return quaternion.setFromEuler(euler.setFromVector3(v));
189
+ };
185
190
 
186
191
  function _defineProperty(obj, key, value) {
187
192
  if (key in obj) {
@@ -293,12 +298,26 @@ const createRigidBodyApi = ref => {
293
298
  },
294
299
 
295
300
  setAngvel: velocity => ref.current().setAngvel(velocity, true),
296
- setNextKinematicRotation: rotation => ref.current().setNextKinematicRotation(_objectSpread2(_objectSpread2({}, rotation), {}, {
297
- w: 1
298
- })),
301
+ setNextKinematicRotation: ({
302
+ x,
303
+ y,
304
+ z
305
+ }) => {
306
+ const q = vector3ToQuaternion(new Vector3(x, y, z));
307
+ ref.current().setNextKinematicRotation({
308
+ x: q.x,
309
+ y: q.y,
310
+ z: q.z,
311
+ w: q.w
312
+ });
313
+ },
299
314
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
300
315
  resetForces: () => ref.current().resetForces(true),
301
- resetTorques: () => ref.current().resetTorques(true)
316
+ resetTorques: () => ref.current().resetTorques(true),
317
+ lockRotations: locked => ref.current().lockRotations(locked, true),
318
+ lockTranslations: locked => ref.current().lockTranslations(locked, true),
319
+ setEnabledRotations: (x, y, z) => ref.current().setEnabledRotations(x, y, z, true),
320
+ setEnabledTranslations: (x, y, z) => ref.current().setEnabledTranslations(x, y, z, true)
302
321
  };
303
322
  }; // TODO: Flesh this out
304
323
 
@@ -323,7 +342,16 @@ const createWorldApi = ref => {
323
342
  removeCollider: collider => ref.current().removeCollider(collider, true),
324
343
  createImpulseJoint: (params, rigidBodyA, rigidBodyB) => ref.current().createImpulseJoint(params, rigidBodyA, rigidBodyB, true),
325
344
  removeImpulseJoint: joint => ref.current().removeImpulseJoint(joint, true),
326
- forEachCollider: callback => ref.current().forEachCollider(callback)
345
+ forEachCollider: callback => ref.current().forEachCollider(callback),
346
+ setGravity: ({
347
+ x,
348
+ y,
349
+ z
350
+ }) => ref.current().gravity = {
351
+ x,
352
+ y,
353
+ z
354
+ }
327
355
  };
328
356
  }; // TODO: Broken currently, waiting for Rapier3D to fix
329
357
 
@@ -351,7 +379,8 @@ const importRapier = async () => {
351
379
  const Physics = ({
352
380
  colliders: _colliders = 'cuboid',
353
381
  gravity: _gravity = [0, -9.81, 0],
354
- children
382
+ children,
383
+ timeStep: _timeStep = 'vary'
355
384
  }) => {
356
385
  const rapier = useAsset(importRapier);
357
386
  const worldRef = useRef();
@@ -376,7 +405,15 @@ const Physics = ({
376
405
  worldRef.current = undefined;
377
406
  }
378
407
  };
379
- }, []);
408
+ }, []); // Update gravity
409
+
410
+ useEffect(() => {
411
+ const world = worldRef.current;
412
+
413
+ if (world) {
414
+ world.gravity = vectorArrayToObject(_gravity);
415
+ }
416
+ }, [_gravity]);
380
417
  const time = useRef(performance.now());
381
418
  useFrame(context => {
382
419
  const world = worldRef.current;
@@ -385,7 +422,13 @@ const Physics = ({
385
422
 
386
423
  const now = performance.now();
387
424
  const delta = Math.min(100, now - time.current);
388
- world.timestep = delta / 1000;
425
+
426
+ if (_timeStep === 'vary') {
427
+ world.timestep = delta / 1000;
428
+ } else {
429
+ world.timestep = _timeStep;
430
+ }
431
+
389
432
  world.step(eventQueue); // Update meshes
390
433
 
391
434
  rigidBodyMeshes.forEach((mesh, handle) => {
@@ -514,7 +557,7 @@ const useRigidBody = (options = {}) => {
514
557
  const rigidBodyRef = useRef();
515
558
  const getRigidBodyRef = useRef(() => {
516
559
  if (!rigidBodyRef.current) {
517
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd;
560
+ var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
518
561
 
519
562
  const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
520
563
  const [lvx, lvy, lvz] = (_options$linearVeloci = options === null || options === void 0 ? void 0 : options.linearVelocity) !== null && _options$linearVeloci !== void 0 ? _options$linearVeloci : [0, 0, 0];
@@ -522,11 +565,15 @@ const useRigidBody = (options = {}) => {
522
565
  const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
523
566
  const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
524
567
  const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
568
+ const [erx, ery, erz] = (_options$enabledRotat = options === null || options === void 0 ? void 0 : options.enabledRotations) !== null && _options$enabledRotat !== void 0 ? _options$enabledRotat : [true, true, true];
569
+ const [etx, ety, etz] = (_options$enabledTrans = options === null || options === void 0 ? void 0 : options.enabledTranslations) !== null && _options$enabledTrans !== void 0 ? _options$enabledTrans : [true, true, true];
525
570
  const desc = new rapier.RigidBodyDesc(type).setLinvel(lvx, lvy, lvz).setAngvel({
526
571
  x: avx,
527
572
  y: avy,
528
573
  z: avz
529
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled);
574
+ }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
575
+ if (options.lockRotations) desc.lockRotations();
576
+ if (options.lockTranslations) desc.lockTranslations();
530
577
  const rigidBody = world.createRigidBody(desc);
531
578
  rigidBodyRef.current = world.getRigidBody(rigidBody.handle);
532
579
  }
@@ -623,144 +670,6 @@ const useCollider = (body, options = {}) => {
623
670
  }, []);
624
671
  const api = useMemo(() => createColliderApi(getColliderRef), []);
625
672
  return [objectRef, api];
626
- };
627
- const useRigidBodyWithCollider = (rigidBodyOptions, colliderOptions) => {
628
- const {
629
- world
630
- } = useRapier();
631
- const [ref, rigidBody] = useRigidBody(_objectSpread2(_objectSpread2({}, rigidBodyOptions), {}, {
632
- colliders: false
633
- }));
634
- useEffect(() => {
635
- if (!colliderOptions) {
636
- return;
637
- }
638
-
639
- const scale = ref.current.getWorldScale(new Vector3());
640
- const collider = createColliderFromOptions(colliderOptions, world, world.getRigidBody(rigidBody.handle), scale);
641
- return () => {
642
- world.removeCollider(collider);
643
- };
644
- }, []);
645
- return [ref, rigidBody];
646
- };
647
- const useCuboid = (rigidBodyOptions = {}, colliderOptions = {}) => {
648
- var _colliderOptions$args;
649
-
650
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
651
- shape: "cuboid",
652
- args: (_colliderOptions$args = colliderOptions.args) !== null && _colliderOptions$args !== void 0 ? _colliderOptions$args : [0.5, 0.5, 0.5]
653
- }, colliderOptions));
654
- };
655
- const useBall = (rigidBodyOptions = {}, colliderOptions = {}) => {
656
- var _colliderOptions$args2;
657
-
658
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
659
- shape: "ball",
660
- args: (_colliderOptions$args2 = colliderOptions.args) !== null && _colliderOptions$args2 !== void 0 ? _colliderOptions$args2 : [0.5]
661
- }, colliderOptions));
662
- };
663
- const useCapsule = (rigidBodyOptions = {}, colliderOptions = {}) => {
664
- var _colliderOptions$args3;
665
-
666
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
667
- shape: "capsule",
668
- args: (_colliderOptions$args3 = colliderOptions.args) !== null && _colliderOptions$args3 !== void 0 ? _colliderOptions$args3 : [0.5, 0.5]
669
- }, colliderOptions));
670
- };
671
- const useHeightfield = (rigidBodyOptions = {}, colliderOptions = {}) => {
672
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
673
- shape: "heightfield"
674
- }, colliderOptions));
675
- };
676
- /**
677
- * Create a trimesh collider and rigid body.
678
- * Note that Trimeshes don't have mass unless provided.
679
- * See https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
680
- * for available properties.
681
- */
682
-
683
- const useTrimesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
684
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
685
- shape: "trimesh"
686
- }, colliderOptions));
687
- };
688
-
689
- useTrimesh.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
690
- var _mesh$geometry, _mesh$geometry$index;
691
-
692
- return useTrimesh(rigidBodyOptions, _objectSpread2({
693
- args: [mesh.geometry.attributes.position.array, ((_mesh$geometry = mesh.geometry) === null || _mesh$geometry === void 0 ? void 0 : (_mesh$geometry$index = _mesh$geometry.index) === null || _mesh$geometry$index === void 0 ? void 0 : _mesh$geometry$index.array) || []]
694
- }, colliderOptions));
695
- };
696
-
697
- const usePolyline = (rigidBodyOptions = {}, colliderOptions = {}) => {
698
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
699
- shape: "polyline"
700
- }, colliderOptions));
701
- };
702
- const useRoundCuboid = (rigidBodyOptions = {}, colliderOptions = {}) => {
703
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
704
- shape: "roundCuboid"
705
- }, colliderOptions));
706
- };
707
- const useCylinder = (rigidBodyOptions = {}, colliderOptions = {}) => {
708
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
709
- shape: "cylinder"
710
- }, colliderOptions));
711
- };
712
- const useRoundCylinder = (rigidBodyOptions = {}, colliderOptions = {}) => {
713
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
714
- shape: "roundCylinder"
715
- }, colliderOptions));
716
- };
717
- const useCone = (rigidBodyOptions = {}, colliderOptions = {}) => {
718
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
719
- shape: "cone"
720
- }, colliderOptions));
721
- };
722
- const useRoundCone = (rigidBodyOptions = {}, colliderOptions = {}) => {
723
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
724
- shape: "roundCone"
725
- }, colliderOptions));
726
- };
727
- const useConvexHull = (rigidBodyOptions = {}, colliderOptions = {}) => {
728
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
729
- shape: "convexHull"
730
- }, colliderOptions));
731
- };
732
-
733
- useConvexHull.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
734
- var _mesh$geometry2, _mesh$geometry2$attri, _mesh$geometry2$attri2;
735
-
736
- return useConvexHull(rigidBodyOptions, _objectSpread2({
737
- args: [(mesh === null || mesh === void 0 ? void 0 : (_mesh$geometry2 = mesh.geometry) === null || _mesh$geometry2 === void 0 ? void 0 : (_mesh$geometry2$attri = _mesh$geometry2.attributes) === null || _mesh$geometry2$attri === void 0 ? void 0 : (_mesh$geometry2$attri2 = _mesh$geometry2$attri.position) === null || _mesh$geometry2$attri2 === void 0 ? void 0 : _mesh$geometry2$attri2.array) || []]
738
- }, colliderOptions));
739
- };
740
-
741
- const useRoundConvexHull = (rigidBodyOptions = {}, colliderOptions = {}) => {
742
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
743
- shape: "roundConvexHull"
744
- }, colliderOptions));
745
- };
746
- const useConvexMesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
747
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
748
- shape: "convexMesh"
749
- }, colliderOptions));
750
- };
751
-
752
- useConvexMesh.fromMesh = (mesh, rigidBodyOptions = {}, colliderOptions = {}) => {
753
- var _mesh$geometry3, _mesh$geometry3$attri, _mesh$geometry3$attri2, _mesh$geometry4, _mesh$geometry4$index;
754
-
755
- return useConvexMesh(rigidBodyOptions, _objectSpread2({
756
- args: [mesh === null || mesh === void 0 ? void 0 : (_mesh$geometry3 = mesh.geometry) === null || _mesh$geometry3 === void 0 ? void 0 : (_mesh$geometry3$attri = _mesh$geometry3.attributes) === null || _mesh$geometry3$attri === void 0 ? void 0 : (_mesh$geometry3$attri2 = _mesh$geometry3$attri.position) === null || _mesh$geometry3$attri2 === void 0 ? void 0 : _mesh$geometry3$attri2.array, ((_mesh$geometry4 = mesh.geometry) === null || _mesh$geometry4 === void 0 ? void 0 : (_mesh$geometry4$index = _mesh$geometry4.index) === null || _mesh$geometry4$index === void 0 ? void 0 : _mesh$geometry4$index.array) || []]
757
- }, colliderOptions));
758
- };
759
-
760
- const useRoundConvexMesh = (rigidBodyOptions = {}, colliderOptions = {}) => {
761
- return useRigidBodyWithCollider(rigidBodyOptions, _objectSpread2({
762
- shape: "convexMesh"
763
- }, colliderOptions));
764
673
  }; // Joints
765
674
 
766
675
  const useImpulseJoint = (body1, body2, params) => {
@@ -773,12 +682,6 @@ const useImpulseJoint = (body1, body2, params) => {
773
682
  let rb1;
774
683
  let rb2;
775
684
 
776
- if ('handle' in body1 && 'handle' in body2) {
777
- rb1 = world.getRigidBody(body1.handle);
778
- rb2 = world.getRigidBody(body2.handle);
779
- jointRef.current = world.createImpulseJoint(params, rb1, rb2);
780
- }
781
-
782
685
  if ('current' in body1 && body1.current && 'current' in body2 && body2.current) {
783
686
  rb1 = world.getRigidBody(body1.current.handle);
784
687
  rb2 = world.getRigidBody(body2.current.handle);
@@ -1114,4 +1017,4 @@ const Debug = () => {
1114
1017
  })));
1115
1018
  };
1116
1019
 
1117
- export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, useBall, useCapsule, useCollider, useCone, useConvexHull, useConvexMesh, useCuboid, useCylinder, useFixedJoint, useHeightfield, useImpulseJoint, usePolyline, usePrismaticJoint, useRapier, useRevoluteJoint, useRigidBody, useRigidBodyWithCollider, useRoundCone, useRoundConvexHull, useRoundConvexMesh, useRoundCuboid, useRoundCylinder, useSphericalJoint, useTrimesh };
1020
+ export { BallCollider, CapsuleCollider, ConeCollider, ConvexHullCollider, CuboidCollider, CylinderCollider, Debug, HeightfieldCollider, Physics, RigidBody, RoundCuboidCollider, TrimeshCollider, useCollider, 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.4.3",
3
+ "version": "0.5.0",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
@@ -23,7 +23,7 @@
23
23
  "three": "^0.139.2"
24
24
  },
25
25
  "dependencies": {
26
- "@dimforge/rapier3d-compat": "0.8.1",
26
+ "@dimforge/rapier3d-compat": "0.9.0",
27
27
  "use-asset": "^1.0.4"
28
28
  },
29
29
  "repository": "https://github.com/pmndrs/react-three-rapier/tree/master/packages/react-three-rapier"
package/readme.md CHANGED
@@ -134,7 +134,7 @@ return (
134
134
  colliders="hull"
135
135
  onSleep={() => setIsAsleep(true)}
136
136
  onWake={() => setIsAsleep(false)}
137
- onCollision={({manifold}) => {
137
+ onCollisionEnter={({manifold}) => {
138
138
  console.log('Collision at world position ', manifold.solverContactPoint(0))
139
139
  }}
140
140
  >
@@ -146,24 +146,9 @@ return (
146
146
  }
147
147
  ```
148
148
 
149
- ## Hooks
149
+ ## Joints
150
150
 
151
- You can also use hooks to generate rigid bodies and colliders, but it's not encouraged.
152
-
153
- ```tsx
154
- import { Box } from "@react-three/drei";
155
- import { useCuboid } from "@react-three/rapier";
156
-
157
- const RigidBox = () => {
158
- // Generates a RigidBody and attaches a BoxCollider to it, returns a ref
159
- const [box, rigidBody, collider] = useCuboid(
160
- { position: [1, 1, 1] },
161
- { args: [0.5, 0.5, 0.5] }
162
- );
163
-
164
- return <Box ref={box} />;
165
- };
166
- ```
151
+ WIP
167
152
 
168
153
  ## Roadmap?
169
154
 
@@ -174,8 +159,9 @@ In order, but also not necessarily:
174
159
  - [x] Nested objects retain world transforms
175
160
  - [x] Nested objects retain correct collider scale
176
161
  - [x] Automatic colliders based on rigidbody children
177
- - [ ] Translation and rotational constraints
162
+ - [x] Translation and rotational constraints
178
163
  - [x] Collision events
164
+ - [ ] Colliders outside RigidBodies
179
165
  - [ ] InstancedMesh support
180
166
  - [ ] Docs
181
167
  - [ ] CodeSandbox examples