Reputation: 944
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.
Upvotes: 2
Views: 959
Reputation: 944
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!
Upvotes: 1
Reputation: 20616
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.
Upvotes: 3