zoukankan      html  css  js  c++  java
  • [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("	- %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("	- %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文件的保存。

  • 相关阅读:
    Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
    Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析
    Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析
    Linq基础操作之Select,Where,OrderBy,ThenBy源码分析
    PAT 1152 Google Recruitment
    PAT 1092 To Buy or Not to Buy
    PAT 1081 Rational Sum
    PAT 1084 Broken Keyboard
    PAT 1077 Kuchiguse
    PAT 1073 Scientific Notation
  • 原文地址:https://www.cnblogs.com/yhlx125/p/6414949.html
Copyright © 2011-2022 走看看