[CC]Mesh文件保存

CC中有两个地方使用了文件保存,一个是MainWindow,另一个是ccCommandLineParser。

MainWindow的保存按钮关联的槽是doActionSaveFile()方法,实现了点云和Mesh的保存。

  1 void MainWindow::doActionSaveFile()
  2 {
  3     size_t selNum = m_selectedEntities.size();
  4     if (selNum == 0)
  5         return;
  6 
  7     ccHObject clouds("clouds");
  8     ccHObject meshes("meshes");
  9     ccHObject images("images");
 10     ccHObject polylines("polylines");
 11     ccHObject other("other");
 12     ccHObject otherSerializable("serializable");
 13     ccHObject::Container entitiesToDispatch;
 14     entitiesToDispatch.insert(entitiesToDispatch.begin(),m_selectedEntities.begin(),m_selectedEntities.end());
 15     ccHObject entitiesToSave;
 16     while (!entitiesToDispatch.empty())
 17     {
 18         ccHObject* child = entitiesToDispatch.back();
 19         entitiesToDispatch.pop_back();
 20 
 21         if (child->isA(CC_TYPES::HIERARCHY_OBJECT))
 22         {
 23             for (unsigned j=0; j<child->getChildrenNumber(); ++j)
 24                 entitiesToDispatch.push_back(child->getChild(j));
 25         }
 26         else
 27         {
 28             //we put the entity in the container corresponding to its type
 29             ccHObject* dest = 0;
 30             if (child->isA(CC_TYPES::POINT_CLOUD))
 31                 dest = &clouds;
 32             else if (child->isKindOf(CC_TYPES::MESH))
 33                 dest = &meshes;
 34             else if (child->isKindOf(CC_TYPES::IMAGE))
 35                 dest = &images;
 36             else if (child->isKindOf(CC_TYPES::POLY_LINE))
 37                 dest = &polylines;
 38             else if (child->isSerializable())
 39                 dest = &otherSerializable;
 40             else
 41                 dest = &other;
 42 
 43             assert(dest);
 44 
 45             //we don't want double insertions if the user has clicked both the father and child
 46             if (!dest->find(child->getUniqueID()))
 47             {
 48                 dest->addChild(child,ccHObject::DP_NONE);
 49                 entitiesToSave.addChild(child,ccHObject::DP_NONE);
 50             }
 51         }
 52     }
 53 
 54     bool hasCloud = (clouds.getChildrenNumber() != 0);
 55     bool hasMesh = (meshes.getChildrenNumber() != 0);
 56     bool hasImages = (images.getChildrenNumber() != 0);
 57     bool hasPolylines = (polylines.getChildrenNumber() != 0);
 58     bool hasSerializable = (otherSerializable.getChildrenNumber() != 0);
 59     bool hasOther = (other.getChildrenNumber() != 0);
 60 
 61     int stdSaveTypes =        static_cast<int>(hasCloud)
 62                         +    static_cast<int>(hasMesh)
 63                         +    static_cast<int>(hasImages)
 64                         +    static_cast<int>(hasPolylines)
 65                         +    static_cast<int>(hasSerializable);
 66     if (stdSaveTypes == 0)
 67     {
 68         ccConsole::Error("Can't save selected entity(ies) this way!");
 69         return;
 70     }
 71 
 72     //we set up the right file filters, depending on the selected
 73     //entities type (cloud, mesh, etc.).
 74     QStringList fileFilters;
 75     {
 76         const FileIOFilter::FilterContainer& filters = FileIOFilter::GetFilters();
 77         for (size_t i=0; i<filters.size(); ++i)
 78         {
 79             bool atLeastOneExclusive = false;
 80 
 81             //current I/O filter
 82             const FileIOFilter::Shared filter = filters[i];
 83 
 84             //does this filter can export one or several clouds?
 85             bool canExportClouds = true;
 86             if (hasCloud)
 87             {
 88                 bool isExclusive = true;
 89                 bool multiple = false;
 90                 canExportClouds = (        filter->canSave(CC_TYPES::POINT_CLOUD,multiple,isExclusive)
 91                                     &&    (multiple || clouds.getChildrenNumber() == 1) );
 92                 atLeastOneExclusive |= isExclusive;
 93             }
 94 
 95             //does this filter can export one or several meshes?
 96             bool canExportMeshes = true;
 97             if (hasMesh)
 98             {
 99                 bool isExclusive = true;
100                 bool multiple = false;
101                 canExportMeshes = (        filter->canSave(CC_TYPES::MESH,multiple,isExclusive)
102                                     &&    (multiple || meshes.getChildrenNumber() == 1) );
103                 atLeastOneExclusive |= isExclusive;
104             }
105 
106             //does this filter can export one or several polylines?
107             bool canExportPolylines = true;
108             if (hasPolylines)
109             {
110                 bool isExclusive = true;
111                 bool multiple = false;
112                 canExportPolylines = (    filter->canSave(CC_TYPES::POLY_LINE,multiple,isExclusive)
113                                     &&    (multiple || polylines.getChildrenNumber() == 1) );
114                 atLeastOneExclusive |= isExclusive;
115             }
116 
117             //does this filter can export one or several images?
118             bool canExportImages = true;
119             if (hasImages)
120             {
121                 bool isExclusive = true;
122                 bool multiple = false;
123                 canExportImages = (        filter->canSave(CC_TYPES::IMAGE,multiple,isExclusive)
124                                     &&    (multiple || images.getChildrenNumber() == 1) );
125                 atLeastOneExclusive |= isExclusive;
126             }
127 
128             //does this filter can export one or several other serializable entities?
129             bool canExportSerializables = true;
130             if (hasSerializable)
131             {
132                 //check if all entities have the same type
133                 {
134                     CC_CLASS_ENUM firstClassID = otherSerializable.getChild(0)->getUniqueID();
135                     for (unsigned j=1; j<otherSerializable.getChildrenNumber(); ++j)
136                     {
137                         if (otherSerializable.getChild(j)->getUniqueID() != firstClassID)
138                         {
139                             //we add a virtual second 'stdSaveType' so as to properly handle exlusivity
140                             ++stdSaveTypes;
141                             break;
142                         }
143                     }
144                 }
145 
146                 for (unsigned j=0; j<otherSerializable.getChildrenNumber(); ++j)
147                 {
148                     ccHObject* child = otherSerializable.getChild(j);
149                     bool isExclusive = true;
150                     bool multiple = false;
151                     canExportSerializables &= (        filter->canSave(child->getUniqueID(),multiple,isExclusive)
152                                                 &&    (multiple || otherSerializable.getChildrenNumber() == 1) );
153                     atLeastOneExclusive |= isExclusive;
154                 }
155             }
156 
157             bool useThisFilter =    canExportClouds
158                                 &&    canExportMeshes
159                                 &&    canExportImages
160                                 &&    canExportPolylines
161                                 &&    canExportSerializables
162                                 &&    (!atLeastOneExclusive || stdSaveTypes == 1);
163 
164             if (useThisFilter)
165             {
166                 QStringList ff = filter->getFileFilters(false);
167                 for (int j=0; j<ff.size(); ++j)
168                     fileFilters.append(ff[j]);
169             }
170         }
171     }
172 
173     //persistent settings
174     QSettings settings;
175     settings.beginGroup(ccPS::SaveFile());
176 
177     //default filter
178     QString selectedFilter = fileFilters.first();
179     if (hasCloud)
180         selectedFilter = settings.value(ccPS::SelectedOutputFilterCloud(),selectedFilter).toString();
181     else if (hasMesh)
182         selectedFilter = settings.value(ccPS::SelectedOutputFilterMesh(), selectedFilter).toString();
183     else if (hasImages)
184         selectedFilter = settings.value(ccPS::SelectedOutputFilterImage(), selectedFilter).toString();
185     else if (hasPolylines)
186         selectedFilter = settings.value(ccPS::SelectedOutputFilterPoly(), selectedFilter).toString();
187     
188     //default output path (+ filename)
189     QString currentPath = settings.value(ccPS::CurrentPath(),QApplication::applicationDirPath()).toString();
190     QString fullPathName = currentPath;
191     if (selNum == 1)
192     {
193         //hierarchy objects have generally as name: 'filename.ext (fullpath)'
194         //so we must only take the first part! (otherwise this type of name
195         //with a path inside perturbs the QFileDialog a lot ;))
196         QString defaultFileName(m_selectedEntities.front()->getName());
197         if (m_selectedEntities.front()->isA(CC_TYPES::HIERARCHY_OBJECT))
198         {
199             QStringList parts = defaultFileName.split(' ',QString::SkipEmptyParts);
200             if (parts.size() > 0)
201                 defaultFileName = parts[0];
202         }
203 
204         //we remove the extension
205         defaultFileName = QFileInfo(defaultFileName).baseName();
206 
207         if (!IsValidFileName(defaultFileName))
208         {
209             ccLog::Warning("[I/O] First entity's name would make an invalid filename! Can't use it...");
210             defaultFileName = "project";
211         }
212         
213         fullPathName += QString("/") + defaultFileName;
214     }
215 
216     //ask the user for the output filename
217     QString selectedFilename = QFileDialog::getSaveFileName(this,
218                                                             "Save file",
219                                                             fullPathName,
220                                                             fileFilters.join(s_fileFilterSeparator),
221                                                             &selectedFilter);
222 
223     if (selectedFilename.isEmpty())
224     {
225         //process cancelled by the user
226         return;
227     }
228 
229     //ignored items
230     if (hasOther)
231     {
232         ccConsole::Warning("[I/O] The following selected entites won't be saved:");
233         for (unsigned i=0; i<other.getChildrenNumber(); ++i)
234             ccConsole::Warning(QString("\t- %1s").arg(other.getChild(i)->getName()));
235     }
236 
237     CC_FILE_ERROR result = CC_FERR_NO_ERROR;
238     FileIOFilter::SaveParameters parameters;
239     {
240         parameters.alwaysDisplaySaveDialog = true;
241         parameters.parentWidget = this;
242     }
243     
244     //specific case: BIN format
245     if (selectedFilter == BinFilter::GetFileFilter())
246     {
247         if (selNum == 1)
248         {
249             result = FileIOFilter::SaveToFile(m_selectedEntities.front(),selectedFilename,parameters,selectedFilter);
250         }
251         else
252         {
253             //we'll regroup all selected entities in a temporary group
254             ccHObject tempContainer;
255             ConvertToGroup(m_selectedEntities,tempContainer,ccHObject::DP_NONE);
256             if (tempContainer.getChildrenNumber())
257             {
258                 result = FileIOFilter::SaveToFile(&tempContainer,selectedFilename,parameters,selectedFilter);
259             }
260             else
261             {
262                 ccLog::Warning("[I/O] None of the selected entities can be saved this way...");
263                 result = CC_FERR_NO_SAVE;
264             }
265         }
266     }
267     else if (entitiesToSave.getChildrenNumber() != 0)
268     {
269         //ignored items
270         /*if (hasSerializable)
271         {
272             if (!hasOther)
273                 ccConsole::Warning("[I/O] The following selected entites won't be saved:"); //display this warning only if not already done
274             for (unsigned i=0; i<otherSerializable.getChildrenNumber(); ++i)
275                 ccConsole::Warning(QString("\t- %1").arg(otherSerializable.getChild(i)->getName()));
276         }
277         //*/
278 
279         result = FileIOFilter::SaveToFile(    entitiesToSave.getChildrenNumber() > 1 ? &entitiesToSave : entitiesToSave.getChild(0),
280                                             selectedFilename,
281                                             parameters,
282                                             selectedFilter);
283     }
284 
285     //update default filters
286     if (hasCloud)
287         settings.setValue(ccPS::SelectedOutputFilterCloud(),selectedFilter);
288     if (hasMesh)
289         settings.setValue(ccPS::SelectedOutputFilterMesh(), selectedFilter);
290     if (hasImages)
291         settings.setValue(ccPS::SelectedOutputFilterImage(),selectedFilter);
292     if (hasPolylines)
293         settings.setValue(ccPS::SelectedOutputFilterPoly(), selectedFilter);
294 
295     //we update current file path
296     currentPath = QFileInfo(selectedFilename).absolutePath();
297     settings.setValue(ccPS::CurrentPath(),currentPath);
298     settings.endGroup();
299 }
void MainWindow::doActionSaveFile()

再看看ccCommandLineParser的Parse方法:

 1 int ccCommandLineParser::Parse(int nargs, char** args)
 2 {
 3     if (!args || nargs < 2)
 4     {
 5         assert(false);
 6         return EXIT_SUCCESS;
 7     }
 8 
 9     //reset default behavior(s)
10     s_loadParameters.autoComputeNormals = false;
11     s_MeshExportFormat = s_CloudExportFormat = BinFilter::GetFileFilter();
12     s_MeshExportExt = s_CloudExportExt = BinFilter::GetDefaultExtension();
13     s_precision = 12;
14     s_addTimestamp = true;
15     s_silentMode = false;
16     s_autoSaveMode = true;
17 
18     //load arguments
19     QStringList arguments;
20     {
21         for (int i=1; i<nargs; ++i) //'i=1' because first argument is always program executable file!
22             arguments.push_back(QString(args[i]));
23     }
24     assert(!arguments.empty());
25 
26     //specific command: silent mode (will prevent the console dialog from appearing!
27     if (IsCommand(arguments.front(),COMMAND_SILENT_MODE))
28     {
29         arguments.pop_front();
30         s_silentMode = true;
31     }
32 
33     QDialog consoleDlg;
34     if (!s_silentMode)
35     {
36         //show console
37         Ui_commandLineDlg commandLineDlg;
38         commandLineDlg.setupUi(&consoleDlg);
39         consoleDlg.show();
40         ccConsole::Init(commandLineDlg.consoleWidget, &consoleDlg);
41         s_loadParameters.parentWidget = &consoleDlg;
42     }
43 
44     //parse input
45     int result = ccCommandLineParser().parse(arguments,&consoleDlg);
46 
47     if (!s_silentMode)
48     {
49         if (result == EXIT_SUCCESS)
50             QMessageBox::information(&consoleDlg,"Processed finished","Job done");
51         else
52             QMessageBox::warning(&consoleDlg,"Processed finished","An error occurred! Check console");
53     }
54 
55     ccConsole::ReleaseInstance();
56 
57     return result;
58 }
int ccCommandLineParser::Parse(int nargs, char** args)

该方法被main函数调用。

  1 //主程序入口,十分重要
  2 int main(int argc, char **argv)
  3 {
  4     //QT initialiation
  5     qccApplication app(argc, argv);
  6 
  7     //Force 'english' local so as to get a consistent behavior everywhere
  8     QLocale::setDefault(QLocale::English);
  9 
 10 #ifdef Q_OS_LINUX
 11     // we reset the numeric locale. As suggested in documetation
 12     // see http://qt-project.org/doc/qt-5/qcoreapplication.html#locale-settings
 13     // Basically - from doc: - "On Unix/Linux Qt is configured to use the system locale settings by default.
 14     // This can cause a conflict when using POSIX functions, for instance,
 15     // when converting between data types such as floats and strings"
 16     setlocale(LC_NUMERIC,"C");
 17 #endif
 18 
 19 #ifdef USE_VLD
 20     VLDEnable();
 21 #endif
 22 
 23     //splash screen
 24     QSplashScreen* splash = 0;
 25     QTime splashStartTime;
 26 
 27     //Command line mode?
 28     bool commandLine = (argc > 1 && argv[1][0] == '-');
 29     
 30     //specific case: translation file selection
 31     int lastArgumentIndex = 1;
 32     QTranslator translator;
 33     if (commandLine && QString(argv[1]).toUpper() == "-LANG")
 34     {
 35         QString langFilename = QString(argv[2]);
 36         
 37         //Load translation file
 38         if (translator.load(langFilename, QCoreApplication::applicationDirPath()))
 39         {
 40             qApp->installTranslator(&translator);
 41         }
 42         else
 43         {
 44             QMessageBox::warning(0, QObject::tr("Translation"), QObject::tr("Failed to load language file '%1'").arg(langFilename));
 45         }
 46         commandLine = false;
 47         lastArgumentIndex = 3;
 48     }
 49 
 50     //command line mode
 51     if (!commandLine)
 52     {
 53         //OpenGL?
 54         if (!QGLFormat::hasOpenGL())
 55         {
 56             QMessageBox::critical(0, "Error", "This application needs OpenGL to run!");
 57             return EXIT_FAILURE;
 58         }
 59 
 60         //splash screen
 61         splashStartTime.start();
 62         QPixmap pixmap(QString::fromUtf8(":/CC/images/imLogoV2Qt.png"));
 63         splash = new QSplashScreen(pixmap,Qt::WindowStaysOnTopHint);
 64         splash->show();
 65         QApplication::processEvents();
 66     }
 67 
 68     //global structures initialization
 69     ccTimer::Init();
 70     FileIOFilter::InitInternalFilters(); //load all known I/O filters (plugins will come later!)
 71     ccNormalVectors::GetUniqueInstance(); //force pre-computed normals array initialization
 72     ccColorScalesManager::GetUniqueInstance(); //force pre-computed color tables initialization
 73 
 74     int result = 0;
 75 
 76     if (commandLine)
 77     {
 78         //command line processing (no GUI)
 79         result = ccCommandLineParser::Parse(argc,argv);
 80     }
 81     else
 82     {
 83         //main window init.
 84         MainWindow* mainWindow = MainWindow::TheInstance();
 85         if (!mainWindow)
 86         {
 87             QMessageBox::critical(0, "Error", "Failed to initialize the main application window?!");
 88             return EXIT_FAILURE;
 89         }
 90         mainWindow->show();
 91         QApplication::processEvents();
 92 
 93         if (argc > lastArgumentIndex)
 94         {
 95             if (splash)
 96                 splash->close();
 97 
 98             //any additional argument is assumed to be a filename --> we try to load it/them
 99             QStringList filenames;
100             for (int i = lastArgumentIndex; i<argc; ++i)
101                 filenames << QString(argv[i]);
102 
103             mainWindow->addToDB(filenames);
104         }
105         
106         if (splash)
107         {
108             //we want the splash screen to be visible a minimum amount of time (1000 ms.)
109             while (splashStartTime.elapsed() < 1000)
110             {
111                 splash->raise();
112                 QApplication::processEvents(); //to let the system breath!
113             }
114 
115             splash->close();
116             QApplication::processEvents();
117 
118             delete splash;
119             splash = 0;
120         }
121 
122         //let's rock!
123         try
124         {
125             result = app.exec();
126         }
127         catch(...)
128         {
129             QMessageBox::warning(0, "CC crashed!","Hum, it seems that CC has crashed... Sorry about that :)");
130         }
131     }
132 
133     //release global structures
134     MainWindow::DestroyInstance();
135     FileIOFilter::UnregisterAll();
136 
137 #ifdef CC_TRACK_ALIVE_SHARED_OBJECTS
138     //for debug purposes
139     unsigned alive = CCShareable::GetAliveCount();
140     if (alive > 1)
141     {
142         printf("Error: some shared objects (%u) have not been released on program end!",alive);
143         system("PAUSE");
144     }
145 #endif
146 
147     return result;
148 }
int main(int argc, char **argv)

两处最终都落实到FileIOFilter::SaveToFile()方法的调用。

 1 //保存文件
 2 CC_FILE_ERROR FileIOFilter::SaveToFile(    ccHObject* entities,
 3                                         const QString& filename,
 4                                         SaveParameters& parameters,
 5                                         QString fileFilter)
 6 {
 7     if (fileFilter.isEmpty())
 8         return CC_FERR_BAD_ARGUMENT;
 9     //获取对应的文件格式,存储器
10     Shared filter = GetFilter(fileFilter,false);
11     if (!filter)
12     {
13         ccLog::Error(QString("[Load] Internal error: no filter corresponds to filter '%1'").arg(fileFilter));
14         return CC_FERR_UNKNOWN_FILE;
15     }
16 
17     return SaveToFile(entities, filename, parameters, filter);
18 }
19 
20 CC_FILE_ERROR FileIOFilter::SaveToFile(    ccHObject* entities,
21                                         const QString& filename,
22                                         SaveParameters& parameters,
23                                         Shared filter)
24 {
25     if (!entities || filename.isEmpty() || !filter)
26         return CC_FERR_BAD_ARGUMENT;
27 
28     //if the file name has no extension, we had a default one!
29     QString completeFileName(filename);
30     if (QFileInfo(filename).suffix().isEmpty())
31         completeFileName += QString(".%1").arg(filter->getDefaultExtension());
32 
33     CC_FILE_ERROR result = CC_FERR_NO_ERROR;
34     try
35     {
36         result = filter->saveToFile(entities, completeFileName, parameters);
37     }
38     catch(...)
39     {
40         ccLog::Warning(QString("[I/O] CC has caught an unhandled exception while saving file '%1'").arg(filename));
41         result = CC_FERR_CONSOLE_ERROR;
42     }
43 
44     if (result == CC_FERR_NO_ERROR)
45     {
46         ccLog::Print(QString("[I/O] File '%1' saved successfully").arg(filename));
47     }
48     else
49     {
50         DisplayErrorMessage(result,"saving",filename);
51     }
52 
53     return result;
54 }
FileIOFilter::SaveToFile

获取需要的文件存储器。

 1 //获取存取器
 2 FileIOFilter::Shared FileIOFilter::GetFilter(QString fileFilter, bool onImport)
 3 {
 4     if (!fileFilter.isEmpty())
 5     {
 6         for (FilterContainer::const_iterator it=s_ioFilters.begin(); it!=s_ioFilters.end(); ++it)
 7         {
 8             QStringList otherFilters = (*it)->getFileFilters(onImport);
 9             if (otherFilters.contains(fileFilter))
10                 return *it;
11         }
12     }
13 
14     return Shared(0);
15 }
FileIOFilter::Shared FileIOFilter::GetFilter

这里重点研究一下obj文件的保存。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值