6

クォータニオンに格納された回転を使用して一人称カメラをコーディングしたいと考えています。残念ながら、回転に問題があります。

次の関数は、カメラの回転を担当します。パラメータは、マウスの移動と回転速度Mouseを渡します。Speed次に、関数は回転クォータニオンをフェッチし、それを回転させ、結果を保存します。ところで、私はタイプと関数の由来であるBullet Physicsを使用しています。

void Rotate(vec2 Mouse, float Speed)
{
    btTransform transform = camera->getWorldTransform();
    btQuaternion rotation = transform.getRotation();

    Mouse = Mouse * Speed;                    // apply mouse sensitivity
    btQuaternion change(Mouse.y, Mouse.x, 0); // create quaternion from angles
    rotation = change * rotation;             // rotate camera by that

    transform.setRotation(rotation);
    camera->setWorldTransform(transform);
}

マウスが移動したときのカメラの回転を説明するために、手描きを示します。左側には、カメラが実際に実行する間違った回転が示されています。右側には、目的の正しいケースが表示されます。矢印は、マウスを上 (オレンジ色) および下 (青色) に動かしたときにカメラがどのように回転するかを示します。

左の間違った回転と右の望ましい回転

ご覧のとおり、ヨーがゼロである限り、回転は正しいです。しかし、ヨーが大きくなるほど、カメラが回転する円は小さくなります。対照的に、円は経度のように常に球全体に沿って走る必要があります。

私はクォータニオンにあまり詳しくないので、ここでそれらを正しく回転させる方法を尋ねます。

4

2 に答える 2

9

自分でクォータニオンを適切に回転させる方法を見つけました。重要なのは、回転させたい軸のベクトルを見つけることでした。これらは、角度が実際の軸を中心に回転する量である場合に、軸と角度からクォータニオンを作成するために使用されます。

次のコードは、私が最終的に得たものを示しています。また、カメラを回転させることもできます。これは、いつか役立つかもしれません。

void Rotate(btVector3 Amount, float Sensitivity)
{
    // fetch current rotation
    btTransform transform = camera->getWorldTransform();
    btQuaternion rotation = transform.getRotation();

    // apply mouse sensitivity
    Amount *= Sensitivity;

    // create orientation vectors
    btVector3 up(0, 1, 0);
    btVector3 lookat = quatRotate(rotation, btVector3(0, 0, 1));
    btVector3 forward = btVector3(lookat.getX(), 0, lookat.getZ()).normalize();
    btVector3 side = btCross(up, forward);

    // rotate camera with quaternions created from axis and angle
    rotation = btQuaternion(up,      Amount.getY()) * rotation;
    rotation = btQuaternion(side,    Amount.getX()) * rotation;
    rotation = btQuaternion(forward, Amount.getZ()) * rotation;

    // set new rotation
    transform.setRotation(rotation);
    camera->setWorldTransform(transform);
}

クォータニオン回転に関する情報はめったに見つからないので、上記のコードについてさらに説明することに時間を費やします。

回転のフェッチと設定は物理エンジンに固有のものであり、この質問とは関係がないため、詳しくは説明しません。次の部分、量にマウスの感度を掛けることは、非常に明確なはずです。方向ベクトルを続けましょう。

  • ベクトルは、独自のup実装に依存します。最も便利なのは、正の Y 軸が上を指すため、最終的に になり0, 1, 0ます。
  • lookatベクトルは、カメラが見ている方向を表します。カメラ回転クォータニオンによって前方を指す単位ベクトルを単純に回転させます。繰り返しますが、前方を指すベクトルは規則によって異なります。Y 軸が上向きの場合、正の Z 軸が前方を指している可能性があり0, 0, 1ます。
  • それを次のベクターと混同しないでください。forwardカメラの回転を参照する名前が付けられています。lookatしたがって、ベクトルを地面に投影するだけです。この場合、単純にlookatベクトルを取得し、上向きのコンポーネントを無視します。きちんとするために、そのベクトルを正規化します。
  • ベクトルはsideカメラの向きから左向きです。したがって、それはupforwardベクトルの両方に垂直であり、外積を使用し計算できます。

これらのベクトルが与えられると、それらの周りでカメラのクォータニオンを正しく回転させることができます。Z、Y、または Z のどれから開始するかは、オイラー角シーケンスに依存します。これも、アプリケーションごとに異なる規則です。回転をYXZ順に適用したいので、次のようにします。

  • 最初に、カメラをup軸の周りに Y 回転の量だけ回転させます。これがヨーです。
  • 次にside、左を指す軸を中心に X 量だけ回転します。ピッチです。
  • 最後に、forwardベクトルを中心に Z 量だけ回転してロールを適用します。

これらの回転を適用するには、現在のカメラの回転で軸と角度によって作成されたクォータニオンを乗算する必要があります。最後に、結果のクォータニオンを物理シミュレーションのボディに適用します。

于 2013-05-06T14:14:13.280 に答える