У меня большая проблема с ограничением угла наклона камеры (от -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º). Прямо сейчас это работает только иногда, в других случаях я буду смотреть в другую сторону вместо того, как я первоначально смотрел.