友情链接:threejs 中文文档
目录
1. 几何体顶点数据和点模型
(1) 缓冲类型几何体 BufferGeometry
(2) BufferAttribute定义几何体顶点数据
(3) 设置几何体顶点.attributes.position
(4) 点模型Points
2. 线模型对象
(1) 线模型对象渲染数据
(2) 线模型LineLoop、LineSegments
3. 网格模型(三角形概念)
4. 几何体顶点索引数据
(1) 定义顶点位置坐标数据
(2) BufferAttribute定义顶点索引.index数据
5. 顶点法线数据
(1) 数学上法线概念
(2) 矩形平面几何体法线案例——无顶点索引
(3) 矩形平面几何体法线案例——有顶点索引
6. 旋转、缩放、平移几何体
threejs的长方体BoxGeometry、球体SphereGeometry等几何体都是基于BufferGeometry (opens new window)类构建的,BufferGeometry是一个没有任何形状的空几何体,你可以通过BufferGeometry自定义任何几何形状,具体一点说就是定义顶点数据。
//创建一个空的几何体对象
const geometry = new THREE.BufferGeometry();
通过javascript类型化数组 (opens new window)Float32Array创建一组xyz坐标数据用来表示几何体的顶点坐标。
//类型化数组创建顶点数据
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
50, 0, 0, //顶点2坐标
0, 100, 0, //顶点3坐标
0, 0, 10, //顶点4坐标
0, 0, 100, //顶点5坐标
50, 0, 10, //顶点6坐标
]);
通过threejs的属性缓冲区对象BufferAttribute (opens new window)表示threejs几何体顶点数据。
// 创建属性缓冲区对象
//3个为一组,表示一个顶点的xyz坐标
const attribue = new THREE.BufferAttribute(vertices, 3);
通过geometry.attributes.position设置几何体顶点位置属性的值BufferAttribute。
// 设置几何体attributes属性的位置属性
geometry.attributes.position = attribue;
点模型Points和网格模型Mesh一样,都是threejs的一种模型对象,只是大部分情况下都是用Mesh表示物体。
网格模型Mesh有自己对应的网格材质,同样点模型Points有自己对应的点材质PointsMaterial
// 点渲染模式
const material = new THREE.PointsMaterial({
color: 0xffff00,
size: 10.0 //点对象像素尺寸
});
几何体geometry作为点模型Points参数,会把几何体渲染为点,把几何体作为Mesh的参数会把几何体渲染为面。
const points = new THREE.Points(geometry, material); //点模型对象
下面代码是以上节内容为基础,把几何体作换为线模型Line的参数,你会发现渲染效果是从第一个点开始到最后一个点,依次连成线。
// 线材质对象
const material = new THREE.LineBasicMaterial({
color: 0xff0000 //线条颜色
});
// 创建线模型对象
const line = new THREE.Line(geometry, material);
threejs线模型除了Line,还提供了LineLoop (opens new window)、LineSegments (opens new window),区别在于绘制线条的规则不同。
// 闭合线条
const line = new THREE.LineLoop(geometry, material);
//非连续的线条
const line = new THREE.LineSegments(geometry, material);
网格模型mesh原理是由n个三角形拼接构成,使用使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三角形,就可以用来模拟表示物体的表面。
网格模型有着正反面之分,默认的情况的下一个三角形只会显示它的正面,threejs的正反面是根据三角形坐标点渲染的顺序来区分的,如果三个点的顺序为顺时针,则为正面,反之则为背面也可以通过设置材质的属性来规定那一面可见
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
来实现。
每个三角形3个顶点坐标,矩形平面可以拆分为两个三角形,也就是6个顶点坐标
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
80, 0, 0, //顶点2坐标
80, 80, 0, //顶点3坐标
0, 0, 0, //顶点4坐标 和顶点1位置相同
80, 80, 0, //顶点5坐标 和顶点3位置相同
0, 80, 0, //顶点6坐标
]);
通过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个为一组
当材质由MeshBasicMaterial材质改为MeshLambertMaterial这种受光照影响的材质,会发现原来的矩形平面无法渲染。原因就是使用了受光照影响的材质,几何体BufferGeometry需要定义顶点法线数据。
先来理解一下数学上的法线概念,比如一个平面,法线的就是改平面的垂线,如果是光滑曲面,一点的法线就是该点切面的法线。
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);
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);
文章中部分素材选取自Threejs中文网:Three.js中文网