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.