Formats
format은 엄청 많고 manual하게 만들수도 있다.
그중에서 제일 많이 쓰는 것은 아래와 같다.
GLTF format 종류
.gltf 파일만 load하면 다른 파일들은 자동적으로 load됨
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
/**
* Models
*/
const gltfLoader = new GLTFLoader()
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)
}
)
gltf를 보면 아래와 같은 구조로 되어있다.
THREE.Group: scene
└───Array: children
└───THREE.Object3D
└───Array: children
├───THREE.PerspectiveCamera
└───THREE.Mesh
gltf를 scene에 추가하는 방법은 여러가지이다.
(gltf) =>
{
scene.add(gltf.scene.children[0])
}
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
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)
더 가볍고 빠르게 적용가능하다.
geometry buffer data를 압축한 것이다.
Google에서 만듬
Draco Loader를 사용해야한다.
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
const dracoLoader = new DRACOLoader()
가장 최근 version에는
/node_modules/three/examples/jsm/libs/
여기에 위치해있다.
-decoder를 설정한다.
dracoLoader.setDecoderPath('/draco/')
gltfLoader.setDRACOLoader(dracoLoader)
DracoLoader가 항상 좋은 것은 아니다.
DracoLoader와 decoder를 load해야하기 때문이다.
100kb 정도면 사용하지 않아도 된다.
그러나 mb 단위가 넘어가면 사용하는게 좋다.
load한 모델이 scale이 맞지 않는다면 object3D의 scale을 줄이면 문제가 발생할 수 있다.
이런 경우, scene을 전체를 load하고 scene의 크기를 수정한다.
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)
}
// ...
}
https://21-imported-models-b82yibwgd-hwangsangjins-projects.vercel.app/