레슨 5 / 8·20분
애니메이션과 카메라 컨트롤
키프레임 애니메이션과 트윈
Three.js는 glTF 모델에 포함된 키프레임 애니메이션을 AnimationMixer로 재생할 수 있습니다. 또한 코드 기반으로 부드러운 전환(tween) 애니메이션을 구현하거나, 다양한 카메라 컨트롤로 사용자 시점을 제어할 수 있습니다.
javascript
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
const gltfLoader = new GLTFLoader();
let animMixer;
gltfLoader.load('/models/character.glb', (gltf) => {
const model = gltf.scene;
scene.add(model);
// AnimationMixer 생성
animMixer = new THREE.AnimationMixer(model);
// 모든 애니메이션 클립 확인
console.log('Animations:', gltf.animations.map(a => a.name));
// 첫 번째 애니메이션 재생
const action = animMixer.clipAction(gltf.animations[0]);
action.play();
});
// 애니메이션 루프에서 mixer 업데이트
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
if (animMixer) animMixer.update(delta);
renderer.render(scene, camera);
}
animate();코드 기반 트윈 애니메이션
javascript
// Lerp(선형 보간) 애니메이션
function lerp(start, end, t) {
return start + (end - start) * t;
}
const targetPos = new THREE.Vector3(3, 1, 0);
function animate() {
requestAnimationFrame(animate);
// 매 프레임 5%씩 목표에 접근
cube.position.x = lerp(cube.position.x, targetPos.x, 0.05);
cube.position.y = lerp(cube.position.y, targetPos.y, 0.05);
cube.position.z = lerp(cube.position.z, targetPos.z, 0.05);
renderer.render(scene, camera);
}
// 클릭 시 목표 위치 변경
window.addEventListener('click', () => {
targetPos.set(
(Math.random() - 0.5) * 6,
Math.random() * 3,
(Math.random() - 0.5) * 6
);
});javascript
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
// OrbitControls — 마우스로 회전/줌/패닝
const orbitControls = new OrbitControls(camera, renderer.domElement);
orbitControls.enableDamping = true;
orbitControls.dampingFactor = 0.05;
orbitControls.minDistance = 2;
orbitControls.maxDistance = 20;
orbitControls.autoRotate = true;
orbitControls.autoRotateSpeed = 2.0;
// PointerLockControls — FPS 게임 스타일 카메라
const fpControls = new PointerLockControls(camera, document.body);
document.addEventListener('click', () => fpControls.lock());
const velocity = new THREE.Vector3();
document.addEventListener('keydown', (e) => {
if (e.code === 'KeyW') velocity.z = -0.1;
if (e.code === 'KeyS') velocity.z = 0.1;
if (e.code === 'KeyA') velocity.x = -0.1;
if (e.code === 'KeyD') velocity.x = 0.1;
});
document.addEventListener('keyup', () => velocity.set(0, 0, 0));- •AnimationMixer — glTF 모델의 키프레임 애니메이션을 관리/재생
- •clipAction() — AnimationClip을 Action으로 변환하여 제어
- •lerp — 선형 보간으로 부드러운 이동/전환 구현
- •OrbitControls — 궤도 카메라 (3D 뷰어에 적합)
- •PointerLockControls — FPS 스타일 카메라 (게임에 적합)
💡
AnimationMixer.update(delta)는 반드시 매 프레임 호출해야 합니다. delta 대신 고정 값을 사용하면 프레임 속도에 따라 애니메이션 속도가 달라집니다.