Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve aspect ratio of 2D object on window resize

Tags:

opengl

I have a Windows (XP) application which needs to display a two-dimensional rectangle within a window. The rectangle must not be clipped (i.e. must always lie completely within the viewport), and must preserve its aspect ratio on resize. Currently, the method which handles layout distorts the aspect ratio of the rectangle to match the window. I want the rectangle to scale to the window and be centered in the window (again, without clipping). The method as it stands is below. lWinDist and lMaxDepth are the width and height of the rectangle to be displayed (in 48ths of an inch, if it matters):

void CRoRRecView::RedoLayout( long lWinDist, long lMaxDepth )
{
    CDC* pDC = GetDC() ;

    if ( pDC != NULL )
    {
        m_lWinDist = lWinDist;
        GetClientRect( m_rectClient ) ;
        int nClientWidth = m_rectClient.Width();
        int nClientHeight = m_rectClient.Height();
        glViewport( 0, 0, nClientWidth, nClientHeight );

        glMatrixMode( GL_PROJECTION);
        glLoadIdentity();

        m_fWinXDist = (float) lWinDist ;
        m_fWinYDist = lMaxDepth ;
        m_fAspectRatio = m_fWinXDist / m_fWinYDist;

        glOrtho(0.0, m_fWinXDist, 0.0, m_fWinYDist, -1, 1 ) ;

        glRotatef(180.0, 0,1,0); 
        glTranslatef( (float)(-1 * lWinDist),0,0 ); // Translate across the x axis

        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity();

        ReleaseDC( pDC ) ;
    }
}
like image 304
PSU Avatar asked Oct 27 '25 09:10

PSU


2 Answers

This one should scale as expected:

// g++ main.cpp -lglut -lGL
#include <GL/glut.h>

void display()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    double ar = w / h;
    glOrtho( -2 * ar, 2 * ar, -2, 2, -1, 1);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();

    glColor3ub( 255, 0, 0 );
    glBegin( GL_QUADS );
    glVertex2i( -1, -1 );
    glVertex2i(  1, -1 );
    glVertex2i(  1,  1 );
    glVertex2i( -1,  1 );
    glEnd();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 640, 480 );
    glutCreateWindow( "Aspect Ratio" );
    glutDisplayFunc( display );
    glutMainLoop();
    return 0;
}
like image 59
genpfault Avatar answered Oct 29 '25 05:10

genpfault


Try this reshape function. It will preserve your aspect ratio, resize the object, and make the viewport to be centralize.

// initial window screen size
int WIDTH = 400;
int HEIGHT = 300;

// reshape function, call with glutReshapeFunc(reshape) in yout main function
void reshape(int width, int height) {
    const float ar_origin = (float) WIDTH / (float) HEIGHT;
    const float ar_new = (float) width / (float) height;

    float scale_w = (float) width / (float) WIDTH;
    float scale_h = (float) height / (float) HEIGHT;
    if (ar_new > ar_origin) {
        scale_w = scale_h;
    } else {
        scale_h = scale_w;
    }

    float margin_x = (width - WIDTH * scale_w) / 2;
    float margin_y = (height - HEIGHT * scale_h) / 2;

    glViewport(margin_x, margin_y, WIDTH * scale_w, HEIGHT * scale_h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0, WIDTH / ar_origin, 0, HEIGHT / ar_origin, 0, 1.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity() ;
}
like image 34
Ifan Iqbal Avatar answered Oct 29 '25 04:10

Ifan Iqbal