问题似乎是相机旋转超过-90º或超过+90º,并且当发生这种情况时,我将向下(或向上)看,但是视图只是围绕Y轴旋转了180º。
例如:我面向北方,看着地平线,然后开始往下看,直到无法再往下走(由下面的代码限制)。然后我开始往上看,我就会面向南方。
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()”函数的完整代码,请看一下。 我也删除了我的第二个问题,因为它可能不再相关。如果需要,我会发布另一个问题,如果你想要,可以编辑你的帖子以删除对第二个问题的回答。 - rfgamaral