@react-three/rapier 0.6.1 → 0.6.4

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.
@@ -2,9 +2,9 @@ import React from "react";
2
2
  import { InstancedRigidBodyApi } from "./api";
3
3
  import { RigidBodyProps } from "./RigidBody";
4
4
  import { Vector3Array } from "./types";
5
- interface InstancedRigidBodiesProps extends Omit<RigidBodyProps, "position" | "rotation" | "onCollisionEnter" | "onCollisionExit"> {
5
+ export interface InstancedRigidBodiesProps extends Omit<RigidBodyProps, "position" | "rotation" | "onCollisionEnter" | "onCollisionExit"> {
6
6
  positions?: Vector3Array[];
7
7
  rotations?: Vector3Array[];
8
+ scales?: Vector3Array[];
8
9
  }
9
10
  export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<InstancedRigidBodiesProps & React.RefAttributes<InstancedRigidBodyApi>>;
10
- export {};
@@ -10,7 +10,8 @@ export interface RapierContext {
10
10
  rigidBodyStates: Map<RigidBodyHandle, {
11
11
  mesh: Object3D;
12
12
  isSleeping: boolean;
13
- setMatrix: (mat: Matrix4) => void;
13
+ setMatrix(mat: Matrix4): void;
14
+ getMatrix(): Matrix4;
14
15
  worldScale: Vector3;
15
16
  invertedMatrixWorld: Matrix4;
16
17
  }>;
@@ -58,6 +59,12 @@ interface RapierWorldProps {
58
59
  * @defaultValue "vary"
59
60
  */
60
61
  timeStep?: number | "vary";
62
+ /**
63
+ * Pause the physics simulation
64
+ *
65
+ * @defaultValue false
66
+ */
67
+ paused?: boolean;
61
68
  }
62
69
  export declare const Physics: FC<RapierWorldProps>;
63
70
  export {};
@@ -1,12 +1,20 @@
1
- import React, { MutableRefObject } from "react";
1
+ import React, { MutableRefObject, RefObject } from "react";
2
2
  import { ReactNode } from "react";
3
3
  import { Object3D } from "three";
4
+ import { InstancedRigidBodyApi } from "./api";
5
+ import { InstancedRigidBodiesProps } from "./InstancedRigidBodies";
4
6
  import { RigidBodyApi, UseRigidBodyOptions } from "./types";
7
+ export declare const RigidBodyContext: React.Context<{
8
+ ref: RefObject<Object3D> | MutableRefObject<Object3D>;
9
+ api: RigidBodyApi | InstancedRigidBodyApi;
10
+ hasCollisionEvents: boolean;
11
+ options: UseRigidBodyOptions | InstancedRigidBodiesProps;
12
+ }>;
5
13
  export declare const useRigidBodyContext: () => {
6
- ref: MutableRefObject<Object3D>;
7
- api: RigidBodyApi;
14
+ ref: RefObject<Object3D> | MutableRefObject<Object3D>;
15
+ api: RigidBodyApi | InstancedRigidBodyApi;
8
16
  hasCollisionEvents: boolean;
9
- options: UseRigidBodyOptions;
17
+ options: UseRigidBodyOptions | InstancedRigidBodiesProps;
10
18
  };
11
19
  export interface RigidBodyProps extends UseRigidBodyOptions {
12
20
  children?: ReactNode;
@@ -75,6 +75,22 @@ export interface RigidBodyApi {
75
75
  * Sets the angular velocity of this rigid-body.
76
76
  */
77
77
  setAngvel(velocity: Vector3Object): void;
78
+ /**
79
+ * The linear damping of this rigid-body.
80
+ */
81
+ linearDamping(): number;
82
+ /**
83
+ * Sets the linear damping factor applied to this rigid-body.
84
+ */
85
+ setLinearDamping(factor: number): void;
86
+ /**
87
+ * The angular damping of this rigid-body.
88
+ */
89
+ angularDamping(): number;
90
+ /**
91
+ * Sets the anugular damping factor applied to this rigid-body.
92
+ */
93
+ setAngularDamping(factor: number): void;
78
94
  /**
79
95
  * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
80
96
  *
@@ -1,8 +1,8 @@
1
1
  import { MutableRefObject } from "react";
2
- import { CoefficientCombineRule, RigidBody as RapierRigidBody, Collider as RapierCollider, TempContactManifold } from "@dimforge/rapier3d-compat";
2
+ import { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody, TempContactManifold } from "@dimforge/rapier3d-compat";
3
3
  import { createColliderApi, createJointApi, createRigidBodyApi, createWorldApi } from "./api";
4
- export { RapierRigidBody, RapierCollider };
5
4
  export { CoefficientCombineRule as CoefficientCombineRule } from "@dimforge/rapier3d-compat";
5
+ export { RapierRigidBody, RapierCollider };
6
6
  export declare type RefGetter<T> = MutableRefObject<() => T | undefined>;
7
7
  export declare type RigidBodyAutoCollider = "ball" | "cuboid" | "hull" | "trimesh" | false;
8
8
  export interface UseRigidBodyAPI {
@@ -126,6 +126,10 @@ export interface UseRigidBodyOptions {
126
126
  * default: true
127
127
  */
128
128
  canSleep?: boolean;
129
+ /** The linear damping coefficient of this rigid-body.*/
130
+ linearDamping?: number;
131
+ /** The angular damping coefficient of this rigid-body.*/
132
+ angularDamping?: number;
129
133
  /** The linear velocity of this body.
130
134
  * default: zero velocity
131
135
  */
@@ -1,11 +1,7 @@
1
- import { Collider, ColliderDesc, RigidBody, RigidBodyDesc, Vector3 as RapierVector3, Quaternion as RapierQuaternion } from "@dimforge/rapier3d-compat";
1
+ import { Collider, ColliderDesc, Quaternion as RapierQuaternion, RigidBody, RigidBodyDesc, Vector3 as RapierVector3 } from "@dimforge/rapier3d-compat";
2
2
  import { BufferGeometry, Matrix4, Object3D, Quaternion, Vector3 } from "three";
3
3
  import { RigidBodyApi, RigidBodyAutoCollider, RigidBodyShape, RigidBodyTypeString, UseColliderOptions, UseRigidBodyOptions, Vector3Array, WorldApi } from "./types";
4
- export declare const vectorArrayToObject: (arr: Vector3Array) => {
5
- x: number;
6
- y: number;
7
- z: number;
8
- };
4
+ export declare const vectorArrayToVector3: (arr: Vector3Array) => Vector3;
9
5
  export declare const vector3ToQuaternion: (v: Vector3) => Quaternion;
10
6
  export declare const rapierVector3ToVector3: ({ x, y, z }: RapierVector3) => Vector3;
11
7
  export declare const rapierQuaternionToQuaternion: ({ x, y, z, w, }: RapierQuaternion) => Quaternion;
@@ -30,7 +26,16 @@ interface CreateColliderFromOptions {
30
26
  }): Collider;
31
27
  }
32
28
  export declare const createColliderFromOptions: CreateColliderFromOptions;
33
- export declare const createCollidersFromChildren: (object: Object3D, rigidBody: RigidBodyApi | RigidBody, options: UseRigidBodyOptions, world: WorldApi, ignoreMeshColliders?: boolean) => Collider[];
29
+ interface CreateCollidersFromChildren {
30
+ (options: {
31
+ object: Object3D;
32
+ rigidBody?: Pick<RigidBodyApi | RigidBody, "handle">;
33
+ options: UseRigidBodyOptions;
34
+ world: WorldApi;
35
+ ignoreMeshColliders: boolean;
36
+ }): Collider[];
37
+ }
38
+ export declare const createCollidersFromChildren: CreateCollidersFromChildren;
34
39
  export declare const colliderDescFromGeometry: (geometry: BufferGeometry, colliders: RigidBodyAutoCollider, scale: Vector3, hasCollisionEvents: boolean) => ColliderDesc;
35
40
  export declare const scaleVertices: (vertices: ArrayLike<number>, scale: Vector3) => number[];
36
41
  export declare const rigidBodyDescFromOptions: (options: UseRigidBodyOptions) => RigidBodyDesc;
@@ -36,13 +36,9 @@ const _vector3 = new three.Vector3();
36
36
  new three.Object3D();
37
37
  const _matrix4 = new three.Matrix4();
38
38
 
39
- const vectorArrayToObject = arr => {
39
+ const vectorArrayToVector3 = arr => {
40
40
  const [x, y, z] = arr;
41
- return {
42
- x,
43
- y,
44
- z
45
- };
41
+ return new three.Vector3(x, y, z);
46
42
  };
47
43
  const vector3ToQuaternion = v => {
48
44
  return _quaternion.setFromEuler(_euler.setFromVector3(v));
@@ -158,13 +154,19 @@ const isChildOfMeshCollider = child => {
158
154
  return flag;
159
155
  };
160
156
 
161
- const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMeshColliders = true) => {
157
+ const createCollidersFromChildren = ({
158
+ object,
159
+ rigidBody,
160
+ options,
161
+ world,
162
+ ignoreMeshColliders: _ignoreMeshColliders = true
163
+ }) => {
162
164
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
163
165
  const colliders = [];
164
166
  new three.Vector3();
165
- object.traverse(child => {
167
+ object.traverseVisible(child => {
166
168
  if ("isMesh" in child) {
167
- if (ignoreMeshColliders && isChildOfMeshCollider(child)) return;
169
+ if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
168
170
  const {
169
171
  geometry
170
172
  } = child;
@@ -205,7 +207,7 @@ const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMe
205
207
  z: rz,
206
208
  w: rw
207
209
  });
208
- const actualRigidBody = world.getRigidBody(rigidBody === null || rigidBody === void 0 ? void 0 : rigidBody.handle);
210
+ const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
209
211
  const collider = world.createCollider(desc, actualRigidBody);
210
212
  colliders.push(collider);
211
213
  }
@@ -271,11 +273,13 @@ const scaleVertices = (vertices, scale) => {
271
273
  return scaledVerts;
272
274
  };
273
275
  const rigidBodyDescFromOptions = options => {
274
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
276
+ var _options$linearVeloci, _options$angularVeloc, _options$angularDampi, _options$linearDampin, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
275
277
 
276
278
  const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
277
279
  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];
278
280
  const [avx, avy, avz] = (_options$angularVeloc = options === null || options === void 0 ? void 0 : options.angularVelocity) !== null && _options$angularVeloc !== void 0 ? _options$angularVeloc : [0, 0, 0];
281
+ const angularDamping = (_options$angularDampi = options === null || options === void 0 ? void 0 : options.angularDamping) !== null && _options$angularDampi !== void 0 ? _options$angularDampi : 0;
282
+ const linearDamping = (_options$linearDampin = options === null || options === void 0 ? void 0 : options.linearDamping) !== null && _options$linearDampin !== void 0 ? _options$linearDampin : 0;
279
283
  const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
280
284
  const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
281
285
  const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
@@ -285,7 +289,7 @@ const rigidBodyDescFromOptions = options => {
285
289
  x: avx,
286
290
  y: avy,
287
291
  z: avz
288
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
292
+ }).setLinearDamping(linearDamping).setAngularDamping(angularDamping).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
289
293
  if (options.lockRotations) desc.lockRotations();
290
294
  if (options.lockTranslations) desc.lockTranslations();
291
295
  return desc;
@@ -370,6 +374,18 @@ const createRigidBodyApi = ref => {
370
374
  },
371
375
 
372
376
  setAngvel: velocity => ref.current().setAngvel(velocity, true),
377
+
378
+ linearDamping() {
379
+ return ref.current().linearDamping();
380
+ },
381
+
382
+ setLinearDamping: factor => ref.current().setLinearDamping(factor),
383
+
384
+ angularDamping() {
385
+ return ref.current().angularDamping();
386
+ },
387
+
388
+ setAngularDamping: factor => ref.current().setAngularDamping(factor),
373
389
  setNextKinematicRotation: ({
374
390
  x,
375
391
  y,
@@ -453,13 +469,14 @@ const Physics = ({
453
469
  colliders: _colliders = "cuboid",
454
470
  gravity: _gravity = [0, -9.81, 0],
455
471
  children,
456
- timeStep: _timeStep = "vary"
472
+ timeStep: _timeStep = "vary",
473
+ paused: _paused = false
457
474
  }) => {
458
475
  const rapier = useAsset.useAsset(importRapier);
459
476
  const worldRef = React.useRef();
460
477
  const getWorldRef = React.useRef(() => {
461
478
  if (!worldRef.current) {
462
- const world = new rapier.World(vectorArrayToObject(_gravity));
479
+ const world = new rapier.World(vectorArrayToVector3(_gravity));
463
480
  worldRef.current = world;
464
481
  }
465
482
 
@@ -484,7 +501,7 @@ const Physics = ({
484
501
  const world = worldRef.current;
485
502
 
486
503
  if (world) {
487
- world.gravity = vectorArrayToObject(_gravity);
504
+ world.gravity = vectorArrayToVector3(_gravity);
488
505
  }
489
506
  }, [_gravity]);
490
507
  const time = React.useRef(performance.now());
@@ -502,7 +519,7 @@ const Physics = ({
502
519
  world.timestep = _timeStep;
503
520
  }
504
521
 
505
- world.step(eventQueue); // Update meshes
522
+ if (!_paused) world.step(eventQueue); // Update meshes
506
523
 
507
524
  rigidBodyStates.forEach((state, handle) => {
508
525
  const rigidBody = world.getRigidBody(handle);
@@ -734,15 +751,22 @@ const useRigidBody = (options = {}) => {
734
751
  rigidBody.resetForces(false);
735
752
  rigidBody.resetTorques(false);
736
753
  const colliderSetting = (_ref = (_options$colliders = options === null || options === void 0 ? void 0 : options.colliders) !== null && _options$colliders !== void 0 ? _options$colliders : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
737
- const autoColliders = colliderSetting !== false ? createCollidersFromChildren(ref.current, rigidBody, _objectSpread2(_objectSpread2({}, options), {}, {
738
- colliders: colliderSetting
739
- }), world) : [];
754
+ const autoColliders = colliderSetting !== false ? createCollidersFromChildren({
755
+ object: ref.current,
756
+ rigidBody,
757
+ options: _objectSpread2(_objectSpread2({}, options), {}, {
758
+ colliders: colliderSetting
759
+ }),
760
+ world,
761
+ ignoreMeshColliders: true
762
+ }) : [];
740
763
  rigidBodyStates.set(rigidBody.handle, {
741
764
  mesh: ref.current,
742
765
  invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
743
766
  isSleeping: false,
744
767
  worldScale: ref.current.getWorldScale(_vector3).clone(),
745
- setMatrix: mat => ref.current.matrix.copy(mat)
768
+ setMatrix: mat => ref.current.matrix.copy(mat),
769
+ getMatrix: () => ref.current.matrix
746
770
  });
747
771
  ref.current.matrixAutoUpdate = false;
748
772
  return () => {
@@ -812,9 +836,9 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
812
836
  const {
813
837
  rapier
814
838
  } = useRapier();
815
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToObject(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToObject(body1LocalFrame)), {}, {
839
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
816
840
  w: 1
817
- }), vectorArrayToObject(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToObject(body2LocalFrame)), {}, {
841
+ }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
818
842
  w: 1
819
843
  })));
820
844
  };
@@ -829,7 +853,7 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
829
853
  const {
830
854
  rapier
831
855
  } = useRapier();
832
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor)));
856
+ return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
833
857
  };
834
858
  /**
835
859
  * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
@@ -841,7 +865,7 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
841
865
  const {
842
866
  rapier
843
867
  } = useRapier();
844
- return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
868
+ return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
845
869
  };
846
870
  /**
847
871
  * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
@@ -853,7 +877,7 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
853
877
  const {
854
878
  rapier
855
879
  } = useRapier();
856
- return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
880
+ return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
857
881
  };
858
882
 
859
883
  const _excluded$1 = ["children"];
@@ -900,9 +924,18 @@ const MeshCollider = ({
900
924
  var _ref;
901
925
 
902
926
  const colliderSetting = (_ref = type !== null && type !== void 0 ? type : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
903
- autoColliders = colliderSetting !== false ? createCollidersFromChildren(object.current, api, _objectSpread2(_objectSpread2({}, options), {}, {
904
- colliders: colliderSetting
905
- }), world, false) : [];
927
+
928
+ if ("raw" in api) {
929
+ autoColliders = createCollidersFromChildren({
930
+ object: object.current,
931
+ rigidBody: api,
932
+ options: _objectSpread2(_objectSpread2({}, options), {}, {
933
+ colliders: colliderSetting
934
+ }),
935
+ world,
936
+ ignoreMeshColliders: false
937
+ });
938
+ }
906
939
  }
907
940
 
908
941
  return () => {
@@ -1049,12 +1082,12 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1049
1082
 
1050
1083
  return instancesRef.current;
1051
1084
  });
1052
- React.useEffect(() => {
1085
+ React.useLayoutEffect(() => {
1053
1086
  const colliders = [];
1054
1087
  const rigidBodies = instancesRefGetter.current();
1055
1088
 
1056
1089
  if (object.current) {
1057
- const scale = object.current.getWorldScale(new three.Vector3());
1090
+ const worldScale = object.current.getWorldScale(new three.Vector3());
1058
1091
  let hasOneMesh = false;
1059
1092
  object.current.traverse(mesh => {
1060
1093
  if (mesh instanceof three.InstancedMesh) {
@@ -1065,21 +1098,34 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1065
1098
 
1066
1099
  hasOneMesh = true;
1067
1100
  mesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
1068
- const rigidBodyDesc = rigidBodyDescFromOptions(props);
1069
- const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders || physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1070
- );
1071
1101
 
1072
1102
  for (let index = 0; index < mesh.count; index++) {
1103
+ const scale = worldScale.clone();
1104
+ const rigidBodyDesc = rigidBodyDescFromOptions(props);
1105
+
1106
+ if (props.scales && props.scales[index]) {
1107
+ const s = vectorArrayToVector3(props.scales[index]);
1108
+ scale.multiply(s);
1109
+ }
1110
+
1073
1111
  const rigidBody = world.createRigidBody(rigidBodyDesc);
1074
1112
  const matrix = new three.Matrix4();
1075
1113
  mesh.getMatrixAt(index, matrix);
1076
1114
  const {
1077
1115
  position,
1078
1116
  rotation
1079
- } = decomposeMatrix4(matrix); // Set positions
1117
+ } = decomposeMatrix4(matrix);
1118
+
1119
+ if (props.colliders !== false) {
1120
+ const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders !== undefined ? props.colliders : physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1121
+ );
1122
+ const collider = world.createCollider(colliderDesc, rigidBody);
1123
+ colliders.push(collider);
1124
+ } // Set positions
1125
+
1080
1126
 
1081
1127
  if (props.positions && props.positions[index]) {
1082
- rigidBody.setTranslation(vectorArrayToObject(props.positions[index]), true);
1128
+ rigidBody.setTranslation(vectorArrayToVector3(props.positions[index]), true);
1083
1129
  } else {
1084
1130
  rigidBody.setTranslation(position, true);
1085
1131
  } // Set rotations
@@ -1092,13 +1138,19 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1092
1138
  rigidBody.setRotation(rotation, true);
1093
1139
  }
1094
1140
 
1095
- const collider = world.createCollider(colliderDesc, rigidBody);
1096
1141
  rigidBodyStates.set(rigidBody.handle, {
1097
1142
  mesh: mesh,
1098
1143
  isSleeping: false,
1099
1144
  invertedMatrixWorld: object.current.matrixWorld.clone().invert(),
1100
1145
  setMatrix: matrix => mesh.setMatrixAt(index, matrix),
1101
- worldScale: object.current.getWorldScale(new three.Vector3())
1146
+ getMatrix: () => {
1147
+ const m = new three.Matrix4();
1148
+ mesh.getMatrixAt(index, m);
1149
+ return m;
1150
+ },
1151
+ // Setting the world scale to the scale here, because
1152
+ // we want the scales to be reflected by instance
1153
+ worldScale: scale
1102
1154
  });
1103
1155
  const api = createRigidBodyApi({
1104
1156
  current() {
@@ -1106,7 +1158,6 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1106
1158
  }
1107
1159
 
1108
1160
  });
1109
- colliders.push(collider);
1110
1161
  rigidBodies.push({
1111
1162
  rigidBody,
1112
1163
  api
@@ -1125,10 +1176,19 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1125
1176
  };
1126
1177
  }
1127
1178
  }, []);
1128
- React.useImperativeHandle(ref, () => createInstancedRigidBodiesApi(instancesRefGetter));
1129
- return /*#__PURE__*/React__default["default"].createElement("object3D", {
1179
+ const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1180
+ React.useImperativeHandle(ref, () => api); // console.log(api);
1181
+
1182
+ return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1183
+ value: {
1184
+ ref: object,
1185
+ api,
1186
+ hasCollisionEvents: false,
1187
+ options: props
1188
+ }
1189
+ }, /*#__PURE__*/React__default["default"].createElement("object3D", {
1130
1190
  ref: object
1131
- }, props.children);
1191
+ }, props.children));
1132
1192
  });
1133
1193
 
1134
1194
  function _extends() {
@@ -1163,18 +1223,40 @@ const AnyCollider = _ref => {
1163
1223
  const rigidBodyContext = useRigidBodyContext();
1164
1224
  const ref = React.useRef(null);
1165
1225
  React.useEffect(() => {
1166
- var _rigidBodyContext$api;
1167
-
1168
1226
  const scale = ref.current.getWorldScale(new three.Vector3());
1169
- const collider = createColliderFromOptions({
1170
- options: props,
1171
- world,
1172
- rigidBody: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : (_rigidBodyContext$api = rigidBodyContext.api) === null || _rigidBodyContext$api === void 0 ? void 0 : _rigidBodyContext$api.raw(),
1173
- scale,
1174
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1175
- });
1227
+ const colliders = []; // If this is an InstancedRigidBody api
1228
+
1229
+ if (rigidBodyContext && "at" in rigidBodyContext.api) {
1230
+ rigidBodyContext.api.forEach((body, index) => {
1231
+ var _rigidBodyContext$opt, _rigidBodyContext$opt2;
1232
+
1233
+ let instanceScale = scale.clone();
1234
+
1235
+ if ("scales" in rigidBodyContext.options && rigidBodyContext !== null && rigidBodyContext !== void 0 && (_rigidBodyContext$opt = rigidBodyContext.options) !== null && _rigidBodyContext$opt !== void 0 && (_rigidBodyContext$opt2 = _rigidBodyContext$opt.scales) !== null && _rigidBodyContext$opt2 !== void 0 && _rigidBodyContext$opt2[index]) {
1236
+ instanceScale.multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
1237
+ }
1238
+
1239
+ colliders.push(createColliderFromOptions({
1240
+ options: props,
1241
+ world,
1242
+ rigidBody: body.raw(),
1243
+ scale: instanceScale,
1244
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1245
+ }));
1246
+ });
1247
+ } else {
1248
+ colliders.push(createColliderFromOptions({
1249
+ options: props,
1250
+ world,
1251
+ // Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
1252
+ rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
1253
+ scale,
1254
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1255
+ }));
1256
+ }
1257
+
1176
1258
  return () => {
1177
- world.removeCollider(collider);
1259
+ colliders.forEach(collider => world.removeCollider(collider));
1178
1260
  };
1179
1261
  }, []);
1180
1262
  return /*#__PURE__*/React__default["default"].createElement("object3D", {
@@ -36,13 +36,9 @@ const _vector3 = new three.Vector3();
36
36
  new three.Object3D();
37
37
  const _matrix4 = new three.Matrix4();
38
38
 
39
- const vectorArrayToObject = arr => {
39
+ const vectorArrayToVector3 = arr => {
40
40
  const [x, y, z] = arr;
41
- return {
42
- x,
43
- y,
44
- z
45
- };
41
+ return new three.Vector3(x, y, z);
46
42
  };
47
43
  const vector3ToQuaternion = v => {
48
44
  return _quaternion.setFromEuler(_euler.setFromVector3(v));
@@ -158,13 +154,19 @@ const isChildOfMeshCollider = child => {
158
154
  return flag;
159
155
  };
160
156
 
161
- const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMeshColliders = true) => {
157
+ const createCollidersFromChildren = ({
158
+ object,
159
+ rigidBody,
160
+ options,
161
+ world,
162
+ ignoreMeshColliders: _ignoreMeshColliders = true
163
+ }) => {
162
164
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
163
165
  const colliders = [];
164
166
  new three.Vector3();
165
- object.traverse(child => {
167
+ object.traverseVisible(child => {
166
168
  if ("isMesh" in child) {
167
- if (ignoreMeshColliders && isChildOfMeshCollider(child)) return;
169
+ if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
168
170
  const {
169
171
  geometry
170
172
  } = child;
@@ -205,7 +207,7 @@ const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMe
205
207
  z: rz,
206
208
  w: rw
207
209
  });
208
- const actualRigidBody = world.getRigidBody(rigidBody === null || rigidBody === void 0 ? void 0 : rigidBody.handle);
210
+ const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
209
211
  const collider = world.createCollider(desc, actualRigidBody);
210
212
  colliders.push(collider);
211
213
  }
@@ -271,11 +273,13 @@ const scaleVertices = (vertices, scale) => {
271
273
  return scaledVerts;
272
274
  };
273
275
  const rigidBodyDescFromOptions = options => {
274
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
276
+ var _options$linearVeloci, _options$angularVeloc, _options$angularDampi, _options$linearDampin, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
275
277
 
276
278
  const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
277
279
  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];
278
280
  const [avx, avy, avz] = (_options$angularVeloc = options === null || options === void 0 ? void 0 : options.angularVelocity) !== null && _options$angularVeloc !== void 0 ? _options$angularVeloc : [0, 0, 0];
281
+ const angularDamping = (_options$angularDampi = options === null || options === void 0 ? void 0 : options.angularDamping) !== null && _options$angularDampi !== void 0 ? _options$angularDampi : 0;
282
+ const linearDamping = (_options$linearDampin = options === null || options === void 0 ? void 0 : options.linearDamping) !== null && _options$linearDampin !== void 0 ? _options$linearDampin : 0;
279
283
  const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
280
284
  const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
281
285
  const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
@@ -285,7 +289,7 @@ const rigidBodyDescFromOptions = options => {
285
289
  x: avx,
286
290
  y: avy,
287
291
  z: avz
288
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
292
+ }).setLinearDamping(linearDamping).setAngularDamping(angularDamping).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
289
293
  if (options.lockRotations) desc.lockRotations();
290
294
  if (options.lockTranslations) desc.lockTranslations();
291
295
  return desc;
@@ -370,6 +374,18 @@ const createRigidBodyApi = ref => {
370
374
  },
371
375
 
372
376
  setAngvel: velocity => ref.current().setAngvel(velocity, true),
377
+
378
+ linearDamping() {
379
+ return ref.current().linearDamping();
380
+ },
381
+
382
+ setLinearDamping: factor => ref.current().setLinearDamping(factor),
383
+
384
+ angularDamping() {
385
+ return ref.current().angularDamping();
386
+ },
387
+
388
+ setAngularDamping: factor => ref.current().setAngularDamping(factor),
373
389
  setNextKinematicRotation: ({
374
390
  x,
375
391
  y,
@@ -453,13 +469,14 @@ const Physics = ({
453
469
  colliders: _colliders = "cuboid",
454
470
  gravity: _gravity = [0, -9.81, 0],
455
471
  children,
456
- timeStep: _timeStep = "vary"
472
+ timeStep: _timeStep = "vary",
473
+ paused: _paused = false
457
474
  }) => {
458
475
  const rapier = useAsset.useAsset(importRapier);
459
476
  const worldRef = React.useRef();
460
477
  const getWorldRef = React.useRef(() => {
461
478
  if (!worldRef.current) {
462
- const world = new rapier.World(vectorArrayToObject(_gravity));
479
+ const world = new rapier.World(vectorArrayToVector3(_gravity));
463
480
  worldRef.current = world;
464
481
  }
465
482
 
@@ -484,7 +501,7 @@ const Physics = ({
484
501
  const world = worldRef.current;
485
502
 
486
503
  if (world) {
487
- world.gravity = vectorArrayToObject(_gravity);
504
+ world.gravity = vectorArrayToVector3(_gravity);
488
505
  }
489
506
  }, [_gravity]);
490
507
  const time = React.useRef(performance.now());
@@ -502,7 +519,7 @@ const Physics = ({
502
519
  world.timestep = _timeStep;
503
520
  }
504
521
 
505
- world.step(eventQueue); // Update meshes
522
+ if (!_paused) world.step(eventQueue); // Update meshes
506
523
 
507
524
  rigidBodyStates.forEach((state, handle) => {
508
525
  const rigidBody = world.getRigidBody(handle);
@@ -734,15 +751,22 @@ const useRigidBody = (options = {}) => {
734
751
  rigidBody.resetForces(false);
735
752
  rigidBody.resetTorques(false);
736
753
  const colliderSetting = (_ref = (_options$colliders = options === null || options === void 0 ? void 0 : options.colliders) !== null && _options$colliders !== void 0 ? _options$colliders : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
737
- const autoColliders = colliderSetting !== false ? createCollidersFromChildren(ref.current, rigidBody, _objectSpread2(_objectSpread2({}, options), {}, {
738
- colliders: colliderSetting
739
- }), world) : [];
754
+ const autoColliders = colliderSetting !== false ? createCollidersFromChildren({
755
+ object: ref.current,
756
+ rigidBody,
757
+ options: _objectSpread2(_objectSpread2({}, options), {}, {
758
+ colliders: colliderSetting
759
+ }),
760
+ world,
761
+ ignoreMeshColliders: true
762
+ }) : [];
740
763
  rigidBodyStates.set(rigidBody.handle, {
741
764
  mesh: ref.current,
742
765
  invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
743
766
  isSleeping: false,
744
767
  worldScale: ref.current.getWorldScale(_vector3).clone(),
745
- setMatrix: mat => ref.current.matrix.copy(mat)
768
+ setMatrix: mat => ref.current.matrix.copy(mat),
769
+ getMatrix: () => ref.current.matrix
746
770
  });
747
771
  ref.current.matrixAutoUpdate = false;
748
772
  return () => {
@@ -812,9 +836,9 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
812
836
  const {
813
837
  rapier
814
838
  } = useRapier();
815
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToObject(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToObject(body1LocalFrame)), {}, {
839
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
816
840
  w: 1
817
- }), vectorArrayToObject(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToObject(body2LocalFrame)), {}, {
841
+ }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
818
842
  w: 1
819
843
  })));
820
844
  };
@@ -829,7 +853,7 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
829
853
  const {
830
854
  rapier
831
855
  } = useRapier();
832
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor)));
856
+ return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
833
857
  };
834
858
  /**
835
859
  * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
@@ -841,7 +865,7 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
841
865
  const {
842
866
  rapier
843
867
  } = useRapier();
844
- return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
868
+ return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
845
869
  };
846
870
  /**
847
871
  * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
@@ -853,7 +877,7 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
853
877
  const {
854
878
  rapier
855
879
  } = useRapier();
856
- return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
880
+ return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
857
881
  };
858
882
 
859
883
  const _excluded$1 = ["children"];
@@ -900,9 +924,18 @@ const MeshCollider = ({
900
924
  var _ref;
901
925
 
902
926
  const colliderSetting = (_ref = type !== null && type !== void 0 ? type : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
903
- autoColliders = colliderSetting !== false ? createCollidersFromChildren(object.current, api, _objectSpread2(_objectSpread2({}, options), {}, {
904
- colliders: colliderSetting
905
- }), world, false) : [];
927
+
928
+ if ("raw" in api) {
929
+ autoColliders = createCollidersFromChildren({
930
+ object: object.current,
931
+ rigidBody: api,
932
+ options: _objectSpread2(_objectSpread2({}, options), {}, {
933
+ colliders: colliderSetting
934
+ }),
935
+ world,
936
+ ignoreMeshColliders: false
937
+ });
938
+ }
906
939
  }
907
940
 
908
941
  return () => {
@@ -1049,12 +1082,12 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1049
1082
 
1050
1083
  return instancesRef.current;
1051
1084
  });
1052
- React.useEffect(() => {
1085
+ React.useLayoutEffect(() => {
1053
1086
  const colliders = [];
1054
1087
  const rigidBodies = instancesRefGetter.current();
1055
1088
 
1056
1089
  if (object.current) {
1057
- const scale = object.current.getWorldScale(new three.Vector3());
1090
+ const worldScale = object.current.getWorldScale(new three.Vector3());
1058
1091
  let hasOneMesh = false;
1059
1092
  object.current.traverse(mesh => {
1060
1093
  if (mesh instanceof three.InstancedMesh) {
@@ -1065,21 +1098,34 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1065
1098
 
1066
1099
  hasOneMesh = true;
1067
1100
  mesh.instanceMatrix.setUsage(three.DynamicDrawUsage);
1068
- const rigidBodyDesc = rigidBodyDescFromOptions(props);
1069
- const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders || physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1070
- );
1071
1101
 
1072
1102
  for (let index = 0; index < mesh.count; index++) {
1103
+ const scale = worldScale.clone();
1104
+ const rigidBodyDesc = rigidBodyDescFromOptions(props);
1105
+
1106
+ if (props.scales && props.scales[index]) {
1107
+ const s = vectorArrayToVector3(props.scales[index]);
1108
+ scale.multiply(s);
1109
+ }
1110
+
1073
1111
  const rigidBody = world.createRigidBody(rigidBodyDesc);
1074
1112
  const matrix = new three.Matrix4();
1075
1113
  mesh.getMatrixAt(index, matrix);
1076
1114
  const {
1077
1115
  position,
1078
1116
  rotation
1079
- } = decomposeMatrix4(matrix); // Set positions
1117
+ } = decomposeMatrix4(matrix);
1118
+
1119
+ if (props.colliders !== false) {
1120
+ const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders !== undefined ? props.colliders : physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1121
+ );
1122
+ const collider = world.createCollider(colliderDesc, rigidBody);
1123
+ colliders.push(collider);
1124
+ } // Set positions
1125
+
1080
1126
 
1081
1127
  if (props.positions && props.positions[index]) {
1082
- rigidBody.setTranslation(vectorArrayToObject(props.positions[index]), true);
1128
+ rigidBody.setTranslation(vectorArrayToVector3(props.positions[index]), true);
1083
1129
  } else {
1084
1130
  rigidBody.setTranslation(position, true);
1085
1131
  } // Set rotations
@@ -1092,13 +1138,19 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1092
1138
  rigidBody.setRotation(rotation, true);
1093
1139
  }
1094
1140
 
1095
- const collider = world.createCollider(colliderDesc, rigidBody);
1096
1141
  rigidBodyStates.set(rigidBody.handle, {
1097
1142
  mesh: mesh,
1098
1143
  isSleeping: false,
1099
1144
  invertedMatrixWorld: object.current.matrixWorld.clone().invert(),
1100
1145
  setMatrix: matrix => mesh.setMatrixAt(index, matrix),
1101
- worldScale: object.current.getWorldScale(new three.Vector3())
1146
+ getMatrix: () => {
1147
+ const m = new three.Matrix4();
1148
+ mesh.getMatrixAt(index, m);
1149
+ return m;
1150
+ },
1151
+ // Setting the world scale to the scale here, because
1152
+ // we want the scales to be reflected by instance
1153
+ worldScale: scale
1102
1154
  });
1103
1155
  const api = createRigidBodyApi({
1104
1156
  current() {
@@ -1106,7 +1158,6 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1106
1158
  }
1107
1159
 
1108
1160
  });
1109
- colliders.push(collider);
1110
1161
  rigidBodies.push({
1111
1162
  rigidBody,
1112
1163
  api
@@ -1125,10 +1176,19 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1125
1176
  };
1126
1177
  }
1127
1178
  }, []);
1128
- React.useImperativeHandle(ref, () => createInstancedRigidBodiesApi(instancesRefGetter));
1129
- return /*#__PURE__*/React__default["default"].createElement("object3D", {
1179
+ const api = React.useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1180
+ React.useImperativeHandle(ref, () => api); // console.log(api);
1181
+
1182
+ return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
1183
+ value: {
1184
+ ref: object,
1185
+ api,
1186
+ hasCollisionEvents: false,
1187
+ options: props
1188
+ }
1189
+ }, /*#__PURE__*/React__default["default"].createElement("object3D", {
1130
1190
  ref: object
1131
- }, props.children);
1191
+ }, props.children));
1132
1192
  });
1133
1193
 
1134
1194
  function _extends() {
@@ -1163,18 +1223,40 @@ const AnyCollider = _ref => {
1163
1223
  const rigidBodyContext = useRigidBodyContext();
1164
1224
  const ref = React.useRef(null);
1165
1225
  React.useEffect(() => {
1166
- var _rigidBodyContext$api;
1167
-
1168
1226
  const scale = ref.current.getWorldScale(new three.Vector3());
1169
- const collider = createColliderFromOptions({
1170
- options: props,
1171
- world,
1172
- rigidBody: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : (_rigidBodyContext$api = rigidBodyContext.api) === null || _rigidBodyContext$api === void 0 ? void 0 : _rigidBodyContext$api.raw(),
1173
- scale,
1174
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1175
- });
1227
+ const colliders = []; // If this is an InstancedRigidBody api
1228
+
1229
+ if (rigidBodyContext && "at" in rigidBodyContext.api) {
1230
+ rigidBodyContext.api.forEach((body, index) => {
1231
+ var _rigidBodyContext$opt, _rigidBodyContext$opt2;
1232
+
1233
+ let instanceScale = scale.clone();
1234
+
1235
+ if ("scales" in rigidBodyContext.options && rigidBodyContext !== null && rigidBodyContext !== void 0 && (_rigidBodyContext$opt = rigidBodyContext.options) !== null && _rigidBodyContext$opt !== void 0 && (_rigidBodyContext$opt2 = _rigidBodyContext$opt.scales) !== null && _rigidBodyContext$opt2 !== void 0 && _rigidBodyContext$opt2[index]) {
1236
+ instanceScale.multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
1237
+ }
1238
+
1239
+ colliders.push(createColliderFromOptions({
1240
+ options: props,
1241
+ world,
1242
+ rigidBody: body.raw(),
1243
+ scale: instanceScale,
1244
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1245
+ }));
1246
+ });
1247
+ } else {
1248
+ colliders.push(createColliderFromOptions({
1249
+ options: props,
1250
+ world,
1251
+ // Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
1252
+ rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
1253
+ scale,
1254
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1255
+ }));
1256
+ }
1257
+
1176
1258
  return () => {
1177
- world.removeCollider(collider);
1259
+ colliders.forEach(collider => world.removeCollider(collider));
1178
1260
  };
1179
1261
  }, []);
1180
1262
  return /*#__PURE__*/React__default["default"].createElement("object3D", {
@@ -1,6 +1,6 @@
1
1
  import { ColliderDesc, ActiveEvents, RigidBodyDesc, CoefficientCombineRule, EventQueue, ShapeType } from '@dimforge/rapier3d-compat';
2
2
  export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat';
3
- import React, { useRef, useState, useEffect, useMemo, createContext, useContext, forwardRef, useImperativeHandle, memo } from 'react';
3
+ import React, { useRef, useState, useEffect, useMemo, createContext, useContext, forwardRef, useImperativeHandle, memo, useLayoutEffect } from 'react';
4
4
  import { useAsset } from 'use-asset';
5
5
  import { useFrame } from '@react-three/fiber';
6
6
  import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
@@ -11,13 +11,9 @@ const _vector3 = new Vector3();
11
11
  new Object3D();
12
12
  const _matrix4 = new Matrix4();
13
13
 
14
- const vectorArrayToObject = arr => {
14
+ const vectorArrayToVector3 = arr => {
15
15
  const [x, y, z] = arr;
16
- return {
17
- x,
18
- y,
19
- z
20
- };
16
+ return new Vector3(x, y, z);
21
17
  };
22
18
  const vector3ToQuaternion = v => {
23
19
  return _quaternion.setFromEuler(_euler.setFromVector3(v));
@@ -133,13 +129,19 @@ const isChildOfMeshCollider = child => {
133
129
  return flag;
134
130
  };
135
131
 
136
- const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMeshColliders = true) => {
132
+ const createCollidersFromChildren = ({
133
+ object,
134
+ rigidBody,
135
+ options,
136
+ world,
137
+ ignoreMeshColliders: _ignoreMeshColliders = true
138
+ }) => {
137
139
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
138
140
  const colliders = [];
139
141
  new Vector3();
140
- object.traverse(child => {
142
+ object.traverseVisible(child => {
141
143
  if ("isMesh" in child) {
142
- if (ignoreMeshColliders && isChildOfMeshCollider(child)) return;
144
+ if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
143
145
  const {
144
146
  geometry
145
147
  } = child;
@@ -180,7 +182,7 @@ const createCollidersFromChildren = (object, rigidBody, options, world, ignoreMe
180
182
  z: rz,
181
183
  w: rw
182
184
  });
183
- const actualRigidBody = world.getRigidBody(rigidBody === null || rigidBody === void 0 ? void 0 : rigidBody.handle);
185
+ const actualRigidBody = rigidBody ? world.getRigidBody(rigidBody.handle) : undefined;
184
186
  const collider = world.createCollider(desc, actualRigidBody);
185
187
  colliders.push(collider);
186
188
  }
@@ -246,11 +248,13 @@ const scaleVertices = (vertices, scale) => {
246
248
  return scaledVerts;
247
249
  };
248
250
  const rigidBodyDescFromOptions = options => {
249
- var _options$linearVeloci, _options$angularVeloc, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
251
+ var _options$linearVeloci, _options$angularVeloc, _options$angularDampi, _options$linearDampin, _options$gravityScale, _options$canSleep, _options$ccd, _options$enabledRotat, _options$enabledTrans;
250
252
 
251
253
  const type = rigidBodyTypeFromString((options === null || options === void 0 ? void 0 : options.type) || "dynamic");
252
254
  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];
253
255
  const [avx, avy, avz] = (_options$angularVeloc = options === null || options === void 0 ? void 0 : options.angularVelocity) !== null && _options$angularVeloc !== void 0 ? _options$angularVeloc : [0, 0, 0];
256
+ const angularDamping = (_options$angularDampi = options === null || options === void 0 ? void 0 : options.angularDamping) !== null && _options$angularDampi !== void 0 ? _options$angularDampi : 0;
257
+ const linearDamping = (_options$linearDampin = options === null || options === void 0 ? void 0 : options.linearDamping) !== null && _options$linearDampin !== void 0 ? _options$linearDampin : 0;
254
258
  const gravityScale = (_options$gravityScale = options === null || options === void 0 ? void 0 : options.gravityScale) !== null && _options$gravityScale !== void 0 ? _options$gravityScale : 1;
255
259
  const canSleep = (_options$canSleep = options === null || options === void 0 ? void 0 : options.canSleep) !== null && _options$canSleep !== void 0 ? _options$canSleep : true;
256
260
  const ccdEnabled = (_options$ccd = options === null || options === void 0 ? void 0 : options.ccd) !== null && _options$ccd !== void 0 ? _options$ccd : false;
@@ -260,7 +264,7 @@ const rigidBodyDescFromOptions = options => {
260
264
  x: avx,
261
265
  y: avy,
262
266
  z: avz
263
- }).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
267
+ }).setLinearDamping(linearDamping).setAngularDamping(angularDamping).setGravityScale(gravityScale).setCanSleep(canSleep).setCcdEnabled(ccdEnabled).enabledRotations(erx, ery, erz).enabledTranslations(etx, ety, etz);
264
268
  if (options.lockRotations) desc.lockRotations();
265
269
  if (options.lockTranslations) desc.lockTranslations();
266
270
  return desc;
@@ -345,6 +349,18 @@ const createRigidBodyApi = ref => {
345
349
  },
346
350
 
347
351
  setAngvel: velocity => ref.current().setAngvel(velocity, true),
352
+
353
+ linearDamping() {
354
+ return ref.current().linearDamping();
355
+ },
356
+
357
+ setLinearDamping: factor => ref.current().setLinearDamping(factor),
358
+
359
+ angularDamping() {
360
+ return ref.current().angularDamping();
361
+ },
362
+
363
+ setAngularDamping: factor => ref.current().setAngularDamping(factor),
348
364
  setNextKinematicRotation: ({
349
365
  x,
350
366
  y,
@@ -428,13 +444,14 @@ const Physics = ({
428
444
  colliders: _colliders = "cuboid",
429
445
  gravity: _gravity = [0, -9.81, 0],
430
446
  children,
431
- timeStep: _timeStep = "vary"
447
+ timeStep: _timeStep = "vary",
448
+ paused: _paused = false
432
449
  }) => {
433
450
  const rapier = useAsset(importRapier);
434
451
  const worldRef = useRef();
435
452
  const getWorldRef = useRef(() => {
436
453
  if (!worldRef.current) {
437
- const world = new rapier.World(vectorArrayToObject(_gravity));
454
+ const world = new rapier.World(vectorArrayToVector3(_gravity));
438
455
  worldRef.current = world;
439
456
  }
440
457
 
@@ -459,7 +476,7 @@ const Physics = ({
459
476
  const world = worldRef.current;
460
477
 
461
478
  if (world) {
462
- world.gravity = vectorArrayToObject(_gravity);
479
+ world.gravity = vectorArrayToVector3(_gravity);
463
480
  }
464
481
  }, [_gravity]);
465
482
  const time = useRef(performance.now());
@@ -477,7 +494,7 @@ const Physics = ({
477
494
  world.timestep = _timeStep;
478
495
  }
479
496
 
480
- world.step(eventQueue); // Update meshes
497
+ if (!_paused) world.step(eventQueue); // Update meshes
481
498
 
482
499
  rigidBodyStates.forEach((state, handle) => {
483
500
  const rigidBody = world.getRigidBody(handle);
@@ -709,15 +726,22 @@ const useRigidBody = (options = {}) => {
709
726
  rigidBody.resetForces(false);
710
727
  rigidBody.resetTorques(false);
711
728
  const colliderSetting = (_ref = (_options$colliders = options === null || options === void 0 ? void 0 : options.colliders) !== null && _options$colliders !== void 0 ? _options$colliders : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
712
- const autoColliders = colliderSetting !== false ? createCollidersFromChildren(ref.current, rigidBody, _objectSpread2(_objectSpread2({}, options), {}, {
713
- colliders: colliderSetting
714
- }), world) : [];
729
+ const autoColliders = colliderSetting !== false ? createCollidersFromChildren({
730
+ object: ref.current,
731
+ rigidBody,
732
+ options: _objectSpread2(_objectSpread2({}, options), {}, {
733
+ colliders: colliderSetting
734
+ }),
735
+ world,
736
+ ignoreMeshColliders: true
737
+ }) : [];
715
738
  rigidBodyStates.set(rigidBody.handle, {
716
739
  mesh: ref.current,
717
740
  invertedMatrixWorld: ref.current.parent.matrixWorld.clone().invert(),
718
741
  isSleeping: false,
719
742
  worldScale: ref.current.getWorldScale(_vector3).clone(),
720
- setMatrix: mat => ref.current.matrix.copy(mat)
743
+ setMatrix: mat => ref.current.matrix.copy(mat),
744
+ getMatrix: () => ref.current.matrix
721
745
  });
722
746
  ref.current.matrixAutoUpdate = false;
723
747
  return () => {
@@ -787,9 +811,9 @@ const useFixedJoint = (body1, body2, [body1Anchor, body1LocalFrame, body2Anchor,
787
811
  const {
788
812
  rapier
789
813
  } = useRapier();
790
- return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToObject(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToObject(body1LocalFrame)), {}, {
814
+ return useImpulseJoint(body1, body2, rapier.JointData.fixed(vectorArrayToVector3(body1Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body1LocalFrame)), {}, {
791
815
  w: 1
792
- }), vectorArrayToObject(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToObject(body2LocalFrame)), {}, {
816
+ }), vectorArrayToVector3(body2Anchor), _objectSpread2(_objectSpread2({}, vectorArrayToVector3(body2LocalFrame)), {}, {
793
817
  w: 1
794
818
  })));
795
819
  };
@@ -804,7 +828,7 @@ const useSphericalJoint = (body1, body2, [body1Anchor, body2Anchor]) => {
804
828
  const {
805
829
  rapier
806
830
  } = useRapier();
807
- return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor)));
831
+ return useImpulseJoint(body1, body2, rapier.JointData.spherical(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor)));
808
832
  };
809
833
  /**
810
834
  * The revolute joint prevents any relative movement between two rigid-bodies, except for relative
@@ -816,7 +840,7 @@ const useRevoluteJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
816
840
  const {
817
841
  rapier
818
842
  } = useRapier();
819
- return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
843
+ return useImpulseJoint(body1, body2, rapier.JointData.revolute(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
820
844
  };
821
845
  /**
822
846
  * The prismatic joint prevents any relative movement between two rigid-bodies, except for relative translations along one axis.
@@ -828,7 +852,7 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
828
852
  const {
829
853
  rapier
830
854
  } = useRapier();
831
- return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToObject(body1Anchor), vectorArrayToObject(body2Anchor), vectorArrayToObject(axis)));
855
+ return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
832
856
  };
833
857
 
834
858
  const _excluded$1 = ["children"];
@@ -875,9 +899,18 @@ const MeshCollider = ({
875
899
  var _ref;
876
900
 
877
901
  const colliderSetting = (_ref = type !== null && type !== void 0 ? type : physicsOptions.colliders) !== null && _ref !== void 0 ? _ref : false;
878
- autoColliders = colliderSetting !== false ? createCollidersFromChildren(object.current, api, _objectSpread2(_objectSpread2({}, options), {}, {
879
- colliders: colliderSetting
880
- }), world, false) : [];
902
+
903
+ if ("raw" in api) {
904
+ autoColliders = createCollidersFromChildren({
905
+ object: object.current,
906
+ rigidBody: api,
907
+ options: _objectSpread2(_objectSpread2({}, options), {}, {
908
+ colliders: colliderSetting
909
+ }),
910
+ world,
911
+ ignoreMeshColliders: false
912
+ });
913
+ }
881
914
  }
882
915
 
883
916
  return () => {
@@ -1024,12 +1057,12 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1024
1057
 
1025
1058
  return instancesRef.current;
1026
1059
  });
1027
- useEffect(() => {
1060
+ useLayoutEffect(() => {
1028
1061
  const colliders = [];
1029
1062
  const rigidBodies = instancesRefGetter.current();
1030
1063
 
1031
1064
  if (object.current) {
1032
- const scale = object.current.getWorldScale(new Vector3());
1065
+ const worldScale = object.current.getWorldScale(new Vector3());
1033
1066
  let hasOneMesh = false;
1034
1067
  object.current.traverse(mesh => {
1035
1068
  if (mesh instanceof InstancedMesh) {
@@ -1040,21 +1073,34 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1040
1073
 
1041
1074
  hasOneMesh = true;
1042
1075
  mesh.instanceMatrix.setUsage(DynamicDrawUsage);
1043
- const rigidBodyDesc = rigidBodyDescFromOptions(props);
1044
- const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders || physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1045
- );
1046
1076
 
1047
1077
  for (let index = 0; index < mesh.count; index++) {
1078
+ const scale = worldScale.clone();
1079
+ const rigidBodyDesc = rigidBodyDescFromOptions(props);
1080
+
1081
+ if (props.scales && props.scales[index]) {
1082
+ const s = vectorArrayToVector3(props.scales[index]);
1083
+ scale.multiply(s);
1084
+ }
1085
+
1048
1086
  const rigidBody = world.createRigidBody(rigidBodyDesc);
1049
1087
  const matrix = new Matrix4();
1050
1088
  mesh.getMatrixAt(index, matrix);
1051
1089
  const {
1052
1090
  position,
1053
1091
  rotation
1054
- } = decomposeMatrix4(matrix); // Set positions
1092
+ } = decomposeMatrix4(matrix);
1093
+
1094
+ if (props.colliders !== false) {
1095
+ const colliderDesc = colliderDescFromGeometry(mesh.geometry, props.colliders !== undefined ? props.colliders : physicsOptions.colliders, scale, false // Collisions currently not enabled for instances
1096
+ );
1097
+ const collider = world.createCollider(colliderDesc, rigidBody);
1098
+ colliders.push(collider);
1099
+ } // Set positions
1100
+
1055
1101
 
1056
1102
  if (props.positions && props.positions[index]) {
1057
- rigidBody.setTranslation(vectorArrayToObject(props.positions[index]), true);
1103
+ rigidBody.setTranslation(vectorArrayToVector3(props.positions[index]), true);
1058
1104
  } else {
1059
1105
  rigidBody.setTranslation(position, true);
1060
1106
  } // Set rotations
@@ -1067,13 +1113,19 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1067
1113
  rigidBody.setRotation(rotation, true);
1068
1114
  }
1069
1115
 
1070
- const collider = world.createCollider(colliderDesc, rigidBody);
1071
1116
  rigidBodyStates.set(rigidBody.handle, {
1072
1117
  mesh: mesh,
1073
1118
  isSleeping: false,
1074
1119
  invertedMatrixWorld: object.current.matrixWorld.clone().invert(),
1075
1120
  setMatrix: matrix => mesh.setMatrixAt(index, matrix),
1076
- worldScale: object.current.getWorldScale(new Vector3())
1121
+ getMatrix: () => {
1122
+ const m = new Matrix4();
1123
+ mesh.getMatrixAt(index, m);
1124
+ return m;
1125
+ },
1126
+ // Setting the world scale to the scale here, because
1127
+ // we want the scales to be reflected by instance
1128
+ worldScale: scale
1077
1129
  });
1078
1130
  const api = createRigidBodyApi({
1079
1131
  current() {
@@ -1081,7 +1133,6 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1081
1133
  }
1082
1134
 
1083
1135
  });
1084
- colliders.push(collider);
1085
1136
  rigidBodies.push({
1086
1137
  rigidBody,
1087
1138
  api
@@ -1100,10 +1151,19 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1100
1151
  };
1101
1152
  }
1102
1153
  }, []);
1103
- useImperativeHandle(ref, () => createInstancedRigidBodiesApi(instancesRefGetter));
1104
- return /*#__PURE__*/React.createElement("object3D", {
1154
+ const api = useMemo(() => createInstancedRigidBodiesApi(instancesRefGetter), []);
1155
+ useImperativeHandle(ref, () => api); // console.log(api);
1156
+
1157
+ return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
1158
+ value: {
1159
+ ref: object,
1160
+ api,
1161
+ hasCollisionEvents: false,
1162
+ options: props
1163
+ }
1164
+ }, /*#__PURE__*/React.createElement("object3D", {
1105
1165
  ref: object
1106
- }, props.children);
1166
+ }, props.children));
1107
1167
  });
1108
1168
 
1109
1169
  function _extends() {
@@ -1138,18 +1198,40 @@ const AnyCollider = _ref => {
1138
1198
  const rigidBodyContext = useRigidBodyContext();
1139
1199
  const ref = useRef(null);
1140
1200
  useEffect(() => {
1141
- var _rigidBodyContext$api;
1142
-
1143
1201
  const scale = ref.current.getWorldScale(new Vector3());
1144
- const collider = createColliderFromOptions({
1145
- options: props,
1146
- world,
1147
- rigidBody: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : (_rigidBodyContext$api = rigidBodyContext.api) === null || _rigidBodyContext$api === void 0 ? void 0 : _rigidBodyContext$api.raw(),
1148
- scale,
1149
- hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1150
- });
1202
+ const colliders = []; // If this is an InstancedRigidBody api
1203
+
1204
+ if (rigidBodyContext && "at" in rigidBodyContext.api) {
1205
+ rigidBodyContext.api.forEach((body, index) => {
1206
+ var _rigidBodyContext$opt, _rigidBodyContext$opt2;
1207
+
1208
+ let instanceScale = scale.clone();
1209
+
1210
+ if ("scales" in rigidBodyContext.options && rigidBodyContext !== null && rigidBodyContext !== void 0 && (_rigidBodyContext$opt = rigidBodyContext.options) !== null && _rigidBodyContext$opt !== void 0 && (_rigidBodyContext$opt2 = _rigidBodyContext$opt.scales) !== null && _rigidBodyContext$opt2 !== void 0 && _rigidBodyContext$opt2[index]) {
1211
+ instanceScale.multiply(vectorArrayToVector3(rigidBodyContext.options.scales[index]));
1212
+ }
1213
+
1214
+ colliders.push(createColliderFromOptions({
1215
+ options: props,
1216
+ world,
1217
+ rigidBody: body.raw(),
1218
+ scale: instanceScale,
1219
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1220
+ }));
1221
+ });
1222
+ } else {
1223
+ colliders.push(createColliderFromOptions({
1224
+ options: props,
1225
+ world,
1226
+ // Initiate with a rigidbody, or undefined, because colliders can exist without a rigid body
1227
+ rigidBody: rigidBodyContext && "raw" in rigidBodyContext.api ? rigidBodyContext.api.raw() : undefined,
1228
+ scale,
1229
+ hasCollisionEvents: rigidBodyContext === null || rigidBodyContext === void 0 ? void 0 : rigidBodyContext.hasCollisionEvents
1230
+ }));
1231
+ }
1232
+
1151
1233
  return () => {
1152
- world.removeCollider(collider);
1234
+ colliders.forEach(collider => world.removeCollider(collider));
1153
1235
  };
1154
1236
  }, []);
1155
1237
  return /*#__PURE__*/React.createElement("object3D", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.6.1",
3
+ "version": "0.6.4",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
package/readme.md CHANGED
@@ -1,5 +1,10 @@
1
1
  <p align="center">
2
- <img src="misc/hero.svg" />
2
+ <img src="https://raw.githubusercontent.com/pmndrs/react-three-rapier/HEAD/packages/react-three-rapier/misc/hero.svg" alt="@react-three/rapier" />
3
+ </p>
4
+
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)](https://discord.gg/ZZjjNvJ" />
3
8
  </p>
4
9
 
5
10
  <p align="center">⚠️ Under heavy development. All APIs are subject to change. ⚠️</p>
@@ -121,6 +126,8 @@ Instanced meshes can also be used and have automatic colliders generated from th
121
126
 
122
127
  By wrapping the `InstancedMesh` in `<InstancedRigidBodies />`, each instance will be attached to an individual `RigidBody`.
123
128
 
129
+ > Note: Custom colliders (compound shapes) for InstancedMesh is currently not supported
130
+
124
131
  ```tsx
125
132
  import { InstancedRigidBodies } from "@react-three/rapier";
126
133
 
@@ -139,7 +146,8 @@ const Scene = () => {
139
146
  });
140
147
  }, []);
141
148
 
142
- // We can set the initial positions, and rotations, of the instances by providing an array equal to the instance count
149
+ // We can set the initial positions, and rotations, and scales, of
150
+ // the instances by providing an array equal to the instance count
143
151
  const positions = Array.from({ length: COUNT }, (_, index) => [index, 0, 0]);
144
152
 
145
153
  const rotations = Array.from({ length: COUNT }, (_, index) => [
@@ -148,16 +156,25 @@ const Scene = () => {
148
156
  Math.random(),
149
157
  ]);
150
158
 
159
+ const scales = Array.from({ length: COUNT }, (_, index) => [
160
+ Math.random(),
161
+ Math.random(),
162
+ Math.random(),
163
+ ]);
164
+
151
165
  return (
152
166
  <InstancedRigidBodies
153
167
  ref={instancedApi}
154
168
  positions={positions}
155
169
  rotations={rotations}
170
+ scales={scales}
156
171
  colliders="ball"
157
172
  >
158
173
  <instancedMesh args={[undefined, undefined, COUNT]}>
159
174
  <sphereBufferGeometry args={[0.2]} />
160
175
  <meshPhysicalGeometry color="blue" />
176
+
177
+ <CuboidCollider args={[0.1, 0.2, 0.1]} />
161
178
  </instancedMesh>
162
179
  </InstancedRigidBodies>
163
180
  );