1.概述stl文件用三維網(wǎng)格表現(xiàn)實(shí)體模型,stl文件有兩種:一種是ASCII明碼格式,另一種是二進(jìn)制格式。(以下摘自百度百科)
2.ASCII格式在STL文件中的三角面片的信息單元 facet 是一個(gè)帶矢量方向的三角面片,STL三維模型就是由一系列這樣的三角面片構(gòu)成。
整個(gè)STL文件的首行給出了文件路徑及文件名。
在一個(gè) STL文件中,每一個(gè)facet由7 行數(shù)據(jù)組成,
facet normal 是三角面片指向?qū)嶓w外部的法矢量坐標(biāo),
outer loop 說明隨后的3行數(shù)據(jù)分別是三角面片的3個(gè)頂點(diǎn)坐標(biāo),3頂點(diǎn)沿指向?qū)嶓w外部的法矢量方向逆時(shí)針排列。
- solidfilenamestl//文件路徑及文件名
- facetnormalxyz//三角面片法向量的3個(gè)分量值
- outerloop
- vertexxyz//三角面片第一個(gè)頂點(diǎn)坐標(biāo)
- vertexxyz//三角面片第二個(gè)頂點(diǎn)坐標(biāo)
- vertexxyz//三角面片第三個(gè)頂點(diǎn)坐標(biāo)
- endloop
- endfacet//完成一個(gè)三角面片定義
- ......//其他facet
- endsolidfilenamestl//整個(gè)STL文件定義結(jié)束
復(fù)制代碼3.二進(jìn)制格式 二進(jìn)制STL文件用固定的字節(jié)數(shù)來給出三角面片的幾何信息。
文件起始的80個(gè)字節(jié)是文件頭,用于存貯文件名;
緊接著用 4 個(gè)字節(jié)的整數(shù)來描述模型的三角面片個(gè)數(shù),
后面逐個(gè)給出每個(gè)三角面片的幾何信息。每個(gè)三角面片占用固定的50個(gè)字節(jié),依次是:
3個(gè)4字節(jié)浮點(diǎn)數(shù)(角面片的法矢量)
3個(gè)4字節(jié)浮點(diǎn)數(shù)(1個(gè)頂點(diǎn)的坐標(biāo))
3個(gè)4字節(jié)浮點(diǎn)數(shù)(2個(gè)頂點(diǎn)的坐標(biāo))
3個(gè)4字節(jié)浮點(diǎn)數(shù)(3個(gè)頂點(diǎn)的坐標(biāo))
三角面片的最后2個(gè)字節(jié)用來描述三角面片的屬性信息。
一個(gè)完整二進(jìn)制STL文件的大小為三角形面片數(shù)乘以 50再加上84個(gè)字節(jié)。 - UINT8//Header//文件頭
- UINT32//Numberoftriangles//三角面片數(shù)量
- //foreachtriangle(每個(gè)三角面片中)
- REAL32[3]//Normalvector//法線矢量
- REAL32[3]//Vertex1//頂點(diǎn)1坐標(biāo)
- REAL32[3]//Vertex2//頂點(diǎn)2坐標(biāo)
- REAL32[3]//Vertex3//頂點(diǎn)3坐標(biāo)
- UINT16//Attributebytecountend//文件屬性統(tǒng)計(jì)
復(fù)制代碼
處理過程當(dāng)開始processFiles時(shí),會(huì)將files中命名的stl文件存貯到model的meshs中。model是一個(gè)PrintObject*
首先,loadModelSTL根據(jù)stl的類型選擇調(diào)用loadModelSTL_binary或者loadModelSTL_ascii,得到meshs。然后用processModel對(duì)Meshs處理,將結(jié)果存入storage。
源碼解析- bool processFiles(const std::vector<std::string> &files)//位于fffProcessor.h的line74
復(fù)制代碼中:
- FMatrix3x3 matrix; //變換用的矩陣,沒什么用
- if (!loadMeshFromFile(model, filename.c_str(), matrix))
- {
- logError("Failed to load model: %s\n", filename.c_str());
- return false;
- }
復(fù)制代碼調(diào)用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;
- }
復(fù)制代碼而loadModelSTL首先讀5個(gè)字節(jié)到buffer中,根據(jù)buffer是否為”solid”判斷stl文件類型,分別調(diào)用
loadModelSTL_ascii和loadModelSTL_binary函數(shù)。
- 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); //矩陣轉(zhuǎn)換vertex到(v0 v1 v2)
- break;
- case 2:
- v1 = matrix.apply(vertex);
- break;
- case 3:
- v2 = matrix.apply(vertex);
- mesh->addFace(v0, v1, v2); //到這里,將stl轉(zhuǎn)換成了mesh
- n = 0;
- break;
- }
- }
- }
- ……
復(fù)制代碼提取出了三維點(diǎn)的信息,存到vertex中,再通過與矩陣matrix(其實(shí)是單位矩陣,結(jié)果一樣)相乘進(jìn)行坐標(biāo)變換,得到三個(gè)點(diǎn)后組成三維面片,
使用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); //矩陣轉(zhuǎn)換vertex到(v0 v1 v2)
- break;
- case 2:
- v1 = matrix.apply(vertex);
- break;
- case 3:
- v2 = matrix.apply(vertex);
- mesh->addFace(v0, v1, v2); //到這里,將stl轉(zhuǎn)換成了mesh
- n = 0;
- break;
- }
- }
- }
- ……
- 提取出了三維點(diǎn)的信息,存到vertex中,再通過與矩陣matrix(其實(shí)是單位矩陣,結(jié)果一樣)相乘進(jìn)行坐標(biāo)變換,得到三個(gè)點(diǎn)后組成三維面片,
- 使用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字節(jié)是文件頭
- {
- 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) //三個(gè)頂點(diǎn)坐標(biāo)
- {
- 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) //三角形面片數(shù)屬性信息,或許可以用來表示材質(zhì)??
- {
- fclose(f);
- return false;
- }
- }
- ……
復(fù)制代碼這樣,stl中得數(shù)據(jù)完全轉(zhuǎn)移到model.meshs中了。
|
|
你可能喜歡
拓竹Bambu Lab A1 mini測(cè)評(píng):這臺(tái)3D打印機(jī)
變廢為寶:通過固相制造將鋁廢料轉(zhuǎn)化為3D打
新突破:基于聲波的3D打印技術(shù)——全息直聲
一篇帶你讀懂:金屬3D打印在航空航天領(lǐng)域的
推薦課程
神奇的3D打印
SLA3D打印工藝全套培訓(xùn)課程 - 軟件篇
3D打印月球燈視頻教程 包括完整貼圖建模流
【原創(chuàng)發(fā)布】Cura軟件修改二次開發(fā)定制視頻