gluLookAt() не работает в OpenGL


Пытаюсь посмотреть на квадрат с другой стороны с помощью функции gluLookAt().
После использования функции ничего не меняется, хотя я ожидал, что углы квадрата изменятся.
Я наведите камеру на крайнюю правую часть мира и посмотрите в ее центр, где находится квадрат.
Пришлось растянуться в стороны. Почему ничего не изменилось?

Код:

#include "includes.h"

using namespace std;

constexpr auto FPS_RATE = 60;
int windowHeight = 600, windowWidth = 600, windowDepth = 600;

void init();
void idleFunction();
void displayFunction();
double getTime();

double getTime()
{
    using Duration = std::chrono::duration<double>;
    return std::chrono::duration_cast<Duration>(
        std::chrono::high_resolution_clock::now().time_since_epoch()
        ).count();
}

const double frame_delay = 1.0 / FPS_RATE;
double last_render = 0;

void init()
{
    glutDisplayFunc(displayFunction);
    glutIdleFunc(idleFunction);
    glViewport(0, 0, windowWidth, windowHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-windowWidth / 2, windowWidth / 2, -windowHeight / 2, windowHeight / 2, -windowDepth / 2, windowDepth / 2);
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
}

void idleFunction()
{
    const double current_time = getTime();
    if ((current_time - last_render) > frame_delay)
    {
        last_render = current_time;
        glutPostRedisplay();
    }
}

void displayFunction()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBegin(GL_POLYGON);
    gluLookAt(-300, 0, 0,
        0, 0, 0,
        0, 1, 0);
    glColor3f(1, 1, 1);
    glVertex3i(-150, 150, 0);
    glVertex3i(150, 150, 0);
    glVertex3i(150, -150, 0);
    glVertex3i(-150, -150, 0);
    glEnd();
    glutSwapBuffers();
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(windowWidth, windowHeight);
    glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - windowWidth) / 2, (GetSystemMetrics(SM_CYSCREEN) - windowHeight) / 2);
    glutCreateWindow("Window");
    init();
    glutMainLoop();
    return 0;
}

person German    schedule 12.07.2019    source источник


Ответы (1)


Проблема вызвана тем, что gluLookAt() вызывается с в последовательности glBegin/glEnd. Это не разрешено. Вы должны вызвать gluLookAt перед glBegin.
После того, как рисование примитивов было запущено glBegin разрешено указывать только координаты вершин (glVertex) и изменить атрибуты (например, glColor, glTexCoord ...), пока розыгрыш не завершится (glEnd).
Все остальные инструкции будут игнорироваться и вызовут ошибку GL_INVALID_OPERATION (код ошибки 1282).

Далее обратите внимание, что glLookAt не устанавливает текущую матрицу. Он определяет матрицу и умножает текущую матрицу на новую матрицу. Установите режим матрицы (glMatrixMode) и установить матрицу идентификации с помощью glLoadIdentity до gluLookAt.

С матрицей просмотра

gluLookAt(-300, 0, 0, 0, 0, 0, 0, 1, 0);

вы хотите «видеть» что угодно, потому что с этой матрицей линия обзора устанавливается вдоль оси x, и вы смотрите на двумерный многоугольник сбоку.

Обратите внимание, что многоугольник — это 2D-объект. Размер объекта кажется другим, если вы смотрите на него спереди, сбоку (тогда это линия и не видна) или с промежуточного направления. Первые 3 параметра gluLookAt определяют точку зрения, следующие 3 параметра определяют точку, на которую вы смотрите. Вектор от точки обзора до точки, на которую вы смотрите, является линией обзора.

Вероятно, вы хотите посмотреть по оси Z:

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

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 0, -300, 0, 0, 0, 0, 1, 0);    

    glBegin(GL_POLYGON);
    glColor3f(1, 1, 1);
    glVertex3i(-150, 150, 0);
    glVertex3i(150, 150, 0);
    glVertex3i(150, -150, 0);
    glVertex3i(-150, -150, 0);
    glEnd();

    glutSwapBuffers();
}

Вы используете ортографическую (параллельную) проекцию. Если бы вы использовали проекцию перспективы, то проецируемый размер объекта уменьшился бы, когда расстояние до точки обзора увеличивается. Перспективную проекцию можно настроить с помощью gluPerspective. например.:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0, (double)windowWidth / windowHeight, 0.1, 600.0);
person Rabbid76    schedule 12.07.2019
comment
Попробовал ваш вариант, но вижу только черный экран. - person German; 12.07.2019
comment
@ Да, я расширил ответ. Вы должны gluLookAt(0, 0, -300, 0, 0, 0, 0, 1, 0); - person Rabbid76; 12.07.2019
comment
Я добавил glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0, (double)window Width / window Height, 0.1, 600.0); в свою функцию init();. В displayFunction(); я добавил glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, -300, 0, 0, 0, 0, 1, 0); после glClear(...) и перед glEnable(...). Когда я бегу, я квадратничаю в виде очень маленькой точки в центре. - person German; 12.07.2019
comment
@Герман Прочитай ответ ...проекционный размер объекта будет уменьшаться, когда расстояние до точки зрения увеличивается.... Используйте gluLookAt(0, 0, -50, 0, 0, 0, 0, 1, 0); и объект увеличится. - person Rabbid76; 12.07.2019
comment
Спасибо за вашу помощь. Но все же мне кажется, что программа ведет себя некорректно. При смещении камеры хотя бы на пиксель в сторону квадрат слишком сильно растягивается. Я разместил видео на YouTube с этой проблемой. Я был бы рад, если бы вы посмотрели на это и объяснили мне, почему это происходит. Спасибо. - person German; 12.07.2019