【问题标题】:Preserve aspect ratio of 2D object on window resize在窗口调整大小时保留 2D 对象的纵横比
【发布时间】:2011-05-19 07:58:46
【问题描述】:

我有一个需要在窗口中显示二维矩形的 Windows (XP) 应用程序。矩形不得被剪裁(即必须始终完全位于视口内),并且必须在调整大小时保持其纵横比。目前,处理布局的方法会扭曲矩形的纵横比以匹配窗口。我希望矩形缩放到窗口并在窗口中居中(同样,没有剪裁)。目前的方法如下。 lWinDist 和 lMaxDepth 是要显示的矩形的宽度和高度(如果重要,以 48 英寸为单位):

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 ) ;
    }
}

【问题讨论】:

    标签: opengl


    【解决方案1】:

    这个应该按预期扩展:

    // 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;
    }
    

    【讨论】:

    • 谢谢。是的,这很好地扩展了。不幸的是,整个问题对我来说都没有实际意义。已宣布长宽比应固定的权力。无论如何,我会把它放在我的后兜里。
    【解决方案2】:

    试试这个重塑功能。它将保留您的纵横比,调整对象大小,并使视口居中。

    // 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() ;
    }
    

    【讨论】:

    • 谢谢 - 这很有用!
    【解决方案3】:

    试试这个:

    #include <GL/glut.h>
    
    size_t win_w = 0;
    size_t win_h = 0;
    
    void display(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, win_w, 0, win_h, -1, 1);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        glColor3ub(255,0,0);
        glPushMatrix();
            glTranslatef(win_w/2,win_h/2,0);
            glScalef(50,50,50);
            glBegin(GL_QUADS);
                glVertex2f(-1,-1);
                glVertex2f(1,-1);
                glVertex2f(1,1);
                glVertex2f(-1,1);
            glEnd();
        glPopMatrix();
    
        glFlush();
        glutSwapBuffers();
    }
    
    void reshape(int w, int h)
    {
        win_w = w;
        win_h = h;
        glViewport(0, 0, w, h);
    }
    
    int main(int argc, char **argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
    
        glutInitWindowSize(800,600);
        glutCreateWindow("Aspect Ratio");
    
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);
        glutMainLoop();
        return 0;
    }
    

    【讨论】:

    • 谢谢。但是,虽然对象的纵横比和居中保持不变,但它不会在调整窗口大小时调整大小。也就是说,如果对象一开始就占据了窗口高度的 3/4,那么在调整大小后它总是占据窗口高度的 3/4。
    • @PSU:是的,你是对的。我有一个稍微不同的版本,它做了正确的事情,我看看能不能把它拉起来。
    【解决方案4】:

    我认为你应该看看这个以获得正确的数字:

    self.hOffset = (self.wOffset / (16.0 / 9.0));
    self.xOffset = ((int)ceil((_backingWidth  / 2.0) - ((_backingWidth  + self.wOffset) / 2.0)));
    self.yOffset = ((int)ceil((_backingHeight / 2.0) - ((_backingHeight + self.hOffset) / 2.0)));
    
    glViewport(self.xOffset, self.yOffset, _backingWidth + self.wOffset, _backingHeight + self.hOffset );
    

    在上面的代码中,wOffset,即图像的宽度,通过一个滑块给或取它的值。第一行随着宽度以正确的比例增加而增加高度,恰好是 16:9(将宽度除以高度来获得比例效果不好;明确指定它最好)。接下来的两行调整图像的 x,y 坐标,使其在大小增加或减小时始终保持居中。

    到目前为止,这是一种更简单、更容易的方法,并且在 GPU 上更轻。如果我在这里看到的大型编码方法更好是有原因的,我想不通。祝你好运。

    【讨论】:

      猜你喜欢
      • 2021-10-05
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      相关资源
      最近更新 更多