Немного сумасшествия
Что такое кватернион — объяснение человеческим языком
Для закончивших ВУЗ данный вопрос не представляет проблемы, а для нас, учащихся ПТУ и техникумов, это тайна за семью замками. Особенно если вы, как и я, постоянно прогуливали высшую математику.
Цитата из википедии: Кватернио́ны (от лат. quaterni, по четыре) — система гиперкомплексных чисел, предложенная Гамильтоном в 1843 году.. Вы что-нибудь поняли? Значит дальше вам читать не надо, до свидания! Заходите еще..
Кватернион — это ось, относительно которой будем вращать объект и угол, на который мы будем вращать объект относительно этой оси. Всего у кватерниона четыре компоненты: X, Y, Z и W. XYZ — та самая ось поворота (нормализуем и каждый компонент умножаем на синус половины угла), W — угол поворота (который задается через косинус половины угла).
Псевдокод получения кватерниона из угла и оси:
def quatFromAngleAxis(self, a, x, y, z):
# Длина вектора xyz
l = sqrt(x * x + y * y + z * z)
# Нормализуем вектор xyz
x = x / l
y = y / l
z = z / l
# Синус половины угла (a - угол в радианах)
hSin = sin(a / 2)
# Заполняем xyz
self.x = x * hSin
self.y = y * hSin
self.z = z * hSin
# Косинус половины угла
hCos = cos(a / 2)
# Заполняем w
self.w = hCos
Важно помнить, что кватернион не задает результат, через него выражается действие, которое можно применить к какому-либо объекту в пространстве.
Ещё более простым языком: представьте, что у вас есть некий объект, допустим яблоко, вы протыкаете его спицей и вращаете. Так вот спица — это ось вращения, её направление — наш вектор (x, y, z)
, а угол вращения — это наш угол a
, который означает насколько вы повернули яблоко на спице по часовой стрелке или против.
Если вас приводит в недоумение термин «матрица», рекомендую почитать заметку: Что такое матрица 4×4 в трехмерных играх?
Углы Эйлера. Крен (roll), тангаж (pitch) и рыскание (yaw)
Наглядно об углах Эйлера. Сначала рыскание (yaw), затем тангаж (pitch), после этого крен (roll)
Примитивное управление камерой в Ogre3D
Задача: камера должна наблюдать за объектом, быть на расстоянии 5 метров от него и не менее 2.5 метров над землей.
Решение:
void initialise()
{
// Включаем слежение за объектом
camera->setAutoTracking(true, target)
}
void update()
{
// Нормаль направления цели
Vector3 targetDir = target->getOrientation() * Vector3::UNIT_Z).normalisedCopy();
// Позиция цели
Vector3 targetPos = target->getPosition();
// Позиция камеры
Vector3 cameraPos = camera->getPosition();
// Нормаль от цели к камере
Vector3 targetToCameraDir = (cameraPos - targetPos).normalisedCopy();
// Ставим камеру в координаты цели
cameraPos = targetPos;
// Сдвигаем камеру в направлении targetToCameraDir на 5 метров
cameraPos += 5.0f * targetToCameraDir;
// Регулируем высоту камеры
cameraPos.y = std::max(2.5f, cameraPos.y);
// Обновляем позицию камеры
camera->setPosition(cameraPos);
}