Resizing an OpenGL window causes it to fall apart - c++

For some reason when I resize my OpenGL windows, everything falls apart. The image is distorted, the coordinates don't work, and everything simply falls apart. I am sing Glut to set it up.
//Code to setup glut
glutInitWindowSize(appWidth, appHeight);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutCreateWindow("Test Window");
//In drawing function
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
//Resize function
void resize(int w, int h)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
}
The OpenGL application is strictly 2D.
This is how it looks like initially: http://www.picgarage.net/images/Corre_53880_651.jpeg
this is how it looks like after resizing: http://www.picgarage.net/images/wrong_53885_268.jpeg

You should not forget to hook the GLUT 'reshape' event:
glutReshapeFunc(resize);
And reset your viewport:
void resize(int w, int h)
{
glViewport(0, 0, width, height); //NEW
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
}
A perspective projection would have to take the new aspect ratio into account:
void resizeWindow(int width, int height)
{
double asratio;
if (height == 0) height = 1; //to avoid divide-by-zero
asratio = width / (double) height;
glViewport(0, 0, width, height); //adjust GL viewport
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(FOV, asratio, ZMIN, ZMAX); //adjust perspective
glMatrixMode(GL_MODELVIEW);
}

Related

OpenGL maintain object shape on window resize

I have a square and I'm trying to make it stay a square when the window is resized, instead of stretching with the window. I have some code which I thought would work but when I resize the window the square shrinks and disappears. It doesn't come back when I return the window to it's original size. Can someone tell me what I've done wrong and how to fix it?
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
return;
}
void reshape(int w, int h) {
const float aspectRatio = ((float)w) / h;
float xSpan = 1;
float ySpan = 1;
if (aspectRatio > 1) {
xSpan *= aspectRatio;
}
else {
ySpan *= aspectRatio;
}
gluOrtho2D(-1*xSpan, xSpan, -1*ySpan, ySpan);
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutCreateWindow("simple");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
}
The functions gluOrtho2D and glOrtho multiply the current matrix by the new orthographic projection matrix.
This causes that if the reshape is called a 2nd time, the matrix which was set by gluOrtho2D before, is multiplied by the new one and you get consecutive changes.
You have to "reset" the matrix (init the identiy matrix) on the matrix stack by glLoadIdentity. Further you should choose the projection matrix stack by glMatrixMode:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1*xSpan, xSpan, -1*ySpan, ySpan);
The setup of the viewport glViewport is correct and you also consider the aspect ratio correctly (in gluOrtho2D). But there is an issue if the aspect ratio is less than 1.0. It should be ySpan /= aspectRatio;
I recommend to do the setting of the viewport and the projection matrix in the display function and just to set a notification flag in the reshape function. Note, the viewport and the projection matrix should be changed as rare as possible.
bool vp_valid = true;
int width, height;
void reshape(int w, int h) {
vp_valid = false;
width = w;
height = h;
}
void display(void)
{
if (!vp_valid)
{
const float aspectRatio = (float)width / height;
float sx = aspectRatio > 1.0f ? aspectRatio : 1.0f;
float sy = aspectRatio > 1.0f ? 1.0f : 1.0f/aspectRatio;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-sx, sx, -sy, sy);
glViewport(0, 0, width, height);
}
.....
}

Why I can not get zoom in and out effect immediately but have to resize window first

I am new to OpenGL. I encounter a problem. Why I can not get zoom in and out effect in OpenGL immediately but have to resize window first and then I can see the image plotted become smaller or larger.
I am so sorry that I do not which part of program should I provide to clarify this problem.
I think the problem may be caused by mouse function?
void glutMouseWheel(int wheel_number, int direction, int x, int y)
{
if (direction == 1)
zoomFactor = 0.5*zoomFactor;
else
zoomFactor = 2* zoomFactor;
glutPostRedisplay();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-0.001*zoomFactor, 0.001*zoomFactor, -0.001*zoomFactor, 0.001*zoomFactor, -100, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
As you see I define a double zoomFactor to adjust the orthogonal volume to zoom the image. It should be fine, but I do not know why I still encounter this problem.
Right now you can change zoomFactor all you want but it won't get applied to the OpenGL state (via the code in resize()) until you resize the window.
The glutPostRedisplay() at the end of glutMouseWheel() will not cause the glutReshapeFunc() callback to run. It only schedules a glutDisplayFunc() call.
Move everything except the glViewport() call from reshape() to your glutDisplayFunc() callback:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
}
void display()
{
// clear framebuffer
...
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-0.001*zoomFactor, 0.001*zoomFactor, -0.001*zoomFactor, 0.001*zoomFactor, -100, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw stuff
...
glutSwapBuffers();
}

opengl: Trouble setting up viewport and glortho

I am trying to setup my OpenGL views for some texture rendering. Following some advice on the forum, I set up my viewport and ortho matrix as follows:
First I try to compute the screen width and height that I can use while maintaining the aspect ratio of my image:
void resize(int w, int h)
{
float target_aspect_ratio = image_width / image_height;
width = w;
height = (int)(width / target_aspect_ratio + 0.5f);
if (height > h) {
height = h;
width = (int)(height * target_aspect_ratio + 0.5f);
}
off_x = (w - width)/2.f;
off_y = (h - height)/2;
// I want to center my image. So I have these offsets
glViewport(off_x, off_y, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, 0.0f, 1.0f);
Now when I want to render my texture I do:
void paint()
{
// texture binding etc.
glTexCoord2f(0, 0); glVertex2f(0, 0);
glTexCoord2f(1, 0); glVertex2f(width, 0);
glTexCoord2f(1, 1); glVertex2f(width, height);
glTexCoord2f(0, 1); glVertex2f(0, height);
}
However, this does not show the image as expected. It does not maintain the aspect ratio as I size the screen. It is almost like the glViewport has no effect and I can verify this function gets called every time my window is resized.
Update:
It is strange. Almost as if these calls have no effect. I even did something as:
_off_x = _off_y = 0;
_width = 500;
_height = 500;
So I expected the viewport to be lower left box of my screen but the image is being drawn as before basically using the whole screen as the viewport.
Update 2:
Ok, so if I call
glViewport(_off_x, _off_y, _width, _height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, _width, 0, _height, 0, 1);
in my paint events, it works as expected! However, I thought it was enough to put this in the resize event handler.
Before start drawing, you need to switch your Matrix mode to GL_MODELVIEW. You don't need to set your projection matrix inside your render function at each frame.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Here is a detailed analysis that I wrote about glMatrixMode() function modes :
OpenGL glMatrixMode(GL_PROJECTION) vs glMatrixMode(GL_MODELVIEW)

OpenGL - how to fit a window on resize

I have a shape that is centered on the window screen. For now on window resize it remains the same (same width and height).
What is the best way to fit it to the window on resize, and also keep it's aspect ratio?
const int WIDTH = 490;
const int HEIGHT = 600;
/**
* render scene
*/
void renderScene(void)
{
//clear all data on scene
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//set white bg color
glClearColor(1, 1, 1, 1);
glColor3ub(153, 153, 255);
glBegin(GL_POLYGON);
glVertex2f(60, 310);
glVertex2f(245, 50);
glVertex2f(430, 310);
glVertex2f(245, 530);
glEnd();
glutSwapBuffers();
}
/**
* reshape scene
*/
void reshapeScene(GLint width, GLint height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluOrtho2D(0, width, height, 0);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
/**
* entry point
*/
int main(int argc, char **argv)
{
//set window properties
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(WIDTH, HEIGHT);
glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH)-WIDTH)/2, (glutGet(GLUT_SCREEN_HEIGHT)-HEIGHT)/2);
glutCreateWindow("Test Window");
//paste opengl version in console
printf((const char*)glGetString(GL_VERSION));
//register callbacks
glutDisplayFunc(renderScene);
glutReshapeFunc(reshapeScene);
//start animation
glutMainLoop();
return 0;
}
Thanks
At the top:
const int WIDTH = 490;
const int HEIGHT = 600;
const float ASPECT = float(WIDTH)/HEIGHT; // desired aspect ratio
Then reshapeScene:
void reshapeScene(GLint width, GLint height)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
int w = height * ASPECT; // w is width adjusted for aspect ratio
int left = (width - w) / 2;
glViewport(left, 0, w, height); // fix up the viewport to maintain aspect ratio
gluOrtho2D(0, WIDTH, HEIGHT, 0); // only the window is changing, not the camera
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
Because you are not constraining the window resize to a particular aspect ratio, you need to pick one of the two dimensions (height, here) to drive the viewport reshape and calculate an adjusted width based on that height and the desired aspect ratio. See adjusted glViewport call above.
Also, gluOrtho2D is your camera, essentially. Since you aren't moving the camera or the object so much, you don't need to change that (so it just uses the initial WIDTH and HEIGHT).

Resizing glut window

I'm doing 2D drawing in a glut window, and I'm having trouble making the window resize properly.
My glutDisplayFunc and glutReshapeFunc are below. As it is, the drawing disappears when the window is resized. If I delete the glClear() from displayFunc(), new pixels don't "initialize" and there are clipping problems. How do I fix this?
glutDisplayFunc:
void displayFunc() {
glDisable( GL_DEPTH_TEST );
glClear( GL_COLOR_BUFFER_BIT );
glPointSize ( 3.0 );
glFlush();
}
glutReshapeFunc:
void windowReshapeFunc( GLint newWidth, GLint newHeight ) {
glViewport( 0, 0, newWidth, newHeight );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, GLdouble (newWidth), 0, GLdouble (newHeight) );
windowWidth = newWidth;
windowHeight = newHeight;
}
I'd try adding a call to glutPostRedisplay() around the end of your reshape function.
This is basic template that I use...
#include <GL/glut.h>
#include <stdio.h>
#include <stdarg.h>
#define WINDOW_WIDTH 300
#define WINDOW_HEIGHT 300
// current Window width and height
int win_width, win_height;
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
// write your code here
//
//
glutSwapBuffers();
}
void on_resize(int w, int h)
{
win_width = w;
win_height = h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-w / 2, w / 2, -h / 2, h / 2, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
display(); // refresh window.
}
void main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("basic resize template");
glutDisplayFunc(display);
glutReshapeFunc(on_resize);
glutMainLoop();
}
You can not call gluOrtho2D twice with the same window, it will break the graphics and so nothing shows up. You would have to init window size and set Ortho to the size of the screen (current display resolution), then draw relative to the size of the window.
I guess your code does not draw everything on scene in display func, you see, if no events occcur ever you have to call display one time and in the first time it has your drawing. But your problem rises when there is an event which says the window is resized! try putting your drawing part in display function. Like so,
void displayFunc() {
glDisable( GL_DEPTH_TEST );
glClear( GL_COLOR_BUFFER_BIT );
glPointSize ( 3.0 );
glBegin(GL_POINTS);
{
//Blah blah blah some points here which you expect to draw
}
glEnd();
glFlush();
}
Please post the full code if this was not helpful.
You're not setting the matrix mode back to GL_MODELVIEW at the end of your reshape function.
void reshape(int width, int height) {
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, GLdouble (width), 0, GLdouble (height) );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
It's hard to say if there's something else in your display function without seeing more code. I hope that helps.