Three.js and React three fiber newbie here. I'm attempting to get ray casting to work correctly using Raycaster from three. I’ve got 2 simple mesh boxes, one static and other movable via keyboard events. Goal is to console log the static mesh when movable mesh intersects it via ray cast helper function. But intersection is not getting detected. Any help would be most appreciated.
Here are the components:
App.js
import { Canvas } from "@react-three/fiber";
import { OrbitControls, Plane } from "@react-three/drei";
import MovingBox from "./MovingBox";
export default function App() {
return (
<>
<Canvas camera={{ position: [0, 7.5, -15], fov: 50 }}>
<ambientLight intensity={0.5} />
<directionalLight
intensity={1}
position={[4, 20, 0]}
color={0xffffff}
/>
<Plane
receiveShadow
rotation={[-Math.PI / 2, 0, Math.PI]}
position={[0, 0, 0]}
args={[200, 200]}
>
<meshStandardMaterial attach="material" color="green" />
</Plane>
<MovingBox />
<mesh scale={[5, 5, 5]} position={[-10, 1, 0]} name="CollisionBox">
<boxGeometry />
<meshStandardMaterial color="hotpink" />
</mesh>
<OrbitControls />
</Canvas>
</>
);
}
MovingBox.js
import { useRef, useMemo } from "react";
import { useHelper } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useKeyboardControls } from "./useKeyboardControls";
import { Vector3, Raycaster, BoxHelper } from "three";
const useForwardRaycast = (obj, collisionItem) => {
// console.log("obj", obj);
// console.log("collisionItem", collisionItem);
const scene = useThree((state) => state.scene);
const raycaster = useMemo(() => new Raycaster(), []);
const pos = useMemo(() => new Vector3(), []);
const dir = useMemo(() => new Vector3(), []);
return () => {
if (!obj.current) return [];
raycaster.set(
obj.current.getWorldPosition(pos),
obj.current.getWorldDirection(dir)
);
return raycaster.intersectObjects(scene);
};
};
const MovingBox = () => {
const boxRef = useRef();
const controls = useKeyboardControls();
const scene = useThree((state) => state.scene);
useHelper(boxRef, BoxHelper, "red");
const raycast = useForwardRaycast(
boxRef,
scene?.children?.find((el) => el.name === "CollisionBox")
);
useFrame(() => {
const { moveForward, moveBackward, moveLeft, moveRight } = controls;
if (moveForward) {
boxRef.current.position.z += 0.1;
}
if (moveBackward) {
boxRef.current.position.z -= 0.1;
}
if (moveLeft) {
boxRef.current.position.x += 0.1;
}
if (moveRight) {
boxRef.current.position.x -= 0.1;
}
});
useFrame(() => {
const intersections = raycast();
if (intersections.length > 0) {
console.log("intersections", intersections);
}
});
return (
// <Box args={[5, 5, 5]} radius={0.05} smoothness={4} position={[0, 1, 0]} castShadow receiveShadow ref={boxRef} name="MovingBox">
// <meshPhongMaterial color="#f3f3f3" />
// </Box>
<mesh scale={[5, 5, 5]} position={[0, 0, 0]} ref={boxRef} name="MovingBox">
<boxGeometry />
<meshStandardMaterial color="grey" />
</mesh>
);
};
export default MovingBox;
Codesandbox: https://codesandbox.io/s/raycast-test-s6vvgd?file=/src/MovingBox.js:0-2041