@react-three/rapier 0.6.5 → 0.6.8

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.
@@ -1,2 +1,13 @@
1
- /// <reference types="react" />
2
- export declare const Debug: () => JSX.Element;
1
+ import { FC } from "react";
2
+ interface DebugProps {
3
+ /**
4
+ * The color of the wireframe representing an active collider that is affected by forces and not sleeping.
5
+ */
6
+ color?: string;
7
+ /**
8
+ * The color of the wireframe representing a static (fixed or kinematic) or sleeping collider.
9
+ */
10
+ sleepColor?: string;
11
+ }
12
+ export declare const Debug: FC<DebugProps>;
13
+ export {};
@@ -7,4 +7,4 @@ export interface InstancedRigidBodiesProps extends Omit<RigidBodyProps, "positio
7
7
  rotations?: Vector3Array[];
8
8
  scales?: Vector3Array[];
9
9
  }
10
- export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<InstancedRigidBodiesProps & React.RefAttributes<InstancedRigidBodyApi>>;
10
+ export declare const InstancedRigidBodies: React.ForwardRefExoticComponent<Pick<InstancedRigidBodiesProps, "type" | "canSleep" | "linearDamping" | "angularDamping" | "linearVelocity" | "angularVelocity" | "gravityScale" | "ccd" | "colliders" | "friction" | "restitution" | "onSleep" | "onWake" | "lockRotations" | "lockTranslations" | "enabledRotations" | "enabledTranslations" | "children" | "quaternion" | "attach" | "args" | "key" | "onUpdate" | "up" | "scale" | "matrix" | "layers" | "dispose" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "visible" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onClick" | "onContextMenu" | "onDoubleClick" | "onPointerUp" | "onPointerDown" | "onPointerOver" | "onPointerOut" | "onPointerEnter" | "onPointerLeave" | "onPointerMove" | "onPointerMissed" | "onPointerCancel" | "onWheel" | "positions" | "rotations" | "scales"> & React.RefAttributes<InstancedRigidBodyApi>>;
@@ -6,7 +6,6 @@ import { Matrix4, Object3D, Vector3 } from "three";
6
6
  export interface RapierContext {
7
7
  rapier: typeof Rapier;
8
8
  world: WorldApi;
9
- colliderMeshes: Map<ColliderHandle, Object3D>;
10
9
  rigidBodyStates: Map<RigidBodyHandle, {
11
10
  mesh: Object3D;
12
11
  isSleeping: boolean;
@@ -1,6 +1,7 @@
1
1
  import React, { MutableRefObject, RefObject } from "react";
2
2
  import { ReactNode } from "react";
3
3
  import { Object3D } from "three";
4
+ import { Object3DProps } from "@react-three/fiber";
4
5
  import { InstancedRigidBodyApi } from "./api";
5
6
  import { InstancedRigidBodiesProps } from "./InstancedRigidBodies";
6
7
  import { RigidBodyApi, UseRigidBodyOptions } from "./types";
@@ -16,7 +17,7 @@ export declare const useRigidBodyContext: () => {
16
17
  hasCollisionEvents: boolean;
17
18
  options: UseRigidBodyOptions | InstancedRigidBodiesProps;
18
19
  };
19
- export interface RigidBodyProps extends UseRigidBodyOptions {
20
+ export interface RigidBodyProps extends UseRigidBodyOptions, Omit<Object3DProps, 'type' | 'position' | 'rotation'> {
20
21
  children?: ReactNode;
21
22
  }
22
- export declare const RigidBody: React.ForwardRefExoticComponent<RigidBodyProps & React.RefAttributes<import("./api").RigidBodyApi>>;
23
+ export declare const RigidBody: React.ForwardRefExoticComponent<Pick<RigidBodyProps, "type" | "canSleep" | "linearDamping" | "angularDamping" | "linearVelocity" | "angularVelocity" | "gravityScale" | "ccd" | "position" | "rotation" | "colliders" | "friction" | "restitution" | "onCollisionEnter" | "onCollisionExit" | "onSleep" | "onWake" | "lockRotations" | "lockTranslations" | "enabledRotations" | "enabledTranslations" | "children" | "quaternion" | "attach" | "args" | "key" | "onUpdate" | "up" | "scale" | "matrix" | "layers" | "dispose" | "id" | "uuid" | "name" | "parent" | "modelViewMatrix" | "normalMatrix" | "matrixWorld" | "matrixAutoUpdate" | "matrixWorldNeedsUpdate" | "visible" | "castShadow" | "receiveShadow" | "frustumCulled" | "renderOrder" | "animations" | "userData" | "customDepthMaterial" | "customDistanceMaterial" | "isObject3D" | "onBeforeRender" | "onAfterRender" | "applyMatrix4" | "applyQuaternion" | "setRotationFromAxisAngle" | "setRotationFromEuler" | "setRotationFromMatrix" | "setRotationFromQuaternion" | "rotateOnAxis" | "rotateOnWorldAxis" | "rotateX" | "rotateY" | "rotateZ" | "translateOnAxis" | "translateX" | "translateY" | "translateZ" | "localToWorld" | "worldToLocal" | "lookAt" | "add" | "remove" | "removeFromParent" | "clear" | "getObjectById" | "getObjectByName" | "getObjectByProperty" | "getWorldPosition" | "getWorldQuaternion" | "getWorldScale" | "getWorldDirection" | "raycast" | "traverse" | "traverseVisible" | "traverseAncestors" | "updateMatrix" | "updateMatrixWorld" | "updateWorldMatrix" | "toJSON" | "clone" | "copy" | "addEventListener" | "hasEventListener" | "removeEventListener" | "dispatchEvent" | "onClick" | "onContextMenu" | "onDoubleClick" | "onPointerUp" | "onPointerDown" | "onPointerOver" | "onPointerOut" | "onPointerEnter" | "onPointerLeave" | "onPointerMove" | "onPointerMissed" | "onPointerCancel" | "onWheel"> & React.RefAttributes<import("./api").RigidBodyApi>>;
@@ -58,7 +58,7 @@ export interface RigidBodyApi {
58
58
  /**
59
59
  * Sets the rotation quaternion of this rigid-body.
60
60
  */
61
- setRotation(rotation: Vector3Object): void;
61
+ setRotation(rotation: Quaternion): void;
62
62
  /**
63
63
  * The linear velocity of this rigid-body.
64
64
  */
@@ -99,7 +99,7 @@ export interface RigidBodyApi {
99
99
  * rigid-body from its current position and its next kinematic position. This velocity will be used
100
100
  * to compute forces on dynamic bodies interacting with this body.
101
101
  */
102
- setNextKinematicRotation(rotation: Vector3Object): void;
102
+ setNextKinematicRotation(rotation: Quaternion): void;
103
103
  /**
104
104
  * If this rigid body is kinematic, sets its future rotation after the next timestep integration.
105
105
  *
@@ -21,7 +21,11 @@ export declare type HeightfieldArgs = [
21
21
  width: number,
22
22
  height: number,
23
23
  heights: number[],
24
- scale: number
24
+ scale: {
25
+ x: number;
26
+ y: number;
27
+ z: number;
28
+ }
25
29
  ];
26
30
  export declare type TrimeshArgs = [
27
31
  vertices: ArrayLike<number>,
@@ -11,7 +11,15 @@ export declare const decomposeMatrix4: (m: Matrix4) => {
11
11
  rotation: Quaternion;
12
12
  scale: Vector3;
13
13
  };
14
- export declare const scaleColliderArgs: (shape: RigidBodyShape, args: (number | ArrayLike<number>)[], scale: Vector3) => (number | ArrayLike<number>)[];
14
+ export declare const scaleColliderArgs: (shape: RigidBodyShape, args: (number | ArrayLike<number> | {
15
+ x: number;
16
+ y: number;
17
+ z: number;
18
+ })[], scale: Vector3) => (number | ArrayLike<number> | {
19
+ x: number;
20
+ y: number;
21
+ z: number;
22
+ })[];
15
23
  interface CreateColliderFromOptions {
16
24
  <ColliderArgs>(options: {
17
25
  options: UseColliderOptions<ColliderArgs>;
@@ -7,6 +7,8 @@ var React = require('react');
7
7
  var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
+ var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
11
+ var threeStdlib = require('three-stdlib');
10
12
 
11
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
12
14
 
@@ -73,11 +75,13 @@ const decomposeMatrix4 = m => {
73
75
  };
74
76
  };
75
77
  const scaleColliderArgs = (shape, args, scale) => {
76
- // Heightfield only scales the last arg
77
- const newArgs = args.slice();
78
+ const newArgs = args.slice(); // Heightfield uses a vector
78
79
 
79
80
  if (shape === "heightfield") {
80
- newArgs[3] *= scale.x;
81
+ const s = newArgs[3];
82
+ s.x *= scale.x;
83
+ s.x *= scale.y;
84
+ s.x *= scale.z;
81
85
  return newArgs;
82
86
  } // Trimesh and convex scale the vertices
83
87
 
@@ -85,9 +89,10 @@ const scaleColliderArgs = (shape, args, scale) => {
85
89
  if (shape === "trimesh" || shape === "convexHull") {
86
90
  newArgs[0] = scaleVertices(newArgs[0], scale);
87
91
  return newArgs;
88
- }
92
+ } // Prepfill with some extra
93
+
89
94
 
90
- const scaleArray = [scale.x, scale.y, scale.z];
95
+ const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
91
96
  return newArgs.map((arg, index) => scaleArray[index] * arg);
92
97
  };
93
98
  const createColliderFromOptions = ({
@@ -163,7 +168,6 @@ const createCollidersFromChildren = ({
163
168
  }) => {
164
169
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
165
170
  const colliders = [];
166
- new three.Vector3();
167
171
  object.traverseVisible(child => {
168
172
  if ("isMesh" in child) {
169
173
  if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
@@ -244,15 +248,15 @@ const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents
244
248
  {
245
249
  var _g$index;
246
250
 
247
- const _g = geometry.clone().scale(scale.x, scale.y, scale.z);
248
-
249
- desc = rapier3dCompat.ColliderDesc.trimesh(_g.attributes.position.array, (_g$index = _g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
251
+ const clonedGeometry = geometry.index ? geometry.clone() : BufferGeometryUtils.mergeVertices(geometry);
252
+ const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
253
+ desc = rapier3dCompat.ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
250
254
  }
251
255
  break;
252
256
 
253
257
  case "hull":
254
- const g = geometry.clone().scale(scale.x, scale.y, scale.z);
255
258
  {
259
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
256
260
  desc = rapier3dCompat.ColliderDesc.convexHull(g.attributes.position.array);
257
261
  }
258
262
  break;
@@ -319,12 +323,7 @@ const createRigidBodyApi = ref => {
319
323
  addTorque: torque => ref.current().addTorque(torque, true),
320
324
 
321
325
  translation() {
322
- const {
323
- x,
324
- y,
325
- z
326
- } = ref.current().translation();
327
- return new three.Vector3(x, y, z);
326
+ return rapierVector3ToVector3(ref.current().translation());
328
327
  },
329
328
 
330
329
  setTranslation: translation => ref.current().setTranslation(translation, true),
@@ -339,18 +338,8 @@ const createRigidBodyApi = ref => {
339
338
  return new three.Quaternion(x, y, z, w);
340
339
  },
341
340
 
342
- setRotation: ({
343
- x,
344
- y,
345
- z
346
- }) => {
347
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
348
- ref.current().setRotation({
349
- x: q.x,
350
- y: q.y,
351
- z: q.z,
352
- w: q.w
353
- }, true);
341
+ setRotation: rotation => {
342
+ ref.current().setRotation(rotation, true);
354
343
  },
355
344
 
356
345
  linvel() {
@@ -386,18 +375,8 @@ const createRigidBodyApi = ref => {
386
375
  },
387
376
 
388
377
  setAngularDamping: factor => ref.current().setAngularDamping(factor),
389
- setNextKinematicRotation: ({
390
- x,
391
- y,
392
- z
393
- }) => {
394
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
395
- ref.current().setNextKinematicRotation({
396
- x: q.x,
397
- y: q.y,
398
- z: q.z,
399
- w: q.w
400
- });
378
+ setNextKinematicRotation: rotation => {
379
+ ref.current().setNextKinematicRotation(rotation);
401
380
  },
402
381
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
403
382
  resetForces: () => ref.current().resetForces(true),
@@ -487,7 +466,6 @@ const Physics = ({
487
466
 
488
467
  return worldRef.current;
489
468
  });
490
- const [colliderMeshes] = React.useState(() => new Map());
491
469
  const [rigidBodyStates] = React.useState(() => new Map());
492
470
  const [rigidBodyEvents] = React.useState(() => new Map());
493
471
  const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
@@ -537,8 +515,8 @@ const Physics = ({
537
515
  // Collect previous state
538
516
  world.bodies.forEach(b => {
539
517
  previousTranslations[b.handle] = {
540
- rotation: b.rotation(),
541
- translation: b.translation()
518
+ rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
519
+ translation: rapierVector3ToVector3(b.translation())
542
520
  };
543
521
  });
544
522
  world.step(eventQueue);
@@ -569,15 +547,15 @@ const Physics = ({
569
547
  state.isSleeping = rigidBody.isSleeping();
570
548
  }
571
549
 
572
- if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !state.setMatrix) {
550
+ if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
573
551
  return;
574
552
  }
575
553
 
576
554
  let oldState = previousTranslations[rigidBody.handle];
577
555
  let newTranslation = rapierVector3ToVector3(rigidBody.translation());
578
556
  let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
579
- let interpolatedTranslation = oldState ? rapierVector3ToVector3(oldState.translation).lerp(newTranslation, interpolationAlpha) : newTranslation;
580
- let interpolatedRotation = oldState ? rapierQuaternionToQuaternion(oldState.rotation).slerp(newRotation, interpolationAlpha) : newRotation;
557
+ let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
558
+ let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
581
559
  state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
582
560
 
583
561
  if (state.mesh instanceof three.InstancedMesh) {
@@ -593,7 +571,7 @@ const Physics = ({
593
571
  const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
594
572
  const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
595
573
 
596
- if (!collider1 || !collider2 || !rigidBodyHandle1 || !rigidBodyHandle2) {
574
+ if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
597
575
  return;
598
576
  }
599
577
 
@@ -637,7 +615,6 @@ const Physics = ({
637
615
  colliders: _colliders,
638
616
  gravity: _gravity
639
617
  },
640
- colliderMeshes,
641
618
  rigidBodyStates,
642
619
  rigidBodyEvents,
643
620
  isPaused
@@ -647,6 +624,24 @@ const Physics = ({
647
624
  }, children);
648
625
  };
649
626
 
627
+ function _extends() {
628
+ _extends = Object.assign || function (target) {
629
+ for (var i = 1; i < arguments.length; i++) {
630
+ var source = arguments[i];
631
+
632
+ for (var key in source) {
633
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
634
+ target[key] = source[key];
635
+ }
636
+ }
637
+ }
638
+
639
+ return target;
640
+ };
641
+
642
+ return _extends.apply(this, arguments);
643
+ }
644
+
650
645
  function _objectWithoutPropertiesLoose(source, excluded) {
651
646
  if (source == null) return {};
652
647
  var target = {};
@@ -913,7 +908,8 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
913
908
  return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
914
909
  };
915
910
 
916
- const _excluded$1 = ["children"];
911
+ const _excluded$1 = ["children"],
912
+ _excluded2 = ["type", "position", "rotation"];
917
913
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
918
914
  const useRigidBodyContext = () => React.useContext(RigidBodyContext); // RigidBody
919
915
 
@@ -924,6 +920,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
924
920
  props = _objectWithoutProperties(_ref, _excluded$1);
925
921
 
926
922
  const [object, api] = useRigidBody(props);
923
+
924
+ const objectProps = _objectWithoutProperties(props, _excluded2);
925
+
927
926
  React.useImperativeHandle(ref, () => api);
928
927
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
929
928
  value: {
@@ -932,9 +931,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
932
931
  hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
933
932
  options: props
934
933
  }
935
- }, /*#__PURE__*/React__default["default"].createElement("object3D", {
934
+ }, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
936
935
  ref: object
937
- }, children));
936
+ }, objectProps), children));
938
937
  });
939
938
 
940
939
  const MeshCollider = ({
@@ -997,6 +996,17 @@ const geometryFromCollider = collider => {
997
996
  return new three.BoxBufferGeometry(x * 2 + 0.01, y * 2 + 0.01, z * 2 + 0.01);
998
997
  }
999
998
 
999
+ case rapier3dCompat.ShapeType.RoundCuboid:
1000
+ {
1001
+ const {
1002
+ x,
1003
+ y,
1004
+ z
1005
+ } = collider.shape.halfExtents;
1006
+ const radius = collider.shape.borderRadius;
1007
+ return new threeStdlib.RoundedBoxGeometry(x * 2 + radius * 2, y * 2 + radius * 2, z * 2 + radius * 2, 8, radius);
1008
+ }
1009
+
1000
1010
  case rapier3dCompat.ShapeType.Ball:
1001
1011
  {
1002
1012
  const r = collider.shape.radius;
@@ -1032,7 +1042,38 @@ const geometryFromCollider = collider => {
1032
1042
  {
1033
1043
  const r = collider.shape.radius;
1034
1044
  const h = collider.shape.halfHeight;
1035
- const g = new three.CylinderBufferGeometry(r, r, h);
1045
+ const g = new three.CylinderBufferGeometry(r, r, h * 2);
1046
+ return g;
1047
+ }
1048
+
1049
+ case rapier3dCompat.ShapeType.Capsule:
1050
+ {
1051
+ const r = collider.shape.radius;
1052
+ const h = collider.shape.halfHeight;
1053
+ const g = new three.CapsuleBufferGeometry(r, h * 2, 4, 8);
1054
+ return g;
1055
+ }
1056
+
1057
+ case rapier3dCompat.ShapeType.Cone:
1058
+ {
1059
+ const r = collider.shape.radius;
1060
+ const h = collider.shape.halfHeight;
1061
+ const g = new three.ConeBufferGeometry(r, h * 2, 16);
1062
+ return g;
1063
+ }
1064
+
1065
+ case rapier3dCompat.ShapeType.HeightField:
1066
+ {
1067
+ const rows = collider.shape.nrows;
1068
+ const cols = collider.shape.ncols;
1069
+ const heights = collider.shape.heights;
1070
+ const scale = collider.shape.scale;
1071
+ const g = new three.PlaneGeometry(scale.x, scale.z, cols, rows);
1072
+ const verts = g.attributes.position.array;
1073
+ verts.forEach((v, index) => verts[index * 3 + 2] = heights[index] * scale.y);
1074
+ g.scale(1, -1, 1);
1075
+ g.rotateX(-Math.PI / 2);
1076
+ g.rotateY(-Math.PI / 2);
1036
1077
  return g;
1037
1078
  }
1038
1079
  }
@@ -1041,12 +1082,18 @@ const geometryFromCollider = collider => {
1041
1082
  };
1042
1083
 
1043
1084
  const DebugShape = /*#__PURE__*/React.memo(({
1044
- colliderHandle
1085
+ colliderHandle,
1086
+ color,
1087
+ sleepColor
1045
1088
  }) => {
1046
1089
  const {
1047
1090
  world
1048
1091
  } = useRapier();
1049
1092
  const ref = React.useRef(null);
1093
+ const [material] = React.useState(new three.MeshBasicMaterial({
1094
+ color,
1095
+ wireframe: true
1096
+ }));
1050
1097
  fiber.useFrame(() => {
1051
1098
  const collider = world.getCollider(colliderHandle);
1052
1099
 
@@ -1062,6 +1109,14 @@ const DebugShape = /*#__PURE__*/React.memo(({
1062
1109
  y,
1063
1110
  z
1064
1111
  } = collider.translation();
1112
+ const parent = collider.parent();
1113
+
1114
+ if (parent !== null && parent !== void 0 && parent.isSleeping() || parent !== null && parent !== void 0 && parent.isFixed() || parent !== null && parent !== void 0 && parent.isKinematic()) {
1115
+ material.color = new three.Color(sleepColor);
1116
+ } else {
1117
+ material.color = new three.Color(color);
1118
+ }
1119
+
1065
1120
  ref.current.position.set(x, y, z);
1066
1121
  ref.current.rotation.setFromQuaternion(new three.Quaternion(rx, ry, rz, rw));
1067
1122
  }
@@ -1071,16 +1126,17 @@ const DebugShape = /*#__PURE__*/React.memo(({
1071
1126
  return geometryFromCollider(collider);
1072
1127
  }, [colliderHandle]);
1073
1128
  return /*#__PURE__*/React__default["default"].createElement("mesh", {
1074
- ref: ref
1129
+ ref: ref,
1130
+ material: material
1075
1131
  }, /*#__PURE__*/React__default["default"].createElement("primitive", {
1076
1132
  object: geometry,
1077
1133
  attach: "geometry"
1078
- }), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
1079
- color: "red",
1080
- wireframe: true
1081
1134
  }));
1082
1135
  });
1083
- const Debug = () => {
1136
+ const Debug = ({
1137
+ color: _color = "red",
1138
+ sleepColor: _sleepColor = "blue"
1139
+ }) => {
1084
1140
  const {
1085
1141
  world
1086
1142
  } = useRapier();
@@ -1096,7 +1152,9 @@ const Debug = () => {
1096
1152
  });
1097
1153
  return /*#__PURE__*/React__default["default"].createElement("group", null, colliders.map(handle => /*#__PURE__*/React__default["default"].createElement(DebugShape, {
1098
1154
  key: handle,
1099
- colliderHandle: handle
1155
+ colliderHandle: handle,
1156
+ color: _color,
1157
+ sleepColor: _sleepColor
1100
1158
  })));
1101
1159
  };
1102
1160
 
@@ -1224,24 +1282,6 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1224
1282
  }, props.children));
1225
1283
  });
1226
1284
 
1227
- function _extends() {
1228
- _extends = Object.assign || function (target) {
1229
- for (var i = 1; i < arguments.length; i++) {
1230
- var source = arguments[i];
1231
-
1232
- for (var key in source) {
1233
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1234
- target[key] = source[key];
1235
- }
1236
- }
1237
- }
1238
-
1239
- return target;
1240
- };
1241
-
1242
- return _extends.apply(this, arguments);
1243
- }
1244
-
1245
1285
  const _excluded = ["children"];
1246
1286
 
1247
1287
  const AnyCollider = _ref => {
@@ -7,6 +7,8 @@ var React = require('react');
7
7
  var useAsset = require('use-asset');
8
8
  var fiber = require('@react-three/fiber');
9
9
  var three = require('three');
10
+ var BufferGeometryUtils = require('three/examples/jsm/utils/BufferGeometryUtils');
11
+ var threeStdlib = require('three-stdlib');
10
12
 
11
13
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
12
14
 
@@ -73,11 +75,13 @@ const decomposeMatrix4 = m => {
73
75
  };
74
76
  };
75
77
  const scaleColliderArgs = (shape, args, scale) => {
76
- // Heightfield only scales the last arg
77
- const newArgs = args.slice();
78
+ const newArgs = args.slice(); // Heightfield uses a vector
78
79
 
79
80
  if (shape === "heightfield") {
80
- newArgs[3] *= scale.x;
81
+ const s = newArgs[3];
82
+ s.x *= scale.x;
83
+ s.x *= scale.y;
84
+ s.x *= scale.z;
81
85
  return newArgs;
82
86
  } // Trimesh and convex scale the vertices
83
87
 
@@ -85,9 +89,10 @@ const scaleColliderArgs = (shape, args, scale) => {
85
89
  if (shape === "trimesh" || shape === "convexHull") {
86
90
  newArgs[0] = scaleVertices(newArgs[0], scale);
87
91
  return newArgs;
88
- }
92
+ } // Prepfill with some extra
93
+
89
94
 
90
- const scaleArray = [scale.x, scale.y, scale.z];
95
+ const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
91
96
  return newArgs.map((arg, index) => scaleArray[index] * arg);
92
97
  };
93
98
  const createColliderFromOptions = ({
@@ -163,7 +168,6 @@ const createCollidersFromChildren = ({
163
168
  }) => {
164
169
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
165
170
  const colliders = [];
166
- new three.Vector3();
167
171
  object.traverseVisible(child => {
168
172
  if ("isMesh" in child) {
169
173
  if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
@@ -244,15 +248,15 @@ const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents
244
248
  {
245
249
  var _g$index;
246
250
 
247
- const _g = geometry.clone().scale(scale.x, scale.y, scale.z);
248
-
249
- desc = rapier3dCompat.ColliderDesc.trimesh(_g.attributes.position.array, (_g$index = _g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
251
+ const clonedGeometry = geometry.index ? geometry.clone() : BufferGeometryUtils.mergeVertices(geometry);
252
+ const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
253
+ desc = rapier3dCompat.ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
250
254
  }
251
255
  break;
252
256
 
253
257
  case "hull":
254
- const g = geometry.clone().scale(scale.x, scale.y, scale.z);
255
258
  {
259
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
256
260
  desc = rapier3dCompat.ColliderDesc.convexHull(g.attributes.position.array);
257
261
  }
258
262
  break;
@@ -319,12 +323,7 @@ const createRigidBodyApi = ref => {
319
323
  addTorque: torque => ref.current().addTorque(torque, true),
320
324
 
321
325
  translation() {
322
- const {
323
- x,
324
- y,
325
- z
326
- } = ref.current().translation();
327
- return new three.Vector3(x, y, z);
326
+ return rapierVector3ToVector3(ref.current().translation());
328
327
  },
329
328
 
330
329
  setTranslation: translation => ref.current().setTranslation(translation, true),
@@ -339,18 +338,8 @@ const createRigidBodyApi = ref => {
339
338
  return new three.Quaternion(x, y, z, w);
340
339
  },
341
340
 
342
- setRotation: ({
343
- x,
344
- y,
345
- z
346
- }) => {
347
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
348
- ref.current().setRotation({
349
- x: q.x,
350
- y: q.y,
351
- z: q.z,
352
- w: q.w
353
- }, true);
341
+ setRotation: rotation => {
342
+ ref.current().setRotation(rotation, true);
354
343
  },
355
344
 
356
345
  linvel() {
@@ -386,18 +375,8 @@ const createRigidBodyApi = ref => {
386
375
  },
387
376
 
388
377
  setAngularDamping: factor => ref.current().setAngularDamping(factor),
389
- setNextKinematicRotation: ({
390
- x,
391
- y,
392
- z
393
- }) => {
394
- const q = vector3ToQuaternion(new three.Vector3(x, y, z));
395
- ref.current().setNextKinematicRotation({
396
- x: q.x,
397
- y: q.y,
398
- z: q.z,
399
- w: q.w
400
- });
378
+ setNextKinematicRotation: rotation => {
379
+ ref.current().setNextKinematicRotation(rotation);
401
380
  },
402
381
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
403
382
  resetForces: () => ref.current().resetForces(true),
@@ -487,7 +466,6 @@ const Physics = ({
487
466
 
488
467
  return worldRef.current;
489
468
  });
490
- const [colliderMeshes] = React.useState(() => new Map());
491
469
  const [rigidBodyStates] = React.useState(() => new Map());
492
470
  const [rigidBodyEvents] = React.useState(() => new Map());
493
471
  const [eventQueue] = React.useState(() => new rapier3dCompat.EventQueue(false)); // Init world
@@ -537,8 +515,8 @@ const Physics = ({
537
515
  // Collect previous state
538
516
  world.bodies.forEach(b => {
539
517
  previousTranslations[b.handle] = {
540
- rotation: b.rotation(),
541
- translation: b.translation()
518
+ rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
519
+ translation: rapierVector3ToVector3(b.translation())
542
520
  };
543
521
  });
544
522
  world.step(eventQueue);
@@ -569,15 +547,15 @@ const Physics = ({
569
547
  state.isSleeping = rigidBody.isSleeping();
570
548
  }
571
549
 
572
- if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !state.setMatrix) {
550
+ if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
573
551
  return;
574
552
  }
575
553
 
576
554
  let oldState = previousTranslations[rigidBody.handle];
577
555
  let newTranslation = rapierVector3ToVector3(rigidBody.translation());
578
556
  let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
579
- let interpolatedTranslation = oldState ? rapierVector3ToVector3(oldState.translation).lerp(newTranslation, interpolationAlpha) : newTranslation;
580
- let interpolatedRotation = oldState ? rapierQuaternionToQuaternion(oldState.rotation).slerp(newRotation, interpolationAlpha) : newRotation;
557
+ let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
558
+ let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
581
559
  state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
582
560
 
583
561
  if (state.mesh instanceof three.InstancedMesh) {
@@ -593,7 +571,7 @@ const Physics = ({
593
571
  const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
594
572
  const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
595
573
 
596
- if (!collider1 || !collider2 || !rigidBodyHandle1 || !rigidBodyHandle2) {
574
+ if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
597
575
  return;
598
576
  }
599
577
 
@@ -637,7 +615,6 @@ const Physics = ({
637
615
  colliders: _colliders,
638
616
  gravity: _gravity
639
617
  },
640
- colliderMeshes,
641
618
  rigidBodyStates,
642
619
  rigidBodyEvents,
643
620
  isPaused
@@ -647,6 +624,24 @@ const Physics = ({
647
624
  }, children);
648
625
  };
649
626
 
627
+ function _extends() {
628
+ _extends = Object.assign || function (target) {
629
+ for (var i = 1; i < arguments.length; i++) {
630
+ var source = arguments[i];
631
+
632
+ for (var key in source) {
633
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
634
+ target[key] = source[key];
635
+ }
636
+ }
637
+ }
638
+
639
+ return target;
640
+ };
641
+
642
+ return _extends.apply(this, arguments);
643
+ }
644
+
650
645
  function _objectWithoutPropertiesLoose(source, excluded) {
651
646
  if (source == null) return {};
652
647
  var target = {};
@@ -913,7 +908,8 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
913
908
  return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
914
909
  };
915
910
 
916
- const _excluded$1 = ["children"];
911
+ const _excluded$1 = ["children"],
912
+ _excluded2 = ["type", "position", "rotation"];
917
913
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
918
914
  const useRigidBodyContext = () => React.useContext(RigidBodyContext); // RigidBody
919
915
 
@@ -924,6 +920,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
924
920
  props = _objectWithoutProperties(_ref, _excluded$1);
925
921
 
926
922
  const [object, api] = useRigidBody(props);
923
+
924
+ const objectProps = _objectWithoutProperties(props, _excluded2);
925
+
927
926
  React.useImperativeHandle(ref, () => api);
928
927
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
929
928
  value: {
@@ -932,9 +931,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
932
931
  hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
933
932
  options: props
934
933
  }
935
- }, /*#__PURE__*/React__default["default"].createElement("object3D", {
934
+ }, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
936
935
  ref: object
937
- }, children));
936
+ }, objectProps), children));
938
937
  });
939
938
 
940
939
  const MeshCollider = ({
@@ -997,6 +996,17 @@ const geometryFromCollider = collider => {
997
996
  return new three.BoxBufferGeometry(x * 2 + 0.01, y * 2 + 0.01, z * 2 + 0.01);
998
997
  }
999
998
 
999
+ case rapier3dCompat.ShapeType.RoundCuboid:
1000
+ {
1001
+ const {
1002
+ x,
1003
+ y,
1004
+ z
1005
+ } = collider.shape.halfExtents;
1006
+ const radius = collider.shape.borderRadius;
1007
+ return new threeStdlib.RoundedBoxGeometry(x * 2 + radius * 2, y * 2 + radius * 2, z * 2 + radius * 2, 8, radius);
1008
+ }
1009
+
1000
1010
  case rapier3dCompat.ShapeType.Ball:
1001
1011
  {
1002
1012
  const r = collider.shape.radius;
@@ -1032,7 +1042,38 @@ const geometryFromCollider = collider => {
1032
1042
  {
1033
1043
  const r = collider.shape.radius;
1034
1044
  const h = collider.shape.halfHeight;
1035
- const g = new three.CylinderBufferGeometry(r, r, h);
1045
+ const g = new three.CylinderBufferGeometry(r, r, h * 2);
1046
+ return g;
1047
+ }
1048
+
1049
+ case rapier3dCompat.ShapeType.Capsule:
1050
+ {
1051
+ const r = collider.shape.radius;
1052
+ const h = collider.shape.halfHeight;
1053
+ const g = new three.CapsuleBufferGeometry(r, h * 2, 4, 8);
1054
+ return g;
1055
+ }
1056
+
1057
+ case rapier3dCompat.ShapeType.Cone:
1058
+ {
1059
+ const r = collider.shape.radius;
1060
+ const h = collider.shape.halfHeight;
1061
+ const g = new three.ConeBufferGeometry(r, h * 2, 16);
1062
+ return g;
1063
+ }
1064
+
1065
+ case rapier3dCompat.ShapeType.HeightField:
1066
+ {
1067
+ const rows = collider.shape.nrows;
1068
+ const cols = collider.shape.ncols;
1069
+ const heights = collider.shape.heights;
1070
+ const scale = collider.shape.scale;
1071
+ const g = new three.PlaneGeometry(scale.x, scale.z, cols, rows);
1072
+ const verts = g.attributes.position.array;
1073
+ verts.forEach((v, index) => verts[index * 3 + 2] = heights[index] * scale.y);
1074
+ g.scale(1, -1, 1);
1075
+ g.rotateX(-Math.PI / 2);
1076
+ g.rotateY(-Math.PI / 2);
1036
1077
  return g;
1037
1078
  }
1038
1079
  }
@@ -1041,12 +1082,18 @@ const geometryFromCollider = collider => {
1041
1082
  };
1042
1083
 
1043
1084
  const DebugShape = /*#__PURE__*/React.memo(({
1044
- colliderHandle
1085
+ colliderHandle,
1086
+ color,
1087
+ sleepColor
1045
1088
  }) => {
1046
1089
  const {
1047
1090
  world
1048
1091
  } = useRapier();
1049
1092
  const ref = React.useRef(null);
1093
+ const [material] = React.useState(new three.MeshBasicMaterial({
1094
+ color,
1095
+ wireframe: true
1096
+ }));
1050
1097
  fiber.useFrame(() => {
1051
1098
  const collider = world.getCollider(colliderHandle);
1052
1099
 
@@ -1062,6 +1109,14 @@ const DebugShape = /*#__PURE__*/React.memo(({
1062
1109
  y,
1063
1110
  z
1064
1111
  } = collider.translation();
1112
+ const parent = collider.parent();
1113
+
1114
+ if (parent !== null && parent !== void 0 && parent.isSleeping() || parent !== null && parent !== void 0 && parent.isFixed() || parent !== null && parent !== void 0 && parent.isKinematic()) {
1115
+ material.color = new three.Color(sleepColor);
1116
+ } else {
1117
+ material.color = new three.Color(color);
1118
+ }
1119
+
1065
1120
  ref.current.position.set(x, y, z);
1066
1121
  ref.current.rotation.setFromQuaternion(new three.Quaternion(rx, ry, rz, rw));
1067
1122
  }
@@ -1071,16 +1126,17 @@ const DebugShape = /*#__PURE__*/React.memo(({
1071
1126
  return geometryFromCollider(collider);
1072
1127
  }, [colliderHandle]);
1073
1128
  return /*#__PURE__*/React__default["default"].createElement("mesh", {
1074
- ref: ref
1129
+ ref: ref,
1130
+ material: material
1075
1131
  }, /*#__PURE__*/React__default["default"].createElement("primitive", {
1076
1132
  object: geometry,
1077
1133
  attach: "geometry"
1078
- }), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
1079
- color: "red",
1080
- wireframe: true
1081
1134
  }));
1082
1135
  });
1083
- const Debug = () => {
1136
+ const Debug = ({
1137
+ color: _color = "red",
1138
+ sleepColor: _sleepColor = "blue"
1139
+ }) => {
1084
1140
  const {
1085
1141
  world
1086
1142
  } = useRapier();
@@ -1096,7 +1152,9 @@ const Debug = () => {
1096
1152
  });
1097
1153
  return /*#__PURE__*/React__default["default"].createElement("group", null, colliders.map(handle => /*#__PURE__*/React__default["default"].createElement(DebugShape, {
1098
1154
  key: handle,
1099
- colliderHandle: handle
1155
+ colliderHandle: handle,
1156
+ color: _color,
1157
+ sleepColor: _sleepColor
1100
1158
  })));
1101
1159
  };
1102
1160
 
@@ -1224,24 +1282,6 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1224
1282
  }, props.children));
1225
1283
  });
1226
1284
 
1227
- function _extends() {
1228
- _extends = Object.assign || function (target) {
1229
- for (var i = 1; i < arguments.length; i++) {
1230
- var source = arguments[i];
1231
-
1232
- for (var key in source) {
1233
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1234
- target[key] = source[key];
1235
- }
1236
- }
1237
- }
1238
-
1239
- return target;
1240
- };
1241
-
1242
- return _extends.apply(this, arguments);
1243
- }
1244
-
1245
1285
  const _excluded = ["children"];
1246
1286
 
1247
1287
  const AnyCollider = _ref => {
@@ -3,7 +3,9 @@ export { CoefficientCombineRule, Collider as RapierCollider, RigidBody as Rapier
3
3
  import React, { useState, useEffect, useRef, 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
- import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
6
+ import { Quaternion, Euler, Vector3, Object3D, Matrix4, InstancedMesh, MeshBasicMaterial, Color, PlaneGeometry, ConeBufferGeometry, CapsuleBufferGeometry, CylinderBufferGeometry, BufferGeometry, BufferAttribute, SphereBufferGeometry, BoxBufferGeometry, DynamicDrawUsage } from 'three';
7
+ import { mergeVertices } from 'three/examples/jsm/utils/BufferGeometryUtils';
8
+ import { RoundedBoxGeometry } from 'three-stdlib';
7
9
 
8
10
  const _quaternion = new Quaternion();
9
11
  const _euler = new Euler();
@@ -48,11 +50,13 @@ const decomposeMatrix4 = m => {
48
50
  };
49
51
  };
50
52
  const scaleColliderArgs = (shape, args, scale) => {
51
- // Heightfield only scales the last arg
52
- const newArgs = args.slice();
53
+ const newArgs = args.slice(); // Heightfield uses a vector
53
54
 
54
55
  if (shape === "heightfield") {
55
- newArgs[3] *= scale.x;
56
+ const s = newArgs[3];
57
+ s.x *= scale.x;
58
+ s.x *= scale.y;
59
+ s.x *= scale.z;
56
60
  return newArgs;
57
61
  } // Trimesh and convex scale the vertices
58
62
 
@@ -60,9 +64,10 @@ const scaleColliderArgs = (shape, args, scale) => {
60
64
  if (shape === "trimesh" || shape === "convexHull") {
61
65
  newArgs[0] = scaleVertices(newArgs[0], scale);
62
66
  return newArgs;
63
- }
67
+ } // Prepfill with some extra
68
+
64
69
 
65
- const scaleArray = [scale.x, scale.y, scale.z];
70
+ const scaleArray = [scale.x, scale.y, scale.z, scale.x, scale.x];
66
71
  return newArgs.map((arg, index) => scaleArray[index] * arg);
67
72
  };
68
73
  const createColliderFromOptions = ({
@@ -138,7 +143,6 @@ const createCollidersFromChildren = ({
138
143
  }) => {
139
144
  const hasCollisionEvents = !!(options.onCollisionEnter || options.onCollisionExit);
140
145
  const colliders = [];
141
- new Vector3();
142
146
  object.traverseVisible(child => {
143
147
  if ("isMesh" in child) {
144
148
  if (_ignoreMeshColliders && isChildOfMeshCollider(child)) return;
@@ -219,15 +223,15 @@ const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents
219
223
  {
220
224
  var _g$index;
221
225
 
222
- const _g = geometry.clone().scale(scale.x, scale.y, scale.z);
223
-
224
- desc = ColliderDesc.trimesh(_g.attributes.position.array, (_g$index = _g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
226
+ const clonedGeometry = geometry.index ? geometry.clone() : mergeVertices(geometry);
227
+ const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
228
+ desc = ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
225
229
  }
226
230
  break;
227
231
 
228
232
  case "hull":
229
- const g = geometry.clone().scale(scale.x, scale.y, scale.z);
230
233
  {
234
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
231
235
  desc = ColliderDesc.convexHull(g.attributes.position.array);
232
236
  }
233
237
  break;
@@ -294,12 +298,7 @@ const createRigidBodyApi = ref => {
294
298
  addTorque: torque => ref.current().addTorque(torque, true),
295
299
 
296
300
  translation() {
297
- const {
298
- x,
299
- y,
300
- z
301
- } = ref.current().translation();
302
- return new Vector3(x, y, z);
301
+ return rapierVector3ToVector3(ref.current().translation());
303
302
  },
304
303
 
305
304
  setTranslation: translation => ref.current().setTranslation(translation, true),
@@ -314,18 +313,8 @@ const createRigidBodyApi = ref => {
314
313
  return new Quaternion(x, y, z, w);
315
314
  },
316
315
 
317
- setRotation: ({
318
- x,
319
- y,
320
- z
321
- }) => {
322
- const q = vector3ToQuaternion(new Vector3(x, y, z));
323
- ref.current().setRotation({
324
- x: q.x,
325
- y: q.y,
326
- z: q.z,
327
- w: q.w
328
- }, true);
316
+ setRotation: rotation => {
317
+ ref.current().setRotation(rotation, true);
329
318
  },
330
319
 
331
320
  linvel() {
@@ -361,18 +350,8 @@ const createRigidBodyApi = ref => {
361
350
  },
362
351
 
363
352
  setAngularDamping: factor => ref.current().setAngularDamping(factor),
364
- setNextKinematicRotation: ({
365
- x,
366
- y,
367
- z
368
- }) => {
369
- const q = vector3ToQuaternion(new Vector3(x, y, z));
370
- ref.current().setNextKinematicRotation({
371
- x: q.x,
372
- y: q.y,
373
- z: q.z,
374
- w: q.w
375
- });
353
+ setNextKinematicRotation: rotation => {
354
+ ref.current().setNextKinematicRotation(rotation);
376
355
  },
377
356
  setNextKinematicTranslation: translation => ref.current().setNextKinematicTranslation(translation),
378
357
  resetForces: () => ref.current().resetForces(true),
@@ -462,7 +441,6 @@ const Physics = ({
462
441
 
463
442
  return worldRef.current;
464
443
  });
465
- const [colliderMeshes] = useState(() => new Map());
466
444
  const [rigidBodyStates] = useState(() => new Map());
467
445
  const [rigidBodyEvents] = useState(() => new Map());
468
446
  const [eventQueue] = useState(() => new EventQueue(false)); // Init world
@@ -512,8 +490,8 @@ const Physics = ({
512
490
  // Collect previous state
513
491
  world.bodies.forEach(b => {
514
492
  previousTranslations[b.handle] = {
515
- rotation: b.rotation(),
516
- translation: b.translation()
493
+ rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
494
+ translation: rapierVector3ToVector3(b.translation())
517
495
  };
518
496
  });
519
497
  world.step(eventQueue);
@@ -544,15 +522,15 @@ const Physics = ({
544
522
  state.isSleeping = rigidBody.isSleeping();
545
523
  }
546
524
 
547
- if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !state.setMatrix) {
525
+ if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
548
526
  return;
549
527
  }
550
528
 
551
529
  let oldState = previousTranslations[rigidBody.handle];
552
530
  let newTranslation = rapierVector3ToVector3(rigidBody.translation());
553
531
  let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
554
- let interpolatedTranslation = oldState ? rapierVector3ToVector3(oldState.translation).lerp(newTranslation, interpolationAlpha) : newTranslation;
555
- let interpolatedRotation = oldState ? rapierQuaternionToQuaternion(oldState.rotation).slerp(newRotation, interpolationAlpha) : newRotation;
532
+ let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
533
+ let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
556
534
  state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
557
535
 
558
536
  if (state.mesh instanceof InstancedMesh) {
@@ -568,7 +546,7 @@ const Physics = ({
568
546
  const rigidBodyHandle1 = (_collider1$parent = collider1.parent()) === null || _collider1$parent === void 0 ? void 0 : _collider1$parent.handle;
569
547
  const rigidBodyHandle2 = (_collider2$parent = collider2.parent()) === null || _collider2$parent === void 0 ? void 0 : _collider2$parent.handle;
570
548
 
571
- if (!collider1 || !collider2 || !rigidBodyHandle1 || !rigidBodyHandle2) {
549
+ if (!collider1 || !collider2 || rigidBodyHandle1 === undefined || rigidBodyHandle2 === undefined) {
572
550
  return;
573
551
  }
574
552
 
@@ -612,7 +590,6 @@ const Physics = ({
612
590
  colliders: _colliders,
613
591
  gravity: _gravity
614
592
  },
615
- colliderMeshes,
616
593
  rigidBodyStates,
617
594
  rigidBodyEvents,
618
595
  isPaused
@@ -622,6 +599,24 @@ const Physics = ({
622
599
  }, children);
623
600
  };
624
601
 
602
+ function _extends() {
603
+ _extends = Object.assign || function (target) {
604
+ for (var i = 1; i < arguments.length; i++) {
605
+ var source = arguments[i];
606
+
607
+ for (var key in source) {
608
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
609
+ target[key] = source[key];
610
+ }
611
+ }
612
+ }
613
+
614
+ return target;
615
+ };
616
+
617
+ return _extends.apply(this, arguments);
618
+ }
619
+
625
620
  function _objectWithoutPropertiesLoose(source, excluded) {
626
621
  if (source == null) return {};
627
622
  var target = {};
@@ -888,7 +883,8 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
888
883
  return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
889
884
  };
890
885
 
891
- const _excluded$1 = ["children"];
886
+ const _excluded$1 = ["children"],
887
+ _excluded2 = ["type", "position", "rotation"];
892
888
  const RigidBodyContext = /*#__PURE__*/createContext(undefined);
893
889
  const useRigidBodyContext = () => useContext(RigidBodyContext); // RigidBody
894
890
 
@@ -899,6 +895,9 @@ const RigidBody = /*#__PURE__*/forwardRef((_ref, ref) => {
899
895
  props = _objectWithoutProperties(_ref, _excluded$1);
900
896
 
901
897
  const [object, api] = useRigidBody(props);
898
+
899
+ const objectProps = _objectWithoutProperties(props, _excluded2);
900
+
902
901
  useImperativeHandle(ref, () => api);
903
902
  return /*#__PURE__*/React.createElement(RigidBodyContext.Provider, {
904
903
  value: {
@@ -907,9 +906,9 @@ const RigidBody = /*#__PURE__*/forwardRef((_ref, ref) => {
907
906
  hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
908
907
  options: props
909
908
  }
910
- }, /*#__PURE__*/React.createElement("object3D", {
909
+ }, /*#__PURE__*/React.createElement("object3D", _extends({
911
910
  ref: object
912
- }, children));
911
+ }, objectProps), children));
913
912
  });
914
913
 
915
914
  const MeshCollider = ({
@@ -972,6 +971,17 @@ const geometryFromCollider = collider => {
972
971
  return new BoxBufferGeometry(x * 2 + 0.01, y * 2 + 0.01, z * 2 + 0.01);
973
972
  }
974
973
 
974
+ case ShapeType.RoundCuboid:
975
+ {
976
+ const {
977
+ x,
978
+ y,
979
+ z
980
+ } = collider.shape.halfExtents;
981
+ const radius = collider.shape.borderRadius;
982
+ return new RoundedBoxGeometry(x * 2 + radius * 2, y * 2 + radius * 2, z * 2 + radius * 2, 8, radius);
983
+ }
984
+
975
985
  case ShapeType.Ball:
976
986
  {
977
987
  const r = collider.shape.radius;
@@ -1007,7 +1017,38 @@ const geometryFromCollider = collider => {
1007
1017
  {
1008
1018
  const r = collider.shape.radius;
1009
1019
  const h = collider.shape.halfHeight;
1010
- const g = new CylinderBufferGeometry(r, r, h);
1020
+ const g = new CylinderBufferGeometry(r, r, h * 2);
1021
+ return g;
1022
+ }
1023
+
1024
+ case ShapeType.Capsule:
1025
+ {
1026
+ const r = collider.shape.radius;
1027
+ const h = collider.shape.halfHeight;
1028
+ const g = new CapsuleBufferGeometry(r, h * 2, 4, 8);
1029
+ return g;
1030
+ }
1031
+
1032
+ case ShapeType.Cone:
1033
+ {
1034
+ const r = collider.shape.radius;
1035
+ const h = collider.shape.halfHeight;
1036
+ const g = new ConeBufferGeometry(r, h * 2, 16);
1037
+ return g;
1038
+ }
1039
+
1040
+ case ShapeType.HeightField:
1041
+ {
1042
+ const rows = collider.shape.nrows;
1043
+ const cols = collider.shape.ncols;
1044
+ const heights = collider.shape.heights;
1045
+ const scale = collider.shape.scale;
1046
+ const g = new PlaneGeometry(scale.x, scale.z, cols, rows);
1047
+ const verts = g.attributes.position.array;
1048
+ verts.forEach((v, index) => verts[index * 3 + 2] = heights[index] * scale.y);
1049
+ g.scale(1, -1, 1);
1050
+ g.rotateX(-Math.PI / 2);
1051
+ g.rotateY(-Math.PI / 2);
1011
1052
  return g;
1012
1053
  }
1013
1054
  }
@@ -1016,12 +1057,18 @@ const geometryFromCollider = collider => {
1016
1057
  };
1017
1058
 
1018
1059
  const DebugShape = /*#__PURE__*/memo(({
1019
- colliderHandle
1060
+ colliderHandle,
1061
+ color,
1062
+ sleepColor
1020
1063
  }) => {
1021
1064
  const {
1022
1065
  world
1023
1066
  } = useRapier();
1024
1067
  const ref = useRef(null);
1068
+ const [material] = useState(new MeshBasicMaterial({
1069
+ color,
1070
+ wireframe: true
1071
+ }));
1025
1072
  useFrame(() => {
1026
1073
  const collider = world.getCollider(colliderHandle);
1027
1074
 
@@ -1037,6 +1084,14 @@ const DebugShape = /*#__PURE__*/memo(({
1037
1084
  y,
1038
1085
  z
1039
1086
  } = collider.translation();
1087
+ const parent = collider.parent();
1088
+
1089
+ if (parent !== null && parent !== void 0 && parent.isSleeping() || parent !== null && parent !== void 0 && parent.isFixed() || parent !== null && parent !== void 0 && parent.isKinematic()) {
1090
+ material.color = new Color(sleepColor);
1091
+ } else {
1092
+ material.color = new Color(color);
1093
+ }
1094
+
1040
1095
  ref.current.position.set(x, y, z);
1041
1096
  ref.current.rotation.setFromQuaternion(new Quaternion(rx, ry, rz, rw));
1042
1097
  }
@@ -1046,16 +1101,17 @@ const DebugShape = /*#__PURE__*/memo(({
1046
1101
  return geometryFromCollider(collider);
1047
1102
  }, [colliderHandle]);
1048
1103
  return /*#__PURE__*/React.createElement("mesh", {
1049
- ref: ref
1104
+ ref: ref,
1105
+ material: material
1050
1106
  }, /*#__PURE__*/React.createElement("primitive", {
1051
1107
  object: geometry,
1052
1108
  attach: "geometry"
1053
- }), /*#__PURE__*/React.createElement("meshBasicMaterial", {
1054
- color: "red",
1055
- wireframe: true
1056
1109
  }));
1057
1110
  });
1058
- const Debug = () => {
1111
+ const Debug = ({
1112
+ color: _color = "red",
1113
+ sleepColor: _sleepColor = "blue"
1114
+ }) => {
1059
1115
  const {
1060
1116
  world
1061
1117
  } = useRapier();
@@ -1071,7 +1127,9 @@ const Debug = () => {
1071
1127
  });
1072
1128
  return /*#__PURE__*/React.createElement("group", null, colliders.map(handle => /*#__PURE__*/React.createElement(DebugShape, {
1073
1129
  key: handle,
1074
- colliderHandle: handle
1130
+ colliderHandle: handle,
1131
+ color: _color,
1132
+ sleepColor: _sleepColor
1075
1133
  })));
1076
1134
  };
1077
1135
 
@@ -1199,24 +1257,6 @@ const InstancedRigidBodies = /*#__PURE__*/forwardRef((props, ref) => {
1199
1257
  }, props.children));
1200
1258
  });
1201
1259
 
1202
- function _extends() {
1203
- _extends = Object.assign || function (target) {
1204
- for (var i = 1; i < arguments.length; i++) {
1205
- var source = arguments[i];
1206
-
1207
- for (var key in source) {
1208
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1209
- target[key] = source[key];
1210
- }
1211
- }
1212
- }
1213
-
1214
- return target;
1215
- };
1216
-
1217
- return _extends.apply(this, arguments);
1218
- }
1219
-
1220
1260
  const _excluded = ["children"];
1221
1261
 
1222
1262
  const AnyCollider = _ref => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-three/rapier",
3
- "version": "0.6.5",
3
+ "version": "0.6.8",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/react-three-rapier.cjs.js",
6
6
  "module": "dist/react-three-rapier.esm.js",
@@ -20,7 +20,8 @@
20
20
  "peerDependencies": {
21
21
  "@react-three/fiber": "^8.0.12",
22
22
  "react": "^18.0.0",
23
- "three": "^0.139.2"
23
+ "three": "^0.139.2",
24
+ "three-stdlib": "^2.15.0"
24
25
  },
25
26
  "dependencies": {
26
27
  "@dimforge/rapier3d-compat": "0.9.0",
package/readme.md CHANGED
@@ -80,8 +80,8 @@ const Scene = () => (
80
80
  {/* Make a compound shape with two custom BallColliders */}
81
81
  <RigidBody position={[0, 10, 0]}>
82
82
  <Sphere />
83
- <BallCollider args={0.5} />
84
- <BallCollider args={0.5} position={[1, 0, 0]} />
83
+ <BallCollider args={[0.5]} />
84
+ <BallCollider args={[0.5]} position={[1, 0, 0]} />
85
85
  </RigidBody>
86
86
 
87
87
  {/* Make a compound shape with two custom BallColliders, an automatic BallCollider,
@@ -97,8 +97,8 @@ const Scene = () => (
97
97
 
98
98
  <Sphere />
99
99
 
100
- <BallCollider args={0.5} />
101
- <BallCollider args={0.5} position={[1, 0, 0]} />
100
+ <BallCollider args={[0.5]} />
101
+ <BallCollider args={[0.5]} position={[1, 0, 0]} />
102
102
  </RigidBody>
103
103
  </Physics>
104
104
  );
@@ -185,6 +185,9 @@ const Scene = () => {
185
185
 
186
186
  Use the Debug component to see live representations of all colliders in a scene.
187
187
 
188
+ - The `color` prop sets the color of awake colliders that are affected by forces.
189
+ - The `sleepColor` prop set the color of a static (fixed, or kinematic) or sleeping collider.
190
+
188
191
  > Note: Experimental. Not all shapes are supported. Unsupported shapes are always represented by cubes.
189
192
 
190
193
  ```tsx
@@ -194,7 +197,7 @@ import { RigidBody, Debug } from "@react-three/rapier";
194
197
  const Scene = () => {
195
198
  return (
196
199
  <Physics>
197
- <Debug />
200
+ <Debug color="red" sleepColor="blue" />
198
201
 
199
202
  <RigidBody>
200
203
  <Box />