BufferGeometry
threejs的长方体BoxGeometry
、球体SphereGeometry
等几何体都是基于类构建的,BufferGeometry是一个没有任何形状的空几何体,你可以通过BufferGeometry自定义任何几何形状,具体一点说就是定义顶点数据
// BufferGeometry 缓存几何体 可以自定义的几何体
// 创建一个几何体的本质就是 设置几何体的各个顶点
const geometry = new THREE.BufferGeometry();
BufferAttribute
定义几何体顶点数据// 创建几何体的 顶点数据
const vertices = new Float32Array([
0, 0, 0, // 第一个点的位置
3, 0, 0,
0, 3, 0,
0, 0, 3,
1, 0, 0,
0, 1, 0,
0, 0, 1,
2, 0, 0,
0, 5, 0,
0, 0, 7
])
通过threejs的属性缓冲区对象表示threejs几何体顶点数据。
// 通过 BufferAttribute来创建几何体的具体的顶点数据
const attribue = new THREE.BufferAttribute(vertices, 3);
.attributes.position
通过geometry.attributes.position
设置几何体顶点位置属性的值BufferAttribute
。
// 设置缓冲几何体的顶点位置
geometry.attributes.position = attribue;
Points
点模型和网格模型Mesh
一样,都是threejs的一种模型对象,只是大部分情况下都是用Mesh表示物体。
网格模型Mesh
有自己对应的网格材质,同样点模型Points
有自己对应的点材质
// 点模型有点模型自己的材料方法
const meterial = new THREE.PointsMaterial({
color: 0xff6600,
size: 0.1, //设置点的大小
})
几何体geometry作为点模型Points参数,会把几何体渲染为点,把几何体作为Mesh的参数会把几何体渲染为面。
const points = new THREE.Points(geometry, material); //点模型对象
Line
渲染顶点数据下面代码是把几何体作为线模型的参数,你会发现渲染效果是从第一个点开始到最后一个点,依次连成线。
// // 线材质对象
const meterial = new THREE.LineBasicMaterial({
color: 0xff6600, // 颜色
linewidth: 1, // 大小
//linecap: 'round', //ignored by WebGLRenderer
//linejoin: 'round' //ignored by WebGLRenderer
})
LineLoop
、LineSegments
threejs线模型除了Line,还提供了、,区别在于绘制线条的规则不同。
// 闭合线条
const line = new THREE.LineLoop(geometry, material);
//非连续的线条
const line = new THREE.LineSegments(geometry, material);
网格模型Mesh其实就一个一个三角形(面)拼接构成。使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三角形,就可以用来模拟表示物体的表面。
空间中一个三角形有正反两面,那么Three.js的规则是如何区分正反面的?非常简单,相机对着三角形的一个面,如果三个顶点的顺序是逆时针方向,该面视为正面,如果三个顶点的顺序是顺时针方向,该面视为反面。
Three.js的材质默认正面可见,反面不可见。
const material = new THREE.MeshBasicMaterial({
color: 0x0000ff, //材质颜色
side: THREE.FrontSide, //默认只有正面可见
});
const material = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide, //两面可见
});
const material = new THREE.MeshBasicMaterial({
side: THREE.BackSide, //设置只有背面可见
});
网格模型Mesh对应的几何体BufferGeometry,拆分为多个三角后,很多三角形重合的顶点位置坐标是相同的,这时候如果你想减少顶点坐标数据量,可以借助几何体顶点索引geometry.index
来实现。
一个矩形平面,可以至少通过两个三角形拼接而成。而且两个三角形有两个顶点的坐标是重合的。
注意三角形的正反面问题:保证矩形平面两个三角形的正面是一样的,也就是从一个方向观察,两个三角形都是逆时针或顺时针。
// 创建几何体的 顶点数据
const vertices = new Float32Array([
0, 0, 0, // 第一个点的位置
3, 0, 0,
3, 3, 0,
0, 0, 0,
3, 3, 0,
0, 3, 0
])
如果几何体有顶点索引geometry.index
,那么你可以吧三角形重复的顶点位置坐标删除。
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
3, 0, 0, //顶点2坐标
3, 3, 0, //顶点3坐标
0, 3, 0, //顶点4坐标
]);
BufferAttribute
定义顶点索引.index
数据通过javascriptUint16Array
创建顶点索引.index
数据。
// Uint16Array类型数组创建顶点索引数据
const indexes = new Uint16Array([
// 下面索引值对应顶点位置数据中的顶点坐标
0, 1, 2, 0, 2, 3,
])
通过threejs的属性缓冲区对象表示几何体顶点索引.index
数据。
// 索引数据赋值给几何体的index属性
geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组
顶点法线(法向量)数据geometry.attributes.normal
。
比如一个平面,法线的就是改平面的垂线,如果是光滑曲面,一点的法线就是该点切面的法线。
Three.js中法线和数学中法线概念相似,只是定义的时候更灵活,会根据需要进行调整,
Three.js中法线是通过顶点定义,默认情况下,每个顶点都有一个法线数据,就像每一个顶点都有一个位置数据。
// 矩形平面,无索引,两个三角形,6个顶点
// 每个顶点的法线数据和顶点位置数据一一对应
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法线
]);
// 设置几何体的顶点法线属性.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);
three.js提供的矩形平面PlaneGeometry
、长方体BoxGeometry
、球体SphereGeometry
等各种形状的几何体,他们都有一个共同的父类BufferGeometry
。这意味着这些几何体有哪些属性或方法,你可以查询文档关于BufferGeometry
的介绍。
可以用顶点索引index数据构建几何体,也可以不用,threejs默认的大部分几何体都有三角形的顶点索引数据,具体可以通过浏览器控制台打印几何体数据查看。
const geometry = new THREE.PlaneGeometry(100,50); //矩形平面几何体
// const geometry = new THREE.BoxGeometry(50,50,50); //长方体
console.log('几何体',geometry);
console.log('顶点位置数据',geometry.attributes.position);
console.log('顶点索引数据',geometry.index);
.wireframe
线条模式渲染,查看几何体三角形结构
const material = new THREE.MeshLambertMaterial({
color: 0x00ffff,
wireframe:true,//线条模式渲染mesh对应的三角形数据
});
Three.js很多几何体都提供了细分数相关的参数,这里以矩形平面几何体PlaneGeometry
为例
矩形平面几何体至少需要两个三角形拼接而成。
//矩形几何体PlaneGeometry的参数3,4表示细分数,默认是1,1
const geometry = new THREE.PlaneGeometry(100,50,1,1);
把一个矩形分为2份,每个矩形2个三角形,总共就是4个三角形
const geometry = new THREE.PlaneGeometry(100,50,2,1);
把一个矩形分为4份,每个矩形2个三角形,总共就是8个三角形
const geometry = new THREE.PlaneGeometry(100,50,2,2);
SphereGeometry
细分数球体SphereGeometry
参数2、3分别代表宽、高度两个方向上的细分数,默认32,16,具体多少以你所用版本为准。
const geometry = new THREE.SphereGeometry( 50, 32, 16 );
如果球体细分数比较低,表面就不会那么光滑。
const geometry = new THREE.SphereGeometry( 20, 10, 8 );
对于一个曲面而言,细分数越大,表面越光滑,但是三角形和顶点数量却越多。
几何体三角形数量或者说顶点数量直接影响Three.js的渲染性能,在不影响渲染效果的情况下,一般尽量越少越好。
BufferGeometry通过.scale()
、.translate()
、.rotateX()
、.rotateY()
等方法可以对几何体本身进行缩放、平移、旋转,这些方法本质上都是改变几何体的顶点数据。
// 几何体xyz三个方向都放大2倍
geometry.scale(2, 2, 2);
// 几何体沿着x轴平移50
geometry.translate(50, 0, 0);
// 几何体绕着x轴旋转45度
geometry.rotateX(Math.PI / 4);
// 几何体旋转、缩放或平移之后,查看几何体顶点位置坐标的变化
// BufferGeometry的旋转、缩放、平移等方法本质上就是改变顶点的位置坐标
console.log('顶点位置数据', geometry.attributes.position);
.scale()
// 几何体xyz三个方向都放大2倍
geometry.scale(2, 2, 2);
// 几何体旋转、缩放或平移之后,查看几何体顶点位置坐标的变化
// BufferGeometry的旋转、缩放、平移等方法本质上就是改变顶点的位置坐标
console.log('顶点位置数据', geometry.attributes.position);
.translate()
// 几何体沿着x轴平移50
geometry.translate(50, 0, 0);
.rotateX()
、.rotateY()
、.rotateZ()
// 几何体绕着x轴旋转45度
geometry.rotateX(Math.PI / 4);
.center()
geometry.translate(50, 0, 0);//偏移
// 居中:已经偏移的几何体居中,执行.center(),你可以看到几何体重新与坐标原点重合
geometry.center();
有兴趣了解更多的小伙伴可以关注我的公众号: codefuzi 我会持续更新相关知识点3D案例
因篇幅问题不能全部显示,请点此查看更多更全内容