BufferGeometry应该算是一种对机器友好,但是API不怎么友好的一种Geometry,适合对性能要求比较高的时候。

BufferGeometry应该是将所有的信息放到了 attributes 中,而不是像geometry里有各种各样的vertices,faces之类的。

其中attributes的设置基本都是对 BufferAttribute 的操作,所以来瞧一瞧。

BufferAttribute

接受一个typedarray的参数,直接存储的就是比较适合gpu的数据结构。
itemSize 比如三角形为3,这样可以用来定位到对应的元素。
除此之外还有一个 normalized flag,具体后边看到的时候说。

不过值得注意的是有:
usage
该buffer中的data的使用,直接与WebGL相关,static draw,dynamic draw之类的

updateRange
应该是更新的时候考虑更新哪个range,具体使用到的时候看

version
标识版本,有一个只写的属性 needsUpdate ,设为true即表示这个buffer需要更新了,因此version+1

有许多get与set函数,可以自由的获取对应的元素

onUpload 按照文档所说,是应用在向GPU传输数据时使用,这个后续需要回顾

除此之外, BufferAttribute.js export了许多其它类型的 BufferAttribute
以Uint8为例,是这样构造的:

  1. function Uint8BufferAttribute( array, itemSize, normalized ) {
  2. BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );
  3. }
  4. Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );
  5. Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;

应该就是为了封装一下,能够让用户直接用对应的类型而不用自己new一个对应的typearray放进去

index

对应到WebGL的indexbuffer,也是 BufferAttribute 类型,可以直接传输到WebGL相关的绑定buffer函数中

attributes

用key-value来存储所有的attributes,这个attributes就是上述的,用来存储数据的地方
有对应的 setAttributegetAttributedeleteAttribute

groups

对于一个geometry,分为多个group,其中除了 startcount 这两个来定位外,还有一个 materialIndex ,是因为划分group是为了对于每个group使用不同的材质,所以这个设计还是很不容易的

drawRange

有时候可能只想画几何体的一部分,这里three也考虑到了,设定了 startcount
不过这个在哪里用到在该部分没有体现,应该是在renderer中吧

userData

TODO:这个 userData 在文件中并没有用到,也没有对应的设置函数,应该就是一些用户自定义的data可以放进去吧,直接赋值就可以,Three只是存下来,不做更多处理

Methods

BufferGeometry 中的大部分方法和 Geometry 中相同
包括一些util的函数: clone , toJSON , copy , dispose
变换的函数: applyMatrix4 , rotateX , translate

除此之外,有一系列的赋值的函数,其中,有一部分涉及 GeometryBufferGeometry 的转换,用到了 DirectGeometry

DirectGeometry

computeGroups
这里算是对group怎么生成的有一个比较清楚的了解,基本上,把相邻的,material相同的放在一起,形成一个组

其它的好像没有什么特别要注意的,也就是数据格式的转换了

因此, Geometry 先转化为 DirectGeometry , 在转换为 BufferGeometry

fromGeometry: function ( geometry ) {
    geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );
    return this.fromDirectGeometry( geometry.__directGeometry );
}

updateFromObject

update的时候会先check DirectGeometry ,如果没有则生成
这时候提到了上一篇中geometry中的 xxxNeedUpdate 的Flag,这就用在这里,只有对应flag是true的时候,才会覆盖到对应的attribute中,这是一种效率上的优化

merge

两个 BufferGeometry merge起来,从offset开始,放geometry2,如果超出了geometry1的长度,忽略

toNoIndexed

把有index的数据变为无index的,里边主要用到了一个工具函数: convertBufferAttribute ,将index指向的data对应填充


整体来看, BufferGeometry 不像 Geometry , 更多的从WebGL的角度出发,从buffer, attribute这些用词就可以看出
这种将Buffer中的数据整合起来作为BufferGeometry,同时也可以从普通的Geometry中转换过来的思想还是很值得学习的。