web-dev-qa-db-ja.com

変換行列を転置する必要があるのはなぜですか?

OpenGLを使用して小さなグラフィックエンジンに取り組んでいますが、変換行列に問題があります。 OpenGL 3.3、GLSL、C++を使用しています。状況は次のとおりです。画面にレンダリングしたい小さな立方体を定義しました。立方体は独自の座標系を使用しているため、立方体を変換できるようにモデル行列を作成しました。自分自身を少し簡単にするために、キューブのモデルマトリックスとして変換マトリックスだけから始め、少しコーディングした後、すべてを機能させることができ、キューブが画面に表示されます。特別なことは何もありませんが、私の変換行列について、少し奇妙だと思うことが1つあります。

私の知る限り、変換行列は次のように定義されています。

1, 0, 0, x
0, 1, 0, y
0, 0, 1, z
0, 0, 0, 1

しかし、これは私にはうまくいきません。このように変換行列を定義すると、画面に何も表示されません。これは、次のように変換行列を定義した場合にのみ機能します。

1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
x, y, z, 1

これが当てはまる理由を見つけるために何度かコードを調べましたが、理由がわからないようです。それとも間違っているので、上記の転置行列のように変換行列を定義する必要がありますか?

私の行列は、左から右、上から下に向かう1次元配列として定義されています。

これが役立つかもしれない私のコードのいくつかです:

//this is called just before cube is being rendered
void DisplayObject::updateMatrices()
{
    modelMatrix = identityMatrix();
    modelMatrix = modelMatrix * translateMatrix( xPos, yPos, zPos );

    /* update modelview-projection matrix */
    mvpMatrix = modelMatrix * (*projMatrix);
}

//this creates my translation matrix which causes the cube to disappear
const Matrix4 translateMatrix( float x, float y, float z )
{
    Matrix4 tranMatrix = identityMatrix();

    tranMatrix.data[3]  = x;
    tranMatrix.data[7]  = y;
    tranMatrix.data[11] = z;

    return Matrix4(tranMatrix);
}

これは私の単純なテスト頂点シェーダーです:

#version 150 core

in vec3 vPos;

uniform mat4 mvpMatrix;

void main()
{
    gl_Position = mvpMatrix * vec4(vPos, 1.0);
}

また、行列の乗算が機能するかどうかを確認するためのテストも行いました。 I * randomMatrixはまだrandomMatrixです

私はあなたたちが助けることができることを願っています。ありがとう

編集:

これが私がマトリックスデータをOpenGLに送る方法です:

void DisplayObject::render()
{
    updateMatrices();

    glBindVertexArray(vaoID);
    glUseProgram(progID);
    glUniformMatrix4fv( glGetUniformLocation(progID, "mvpMatrix"), 1, GL_FALSE, &mvpMatrix.data[0] );
    glDrawElements(GL_TRIANGLES, bufferSize[index], GL_UNSIGNED_INT, 0);
}

mvpMatrix.dataはstd :: vector:です。

24
Krienie

OpenGLの場合

1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
x, y, z, 1

正しい変換行列です。どうして? Openglはcolumn-major行列の順序を使用します。これは、最初に提示した行列の転置であり、row-majorの順序になっています。行メジャーは、ほとんどの数学の教科書やDirectXでも使用されているため、OpenGLを初めて使用する人にとってはよくある混乱のポイントです。

参照: http://www.mindcontrol.org/~hplus/graphics/matrix-layout.html

行列の乗算では行列を交換できないため、A * BはB * Aとは異なります。行列を交換する前にBを転置する必要があります。

A * B = t(B) * A

試してみてください

void DisplayObject::updateMatrices()
{
    modelMatrix = identityMatrix();
    modelMatrix = translateMatrix( xPos, yPos, zPos ) * modelMatrix;

    /* update modelview-projection matrix */
    mvpMatrix = modelMatrix * (*projMatrix);
}
3