У меня возникла большая проблема с ограничением угла наклона камеры (от -90º до 90º) с помощью приведенного ниже кода. Это своего рода продолжение этот вопрос.
Проблема, похоже, в том, что камера поворачивается более чем на -90º или более чем на +90º, и когда это произойдет, я буду смотреть вниз (или вверх), но вид просто повернется на 180º вокруг оси Y.
Пример: я смотрю на север, глядя на горизонт, и начинаю смотреть вниз до тех пор, пока не могу больше опускаться (ограничено приведенным ниже кодом). Затем я начинаю смотреть вверх и смотрю на юг.
void Camera::Rotate(Vector3D angle) {
angle = angle * CAMERA_ROTATION_SPEED;
accumPitchAngle += angle.x;
if(accumPitchAngle > 90.0f) {
angle.x = 90.0f - (accumPitchAngle - angle.x);
accumPitchAngle = 90.0f;
}
if(accumPitchAngle < -90.0f) {
angle.x = -90.0f - (accumPitchAngle - angle.x);
accumPitchAngle = -90.0f;
}
// Rotate along the WORLD_SKY_VECTOR axis (yaw/heading rotation)
// WORLD_SKY_VECTOR = (0.0f, 1.0f, 0.0f)
if(angle.y != 0.0f) {
Reference = RotateArbitraryAxis(Reference, WORLD_SKY_VECTOR, angle.y);
RightVector = Vector3D::CrossProduct(Reference, WORLD_SKY_VECTOR);
UpVector = Vector3D::CrossProduct(RightVector, Reference);
}
// Rotate along the x axis (pitch rotation)
if(angle.x != 0.0f) {
Reference = RotateArbitraryAxis(Reference, RightVector, angle.x);
UpVector = Vector3D::CrossProduct(RightVector, Reference);
}
// Makes sure all vectors are perpendicular all the time
Reference.Normalize();
RightVector = Vector3D::CrossProduct(Reference, UpVector);
RightVector.Normalize();
UpVector = Vector3D::CrossProduct(RightVector, Reference);
UpVector.Normalize();
}
Vector3D Camera::RotateArbitraryAxis(const Vector3D v, Vector3D u, double angle) {
Vector3D result;
u.Normalize();
double scalar = Vector3D::DotProduct(v, u);
double c = cos(Math::DegreesToRadians(angle));
double s = sin(Math::DegreesToRadians(angle));
double a = 1.0f - c;
result.x = u.x * scalar * a + (v.x * c) + ((-u.z * v.y) + (u.y * v.z)) * s;
result.y = u.y * scalar * a + (v.y * c) + (( u.z * v.x) - (u.x * v.z)) * s;
result.z = u.z * scalar * a + (v.z * c) + ((-u.y * v.x) + (u.x * v.y)) * s;
return result;
}
Вероятно, проблема в операторе if(angle.y != 0.0f)
, если я прокомментирую этот блок кода, проблема вообще не существует. Это как-то связано с WORLD_SKY_VECTOR
, но этот код таков, что позволяет мне поверните заголовок и держите камеру горизонтально. Если бы я вместо этого использовал UpVector
, проблема была бы решена. Но это годится только для авиасимулятора, мне нужно выровнять горизонт, вот причина WORLD_SKY_VECTOR
. Но кажется, что это причина «переключения в сторону», когда я направляю камеру прямо вниз.
Согласно запросу в комментарии ниже... Это для камеры от первого лица (и третьего лица, но я еще не начал реализовывать эту часть), и когда я смотрю прямо вниз, -90º (или прямо вверх, +90º) и когда угол изменяется от -89º до -91º (или от +89º до +91º), я хочу, чтобы камера предотвращала это и не выходила за пределы -90º, +90º. Когда он достигает этого предела, мне нужно, чтобы камера могла вернуться (либо вверх, если я на -90º, либо вниз, если я на +90º). Прямо сейчас это работает только иногда, в других случаях я буду смотреть в другую сторону, а не так, как я изначально смотрел.
UpVector
, а неWORLD_SKY_VECTOR
, я изменил это для другой проблемы, которая у меня была, и, пока я ее исправил, я облажался с этой. Однако это все еще не решает проблему. Я обновил вопрос, почему мой полный код для функцииRotate()
, пожалуйста, взгляните. Также удалил мой второй вопрос, который, возможно, больше не актуален, я опубликую еще один вопрос, если потребуется, отредактируйте свой пост, чтобы удалить ответ на второй вопрос, если хотите. 22.03.2011WORLD_SKY_VECTOR
наUpVector
в коде под// Makes sure all vectors are perpendicular all the time
. Но я все еще используюWORLD_SKY_VECTOR
в вращении рыскания/направления, чтобы держать камеру всегда перпендикулярной земле/небу, иначе это будет похоже на симулятор полета, я не хочу этого. Я получил это из другого вопроса, который я связал в верхней части этого поста. 22.03.2011WORLD_SKY_VECTOR
, поскольку у меня будет векторReference
, указывающий прямо вниз, а вектор неба, указывающий прямо вверх, и это проблематично. Я понятия не имею, как решить эту проблему, кроме как с помощью решенияaib
(то есть с ограничением -89,9 и +89,9). 23.03.2011