I’m a real newbie when it comes to OpenGL, but my personal plan is to try to learn as much as possible about OpenGL ES 2.0 and be able to understand it better e.g. how things like Qt Scene Graph works. Of course, it would be nice to be able to contribute to the Qt Scene Graph project too at some point.
Now I have spend few evenings trying to study how you can do things with OpenGL and I went little bit side tracked at some point. I started do some research how could use a QML application in 3D. The solution was actually much easier than I thought. Here’s the PoC video about running Samegame, the QML demo application rendered on a 3D cube.
As you can see from the video, it’s not perfect yet. The mouse events aren’t delivered with the correct coordinates to the QML item, but it shouldn’t be a big deal to transform them to the correct coordinates.
How it’s done?
I will do more research related on this topic, so I don’t want to release the source code yet, but here is how it works.
Update: QmlAtlas is a class that I am working on. It’s not available or released yet. I wanted to mention this here because people where trying to find source code from a web. Sorry about that.
I don’t go too deep into details because I’m planning to change a lot in the next implementation. But the idea is that each QML document is loaded using QDeclarativeComponent and then the component creates a QDeclarativeItem. This item is added to QmlAtlas, which is QGraphicsScene. QmlAtlas acts as a large scene which can contain one or more QDeclarativeItems. The good thing here is that QmlAtlas knows when an item in a scene changes and it notifies of changes via QGraphicsScene::changed(QList<QRectF> signal.
So basically the “Cube” can contain a different QML component on each of its side. So far all the items are only in the QmlAtlas and next they need to be used as a texture on a surface of the cube. That’s done using QGLFrameBufferObject and QPainter in the QGLWidget::paintGL() method. What happens there is that, it creates a QPainter object which takes QGLFrameBufferObject as a paint device. Then it calls QmlAtlas::renderQml(int id, QPainter* painter) method. That method renders a part of the scene to the QGLFrameBufferObject. After this QGLFrameBufferObject is used for providing a texture for a 3D object. That’s all (bit simplified) when it comes to drawing.
The next thing to deal with is how mouse events are handled. As you can see from the video, mouse events are not delivered to the QML components as they should. The reason is that I was bit lazy in this demo and I didn’t have too much time for implementing that. But how it works so far is that it uses QCoreApplication::sendEvent(QObject*,QEvent*) to send events to the scene. I tried to use QGraphicsScene::sendEvent(QGraphicsItem*, QEvent*), but for some reason QML side never received or handled events.
Let’s see. I’m gonna learn more OpenGL ES 2.0 and I have some ideas how to use QML with OpenGL. I know there is Qt / 3D with QML bindings which will support this kind of stuff at some point, but this is purely for me and it’s fun to try out things.
Thanks for reading my blog!