3.3.5. 3D Rendering Module

The 3D renderer is C++ module that has to be compile as a QML plugin to be used in the application. The communication between the module and the orchestrator can only be made through QML. To display openGL under QML, we used the QML scene graph.

3.3.5.1. openGL implementation and .ply reader

The C++ code for the openGL implementation is based on this tutorial . There are many differences as we had to use this module in a Qt context : we had to convert every C++ openGL function in Qt openGL functions.

Those are really often the same function, only the name changes. Only Buffer Object and Vertex Array Object are different since they are Qt object that we have to create before using them.

The .ply reader can be found in an old commit made in the openMVG repository. This reader is the one initializing the position and color buffers of the renderer.

When a point cloud has been read by the reader, we initialize a list of camera coordinates simply by reading the end of the position buffer (because cameras are found at the end of the ply file). We then initialize the default camera to the first camera : that’s the default point of view used for the renderer. We can switch this point of view, in the camera list order, simply by calling the nextCam function. The renderer is still pretty basic, but what is interesting here is the conversion between the C++ openGL implementation to a Qt implementation. We then describe how to use this renderer as a QML plugin. The pathply attribute and the nextCam function are two good examples of interactions between QML and the plugin, and are two ways of communicating (by setting attributes directly from QML, or by calling a C++ function also directly from QML).

3.3.5.2. The QML Plugin

To create a new QML plugin, we followed the QT documentation. The plugin is in the PointCloud.cpp file as a new class extending QQmlExtensionPlugin. As said before, we used the QML scene graph to display openGL under QML. As explained in the tutorial, we had to separate the PointCloud, which lives in the GUI thread, and the PointCloudRenderer, which lives in the rendering thread. When the beforeRendering signal from the window is emitted , at the start of every frame before the window rendering, any OpenGL draw calls that are made as a response to this signal will stack under the Qt Quick items. We then simply connect the beforeRendering signal to the renderer paint function to paint the PointCloud.

3.3.5.3. Communication between QML and the plugin

With our plugin, you can either communicate by directly calling C++ function from QML, or by dynamically setting attribute in QML. We implemented both ways of communication :

  • You can set in the QML PointCloud object a path to a ply file used for the rendering. The communication is not made directly from QML to the renderer, you have to use the PointCloud to communicate. To set the ply path, we added a setter and a getter, and also a Qt property in order to make QML aware on how to set and get the attribute.
  • You can call directly from QML the nextCam function. To do that, you also have to go through the point cloud object and not directly call the renderer function. You have to add a Qt invokable function which calls the renderer function.

Note that you really have to be aware of the whole logic behind the scene graph in order to synchronize everything. You especially have to use the QQuickItem function like sync to be able to stack the openGL calls under the Qt Quick item.