jonbonazza
jonbonazza

Reputation: 944

viewport or projection not resizing correctly on window resize in wxWidgets

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

Answers (2)

jonbonazza
jonbonazza

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

ravenspoint
ravenspoint

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

Related Questions