几何体
在three.js
中如球体、立方体、平面、狗、猫、人、树、建筑等物体,都是几何体。它们都是根据大量顶点参数生成。在three.js
中内置了许多基本几何体,也提供了自定义几何体的方法。在开发中常见的做法是让美术在 3D 建模软件中创建 3D 模型,在由开发人员进行交互开发。常见几何体
BoxGeometry 盒子
分段数简单理解,就是每多一个分段,在对应面的轴上添加两个顶点,增加组成这个面三角形的数量。分段数越多面就越精细,性能消耗也会变大。const width = 8 // 宽度const height = 8 // 高度const depth = 8 // 深度const widthSegments = 4 // ui: 宽度的分段数const heightSegments = 4 // ui: 高度的分段数const depthSegments = 4 // ui: 深度的分段数const boxGeometry = new THREE.BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
SphereGeometry 球
SphereGeometry
是通过扫描并计算围绕着Y轴和X轴的顶点来创建的。我们可以通过修改水平、垂直扫描角度的大来实现球体切片。const radius = 8 // 球体半径const widthSegments = 32 // 水平分段数const heightSegments = 16 // 垂直分段数const geometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments)// 网格const mesh = new THREE.Mesh(geometry, material)mesh.position.x = 10scene.add(mesh){const radius = 8 // 球体半径const widthSegments = 32 // 水平分段数const heightSegments = 16 // 垂直分段数const phiStart = Math.PI * 0.25 // 水平(经线)起始角度const phiLength = Math.PI * 2 // 水平(经线)扫描角度的大小const thetaStart = Math.PI * 0.25 // 垂直(纬线)起始角度const thetaLength = Math.PI * 0.5 // 垂直(纬线)扫描角度大小const geometry1 = new THREE.SphereGeometry(radius,widthSegments,heightSegments,phiStart,phiLength,thetaStart,thetaLength)// 网格const mesh1 = new THREE.Mesh(geometry1, material)mesh1.position.x = -10scene.add(mesh1)}
PlaneGeometry 平面几何体
const width = 8 // 宽度const height = 8 // 高度const widthSegments = 2 // 宽度的分段数const heightSegments = 2 // 高度的分段数const geometry = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments)
BufferGeometry 自定义几何体
BufferGeometry
是面片、线或点几何体的有效表述。通过顶点位置、法相量、颜色值、UV 坐标等值来绘制几何体使用BufferGeometry
可以有效减少向 GPU 传输顶点数据所需的开销。 定义面的顶点位置,法线坐标(法线是面朝向的信息)。一个面是两个三角形组成,所以需要6个顶点,一个立方体就需要36个顶点信息。const vertices = [// front{pos: [-1, -1, 1], norm: [0, 0, 1] },{pos: [1, -1, 1], norm: [0, 0, 1] },{pos: [-1, 1, 1], norm: [0, 0, 1] },{pos: [-1, 1, 1], norm: [0, 0, 1] },{pos: [1, -1, 1], norm: [0, 0, 1] },{pos: [1, 1, 1], norm: [0, 0, 1] },// right{pos: [1, -1, 1], norm: [1, 0, 0] },{pos: [1, -1, -1], norm: [1, 0, 0] },{pos: [1, 1, 1], norm: [1, 0, 0] },{pos: [1, 1, 1], norm: [1, 0, 0] },{pos: [1, -1, -1], norm: [1, 0, 0] },{pos: [1, 1, -1], norm: [1, 0, 0] },// back{pos: [1, -1, -1], norm: [0, 0, -1] },{pos: [-1, -1, -1], norm: [0, 0, -1] },{pos: [1, 1, -1], norm: [0, 0, -1] },{pos: [1, 1, -1], norm: [0, 0, -1] },{pos: [-1, -1, -1], norm: [0, 0, -1] },{pos: [-1, 1, -1], norm: [0, 0, -1] },// left{pos: [-1, -1, -1], norm: [-1, 0, 0] },{pos: [-1, -1, 1], norm: [-1, 0, 0] },{pos: [-1, 1, -1], norm: [-1, 0, 0] },{pos: [-1, 1, -1], norm: [-1, 0, 0] },{pos: [-1, -1, 1], norm: [-1, 0, 0] },{pos: [-1, 1, 1], norm: [-1, 0, 0] },// top{pos: [1, 1, -1], norm: [0, 1, 0] },{pos: [-1, 1, -1], norm: [0, 1, 0] },{pos: [1, 1, 1], norm: [0, 1, 0] },{pos: [1, 1, 1], norm: [0, 1, 0] },{pos: [-1, 1, -1], norm: [0, 1, 0] },{pos: [-1, 1, 1], norm: [0, 1, 0] },// bottom{pos: [1, -1, 1], norm: [0, -1, 0] },{pos: [-1, -1, 1], norm: [0, -1, 0] },{pos: [1, -1, -1], norm: [0, -1, 0] },{pos: [1, -1, -1], norm: [0, -1, 0] },{pos: [-1, -1, 1], norm: [0, -1, 0] },{pos: [-1, -1, -1], norm: [0, -1, 0] }]const positions = []const normals = []// 以数组形式获取 数据for (const vertex of vertices) {positions.push(...vertex.pos)normals.push(...vertex.norm)}
通过.setAttribute()
设置定义好的顶点信息。这里需要注意的是.BufferAttribute()
第二个参数是确认,数组中连续的几个值组合为一组信息。
const geometry = new THREE.BufferGeometry()const positionNumComponents = 3 // 3个一组 为一个顶点const normalNumComponents = 3 // 3个一组 为一个顶点geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents))geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents))
自定义几何体的优势是它和GPU传输的数度快,缺点是顶点信息难以修改,在开发中需要根据需求判断是否使用。
总结
在three.js
中内置的几何体非常的多,需要深入了解的需要到官网上查看。本节简单的介绍了几何体是什么。在创建几何体时需要注意,分段数的大小要控制好。细分的越少,运行的越流畅,使用的内存也会更少。细分的越多,动画越精细,运行的越不流畅。