ThreeJs入门26-THREE.BufferGeometry的奥秘

2,868 阅读2分钟

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战

示例代码采用three.js-r73版本: cdnjs.cloudflare.com/ajax/libs/t…

yuque_diagram.jpg

上一节,我们主要讲了vtk模型文件格式,和模型解析parse函数,这一节我们主要讲一下,BufferGeometry在模型解析时的应用。 ​

我们为什么要用BufferGeometry而不是使用Geometry呢?

BufferGeometry的特点

  • 一个更高效的Geometry
  • 高效的秘诀:将数据放在一块连续的内存空间中
  • 是面片、线或点几何体的有效表述。包括顶点位置,面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值
  • 连续的存储空间,可以有效减少向 GPU 传输上述数据所需的开销

示例详解

var geometry = new THREE.BufferGeometry();
// 创建一个简单的矩形. 在这里我们左上和右下顶点被复制了两次。
// 因为在两个三角面片里,这两个顶点都需要被用到。
var vertices = new Float32Array( [
	-1.0, -1.0,  1.0,
	 1.0, -1.0,  1.0,
	 1.0,  1.0,  1.0,

	 1.0,  1.0,  1.0,
	-1.0,  1.0,  1.0,
	-1.0, -1.0,  1.0
] );

// itemSize = 3 因为每个顶点都是一个三元组。
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var mesh = new THREE.Mesh( geometry, material );
  • THREE.BufferGeometry创建一个geometry实例
  • Float32Array是定义一个float类型数组
  • geometry.addAttribute我们向geometry存放顶点、法线等等都是通过这个方法来添加
    • 最新版已经改成setAttribute
  • THREE.BufferAttribute(array,itemSize)
    • 用于存储与BufferGeometry相关联的 attribute
    • array,存放vertices数据
    • itemSize,3表示三个数据组成一个position

VTKLoader中对于BufferGeometry的使用

// 解析完成之后通过BufferGeometry生成geometry
var geometry = new THREE.BufferGeometry();
geometry.setIndex(new THREE.BufferAttribute(new (indices.length > 65535 ? Uint32Array : Uint16Array)(indices), 1));
geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(positions), 3));
  • 定义一个BufferGeometry
  • geometry.setIndex设置面的索引
    • 如果索引数组长度大于65535,我们分配一个Uint32Array数组,否则分配一个Uint16Array数组
    • indicesindices作为BufferAttribute的第一个参数,每1个数字代表一个索引
  • geometry.addAttribute这里添加了一个position属性
    • 每三个数据组成一个position
  • 最后生成了我们的geometry

注意: 查看源码可以看出来,下面两个代码等价的。

geometry.setIndex(...)
geometry.addAttribute('index',...)

总结

这一节我们主要讲了以下内容:

  • BufferGeometry的特点
  • BufferGeometry使用示例
  • BufferGeometry在模型解析中的应用