Three.js Chapter 3 section 21 Imported models

황상진·2024년 4월 15일
0

Three.js

목록 보기
9/15
post-thumbnail

Imported Models

Formats
format은 엄청 많고 manual하게 만들수도 있다.
그중에서 제일 많이 쓰는 것은 아래와 같다.

  • OBJ
  • FBX
  • STL
  • PLY
  • COLLADA
  • 3DS
  • GLTF

GLTF

  • GL Transmission Format
  • Khronos Group(OpenGL, WebGL, Vulkan, Collada를 만듬)이 만듬
  • geometry, material, cameras, lights, scene graph, animations, skeletons, morphing 등을 지원해준다.
  • json, binary, embed textures 등으로 활용된다.
  • 대부분의 3D software에 사용 가능하다.

GLTF format 종류

  • gltf
  • gltf-binary
  • gltf-draco
  • gltf-embedded

default gltf format

  • .gltf - camera,light,scene,material,object transformation을 담은 JSON
  • .bin - geometry의 data를 담은 binary
  • .png - texture

.gltf 파일만 load하면 다른 파일들은 자동적으로 load됨

gltf-binary format

  • 위에 있는 모든 data가 한 파일에 있다.
  • 더 가볍다
  • 하나의 파일이여서 load하기 쉽다.
  • data를 교체하기는 어렵다.

gltf-draco

  • default랑 비슷하지만 더 가볍다
  • draco algorithm으로 압축된 형태

Setup

  • GLTF Loader
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
  • Instantiate
/**
 * Models
 */
const gltfLoader = new GLTFLoader()
  • load model
  • load 함수를 활용한다.
  • load(gltf 파일 url, success callback fn, progress callback fn, error callback fn)
gltfLoader.load(
    '/models/Duck/glTF/Duck.gltf',
    (gltf) =>
    {
        console.log('success')
        console.log(gltf)
    },
    (progress) =>
    {
        console.log('progress')
        console.log(progress)
    },
    (error) =>
    {
        console.log('error')
        console.log(error)
    }
)
  • add loaded model to scene

gltf를 보면 아래와 같은 구조로 되어있다.
THREE.Group: scene
└───Array: children
└───THREE.Object3D
└───Array: children
├───THREE.PerspectiveCamera
└───THREE.Mesh

gltf를 scene에 추가하는 방법은 여러가지이다.

  • gltf의 scene을 다 추가한다.
  • scene의 children만 추가하고 PerspectiveCamera는 무시한다.
  • scene의 children만 추가하고 PerspectiveCamera는 추가하지 않는다.
  • Mesh만 추가한다. 그러나 이 경우 scale, position, rotation이 다를 수 있다.
  • 3D software에서 PerspectiveCamera를 지우고서 다시 export한다.
(gltf) =>
{
        scene.add(gltf.scene.children[0])
}

  • 아래와 같이 여러가지 format으로도 변경이 가능하다.
gltfLoader.load(
    '/models/Duck/glTF/Duck.gltf', // Default glTF

// Or
gltfLoader.load(
    '/models/Duck/glTF-Binary/Duck.glb', // glTF-Binary

// Or
gltfLoader.load(
    '/models/Duck/glTF-Embedded/Duck.gltf', // glTF-Embedded
  • 여러개의 children을 가진 gltf의 경우 load하는 법은 아래와 같다.

for loop로 순회하면서 add하면 정상적으로 보이지 않는다.
하나를 움직이면 자동적으로 지워버린다. 그러므로 loop가 적절하지 않다.
그래서 첫번째 children을 아무것도 없을때까지 scene에 추가한다.
아니면 children을 배열 분해하여서 for loop에 적용해서 추가한다.
더 쉽게는 그냥 gltf.scene을 scene에 추가한다.

while(gltf.scene.children.length)
{
    scene.add(gltf.scene.children[0])
}

const children = [...gltf.scene.children]
for(const child of children)
{
    scene.add(child)
}

scene.add(gltf.scene)

Draco Compression

  • 더 가볍고 빠르게 적용가능하다.

  • geometry buffer data를 압축한 것이다.

  • Google에서 만듬

  • Draco Loader를 사용해야한다.

import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
  • initiate
const dracoLoader = new DRACOLoader()
  • draco algorithm으로 된 녀석을 decode해야한다.
  • decoder는 다른 thread로 하면 더 빠르므로 다음 방식을 참고하자
  • Three.js에서 decoder를 제공한다.
  • 이 decoder를 static 폴더로 가져와서 활용한다.

가장 최근 version에는
/node_modules/three/examples/jsm/libs/
여기에 위치해있다.

-decoder를 설정한다.

dracoLoader.setDecoderPath('/draco/')
  • dracoLoader를 기존 gltfLoader에 세팅해준다.
gltfLoader.setDRACOLoader(dracoLoader)

DracoLoader가 항상 좋은 것은 아니다.
DracoLoader와 decoder를 load해야하기 때문이다.
100kb 정도면 사용하지 않아도 된다.
그러나 mb 단위가 넘어가면 사용하는게 좋다.

load한 모델이 scale이 맞지 않는다면 object3D의 scale을 줄이면 문제가 발생할 수 있다.
이런 경우, scene을 전체를 load하고 scene의 크기를 수정한다.

Animations

  • gltf object에 animation 속성이 있다.

  • animation 속성을 다량의 animationClip으로 구성되어있다.

  • animation을 재생하기 위해서 AnimationMixer가 필요하다.

  • AnimationMixer는 animationClip들을 관리하는 player이다.

  • THREE.AnimationMixer에 gltf.scene을 parameter로 주고 mixer 생성

  • mixer를 활용해서 animations을 담아서 action에 전달

  • action.play()로 animation 시작

  • tick 함수에서 mixer를 deltaTime으로 update해주면 성공

let mixer = null

gltfLoader.load(
    '/models/Fox/glTF/Fox.gltf',
    (gltf) =>
    {
        gltf.scene.scale.set(0.03, 0.03, 0.03)
        scene.add(gltf.scene)

        mixer = new THREE.AnimationMixer(gltf.scene)
        const action = mixer.clipAction(gltf.animations[0])
        action.play()
    }
)

const tick = () =>
{
    // ...

    if(mixer)
    {
        mixer.update(deltaTime)
    }

    // ...
}

Three.js Editor

https://threejs.org/editor/

  • 3D model을 위에서 확인이 가능하다.

결과물

https://21-imported-models-b82yibwgd-hwangsangjins-projects.vercel.app/

profile
Web FrontEnd Developer

0개의 댓글

관련 채용 정보