当前位置: 首页 > 工具软件 > rotation.js > 使用案例 >

Three.js入门(三)

漆雕嘉平
2023-12-01

摘自Three.js入门指南 张雯莉 (作者)

6、网格

在学习了几何形状和材质之后,我们就能使用他们来创建物体了。最常用的一种物体就是网格(Mesh),网格是由顶点、边、面等组成的物体;其他物体包括线段(Line)、骨骼(Bone)、粒子系统(ParticleSystem)等。创建物体需要指定几何形状和材质,其中,几何形状决定了物体的顶点位置等信息,材质决定了物体的颜色、纹理等信息。

网格创建

网格的创建非常简单,只要把几何形状与材质传入其构造函数。最常用的物体是网格(Mesh),它代表包含点、线、面的几何体,其构造函数是:

Mesh(geometry, material)

创建一个材质为黄色的Lambert材质,形状为长宽高分别为1,2,3的长方体网格物体。

var material = new THREE.MeshLambertMaterial({
    color: 0xffff00
});
var geometry = new THREE.CubeGeometry(1, 2, 3);
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

//也可以合并写
var mesh = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3), 
    new THREE.MeshLambertMaterial({
        color: 0xffff00
    })
);

修改属性

  • 除了在构造函数中指定材质,在网格被创建后,也能对材质进行修改。

如将上面的例子中的材质的颜色改为红色:

mesh.material = new THREE.MeshLambertMaterial({
    color: 0xff0000
});
  • 位置、缩放、旋转

    位置、缩放、旋转是物体三个常用属性。由于THREE.Mesh基础自THREE.Object3D,因此包含scale、rotation、position三个属性,它们都是THREE.Vector3实例。

修改位置position:

//修改z坐标为1
mesh.position.z = 1;

//整体移动到(1.5, -0.5, 0)
mesh.position.set(1.5, -0.5, 0);
//或
mesh.position = new THREE.Vector3(1.5, -0.5, 0)

缩放scale

//x轴方向放大2倍
mesh.scale.x = 2.0;

//整体缩小为原来0.5倍
mesh.scale.set(0.5,0.5,0.5);

旋转rotation,这是一个欧拉类型的值,但是旋转实际是通过有三个轴旋转的角度,单位是弧度。

//按Y轴正方向旋转45°
mesh.rotation.x += 0.25*Math.PI;

//顺序默认为x y z
mesh.rotation.set(100,0,0);

7、动画

实现动画效果

动画的本质是利用了人眼的视觉暂留特性,快速地变换画面,从而产生物体在运动的假象。而对于Three.js程序而言,动画的实现也是通过在每秒中多次重绘画面实现的。

为了衡量画面切换速度,引入了每秒帧数FPS(Frames Per Second)的概念,是指每秒画面重绘的次数。FPS越大,则动画效果越平滑,当FPS小于20时,一般就能明显感受到画面的卡滞现象。而当FPS足够大(比如达到60),再增加帧数人眼也不会感受到明显的变化,反而相应地就要消耗更多资源,因此只需选择一个合适的FPS即可。

对于Three.js动画而言,一般FPS在30到60之间都是可取的。

  • setInterval方法

    如果要设置特定的FPS(虽然严格来说,即使使用这种方法,JavaScript也不能保证帧数精确性),可以使用JavaScript DOM定义的方法:

setInterval(func, msec)

其中,func是每过msec毫秒执行的函数,如果将func定义为重绘画面的函数,就能实现动画效果。setInterval函数返回一个id
如果需要停止重绘,需要使用clearInterval方法,并传入该id

clearInterval(id_of_setinterval)

下面的例子通过setInterval函数设置FPS为60,渲染了一个物体绕y轴不断旋转的动画

id = setInterval(draw, 60);
//绘制一个绕y轴旋转的网格物体
function draw() {
    mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
    renderer.render(scene, camera);
}

//停止动画
//html
<button id="stopBtn" onclick="stop()">Stop</button>

//script
function stop() {
    if (id !== null) {
        clearInterval(id);
        id = null;
    }
}
  • requestAnimationFrame方法

    大多数时候,我们并不在意多久重绘一次,这时候就适合用requestAnimationFrame方法了。它告诉浏览器在合适的时候调用指定函数,通常可能达到60FPS。

function draw() {
    mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
    renderer.render(scene, camera);
    //requestAnimationFrame只请求一帧画面,因此需要无终止递归调用
    id = requestAnimationFrame(draw);
}

//同样也有办法停止动画
function stop() {
    if (id !== null) {
        cancelAnimationFrame(id);
        id = null;
    }
}

使用stat.js记录FPS

stat.js是Three.js的作者Mr. Doob的另一个有用的JavaScript库。很多情况下,我们希望知道实时的FPS信息,从而更好地监测动画效果。这时候,stat.js就能提供一个很好的帮助,它占据屏幕中的一小块位置,单击后显示每帧渲染时间。

function initStat() {
    stat = new Stats();
    stat.domElement.style.position = 'absolute';
    stat.domElement.style.right = '0px';
    stat.domElement.style.top = '0px';
    document.body.appendChild(stat.domElement);
}

//表示一帧的开始与结束
stat.begin();

mesh.rotation.y = (mesh.rotation.y + 0.01) % (Math.PI * 2);
renderer.render(scene, camera);

stat.end();
 类似资料: