Nov 4, 2011

Maintaining Aspect Ratio in OpenGL with glFrustum While Resizing Windows

Maintaining aspect ratio in OpenGL can be tricky with glFrustum calls. I searched the web for some good code to do this, but I found nothing really satisfying.  Let me set up the scenario. Let's say you have a texture that you want to display (an image). Let's also say it has some aspect ratio.  Whenever you resize you window you want to set the viewport to be the same size as the window, but still maintain aspect ratio and not have the texture spill out of window bounds.  The correct way to do this is with some glFrustum calls to set up your projection matrix correctly.  First let's draw the texture centered at (0,0).  Here is the code for that:

Assuming you have already created a texture, bound it and enabled GL_TEXTURE...
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-aspectRatio * 0.5f, 0.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-aspectRatio * 0.5f, -0.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(aspectRatio * 0.5f, -0.5f);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(aspectRatio * 0.5f, 0.5f);

Notice that our x-coordinates are all half of the aspect ratio and the y-coordinates are half of one. Every time you resize your window you need to then snap your texture to the top and bottom with some space on the sides or to the left and right with some space on the sides. This is assuming that your window aspect ratio is not the same as your texture aspect ratio. If they are the same, then all is well and there will be no space on either side. So, what magic will get you the right aspect ratio on every resize without the texture spilling out of bounds? Here it is:
// get the window aspect ratio
float windowAspectRatio = this->width() / (float) this->height();
float halfWindowAspectRatio = windowAspectRatio * 0.5f;
// aspectRatio is the aspect ratio of your frame or texture
float halfAspectRatio = aspectRatio * 0.5f;
float left, right, top, bottom;
if (aspectRatio < windowAspectRatio) {
    // top and bottom should be flush with window
    top = 0.5f; // remember this is the top of the texture
    left = -halfWindowAspectRatio;
} else {
    // left and right should be flush with window
    left = -halfAspectRatio;
    // we are keeping top relative to the windowAspectRatio (normalizing here)
    top = halfAspectRatio / windowAspectRatio;
right = -left;
bottom = -top;
There it is. Notice that the two cases rely on the fact that the aspect ratio of the texture is either less than or greater than the aspect ratio of the window. There it is though, in all its glory.  Once you have that you just need to set those values into your glFrustum call and you're done.

Nov 2, 2011

OpenCV on Windows Debug Mode

For some reason (I am not clear as to why), OpenCV seemingly did not work in debug mode with QT on Windows 7. I am running Windows 7 64-bit and I built the OpenCV libraries myself (in Visual Studio 2010).  Unfortunately, it took me an unreasonable amount of time to discover that in Windows, if I want to run some of the OpenCV libraries in debug mode without everything blowing up in my face, I need not only the .dlls and the .libs, but also the .pdb files. Apparently, Windows uses these to run the libraries in debug mode. Once I figured this little piece of magic out (and Google did not offer a solution immediately), I just placed the libs, the dlls, and the pdbs in the same folder and told my program where this directory was when linking. Then, viola---it worked perfectly.  Wish I had found out sooner.