概要
three.jsでanimation systemを、理解したかった。
練習問題、やってみた。
練習問題
vrmのAnimationClipを自作せよ。
写真
サンプルコード
let lastTime;
let mixer;
let currentVrm = null;
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(45, 500 / 400, 0.1, 1000)
camera.position.set(0, 1.2, -1.9)
camera.rotation.set(0, Math.PI, 0)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(500, 400)
document.body.appendChild(renderer.domElement)
const directionalLight = new THREE.DirectionalLight('#ffffff', 1)
directionalLight.position.set(1, 1, 1)
scene.add(directionalLight)
const loader = new THREE.GLTFLoader();
loader.load('https://drumath2237.github.io/three-vrm-test/models/undefined-chan-toon.vrm',
(gltf) => {
THREE.VRM.from(gltf).then((vrm) => {
currentVrm = vrm;
scene.add(vrm.scene);
vrm.blendShapeProxy.setValue(THREE.VRMSchema.BlendShapePresetName.Joy, 1.0);
vrm.blendShapeProxy.update();
var clip = make();
console.log(clip);
mixer = new THREE.AnimationMixer(vrm.scene);
mixer.clipAction(clip).setEffectiveWeight(1.0).play();
});
},
(progress) => console.log('Loading model...', 100.0 * (progress.loaded / progress.total), '%'),
(error) => console.error(error)
)
function tick() {
requestAnimationFrame(tick)
let time = new Date().getTime();
if (mixer)
mixer.update(time - lastTime);
lastTime = time;
renderer.render(scene, camera)
}
function make() {
const bones = [THREE.VRMSchema.HumanoidBoneName.Hips].map((boneName) => {
return currentVrm.humanoid.getBoneNode(boneName)
})
//alert(bones);
const clip = THREE.AnimationClip.parseAnimation({
hierarchy: [{
keys: [{
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)).toArray(),
time: 0.0,
}, {
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 1.2, 0)).toArray(),
time: 100.0,
}, {
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)).toArray(),
time: 200.0,
}, {
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(0, -1.2, 0)).toArray(),
time: 300.0,
}, {
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)).toArray(),
time: 400.0,
}, {
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)).toArray(),
time: 500.0,
}]
}]
}, bones)
clip.tracks.some((track) => {
track.name = track.name.replace(/^\.bones\[([^\]]+)\].(position|quaternion|scale)$/, '$1.$2')
})
return clip;
}
tick()
成果物
以上。