1.几何体顶点索引数据
经过前面两节的介绍,我们对BufferGeometry有了更深入的了解,但是,在我们之前创建面、线或点的时候,我们给的顶点坐标数据是不同的,考虑下面的场景,如果我们给的顶点坐标数据有重复的坐标(比如有两个点都是0,0,0)的时候我们需要重复输入两次吗?答案当然是不用的,我们可以借助Threejs提供的几何体顶点索引geometry.index来实现。
比如我们通过下面一组数据来创建一个几何体
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
100, 0, 0, //顶点2坐标
100, 100, 0, //顶点3坐标
0, 0, 0, //顶点4坐标 和顶点1位置相同
100, 100, 0, //顶点5坐标 和顶点3位置相同
0, 100, 0, //顶点6坐标
])
在这组数据中,顶点1坐标和顶点4坐标是重合的,顶点3坐标和顶点5坐标是重合的,这时,我们就可以使用几何体的顶点索引geometry.index,把重复的顶点位置坐标删除
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
100, 0, 0, //顶点2坐标
100, 100, 0, //顶点3坐标
0, 100, 0, //顶点4坐标
])
然后,通过BufferAttribute定义顶点索引.index数据;这里通过javascript类型数组Uint16Array创建顶点索引.index数据。
// Uint16Array类型数组创建顶点索引数据
const indexes = new Uint16Array([
// 下面索引值对应顶点位置数据中的顶点坐标
0, 1, 2, 0, 2, 3,
])
然后,可以通过threejs的属性缓冲区对象BufferAttribute表示几何体顶点索引.index数据。
// 索引数据赋值给几何体的index属性
geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组
将属性添加到几何体
// 创建属性缓冲区对象
const attribute = new THREE.BufferAttribute(vertices, 3);
// 设置几何体attributes属性的位置属性
geometry.attributes.position = attribute;
// 创建材质
const material = new THREE.MeshBasicMaterial({
color: 0xff0000
})
// 创建物体
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
刷新浏览器查看效果
2.顶点法线数据
前面在讲光的时候我们提到过MeshBasicMaterial和MeshLambertMaterial的不同,MeshBasicMaterial材质是不受光照影响的;而MeshLambertMaterial是受光照影响的。如果我们将上面创建的四边形的材质换成MeshLambertMaterial,刷新浏览器后我们发现物体看不见了,这是因为使用受光照影响的材质,BufferGeometry需要定义顶点法线数据。那么什么是顶点法线呢?
在数学上,我们知道在一个平面上,法线就是该平面的垂线,如果是光滑曲面,一点的法线就是该点切面的法线;Three.js中法线是通过顶点定义,默认情况下,每个顶点都有一个法线数据,我们通过一个类型数组来标识各个点的顶点法线;
// 每个顶点的法线数据和顶点位置数据一一对应
const normals = new Float32Array([
0, 0, 1, //顶点1法线( 法向量 )
0, 0, 1, //顶点2法线
0, 0, 1, //顶点3法线
0, 0, 1, //顶点4法线
0, 0, 1, //顶点5法线
0, 0, 1, //顶点6法线
])
在Threejs中,通过.attributes.normal设置几何体的顶点法线属性
// 设置几何体的顶点法线属性.attributes.normal
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3)
这样设置后,就可以在浏览器中正常看到物体了
这里需要注意的一点是顶点法线的数据和顶点的位置数据是一一对应的,如果我们使用了顶点索引,顶点法线数据也要和顶点位置数据一一对应
// 矩形平面,有索引,有2个顶点重合,有4个顶点
// 每个顶点的法线数据和顶点位置数据一一对应
const normals = new Float32Array([
0, 0, 1, //顶点1法线( 法向量 )
0, 0, 1, //顶点2法线
0, 0, 1, //顶点3法线
0, 0, 1, //顶点4法线
])
// 设置几何体的顶点法线属性.attributes.normal
geometry.attributes.normal = new THREE.BufferAttribute(normals, 3)
看效果
3.缓冲几何体的旋转、缩放、平移等操作
BufferGeometry通过.scale()、.translate()、.rotateX()、.rotateY()等方法可以对几何体本身进行缩放、平移、旋转,这些方法本质上都是通过改变几何体的顶点数据来实现的。
缩放.scale()
// 几何体xyz三个方向都放大2倍
geometry.scale(2, 2, 2)
// 几何体旋转、缩放或平移之后,查看几何体顶点位置坐标的变化
// BufferGeometry的旋转、缩放、平移等方法本质上就是改变顶点的位置坐标
console.log('顶点位置数据', geometry.attributes.position)
刷新浏览器打开调试模式,可以看到顶点的位置坐标发生了变换
平移.translate()
// 几何体沿着x轴平移100
geometry.translate(100, 0, 0)
console.log('顶点位置数据', geometry.attributes.position)
旋转.rotateX()、.rotateY()、.rotateZ()
// 几何体绕着x轴旋转45度
geometry.rotateX(Math.PI / 4)
console.log('顶点位置数据', geometry.attributes.position)
总结:通过三个小结的详细介绍,我们对BufferGeometry的了解有了更近一步的认知,这几节偏理论写,可能比较枯燥,下一节我们通过这几节将的内容来实现一个旋转的地球的效果,喜欢的关注加点赞收藏哦。