そのため、現在、2 つの 3D ポイント A と B を取り、ポイント A がポイント B を「見る」ために必要な回転を表すクォータニオンを提供する関数を作成しようとしています (ポイント A のローカル Z 軸が通過するように)必要に応じてポイント B)。
私は最初にこの投稿を見つけました。その一番の答えは、良い出発点を提供してくれたようです。次のコードを実装しました。元の回答が示唆するように、デフォルトの (0, 0, -1) 方向を想定する代わりに、カメラの実際の方向を表す単位ベクトルを抽出しようとします。
void Camera::LookAt(sf::Vector3<float> Target)
{
///Derived from pseudocode found here:
///https://stackoverflow.com/questions/13014973/quaternion-rotate-to
//Get the normalized vector from the camera position to Target
sf::Vector3<float> VectorTo(Target.x - m_Position.x,
Target.y - m_Position.y,
Target.z - m_Position.z);
//Get the length of VectorTo
float 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<float> LocalVector = m_Orientation.MultVect(sf::Vector3<float>(0, 0, -1));
//Get the cross product as the axis of rotation
sf::Vector3<float> 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);
//Get the dot product to find the angle
float Angle = acos(VectorTo.x*LocalVector.x +
VectorTo.y*LocalVector.y +
VectorTo.z*LocalVector.z);
//Determine whether or not the angle is positive
//Get the cross product of the axis and the local vector
sf::Vector3<float> 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;
AxisAngle.FromAxisAngle(Angle, Axis.x, Axis.y, Axis.z);
//And multiply it into the current orientation
m_Orientation = AxisAngle * m_Orientation;
}
これはほとんど機能します。何が起こるかというと、カメラがターゲット ポイントに向かって半分の距離だけ回転しているように見えます。もう一度回転を試みると、残りの半分の回転が無限に実行されるため、「Look-At-Button」を押したままにすると、カメラの向きがターゲットを直接見る方向にどんどん近づいていきますが、常に回転が遅くなり、そこに到達することはありません。
gluLookAt() に頼りたくないことに注意してください。最終的には、カメラ以外のオブジェクトを互いに向けるためにこのコードが必要になるためです。私のオブジェクトは既に向きにクォータニオンを使用しています。たとえば、目の前を動き回る物体の位置を追跡する眼球や、ターゲットを探すために方向を更新する発射体を作成したい場合があります。