「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」
示例代码采用three.js-r73版本: cdnjs.cloudflare.com/ajax/libs/t…
我们现在可以在场景中画出一条线和基本的三角形,下面会使用直线画一个网格出来,为了更好的理解这个网格在空间中的位置,我们需要先了解一下空间坐标系。
坐标系
坐标系如下图,向上为Y正轴,向右为X正轴,向屏幕从里到外方向为Z正轴。
左手坐标系和右手坐标系
- 三维坐标系分为两种,左手坐标系和右手坐标系。下面两张图都可以表示左右手坐标系。
- Threejs使用的是右手坐标系,这源于opengl默认情况下,也是右手坐标系。x轴正方向向右,y轴正方向向上,z轴由屏幕从里向外。
使用three.js-editor编辑器看坐标系
- three.js源码地址:github.com/mrdoob/thre…
- 在three.js源码中,有一个编辑器,就是
editor
目录,在浏览器打开index.html
页面,大概长这个样子:
- 然后我们点击左上角add,添加一个box
- 我们可以看到,红轴为X轴,绿轴为Y轴,蓝轴为Z轴,箭头指向为正方向。
关于围绕某个轴旋转
- 还记得我们之前做过的物体旋转动画吗
- 拇指指向旋转轴的正方向,四指弯曲的方向为旋转的正方向。
世界坐标和本地坐标
- 一个应用程序可能包含成百上千个单独的对象,我们必须把它们放到一个公共的场景里。
- 公共的场景就是世界坐标
- 相对于物体来说,物体本身的坐标就是本地坐标
- 相机默认在世界坐标系的原点
世界坐标
- 比如我们在threejs编辑器中,添加两个盒子,这两个盒子在场景中都有自己的position
- 场景就是世界坐标
- 两个盒子的位置是世界坐标系下的位置
本地坐标
- 还是上面那张图,我们每个盒子都有自己的坐标系,自己的坐标系就是本地坐标系。
场景中添加辅助坐标
- 我们可以给我们的场景添加辅助坐标
- 用于简单模拟3个坐标轴的对象.
- 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
new THREE.AxisHelper() // 最新版重命名 AxesHelper
// 定义辅助坐标
var axisHelper
function initAxisHelper() {
axisHelper = new THREE.AxisHelper(4) //
scene.add(axisHelper)
}
- 相机的位置:
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 5;
- 添加之后的效果:
- 这个时候我们看不到我们的Z轴,因为我们的摄像机是正对着物体(就像正在观看电脑屏幕的你),如何才能看到Z轴呢,我们需要让摄像机偏移一点,让相机向右移动一些距离
camera.position.x = 5;
camera.position.y = 0;
camera.position.z = 5;
- 此时我们就可以看到x,y,z轴了
辅助坐标轴进行旋转
我们可以让我们的辅助坐标旋转,然后相对于物体是静止的
function render() {
renderer.clear();
cube.rotation.y += 0.01;
axisHelper.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
Object3D添加辅助坐标和物体为子类
- 目前的辅助坐标是场景的,并不是物体的,通过相对静止的方法才使得辅助坐标作用在物体上,当关闭旋转就不是了
- 我们可以把辅助坐标和物体组合到一个3D对象上-Object3D,
new THREE.Object3D()
- 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对三维空间中的物体进行操纵。
- 请注意,可以通过**.add( object )**方法来将对象进行组合,该方法将对象添加为子对象,但为此最好使用Group(来作为父对象)。
修改原来的代码
- 辅助坐标不再添加到场景中
var cube;
function initObject() {
....
cube = new THREE.Mesh(geometry, material);
// scene.add(cube);
}
// 定义辅助坐标
var axisHelper
function initAxisHelper() {
axisHelper = new THREE.AxisHelper(4) //
// scene.add(axisHelper)
}
- 添加
initObjectTotal
方法,将物体和辅助坐标添加到objectTotal
中
// 初始化一个三维物体,并添加子物体和辅助坐标
var objectTotal
function initObjectTotal() {
objectTotal = new THREE.Object3D()
objectTotal.add(cube)
objectTotal.add(axisHelper)
scene.add(objectTotal)
}
render
函数中旋转objectTotal
就可以让子物体一起旋转
function render() {
renderer.clear();
objectTotal.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
function threeStart() {
initThree();
initCamera();
initScene();
initObject();
initAxisHelper();
initObjectTotal()
initLight();
render();
}