@react-three/rapier 0.6.4 → 0.6.7

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>>;
@@ -19,6 +19,7 @@ export interface RapierContext {
19
19
  colliders: RigidBodyAutoCollider;
20
20
  };
21
21
  rigidBodyEvents: EventMap;
22
+ isPaused: boolean;
22
23
  }
23
24
  export declare const RapierContext: React.Context<RapierContext | undefined>;
24
25
  declare type EventMap = Map<ColliderHandle | RigidBodyHandle, {
@@ -51,14 +52,15 @@ interface RapierWorldProps {
51
52
  * Setting this to a number (eg. 1/60) will run the
52
53
  * simulation at that framerate.
53
54
  *
54
- * "vary" will run the simulation at a delta-value based
55
- * on the users current framerate. This ensures simulations
56
- * run at the same percieved speed at all framerates, but
57
- * can also lead to instability.
55
+ * @defaultValue 1/60
56
+ */
57
+ timeStep?: number;
58
+ /**
59
+ * Maximum number of fixed steps to take per function call.
58
60
  *
59
- * @defaultValue "vary"
61
+ * @defaultValue 10
60
62
  */
61
- timeStep?: number | "vary";
63
+ maxSubSteps?: number;
62
64
  /**
63
65
  * Pause the physics simulation
64
66
  *
@@ -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>>;
@@ -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 = ({
@@ -117,6 +122,10 @@ const createColliderFromOptions = ({
117
122
  w: qRotation.w
118
123
  }).setRestitution((_options$restitution = options === null || options === void 0 ? void 0 : options.restitution) !== null && _options$restitution !== void 0 ? _options$restitution : 0).setRestitutionCombineRule((_options$restitutionC = options === null || options === void 0 ? void 0 : options.restitutionCombineRule) !== null && _options$restitutionC !== void 0 ? _options$restitutionC : rapier3dCompat.CoefficientCombineRule.Average).setFriction((_options$friction = options === null || options === void 0 ? void 0 : options.friction) !== null && _options$friction !== void 0 ? _options$friction : 0.7).setFrictionCombineRule((_options$frictionComb = options === null || options === void 0 ? void 0 : options.frictionCombineRule) !== null && _options$frictionComb !== void 0 ? _options$frictionComb : rapier3dCompat.CoefficientCombineRule.Average);
119
124
 
125
+ if (colliderShape === "heightfield") {
126
+ console.log(colliderDesc);
127
+ }
128
+
120
129
  if (hasCollisionEvents) {
121
130
  colliderDesc = colliderDesc.setActiveEvents(rapier3dCompat.ActiveEvents.COLLISION_EVENTS);
122
131
  } // If any of the mass properties are specified, add mass properties
@@ -244,15 +253,15 @@ const colliderDescFromGeometry = (geometry, colliders, scale, hasCollisionEvents
244
253
  {
245
254
  var _g$index;
246
255
 
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);
256
+ const clonedGeometry = geometry.index ? geometry.clone() : BufferGeometryUtils.mergeVertices(geometry);
257
+ const g = clonedGeometry.scale(scale.x, scale.y, scale.z);
258
+ desc = rapier3dCompat.ColliderDesc.trimesh(g.attributes.position.array, (_g$index = g.index) === null || _g$index === void 0 ? void 0 : _g$index.array);
250
259
  }
251
260
  break;
252
261
 
253
262
  case "hull":
254
- const g = geometry.clone().scale(scale.x, scale.y, scale.z);
255
263
  {
264
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
256
265
  desc = rapier3dCompat.ColliderDesc.convexHull(g.attributes.position.array);
257
266
  }
258
267
  break;
@@ -469,10 +478,15 @@ const Physics = ({
469
478
  colliders: _colliders = "cuboid",
470
479
  gravity: _gravity = [0, -9.81, 0],
471
480
  children,
472
- timeStep: _timeStep = "vary",
481
+ timeStep: _timeStep = 1 / 60,
482
+ maxSubSteps: _maxSubSteps = 10,
473
483
  paused: _paused = false
474
484
  }) => {
475
485
  const rapier = useAsset.useAsset(importRapier);
486
+ const [isPaused, setIsPaused] = React.useState(_paused);
487
+ React.useEffect(() => {
488
+ setIsPaused(_paused);
489
+ }, [_paused]);
476
490
  const worldRef = React.useRef();
477
491
  const getWorldRef = React.useRef(() => {
478
492
  if (!worldRef.current) {
@@ -492,7 +506,6 @@ const Physics = ({
492
506
  return () => {
493
507
  if (world) {
494
508
  world.free();
495
- worldRef.current = undefined;
496
509
  }
497
510
  };
498
511
  }, []); // Update gravity
@@ -504,22 +517,46 @@ const Physics = ({
504
517
  world.gravity = vectorArrayToVector3(_gravity);
505
518
  }
506
519
  }, [_gravity]);
507
- const time = React.useRef(performance.now());
508
- fiber.useFrame(context => {
520
+ const [steppingState] = React.useState({
521
+ time: 0,
522
+ lastTime: 0,
523
+ accumulator: 0
524
+ });
525
+ fiber.useFrame((_, delta) => {
509
526
  const world = worldRef.current;
510
- if (!world) return; // Set timestep to current delta, to allow for variable frame rates
511
- // We cap the delta at 100, so that the physics simulation doesn't get wild
512
-
513
- const now = performance.now();
514
- const delta = Math.min(100, now - time.current);
515
-
516
- if (_timeStep === "vary") {
517
- world.timestep = delta / 1000;
518
- } else {
519
- world.timestep = _timeStep;
527
+ if (!world) return;
528
+ world.timestep = _timeStep;
529
+ /**
530
+ * Fixed timeStep simulation progression
531
+ * @see https://gafferongames.com/post/fix_your_timestep/
532
+ */
533
+
534
+ let previousTranslations = {}; // don't step time forwards if paused
535
+
536
+ const nowTime = steppingState.time += _paused ? 0 : delta * 1000;
537
+ const timeStepMs = _timeStep * 1000;
538
+ const timeSinceLast = nowTime - steppingState.lastTime;
539
+ steppingState.lastTime = nowTime;
540
+ steppingState.accumulator += timeSinceLast;
541
+
542
+ if (!_paused) {
543
+ let subSteps = 0;
544
+
545
+ while (steppingState.accumulator >= timeStepMs && subSteps < _maxSubSteps) {
546
+ // Collect previous state
547
+ world.bodies.forEach(b => {
548
+ previousTranslations[b.handle] = {
549
+ rotation: rapierQuaternionToQuaternion(b.rotation()).normalize(),
550
+ translation: rapierVector3ToVector3(b.translation())
551
+ };
552
+ });
553
+ world.step(eventQueue);
554
+ subSteps++;
555
+ steppingState.accumulator -= timeStepMs;
556
+ }
520
557
  }
521
558
 
522
- if (!_paused) world.step(eventQueue); // Update meshes
559
+ const interpolationAlpha = steppingState.accumulator % timeStepMs / timeStepMs; // Update meshes
523
560
 
524
561
  rigidBodyStates.forEach((state, handle) => {
525
562
  const rigidBody = world.getRigidBody(handle);
@@ -541,11 +578,16 @@ const Physics = ({
541
578
  state.isSleeping = rigidBody.isSleeping();
542
579
  }
543
580
 
544
- if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !state.setMatrix) {
581
+ if (!rigidBody || rigidBody.isSleeping() || !state.setMatrix) {
545
582
  return;
546
583
  }
547
584
 
548
- state.setMatrix(_matrix4.compose(rapierVector3ToVector3(rigidBody.translation()), rapierQuaternionToQuaternion(rigidBody.rotation()), state.worldScale).premultiply(state.invertedMatrixWorld));
585
+ let oldState = previousTranslations[rigidBody.handle];
586
+ let newTranslation = rapierVector3ToVector3(rigidBody.translation());
587
+ let newRotation = rapierQuaternionToQuaternion(rigidBody.rotation());
588
+ let interpolatedTranslation = oldState ? oldState.translation.lerp(newTranslation, 1) : newTranslation;
589
+ let interpolatedRotation = oldState ? oldState.rotation.slerp(newRotation, interpolationAlpha) : newRotation;
590
+ state.setMatrix(_matrix4.compose(interpolatedTranslation, interpolatedRotation, state.worldScale).premultiply(state.invertedMatrixWorld));
549
591
 
550
592
  if (state.mesh instanceof three.InstancedMesh) {
551
593
  state.mesh.instanceMatrix.needsUpdate = true;
@@ -595,7 +637,6 @@ const Physics = ({
595
637
  });
596
638
  }
597
639
  });
598
- time.current = now;
599
640
  });
600
641
  const api = React.useMemo(() => createWorldApi(getWorldRef), []);
601
642
  const context = React.useMemo(() => ({
@@ -607,13 +648,32 @@ const Physics = ({
607
648
  },
608
649
  colliderMeshes,
609
650
  rigidBodyStates,
610
- rigidBodyEvents
611
- }), []);
651
+ rigidBodyEvents,
652
+ isPaused
653
+ }), [isPaused]);
612
654
  return /*#__PURE__*/React__default["default"].createElement(RapierContext.Provider, {
613
655
  value: context
614
656
  }, children);
615
657
  };
616
658
 
659
+ function _extends() {
660
+ _extends = Object.assign || function (target) {
661
+ for (var i = 1; i < arguments.length; i++) {
662
+ var source = arguments[i];
663
+
664
+ for (var key in source) {
665
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
666
+ target[key] = source[key];
667
+ }
668
+ }
669
+ }
670
+
671
+ return target;
672
+ };
673
+
674
+ return _extends.apply(this, arguments);
675
+ }
676
+
617
677
  function _objectWithoutPropertiesLoose(source, excluded) {
618
678
  if (source == null) return {};
619
679
  var target = {};
@@ -880,7 +940,8 @@ const usePrismaticJoint = (body1, body2, [body1Anchor, body2Anchor, axis]) => {
880
940
  return useImpulseJoint(body1, body2, rapier.JointData.prismatic(vectorArrayToVector3(body1Anchor), vectorArrayToVector3(body2Anchor), vectorArrayToVector3(axis)));
881
941
  };
882
942
 
883
- const _excluded$1 = ["children"];
943
+ const _excluded$1 = ["children"],
944
+ _excluded2 = ["type", "position", "rotation"];
884
945
  const RigidBodyContext = /*#__PURE__*/React.createContext(undefined);
885
946
  const useRigidBodyContext = () => React.useContext(RigidBodyContext); // RigidBody
886
947
 
@@ -891,6 +952,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
891
952
  props = _objectWithoutProperties(_ref, _excluded$1);
892
953
 
893
954
  const [object, api] = useRigidBody(props);
955
+
956
+ const objectProps = _objectWithoutProperties(props, _excluded2);
957
+
894
958
  React.useImperativeHandle(ref, () => api);
895
959
  return /*#__PURE__*/React__default["default"].createElement(RigidBodyContext.Provider, {
896
960
  value: {
@@ -899,9 +963,9 @@ const RigidBody = /*#__PURE__*/React.forwardRef((_ref, ref) => {
899
963
  hasCollisionEvents: !!(props.onCollisionEnter || props.onCollisionExit),
900
964
  options: props
901
965
  }
902
- }, /*#__PURE__*/React__default["default"].createElement("object3D", {
966
+ }, /*#__PURE__*/React__default["default"].createElement("object3D", _extends({
903
967
  ref: object
904
- }, children));
968
+ }, objectProps), children));
905
969
  });
906
970
 
907
971
  const MeshCollider = ({
@@ -964,6 +1028,17 @@ const geometryFromCollider = collider => {
964
1028
  return new three.BoxBufferGeometry(x * 2 + 0.01, y * 2 + 0.01, z * 2 + 0.01);
965
1029
  }
966
1030
 
1031
+ case rapier3dCompat.ShapeType.RoundCuboid:
1032
+ {
1033
+ const {
1034
+ x,
1035
+ y,
1036
+ z
1037
+ } = collider.shape.halfExtents;
1038
+ const radius = collider.shape.borderRadius;
1039
+ return new threeStdlib.RoundedBoxGeometry(x * 2 + radius * 2, y * 2 + radius * 2, z * 2 + radius * 2, 8, radius);
1040
+ }
1041
+
967
1042
  case rapier3dCompat.ShapeType.Ball:
968
1043
  {
969
1044
  const r = collider.shape.radius;
@@ -999,7 +1074,38 @@ const geometryFromCollider = collider => {
999
1074
  {
1000
1075
  const r = collider.shape.radius;
1001
1076
  const h = collider.shape.halfHeight;
1002
- const g = new three.CylinderBufferGeometry(r, r, h);
1077
+ const g = new three.CylinderBufferGeometry(r, r, h * 2);
1078
+ return g;
1079
+ }
1080
+
1081
+ case rapier3dCompat.ShapeType.Capsule:
1082
+ {
1083
+ const r = collider.shape.radius;
1084
+ const h = collider.shape.halfHeight;
1085
+ const g = new three.CapsuleBufferGeometry(r, h * 2, 4, 8);
1086
+ return g;
1087
+ }
1088
+
1089
+ case rapier3dCompat.ShapeType.Cone:
1090
+ {
1091
+ const r = collider.shape.radius;
1092
+ const h = collider.shape.halfHeight;
1093
+ const g = new three.ConeBufferGeometry(r, h * 2, 16);
1094
+ return g;
1095
+ }
1096
+
1097
+ case rapier3dCompat.ShapeType.HeightField:
1098
+ {
1099
+ const rows = collider.shape.nrows;
1100
+ const cols = collider.shape.ncols;
1101
+ const heights = collider.shape.heights;
1102
+ const scale = collider.shape.scale;
1103
+ const g = new three.PlaneGeometry(scale.x, scale.z, cols, rows);
1104
+ const verts = g.attributes.position.array;
1105
+ verts.forEach((v, index) => verts[index * 3 + 2] = heights[index] * scale.y);
1106
+ g.scale(1, -1, 1);
1107
+ g.rotateX(-Math.PI / 2);
1108
+ g.rotateY(-Math.PI / 2);
1003
1109
  return g;
1004
1110
  }
1005
1111
  }
@@ -1008,12 +1114,18 @@ const geometryFromCollider = collider => {
1008
1114
  };
1009
1115
 
1010
1116
  const DebugShape = /*#__PURE__*/React.memo(({
1011
- colliderHandle
1117
+ colliderHandle,
1118
+ color,
1119
+ sleepColor
1012
1120
  }) => {
1013
1121
  const {
1014
1122
  world
1015
1123
  } = useRapier();
1016
1124
  const ref = React.useRef(null);
1125
+ const [material] = React.useState(new three.MeshBasicMaterial({
1126
+ color,
1127
+ wireframe: true
1128
+ }));
1017
1129
  fiber.useFrame(() => {
1018
1130
  const collider = world.getCollider(colliderHandle);
1019
1131
 
@@ -1029,6 +1141,14 @@ const DebugShape = /*#__PURE__*/React.memo(({
1029
1141
  y,
1030
1142
  z
1031
1143
  } = collider.translation();
1144
+ const parent = collider.parent();
1145
+
1146
+ if (parent !== null && parent !== void 0 && parent.isSleeping() || parent !== null && parent !== void 0 && parent.isFixed() || parent !== null && parent !== void 0 && parent.isKinematic()) {
1147
+ material.color = new three.Color(sleepColor);
1148
+ } else {
1149
+ material.color = new three.Color(color);
1150
+ }
1151
+
1032
1152
  ref.current.position.set(x, y, z);
1033
1153
  ref.current.rotation.setFromQuaternion(new three.Quaternion(rx, ry, rz, rw));
1034
1154
  }
@@ -1038,16 +1158,17 @@ const DebugShape = /*#__PURE__*/React.memo(({
1038
1158
  return geometryFromCollider(collider);
1039
1159
  }, [colliderHandle]);
1040
1160
  return /*#__PURE__*/React__default["default"].createElement("mesh", {
1041
- ref: ref
1161
+ ref: ref,
1162
+ material: material
1042
1163
  }, /*#__PURE__*/React__default["default"].createElement("primitive", {
1043
1164
  object: geometry,
1044
1165
  attach: "geometry"
1045
- }), /*#__PURE__*/React__default["default"].createElement("meshBasicMaterial", {
1046
- color: "red",
1047
- wireframe: true
1048
1166
  }));
1049
1167
  });
1050
- const Debug = () => {
1168
+ const Debug = ({
1169
+ color: _color = "red",
1170
+ sleepColor: _sleepColor = "blue"
1171
+ }) => {
1051
1172
  const {
1052
1173
  world
1053
1174
  } = useRapier();
@@ -1063,7 +1184,9 @@ const Debug = () => {
1063
1184
  });
1064
1185
  return /*#__PURE__*/React__default["default"].createElement("group", null, colliders.map(handle => /*#__PURE__*/React__default["default"].createElement(DebugShape, {
1065
1186
  key: handle,
1066
- colliderHandle: handle
1187
+ colliderHandle: handle,
1188
+ color: _color,
1189
+ sleepColor: _sleepColor
1067
1190
  })));
1068
1191
  };
1069
1192
 
@@ -1191,24 +1314,6 @@ const InstancedRigidBodies = /*#__PURE__*/React.forwardRef((props, ref) => {
1191
1314
  }, props.children));
1192
1315
  });
1193
1316
 
1194
- function _extends() {
1195
- _extends = Object.assign || function (target) {
1196
- for (var i = 1; i < arguments.length; i++) {
1197
- var source = arguments[i];
1198
-
1199
- for (var key in source) {
1200
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1201
- target[key] = source[key];
1202
- }
1203
- }
1204
- }
1205
-
1206
- return target;
1207
- };
1208
-
1209
- return _extends.apply(this, arguments);
1210
- }
1211
-
1212
1317
  const _excluded = ["children"];
1213
1318
 
1214
1319
  const AnyCollider = _ref => {