Search code examples
c++openglglut

Trying to Scale OpenGL Program with Width (but not height)?


I am fiddling with graphics, and trying to find a way to have the shape I am drawing (in this case, a triangle) scale with window sizing. However, I only want the width to update, and the height to remain the same.

I have done some research, and tried using glutGet(GLUT_SCREEN_WIDTH) as a multiplier or similar (e.g. (GLUT_SCREEN_WIDTH /100) - 250) to the vertices of my shape, but I feel I may be missing a key idea. Should I instead be applying the scaling operation to the viewport, not the shape's points? Whenever I scale the points, they don't seem to scale with the window. Code below.

#define GLUT_DISABLE_ATEXIT_HACK
#include <GL/glut.h>
#include <GL/gl.h>
//#include <assert.h>

void init (void)
{

glClearColor (1.0, 1.0, 0.0, 0.0); /* Set background to yellow */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

}

void display(void)
{

glClear (GL_COLOR_BUFFER_BIT);

glColor3f (0.0, 0.0, 1.0);

glBegin(GL_TRIANGLES);

glVertex2d (0.0, 0.0);
glVertex2d(1.0, 0.0);
glVertex2d (0.5, 0.866);

glEnd();

glFlush (); //Display immediately

}

void keyEscape( unsigned char key, int x, int y )
{
switch ( key )
{
case 113: // 'Q' key for escape
  int windowID = glutCreateWindow ("triangle");
  glutDestroyWindow (windowID);
  exit (0);
  break;
}

glutPostRedisplay();

}

void mouseEscape( int button, int state, int x, int y )
{
if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
{

    int windowID = glutCreateWindow ("triangle");
    glutDestroyWindow (windowID);
    exit (0);

    glutPostRedisplay();

}

}

int main(int argc, char** argv)
{

glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (250, 250);
glutInitWindowPosition ((glutGet(GLUT_SCREEN_WIDTH)-250)/2,    (glutGet(GLUT_SCREEN_HEIGHT)-250)/2);
glutCreateWindow ("triangle");
init ();

glutKeyboardFunc(keyEscape);
glutMouseFunc(mouseEscape);
glutDisplayFunc(display);
glutMainLoop();

return 0;

}

Solution

    • Step 1: Get rid of the Init function. Projection setup is part of the drawing process.
    • Step 2: Use the Window width as input for the left/right parameter of glOrtho

    Like this:

    void display(void)
    {
        int const win_width  = glutGet(GLUT_WINDOW_WIDTH);
        int const win_height = glutGet(GLUT_WINDOW_HEIGHT);
        float const win_aspect = (float)win_width / (float)win_height;
    
        glClearColor (1.0, 1.0, 0.0, 0.0); /* Set background to yellow */
        glClear (GL_COLOR_BUFFER_BIT);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0, win_aspect, 0.0, 1.0, -1.0, 1.0);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        glColor3f (0.0, 0.0, 1.0);
    
        glBegin(GL_TRIANGLES);
    
        glVertex2d (0.0, 0.0);
        glVertex2d(1.0, 0.0);
        glVertex2d (0.5, 0.866);
    
        glEnd();
    
        glFlush (); // Tell OpenGL to process what we submitted so far
    }
    

    BTW: You should switch to a double buffered mode and use glutSwapBuffers instead of glFlush/glFinish; on some systems single buffered mode doesn't work (well). Today the only reliable method is double buffering.