Фон
Определяя общий смысл up , вы вводите соглашение, которое позволяет вам определять рулон камеры дано только его вперед направление. Это соглашение работает до тех пор, пока вы не смотрите прямо вверх или прямо вниз. Нам, людям, нравится это, потому что наши глаза находятся рядом друг с другом, и нам приходится иметь дело со странными чувствами в нашей вестибулярной системе, когда наши головы наклонены в сторону. Держите оба уха ровно на одной высоте, и все хорошо. :)
Вот как это работает
Учебное пособие имеет следующее определение прямого вектора от рыскания и шага
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
Этот вектор указывает где-то в плоскости xz, когда шаг равен нулю, а когда высота высока (до максимума 89 °), он приближается к вектору (0,1,0), а когда высота звука низкая (до мин. -89 °), он приближается к вектору (0, -1,0).
Расчет матрицы камеры выполняет традиционную просмотр операцию , объясненную здесь , которая начинается с этого cameraFront
вектор является вперед вектором и пытается вычислить ортогональный правый вектор, беря перекрестное произведение cameraFront
и вектора cameraUp
. Ограничение диапазона высоты тона гарантирует, что front и cameraUp
никогда не будут коллинеарными, и поэтому всегда можно определить, какой путь right относительно up, Единственный раз, когда вправо не имеет смысла, это если вы смотрите прямо вверх или вниз - в этих случаях любое направление может быть правильным (при повороте камеры вдоль ее главной оси), и это будет быть неоднозначным, пытаясь вывести вправо из вперед в одиночку ..
Вот что вы сделали неправильно
Теперь, если все, что вы сделали, это изменили cameraUp
вектора на (0,0,1), без изменения способа определения высоты тона и рыскания, теперь вы вводите проблему, с которой вы можете легко получить вектор cameraFront
, который является коллинеарным с (0,0,1) , Если шаг равен нулю, то рыскание = 90 ° дает выход cameraFront
= (0,0,1), а рыскание = -90 ° дает выход cameraFront
= (0,0, -1). В обоих этих случаях будет получена единичная матрица (без решения) для матрицы камеры, поскольку перекрестное произведение с cameraFront
и cameraUp
равно нулю, то есть cameraRight
равно нулю, и все это разваливается.
На практике вектор не будет точно равен нулю из-за природы плавающей запятой, но он не даст хорошего стабильного вычисления матрицы ортогональной камеры из-за того, что перекрестное произведение равно нулю (или бесконечно близко к нулю) .
Вот как вы можете это исправить
Так что если вы хотите изменить cameraUp
на (0,0,1), то имеет смысл, что вам, вероятно, следует переделать определение шаг и рыскание также. Вы бы сохранили предел, что шаг колеблется от -89 до +89, но сделайте так, чтобы pitch = 0 давало векторы в плоскости xy вместо плоскости xz. По сути, выберите новый вектор для yaw = 0, pitch = 0 и убедитесь, что это вектор в плоскости xy. (Если я могу смело сделать предположение: + x, вероятно, все еще естественно вправо . Так что yaw = 0, вероятно, указывает вниз по оси y? Просто мое собственное предположение.)
Но это код что я вычеркнул (который вычисляет передний вектор из рыскания и высоты тона), который нужно переизобразить, чтобы хорошо играть с вашим определением up , равным (0,0,1).
На В конце дня, просто перемаркировка осей - это все, что вам нужно. Вот один из способов сделать это:
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
front.z = sin(glm::radians(pitch));