2017-08-12 9 views
1

私は現在、自分の2D Mathsライブラリを使って、基礎となる行列演算の理解を深めています。 これまで私はGLMのようなライブラリを使っていましたが、学習経験として検討する価値があるように感じました。カスタムビューマトリックスでのストレッチ問題

これのほとんどはわかりやすく、数学クラスの大半はOpenGLと統合されていますが、私のビューマトリックスはウィンドウの端に四辺を伸ばしているようです。

これは遠近法の問題ではないことに注意してください。私は正書法マトリックスを使用していますが、MVPの代わりにビューマトリックスを使用してこれをMVPから分離しました。 (私が正しく理解していれば)行列が主要な柱です

Matrix4x4 GenerateView(const Vector2f &cameraPosition) 
{ 
    Matrix4x4 mat; 

    //Right 
    mat.elements[0][0] = 1; 
    mat.elements[0][1] = 0; 
    mat.elements[0][2] = 0; 
    mat.elements[0][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, 1, 0, 0); 

    //Up 
    mat.elements[1][0] = 0; 
    mat.elements[1][1] = 1; 
    mat.elements[1][2] = 0; 
    mat.elements[1][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, 0, 1, 0); 

    //Look 
    mat.elements[2][0] = cameraPosition.x; 
    mat.elements[2][1] = cameraPosition.y; 
    mat.elements[2][2] = -1; 
    mat.elements[2][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, cameraPosition.x, cameraPosition.y, -1); 

    //Last Column 
    mat.elements[3][0] = 0; 
    mat.elements[3][1] = 0; 
    mat.elements[3][2] = 0; 
    mat.elements[3][3] = 1; 
    return mat; 
} 

は、以下の私のビュー行列生成コードです。 「ルック」がフォワードユニットベクタを参照しているかどうかはわかりませんでしたので、「センター」と同様にそれを試みましたが、問題は解決しません。

//Look 
    mat.elements[2][0] = 0; 
    mat.elements[2][1] = 0; 
    mat.elements[2][2] = -1; 
    mat.elements[2][3] = -Dot(cameraPosition.x, cameraPosition.y, 10, 0, 0, -1); 

最後に、ケースには誰もが内積が正しく実装されていることを疑う:

float Dot(float x1, float y1, float z1, float x2, float y2, float z2) 
{ 
    return x1 * x2 + y1 * y2 + z1 * z2; 
} 

答えて

3

世界でX軸は右を指しているが、フロントにY軸、 Z軸が上に移動すると、ビューポート上でX軸が左を指し、Y軸が上を示し、Z軸が視野から外れます(右手系ではZ軸は外積ですX軸とY軸の)

world to viewport

各点とシーンの参照システムからの各ベクトルは、したがって、ビューポート座標に最初に変換されなければなりません。これは簡単に次の表で処理することができる:変換行列は、通常、次のように見えること

x y z 
-------- 
1 0 0 | x' = x 
0 0 1 | y' = z 
0 -1 0 | z' = -y 

(X-axis.x, X-axis.y, X-axis.z, 0) 
(Y-axis.x, Y-axis.y, Y-axis.z, 0) 
(Z-axis.x, Z-axis.y, Z-axis.z, 0) 
(trans.x, trans.y, trans.z, 1) 

以下のコードは、正確な外観を計算するのに必要なステップをカプセル化マトリックスを定義します場面で:

  • モデル座標をビューポート座標に変換します。
  • 回転、ビューの方向を見ます。
  • 運動


Matrix4x4 LookAt(const Vector3f &pos, const Vector3f &target, const Vector3f &up) 
{ 
    Vector3f mz(pos[0] - target[0], pos[1] - target[1], pos[2] - target[2] }; 
    Normalize(mz); 
    Vector3f my(up[0], up[1], up[2]); 
    Vector3f mx = Cross(my, mz); 
    Normalize(mx); 
    my = Cross(mz, mx); 

    Matrix4x4 m; 
    m.elements[0][0] = mx[0]; m.elements[0][1] = my[0]; m.elements[0][2] = mz[0]; m.elements[0][3] = 0.0f; 
    m.elements[1][0] = mx[1]; m.elements[1][1] = my[1]; m.elements[1][2] = mz[1]; m.elements[1][3] = 0.0f; 
    m.elements[2][0] = mx[2]; m.elements[2][1] = my[2]; m.elements[2][2] = mz[2]; m.elements[2][3] = 0.0f; 

    m.elements[3][0] = Dot(mx, pos); 
    m.elements[3][1] = Dot(my, pos); 
    m.elements[3][2] = Dot(Vector3f(-mz[0], -mz[1], -mz[2]), pos); 
    m.elements[3][3] = 1.0f; 

    return m; 
} 

Vector3f Cross(const Vector3f &a, const Vector3f &b) 
{ 
    return Vector3f(a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]); 
} 

float Dot(const Vector3f &a, const Vector3f &b) 
{ 
    return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; 
} 

void Normalize(Vector3f &v) 
{ 
    float len = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 
    v = Vector3f(v[0]/len, v[1]/len, v[2]/len); 
} 
目の位置に