cura-engine為開源3D打印軟件cura的核心引擎代碼,詳細(xì)介紹參看github主頁?,F(xiàn)在學(xué)習(xí)的是一個簡單版的https://github.com/repetier/CuraEngine,最新版https://github.com/Ultimaker/CuraEngine添加了很多功能,尤其通信部分有點(diǎn)難懂。本系列文章主要是為了保存本人閱讀記憶,一面吃過就忘,所以完全按照閱讀順序編寫,故稍有凌亂。下面直接進(jìn)入學(xué)習(xí)。

  首先看fffProcessor.h中的讀取STL文件部分:

函數(shù)ProsessFile:功能:STL文件讀取prepareModel、生成切片數(shù)據(jù)processSliceData、生成Gcode writeGcode。(log函數(shù)現(xiàn)在濾去,單獨(dú)研究)

函數(shù)prepareModel:功能:STL文件讀取、優(yōu)化STL文件、生成LayerParts。涉及到的類:class SimpleModel、class SimpleVolume、class OptimizedModel、cura class Slicer、cura class SupportStorage

文件讀取的實現(xiàn):

 

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 1  if (files.size() == 1 && files[0][0] == '$') 2         { 3             const char *input_filename = files[0].c_str(); 4             model = new SimpleModel(); 5             for(unsigned int n=0; input_filename[n]; n++) 6             { 7                 model->volumes.push_back(SimpleVolume()); 8                 SimpleVolume* volume = &model->volumes[model->volumes.size()-1]; 9                 guiSocket.sendNr(GUI_CMD_REQUEST_MESH);10 11                 int32_t vertexCount = guiSocket.recvNr();12                 int pNr = 0;13                 cura::log("Reading mesh from socket with %i vertexes\n", vertexCount);14                 Point3 v[3];15                 while(vertexCount)16                 {17                     float f[3];18                     guiSocket.recvAll(f, 3 * sizeof(float));19                     FPoint3 fp(f[0], f[1], f[2]);20                     v[pNr++] = config.matrix.apply(fp);21                     if (pNr == 3)22                     {23                         volume->addFace(v[0], v[1], v[2]);24                         pNr = 0;25                     }26                     vertexCount--;27                 }28             }29         }else{30             model = new SimpleModel();31             for(unsigned int i=0;i < files.size(); i++) {32                 if(files[i] == "-")33                     model->volumes.push_back(SimpleVolume());34                 else {35                     cura::log("Loading %s from disk...\n", files[i].c_str());36                     SimpleModel *test = loadModelFromFile(model,files[i].c_str(), config.matrix);37                     if(test == nullptr) { // error while reading occurred38                         cura::logError("Failed to load model: %s\n", files[i].c_str());39                         return false;40                     }41                 }42             }43         }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 

  此處讀入文件來源有兩種,一是通過guiSocket從通信中接收的數(shù)據(jù),二是從硬盤中讀取STL文件,通信部分暫且不提,先學(xué)習(xí)后者。這就到了loadModelFromFile函數(shù),此函數(shù)名字就已透露其作用-讀文件。代碼在文件modelFile.cpp中,如下:

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 1 SimpleModel* loadModelFromFile(SimpleModel *m,const char* filename, FMatrix3x3& matrix) 2 { 3     const char* ext = strrchr(filename, '.'); 4     if (ext && stringcasecompare(ext, ".stl") == 0) 5     { 6         return loadModelSTL(m,filename, matrix); 7     } 8     if (filename[0] == '#' && binaryMeshBlob != nullptr) 9     {10         while(*filename == '#')11         {12             filename++;13 14             m->volumes.push_back(SimpleVolume());15             SimpleVolume* vol = &m->volumes[m->volumes.size()-1];16             int32_t n, pNr = 0;17             if (fread(&n, 1, sizeof(int32_t), binaryMeshBlob) < 1)18                 return nullptr;19             cura::log("Reading mesh from binary blob with %i vertexes\n", n);20             Point3 v[3];21             while(n)22             {23                 float f[3];24                 if (fread(f, 3, sizeof(float), binaryMeshBlob) < 1)25                     return nullptr;26                 FPoint3 fp(f[0], f[1], f[2]);27                 v[pNr++] = matrix.apply(fp);28                 if (pNr == 3)29                 {30                     vol->addFace(v[0], v[1], v[2]);31                     pNr = 0;32                 }33                 n--;34             }35         }36         return m;37     }38     return nullptr;39 }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

  此處可以看出分兩種情況,一是讀取.stl后綴的STL文件,二是讀取blob(binary large object)二進(jìn)制大對象,blob同樣來源與硬盤數(shù)據(jù)文件,至于到底是神馬,還不知道。

1  m->volumes.push_back(SimpleVolume());2             SimpleVolume* vol = &m->volumes[m->volumes.size()-1];

  代碼作者超級喜歡這種先推入一個初始的幾何體,然后在通過引用取出到vol,再賦值,貌似我一般都是相反的順序,不知這種有何優(yōu)勢。下面還是看一看函數(shù)LoadModelSTL()吧,就在正上方。

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

 1 SimpleModel* loadModelSTL(SimpleModel *m,const char* filename, FMatrix3x3& matrix) 2 { 3     FILE* f = fopen(filename, "r"); 4     char buffer[6]; 5     if (f == nullptr) 6         return nullptr; 7  8     if (fread(buffer, 5, 1, f) != 1) 9     {10         fclose(f);11         return nullptr;12     }13     fclose(f);14 15     buffer[5] = '\0';16     if (stringcasecompare(buffer, "solid") == 0)17     {18         SimpleModel* asciiModel = loadModelSTL_ascii(m, filename, matrix);19         if (!asciiModel)20             return nullptr;21 22         // This logic is used to handle the case where the file starts with23         // "solid" but is a binary file.24         if (m->volumes[m->volumes.size()-1].faces.size() < 1)25         {26             m->volumes.erase(m->volumes.end() - 1);27             return loadModelSTL_binary(m, filename, matrix);28         }29         return asciiModel;30     }31     return loadModelSTL_binary(m, filename, matrix);32 }

大數(shù)據(jù)培訓(xùn),云培訓(xùn),數(shù)據(jù)挖掘培訓(xùn),云計算培訓(xùn),高端軟件開發(fā)培訓(xùn),項目經(jīng)理培訓(xùn)

  此函數(shù)同樣分兩種情況(看來碼農(nóng)都喜歡二分)。很簡單,讀入開頭5個字母,如果是solid,則按Ascii讀入,否則按照二進(jìn)制讀入。然而作者心思謹(jǐn)慎,開頭是solid時也有二進(jìn)制情況,所以檢查一下讀入最后一個幾何體如果一個面都沒有,那就錯了唄,滾回用二進(jìn)制重新讀。

  函數(shù)loadModelSTL_ascii(SimpleModel *m,const char* filename, FMatrix3x3& matrix)

   和loadModelSTL_binary(SimpleModel *m,const char* filename, FMatrix3x3& matrix)是我們這部分的最后一站,代碼不是很難,但有個小小的問題,matrix到底是干什么用的。這個matrix來自最初的函數(shù)loadModelFromFile(model,files[i].c_str(), config.matrix);config據(jù)我目前所知是整個系統(tǒng)一些參數(shù)設(shè)置的一個匯總類class ConfigSettings。這里面保存了大量的參數(shù)設(shè)置。這個matrix是的用途就是每個讀入的坐標(biāo)與其相乘,結(jié)果再存入model->volume.faces,就是將幾何體坐標(biāo)根據(jù)需要做了個變換,至于變換的作用,現(xiàn)在還不清楚。

  至此,文件讀入功能結(jié)束,文中還有一些問題沒有解決,主要有l(wèi)og相關(guān)函數(shù),socket相關(guān)函數(shù)和config相關(guān),這些都是貫穿整個程序的,以后詳細(xì)學(xué)習(xí)。