React-Three-Fiber로 3D 모델 보여주기

Einere·2022년 8월 19일
1

1. 준비물

react-three-fiber , 3D model file (.gltf 추천)

💡 보통 3D 모델 파일은 https://sketchfab.com 에서 구할 수 있다.

💡 다른 확장자에 대한 모델 로딩 방법은 Loading Models 을 참고하자!

2. gltf 파일 수정하기

기본적으로 gltf 형식은 uri 필드를 통해 필요한 부수 자원을 가져오는 방식을 사용한다. 따라서 .gltf 파일을 서빙할 때, URL에 대해 신경을 많이 써야 한다.

한 예시로, Google의 Firestore에 .gltf 파일을 업로드해서 사용하는 경우,

  1. 메인 파일인 .gltf 파일 외의 부수 자원에 대한 uri 도 토큰이 적용되어야 한다.
  2. 토큰을 일일이 집어 넣더라도, 실제로 이후에 설명할 로더를 이용해 로드를 한다 하더라도, 주소가 이상하게 되어버려 제대로 로드를 할 수 없다.
  3. 그러나 각 부수 자원 파일을 base64로 인코딩하여 직접 uri 필드에 임베딩하는 것으로 해결할 수 있다.
  4. 이렇게 임베딩한 .gltf 파일을 firestore에 업로드하고, 그 주소를 이용해 로드하면 끝!

참고: How to get the link to raw data of a file on Cloud Storage?

3. 캔버스 만들기

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

  • React Three Fiber에서 제공하는, 씬을 만들기 위한 객체이다.

ambientLight

  • 씬에 존재하는 모든 물체에 전역적으로 빛을 비춘다.
  • 방향이 없기 때문에, 그림자를 만들 수 없다.

directionalLight

  • 일광과 같이, 아주 먼 거리의 광원에서 평행으로 진행하는 빛이다.

PerspectiveCamera

  • 인간의 시각을 흉내낸 투시 모드. 3D에서 흔한 투시 모드다.

OrbitControls

  • 카메라가 물체 주위를 궤도로 움직일 수 있게 해준다. (약간 행성처럼)

4. Mesh 만들기

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")
        }
      />
    </>
  );
}
  1. useLoaderGLTFLoader 를 이용해 gltf 파일을 로드한다.
  2. primitive.objectgltf.scene 을 넣어 주면 기본적으로 모델을 보여줄 메쉬가 완성!
  3. primitive 는 ref 를 이용할 수 없기 때문에, useFramegltf 를 이용해 애니메이션 등의 조작을 할 수 있다.

이렇게 3D 모델이 정상적으로 보여지는 것을 확인할 수 있다.

여기서 좀 힘든 게, primitive.scaleprivitive.position , Camera.position 을 적절히 잘 조절해야 3D 모델이 이상적인 크기로 보여질 수 있는데, 카메라와 컨트롤러 렌더링 유무에 따라 줌 수치가 달라져서 일일이 수정해줘야한다… (position 이 각 어떤 수치인지 이해를 해야 할 것 같다.)

profile
지속가능한 웹 개발자를 지향합니다. 경험의 공유를 통해 타인에게 도움이 되는 것을 좋아합니다. 사용자에게 가치를 제공하는 것에 기쁨을 느낍니다.

0개의 댓글