- Udemy의 Three.js and TypeScript 강의를 듣고 정리한 내용을 기록한다.
- 29. JEasings 부터 30. GLTF Animations 까지.
JEasings
- 애니메이션에 사용할 수 있는 자바스크립트의 Easing 엔진.
Easing: 사전적 의미로는 ‘완화’라는 의미를 갖는다. 애니메이팅에서는 애니메이션을 자연스럽게 만들기 위해 천천히 움직이도록 완화하는 기법을 의미하는 것 같다.
- 일정 시간동안 물체의 속성을 새로운 값으로 변하도록 해주는 기능을 제공한다.
- 아래의 값들을 설정할 수 있다.
- 변환 시간
- 새로이 설정할(변환될) 값
- 시작하기 까지의 딜레이
- 변환이 끝났을 때 실행될 스크립트
- 변환 시간 동안 변환에 걸리는 시간을 변경하는 Easing 함수
- 등등…
강사분이 직접 만드신 패키지같다. Tween.js에 기반한 패키지라고.
사용 방법
- yarn 이나 npm 등을 사용해 패키지를 설치한다.
yarn add -D jeasings
- 아래와 같이 불러와 사용한다.
import JEASINGS from 'jeasings';
- JEasings를 사용해 변하는 값을 업데이트 하기 위해서는, 애니메이션 루프에서 update 함수를 호출해야 한다.
import * as THREE from 'three';
import JEASINGS from 'jeasings';
/* 생략 */
function animate() {
requestAnimationFrame(animate);
JEASINGS.update();
}
animate();
- JEasings을 통해 값을 변환하기 위해서는 JEasing 객체를 생성한다.
import * as THREE from 'three';
import JEASINGS from 'jeasings';
/* 일부 코드 생략 */
// Raycaster를 사용하여 얻어낸 교차점의 좌표 P
const p = intersects[0].point;
new JEASINGS.JEasing(controls.target)
.to(
{
x: p.x,
y: p.y,
z: p.z
},
500
)
//.delay (1000)
//.easing(JEASINGS.Cubic.Out)
//.onUpdate(() => render())
.start();
- JEasing 생성자로 객체를 선언하며, 변환할 값인 controls.target(OrbitControls의 target)을 전달하고 있다.
- to 함수를 통해 변환 후의 목표 값과 걸리는 시간을 설정한다.
- 다른 함수들을 체이닝하여 부가적인 세팅을 할 수 있다.
- delay: 변환 효과를 바로 주지 않고, 설정한 값만큼의 시간이 흐른 후 시작한다.
- easing: 변환에 사용되는 Easing 함수를 설정한다.
- onUpdate: 매 Update 시 실행할 로직을 추가할 수 있다.
- start 함수로 Easing을 시작한다.
Easing 함수에는 아래와 같은 함수들이 존재한다(링크).
JEasings에서는 JEASINGS.[방정식 이름].[방향] 의 포맷으로 함수를 사용할 수 있다(참고).
GLTF Animations
Mixamo: 다양한 3D 모델과 애니메이션을 다운로드 받을 수 있는 사이트(링크).
에셋을 다운받기 위해서는 어도비 계정이 필요하다.
- 실습을 위해 Mixamo 에서 애니메이션이 붙어있는 모델 파일을 fbx 형식으로 받는다.
- 받은 파일을 Blender를 사용해 glTF 파일로 변경해준다.
- 받은 모델을 Three.js에서 로딩하고, console.log로 확인해보면 animations 속성이 존재하고 같이 붙여준 animation이 들어가 있음을 알 수 있다.
AnimationMixer
- Scene에 존재하는 특정 물체의 애니메이션을 재생시키는 플레이어 역할을 수행한다.
- AnimationMixer 생성자로 AnimationMixer 객체를 생성하여 사용할 수 있다.
- 애니메이션을 갖는 복수의 모델이 있다면, 한 모델 당 하나의 mixer를 가져야 한다.
import * as THREE from 'three';
let mixer: THREE.AnimationMixer;
new GLTFLoader().load('models/eve$@walk.glb', (gltf) => {
mixer = new THREE.AnimationMixer(gltf.scene);
console.log(gltf);
mixer.clipAction(gltf.animations[0]).play();
scene.add(gltf.scene);
})
// 생략
const clock = new THREE.Clock();
let delta = 0;
function animate() {
requestAnimationFrame(animate);
delta = clock.getDelta();
controls.update();
mixer.update(delta);
renderer.render(scene, camera);
}
- AnimationMixer 생성자를 사용해 mixer 변수에 할당하고, 생성자의 인자로 로딩한 모델을 넘겨준다.
- clipAction 메서드를 사용해 모델 객체에 존재하는 animation 중 하나를 가져와, play 메서드로 재생한다.
- Animation 루프에서는 mixer.update()를 통해 애니메이션을 업데이트한다.
- 모델과 함께 붙어있는 애니메이션이 아닌, 오직 애니메이션’만’을 가져와 모델에 재생시키는 것도 가능하다.
- 다만, 이 경우 재생하려는 애니메이션이 현재 모델과 잘 맞는지 미리 살펴봐야 한다.
import * as THREE from 'three';
async function loadEve() {
const loader = new GLTFLoader()
const [eve, idle] = await Promise.all([
loader.loadAsync('models/eve$@walk.glb'),
loader.loadAsync('models/eve@idle.glb'),
]);
mixer = new THREE.AnimationMixer(eve.scene);
mixer.clipAction(idle.animations[0]).play();
scene.add(eve.scene);
}
await loadEve();
- 모델(eve$@walk.glb)과 가만히 서있는 애니메이션(eve@idle.glb)을 가져온다.
- clipAction에 모델이 갖고 있는 애니메이션이 아닌, 따로 가져온 애니메이션을 할당하여 재생한다.
한 모델의 애니메이션 전환하기
- 하나의 모델에 여러 개의 애니메이션이 있고, 이를 서로 전환하고 싶을 때는 별도의 객체로 애니메이션 정보를 관리해야 한다.
import * as THREE from 'three';
// 생략
let animationActions: { [key: string]: THREE.AnimationAction } = {};
let activeAction: THREE.AnimationAction;
async function loadEve() {
const loader = new GLTFLoader()
const [eve, idle, run] = await Promise.all([
loader.loadAsync('models/eve$@walk.glb'),
loader.loadAsync('models/eve@idle.glb'),
loader.loadAsync('models/eve@run.glb')
]);
mixer = new THREE.AnimationMixer(eve.scene);
animationActions['idle'] = mixer.clipAction(idle.animations[0]);
animationActions['walk'] = mixer.clipAction(eve.animations[0]);
animationActions['run'] = mixer.clipAction(run.animations[0]);
animationActions['idle'].play();
activeAction = animationActions['idle'];
scene.add(eve.scene);
}
await loadEve();
- 모델과 애니메이션을 로딩한 후, 각 애니메이션을 clipAction으로 가져와 animationActions라는 객체에 할당한다.
- 이를 통해 메모리 내에 애니메이션을 담아두고, 언제든 불러와 쓸 수 있다.
- 현재 실행 중인 애니메이션을 activeAction 이라는 변수로 관리한다.
- animationActions의 값(value)과 activeAction은 AnimationAction 타입을 가지며, 이를 통해 애니메이션을 재생하는 등의 함수를 사용할 수 있다.
'공부 > etc' 카테고리의 다른 글
Three.js and TypeScript (11) (2) | 2024.12.03 |
---|---|
Three.js and TypeScript (9) (0) | 2024.11.22 |
Three.js and TypeScript (8) (1) | 2024.11.21 |
Three.js and TypeScript (7) (2) | 2024.11.20 |
Three.js and TypeScript (6) (0) | 2024.11.19 |