使用Qt / OpenGL保持正交投影比例的问题

时间:2016-08-19 23:00:04

标签: qt opengl orthographic

我很难理解我在QMatrix4x4 :: ortho(左,右,底,顶,近,远)的调用中应该使用哪些值。

具体来说,我不了解left,right,bottom和top值的文档。我有一个可以用投影矩阵绘制OpenGL猴子的工作演示。我设置了演示,这样当我在键盘上点击“O”时,它会将投影矩阵从透视切换到正交。透视投影效果很好,因为它保持模型的纵横比不变(即它不会在宽度或高度上拉伸)。这是在调用'O'或'P'键并更新m_proj时调用的函数。这是一个热点,因为你可以看到我已经尝试了一堆想法,但没有一个真正按照我想要的方式工作。

感谢任何有助于我理解这一点的见解。其他有用的细节:我的视线在z = 2面向中心(0,0,0),向上是(0,1,0)。

void AppGLScene::setProjectionMatrix(void)
{
    m_projectionMatrix.setToIdentity();
    float windowWidth = rect().width();
    float windowHeight = rect().height();
    float left, right, bottom, top;
    float aratio = (float) windowWidth / (float) windowHeight;
    qDebug() << "win wid, win hei" << windowWidth << windowHeight;

    // I modify the vertical FOV in an attempt to keep the size of the
    // model the same as the vertical size of the window changes.
    //
    float vFov = 90 * ((float)windowHeight / m_initialWinHeight);
    qDebug() << "vFov" << vFov;

    switch (m_proj)
    {
    case PROJ_PERSP:
        m_projectionMatrix.perspective(vFov, qreal(windowWidth)/qreal(windowHeight), 0.5, 40);
        break;
    case PROJ_ORTHO:
    default:
//        left = rect().x();
//        right = rect().x() + rect().width();
//        bottom = rect().y();
//        top = rect().y() + rect().height();
        if (windowWidth > windowHeight)
        {
            left = -(3.0 - ((float)windowHeight/(float)windowWidth));
            right = -left;
            bottom = -3.0;
            top = 3.0;
        }
        else
        {
            left = -3.0;
            right = 3.0;
            bottom = -(3.0 - ((float)windowWidth/(float)windowHeight));
            top = -bottom;
        }

        qDebug() << "l r b t = " << left << right << bottom << top;
        m_projectionMatrix.ortho(left, right, bottom, top, 0.5, 40);
//        m_projectionMatrix.ortho(-3.0, 3.0, -3.0, 3.0, 0.5, 40);
//        m_projectionMatrix.ortho(-aratio, aratio, -aratio, aratio, 0.5, 40);
        break;
    }
}

1 个答案:

答案 0 :(得分:3)

为避免在任一方向上拉伸对象,您需要使(右 - 左)/(上 - 下)与窗口的纵横比相匹配。在您的情况下,您可以通过 right 确保 top 的值乘以宽高比来确保。

看起来您希望将范围[-3.0,3.0]用于较短的窗口尺寸,并相应地调整较长的窗口尺寸。以上转换为:

    if (windowWidth > windowHeight)
    {
        top = 3.0f;
        bottom = -top;
        right = top * aratio;
        left = -right;
    }
    else
    {
        right = 3.0f;
        left = -right;
        top = right / aratio;
        bottom = -top;
    }

注意两种情况下的 right / top = aratio