Using QML with 3D and OpenGL

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.

What’s Next?

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!

Tags: , , , , , ,

6 Responses to “Using QML with 3D and OpenGL”

  1. kypeli says:

    Impressive and interesting stuff!

    Is QmlAtlas your own component or a QML component? I couldn’t find anything about it with Google.

    • zchydem says:

      @kypeli Thanks.

      QmlAtlas is a convenience class which inherits QGraphcisScene. It provides interfaces for adding QDeclarativeItems to the scene (int QmlAtlas::addQmlItem(const QString path)) and for rendering them (renderQmlItem(int id, QPainter *)).

      I will publish the source code at some point.

  2. tankd says:

    Very impressive.

    I actually work on an similar project ( 2d gui for SFML vith QML).
    And, as you, I can’t handle keyboard and mouse input.
    Did you have any solution for this.

    Thanks,
    Tankd

    • zchydem says:

      @tankd Thanks for your comment.

      No, I don’t have any implemented solution, but basically mouse events should be transformed to the correct position. This was more like a proof of concept if this kind of thing can be done so I didn’t bother to continue it. The keyboard event is a bit different, because it should be decided which 3D object has focus and send events to that object. For a single object it’s trivial – just send key events to that.

  3. drinkmilk says:

    Hey,

    I am working on something similar and thus I find this project very interesting. Do you mind sharing the code? I am mainly interested in the architecture, so it’s totally fine by me if it’s in alpha stage.

    Thanks!

Leave a Reply

You must be logged in to post a comment.