把整个源码梳理了之后,还是决定从 core 部分看起,先核心后外围,基本做到逐块阅读,部分要做到逐行阅读。
先从一个比较关键的geometry看起吧,毕竟是整个three中绘制形体的关键。
属性
一些属性比较简单:
- uuid
- name
- type
id:
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中还有 boundingBox 和 boundingSphere 两个属性
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
这是 BufferGeometry 到 Geometry 的转换,大致就是从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等数据
