Artem.spb писал(а):Таки нет, никакой путаницы в терминологии, никто оси не вращает. Объект вращается вокруг выбранной оси.
Считайте, что объект вращается, если вам так легче. Оси вообще штука вспомогательная и реально не существующая. Но они сильно облегчают понимание. Я не зря предложил представить (или нарисовать программно) прямоугольную систему координат (СК). Почему - позже будет понятно.
Artem.spb писал(а):И опять нет. Вы невнимательны даже к своему примеру.
Где именно я невнимателен? Мой пример как раз демонстрирует работу поворота по Y и расположение объекта в СК сцены до и после этой операции. Если бы вы не отвергли сходу моё высказывание, то мне не пришлось бы отвечать на следующие две-три цитаты.
Artem.spb писал(а):Во-первых, если заглянуть внутрь функции Rotate X/Y/Z Axis, то там можно обнаружить вызов одной из двух: Set roration и Rotate, которые и выполняют относительное или абсолютное вращение (со смещением то же самое). И в описании этих функций ничего про смену точки отсчёта.
СК сцены не меняет своего положения при этих операциях. СК объекта - да, и именно её мы перемещаем (вместе с объектом, т.к. объект жёстко привязан к своей СК) в процессе транслирования и поворота. 3D Picture Control вообще слабо документирован, очень многих вещей просто нет в официальной справке. Не стоит обращать на это внимание.
Artem.spb писал(а):То есть, нет двух вариантов-антонимов "относительный поворот" / "абсолютный поворот".
Очень даже есть: в абсолютном случае при сохранении величины угла смещения объект остаётся на своём месте, сколько бы я ни жал на кнопку поворота. Сказали ему 5 градусов, он в 5 и повернулся (вокруг своего центра).
А если включить относительный поворот, то при каждом вызове функции объект будет смещаться на 5 градусов из текущего положения, и при этом поворот осуществляется относительно начала координат.
Повторюсь, что не считаю эти два режима поворота противоположными друг другу. Есть "относительный поворот" - с оглядкой на СК сцены и с учётом СК объекта, и "не относительный поворот" (пусть будет "абсолютный", раз так) - только с учётом СК объекта; СК сцены не принимает участия.
Artem.spb писал(а):Даже если принять вашу точку зрения, что абсолютно - это объект сам по себе, а относительно - это относительно начала координат, то во втором случае всё равно присутствует дополнительное действие. Точнее, доп действие присутствует в функции "абсолютно": в описании так и сказано: "Clears any rotations previously applied to an object". А вот относительное смещение не возвращает объект в начало координат.
А что будет, если не очищать матрицу преобразований? Получится "относительный поворот", только без сдвига объекта по осям СК сцены. Смысл создавать два (почти) одинаковых метода? Проще пользователю самому реализовать такой подход - сдвигаем объект в (0,0,0), крутим на нужный угол, сдвигаем обратно. Подозреваю, что именно такой метод вы бы хотели видеть в качестве "относительного поворота". Но это чуть иначе работает.
Вообще, прежде чем сходу отметать мои высказывания, стоило бы почитать матчасть. Начать можно, например, отсюда:
1.
OpenGL Transformation
2.
OpenGL Angles to Axes
3.
Народный учебник по OpenGL. Урок 4. Вращение полигонов
4.
Coordinate Systems in OpenGL
5.
Введение в OpenGL
6.
OpenGL: преобразование координат
И так далее. Плюс вот такая весьма неплохая книжка:
Компьютерная графика и стандарт OpenGL. 3-е издание. Дональд Херн, М. Паулин Бейкер
Итак, что мы имеем в очень кратком пересказе. Из [3] - наглядное представление поворота:
Чтобы лучше понять вращения по осям X, Y и Z я объясню это на примерах.
Ось X - предположим Вы работаете за токарным станком. Заготовка перемещается слева направо (также как ось X в OpenGL). Заготовка вращается вокруг оси X. Также мы вращаем что-то вокруг оси X в OpenGL.
Ось Y- Представьте что Вы стоите посреди поля. Огромный торнадо приближается к Вам. Центр торнадо перемещается от земли в небо (верх и низ, подобно оси Y в OpenGL). Предметы захваченные торнадо кружаться вдоль оси Y (центр торнадо) слева направо или справо налево. Когда вы вращаете что-то вокруг оси Y в OpenGL, это что-то будет вращаться также.
Ось Z - Вы смотрите на переднюю часть вентилятора. Передняя часть вентилятора ближе к Вам, а дальняя часть дальше от Вас (также как ось Z в OpenGL). Лопасти вентилятора вращаются вдоль оси Z (центр вентилятора) по часовой или против часовой стрелки. Когда Вы вращаете что-то вокруг оси Z в OpenGL, это что-то будет вращаться также.
Из [4] узнаём, какие существуют системы координат (СК) в OpenGL:
There are multiple coordinate Systems involved in 3D Graphics:
- ● Object Space
- ● World Space (aka Model Space)
- ● Camera Space (aka Eye Space or View Space)
- ● Screen Space (aka Clip Space)
[/i][/color]
То есть, имеем 4 основных СК: СК объекта (локальную СК), СК сцены (СК модели) (мировую СК), СК камеры и оконную СК. Нас сейчас интересуют только первые две.
Из [1] понимаем, что OpenGL выполняет все преобразования с помощью матриц размерностью 4x4, и есть 4 основных типа таких матриц: GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE и GL_COLOR. Именно первая отвечает за смещение (трансляцию), поворот, масштабирование как камеры, так и объектов на сцене, причём на каждый объект (помимо самой сцены) заводится отдельная матрица модели (ModelView). Есть и вот такая картинка, расшифровывающая назначение элементов матрицы:
Получается, что первые три столбца определяют поворот вокруг осей X,Y и Z соответственно, а последний столбец содержит смещения по этим трём осям. В [2] приведена та же картинка, а также расписано, как рассчитываются элементы матрицы GL_MODELVIEW для конкретного угла поворота. Возьмём, например, ось Y, поскольку я её использовал в своём примере.
Инфа эта вовсе не секретная. Вообще, проходится в технических ВУЗах на начальных курсах. Ну, и в интернете всё расписано.
Матрица поворота. Матрица поворота в трёхмерном пространстве
Теперь попробуем снова запустить пример
Axis Rotation Test.vi в
и посмотреть, какие получаются матрицы для "относительного" и "абсолютного" поворота. Сперва транслируем кубик на 3 единицы вдоль X, затем повернём на 15 градусов. Тип поворота регулируем кнопкой.
Небольшое примечание. даёт в явном виде просмотреть или изменить матрицу ModelView только для сцены. Аналогичные матрицы для объектов рассчитываются внутри движка, а снаружи можно "пощупать" только матрицу преобразований (Transformation Matrix). Однако, довольно просто получить из одного другое. Положим, A - матрица ModelView сцены, B - матрица преобразований объекта, C - матрица ModelView объекта. Справедливо такое выражение:
C = A x B
Отсюда можем получить при желании:
B = A^-1 x C
A = C x B^-1
И это действительно так. Матрицы преобразований не хранятся, а рассчитываются "на лету":
Код: Выделить всё
glMatrixMode(GL_PROJECTION)
glLoadMatrixd({2.41, 0, 0, 0, 0, 2.41, 0, 0, 0, 0, -1.00, -1, 0, 0, -2.00, 0})
glMatrixMode(GL_MODELVIEW)
glLoadMatrixd({-0.81, -0.36, 0.45, 0, 0.58, -0.51, 0.63, 0, 0, 0.77, 0.63, 0, 0, 0, -11.09, 1})
glLoadMatrixd({-0.81, -0.36, 0.45, 0, 0.58, -0.51, 0.63, 0, 0, 0.77, 0.63, 0, 0, 0, -11.09, 1})
Ну, то есть, сначала грузится матрица проекций, затем две матрицы моделей - одна для сцены, другая для объекта. Как видим, в самом начале, когда мы ещё не трогали объект, его матрица ModelView равна матрице сцены. Как только мы сдвинем объект с помощью трансляции или поворота, матрица ModelView объекта примет другие значения. Матрицы грузятся на каждой итерации рендеринга, т.о. постоянно обновляя все элементы 3D контрола.[/size]
Матрица преобразований для "абсолютного" поворота:
На рисунке видно, что центр объекта действительно смещён на 3 единицы по X (последний столбец матрицы), а сам объект повёрнут на 15 градусов (первые три столбца матрицы содержат синус 15°, косинус 15° и т.д. согласно описанию выше).
Матрица преобразований для "относительного" поворота:
На этой картинке видим, что объект точно так же повёрнут на 15° (первые три столбца матрицы такие же, как в случае "абсолютного" поворота), однако центр объекта смещён и по X, и по Z, а смещения какие-то "странноватые". Откуда взялись эти смещения?
Вот отсюда:
X' = X*cos (a) + Z*sin (a)
Y' = Y
Z' = Z*cos (a) - X*sin (a)
Это не что иное, как координаты локальной СК при повороте относительно глобальной СК:
Описание направлений и поворотов в трёхмерном пространстве
По каким формулам вычислить новые координаты объекта в трёхмерном пространстве при относительном перемещении?
Аналогичные формулы выведены и для поворота в двумерном пространстве:
Поворот
Поворот плоскости и его матричное представление
Поворот осей координат
И в принципе это всё выглядит довольно логично. При "относительном" повороте мы учитываем значения, на которые уже смещён центр объекта (т.е., точка отсчёта локальной СК) по осям и по этим смещениям рассчитываем новые координаты центра объекта. При "абсолютном" повороте нам "по барабану", на какое расстояние от глобальной СК смещёна локальная СК:
X' = X
Y' = Y
Z' = Z
Для большей наглядности я переделал свой предыдущий пример
Axis Rotation Test: воспроизведен механизм работы инструмента
Rotate Y-axis.vi. Когда кнопка
Native Rotation? не нажата, рассчитывается и составляется матрица преобразований (Transformation Matrix), после чего она применяется к объекту (кубику) на сцене через соответствующий Property Node. Если кнопка нажата, для поворота используется стандартный
Rotate Y-axis.vi. На панель также выведено несколько матриц: матрица модели сцены (Scene ModelView Matrix), матрица проекций (Scene Projection Matrix), текущая матрица преобразований объекта (Object Transf. Matrix (native)) и матрица преобразований объекта (Object Transf. Matrix (own)), рассчитанная согласно вышеописанной логике (расчёт ведётся только при повороте). Также имеется индикатор
Matrixes are equal, который загорается, когда обе матрицы преобразований (текущая и рассчитанная) равны. По индикатору можно понять, что рассчитанная матрица в точности равна той матрице, что применяет
Rotate Y-axis.vi. Единственный нюанс, который для меня остался не совсем понятен: почему движок работает с числами двойной точности (double, 8 байт), а "наружу" (т.е., в
) отдаёт числа одинарной точности (float, single, 4 байта). Из-за такой вот нестыковки происходит серьёзная потеря точности, из-за чего, например, нельзя использовать машинный эпсилон.