Giter Site home page Giter Site logo

react-three-rapier's People

Contributors

0xtito avatar alexandernanberg avatar balraj-johal avatar bvkimball avatar codyjasonbennett avatar console-buche avatar davcri avatar dependabot[bot] avatar drcmda avatar edwinwebb avatar firtoz avatar github-actions[bot] avatar glavin001 avatar hmans avatar isaac-mason avatar lakshjaisinghani avatar machado2 avatar micmania1 avatar planktonrobo avatar rodrigohamuy avatar roombawulf avatar vegancat avatar vynetic avatar wiledal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-three-rapier's Issues

Gravity change with state

Hello, here's the first of a few issue I found when converting an experiment from cannon to rapier, as asked!

Doesn’t look like I can change the gravity mid render with state. I have a boolean called switchModeOn that alternates on a timer, worked great in cannon to reverse the gravity on the fly!

/src/BoxFan/index.js line 81, switchModeOn should be flipping the gravity.
https://codesandbox.io/s/rapier-physics-box-fan-experiment-debug-gravity-kh45y3?file=/src/BoxFan/index.js

Support for Rapier 2D

It would be nice to have an option to use Rapider 2D instead of 3D for applications that only need 2D physics, even if they use 3D graphics (think RTS, MOBA games, or 2D platformers with 3D graphics...). The WASM file is 1MB instead of 1.4MB. I suppose <Physics> would need some props to configure the axes to use, and to project onto.

issue with generating colliders

Hello
I'm using CuboidCollider for generating a limitless flat plane
problem is visible in image below

image

first three block on left have collider and other three on right have no any collider
code for each of them is same and don't now why it's ignoring that part
and when I refresh the page
it keeps ignoring that three!
I'll attach the Code here too
<RigidBody colliders={false} type="fixed"> <Center position-y={-2}> <mesh material={props.material} receiveShadow scale={[props.scale, 4, props.scale]} > <boxGeometry /> </mesh> </Center> <CuboidCollider args={[1, 1, 1]} scale={[props.scale / 2, 2, props.scale / 2]} position={[0, -2, 0]} /> </RigidBody>

is there any way to solve this issue?
Thank you

Wasm build

Following the discussion on #113 :

It would be nice to have the option to use the rapier3d Wasm build instead of the rapier3d-compat build.

Size on disk as of 0.9.0:
rapier3d (Wasm): 1.4MB
rapier3d-compat (JS): 1.9MB

Why object inside a rigid bodies shaking when applying linear velocity?

shaking
So here is an example, can someone explain to me why this is happening and how can I prevent this?
This is a next js version 13 project and I'm using react three fiber version ^8.9.1 and react three rapier ^0.10.0.
here is the code where I move my rigid body:

code
and here is my scene:

scene

Will Rapier run in a WebWorker?

Searching through this code and Rapier docs I was unable to determine if this package would run Rapier in a separate thread/WebWorker, like use-cannon does automatically.

Will there be support on Next.js in the future?

Tried to import anything from rapier, ocurrs error:

Error: Cannot find module '/repo/node_modules/three/examples/jsm/utils/BufferGeometryUtils'

I thinks rapier was trying to get example stuff from three which npm three don't have, hence the error.

Can I tricks rapier to get examples from three-stdlib?

I was running in the latest Next.js, r3f and three.

Side effects in useMemo

First I just want to say great work with this!

I was reading through the code and noticed that you're calling world.createRigidBody inside useMemo which breaks some React rules since world.createRigidBody has side effects. useMemo isn't the best choice for this anyway because React can decide to throw away the value at any time and recompute it.

const rigidBody = useMemo(() => {
const [lvx, lvy, lvz] = options?.linearVelocity ?? [0, 0, 0];
const [avx, avy, avz] = options?.angularVelocity ?? [0, 0, 0];
const gravityScale = options?.gravityScale ?? 1;
const canSleep = options?.canSleep ?? true;
const ccdEnabled = options?.ccd ?? false;
const type = rigidBodyTypeFromString(options?.type || "dynamic");
const [x, y, z] = options?.position || [0, 0, 0];
const [rx, ry, rz] = options?.rotation || [0, 0, 0];
const rigidBodyDesc = new RAPIER.RigidBodyDesc(type)
.setLinvel(lvx, lvy, lvz)
.setAngvel({ x: avx, y: avy, z: avz })
.setGravityScale(gravityScale)
.setCanSleep(canSleep)
.setCcdEnabled(ccdEnabled)
.setTranslation(0,0,0)
const body = world.createRigidBody(rigidBodyDesc);
return body;
}, []);

In my own integration I ended up using a getter which as far as I can tell should be React 18+ safe. The approach is described in the bottom of reactwg/react-18#18

https://github.com/alexandernanberg/playground/blob/973c512aa192a6500a503a15aea6d6dd1b83d2be/src/components/physics.tsx#L265-L272

Types: RigidBody and Collider should accept Vector3 positions

<RigidBody> and the collider components accept position props that are currently typed to [number, number, number]. They also work fine with Vector3 instances (which is great!), but this is currently not reflected in the types:

image

(new Vector3() instances in the screenshot are purely for demonstration purposes. 🤡 )

`RigidBodyProps` is not exported, and incorrect

As Is:

  1. RigidBodyProps is not exported from the package

  2. When used, it still makes TypeScript throw an error where it shouldn't:

image

To Be:

The type should be exported from the library, and it should not cause TypeScript warnings.

Why is this important:

The user might want to encapsulate a RigidBody in a component (like I did in the screenshot), but make it possible for the users of this component to specify the initial position and/or rotation of the body (or override other props.)

If a parent object has non-uniform scale, rigid bodies behave strangely

When you have a parent group object that has a non-uniform scale, rigid bodies appear wonky.

For example:

<Canvas>
  <OrbitControls/>

  <React.Suspense>
    <Physics>
      <Debug/>
      <group scale={[2, 0.2, 0.2]}>
        <RigidBody restitution={1} colliders={false}>
          <CuboidCollider
            args={[1, 1, 1]}
          />
          <Box args={[2, 2, 2]}>
            <meshBasicMaterial color={'green'}/>
          </Box>
        </RigidBody>
      </group>
      
      <RigidBody position={[0, -2.5, 0]} type="kinematicPosition">
        <Box args={[20, 0.5, 20]}/>
      </RigidBody>
      <RigidBody position={[1, -2, 0]} type="kinematicPosition">
        <Box args={[1, 0.5, 1]}/>
      </RigidBody>
    </Physics>
  </React.Suspense>
</Canvas>

It looks like this:

Mozilla.Firefox.-.27.October.2022.mp4

However, if we put the scaling operation inside of the rigid body, it seems to work well:

<Canvas>
  <OrbitControls/>

  <React.Suspense>
    <Physics>
      <Debug/>
      <group>
        <RigidBody restitution={1} colliders={false}>
          <group scale={[2, 0.2, 0.2]}>
            <CuboidCollider
              args={[1, 1, 1]}
            />
            <Box args={[2, 2, 2]}>
              <meshBasicMaterial color={'green'}/>
            </Box>
          </group>
        </RigidBody>
      </group>
      
      <RigidBody position={[0, -2.5, 0]} type="kinematicPosition">
        <Box args={[20, 0.5, 20]}/>
      </RigidBody>
      <RigidBody position={[1, -2, 0]} type="kinematicPosition">
        <Box args={[1, 0.5, 1]}/>
      </RigidBody>
    </Physics>
  </React.Suspense>
</Canvas>
Mozilla.Firefox.-.27.October.2022.1.mp4

The issue with this one is that I'm working on a game engine, and we receive the game object's transform through matrices. So to use this workaround, I need to decompose the matrix to translation rotation scale, apply translation and rotation to the parent group, then apply the scale to the child, which is quite complicated and would be best to be prevented. Also, I can totally see others running into this issue if they have scaling of the ancestors of the rigid body.

For me, if a greater ancestor has the scaling (which is possible) it'd be even harder to resolve, if the issue happens there too.

World simulation unexpectedly speeds up

When I leave a project that uses react-three/rapier running in a background tab for a couple of minutes and then return to it, the speed at which the physics simulation runs is significantly increased for a little while, as if the fixed step look is trying to catch up on missed frames.

Generate JSDoc!

The readme is getting too thicc. Let's generate a JSDoc from the source!

  • Find a suitable way to do so
  • Choose a theme
  • Ensure source is sufficiently covered in TSDoc comments

[Question] Is there a way to put physic on pause?

I'm currently working on a game engine with React-Three-Fiber and I'm now looking for the best physic engine possible and this one looks great!

I would like to know if there is a way to put the physic on pause (just like use-cannon) which I was not able to find in the documentation.

Thanks!

a way to prevent children inside rigidbodies to be treated as colliders

currently everything inside a <RigidBody> is being interpreted as a collider, useRigidBody will call:

const autoColliders = colliderSetting !== false ? createCollidersFromChildren(ref.current, rigidBody, {...options, colliders: colliderSetting}, world) : []

which then calls

  object.traverse((child: Object3D | Mesh) => {
    if ("isMesh" in child) {
      ...

the problem is that this makes it hard to add ornamentals to objects, things that are supposed to be grouped with the main physics object so that they may move along, but that should not create a physics shape.

the only workaround i have found is this:

<RigidBody ...>
  <mesh>
    <sphereGeometry />
  </mesh>     
  <mesh traverse={() => null}>
    ...

the second mesh would move with the main object, but tricks rapier so that it skips auto shape. imo this is a super common case and something should probably be introduced to make this more comfortable:

<RigidBody ...>
  <mesh />
  <mesh skip /> // ?
  <mesh userData={{ rapier: { skip: true } }} /> // ?

Is Rigidbody supposed to be compatible with the TransformControls of Threejs

Maybe related to this issue #53, but I wanted to know if the Rigidbody component is supposed to be compatible with the ThreeJS TransformControls.

I'm building a game engine and react-three-rapier seems to be the best physic engine for it, but the thing is when I want to drag an item that has physic with my TransformControls implementation it seems buggy.

I tried on a vanilla react-three-fiber and it seems to be buggy as well.

Here is my dirt codesandbox that represents the issue.
https://codesandbox.io/p/github/fgarrec0397/rapier-issue/draft/nostalgic-sammet?file=%2Fsrc%2FApp.tsx

Just drag the cube and you will see what I'm talking about.

Thanks a lot!

Add support for declaratively setting RigidBody userData

I ran into a case where I wanted to add user data to a rigid body in order to read it when raycasting. I can do this now with a ref and the raw api, but it would be nice to be able to set rapier user data on <RigidBody /> declaratively.

I have noted that the RigidBody component and Collider components already have a userData prop for body/collider Object3Ds.


Here are some approaches I've thought of:

Option 1: add a rapierUserData prop for the RigidBody userData

Fairly self-explanatory. One con is if you want some user data on both the Object3D + the rigid body, two props are needed.

Option 2: use the userData prop as both the three Object3D userData and the rapier RigidBody userData

Both three.js Object3D userData and rapier RigidBody userData are just arbitrary objects. We could set both of these to the one userData prop. There could be some potential footguns though around expectations of Object3D userData and RigidBody userData always being equal.


Option 1 would be my preference for its simplicity, but keen to get thoughts. I'm happy to do the implementation too 🙂

RigidBody scaling does not apply to collider scaling

Version: 0.7.1

When I have a RigidBody like this (note the scale prop), I would expect the contained colliders to also scale accordingly:

<RigidBody scale={2}>
  <ConvexHullCollider
    density={3}
    args={[points]} />
</RigidBody>

Colliders appear to respect scaled transforms inside the RigidBody, though, so I can currently sort-of (*) work around this like this:

<RigidBody>
  <group scale={2}>
    <ConvexHullCollider
      density={3}
      args={[points]} />
  </group>
</RigidBody>

However, this has two problems:

  • It's a little confusing because the RigidBody specifically accepts scene object props like position and scale, suggesting that all its contents will be scaled accordingly (which works fine for Three.js scene objects, but not the colliders)
  • In my project, I disable matrixAutoUpdate in some situations for some performance tweaks, but if I do it on the group here, the scale will not be picked up at all. (Speaking of which: the scene objects created by rigidbodies should have their auto matrix calculations disabled, and only performed explicitly for non-sleeping bodies.)

<Physics> doesn't let the user configure the priority for its `useFrame`

As Is:

<Physics> runs its per-frame update look through useFrame, but doesn't let the user specify the priority (useFrame's second argument.)

To Be:

<Physics> should gain a updatePriority prop that lets the user specify the update priority.

Why is this important:

With no way to configure the update priority, useFrame will use a priority if 0. Depending on the project, this can quickly be the wrong update priority. Games in particular will want to update the physics inbetween input and other processing and need immediate control over this.

Issue with Next.js and three MathUtils

I'm using the React-Three-Next starter and just wrap my scene in Index.js with Rapier Physics.

Page.r3f = (props) => (
  <>
    <Suspense>
      <Physics>
        
      </Physics>
    </Suspense>
  </>
)

But it show this error: Cannot find module '...\node_modules\three\src\math\MathUtils'.
I saw the error like this in #88, Is this a bug or I'm just doing something wrong.

Add support for contact force events

Documentation

Use Case

When two objects collide, I want to play a sound at the volume appropriate for the collision. eg. softer collisions should be quieter.

Solution

I was expecting to be able to do this from the onCollisionEnter event but it looks like rapier separates colission events and contact force events. With that in mind, would the solution be to add the onContactForce prop to colliders and rigid body's and apply it in the same way other events are within Physics?

I'm happy to add this in, just thought I'd check on the apprach first.

Lock rotation or lock translation are not working

I tried using lock rotation but it didn't work. I tried enabledRotations prop too but it didn't work either. Am I missing something or is this a bug? Oh and this also applies to lock translation and enabledTranslations too

Crash when creating a trimesh collider with non-indexed geometry

It happened using it together with @react-three/csg that creates non-indexed geometries. I'm making a pull request to show how I solved it for me.

Code to reproduce it, also on stackblitz here: https://react-ts-kfoy98.stackblitz.io

import {
  Debug,
  Physics,
  RigidBody,
  InstancedRigidBodies,
  InstancedRigidBodyApi,
  CuboidCollider,
} from '@react-three/rapier';
import { Subtraction, Brush } from '@react-three/csg';
import { Canvas, useFrame } from '@react-three/fiber';
import * as React from 'react';
import './style.css';

function HollowSphere() {
  return (
    <mesh>
      <Subtraction>
        <Brush a>
          <sphereGeometry args={[2]} />
        </Brush>
        <Brush b>
          <sphereGeometry args={[1]} />
        </Brush>
      </Subtraction>
      <meshPhysicalMaterial transmission="0.9" ior="0.97" />
    </mesh>
  );
}

export default function App() {
  return (
    <Canvas>
      <Physics>
        <RigidBody colliders="trimesh">
          <HollowSphere />
        </RigidBody>
        <RigidBody>
          <mesh>
            <sphereGeometry args={[0.4]} />
            <meshBasicMaterial color="green" />
          </mesh>
        </RigidBody>
      </Physics>
      <ambientLight />
      <pointLight position={[10, 10, 10]} />
    </Canvas>
  );
}

Best way to Lock Rotations?

Heya,

Awesome job on this lib so far, really exciting stuff

Was playing around and wanted to lock an objects rotation, found this seemed to work:
<RigidBody ref={api=>api.raw().lockRotations(true)}>

Is that the best way to do this currently? Was thinking something like this would be more ergonomic but unsure of feasibility / implications:

<RigidBody lockRotations={true}>

Expose world API / rapier context to users

Currently there's no way to set a ref for the Physics component. I would expect to be able to pull and manipulate the world ref with
const {world} = useContext(RapierContext);

Can't configure collision masks and groups for colliders, and active collision types

As Is:

There doesn't seem to be a way to configure collision masks and groups for colliders, or their active collision types.

To Be:

There needs to be a way to configure collision masks and groups for colliders, and active collision types. These are just bitmasks (expressed as numbers), so ideally there should be a supplementary API for creating them without requiring the user to do the math. (In an earlier project, I had a collisions(group, mask) helper that would return the correct numerical value.

Further reading:

Why is this important:

Games need to control exactly which bodies (colliders) are supposed to collide with what other bodies (colliders), and which of them generate collision events.

`.translation()` does not return the world position systematically

I'm facing an odd behaviour to me:

Description

✅ OK Case 1: position on <RigidBody>

<RigidBody ref={bodyRef} colliders="ball"
  position={[3, 3, 3]} // 👈🏻 `position` on RigidBody
>
  <mesh> 
    <icosahedronGeometry />
    <meshStandardMaterial />
  </mesh>
</RigidBody>
useEffect(() => {
  console.log("translation=", bodyRef.current?.translation());
}, []);

outputs: translation= Vector3 {x: 3, y: 3, z: 3}

image

https://codesandbox.io/s/heuristic-ramanujan-emrms9?file=/src/App.tsx:529-549

❌ NOK Case 2: position on <mesh>

<RigidBody ref={bodyRef} colliders="ball">
  <mesh
    position={[3, 3, 3]} // 👈🏻 `position` on mesh
  >
    <icosahedronGeometry />
    <meshStandardMaterial />
  </mesh>
</RigidBody>
useEffect(() => {
  console.log("translation=", bodyRef.current?.translation());
}, []);

outputs: translation= Vector3 {x: 0, y: 0, z: 0}

image

https://codesandbox.io/s/quirky-microservice-ki7gr7?file=/src/App.tsx:553-573

Expected

The expected behaviour to me, should be .translation() always return 3,3,3 ie. the real, absolute, only one world position of the object

How to synchronize the positions of physical objects with the store?

I use zustand as a store provider.
I process every position change through callbacks

            const threeObject = scene.getObjectByName(selectedObject.id);
            if (threeObject)
              moveObject(
                selectedObject,
                new V3(
                  threeObject.position.x,
                  threeObject.position.y,
                  threeObject.position.z
                )
              );
  • TransformPanel - onChange
    image
       moveObject(
              selectedObject,
              new V3(v, selectedObject.position.y, selectedObject.position.z)
            );

How can I handle position changes of physical bodies?

P.S.

  moveObject: (gameObject, position) => changeObject(gameObject, { position })
const changeObject = (gameObject: GameObject, props: Partial<GameObject>) => {
useSceneStore.setState((old) => {
  const copy = [...old.objects];
  const index = copy.findIndex(({ id }) => id === gameObject.id);
  copy[index] = { ...gameObject, ...props };
  return { objects: copy };
});
if (useSceneStore.getState().selectedObject?.id === gameObject.id)
  useSceneStore.getState().selectObject({ ...gameObject, ...props });
};

TypeError: Cannot destructure property 'rapier' of 'useRapier(...)' as it is undefined.

Thanks for the great initiative. I just installed the package and I am trying to get it working on a GLTF like so:

    import { RigidBody } from "@react-three/rapier";
    
    <RigidBody colliders={"hull"} restitution={2}>
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.perimeter_extrude.geometry}
        material={materials["Material.088"]}
        position={[1180.06, 0, 479.2]}
      />
    </RigidBody>

But getting:

Screen Shot 2022-07-20 at 2 18 22 PM

can someone point me in the right direction please?

thanks!

How to rotate the wheels on the y axis? (useRevoluteJoint)

https://github.com/pmndrs/react-three-rapier/blob/main/demo/src/examples/car/CarExample.tsx
The current example only shows how to move the car forward and backward

I tried to just turn the wheel a few degrees in the right direction, but got a very strange result

2023-01-20.20-30-27.mp4

Code, Car.tsx:

/* eslint-disable react/no-unknown-property */
import { Cylinder } from "@react-three/drei";
import { GroupProps, useFrame } from "@react-three/fiber";
import {
  RigidBody,
  RigidBodyApi,
  RigidBodyApiRef,
  useRevoluteJoint,
  Vector3Array,
} from "@react-three/rapier";
import { createRef, useEffect, useRef, useState } from "react";
import { Euler, Quaternion } from "three";
import { degToRad } from "three/src/math/MathUtils";

import chasisModel from "./chasis.glb";
import { GLBModel } from "./glb-model";
// import wheelModel from "./wheel.glb"; // not working currently

const WheelJoint = ({
  body,
  wheel,
  bodyAnchor,
  wheelAnchor,
  rotationAxis,
}: {
  body: RigidBodyApiRef;
  wheel: RigidBodyApiRef;
  bodyAnchor: Vector3Array;
  wheelAnchor: Vector3Array;
  rotationAxis: Vector3Array;
}) => {
  useRevoluteJoint(body, wheel, [bodyAnchor, wheelAnchor, rotationAxis]);
  return null;
};

const useControls = () => {
  const [controls, setControls] = useState({
    KeyW: false,
    KeyA: false,
    KeyS: false,
    KeyD: false,
  });

  useEffect(() => {
    const listener = (e: KeyboardEvent) => {
      if (e.repeat) return;
      setControls((old) => ({ ...old, [e.code]: true }));
    };
    document.addEventListener("keydown", listener);
    return () => document.removeEventListener("keydown", listener);
  }, []);

  useEffect(() => {
    const listener = (e: KeyboardEvent) => {
      if (e.repeat) return;
      setControls((old) => ({ ...old, [e.code]: false }));
    };
    document.addEventListener("keyup", listener);
    return () => document.removeEventListener("keyup", listener);
  }, []);

  return controls;
};

export const Car = (props: GroupProps) => {
  const controls = useControls();

  // not working(
  // const wheelPositions: [number, number, number][] = [
  //   [0, -0.5, 0],
  //   [0, -0.5, 0.8],
  //   [-1.2, -0.5, 0],
  //   [-1.2, -0.5, 0.8],
  // ];
  const wheelPositions: [number, number, number][] = [
    [-0.7, 0, 0.7],
    [-0.7, 0, -0.7],
    [0.5, 0, 0.7],
    [0.5, 0, -0.7],
  ];
  const bodyRef = useRef<RigidBodyApi | null>(null);
  const wheelRefs = useRef(wheelPositions.map(() => createRef<RigidBodyApi>()));

  useFrame(() => {
    const speed = controls.KeyW ? 1 : controls.KeyS ? -1 : 0;
    const rotation = controls.KeyA ? 1 : controls.KeyD ? -1 : 0;

    for (const wheel of wheelRefs.current) {
      wheel.current?.applyTorqueImpulse({ x: 0, y: 0, z: speed * 1.5 });
      wheel.current?.setRotation(
        new Quaternion().setFromEuler(new Euler(0, degToRad(rotation * 45), 0))
      );
    }
  });

  return (
    <group {...props}>
      <RigidBody
        angularDamping={1}
        linearDamping={1}
        ref={bodyRef}
        colliders="hull"
        mass={10}
        enabledRotations={[false, false, false]}
      >
        <group
          position={[0, -0.5, 0]}
          rotation={[-1 * (1 / 2) * Math.PI, 0, Math.PI]}
        >
          <GLBModel src={chasisModel} />
        </group>
      </RigidBody>
      {wheelPositions.map((wheelPosition, i) => (
        <>
          <WheelJoint
            key={`wheel-joint-${i}`}
            body={bodyRef}
            wheel={wheelRefs.current[i]}
            bodyAnchor={wheelPosition}
            wheelAnchor={[0, 0, 0]}
            rotationAxis={[0, 0, 1]}
          />
          <RigidBody
            mass={20}
            position={wheelPosition}
            ref={wheelRefs.current[i]}
            colliders="hull"
            key={`wheel-rigidbody-${i}`}
          >
            <Cylinder
              rotation={[Math.PI / 2, 0, 0]}
              args={[0.25, 0.25, 0.2, 32]}
              castShadow
              receiveShadow
            >
              <meshPhysicalMaterial />
            </Cylinder>
            {/* 
            not working, messy movement
            <group rotation={[-Math.PI / 2, 0, 0]}>
              <GLBModel src={wheelModel} />
            </group> */}
          </RigidBody>
        </>
      ))}
    </group>
  );
};

Add support for pre-step and post-step logic

Hi!

Looking for thoughts on adding pre-step and post-step events.

Use cases for this include creating custom character and vehicle controllers, where forces should only be applied once per physics step. When not using timestep="vary", applying forces on each frame isn't desirable, as not every frame will step the physics world, some will just interpolate.

This could come in the form of hooks, e.g.

import { usePreStep, usePostStep } from "@react-three/rapier"

usePreStep(() => { /* called before stepping the world */ })
usePostStep(() => { /* called after stepping the world */ })

Or via signals/event handlers on the wrapped rapier World, e.g.

world.onPreStep.add(() => { /* called before stepping the world */ })
world.onPostStep.add(() => { /* called after stepping the world */ })

Or maybe a combination of both.

Keen to hear thoughts, and as usual, happy to help implement 🙂

Meshes are not syncing properly with physics objects in latest version

Hello! I ran yarn upgrade on @react-three/rapier today and noticed that it was behaving quite oddly - I made some videos of it on version 0.6.3 (old) and the latest version (new). You can see that the meshes are desyncing from the physics bounds and wobbling around for some reason:

https://www.dropbox.com/scl/fo/99bg75xu9k2o5a08ma8ec/h?dl=0&rlkey=723r3a69flycizmy6oih2w3gh

Assuming it's from here, maybe?
e71ea11#diff-c7ceb0f2f5cdf0d343ec1c8dc97e80c669fa7e755c722586b60caa26b38a8ff6L219

I would make a PR but there seems to be a lot going on in that commit, ...if I get time later I might try to give it a shot :)

Thanks!

rt-rapier breaks with StrictMode enabled

I recently learned that the default <StrictMode> setup that the typical CRA and Vite templates enable by default does not automatically extend into an R3F canvas, and that you need to explicitly create a <StrictMode> node inside <Canvas> to use it. I am now going through all of my own libraries as well as some others that I'm using (like this one) to find out how badly they break with strict mode enabled, and @react-three/rapier unfortunately is one of the things that do break.

To reproduce, just wrap everything inside the <Canvas> in the demo app in a <StrictMode> node.

image

How to use Motors

From rapier docs, the motor is accessible from the joint creation.

let joint = world.createImpulseJoint(params, body1, body2);
(joint as RAPIER.PrismaticJoint).configureMotorVelocity(1.0, 0.5);

But the useImpulseJoint hook doesn't expose it.

export const useImpulseJoint = <T extends ImpulseJoint>(
body1: MutableRefObject<RapierRigidBody | undefined | null>,
body2: MutableRefObject<RapierRigidBody | undefined | null>,
params: Rapier.JointData
) => {
const { world, RAPIER } = useRapier();
useLayoutEffect(() => {
let joint: T;
if (body1 && body2 && params) {
joint = world.createImpulseJoint(
params,
body1.current!,
body2.current!
) as T;
}
return () => {
if (joint) world.removeImpulseJoint(joint, true);
};
}, [body1, body2]);
};

Question

How to use Motors? Is there another way?
Are there plans to expose the joint from the hooks?

I'd expect something like this:

const joint = useRevoluteJoint(...)

<Box onClick={() => { joint.configureMotorVelocity(1.0, 0.5); }} />

I'd be glad to contribute with a PR.

Tracking: Game-readiness of @react-three/rapier

I'm using this ticket as a high-level overview of things that are still missing for the library to be "game-ready". Please ready this merely as a tracking issue, not a wishlist. :-) I will be implementing some of these myself, and submitting them via PR. Also please consider this a living document, I will probably add a thing or two to this list over time.

Must Have:

  • Make update priority configurable. (#78)
  • Clamp deltatime values to 1s max. (#85)
  • Either provide interpolation for translation (currently disabled), or allow the user to configure a varying time step. (Currently, using a lerping follow camera immediately makes the non-interpolated "jumpy" nature of rigidbody movements very obvious.)
  • Allow the user to use sensors. (#90?)
  • Allow setting of restrictRotations and restrictTranslations on rigidbodies. (see rapier docs) This is now enabledRotations and enabledTranslations, and it's already in, yay!

Should Have:

  • Allow for per-collider collision callbacks. (#83)
  • Easy convex collider generation from any geometry, including loaded GLTFs.
  • Allow the user to specify the density of colliders (or a default value on RigidBody.) (Rapier is nice in that it will automatically calculate the mass from the density and the volume of the colliders.)
  • Allow the user to access a rigidbody's scene object through the ref/API. (RigidBodies wrap their children in an <object3D> scene object, but don't expose them through their API. Systems that need to interact with the scene object currently only have the option of establishing their own wrapper object and storing the ref to that separately.)
  • The RigidBodyApi should not force bodies that it interacts with to wake up. This decision should be left to the user (but it would be fine to default this to true.) (#125)
  • The scene object created by RigidBodies and Colliders should default to matrixAutoUpdate={false}, and have their matrices updated explicitly (or this attribute toggled) when the owning rigidbody is awake (ie. not sleeping).
    • Sleeping bodies will never move, so disabling their automatic matrix recalculations is a good optimizations for scenes with larger amounts of rigid bodies (a large portion of which might be sleeping.)
    • It'd be okay to make this optimization opt-in

Nice to Have:

  • Easy to use physics debugger
  • #113

Debug shows detailed/trimesh geometry instead of hull colliders

Example Code

<Physics>
  <Debug />
  <RigidBody
    colliders={"hull"}
    position={[0, 0, 0]}
  >
    <MiteModel />
  </RigidBody>
</Physics>

Output

See a close fitting detailed/trimesh geometry:

image

Expected

  • I would expect to see a convex hull wrapping the outside of the shape (see below)
  • When other bodies collide with this rigid hull collider body it acts like a hull, not a detailed/trimesh shape.

image


When I have more time I'll whip up a Codesandbox demo.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.