three.js教程2-几何体BufferGeomety顶点
1、网格模型(三角形概念)
网格模型Mesh其实就一个一个三角形(面)拼接构成。使用使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三角形,就可以用来模拟表示物体的表面。
正面三角形:顶点逆时针形成
反面三角形:顶点顺时针形成
const material = new THREE.MeshBasicMaterial({ color: 0x0000ff, //材质颜色 side: THREE.FrontSide, //默认只有正面可见 }); //THREE.FrontSide, //默认只有正面可见 //THREE.DoubleSide, //两面可见 //THREE.BackSide, //设置只有背面可见
2、根据顶点坐标生成面
个矩形平面,可以至少通过两个三角形拼接而成。而且两个三角形有两个顶点的坐标是重合的。
注意三角形的正反面问题:保证矩形平面两个三角形的正面是一样的,也就是从一个方向观察,两个三角形都是逆时针或顺时针。
const geometry = new THREE.BufferGeometry(); //创建一个几何体对象 //类型数组创建顶点数据 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坐标 ]); // 创建属性缓冲区对象 const attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组,表示一个顶点的xyz坐标 // 设置几何体attributes属性的位置属性 geometry.attributes.position = attribue; const material = new THREE.MeshBasicMaterial({ color: 0x00ffff, side: THREE.DoubleSide, //两面可见 }); // 网格模型本质:一个一个三角形(面)构成 const mesh = new THREE.Mesh(geometry, material);
3、几何体顶点索引数据
网格模型Mesh对应的几何体BufferGeometry,拆分为多个三角后,很多三角形重合的顶点位置坐标是相同的,这时候如果你想减少顶点坐标数据量,可以借助几何体顶点索引geometry.index
来实现。
const geometry = new THREE.BufferGeometry(); //创建一个几何体对象 //类型数组创建顶点数据 const vertices = new Float32Array([ 0, 0, 0, //顶点1坐标 80, 0, 0, //顶点2坐标 80, 80, 0, //顶点3坐标 0, 80, 0, //顶点4坐标 ]); // 创建属性缓冲区对象 const attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组,表示一个顶点的xyz坐标 // 设置几何体attributes属性的位置属性 geometry.attributes.position = attribue; // Uint16Array类型数组创建顶点索引数据 const indexes = new Uint16Array([ 0, 1, 2, 0, 2, 3, ]) // BufferAttribute表示顶点索引属性的值 geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组 // 索引数据赋值给几何体的index属性 const material = new THREE.MeshBasicMaterial({ color: 0x00ffff, side: THREE.DoubleSide, //两面可见 }); // 网格模型本质:一个一个三角形(面)构成 const mesh = new THREE.Mesh(geometry, material);
4、顶点法线数据
法线的就是该平面的垂线,如果是光滑曲面,一个点的法线就是该点切面的线。
MeshBasicMaterial不受光照影像,可以直接显示平面颜色。但是MeshLambertMaterial受光照影像,需要给他设置顶点法线,这样平面颜色才能正常显示(因为threeJs需要根据法线计算光的反射角度等问题,没有法线就计算不了,不能显示颜色)。
(1)不用索引的矩形平面构建
const geometry = new THREE.BufferGeometry(); //创建一个几何体对象 //类型数组创建顶点数据 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坐标 ]); // 设置几何体attributes属性的位置属性 geometry.attributes.position = new THREE.BufferAttribute(vertices, 3); //3个为一组,表示一个顶点的xyz坐标 // 每个顶点的法线数据和顶点位置数据一一对应 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); //3个为一组,表示一个顶点的法线数据 // MeshBasicMaterial不受光照影响 // 使用受光照影响的材质,Geometry几何体需要定义顶点法线数据 const material = new THREE.MeshLambertMaterial({ color: 0x0000ff, side: THREE.DoubleSide, //两面可见 }); // 网格模型本质:一个一个三角形(面)构成 const mesh = new THREE.Mesh(geometry, material);
(2)用索引的矩形平面构建
const geometry = new THREE.BufferGeometry(); //创建一个几何体对象 //类型数组创建顶点数据 const vertices = new Float32Array([ 0, 0, 0, //顶点1坐标 80, 0, 0, //顶点2坐标 80, 80, 0, //顶点3坐标 0, 80, 0, //顶点4坐标 ]); // 设置几何体attributes属性的位置属性 geometry.attributes.position = new THREE.BufferAttribute(vertices, 3); //3个为一组,表示一个顶点的xyz坐标 // 每个顶点的法线数据和顶点位置数据一一对应 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个为一组,表示一个顶点的法线数据 // Uint16Array类型数组创建顶点索引数据 const indexes = new Uint16Array([ 0, 1, 2, 0, 2, 3, ]) // 索引数据赋值给几何体的index属性 geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组 const material = new THREE.MeshBasicMaterial({ color: 0x0000ff, side: THREE.DoubleSide, //两面可见 }); // 网格模型本质:一个一个三角形(面)构成 const mesh = new THREE.Mesh(geometry, material);
5、几何体的旋转、缩放、平移方法
BufferGeometry的旋转、缩放、平移等方法本质上就是改变顶点的位置坐标
// 几何体xyz三个方向都放大2倍 geometry.scale(2, 2, 2); // 几何体沿着x轴平移50 geometry.translate(50, 0, 0); // 几何体绕着x轴旋转45度 geometry.rotateX(Math.PI / 4); // 居中:已经偏移的几何体居中,执行.center(),你可以看到几何体重新与坐标原点重合 geometry.center(); // 几何体旋转、缩放或平移之后,查看几何体顶点位置坐标的变化 // BufferGeometry的旋转、缩放、平移等方法本质上就是改变顶点的位置坐标 console.log('顶点位置数据', geometry.attributes.position);
用索引构建的矩形平面,打印输出geometry属性,观察position和normal的数量:
BoxGeometry生成立方体,输出geometry,观察position和normal的数量
uv坐标:是平面二维坐标,负责二维纹理映射到三维几何体的对应关系,和顶点一一对应。
文章中部分素材选取自Threejs中文网:http://www.webgl3d.cn/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了