そのため、OpenGL シーンで 3D オブジェクトの回転を実装していますが、これまでのところ基本的な回転自体 (クォータニオンを使用) は正常に機能しています。また、カメラを含む任意の 3D オブジェクトを 3D 空間内の任意の点に正確かつ困難なく向けることができるように、「ルックアット」の問題もほぼ解決しました。
ただし、オブジェクトに特定の点を向くように命令すると、オブジェクトはローカル Z 軸に沿って頻繁に回転します。小さな船が赤、緑、青の線が収束する点を見ているこの画像を見てください。たとえば、Y 軸に沿って回転して緑色の線に面し、X 軸に沿って下に傾けて 3 つの線の交点に面するオブジェクトから予想されるように見えないことがわかります。
私は必ずしもこれを望んでいません。その点を直接見たいのですが、(正面から見て)時計回りに少し傾けて、翼の先端が同じ Y レベルになるようにします。点に面することの全体的なポイントは、ローカル Z 軸がその点を通過することであるため、オブジェクトがそのローカル Z 軸を中心にどのように回転するかは問題ではありませんが、結果の回転は一貫して歪んでいます。オブジェクトとその焦点の相対位置。
いずれにせよ、これが私の LookAt() コードです。これを変更して、最終的な Z 回転をより細かく制御できるようにします。
void Thing::LookAt(sf::Vector3<float> Target)
{
///Derived from pseudocode found here:
///http://stackoverflow.com/questions/13014973/quaternion-rotate-to
//Reset the rotation to default
m_Orientation = Quaternion();
//Get the normalized vector from the camera position to Target
sf::Vector3<double> VectorTo(Target.x - m_Position.x,
Target.y - m_Position.y,
Target.z - m_Position.z);
//Get the length of VectorTo
double VectorLength = sqrt(VectorTo.x*VectorTo.x +
VectorTo.y*VectorTo.y +
VectorTo.z*VectorTo.z);
//Normalize VectorTo
VectorTo.x /= VectorLength;
VectorTo.y /= VectorLength;
VectorTo.z /= VectorLength;
//Straight-ahead vector
sf::Vector3<double> LocalVector = m_Orientation.MultVect(sf::Vector3<double>(0, 0, -1));
//Get the cross product as the axis of rotation
sf::Vector3<double> Axis(VectorTo.y*LocalVector.z - VectorTo.z*LocalVector.y,
VectorTo.z*LocalVector.x - VectorTo.x*LocalVector.z,
VectorTo.x*LocalVector.y - VectorTo.y*LocalVector.x);
//Normalize the axis
//Get the length of VectorTo
double AxisLength = sqrt(Axis.x*Axis.x +
Axis.y*Axis.y +
Axis.z*Axis.z);
//Normalize VectorTo
Axis.x /= AxisLength;
Axis.y /= AxisLength;
Axis.z /= AxisLength;
//Get the dot product to find the angle
double DotProduct = (VectorTo.x*LocalVector.x +
VectorTo.y*LocalVector.y +
VectorTo.z*LocalVector.z);
double Angle = acos(DotProduct);
//Determine whether or not the angle is positive
//Get the cross product of the axis and the local vector
sf::Vector3<double> ThirdVect(Axis.y*LocalVector.z - Axis.z*LocalVector.y,
Axis.z*LocalVector.x - Axis.x*LocalVector.z,
Axis.x*LocalVector.y - Axis.y*LocalVector.x);
//If the dot product of that and the local vector is negative, so is the angle
if (ThirdVect.x*VectorTo.x + ThirdVect.y*VectorTo.y + ThirdVect.z*VectorTo.z < 0)
{
Angle = -Angle;
}
//Finally, create a quaternion
//Quaternion AxisAngle;
m_Orientation.FromAxisAngle(Angle, Axis.x, Axis.y, Axis.z);
m_Orientation.RotationMatrix(m_RotationMatrix);
}
私の問題は、Z 軸を中心とした最終的な回転を制御する方法がわからないことです。m_Orientation クォータニオンから Z 角度を抽出すると、上の写真の船が Z 軸を中心に 0 ラジアン回転していることがわかります。Z コンポーネントを手動で 0 に設定し、クォータニオンを再正規化しようとしましたが、(当然だと思いますが) うまくいきませんでした。
当分の間、船を「上向き」に回転させるために必要な特定の Z コンポーネントを計算することは問題ありません。最終的な Z 回転を操作する方法について、より明確なアイデアが欲しいです。アイデアやリソースはありますか?