Грязный код gluPerspective

Меня интересует функция gluPerspective. Я переводил код для своего движка, когда увидел, что код этой функции беспорядочный.

void glhPerspectivef2(float *matrix, float fovyInDegrees, float aspectRatio,
                  float znear, float zfar)
{
    float ymax, xmax;
    float temp, temp2, temp3, temp4;
    ymax = znear * tanf(fovyInDegrees * M_PI / 360.0);
    //ymin = -ymax;
    //xmin = -ymax * aspectRatio;
    xmax = ymax * aspectRatio;
    glhFrustumf2(matrix, -xmax, xmax, -ymax, ymax, znear, zfar);
}

Почему он создает temp, temp2, temp3 и temp4? Почему там закомментированный код? Я полагаю, это для указания некоторых параметров glFrustum. Но тогда почему xmin = -ymax * aspectRatio; а не xmin=-max;


person Benoît Dubreuil    schedule 11.01.2014    source источник


Ответы (2)


Я понятия не имею, откуда у вас эта функция... Но если вы действительно хотите вычислить матрицу перспективы, вы можете сделать это так.

Где следующий m определяется как float m[16]; и где функция zero() устанавливает все поплавки в m на 0.0f

void perspective(const float &fovy, const float &aspect, const float &zNear, const float &zFar)
{
    float range = tanf(fovy / 2.0f) * zNear;
    float sx = (2.0f * zNear) / (range * aspect + range * aspect);
    float sy = zNear / range;
    float sz = -(zFar + zNear) / (zFar - zNear);
    float pz = -(2.0f * zFar * zNear) / (zFar - zNear);

    zero();

    m[0] = sx;
    m[5] = sy;
    m[10] = sz;
    m[14] = pz;
    m[11] = -1.0f;
}
person vallentin    schedule 11.01.2014
comment
Если я, к сожалению, неправильно понял, эта строка: float sx = (2.0f * zNear) / (диапазон * аспект + диапазон * аспект); можно заменить на это: float sx = zNear / (диапазон * аспект); - person Graham Asher; 19.08.2014
comment
Можете ли вы объяснить несоответствие между этим кодом, который устанавливает 5 элементов матрицы в ненулевые значения, и другим кодом, таким как opengl.org/wiki/GluPerspective_code, который устанавливает для 7 элементов ненулевые значения. Похоже, что вы пропустили элементы 8 и 9 в порядке возрастания строк. - person Graham Asher; 21.08.2014
comment
@GrahamAsher матрица перспективы отличается от усеченной матрицы, поэтому они нам не нужны. - person vallentin; 21.08.2014

Вы получили этот код на этой вики-странице: http://www.opengl.org/wiki/GluPerspective_code случайно?

Почему он создает temp, temp2, temp3 и temp4?

Да, неиспользуемые переменные. Скорее всего скопировано из реализации glhFrustumf2.

Почему там закомментированный код? Я полагаю, это для указания некоторых параметров glFrustum.

Да, наверное, чтобы объяснить значения параметров, передаваемых в функцию glhFrustumf2.

Но тогда почему xmin = -ymax * aspectRatio; а не xmin=-max;

Да, xmin = -xmax правильно и позволяет избежать дублирования.

Я обычно использую аналогичный подход: перспектива реализуется в терминах усеченной пирамиды, а сама усеченная пирамида реализуется в терминах простой установки всех коэффициентов матрицы (это позволяет скрыть формат хранения, т. е. по строкам или по столбцам). Кроме того, наличие тех же соглашений об именах для параметров, что и на справочных страницах OpenGL, очень помогает, когда вам позже понадобится обратиться к коду.

void
setPerspectiveMatrix4x4f(float fovy, float aspect, float zNear, float zFar, float* m)
{
    const float bottom = -zNear * tanf(0.5f * fovy * M_PI / 180.0f);
    const float top    = -bottom;

    const float left   = aspect * bottom;
    const float right  = -left;

    setFrustumMatrix4x4f(left, right, bottom, top zNear, zFar, m);
}

void
setFrustumMatrix4x4f(float left, float right, float bottom, float top, float zNear, float zFar, float* m)
{
    const float dx = right - left;
    const float dy = top - bottom;
    const float dz = zFar - zNear;

    const float mx = 0.5f * (left + right);
    const float my = 0.5f * (bottom + top);
    const float mz = 0.5f * (zNear + zFar);

    const float n = zNear;
    const float nf = zNear * zFar;

    setMatrix4x4f(2.0f * n / dx,          0.0f,  2.0f * mx / dx,           0.0f,
                           0.0f, 2.0f * n / dy,  2.0f * my / dy,           0.0f,
                           0.0f,          0.0f, -2.0f * mz / dz, -2.0f * nf / dz,
                           0.0f,          0.0f,           -1.0f,           0.0f,
                  m);
}

void
setMatrix4x4f(float m00, float m01, float m02, float m03,
              float m10, float m11, float m12, float m13,
              float m20, float m21, float m22, float m23,
              float m30, float m31, float m32, float m33,
              float* m)
{
    // Fill m with m00, ... in row-major or column-major order
}
person user3146587    schedule 11.01.2014