I tried to just turn the wheel a few degrees in the right direction, but got a very strange result
/* 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>
);
};
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: