OpenGL, как перемещать сцену в ответ на ввод мыши с помощью gluLookAt

Я использую OpenGL в Qt через QGLWidget и пытаюсь реализовать базовое взаимодействие с мышью и клавиатурой.

Так, например, клавиши со стрелками на клавиатуре будут использоваться для «панорамирования» сцены, колесико мыши — для увеличения сцены, а мышь следует использовать для вращения модели.

Я понял, как реализовать панорамирование и масштабирование, но у меня проблемы с вращением.

Это то, что у меня есть до сих пор:

void MyGLWidget::paintGL() {
    glLoadIdentity();
    gluLookAt(0+camDelta[0],0+camDelta[1],-100+camDelta[2],centerCoords[0]+lookAtDelta[0],centerCoords[1]+lookAtDelta[1],centerCoords[2]+lookAtDelta[2],0,1,0);
    // draw stuff here
}

Итак, в основном я установил начальные параметры gluLookAt, а затем добавил два массива, float camDelta[3] и float lookAtDelta[3], чтобы отслеживать изменение положения камеры и того, куда она смотрит, в ответ на взаимодействие пользователя со сценой.

Для колеса мыши я делаю:

void MyGLWidget::wheelEvent(QWheelEvent *event) {
    camDelta[2] += (event->delta() / 8.0 / 15.0) * WHEEL_DELTA;
    lookAtDelta[2] += (event->delta() / 8.0 / 15.0) * WHEEL_DELTA;
    updateGL();
}

Точно так же в MyGLWidget::keyPressEvent я изменяю поле дельт [0] для панорамирования влево и вправо, а дельты [1] для панорамирования вверх и вниз.

Итак, мой вопрос: как мне реализовать что-то подобное для поддержки вращения с помощью мыши? Я немного запутался, потому что я предполагаю, что мне придется как-то изменить не только то, куда смотрит камера, но и вектор вверх, но у меня нет четкого представления о том, как это сделать.


person houbysoft    schedule 12.06.2012    source источник
comment
Привет, Houbysoft, я также ищу функцию панорамирования в Android. [Мне нужно переместить GLSurfaceview с помощью сенсорного события]. если у вас есть какие-либо идеи сейчас, пожалуйста, дайте любой пример кода. мне было бы полезно завершить свою работу. мой пример кода здесь. .который   -  person harikrishnan    schedule 06.07.2013


Ответы (2)


То, что я сделал для подобных вещей, называется моделью орбитальной камеры.

Вы отслеживаете положение цели камеры (или смотрите на нее) и 3 других параметра: азимут, склонение (или наклон) и расстояние (или радиус). Азимут — это вращение камеры вокруг цели по горизонтали (как если бы цель находилась на земле, а вы ходили вокруг нее по кругу, глядя на нее). Склонение - вертикальное вращение. Расстояние — это, ну, расстояние между целью и камерой.

Их также называют сферическими координатами:

http://mathworld.wolfram.com/SphericalCoordinates.html

Вам нужны такие уравнения:

x = r * sin(phi) * cos(theta)
y = r * sin(phi) * sin(theta)
z = r * cos(phi)

Где r — расстояние, тета — азимут, а фи — склонение. Это дает вам смещение для перехода от положения взгляда камеры к положению камеры.

Итак, вот что вы делаете. Сохраняйте целевое положение камеры, но не положение камеры. Когда вы панорамируете камеру, перемещайте целевое положение. При повороте камеры регулируйте азимут и склонение. Когда вы масштабируете камеру, регулируйте расстояние. Затем в каждом кадре перед вызовом gluLookAt вычисляйте положение камеры, используя приведенную выше формулу. Вы просто добавляете эти x, y и z к целевой позиции.

person J. Alan Atherton    schedule 15.06.2012
comment
Привет, Алан, я также ищу функцию панорамирования в Android. [Мне нужно переместить GLSurfaceview с помощью сенсорного события]. если у вас есть какие-либо идеи сейчас, пожалуйста, дайте любой пример кода. мне было бы полезно выполнить мою задачу. Я борюсь здесь. мой пример кода здесь. - person harikrishnan; 06.07.2013

Лучший подход для этого — использовать кватернионы. Подобно тому, как комплексные числа весьма полезны для вращения в 2D, кватернионы идеально подходят для вращения в 3D.

Стандартный «поворот вокруг оси x, y, z» может работать, он будет вести себя странно и не так, как ожидалось.

Вы можете получить хороший учебник обо всем этом по адресу: http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation

person Ivan    schedule 15.06.2012
comment
Привет, Иван, я также ищу функцию панорамирования в Android. [Мне нужно переместить GLSurfaceview с помощью сенсорного события]. если у вас есть какие-либо идеи сейчас, пожалуйста, дайте любой пример кода. мне было бы полезно выполнить мою задачу. Я борюсь здесь. мой пример кода здесь. - person harikrishnan; 06.07.2013