Seeking advice on using QGLWidget in Qt4 - c++

I'm new here, and have a question about opengl in Qt4, which I've been learning over the last few months.
Particularly, I'm seeking advice on the best way to compose a scene in a good object-oriented fashion using the QGLWidget. I'd ideally like every item in my scene to be sub-classes of a super 'Entity' class. Then in my main QGLWidget I can sort the entities and render them accordingly.
I noticed though that certain openGL functions (like bindTexture) need to be called from the QGLWidget (or the widget's QGLContext). At the moment I'm passing a pointer to the QGLWidget that controls my main viewport to each entity and storing it so that I can gain access to those functions. Is this a good idea?
Any advice would be gratefully received, or even directions to good websites/books that might be of help. I've got the Blanchette/ Summerfield book but the OpenGL section is quite short and most of the examples on the Qt website are pretty simplistic.
Thanks,
Dan

I agree with Vime: You're building a scene graph, and there are a number of classical approaches for designing its object hierarchy. Check out "3D Game Engine Design," by Dave Eberly, for details on one such engine, and look at OGRE for another example.
Since only one GL context can be active at a time on a particular thread, consider storing the QGLWidget pointer as a static class member to save effort:
class MyGLWidget : public QGLWidget {
// ...
public:
static inline MyGLWidget *GetActiveWidget() {
return ms_activeWidget;
}
protected:
static __declspec(thread) MyGLWidget *ms_activeWidget = 0; // uses MSVC extension
inline void SetActiveWidget() {
ms_activeWidget = this;
}
};
void MyGLWidget::paintGL() {
SetActiveWidget();
// ...
}
Then in your entity classes you can simply call MyGLWidget::GetActiveWidget() on the few occasions when you need to call QGLWidget member functions, and not need to copy a (probably invariant) pointer all over the place.

You are building something that is usually called "scene graph". In our engine scene graph objects need no access to QGLWidget. It's enough if you create your OpenGL objects inside void initializeGL() and render everything inside void paintGL().
There is a slightly higher level Qt/OpenGL example called Boxes. It can be found from qt/demos/boxes folder in Qt 4.6 installation.

Related

Qt QML draw in cpp subclass

so I am trying to understand drawing in Qt, but I dont get this one:
So first of all I had a qml file where I embedded a custom class called Game which has this constructor: Game::Game(QQuickItem *parent) : QQuickItem(parent)
Writing setFlag(ItemHasContents, true); in the constructor code was sufficient to being able to draw with QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); using QSGGeometry (This worked). Now I tried to draw in a subclass, using the same procedure but now it does not work anymore: So what I did was create a class called qcurver, and in Game I create an instance of qcurver. QCurver has the same constructor like Game and I pass the parent of Game so that technically it has the same parent as Game, but now when I try to draw in this class, nothing happens. Does anyone know, how I can pass the QML object for drawing, so that I actually see the drawing?
You're creating a Game object from QML code, so it's registered correctly in the QML scene. But the QCurver isn't created there, so it won't work.
Yes, it has the same parent, but it only means that if the parent gets deleted - the QCurver will be deleted too. Qt doesn't revise all QObjects that are added as children to find out if they are of type QQuickItem and should be rendered.
Also, QML itself was added to be able to avoid doing widget hierarchies in C++. So, compose hierarchies in QML. Or, if you want some of them in C++ for the performance reasons - then it is possible to do QSGNode hierarchies inside a QQuickItem (that's useful for rendering complex scenes with OpenGL).

Get only one QOpenGLContext for different QT widgets

I've the following problem :
I want to get an application composed of many view which render a common OpenGL scene from a different point of view, illumination, and others options.
Basically, my question is what is the best way to do that with qt ?
My first attempt was to create multiple QOpenGLWidget and get a common QOpenGLContext where I stored the textures but also the meshes and shaders.
But it didn't work for meshes because Vertex Array Objects seem to not be shareable.
After lot of tries, a possible solution is to store one VAO for each widget that need the mesh but this look really awful.
So, I wonder if there is a good alternative for this kind of problem, or maybe a good documentation to understand how these QOpenGLContext work.
The simplest idea that I've imagined is to create only one QOpenGLContext and use it in the different widgets. But I don't know how to just create a QOpenGLContext alone nor what kind of QWidgets is able to display these renderings.
It's my first post so I don't know if it's clear enough or if I need to describe my whole architecture.
You already tried, so I pass the word about shared contexts.
An OpenGL context is bound to a window: if you want only one context, the straight answer is to have only one window.
Using the widgets module, you can have multiple views of a same scene using multiple viewports in a same QOpenGLWidget. Something like:
void myWidget::paintGL() {
//...
glViewport(
0, 0,
this->width()/2, this->height()/2
);
// draw scene from one point of view
glViewport(
this->width()/2, this->height()/2,
this->width()/2, this->height()/2
);
// draw scene from an other point of view
//...
}
You should probably design a viewport class to store and manage the rendering parameters for each viewport.
The drawback is that you will have to detect in which viewport the user is clicking to handle interactions: some kind of if event.pos.x is between 0 and this->width()/2 ....
An other way could be to let down the widgets module and use Qt Quick and QML: a quick window declares a unique OpenGL context, where each quick item is like a viewport, but encapsulated in its own object so you don't have to think about where the user is interacting.
Inherit QQuickItem instead of QOpenGLWidget and export your class to QML using the qmlRegisterType() macro. You can then create a QQuickView in your program to load a QML code where you declare your items. An example from Qt's documentation here.
I think since multiple views/surfces can update independently, unfortunately its not possible to have one single QOpenGLContext that does the job. And sharing contexts have the limitation you already point out in your question.
QOpenGLContext can be moved to a different thread with moveToThread().
Do not call makeCurrent() from a different thread than the one to
which the QOpenGLContext object belongs. A context can only be current
in one thread and against one surface at a time, and a thread only has
one context current at a time.
Link : http://doc.qt.io/qt-5/qopenglcontext.html
So one way you can get it working is have independent updates to your views in a sequential order and make the context current one by one and render before moving on to the next view. This will guarantee that the context is current in only one view at any given time. Perhaps use a QMutex to serialize the updates.
Alternatively you can also pass the context around among threads and serialize their updates, but this is a bad approach.

Moving from QGLWidget to QWindow

I have some code using Qt 4. I want to migrate it to Qt 5 and switch to QOpenGL stuff. I can't understand where the code from void paintGL() and void initializeGL() needs to go in a QWindow. Can anyone help me with an example?
I have created a simple example of using QWindow with OpenGL.
To simplify OpenGL development I have created an abstract class GLWindow, which contains the virtual functions initializeGL(), paintGL() and resizeGL(int w, int h). I believe the source code shows the relationship between the old style and the new style.
The example is available here:
https://github.com/mortennobel/QtOpenGLChapter/tree/master/OpenGL3xAlt
Qt has at least one example (Overpainting) of putting widgets over an OpenGL scene. By looking at that, it appears the easiest way would be to inherit from QGLWidget instead of QWidget and override the appropriate virtual functions for initialize and paint.
The standard example for using QWindow with OpenGL is hellowindow in qtbase/examples/opengl.
There is no direct replacement for initializeGL and paintGL. Instead you do something like this:
Have a QWindow with surface type OpenGLSurface.
Create a QOpenGLContext with a matching format.
When the window receives an expose event, start rendering (makeCurrent, your GL calls and finally swapBuffers).

Game screen management

I am working on a screen manager for a miniature game engine, and so far I cannot find a proper solution to managing screen objects without using the 'blob' for each one of the screens. Is blob tolerable in such circumstances where I need a list of renderable objects in one controller?
I would consider using the MVC pattern in this situation. Otherwise, if you're not careful, it's very easy to end up with a bunch of spaghetti code where the screen code is reaching into the game code, and vice versa.
I have recently coded something you might call a "screen manager".
I started with the idea that, whatever game I make, the render system is going to be pretty much the same in terms of how to render (how to manage the hardware). The thing that changes is what is rendered, and how to draw it (do I want a box or a circle or a bitmap.. representing what... etc).
So basically the "game state" is responsible for knowing how to render itself, and should do so when given a render surface from the screen manager or graphics system (It should also be responsible for other things like knowing how input, physics, etc act upon itself).
I implemented it with a singleton for the GraphicsSystem object, which was called something like this:
GameState gs;
Graphics::System().Init(DOUBLE_BUFFER, 640, 480);
...
while(still_looping) {
...
// When it is time to render:
Graphics::System().RenderGameState(&gs);
}
And how, you ask, does the Graphics::System() singleton know how to render the game state? It knows because the game state is inherited from a listener exposed by the graphics system...
//within GraphicsSystem.h...
class BaseRenderer
{
public:
virtual void Render(BITMAP *render_surface) = 0;
};
//GameState defined with:
class GameState : public BaseRenderer
{
public:
void Render(BITMAP *render_surface);
...
You can do this with nearly all the subsystems... (probably not timing, as it is needed in the game loop).
Why singletons? Well, it is C++ and I'm assuming there is only 1 screen, or graphics subsystem to render with. I'm not sure if you are using multiple screens, or a mobile phone or a console. The other way I would do it is to have the graphics system as static global variables in a separate file, giving them file scope only, and having accessor functions in that file (my old C way of doing things).
The key though is encapsulation. Let your screen manager manage the hardware. Let your game state dictate how itself should be expressed.
If this misses the point, please clear up your question and I can edit the answer.

Do I need a visitor for my component?

I'm trying to do a small and simple GUI in C++ (with SDL). I'm experimenting with the Composite pattern to have a flexible solution.
I've got a Widget class, with Component objects : for instance, there is a PaintingComponent ; if I want to draw a box, I'll use a PaintingBoxComponent, that inherits from the PaintingComponent.
The ideal Widget class would look a bit like that :
Class Widget
{
private:
vector<Component*> myComponents;
public:
// A small number of methods able to communicate with the component
// without knowing their types
}
My question is simple : what is the best way to activate this component when I need it ?
I first went with a "display" function in the Widget class. But I see two problems :
1°) I'm losing the pure polymorphism of "Compoonent" in Widget, since I'm forced to declare a particular component of the widget as PaintingComponent. I can deal with this, since it's logical that a Widget should be displayed.
2°) More troublesome, I need to pass information between my main programm and my PaintingComponent. Either I pass the SDL_Surface* screen to the PaintingComponent, and it paints the image it drew on it, or I give to my component a reference to the object that need to receive the image it has drawn (and this object will paint the image on the screen). In both cases, Widget will have to handle the data, and will have to know what a SDL_Surface* is. I'm loosing the loose coupling, and I don't want that.
Then, I considered using a "Visitor" pattern, but I'm not used to it and before I try to implement it, I'd like to have your advice.
How would you proceed to have a flexible and solid solution in this case ? Thanks in advance !
If you plan to change graphic system later, you could implement this pattern. Visitor goes to root node, then recursively to all children, drawing them on some surface (known only to Visitor itself). You can gather "display list" with that, then optimize it before drawing (for example, on OpenGL apply z-sorting (lower z first).