Russian Qt Forum
Ноябрь 25, 2024, 22:48 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: libQGLViewer и управление мышкой направления смотрения камеры  (Прочитано 6102 раз)
Smogg
Гость
« : Ноябрь 17, 2014, 16:54 »

Подскажите в общих чертах, как в OpenGL (и в частности в libQGLViewer, если кто с этой либой баловался) вращать камеру в 3D в зависимости от 2-мерных передвижений мышки? А то я что-то смутно-смутно отражаю матричные трансформации... Надо умножать что-то на что-то. Первое "что-то" (или второе?) откуда-то берется, а второе (или первое?) есть единичная матрица, к которой применено вращение по соответствующим осям.

Но при всем при этом состояние камеры задается как Vector3, который есть точка, где камера находится и Vector4, который кватернион, у которого первые три числа - углы вращения по осям, а последний "scale" этого вращения. Но scale применяется сразу к трем осям...

То есть, я у меня есть в камере кватернион orientation и могу получить углы вращения камеры по нужным осям:
Код:
Quaternion qu = camera->orientation();
angleY = (currentPoint.x-previousPoint.x) * factX;
angleX = (currentPoint.f-previousPoint.y) * factY;
делаю какой-то магический  финт ушами:
Код:
qu = AbraCadabra(qu, AngleX, AngleY);
и засовываю получившееся обратно в камеру:
Код:
 camera->setOrientation(qu);

в чем магия в трех словах?

Википидийная дефиниция кватернионов это какой-то извращенный ахтунг:
Цитировать
Чем больше угол вращения, тем дальше вращение от единичного вращения — о таких вращениях можно думать как о концентрических сферах с увеличивающимся радиусом.
« Последнее редактирование: Ноябрь 17, 2014, 17:39 от Smogg » Записан
vulko
Гость
« Ответ #1 : Ноябрь 17, 2014, 19:42 »

С qglviewer не работал, не знаю что там.
В OpenGL есть разные способы.

Например чтобы камера смотрела на определенную точку, используй gluLookAt.
Вращение делается по 2-м углам и радиусу. Почитай про сферические координаты.
Записан
Smogg
Гость
« Ответ #2 : Ноябрь 17, 2014, 20:01 »

С qglviewer не работал, не знаю что там.
В OpenGL есть разные способы.

Например чтобы камера смотрела на определенную точку, используй gluLookAt.
Вращение делается по 2-м углам и радиусу. Почитай про сферические координаты.

Извиняюсь, я как-то коряво сформулировал вопрос(

Мне надо сделать движение камеры как в FirstPersonShooter. Но у меня есть только ориентация камеры заданная кватернионом относительно мировых координат и точка, где висит собственно камера. Такие вот свойства у Camera .

Чтобы делать чрез LookAt все равно придется связываться с кватернионами, потому что нужно определить прежнюю "точку рассматривания", построить вектор из точки висения в "точку рассматривания", привести его к началу координат, потом крутнуть этот вектор, переместить в точку висения, определить "точку нового рассматривания" и лишь после всего этого делать LookAt. Работать то будет работать, но уж больно через пеньколоду и обойти кватернион все равно не получится(... А кватернионы я не понимаю...
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #3 : Ноябрь 17, 2014, 22:49 »

На матрицы вообще никак не перейти?
Там прозрачнее.
Записан
Smogg
Гость
« Ответ #4 : Ноябрь 18, 2014, 04:07 »

На матрицы вообще никак не перейти?
Там прозрачнее.
разве только перекомпилять либу, самостоятельно добавив нужный функционал) Теоретически- можно, а практически - это последнее с чем я желал бы связаться.

Camera там действительно удобная. И от нее отказываться не хочу)
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Ноябрь 18, 2014, 08:48 »

Но при всем при этом состояние камеры задается как Vector3, который есть точка, где камера находится и Vector4, который кватернион, у которого первые три числа - углы вращения по осям, а последний "scale" этого вращения. Но scale применяется сразу к трем осям...
Первые три числа - это вектор, ось вращения. Последнее - угол поворота. Кватернион однозначно переводится в матрицу вращения (но не наоборот).

C libQGLViewer не сталкивался, сейчас глянул доку - все норм. Напр нужно повернуться вокруг текущей оси Y - берете viewDirection, вращаете его вокруг upVector и подаете обратно. Через кватернион тоже можно, но надо знать какие соглашения у них приняты (чему соответствует ось кватерниона). Распечатайте

orientation()
viewDirection()
upVector()
Записан
vulko
Гость
« Ответ #6 : Ноябрь 18, 2014, 12:09 »

Цитировать
void setOrientation   (   qreal    theta,
qreal    phi
)      
slot
Sets the orientation() of the Camera using polar coordinates.

theta rotates the Camera around its Y axis, and then phi rotates it around its X axis. The polar coordinates are defined in the world coordinates system: theta = phi = 0 means that the Camera is directed towards the world Z axis. Both angles are expressed in radians.

See also setUpVector(). The position() of the Camera is unchanged, you may want to call showEntireScene() after this method to move the Camera.

This method can be useful to create Quicktime VR panoramic sequences, see the QGLViewer::saveSnapshot() documentation for details.

вот же отличный метод есть.
Используй его. Для камеры типа шутера тебе нужно 2 угла, один для вращения вокруг оси Z, т.е. для того чтобы смотреть вокруг.
Ну и второй угол для того чтобы крутить камеру вверх/вниз.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Ноябрь 18, 2014, 12:56 »

Я в кватернионах 0. Так что на всякий случай напишу как я вращал кад модель с помощью матриц. Вдруг пригодится.

У нас имеется матрица представления (иначе ModelView). В ней хранятся значения, которые описывают позицию рабочей системы координат относительно глобального центра {0; 0; 0} и единичные вектора, которые указывают на направления осей.
Когда мы начинаем вращать геометрию мышкой мы берём за основу единичную матрицу. Проведя мышкой по экрану мы можем считать отрезок, начало которого находится в исходном положении, конец в конечном. Далее ищем перпендикуляр к этому отрезку и поворачиваем единичную матрицу вокруг этого перпендикуляра на n градусов (n зависит от манхэттенской длины отрезка помноженной на удовлетворительный коэффициент aka чувствительность поворота). Заметьте, координата Z не используется (кстати, в OpenGL она направлена из экрана к зрителю).
Далее мы получившуюся матрицу умножаем на нашу ModelView и получаем новую ModelView, с помощью которой перерисовываем наши данные.
Возможно еще придется скорректировать позицию рабочей СК.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 18, 2014, 14:48 »

Когда мы начинаем вращать геометрию мышкой мы берём за основу единичную матрицу. Проведя мышкой по экрану мы можем считать отрезок, начало которого находится в исходном положении, конец в конечном. Далее ищем перпендикуляр к этому отрезку и поворачиваем единичную матрицу вокруг этого перпендикуляра на n градусов (n зависит от манхэттенской длины отрезка помноженной на удовлетворительный коэффициент aka чувствительность поворота). Заметьте, координата Z не используется (кстати, в OpenGL она направлена из экрана к зрителю).
Чем обычная (Евклидова) длина не устроила? Наверное привлекает красивое слово "манхэттенский" Улыбающийся И как Вы нашли "перпендикуляр к отрезку" - ведь их же много, да еще и отрезок в координатах экрана.

Матрица поворачивается вокруг своих осей точно так же как вектор на плоскости, напр поворот вокруг z на угол a
Код:
x_new = x * cos(a) - y * sin(a);
y_new = x * sin(a) + y * cos(a);
z_new = z
Разница лишь в том что на плоскости x, y - числа, а для иатрицы - вектора, ее строки или столбцы. Как в OpenGL - не помню, ну вариантов всего 2.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #9 : Ноябрь 18, 2014, 16:08 »

Чем обычная (Евклидова) длина не устроила? Наверное привлекает красивое слово "манхэттенский" Улыбающийся И как Вы нашли "перпендикуляр к отрезку" - ведь их же много, да еще и отрезок в координатах экрана.
Манхэттенская длина просто считает количество смежных по ребру пикселей вместо кратчайшего расстояния. Меня больше привлекло поворачивать таким образом, потому что ведя мышь по диагоноли поворот будет осуществляться медленнее, чем поворот вызванный движением курсора ортогонально.

Перпендикуляров много, но нам нужно знать только единичный вектор направления. Единственное, мне нужно было подшаманить со знаком вектора, но это просто и описывать я не стану как это сделать. После того, как мы вычислили единичный вектор, который представляет наш перпендикуляр, пусть это будет QPointF(0.447, 0.894)), мы берём нашу единичную матрицу и выполняем её поворот
Код
C++ (Qt)
QMatrix4x4 rotateMatrix;
rotateMatrix.rotate(angle, 0.447, 0.894)
Матрица поворота готова. Бежим и умножаем её на нашу текущую...
Записан
vulko
Гость
« Ответ #10 : Ноябрь 18, 2014, 16:54 »

Как вариант ещё можно попробовать GLM. Мне отлично помогает для работы с матрицами, кватернионы там тоже были вроде...
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.083 секунд. Запросов: 23.