上节初篇就画了个正方体,看起来没什么感觉,所以下面我大概介绍一下这个模型怎么才能旋转起来,让事情变得有趣一些
function render() {
renderer.render(scene,camera);//执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
}
//间隔20ms周期性调用函数fun,20ms也就是刷新频率是50FPS(1s/20ms),每秒渲染50次
setInterval(render,20);
把上节的renderer.render(scene,camera),替换成上面的代码就可以实现模型自己旋转,这个大概还有第二种方式实现旋转吧,如下
function render() {
renderer.render(scene,camera);//执行渲染操作
mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render
}
render();
嗯,这个方法一般默认保持60FPS的频率,大约每16.7ms调用一次requestAnimationFrame()方法指定的函数,60FPS是理想的情况下,如果渲染的场景比较复杂或者说硬件性能有限可能会低于这个频率,所有下面的可以真正实现匀速旋转,嗯,是的,匀速!
let T0: any = new Date();//上次时间
function render() {
let T1: any = new Date();//本次时间
let t = T1-T0;//时间差
T0 = T1;//把本次时间赋值给上次时间
requestAnimationFrame(render);
renderer.render(scene,camera);//执行渲染操作
mesh.rotateY(0.001*t);//旋转角速度0.001弧度每毫秒
}
render();
上面介绍了怎么实现旋转,但是我们一般还要自己选角度,不是说模型自己旋转到哪就看哪,这就非常被动,所以我们需要主动一点,我们添加个鼠标操作,会不会更好一点呢。来吧!
function render() {
renderer.render(scene,camera);//执行渲染操作
}
render();
var controls = new THREE.OrbitControls(camera,renderer.domElement);//创建控件对象
controls.addEventListener('change', render);//监听鼠标、键盘事件
这个是正常模式,但是呢,这里会报错TypeError: THREE.OrbitControls is not a constructor,为什么呢?这个是因为用npm 安装的three.js里面的确没有OrbitControls,所以这个需要手动安装一下
npm install three-orbitcontrols
安装完之后,需要在需要用到的页面/组件的头部引入一下
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
然后把THREE.OrbitControls(camera,renderer.domElement)改成OrbitControls(camera,renderer.domElement)就行了
再换成requestAnimationFrame写法把,不然感觉学了不用,有点扯呼。
function render() {
renderer.render(scene,camera);//执行渲染操作
// mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render
}
render();
var controls = new OrbitControls(camera,renderer.domElement);//创建控件对象
// 已经通过requestAnimationFrame(render);周期性执行render函数,没必要再通过监听鼠标事件执行render函数
// controls.addEventListener('change', render)
这大概就行了,咦,这里我想了想,光源会跟着模型旋转而旋转,如果我需要实现光源永远跟着相机不动,就像主角都会想一直在舞台灯光下那样,下面我们一起来实现模型的主角梦想:
function render() {
// 复制相机的坐标
var vector = camera.position.clone();
point.position.set(vector.x, vector.y, vector.z); //重置点光源位置
renderer.render(scene, camera);//执行渲染操作
// mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度
requestAnimationFrame(render);//请求再次执行渲染函数render
}
render();
var controls = new OrbitControls(camera, renderer.domElement);//创建控件对象
这样鼠标无论转到哪,光源都会在相机那里,不会再跟着模型旋转了。
梦想是实现了,但是为什么我感觉没啥用呢
到这里就有人会问,这个是正方体的,我想加圆球或者其他的模型呢,接着,下面就给大家看看怎么添加其他类型的几何体
//长方体 参数:长,宽,高
let geometry = new THREE.BoxGeometry(100, 100, 100);
// 球体 参数:半径60 经纬度细分数40,40
let geometry = new THREE.SphereGeometry(60, 40, 40);
// 圆柱 参数:圆柱面顶部、底部直径50,50 高度100 圆周分段数
let geometry = new THREE.CylinderGeometry(50, 50, 100, 25);
// 正八面体
let geometry = new THREE.OctahedronGeometry(50);
// 正十二面体
let geometry = new THREE.DodecahedronGeometry(50);
// 正二十面体
let geometry = new THREE.IcosahedronGeometry(50);
这里还会有人问,我怎么添加多个几何体组成其他形状呢?不要着急,下面就带大家看看
//立方体网格模型
let geometry1 = new THREE.BoxGeometry(100, 100, 100);
let material1 = new THREE.MeshLambertMaterial({
color: 0x0000ff
}); //材质对象Material
let mesh1 = new THREE.Mesh(geometry1, material1); //网格模型对象Mesh
scene.add(mesh1); //网格模型添加到场景中
//球体网格模型
let geometry2 = new THREE.SphereGeometry(60, 40, 40);
let material2 = new THREE.MeshLambertMaterial({
color: 0xff00ff
});
let mesh2 = new THREE.Mesh(geometry2, material2); //网格模型对象Mesh
mesh2.translateY(120); //球体网格模型沿Y轴正方向平移120
scene.add(mesh2);
// 圆柱网格模型
let geometry3 = new THREE.CylinderGeometry(50, 50, 100, 25);
let material3 = new THREE.MeshLambertMaterial({
color: 0xffff00
});
let mesh3 = new THREE.Mesh(geometry3, material3); //网格模型对象Mesh
// mesh3.translateX(120); //球体网格模型沿Y轴正方向平移120
mesh3.position.set(120, 0, 0);//设置mesh3模型对象的xyz坐标为120,0,0
scene.add(mesh3);
当然这里可以自己自由发挥,想要什么东西,自己可以慢慢研究,我就简单示范一下。
不知道有没有人发现我的图片有XYZ轴,这个东西不是默认有的,需要自己手动添加的,关键代码我给出来,需要的可以加上,不需要的了解一下也是可以的
// 辅助坐标系 参数250表示坐标系大小,可以根据场景大小去设置
let axisHelper = new THREE.AxisHelper(250);//换成THREE.AxesHelper(250)
scene.add(axisHelper);
这里也有个注意的就是AxisHelper是旧版的,新版的要用AxesHelper,如果用axisHelper没报错就不用管了