Three.js/기초튼튼

three.js 3D 모델 불러오기(glTF 파일 로드) - GLTFLoader

carrotweb 2023. 9. 10. 18:35
728x90
반응형

이번에는 외부에서 만들어진 3D 모델을 로드하여 Scence(씬, 장면)에 추가해 보도록 하겠습니다.

 

3D 모델들은 다양한 파일 포맷으로 저장됩니다. 대표적인 3D 파일 포맷으로 OBJ, FBX, glTF, USD가 있습니다.

 

다양한 파일 포맷 중에서 three.js에서는 glTF 파일 포맷을 사용하는 것을 추천하고 있습니다.

 

 

glTF(GL Transmission Format, GL 트랜스미션 포맷)는 응용프로그램에서 3D 장면과 3D 모델을 효율적으로 전송하고 로드시키는 방법에 대한 사양(규격, 명세)으로 로열티가 없는 오픈 소스 파일 포맷입니다.

 

glTF는 3D Assets(3D 에셋, 3D 자산(모델 정보, 텍스처, 바이너리 데이터))의 파일 크기를 최소화하였습니다. 그리고 3D Assets(3D 에셋)을 사용하기 위해 압축을 풀고 처리하는 런타임 프로세싱을 최소화하였습니다. (이것은 .glb 파일에 적용되는 내용입니다.)

 

glTF는 제작 작업 절차를 간소화하고 산업 전반에서 콘텐츠가 서로 호환되어 사용(상호운용)이 가능하게 3D 콘텐츠 도구 및 서비스를 위한 확장 가능한 공통 배포 포맷을 정의하였습니다.

 

자세한 설명은 glTF(https://github.com/KhronosGroup/glTF)를 참조하시기 바랍니다.

 

그럼 glTF는 어떤 구조로 되어 있을까요?

 

glTF 2.0 Specification(https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html)를 보면 다음과 같이 glTF의 Asset(에셋)에 대해 설명하고 있습니다.

 

 

glTF Asset(에셋, 자산)은 다음과 같이 표현됩니다.

  • Scence(씬, 장면)에 대한 전체 설명이 담긴 JSON 포맷 파일 (.gltf) : 노드 계층 구조, 머티리얼, 카메라 정보뿐만 아니라 메시, 애니메이션 그리고 기타 구성에 대한 설명자 정보도 포함됩니다.
  • 지오메트리, 애니메이션 그리고 기타 버퍼 기반 데이터가 담긴 바이너리 파일 (.bin)
  • 텍스처 이미지가 담긴 이미지 파일 (.jpg, .png, 등등)

 

즉, 아래 샘플(https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/BoomBox/glTF)처럼 glTF Asset(에셋, 자산)은 3개의 유형으로 JSON 포맷 파일 (.gltf), 데이터 파일 (.bin), 이미지 파일 (.jpg, .png, 등등)로 구성됩니다.

3D 모델에 대한 정보는 JSON 포맷으로 .gltf 파일로 저장되고 3D 모델의 지오메트리, 애니메이션, 스킨 정보들은 .bin 파일로 저장되고 3D 모델 머티리얼에서 사용되는 이미지들은 각각의 이미지 파일(.jpg, .png, 등등)로 저장됩니다.

그리고 JSON 포맷 파일(.gltf)에는 데이터가 담긴 바이너리 파일 (.bin)과 이미지 파일 (.jpg, .png)들이 연결되어 있습니다.

 

또는 JSON 포맷 파일, 데이터 파일, 모든 이미지 파일들이 하나의 바이너리 파일 (.glb)로 결합되어 저장됩니다.

대부분 glTF는 .glb 파일로 저장되고 배포됩니다. 그 이유는 데이터 파일 (.bin)과 이미지 파일 (.jpg, .png, 등등)를 함께 배포하는 것보다 배포가 용이하기 때문입니다.

 

그럼 glTF 파일을 로드해 보겠습니다.

 

1. import를 통해 GLTFLoader(GLTF로더) 모듈을 가져옵니다. GLTFLoader(GLTF로더)는 glTF 파일을 로드합니다.

import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

 

GLTFLoader(GLTF로더) 모듈의 실제 위치는 "\node_modules\three\examples\jsm\loaders\GLTFLoader.js" 입니다.

 

2. GLTF로더로 로드할 모델을 glTF-Sample-Models(https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/BoomBox/glTF-Binary/BoomBox.glb)에서 다운로드합니다.

 

그리고 프로젝트에 resources \ textures 폴더 다운로드한 BoomBox 파일(BoomBox.glb)을 추가합니다.

VSCode에서는 glTF 파일을 볼 수 없습니다.

 

3. GLTFLoader(GLTF로더)를 생성합니다.

GLTFLoader(manager : LoadingManager)
  • manager(매니저) : GLTF로더가 사용할 LoadingManager(로딩 매니저)입니다. 기본값 THREE.DefaultLoadingManager

 

기본 로딩 매니저로 GLTFLoader(GLTF로더)를 생성합니다.

// GLTF로더 생성
const loader = new GLTFLoader();

 

4. resources \ textures 폴더에 있는 BoomBox 파일(BoomBox.glb)을 GLTFLoader(GLTF로더)로 로드합니다.

.load (url : String, onLoad : Function, onProgress : Function, onError : Function)
  • url: .glb 파일 또는 .gltf 파일의 웹 주소입니다.
  • onLoad: 로딩이 성공적으로 완료된 후 호출되는 함수입니다. (함수 파라메타로  glTF JSON를 넘겨줍니다.)
  • onProgress: 로딩이 진행되는 동안 호출될 함수입니다. (함수 파라메타로 로드 정보를 넘겨줍니다. - 옵션)
  • onError: 로딩 중 오류가 발생하면 호출되는 함수입니다. ( 함수 파라메타로 에러 정보를 넘겨줍니다. - 옵션)

 

onLoad 함수에서는 콘솔 로그로 로드한 glTF의 JSON 정보를 출력하고 onProgress 함수에서는 콘솔 로그로 로딩 프로세스를 출력하고 onError 함수에서는 콘솔 로그로 오류 정보를 출력하게 합니다.

// glTF 파일 로드
loader.load('resources/textures/BoomBox.glb', 
    function (gltf) {
        console.log(gltf);
    },
    function (xhr) {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
	}, 
    function (error) {
        console.error(error);
    })
;

 

 

그러면  콘솔 로그에 로딩 프로세스가 출력되고 glTF의 JSON 정보가 출력됩니다.

 

5. Scence(씬, 장면)에 로드한 모델을 추가하기 위해 onLoad 함수에 glt의 scene를 추가하고 로드한 모델을 보기 위해 Camera(카메라)의 Focus Point(포커스 포인트, 초점)과 Position(포지션, 위치)를 변경합니다.

// glTF 파일 로드
loader.load('resources/textures/BoomBox.glb', 
    function (gltf) {
        console.log(gltf);
        scene.add(gltf.scene);
        // 육면체 옆으로 위치 변경
        gltf.scene.position.set(-2, 0, 0);
        // 카메라 초점 변경
        controls.target.copy(gltf.scene.position);
        // 카메라 위치 변경
        camera.position.set(-2, 1, 2);
    },
    function (xhr) {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
	}, 
    function (error) {
        console.error(error);
    })
;

그런데 로드된 모델이 점으로 보입니다. 그 이유는 로드되는 모델마다 크기가 일정하지 않기 때문입니다. 어떤 모델은 크기가 크고 어떤 모델은 크기가 작습니다.

 

그럼 로드된 모델의 크기가 어떻게 되는지 확인해 보겠습니다.

 

onLoad 함수에서 로드된 모델의 객체를 가져옵니다. 그리고 객체의 크기를 가져와서 콘솔 로그로 출력합니다.

// 로드된 모델의 크기 확인
var gltfObject = new THREE.Box3().setFromObject(gltf.scene);
var gltfObjectSize = gltfObject.getSize(new THREE.Vector3());
console.log(gltfObjectSize);

콘솔 로그에 보면 크기가 매우 작은 것을 확인할 수 있습니다.

{
    "x": 0.019842308,
    "y": 0.01954326,
    "z": 0.0201524906
}

 

모델의 크기를 키우기 위해 전체 Scale(스케일)의 크기를 변경합니다. 크기를 100배 정도 크게 하겠습니다.

// glTF 파일 로드
loader.load('resources/textures/BoomBox.glb', 
    function (gltf) {
        console.log(gltf);

        // 로드된 모델의 크기 확인
        var gltfObject = new THREE.Box3().setFromObject(gltf.scene);
        var gltfObjectSize = gltfObject.getSize(new THREE.Vector3());
        console.log(gltfObjectSize);

        // 모델의 스케일 변경
        gltf.scene.scale.x = 100;
        gltf.scene.scale.y = 100;
        gltf.scene.scale.z = 100;

        scene.add(gltf.scene);
        // 육면체 옆으로 위치 변경
        gltf.scene.position.set(-2, 0, 0);
        // 카메라 초점 변경
        controls.target.copy(gltf.scene.position);
        // 카메라 위치 변경
        camera.position.set(-2, 1, 2);
    },
    function (xhr) {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
	}, 
    function (error) {
        console.error(error);
    })
;

 

모델의 Scale(스케일)을 크게 하니 적당한 크기로 보입니다.

 

 

728x90
반응형