QT cmake cc cascade pcl magic modification project

Table of Contents

1. Origin:

2. cmake compilation of qt

1. The final directory is as follows:

2. Related cmakelist modifications

3. Activation of qpcl

3. Magic modification of actual code

1.cc plug-in and UI transformation

2.MainWindow.cpp

3. Display of point cloud files

4.Finally integrated into your own project

4. Summary:

1.QT 64-bit error 0xc000007b. This error is either due to a missing DLL or because 64 and 32-bit are mixed up.

2.CDB process terminated unexpectedly (exit code: -2)


1. Origin:

It is still the company’s project needs, but there is too much content related to the UI layer of CC originally, and it is quite different from the project needs, so we are going to magically change the interface layer related qcc of CC (couldCompare), and the core cclib is not going to make any changes. .

Because there were previous preparations related to cmake construction and preparation, and qt also chose the cmake build project in order to facilitate the integration into your own project, it was relatively smooth this time.

For the pre-environment and cmake to build CC cascade and compile pcl, please refer to the author’s previous article:

“CMAKE builds QT5 CC PCL point cloud related”

Second, cmake compilation of qt

Because cross-platform projects on git require cmake to be built, cmake was chosen to build when building the QT project. So basically after you have the basic syntax and basic knowledge and understanding of cmake, you can understand the difference with QT cmake and the related content exclusive to Qt.

I originally thought that these two are the same thing, and they are both compiled by cmake, and it has been determined to be built by qt, so I did not change it directly. Compiling with qt cmake directly reports various errors:

So, at first glance, we still need to make engineering changes. There are several main issues: directory reconstruction and resource reloading. Anyway, it’s all a matter of path.

1.The final directory is as follows:

My own project has determined that all the Qt environment is generated directly through Qt. The rest is to directly move the functions required by CC into the integration and eliminate the unnecessary interface layer qcc directory. The circled ones are directly extracted from the original qcc. You can Use it according to your needs, and then modify CMakeLists.txt.

It is mainly the integration of icons.qrc resource files and the integration of some functional codes that need to be used (some are copied directly from qcc)

The mosaic area is not displayed for some content related to the company’s needs used in this project.

The magic modification cmake part mainly related to CC is as above.

Enablement of 3.qpcl

plugins/core/standard/qPCL/CMakeLists.txt

option( PLUGIN_STANDARD_QPCL “Check to install qPCL plugin” OFF ) —>Change OFF to ON to enable

include( ../../../CMakePluginTpl.cmake ) ==========》 plugins/CMakePluginTpl.cmake

You can also find the corresponding option in the qt cmake project build configuration and check it directly:

Then the whole process of compiling was completed in one go. I was really shocked. It went unexpectedly smoothly:

But it should be the norm to just do it once, after all, it is all cmake.

It means that the above basic directory and cmakelist modifications should be correct.

Compilation information can be viewed directly in the summary information. There is no need to manually enable debugging information like cmake.

Moreover, when cmake was originally built here, it was detected as 32-bit. In this Qt cmake, it can be directly detected as 64-bit. I don’t know if it has something to do with the previous change, and I am too lazy to look again.

After everything is compiled successfully,

In the column of the project structure, the relevant cmake-related configuration files will also appear correctly in cmakemodel.

3. Magical modification of the actual code

1.cc plug-in and ui modification

If you only use CC related file formats such as bin txt ply and other formats, it is actually very simple and does not require plug-in modules.

However, the author also needs to use some third-party formats such as pcd, and needs to add plug-in related content.

CC plug-ins are divided into three types: CC_STD_PLUGIN, CC_GL_FILTER_PLUGIN, CC_IO_FILTER_PLUGIN

Standard type, third-party type (divided into two sub-categories, it seems IO and Core), and there is another type that I didn’t pay close attention to,

Therefore, all relevant and unnecessary ones can be commented out.

//Plug-in management class, QT native
class ccPluginUIManager : public QObject
{
//Others are some associated management related to the main interface controls, and can be commented out.
    ........
//Key variables
QList<ccPluginInterface *> m_plugins;

    ...

}

At the same time, some macro conditional compilation is directly eliminated, but the command line operation is still retained. I don’t know if it will be shared with the UI. The main.cpp code is simplified as follows:

int main(int argc, char *argv[])
{
    bool commandLine = (argc > 1) & amp; & amp; (argv[1][0] == '-');
    if (!commandLine)
    {
        ccApplication::initOpenGL();
    }


    ccApplication app(argc, argv, commandLine);

    //store the log message until a valid logging instance is registered
    ccLog::EnableMessageBackup(true);

    //restore some global parameters
    {
        QSettings settings;
        settings.beginGroup(ccPS::GlobalShift());
        double maxAbsCoord = settings.value(ccPS::MaxAbsCoord(), ccGlobalShiftManager::MaxCoordinateAbsValue()).toDouble();
        double maxAbsDiag = settings.value(ccPS::MaxAbsDiag(), ccGlobalShiftManager::MaxBoundgBoxDiagonal()).toDouble();
        settings.endGroup();

        ccLog::Print(QString("[Global Shift] Max abs. coord = %1 / max abs. diag = %2").arg(maxAbsCoord, 0, 'e', 0).arg(maxAbsDiag , 0, 'e', 0));

        ccGlobalShiftManager::SetMaxCoordinateAbsValue(maxAbsCoord);
        ccGlobalShiftManager::SetMaxBoundgBoxDiagonal(maxAbsDiag);
    }
    //global structures initialization
    FileIOFilter::InitInternalFilters(); //load all known I/O filters (plugins will come later!)
    ccNormalVectors::GetUniqueInstance(); //force pre-computed normals array initialization
    ccColorScalesManager::GetUniqueInstance(); //force pre-computed color tables initialization

    ccPluginManager::get().loadPlugins();

    int result = 0;

    QTranslator translator;
    const QStringList uiLanguages = QLocale::system().uiLanguages();
    for (const QString & locale : uiLanguages) {
        const QString baseName = "xxxxTester_" + QLocale(locale).name();
        if (translator.load(":/i18n/" + baseName)) {
            app.installTranslator( & amp;translator);
            break;
        }
    }

    MainWindow w;
    w.setWindowFlags(Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint|Qt::MSWindowsFixedSizeDialogHint);
    w.showMaximized();
    //w.setFixedSize(w.width(), w.height());
    QApplication::processEvents();


    QDir workingDir = QCoreApplication::applicationDirPath();
    QDir::setCurrent(workingDir.absolutePath());

    result = app.exec();

    //release global structures
    FileIOFilter::UnregisterAll();

    return result;
}
2.MainWindow.cpp

Changes to the main form structure. If you do not use the plug-in system, you do not need to inherit ccMainAppInterface.

ccMainAppInterface is an interface class that provides various method interfaces for third-party plug-ins to use in the plug-in to operate related content on this interface. Therefore, if you do not need to use plug-ins, you can directly not inherit this interface.

At the same time, in addition to the override function of the ccMainAppInterface interface, there are also some echoes related to the DB tree view and property page view. If the relevant CC-defined controls are not used for display,

Or if you plan to make a complete magic modification like the author, you can completely explain the re-modification process.

In this case, the entire MainWindow.cpp will be more streamlined and more readable.

class MainWindow : public QMainWindow,public ccMainAppInterface
{


dbTreeView//Customized display control variables, you can comment them out if not used, the view model is associated with ccDBRoot

//-----When constructing initialization:

//Very important signal function, emitted internally by m_ccRoot->changeSelection. Comment it out without displaying it.
connect(m_ccRoot, & amp;ccDBRoot::selectionChanged, this, & amp;MainWindow::updateUIWithSelection);

//Comment it out without displaying it, same as above
connect(m_ccRoot, & amp;ccDBRoot::dbIsEmpty, [ & amp;]() { updateUIWithSelection(); updateMenus(); }); //we don't call updateUI because there's no need to update the properties dialog

//Comment it out without displaying it, same as above
connect(m_ccRoot, & amp;ccDBRoot::dbIsNotEmptyAnymore, [ & amp;]() { updateUIWithSelection(); updateMenus(); });
//we don't call updateUI because there's no need to update the properties dialog
   


}
3. Display of point cloud files

The point cloud model displayed in the main form of MainWindow is displayed through the sub-window of the multi-document form of MDI. However, MDI is not actually needed in this project. I originally thought that SDI would also work, but later I saw that QT’s interface control association is simpler than MFC’s. There are too many, and there is no such distinction as panel. It is possible to embed widgets in widgets, so just use a widget to display them.

The original core display principle of qcc is

1. The doActionLoadFile() function executes to open the file selection dialog box (it will confirm some additional format information selection based on the content of the CC plug-in),

2. The format corresponding to addToDB() analysis is stored in the CC core data format: ccHObject, which includes point cloud data and attribute analysis, etc.

3. Set the scene of the view window to the ccHObject* object pointer in new3DView(). In this way, as long as the pointer is changed, the serial port model can be changed.

The analysis of the core code of the relevant display model is organized as follows:

class Q_CORE_EXPORT QAbstractItemModel : public QObject;

//QT's native structure provides management and related operations of DB views and attribute views corresponding to read files
class ccDBRoot : public QAbstractItemModel
{
ccHObject* m_treeRoot;//Tree view model---the main structure of CC
\t
QTreeView* m_dbTreeWidget;//QT form displays component view, no comments required

    //If other related interface control elements in qCC are used and need to be refreshed, this is a function rewrite inherited from the interface.
MainWindow::RefreshAllGLWindow(false);

    //Display model usage, very important. Changing this content after loading the file will cause changes in the model in the 3D window
ccHObject* ccDBRoot::getRootEntity()
{
return m_treeRoot;
}
\t
//CCDBRoot.cpp line 357
void ccDBRoot::addElement(ccHObject* object, bool autoExpand/*=true*/)
{
\t
}
\t
//Non-slot functions in this class, call this function in the slot function provided to the main page tree component signal link
    //CCDBRoot.cpp line 964
void ccDBRoot::selectEntities(std::unordered_set<int> entIDs);

}



//Some settings operations related to the file selection dialog box, mainly related to file filtering
doActionLoadFile()
------>addToDB(....);
{
//Main core call--CC's analysis and structuring of content loaded from file
ccHObject* newGroup = FileIoFilter::LoadFormFile(...);
\t\t
if(destWin)
{
newGroup->setDisplay_recursive(destWin);
}
addToDB(newGroup, true, true, false)--》 {
//add object to DB root
if (m_ccRoot)
{
//force a 'global zoom' if the DB was emtpy!
if (!m_ccRoot->getRootEntity() || m_ccRoot->getRootEntity()->getChildrenNumber() == 0)
{
updateZoom = true;
}
m_ccRoot->addElement(obj, autoExpandDBTree);//obj = newGroup
}
\t\t\t\t
\t\t\t\t
\t\t\t\t
}
\t\t
}



//Initialize to generate window window, important
new3DView(true);
\t
//Slot link function, provided to the new view window button
connect(m_UI->actionNew3DView, & QAction::triggered, this, & MainWindow::new3DView);

//The functions inherited from the main form structure interface
void MainWindow::activateRegisterPointPairTool(){...new3DView()...}

//The functions inherited from the main form structure interface
void MainWindow::activateSectionExtractionMode(){...new3DView()...};


//The function inherited from the main form structure interface is very important
new3DView(){

void ccDBRoot::selectEntities(std::unordered_set<int> entIDs);

view3D->setSceneDB(m_ccRoot->getRootEntity());


}


//#include "ccPropertiesTreeDelegate.h"
//#include "ccSelectChildrenDlg.h"
/*
It is not a necessary header file. Once introduced, it will introduce a bunch of interfaces related to point cloud value and model attribute display.
Comment out all relevant content
ccDBRoot <------- sfEditDlg <---- ccHistogramWindow.h
ccDBRoot <------- ccColorScaleEditorDlg.h
ccSelectChildrenDlg.h
*/



//The + - sign of the line width and point size on the viewport does not display the problem
ccGLWindow.cpp

void ccGLWindow::renderText(......);

void ccGLWindow::drawClickableItems(.....){




    //+-number related resource image call
//line 1398:
static const QImage c_minusPix = QImage(":/CC/images/ccMinus.png").mirrored();
static const QImage c_plusPix = QImage(":/CC/images/ccPlus.png").mirrored();



line 1414 call ccGLUtils::DisplayTexture2DPosition


}


ccGLUtils.cpp
void ccGLUtils::DisplayTexture2DPosition(...) //line 24
4.Finally integrated into your own project

The rendering of the content magic modification is as follows: (The following is a picture record of some minor problems encountered during the magic modification process and the above solution process)

At the same time, the main interface uses QT’s dockWidget processing, and everything can be floated and dragged.

Four. Summary:

This magic modification mainly brings huge benefits to QT interface development and QT cmake construction and development projects.

But QT’s IDE debugger is really unfriendly, and it’s not as easy to use as VS’s.

Problems such as crashing or being unable to continue debugging after encountering some exceptions during the process and having to restart and re-debug are common.

1. QT 64-bit error 0xc000007b, this error is either a missing DLL, or 64 and 32 bits are mixed. The bits are mixed up.

For details, please refer to: QT application cannot start normally 0xc000007b error_qt application cannot start normally 0xc000007b_Navy Governor’s Blog-CSDN Blog

ACLUI.DLL
ACTIVEDS.DLL
ADSLDPC.DLL
ADVAPI32.DLL
ADVPACK.DLL
AEPIC.DLL

2.CDB process terminated unexpectedly (exit code: -2)

This is rather tricky.

There are similar problems on the Internet: Solving the problem that QT cannot be debugged—–the cdb process terminated unexpectedly (exit code -805306296)_qt cannot be debugged_lizhengl’s blog-CSDN blog

The CDB process terminated solution appears when running QT (personal test is valid)_bloomerOAO’s blog-CSDN blog

But my error code is -2, but seeing that the two problems are related to the IDE, I made a guess.

Because the company’s computers are encrypted, all related files in the IDE are encrypted. As a result, the operation is OK, but as soon as CDB is called during debugging, this error is reported.

After decrypting it later, it will be fine.