Dandy Now!
  • [Next.js] 동일한 GLTF 모델을 2번 이상 렌더링하기(react-three-fiber/drei/Three.js)
    2023년 12월 28일 09시 45분 38초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    1. 한 페이지에 하나의 GLTF만 렌더링 되는 문제

    페이지에 하나의 GLTF 파일을 이용해 여러 개의 모델을 렌더링 하고자 하였다. 이미지 태그를 이용하는 방식처럼 당연히 가능할 거라 생각했는데 현실은 [그림 2]와 같이 마지막 하나의 구성만 적용되었다. 여러 테스트 중에 GLTF의 복사본의 만들어 이름을 달리하여 로드했더니 원하는 결과를 얻을 수 있었다. 하지만 렌더링 모델의 개수만큼 동일한 내용을 담고 있는 GLTF 파일을 무수히 만들 수는 없는 일이었다.

     

    [그림 1] 2개 모델 중 마지막 모델만 화면에 보이고 있음

     

    2. Clone으로 문제 해결

    react-three-fiber에서 Clone 컴포넌트를 제공하고 있었다. 이 기능을 이용하여 [그림 2]와 같이 하나의 GLTF를 통해 2개 이상의 모델을 화면에 렌더링 할 수 있었다.

     

    [그림 2] Clone 이용해 2개 이상 모델 렌더링 성공

     

    해당 코드는 아래와 같다.

    // page.tsx
    "use client";
    import React from "react";
    import CharacterViewer from "./CharacterViewer";
    
    export default function Page() {
      const characterPath = "red_01.glb";
    
      return (
        <>
          <div>
            <CharacterViewer characterPath={characterPath} />
          </div>
          <div>
            <CharacterViewer characterPath={characterPath} />
          </div>
        </>
      );
    }

     

    // CharacterViewer.jsx
    "use client";
    import React, { Suspense } from "react";
    import { Canvas, useFrame } from "@react-three/fiber";
    import { Clone, OrbitControls, useGLTF } from "@react-three/drei";
    import * as THREE from "three";
    
    const Character = ({ characterPath, scale }) => {
      const { scene, animations } = useGLTF(characterPath);
    
      let mixer = null;
    
      // 애니메이션 재생
      if (animations.length !== 0) {
        mixer = new THREE.AnimationMixer(scene);
        void mixer.clipAction(animations[0]).play();
    
        // eslint-disable-next-line react-hooks/rules-of-hooks
        useFrame((state, delta) => {
          mixer.update(delta);
        });
      }
    
      return (
        <Clone object={scene} scale={scale} /> // 애니메이션 재생 안됨
        // <primitive object={scene} scale={scale} /> // 애니메이션 재생됨
      );
    };
    
    const CharacterViewer = ({ characterPath }) => {
      return (
        <div>
          // Canvas에 키를 주어야 렌더링 오작동을 예방할 수 있음
          <Canvas key={characterPath} camera={{ position: [20, 0, -8] }}>
            <OrbitControls />
            <ambientLight intensity={2} />
            <pointLight position={[10, 10, 10]} />
            <group {...characterPath} dispose={null} rotation-y={Math.PI / 2}>
              <Character scale={[15, 15, 15]} characterPath={characterPath} />
            </group>
            <Suspense fallback={null}></Suspense>
          </Canvas>
        </div>
      );
    };
    
    export default CharacterViewer;

     

    3. 또 다른 문제

    primitive 태그를 이용하면 모델의 애니메이션이 정상적으로 동작하지만, Clone 태그를 이용하면 재생되지 않는 문제가 있어 숙제가 생겼다.

     

    참고 자료
    https://stackoverflow.com/questions/68813736/use-the-same-gltf-model-twice-in-react-three-fiber-drei-three-js

     

    728x90
    반응형
    댓글