Как правильно использовать gluLookAt?

Я не хочу вдаваться в сложную тригонометрию для расчета вращений и тому подобного для моего трехмерного мира, поэтому gluLookAt кажется хорошей альтернативой. Согласно документации все, что мне нужно сделать, это разместить 3 координаты для положения камеры, три для того, на что я должен смотреть, и положение «вверху». Последнее не имело смысла, пока я не предположил, что оно должно быть под прямым углом к ​​линии обзора в том направлении, в котором должна быть верхняя часть экрана.

Это вообще так не работает. У меня есть код на питоне. Это код, который инициализирует некоторые данные и некоторый код режима, когда я вхожу в эту часть игры:

def init(self):
    self.game_over = False
    self.z = -30
    self.x = 0
def transfer(self):
    #Make OpenGL use 3D
    game.engage_3d(45,0.1,100)
    gluLookAt(0,0,-30,0,0,0,0,1,0)

«game.engage_3d(45,0.1,100)» в основном настраивает матрицу проекции так, чтобы она имела угол обзора 45 градусов и ближнюю и дальнюю координаты 0,1 и 100.

Первый gluLookAt красиво ставит камеру в правильное положение.

У меня нарисован куб с центром (0,0,0), и он отлично работает без gluLookAt. Прежде чем я нарисую его, у меня есть этот код:

gluLookAt(self.x,0,self.z,0,0,0,0,1,0)
if game.key(KEY_UP):
    self.z += 2.0/game.get_fps()
if game.key(KEY_DOWN):
    self.z -= 2.0/game.get_fps()
if game.key(KEY_LEFT):
    self.x += 2.0/game.get_fps()
if game.key(KEY_RIGHT):
    self.x -= 2.0/game.get_fps()

Теперь, исходя из этого, верхнее положение всегда должно быть таким же, как и всегда под прямым углом. Я думал, что он будет двигаться вперед и назад по оси Z с помощью клавиш вверх и вниз, а также влево и вправо по оси X с помощью клавиш влево и вправо. Что на самом деле происходит, так это то, что когда я использую левую и правую клавиши, куб будет вращаться вокруг «глаза», ускоряясь клавишами. Клавиша «вверх» заставляет другой куб из ниоткуда прорезать экран и ударять по первому кубу. Клавиша «вниз» возвращает таинственный клонированный куб. Это может быть объединено с вращением, чтобы получить совершенно другой результат, как указано в документации.

Что не так?

Спасибо.


person Matthew Mitchell    schedule 31.07.2010    source источник


Ответы (1)


(Интуиция, стоящая за вектором «вверх» в gluLookAt, проста: посмотрите на что угодно. Теперь наклоните голову на 90 градусов. То, где вы находитесь, не изменилось, направление, на которое вы смотрите, не изменилось, но изображение в вашем на сетчатке точно есть. Какая разница? Куда указывает макушка. Это восходящий вектор.)

Но чтобы ответить на ваш вопрос: вызовы gluLookAt не должны объединяться. Другими словами, единственный шаблон, в котором можно использовать gluLookAt, если вы точно не знаете, как он работает, следующий:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(...);
# do not touch the modelview matrix anymore!

Из вашего кода кажется, что вы делаете что-то вроде этого:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(...);
# some stuff..
gluLookAt(...);

Это приведет к странным результатам, потому что gluLookAt умножает текущую матрицу на вычисленную матрицу просмотра. Если вы хотите объединить преобразования, вам действительно лучше выяснить, как заставить glTranslate, glScale и glRotatef работать на вас. Более того, вы должны изучить, как работают преобразования координат, и придерживаться glMultMatrix.

person Carlos Scheidegger    schedule 31.07.2010
comment
Спасибо большое. Теперь он работает отлично. Теперь я могу перейти к более продвинутым вещам. Но вы говорите, что gluLookAt медленный? - person Matthew Mitchell; 01.08.2010
comment
Дело не в том, что это медленно. Дело в том, что gluLookAt скрывает несколько вещей, о которых вам следует знать, когда вы серьезно занимаетесь программированием на OpenGL. В частности, следует научиться комбинировать различные преобразования координат. К этому нужно привыкнуть и поначалу это несколько разочаровывает, но в конце концов это окупается: многие графические приемы построены на умном преобразовании систем координат. - person Carlos Scheidegger; 02.08.2010