2

やあみんな私はglmライブラリのlookAtを使用するCameraクラスをやろうとしています。私には4つのポイントがあります。1つ目は目、つまり空間内のカメラの位置、2つ目は外観、つまりカメラが見ているポイント、3つ目はuppで、カメラの向きを設定します。 、そして4番目はサイドです。これは、look-eyeとupp-eyeの外積です。

したがって、最終的には、アイポイントを原点とする3つのベクトルのベースを取得しました。カメラの座標系を取得しました。

私のカメラクラスでは、世界の座標系ではなく、カメラの座標系を中心に回転できるようにしたいと考えています。だから私がやっていることは、カメラの座標系の軸の1つを中心に回転することです。

次のような初期値でクラスを作成します。

void Observer::initialize(glm::vec3 eye, glm::vec3 look, glm::vec3 upp, glm::vec3 side) 
{
    this->eye = eye;        // (0.0, 0.0,  0.0)
    this->look = look;      // (0.0, 0.0, -1.0)
    this->upp = upp;        // (0.0, 1.0,  0.0)
    this->side = side;      // (1.0, 0.0,  0.0)
}

たとえば、座標系をx軸を中心に回転させたい場合は、次のようにglmから関数を呼び出します。

void Observer::pitch(GLfloat pitch) 
{
    glm::mat4 rotate(1.0f);

    rotate = glm::rotate(rotate, pitch, side - eye);

    look = glm::vec3(rotate * glm::vec4(look, 1.0f));
    upp = glm::vec3(rotate * glm::vec4(upp, 1.0f));
}

これまでのところ、すべてのポイントがカメラの座標系を形成しており、すべてのベクトルが互いに垂直であることを理解しています。

しかし、次に、lookAt関数で取得したこれらのポイントを使用して、カメラを世界に配置します。

 glm::mat4 view = glm::lookAt(eye, look, upp);

そして、このマトリックスにOpenGLのmodelviewマトリックスを掛けます

たくさん回転し始めると、数回転した後のカメラは、他の方法で回転していたように、回転を「反映」します(実際に何が起こっているのかをより良い方法で説明する方法がわかりません= s)。

何が起こっているのか本当にわかりません。回転を適用した後、ベクトルを正規化する必要がありますか?ジンバルロックに問題がありますか(ジンバルロックについてはよくわかりません)?

4

1 に答える 1

2

これまでと同じようにベクトルを増分回転すると、数値エラーが発生します。エラーによってアップベクトルとルックアットベクトルがほぼ同じ方向または反対方向を指す場合、カメラ変換の計算が不安定になり、奇妙なことが発生する可能性があります。ジンバルロック。長さを変更すると、さまざまな問題が発生します。

私のために働いた解決策は、各回転の後にアップベクトルとルックアットベクトルを再直交化することです。これを行うには、外積Lを計算してから、LをlookAtと交差させて、アップベクトルを調整(実際に置き換え)します。結局、これは単位長にアップとルックアットの両方を再正規化します。

直交化-正規化は高速な操作ですが、実際にはすべてのカメラの動きでそれを行う必要はありません。

このようにベクトルを修正すると、実際にはlookAt行列の計算の一部を実行していることに注意してください。したがって、不要な外積を避けるために、独自のベクトルを実装することを検討してください。たとえば、このトピックに関するこの以前のSOの記事を参照してください。

于 2013-03-25T03:25:37.400 に答える