用法:
var tween = new TWEEN.Tween({x:10}).to({x:3},10000).easing(TWEEN.Easing.Elastic.InOut).OnUpdate(function(){
})
Tween(…).to(…,time)是从一个状态变化到另一个状态,time是变化需要的时间(毫秒)
easing是变化的方式,OnUpdate是变化过程的需要更新的一些变化
var posSrc = {pos: 1};//初始状态
var tween = new TWEEN.Tween(posSrc).to({pos: 0}, 5000);
tween.easing(TWEEN.Easing.Sinusoidal.InOut);
var tweenBack = new TWEEN.Tween(posSrc).to({pos: 1}, 5000);
tweenBack.easing(TWEEN.Easing.Sinusoidal.InOut);
tween.chain(tweenBack);//将两个tween连接在一起
tweenBack.chain(tween);
var onUpdate = function () {
var count = 0;
var pos = this.pos;
loadedGeometry.vertices.forEach(function (e) {
var newY = ((e.y + 3.22544) * pos) - 3.22544;
pointCloud.geometry.vertices[count++].set(e.x, newY, e.z);
});
pointCloud.sortParticles = true;
};
tween.onUpdate(onUpdate);
tweenBack.onUpdate(onUpdate);
变形动画简单地说就是把一堆顶点移动到一个新的位置
使用外部模型创建动画
var loader = new THREE.JSONLoader();
loader.load('../assets/models/horse.js', function (geometry, mat) {
var mat = new THREE.MeshLambertMaterial(
{
morphTargets: true,//使用变形动画时,此值要设置为true
vertexColors: THREE.FaceColors//材质颜色设置为几何体的面的颜色
});
morphColorsToFaceColors(geometry);
geometry.computeFaceNormals();//计算各个面的法向量,这样才能有效计算出各个面的变化
meshAnim = new THREE.MorphAnimMesh(geometry, mat);
scene.add(meshAnim);
}, '../assets/models');
//这个函数的作用是将每个面形变后的颜色传给当前的颜色
function morphColorsToFaceColors(geometry) {
//形变动画形变的各个面的颜色都存储在geometry.morphColors中,将其提取出来赋给几何体的面即可
if (geometry.morphColors && geometry.morphColors.length) {
var colorMap = geometry.morphColors[0];
for (var i = 0; i < colorMap.colors.length; i++) {
geometry.faces[i].color = colorMap.colors[i];
geometry.faces[i].color.offsetHSL(0, 0.3, 0);
}
}
}
function render() {
stats.update();
//使用clock更新
var delta = clock.getDelta();
webGLRenderer.clear();
if (meshAnim) {
meshAnim.updateAnimation(delta * 1000);
meshAnim.rotation.y += 0.01;
}
// render using requestAnimationFrame
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
很简单,先使用cubeGeometry.morphTargets[]
指定变化后的几何体,再使用cube.morphTargetInfluences
指定这个几何体的影响程度,注意可以指定多个几何体
// create a cube
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({morphTargets: true, color: 0xff0000});
// define morphtargets, we'll use the vertices from these geometries
var cubeTarget1 = new THREE.BoxGeometry(2, 10, 2);
var cubeTarget2 = new THREE.BoxGeometry(8, 2, 8);
// define morphtargets and compute the morphnormal
cubeGeometry.morphTargets[0] = {name: 't1', vertices: cubeTarget2.vertices};
cubeGeometry.morphTargets[1] = {name: 't2', vertices: cubeTarget1.vertices};
cubeGeometry.computeMorphNormals();
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
var controls = new function () {
this.influence1 = 0.01;
this.influence2 = 0.01;
this.update = function () {
cube.morphTargetInfluences[0] = controls.influence1;
cube.morphTargetInfluences[1] = controls.influence2;
};
};
比变形动画复杂一些,一组顶点作为一块骨头,一般一块骨头动整组定点都会跟着动,而且负责一些动作(旋转,扭动等)的点一般都是关节点,一般从外部模型导入。
使用THREE.SkinnedMesh创建网格
一般SkinnedMesh和Tween配合使用
var loader = new THREE.JSONLoader();
loader.load('../assets/models/hand-1.js', function (geometry, mat) {
//使用骨骼动画要将skinning设置为true
var mat = new THREE.MeshLambertMaterial({color: 0xF0C8C9, skinning: true});
mesh = new THREE.SkinnedMesh(geometry, mat);
// rotate the complete hand
mesh.rotation.x = 0.5 * Math.PI;
mesh.rotation.z = 0.7 * Math.PI;
// add the mesh
scene.add(mesh);
// and start the animation
tween.start();
}, '../assets/models');
//设置骨架的动作
var onUpdate = function () {
var pos = this.pos;
console.log(mesh.skeleton);
// rotate the fingers
mesh.skeleton.bones[5].rotation.set(0, 0, pos);
mesh.skeleton.bones[6].rotation.set(0, 0, pos);
mesh.skeleton.bones[10].rotation.set(0, 0, pos);
mesh.skeleton.bones[11].rotation.set(0, 0, pos);
mesh.skeleton.bones[15].rotation.set(0, 0, pos);
mesh.skeleton.bones[16].rotation.set(0, 0, pos);
mesh.skeleton.bones[20].rotation.set(0, 0, pos);
mesh.skeleton.bones[21].rotation.set(0, 0, pos);
// rotate the wrist
mesh.skeleton.bones[1].rotation.set(pos, 0, 0);
};
var tween = new TWEEN.Tween({pos: -1})
.to({pos: 0}, 3000)
.easing(TWEEN.Easing.Cubic.InOut)
.yoyo(true)//一个动作完毕后,使用相反的动作变回初始状态
.repeat(Infinity)//无限循环
.onUpdate(onUpdate);
render();
因为动作在外部模型中已经定义好了,只需要闯将一个Animation对象,调用其play()方法即可
var loader = new THREE.JSONLoader();
loader.load('../assets/models/hand-2.js', function (model, mat) {
var mat = new THREE.MeshLambertMaterial({color: 0xF0C8C9, skinning: true});
mesh = new THREE.SkinnedMesh(model, mat);
//在geometry中已经定义好了动画
var animation = new THREE.Animation(mesh, model.animation);
mesh.rotation.x = 0.5 * Math.PI;
mesh.rotation.z = 0.7 * Math.PI;
scene.add(mesh);
//能够看到线框
helper = new THREE.SkeletonHelper(mesh);
helper.material.linewidth = 2;
helper.visible = false;
scene.add(helper);
// start the animation
animation.play();
}, '../assets/models');