react-three-fiber , 3D model file (.gltf
추천)
💡 보통 3D 모델 파일은 https://sketchfab.com 에서 구할 수 있다.
💡 다른 확장자에 대한 모델 로딩 방법은 Loading Models 을 참고하자!
기본적으로 gltf 형식은 uri
필드를 통해 필요한 부수 자원을 가져오는 방식을 사용한다. 따라서 .gltf
파일을 서빙할 때, URL에 대해 신경을 많이 써야 한다.
한 예시로, Google의 Firestore에 .gltf
파일을 업로드해서 사용하는 경우,
.gltf
파일 외의 부수 자원에 대한 uri
도 토큰이 적용되어야 한다.uri
필드에 임베딩하는 것으로 해결할 수 있다..gltf
파일을 firestore에 업로드하고, 그 주소를 이용해 로드하면 끝!참고: How to get the link to raw data of a file on Cloud Storage?
import { Canvas } from "@react-three/fiber";
function CustomCanvas() {
const cameraRef = useRef<Camera>(null);
return (
<Canvas>
<ambientLight />
<directionalLight />
{/* 카메라와 컨트롤러 */}
{/*<PerspectiveCamera
ref={cameraRef}
makeDefault={true}
position={[0, 0, 50]}
/>
<OrbitControls
camera={cameraRef.current}
makeDefault={true}
enableZoom={false}
/>*/}
<Suspense fallback={null}>
<WolfMesh position={[0, 0, -10]} />
</Suspense>
</Canvas>
);
}
💡 기본적으로, React Three Fiber 에서는 Three.js 에서 사용되는 요소를 컴포넌트화 시켜 사용할 수 있게 만들었다. 이러한 컴포넌트들은 기존 React의 컨벤션을 따르지 않고, 첫 글자를 소문자로 시작해야 한다.
Canvas
ambientLight
directionalLight
PerspectiveCamera
OrbitControls
import { Canvas, Camera, useFrame, useLoader } from "@react-three/fiber";
// ...
function WolfMesh(props: JSX.IntrinsicElements["mesh"]) {
const [hovered, setHover] = useState(false);
const [active, setActive] = useState(false);
// load GLTF
const gltf = useLoader(GLTFLoader, "<GLTF_URI>");
// handle 3d model
useFrame((state, delta, frame) => {
const mesh = gltf.scene.children[0];
mesh.rotation.y = mesh.rotation.z += 0.01;
mesh.rotation.x = state.clock.getElapsedTime();
});
return (
<>
<primitive
object={gltf.scene}
scale={0.01}
onPointerOver={(e) => setHover(true)}
onPointerOut={(e) => setHover(false)}
onClick={(e) =>
window.open("https://sketchfab.com/anthonyjamesgirdler")
}
/>
</>
);
}
useLoader
와 GLTFLoader
를 이용해 gltf 파일을 로드한다.primitive.object
에 gltf.scene
을 넣어 주면 기본적으로 모델을 보여줄 메쉬가 완성!primitive
는 ref 를 이용할 수 없기 때문에, useFrame
과 gltf
를 이용해 애니메이션 등의 조작을 할 수 있다.이렇게 3D 모델이 정상적으로 보여지는 것을 확인할 수 있다.
여기서 좀 힘든 게, primitive.scale
과 privitive.position
, Camera.position
을 적절히 잘 조절해야 3D 모델이 이상적인 크기로 보여질 수 있는데, 카메라와 컨트롤러 렌더링 유무에 따라 줌 수치가 달라져서 일일이 수정해줘야한다… (position
이 각 어떤 수치인지 이해를 해야 할 것 같다.)