1.概述stl文件用三维网格表现实体模型,stl文件有两种:一种是ASCII明码格式,另一种是二进制格式。(以下摘自百度百科)
2.ASCII格式在STL文件中的三角面片的信息单元 facet 是一个带矢量方向的三角面片,STL三维模型就是由一系列这样的三角面片构成。
整个STL文件的首行给出了文件路径及文件名。
在一个 STL文件中,每一个facet由7 行数据组成,
facet normal 是三角面片指向实体外部的法矢量坐标,
outer loop 说明随后的3行数据分别是三角面片的3个顶点坐标,3顶点沿指向实体外部的法矢量方向逆时针排列。
- solidfilenamestl//文件路径及文件名
- facetnormalxyz//三角面片法向量的3个分量值
- outerloop
- vertexxyz//三角面片第一个顶点坐标
- vertexxyz//三角面片第二个顶点坐标
- vertexxyz//三角面片第三个顶点坐标
- endloop
- endfacet//完成一个三角面片定义
- ......//其他facet
- endsolidfilenamestl//整个STL文件定义结束
复制代码3.二进制格式 二进制STL文件用固定的字节数来给出三角面片的几何信息。
文件起始的80个字节是文件头,用于存贮文件名;
紧接着用 4 个字节的整数来描述模型的三角面片个数,
后面逐个给出每个三角面片的几何信息。每个三角面片占用固定的50个字节,依次是:
3个4字节浮点数(角面片的法矢量)
3个4字节浮点数(1个顶点的坐标)
3个4字节浮点数(2个顶点的坐标)
3个4字节浮点数(3个顶点的坐标)
三角面片的最后2个字节用来描述三角面片的属性信息。
一个完整二进制STL文件的大小为三角形面片数乘以 50再加上84个字节。 - UINT8//Header//文件头
- UINT32//Numberoftriangles//三角面片数量
- //foreachtriangle(每个三角面片中)
- REAL32[3]//Normalvector//法线矢量
- REAL32[3]//Vertex1//顶点1坐标
- REAL32[3]//Vertex2//顶点2坐标
- REAL32[3]//Vertex3//顶点3坐标
- UINT16//Attributebytecountend//文件属性统计
复制代码
处理过程当开始processFiles时,会将files中命名的stl文件存贮到model的meshs中。model是一个PrintObject*
首先,loadModelSTL根据stl的类型选择调用loadModelSTL_binary或者loadModelSTL_ascii,得到meshs。然后用processModel对Meshs处理,将结果存入storage。
源码解析- bool processFiles(const std::vector<std::string> &files)//位于fffProcessor.h的line74
复制代码中:
- FMatrix3x3 matrix; //变换用的矩阵,没什么用
- if (!loadMeshFromFile(model, filename.c_str(), matrix))
- {
- logError("Failed to load model: %s\n", filename.c_str());
- return false;
- }
复制代码调用loadMeshFromFile.
- bool loadMeshFromFile(PrintObject* object, const char* filename, FMatrix3x3& matrix)
- {
- const char* ext = strrchr(filename, '.');
- if (ext && (strcmp(ext, ".stl") == 0 || strcmp(ext, ".STL") == 0))
- {
- object->meshes.emplace_back(object);
- return loadModelSTL(&object->meshes[object->meshes.size()-1], filename, matrix);
- }
- return false;
- }
复制代码而loadModelSTL首先读5个字节到buffer中,根据buffer是否为”solid”判断stl文件类型,分别调用
loadModelSTL_ascii和loadModelSTL_binary函数。
- bool loadModelSTL_ascii(Mesh* mesh, const char* filename, FMatrix3x3& matrix)
- {
- FILE* f = fopen(filename, "rt");
- char buffer[1024];
- FPoint3 vertex;
- int n = 0;
- Point3 v0(0,0,0), v1(0,0,0), v2(0,0,0);
- while(fgets_(buffer, sizeof(buffer), f))
- {
- if (sscanf(buffer, " vertex %f %f %f", &vertex.x, &vertex.y, &vertex.z) == 3)
- {
- n++;
- switch(n)
- {
- case 1:
- v0 = matrix.apply(vertex); //矩阵转换vertex到(v0 v1 v2)
- break;
- case 2:
- v1 = matrix.apply(vertex);
- break;
- case 3:
- v2 = matrix.apply(vertex);
- mesh->addFace(v0, v1, v2); //到这里,将stl转换成了mesh
- n = 0;
- break;
- }
- }
- }
- ……
复制代码提取出了三维点的信息,存到vertex中,再通过与矩阵matrix(其实是单位矩阵,结果一样)相乘进行坐标变换,得到三个点后组成三维面片,
使用addFace添加到mesh中。
- bool loadModelSTL_ascii(Mesh* mesh, const char* filename, FMatrix3x3& matrix)
- {
- FILE* f = fopen(filename, "rt");
- char buffer[1024];
- FPoint3 vertex;
- int n = 0;
- Point3 v0(0,0,0), v1(0,0,0), v2(0,0,0);
- while(fgets_(buffer, sizeof(buffer), f))
- {
- if (sscanf(buffer, " vertex %f %f %f", &vertex.x, &vertex.y, &vertex.z) == 3)
- {
- n++;
- switch(n)
- {
- case 1:
- v0 = matrix.apply(vertex); //矩阵转换vertex到(v0 v1 v2)
- break;
- case 2:
- v1 = matrix.apply(vertex);
- break;
- case 3:
- v2 = matrix.apply(vertex);
- mesh->addFace(v0, v1, v2); //到这里,将stl转换成了mesh
- n = 0;
- break;
- }
- }
- }
- ……
- 提取出了三维点的信息,存到vertex中,再通过与矩阵matrix(其实是单位矩阵,结果一样)相乘进行坐标变换,得到三个点后组成三维面片,
- 使用addFace添加到mesh中。
- bool loadModelSTL_binary(Mesh* mesh, const char* filename, FMatrix3x3& matrix)
- {
- FILE* f = fopen(filename, "rb");
- char buffer[80];
- uint faceCount;
- //Skip the header
- if (fread(buffer, 80, 1, f) != 1) //前80字节是文件头
- {
- fclose(f);
- return false;
- }
- //Read the face count
- if (fread(&faceCount, sizeof(uint), 1, f) != 1)
- {
- fclose(f);
- return false;
- }
- //For each face read:
- //float(x,y,z) = normal, float(X,Y,Z)*3 = vertexes, uint16_t = flags
- for(unsigned int i=0;i<faceCount;i++)
- {
- if (fread(buffer, sizeof(float) * 3, 1, f) != 1) //角面片的法矢量
- {
- fclose(f);
- return false;
- }
- float v[9];
- if (fread(v, sizeof(float) * 9, 1, f) != 1) //三个顶点坐标
- {
- fclose(f);
- return false;
- }
- Point3 v0 = matrix.apply(FPoint3(v[0], v[1], v[2]));
- Point3 v1 = matrix.apply(FPoint3(v[3], v[4], v[5]));
- Point3 v2 = matrix.apply(FPoint3(v[6], v[7], v[8]));
- mesh->addFace(v0, v1, v2);
- if (fread(buffer, sizeof(uint16_t), 1, f) != 1) //三角形面片数属性信息,或许可以用来表示材质??
- {
- fclose(f);
- return false;
- }
- }
- ……
复制代码这样,stl中得数据完全转移到model.meshs中了。
|
|
你可能喜欢
拓竹Bambu Lab A1 mini测评:这台3D打印机
变废为宝:通过固相制造将铝废料转化为3D打
新突破:基于声波的3D打印技术——全息直声
一篇带你读懂:金属3D打印在航空航天领域的
推荐课程
神奇的3D打印
SLA3D打印工艺全套培训课程 - 软件篇
3D打印月球灯视频教程 包括完整贴图建模流
【原创发布】Cura软件修改二次开发定制视频