I'm trying to use the QGLWidget to use OpenGL in a Qt application.
I made a subclass of QGLWidget etc., and thought I'd test if it works.
However, the following code is not working as I expected it would:
void MyGLWidget::paintGL() {
gluLookAt(0,0,-10,0.5,0.5,0,0,1,0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1,0,0);
glBegin(GL_POLYGON);
glVertex3f(0,0,0);
glVertex3f(0,1,0);
glVertex3f(1,1,0);
glVertex3f(1,0,0);
glEnd();
}
What I imagined this would do is look at the center of a red square. But instead, when I run it, it seems to extremely briefly look at the center of the square, and then the display just becomes black.
Is there something I'm doing wrong? I'm not doing any OpenGL anywhere else. The function above is the only OpenGL code in the subclass (for now there's nothing in ::resizeGL() and ::initializeGL()).
I think you need to setup the OpenGL viewport. There are some Qt+OpenGL examples in the SDK. Take a look!
It seems that there were two problems with my code. First, I had to set up the view port in :
void MyGLWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.,((GLfloat)w)/((GLfloat)h),0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
and secondly, I had to call glLoadIdentity() before calling gluLookAt() in paintGL().
Related
I'm starting to work in a 2D game, but I don't know the way I'm supposed to use viewPort(). This is my Init() code:
void init(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(100, 100, 800, 600);
gluOrtho2D(0, 800, 600, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.0, 0.0, 0.0, 0.0);
}
What I want to know is that, after drawing an image to the window, how can I look only at a part of it, and not the whole world?
Everything you did there belongs into the drawing code. Loading textures and shaders, setting up framebuffer objects would be initialization, but you're not doing that up there.
Also glClear must come after glClearColor.
Last but not least, the viewport does not affect clear operations (you have to use scissor testing for clear operations to be limited to a certain rectangle).
So, I've been trying to rotate a single object in an OpenGL/GLUT environment.
After going through several questions on SO and the like, I've written what appears to be correct code, but no dice. Does anyone know how to make this work?
PS: I've tried changing the GLMatrixmode to Projection, but that just shows a black screen. Same thing happens if I use glLoadIdentity().
Here's my rendering code
void display()
{
preProcessEvents();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(Camera::position.x, Camera::position.y, Camera::position.z,
Camera::position.x+Math::sind(Camera::rotationAngles.x)*Math::cosd(Camera::rotationAngles.y),
Camera::position.y+Math::cosd(Camera::rotationAngles.x),
Camera::position.z+Math::sind(Camera::rotationAngles.x)*Math::sind(Camera::rotationAngles.y),
0.0, 1.0, 0.0);
glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0);
glVertex3f(-1, 0,-3);
glColor3f(0, 1, 0);
glVertex3f(0.0f, 2.0f,-3);
glColor3f(0, 0, 1);
glVertex3f(1.0f, 0.0f,-3);
glEnd();
glBindTexture(GL_TEXTURE_2D, tex->textureID);
glBegin(GL_QUADS);
glColor3f(1, 1, 1);
glTexCoord2f(100, 100);
glVertex3f(100,0,100);
glTexCoord2f(-100, 100);
glVertex3f(-100,0,100);
glTexCoord2f(-100,-100);
glVertex3f(-100,0,-100);
glTexCoord2f(100,-100);
glVertex3f(100,0,-100);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
object1.draw();
glTranslatef(-10.0, 10.0, 0.0);
glBindTexture(GL_TEXTURE_2D, tex2->textureID);
gluQuadricTexture(quad,1);
gluSphere(quad,10,20,20);
glBindTexture(GL_TEXTURE_2D, 0);
//RELEVANT CODE STARTS HERE
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glRotatef(190, 0.0, 0.0, 1.0);
glPopMatrix();
glutSwapBuffers();
}
Are you aware what glPushMatrix and glPopMatrix do? They save and restore the "current" matrix.
By enclosing your rotation in that and then doing no actual drawing operation before restoring the matrix the entire sequence of code beginning with //RELEVANT CODE STARTS HERE is completely pointless.
Even if you did not push/pop, your rotation would only be applied the next time you draw something. Logically you might think that would mean the next time you call display (...), but one of the first things you do in display (...) is replace the current matrix with an identity matrix (line 3).
In all honesty, you should consider abandoning whatever resource you are currently using to learn OpenGL. You are using deprecated functionality and missing a few fundamentals. A good OpenGL 3.0 tutorial will usually touch on the basics of transformation matrices.
As for why changing the matrix mode to projection produces a black screen, that is because the next time you call display (...), gluLookAt operates on the projection matrix. In effect, you wind up applying the camera transformation twice. You should really add glMatrixMode (GL_MODELVIEW) to the beginning of display (...) to avoid this.
You do the rotation (and reset it with glPopMatrix) after you draw, do the rotation code before the glBegin/glEnd calls.
Or just move to the shader based pipeline and manage you own transformation matrices.
I have a wxWigets application, using the wxGLCanvas widget from the contrib package. Every time the widget is refreshed, I recreate the projection matrix and the viewport before rendering the scene. The problem is, after the frame is resized, whether by dragging or maximizing or w/e, the widget is correctly resized, but the viewport or projection (can't really discern which) is not resized, so the scene ends up being cropped.
Now for some code.
The constructor of my wxGLCanvas widget looks like this:
int attrib_list[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER };
RenderCanvas::RenderCanvas(wxFrame* parent) : wxGLCanvas(parent, idRender, wxPoint(200, -1), wxSize(800, 600), wxFULL_REPAINT_ON_RESIZE, wxT("GLCanvas"), attrib_list)
{
Connect(idRender, wxEVT_PAINT, wxPaintEventHandler(RenderCanvas::PaintIt));
Connect(idRender, wxEVT_SIZE, wxSizeEventHandler(RenderCanvas::Resize));
Connect(idRender, wxEVT_LEFT_DOWN, wxMouseEventHandler(RenderCanvas::OnMouseLeftDown));
Connect(idRender, wxEVT_LEFT_UP, wxMouseEventHandler(RenderCanvas::OnMouseLeftUp));
Connect(idRender, wxEVT_MOTION, wxMouseEventHandler(RenderCanvas::OnMouseMotion));
}
I overriode the PaintIt method like so:
void RenderCanvas::PaintIt(wxPaintEvent& event)
{
SetCurrent();
wxPaintDC(this);
Render();
Refresh(false);
}
and the resize method:
void RenderCanvas::Resize(wxSizeEvent& event)
{
Refresh();
}
The Render method used above looks like this:
void RenderCanvas::Render()
{
Prepare2DViewport(0,GetClientSize().y,GetClientSize().x, 0);
glClear(GL_COLOR_BUFFER_BIT);
//Renders stuff...
glFlush();
SwapBuffers();
}
And lastly, the Prepare2DViewport, where the glViewport and glOrtho functions are being called is:
void RenderCanvas::Prepare2DViewport(int x, int h, int w, int y)
{
glClearColor(0.7f, 0.7f, 0.7f, 1.0f); // Grey Background
glEnable(GL_TEXTURE_2D); // textures
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glViewport(x, y, w, -h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(x, (float)w, y, (float)h, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
It should also be noted that I have tried using GetSize() instead of GetClientSize() but the effects are the same. Also, I am on Ubuntu 12.04 and wxWidgets is using GTK
UPDATE:
It should also be noted that I have click/drag functionality implemented as well (not shown), and every time the mouse is clicked or dragged, the widget is refreshed. With that said, I tried disconnecting the wxEVT_SIZE event, but after resizing and then clicking and dragging, the same effect persists.
From a quick glance at your code, I notice that your resize event handler is not doing anything more than asking for another refresh. This does not seem correct to me. A resize handler would normally do some calculation, call resize handlers of one or more child windows and so on before asking for a refresh. So, I think that your problem is that the canvas has not been resized BEFORE being repainted. This would explain why your scene is clipped. Not sure what the fix would be - hopefully this will be enough of a hint so you can look in the right direction.
Okay, so it turned out to be a very, very stupid mistake on my part.
in this line
glViewport(x, y, w, -h);
I accidentally set the height to a negative value. removing the negative sign fixed the issue. I am not sure why it was causing a crop. I would think having the height negative would prevent me from seeing anything, but it works, so I can't complain I guess. Thanks again all for the help!
Been integrating this camera tutorial http://www.swiftless.com/tutorials/opengl/camera2.html and having a bit of trouble centering the camera in the skybox.
Using this code below makes my camera inside the box:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-1.0, 1.0, -1.0*(GLfloat)h/(GLfloat)w,
1.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
else
glOrtho(-1.0*(GLfloat)w/(GLfloat)h,
1.0*(GLfloat)w/(GLfloat)h, -1.0, 1.0, -10.0, 10.0);
glMatrixMode(GL_MODELVIEW);
}
To draw the skybox, I followed this tutorial: http://sidvind.com/wiki/Skybox_tutorial
I've been trying to translate objects closer to the camera, but didn't work as I expected. Now I'm not sure what I need to do.
Appreciate any help.
First: Don'y apply the projection in the reshape handler. Otherwise simple things appear impossible (like doing a skybox). Second: For a skybox to work you must use the very same projection like for the rendering of the rest of the scene. What you should change is the translation of the modelview to 0, yet keeping the camera orientation.
You can do this by setting the last column of the modelview matrix to (0,0,0,1).
So this makes your rendering code like this:
void render_skybox()
{
push_modelview();
set_modelview_column(3, 0, 0, 1);
draw_skybox();
pop_modelview();
}
void render()
{
set_viewport();
set_projection();
apply_camera_transform();
render_skybox();
render_scene();
}
I just started working with OpenGL, but I ran into a problem after implementing a Font system.
My plan is to simply visualize several Pathfinding Algorithms.
Currently OpenGL gets set up like this (OnSize gets called once on window creation manually):
void GLWindow::OnSize(GLsizei width, GLsizei height)
{
// set size
glViewport(0,0,width,height);
// orthographic projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,width,height,0.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
m_uiWidth = width;
m_uiHeight = height;
}
void GLWindow::InitGL()
{
// enable 2D texturing
glEnable(GL_TEXTURE_2D);
// choose a smooth shading model
glShadeModel(GL_SMOOTH);
// set the clear color to black
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.0f);
}
In theory I don't need blending, because I will only use untextured Quads to visualize obstacles and line etc to draw paths... So everything will be untextured, except the fonts...
The Font Class has a push and pop function, that look like this (if I remember right my Font system is based on a NeHe Tutorial that I was following quite a while ago):
inline void GLFont::pushScreenMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(viewport[0],viewport[2],viewport[1],viewport[3], -1.0, 1.0);
glPopAttrib();
}
inline void GLFont::popProjectionMatrix()
{
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
}
So the Problem:
If I don't draw a Text I can see the Quads I want to draw, but they are quite dark, so there must be something wrong with my general OpenGL Matrix Properties.
If I draw Text (so the font related push and pop functions get called) I can't see any Quads.
The question:
How do I solve this problem and some background information why this happened would also be nice, because I am still a beginner/student, who just started.
If your quads are untextured, you will run into undefined behaviour. What will probably happen is that any previous texture will be used, and the colour at point (0,0) will be used, which could be what is causing them to be invisible.
Really, you need to disable texturing before trying to draw untextured quads using glDisable(GL_TEXTURE_2D). Again, if you don't, it'll just use the previous texture and texture co-ordinates, which without seeing your draw() loop, I'm assuming to be undefined.