Não é possível limitar o ângulo de inclinação da câmera entre [-90º, 90º] no OpenGL usando vetores!
Estou tendo um grande problema ao limitar o ângulo de inclinação da câmera (entre -90º e 90º) com o código abaixo. Este é um acompanhamento de atéessa questã.
O problema, ao que parece, é que a câmera gira mais que -90º ou mais que + 90º e, quando isso acontecer, estarei olhando para baixo (ou para cima), mas a visão girou 180º em torno do eixo Y.
Exemplo: estou voltado para o norte, olhando para o horizonte e começo a olhar para baixo até não poder mais descer (limitado pelo código abaixo). Então começo a olhar para cima e voltarei para o sul.
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;
}
O problema provavelmente está noif(angle.y != 0.0f)
, se eu comentar esse bloco de código, o problema não exist Tem algo a ver comWORLD_SKY_VECTOR
, mas esse código é assim para permitir que eu gire o cabeçalho e mantenha a câmera nivelada. Se eu usasse oUpVector
em vez disso, problema resolvido. Mas isso só é bom para um simulador de vôo. Preciso manter o horizonte nivelado. Essa é a razão por trás deWORLD_SKY_VECTOR
. Mas parece que essa é a causa da "troca lateral" quando aponto a câmera diretamente para baix
Conforme solicitado em um comentário abaixo ... Isto é para uma câmera de primeira pessoa (e terceira pessoa, mas ainda não comecei a implementar essa parte) e quando olho para baixo, -90º (ou para cima, + 90º) e quando o ângulo vai de -89º a -91º (ou de + 89º a + 91º), quero que a câmera impeça isso e não ultrapasse o limite de -90º e + 90º. Quando atingir esse limite, preciso que a câmera seja capaz de voltar (para cima se estiver a -90º ou para baixo se estiver a + 90º). No momento, isso só funciona algumas vezes; outras vezes, eu vou estar olhando para o outro lado, e não para o que estava olhando inicialment