概要
three.jsでanimation systemを、理解したかった。
フルスクラッチで、やってみた。
写真
サンプルコード
var clock = new THREE.Clock();
var camera,
controls,
scene,
renderer,
mixer,
helper;
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
if (mixer) mixer.update(clock.getDelta());
helper.update();
renderer.render(scene, camera);
}
function init() {
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(70, 70, 70);
controls = new THREE.OrbitControls(camera);
controls.minDistance = 10;
controls.maxDistance = 100;
scene = new THREE.Scene();
scene.add(new THREE.GridHelper(100, 10));
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xeeeeee);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
var armGeometry = new THREE.CylinderGeometry(5, 5, 40, 3, 4, true);
armGeometry.bones = [{
name: "bone0",
parent: -1,
pos: [0, -20, 0],
rotq: [0, 0, 0, 1],
scl: [1, 1, 1],
}, {
name: "bone1",
parent: 0,
pos: [0, 10, 0],
rotq: [0, 0, 0, 1],
scl: [1, 1, 1],
}, {
name: "bone2",
parent: 1,
pos: [0, 10, 0],
rotq: [0, 0, 0, 1],
scl: [1, 1, 1],
}, {
name: "bone3",
parent: 2,
pos: [0, 10, 0],
rotq: [0, 0, 0, 1],
scl: [1, 1, 1],
}, {
name: "bone4",
parent: 3,
pos: [0, 10, 0],
rotq: [0, 0, 0, 1],
scl: [1, 1, 1],
}];
armGeometry.skinIndices = [
new THREE.Vector4(4, 3, -1, -1),
new THREE.Vector4(4, 3, -1, -1),
new THREE.Vector4(4, 3, -1, -1),
new THREE.Vector4(3, 4, 2, -1),
new THREE.Vector4(3, 4, 2, -1),
new THREE.Vector4(3, 4, 2, -1),
new THREE.Vector4(2, 3, 1, -1),
new THREE.Vector4(2, 3, 1, -1),
new THREE.Vector4(2, 3, 1, -1),
new THREE.Vector4(1, 2, 0, -1),
new THREE.Vector4(1, 2, 0, -1),
new THREE.Vector4(1, 2, 0, -1),
new THREE.Vector4(0, 1, -1, -1),
new THREE.Vector4(0, 1, -1, -1),
new THREE.Vector4(0, 1, -1, -1),
];
armGeometry.skinWeights = [
new THREE.Vector4(.8, .2, 0, 0),
new THREE.Vector4(.8, .2, 0, 0),
new THREE.Vector4(.8, .2, 0, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.6, .2, .2, 0),
new THREE.Vector4(.8, .2, 0, 0),
new THREE.Vector4(.8, .2, 0, 0),
new THREE.Vector4(.8, .2, 0, 0),
];
var armMaterial = new THREE.MeshNormalMaterial({
skinning: true,
side: THREE.DoubleSide,
shading: THREE.FlatShading,
});
var arm = new THREE.SkinnedMesh(armGeometry, armMaterial);
var waveClip = THREE.AnimationClip.parseAnimation({
hierarchy: [{
}, {
}, {
keys: [{
pos: [0, 10, 0],
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(- Math.PI / 4, 0, 0)),
scl: [1, 1, 1],
time: 0,
}, {
pos: [0, 10, 0],
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 4, 0, 0)),
scl: [1, 1, 1],
time: 1,
}, {
pos: [0, 10, 0],
rot: new THREE.Quaternion().setFromEuler(new THREE.Euler(- Math.PI / 4, 0, 0)),
scl: [1, 1, 1],
time: 2,
}],
}, {
}, {
}]
}, armGeometry.bones);
mixer = new THREE.AnimationMixer(arm);
mixer.clipAction(waveClip).play();
helper = new THREE.SkeletonHelper(arm);
init();
scene.add(arm);
scene.add(helper);
animate();
成果物
以上。