• [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文件的保存。

  • 相关阅读:
    将表中数据生成SQL语句
    遍历页面所有的控件
    MSN不能登陆
    刷新框架页
    JS传参出现乱码
    iframe攻击
    有关于VS调试Javascript的问题
    C#中StringBuilder类的使用
    前瞻XAML
    Asp.Net在SqlServer中的图片存取
  • 原文地址:https://www.cnblogs.com/yhlx125/p/6414949.html
Copyright © 2020-2023  润新知