Как правильно настроить сцену OpenGL для визуализации отдельных объектов - PullRequest
2 голосов
/ 22 февраля 2009

Мне нужно написать простой визуализатор для моего инструментария меша. Объекты, с которыми я работаю, всегда находятся внутри поля [-1,1] ^ 3 (включительно), поэтому мне нужно убедиться, что объект будет полностью виден пользователю. Я также хочу иметь возможность вращать камеру вокруг объекта, как будто пользователь «летает» вокруг объекта.

Вот как я это делаю:

static void Reshape(int w, int h)
{
    glViewport(0,0,(GLsizei) w, (GLsizei) h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    float maxDistance = sqrt(2);
    if (w <= h)
    {
        glOrtho(-maxDistance, maxDistance, -maxDistance * (GLfloat)h / (GLfloat)w,
            maxDistance * (GLfloat)h / (GLfloat)w, -6.0, 6.0);
    }
    else
    {
        glOrtho(-maxDistance * (GLfloat)w / (GLfloat)h, maxDistance * (GLfloat)w / (GLfloat)h,
            -maxDistance, maxDistance, -6.0, 6.0);
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

static void PolarView(GLdouble distance, GLdouble twist, GLdouble elevation)
{
    double centerx, centery, centerz;
    double eyex, eyey, eyez;

    eyex = distance * cos(-twist) * cos(elevation);
    eyey = distance * sin(-twist) * cos(elevation);
    eyez = distance * sin(elevation);
    centerx = centery = centerz = 0;

    gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0, 0, 1);
}

Функция Reshape вызывается во время начальной настройки, и после каждого изменения размера элемента управления визуализатора функция PolarView вызывается для каждого перерисовки с некоторыми углами и расстоянием, большим квадратного корня из 3 (это действительно имеет значение?). Этот код прекрасно работает с выпуклыми объектами, такими как куб или сфера, но у него есть некоторые проблемы с объектом тора (некоторые грани видны через другие), поэтому я считаю, что это что-то о глубинном тестировании. Что не так с моей настройкой? Снимок экрана:
Bad torus
Bad torus filled
Я провел поиск в Интернете и обнаружил, что такая проблема может возникнуть, если что-то не так с параметрами моей ближней и дальней плоскости. Каковы правильные значения для них в моем случае? Моя процедура рисования выглядит так:

glEnable(GL_DEPTH_TEST);
glClearDepth(1);
glPolygonMode(GL_FRONT, GL_LINE); // Changing of GL_LINE to GL_FILL doesn't fixing my problem, it just changing the appearance of the model.
glClearColor(BackColor.R / 255.0f, BackColor.G / 255.0f, BackColor.B / 255.0f, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
PolarView(sqrt(3), _phi, _theta);
// .. only draws 

Мой PIXELFORMATDESCRIPTOR:

        PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        24,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        32, // Depth buffer size
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0,
        0,
        0
    };

Я нашел несколько способов обойти это:

  • Поменять значения для моих ближних и дальних самолетов
  • установить glDepthFunc на GL_GREATER и glClearDepth на 0
    Хорошо, мой код будет работать нормально, если есть четное количество ошибок. Но где первая ошибка?

Ответы [ 2 ]

2 голосов
/ 22 февраля 2009

Вы читали FAQ по OpenGL 12 ?

Единственное, что выглядит подозрительно в вашем коде, это отрицательная ближняя плоскость. Отрицательные значения Z находятся за камерой, что обычно является ошибкой при рендеринге 3D-сцены. Однако это само по себе не должно вызывать проблем, с которыми вы сталкиваетесь, и диапазон [-6,6] для Z должен обеспечивать достаточную точность для сцен такого типа.

Вы звоните glEnable(GL_DEPTH_TEST)? Вы передаете GL_DEPTH_BUFFER_BIT на glClear каждый кадр?

Обновление: вы звоните glPolygonMode(GL_FRONT, GL_LINE). Это означает, что передние треугольники нарисованы только в общих чертах, что означает, что если передний треугольник A перекрывает другой передний треугольник B, вы можете видеть сквозь A до краев B. С выпуклым телом это не может произойти так что вы не замечаете проблему.

Если вы хотите, чтобы треугольники перекрывали треугольники позади них, вам необходимо заполнить их в режиме GL_FILL. Чтобы получить каркасную фигуру, вам нужно нарисовать модель с белой заливкой, а затем снова нарисовать модель с черным контуром, например:

glDepthFunc(GL_LEQUAL);
glPolygonMode(GL_FRONT, GL_FILL);
/* draw the model in white */
glDepthFunc(GL_EQUAL);
glPolygonMode(GL_FRONT, GL_LINE);
/* draw the model again in black */

Идея состоит в том, что на втором проходе над моделью мы хотим нарисовать только контуры, которые не затенены каким-то треугольником, нарисованным на первом проходе, который ближе к камере (то есть с более низким Z).

Еще одна идея: я думаю, что ваша камера может указывать в неправильном направлении. Это объясняет, почему сцена рисуется неправильно с точки зрения glOrtho, а не с точки зрения glFrustum. В случае glOrtho вся сцена рисуется за камерой ; именно поэтому он нарисован с Z-порядком в неправильном направлении. Когда вы устанавливаете ближнюю плоскость на положительное число, вся сцена отбраковывается.

0 голосов
/ 23 февраля 2009

"8.070 Как автоматически рассчитать представление, отображающее всю мою модель? (Я знаю ограничивающую сферу и вектор вверх.)" запись в FAQ по OpenGL 8 отвечает на мой вопрос , Однако мои настройки немного отличаются, вот мои переписанные функции PolarView и Reshape:

static void Reshape(int w, int h)
{
    float diameter = sqrt(3);
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    GLdouble zNear = 1;
    GLdouble zFar = zNear + diameter * 2;
    GLdouble left = -diameter;
    GLdouble right = diameter;
    GLdouble top = -diameter;
    GLdouble bottom = diameter;
    double aspect = (double)w / (double)h;
    if (aspect < 1)
    {
        bottom /= aspect;
        top /= aspect;
    }
    else
    {
        left *= aspect;
        right *= aspect;
    }
    glOrtho(left, right, bottom, top, zNear, zFar);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

static void PolarView(GLdouble twist, GLdouble elevation)
{
    float diameter = sqrt(3);
    double distance = diameter * 2;
    double centerx, centery, centerz;
    double eyex, eyey, eyez;

    eyex = distance * cos(twist) * cos(elevation);
    eyey = distance * sin(twist) * cos(elevation);
    eyez = distance * sin(elevation);
    centerx = centery = centerz = 0;
    gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, 0, 0, 1);
}  
...