把整个源码梳理了之后,还是决定从 core 部分看起,先核心后外围,基本做到逐块阅读,部分要做到逐行阅读。

先从一个比较关键的geometry看起吧,毕竟是整个three中绘制形体的关键。


属性

一些属性比较简单:

  • uuid
  • name
  • type

id:

  1. Object.defineProperty( this, 'id', { value: _geometryId += 2 } );

defineProperty 使id只读,不过这里有个有趣的地方,geometry的id都是偶数,而buffer geometry的id是奇数,这个可能会在后续有的地方会用到来区分两种geometry吧。

紧接着有四个数组存储最基本的点与面的信息:

  • vertices:一维数组,元素类型为vertex3
  • colors
  • faces:一维数组,类型是Face3,存储的是vertices的indices
  • faceVertexUvs

就直观来看不难理解,后续结合添加vertex或face的方法来看。

接着有几个属性暂时不太明白:

  • morphTargets
  • morphNormals
  • skinWeights
  • skinIndices

应该是动画相关的,等到看动画部分的时候再看(不过这个优先级很低了)

geometry中还有 boundingBoxboundingSphere 两个属性

lineDistances:
也是一个属性,用来存储每条边的长度

This is required for LineDashedMaterial to render correctly.

除此之外,还有一系列标识是不是要更新相关属性的状态flag:

  • elementsNeedUpdate

这些flag应该会在后续的方法中用到

Face3

由于geometry中faces是一个个的 Face3 对象,那么就先瞧一瞧这个 Face3 是啥

大概就是三个vertex的index,然后在加上normal和color的信息,这里的normal,既可以是一个 Vector3 的类型,表示整个面的normal,即三个vertex都是同样的normal,或者一个array,每个点的normal不同;color同理。

除此之外还有 materialIndex ,暂时不知道有什么用。

方法

变换操作

首先有一系列的变换操作

applyMatrix4 :更新vertex和normal,如果有boundingbox或sphere,也需要重新计算
之后的多个变换是纯粹的几何操作,都是算出transform matrix然后apply:

  • rotateX/Y/Z
  • translate
  • scale
  • lookAt

fromBufferGeometry

这是 BufferGeometryGeometry 的转换,大致就是从typed array到Three自己的数据结构的过程,其中又一点需要注意的是, BufferGeometry 似乎是有groups这个概念的, Geometry 中没有,这个之后看的时候在看看具体是什么样的,现在看代码的话,应该是类似一种flatten的方式,不区分group。

center , normalize

这个和基础的几何体的操作无异,只不过是分别用boundingbox和boundingsphere来做

computeFaceNormals , computeVertexNormals , computeFlatVertexNormals

face normal的计算,直接叉乘两个向量就可以了

vertex normal是根据邻接的面的向量平均得到的

计算时需要区分是不是带面积权重,如果是areaWeighted的话,就会乘以面的三角形面积(其实就是叉乘得出面的法向量的时候,不用normalize),否则就是单位法向量

flat vertex normal的话,就是直接用face的normal作为vertex normal

computeMorphNormals

TODO:动画相关的,之后再说

computeBoundingBox , computeBoundingSphere

计算包围盒或包围球,相对简单,几何运算,调用math里的即可

merge , mergeMesh , mergeVertices

先看 mergeVertices :
将geometry里重合的点融合,还是用hashmap,找到位置相近到可以视为一个点的点
因为点的变动,face也要相应作出调整
这里还有一个操作是,如果face中两个点重合,那么这个面也就没有了意义,需要删掉
删除的话,就是遍历标记然后删除

merge
也很清晰,就是把两个geometry的种种信息concate到一起,其中支持变换矩阵和material的indexOffset

mergeMesh :
mesh中包含geometry,transformation matrix等信息,其实就是提取出mesh中的geometry和matrix,然后merge起来

setFromPoints

可以生成只有点的一个geometry
(面的话,估计要自己在faces里push吧)

sortFacesByMaterialIndex

根据材质的序号来排序,同时也要注意更新uv信息

toJSON

序列化的函数,看看里边有没有什么值得注意的地方

vertex3都flatten掉

面的话序列化的时候需要一些元信息,这里用一个8位的bit来表示不同的信息,读取的时候根据是否有相关信息从flatten的face中读取
这里的face存储的都是index的信息,包括vertices,colors,normals,都分别存储,然后在faces中存储对应的index来获取

在设置index的时候,用了hash map来提升效率,在 getColorIndex() 等函数中

dispose

销毁geometry,这个触发一个时间,监听的话,在geometry中,应该是清理一些attribute,buffer等数据