Skip to content

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

Description

@fax1ty

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>
  );
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions