以下のコードでは、カメラのピッチ角 (-90 度から 90 度の間) を制限するのに大きな問題があります。これは、この質問のフォローアップです。
問題は、カメラが -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° の場合は下に)。現在、これは時々しか機能しません。それ以外の場合は、最初に見た方法ではなく、反対の方向を向いていることもあります.