前面我们绘制的物体要么是手动设置的顶点(比如简单的三角形),要么是程序生成的顶点(比如绘制的地球)。还有一种就是加载3D建模软件建好的3D模型。常见的3D模型格式有很多:.OBJ, .STL, .PLY, .fbx, .x 等等。当然加载这些3D模型有成熟的第三方库,如Assimp,我们自己手动写代码解析这些模型的格式是为了熟悉模型加载的流程,为了以后在使用第三方库的时出错了,或者加载的模型和预期的结果不同时,方便排错。
本节我们来介绍如何加载STL格式的3D模型。这种格式很简单,只包含顶点数据位置数据以及三角面片的法线数据,其他的数据格式还可能包括:纹理坐标数据,纹理贴图数据,甚至是动画数据,这需要在解析的时候建立相应的数据结构来存储这些数据,特别是动画数据,往往和你的引擎动画机制相关,你需要将模型文件中的动画数据加载为你引擎能够工作的数据结构,否则你读出来动画数据,你也使用不了。
原先我是打算加载OBJ模型的,因为OBJ文件中包含物体的顶点,法线,还有纹理数据。但是应一位小伙伴的请求,这节先加载个STL文件吧。
![](https://i-blog.csdnimg.cn/blog_migrate/f02d87d634d487c52cb42326ad0d2d0c.png)
STL文件格式
STL (STereoLithography, 立体光刻)是由3D Systems软件公司创立、原本用于立体光刻计算机辅助设计软件的文件格式。
STL文件仅描述三维物体的表面几何形状,没有颜色、材质贴图或其它常见三维模型的属性。
STL文件两种格式,ASCII STL和Binary STL。说白了,就是一个是文本数据,一个是二进制数据。
STL的ASCII格式
ASCII STL,每一个facet由7行数据组成,outer loop后面三个顶点的顺序沿法线矢量逆时针排序,格式如下:
solid name // 文件名及文件路径
facet normal ni nj nk // 三角形法向量的三个分量
outer loop
vertex v1x v1y v1z // 第一个顶点坐标
vertex v2x v2y v2z // 第二个顶点坐标
vertex v3x v3y v3z // 第三个顶点坐标
endloop
endfacet // 完成一个三角形的定义
endsolid name // 整个文件结束
STL的二进制格式
Binary STL,起始有80个字节文件头用于存储文件名,紧接4个字节表示三角形数量,而每个三角面片占用固定的50个字节,3个4字节浮点数(法线矢量),3个4字节浮点数(第一个顶点坐标),3个4字节浮点数(第二个顶点坐标),3个4字节浮点数(第三个顶点坐标),接着2个字节描述三角形基本属性,那么一个完整的二进制STL文件的字节大小就是三角形面数乘50再加上84字节,格式如下:
UINT8[80] – Header // 文件头
UINT32 – Number of triangles // 三角形数量
foreach triangle
REAL32[3] – Normal vector // 法线矢量
REAL32[3] – Vertex 1 // 第一个顶点坐标
REAL32[3] – Vertex 2 // 第二个顶点坐标
REAL32[3] – Vertex 3 // 第三个顶点坐标
UINT16 – Attribute byte count // 文件属性
end
加载STL二进制文件
说实话C++读取文件文件太费劲了,用C#就方便多了。我们这里读一下二进制文件吧,按照文件字节读取就行。读文本文件就作为课后作业吧,照葫芦画瓢的事。其实就是因为太麻烦了。
![](https://i-blog.csdnimg.cn/blog_migrate/48bf3de036da3885ee64b0bb4bdf8a79.png)
因为我们的引擎还没有添加光照,所以只显示了线框模型和纯色模型,看起来并没有立体感。
![](https://i-blog.csdnimg.cn/blog_migrate/6053886c920ef8e30d4a67552fad5a1d.png)
ok。本节结束。