PDA

View Full Version : OpenGL Textures + Rotating



aleksgidenko
28th May 2009, 15:44
Hi, I am having a problem that I just cannot figure out. I am trying to create a simple rotating cube with a texture on it. I wanted to make the code as simple as possible so I have a derived class GLWidget from QGLWidget and in main I create an instance of it and call show. I use bindTexture to load the texture and here is some code from the paintGL function:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);

glBindTexture(GL_TEXTURE_2D, texture[0]);

...

Now, here is my problem. When I comment out the glRotatef commands, I see the texture. If I comment out the first two glRotatef commands, I still see the texture and it rotates. But if I don't comment out the first two glRotatef commands, I don't see anything. Now the code is fine, here is how I can get it to work, it's strange and I don't understand why it works. If I create another derived class MainWindow from QWidget and in that class I create an instance of GLWidget, everything works fine. So, to summerize...

main -> GLWidget (doesn't work)
main -> MainWindow -> GLWidget (works)

Now, I understand that the latter approach would be used in most cases and if it wasn't, why not just use GLUT. I am just curious as to why the first approach doesn't work. Here is the code from main.cpp

#include <QtGui/QApplication>
#include "glwidget.h"
#include "mainwindow.h"

int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(data);

QApplication a(argc, argv);
//GLWidget glWidget;
MainWindow glWidget;
glWidget.show();

return a.exec();
}

As you can see, I commented out the GLWidget line and am using the second approach which works.

Any help would greatly be appreciated. I have tried everything I could think of, it just doesn't make sense. I have tried different ways to load the texture, same thing. It's not the code, it's the setup. Why do I have to create a QGLWidget inside a QWidget, why can't I just create a QGLWidget?

-- Aleks

aleksgidenko
28th May 2009, 19:50
Ok, I recompiled the project in Linux and I can see the rotating cube and texture without having the extra widget. Should I file a bug report to Qt about this issue?

To recap,
I have a class GLWidget, derived from QGLWidget, which is instantiated in the main function. The only thing GLWidget does is load a texture and draws a rotating cube with that texture. This example works in Linux. But in Windows, I cannot see the cube or texture unless I comment out the glRotatef commands. It does work though if you instatiate GLWidget inside another QWidget. I am using Windows XP, I will recompile this code at home on a Windows Vista to see if it just on XP.

aleksgidenko
29th May 2009, 06:04
I really hate when something doesn't work like it should, it really bugs me. I am still trying to figure out the bug. I have tested on Windows Vista and I get the same result as on Windows XP. I am going to have to dig through the Qt source to figure this one out. I have made progress though.

If I replace:

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);

with:

GLfloat xview[16] = { 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
xview[5] = cos(xrot / 16.0);
xview[6] = -sin(xrot / 16.0);
xview[9] = sin(xrot / 16.0);
xview[10] = cos(xrot / 16.0);

GLfloat yview[16] = { 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
yview[0] = cos(yrot / 16.0);
yview[2] = sin(yrot / 16.0);
yview[8] = -sin(yrot / 16.0);
yview[10] = cos(yrot / 16.0);

GLfloat zview[16] = { 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
zview[0] = cos(zrot / 16.0);
zview[1] = -sin(zrot / 16.0);
zview[4] = sin(zrot / 16.0);
zview[5] = cos(zrot / 16.0);

glMultMatrixf(xview);
glMultMatrixf(yview);
glMultMatrixf(zview);

It works like it should. So why is glRotatef not working correctly in Qt, only on Windows? Is Qt possibly overloading the glRotatef function? I'm really hoping someone will find an answer to this bug before I start digging through the Qt source code.

aleksgidenko
29th May 2009, 06:24
If I replace:

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);

with:

glRotatef(GLint(xrot),1.0f,0.0f,0.0f);
glRotatef(GLint(yrot),0.0f,1.0f,0.0f);
glRotatef(GLint(zrot),0.0f,0.0f,1.0f);

It works. So why does glRotatef not work when passed a GLfloat but works when passed a GLint? Again, only on Windows. I have also tried glRotated, same results, only works when passed a GLint.

*** Note: If you read my first post, this testing is done using approach one. Using approach two, these gl functions work as expected.

aleksgidenko
29th May 2009, 06:54
Not sure if this will help anyone, but I was able to find the glRotatef function inside the Qt source code.


#ifdef QT_OPENGL_ES_1_CL
...
inline void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
{
glRotatex(FLOAT2X(angle), FLOAT2X(x), FLOAT2X(y), FLOAT2X(z));
}
...
#endif //QT_OPENGL_ES_1_CL

Not sure if this is being called. What does QT_OPENGL_ES_1_CL stand for?

aleksgidenko
29th May 2009, 07:11
from qgl.cpp:

... (Line 2606)
Note that under Windows, the QGLContext belonging to a QGLWidget
has to be recreated when the QGLWidget is reparented. This is
necessary due to limitations on the Windows platform. This will
most likely cause problems for users that have subclassed and
installed their own QGLContext on a QGLWidget. It is possible to
work around this issue by putting the QGLWidget inside a dummy
widget and then reparenting the dummy widget, instead of the
QGLWidget. This will side-step the issue altogether, and is what
we recommend for users that need this kind of functionality.
...

Not sure if this helps anybody.

aleksgidenko
29th May 2009, 07:52
Ok, I have found a solution that I can live with. It must have something to do with the paragraph from the last post. If I create a QGLContext before I create the QGLWidget, everything works. I don't even have to pass the QGLContext to the QGLWidget class for it to work, as long as the context is created before the widget.

Here is my main:

#include <QtGui/QApplication>
#include <QGLContext>
#include <QGLFormat>
#include "glwidget.h"

int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(data);

QApplication a(argc, argv);

QGLFormat glFormat;
QGLContext glContext(glFormat);
glContext.create();

GLWidget glWidget;
glWidget.show();

return a.exec();
}

This WORKS!!! :D

If I comment out:

QGLFormat glFormat;
QGLContext glContext(glFormat);
glContext.create();

I doesn't work!!!

Finally!!! I have figured out the problem. There's nothing like figuring out a problem that's been bugging you all day. I am going to sleep, it is almost 3 AM and I have to get up for work tomorrow to solve more programming problems, yay.

aleksgidenko
29th May 2009, 16:24
I tried the solution from my last post at work today, and nothing. I am still having the problem!!! :confused: I am running Windows XP at work and Windows Vista at home, that is the only difference I can think of. So, I will go home for lunch today and recompile the code at home to make sure it works, then I will bring that same exact code to work to see if it works. Does anyone have any suggestions?

aleksgidenko
29th May 2009, 16:46
Ok, I was able to get it to work by putting a qDebug command between the QGLContext and GLWidget.

QGLFormat glFormat;
QGLContext glContext(glFormat);
glContext.create();
qDebug() << "Create GL Widget";
GLWidget glWidget; // Create GL Widget

Without the qDebug command, it doesn't work. What is going on with this buggy code? What is Qt doing internally that I cannot seem to figure out? Where are the Qt guru's?

aleksgidenko
21st August 2009, 16:57
*** IGNORE ALL MY PREVIOUS POSTS!!! ***

I recently looked back at my Qt + OpenGL examples and I finally figured out the problem I was having when I first started this Thread. If you read any of my previous posts, you know that I was having trouble getting a cube with a texture to show up on the screen. This had nothing to do with how Windows handles the OpenGL context or with Windows at all. This had everything to do with BAD programming.

I have been programming for 8 - 9 years now. I program at work everyday, so I feel pretty STUPID for the mistake I made. I wanted to leave this last post so that people could laugh at the mistake, or at me, but more importantly so that nobody else makes the same mistake.

The problem was that I forgot to initialize the xrot, yrot, and zrot variables which I use in

glRotatef(xrot, 1.0f, 0.0f, 0.0f);
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
glRotatef(zrot, 0.0f, 0.0f, 1.0f);

I declared them in the header file but didn't initialize them in the constructor. A NOOB mistake, and I feel STUPID for making it. I guess all the extra code I added to fix the problem only moved the variables in the binary which resulted in them having different random values that worked.

*** IMPORTANT ***
DON'T FORGET TO INITIALIZE YOUR VARIABLES