15

前提A

線形メモリの「列メジャー」行列について話すとき、メモリの最初の4つのエントリが行列の最初の列に対応するように、列が次々に指定されます。一方、「行メジャー」行列は、メモリ内の最初の4つのエントリが行列の最初の行を指定するように、行を次々に指定すると理解されます。


AGLKMatrix4は次のようになります。

union _GLKMatrix4
{
    struct
    {
        float m00, m01, m02, m03;
        float m10, m11, m12, m13;
        float m20, m21, m22, m23;
        float m30, m31, m32, m33;
    };
    float m[16];
}
typedef union _GLKMatrix4 GLKMatrix4;

メンバーのドキュメントには次のように書かれています。m

列優先順の行列要素の1次元配列。

構内B

GLKMatrix4の「行」は、水平方向に宣言された4つのフロートのセットです([m00, m01, m02, m03]最初の「行」になります)。したがって、これらのエントリはmRowColとして解釈できます(m12行1、列2のエントリになります)。


これらのGLKMatrix構造体メンバーが宣言の順序に基づいてどのように配置されているかを見ると、次のようになります。

[m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, ...]

最初の4つのエントリは、最初の列ではなく、マトリックスの最初の行を明確に表しています。

結論

m実際には列メジャーではなく、ドキュメントが間違っています。


さて、私は実際には結論を信じていないことに注意する必要がありますが、2つの前提はかなり合理的であるように思われます。本当に、私は前提Bを最も信用していませんが、「行」を垂直に、「列」を水平に定義するのは奇妙に思えます。誰かがこれを説明できますか?

4

3 に答える 3

11

宣言は少し紛らわしいですが、行列は列の主要な順序になっています。構造体の4つの行は、マトリックスの列を表します。m0*は列0、m3 *は列3です。これは簡単に確認できます。変換マトリックスを作成し、変換コンポーネントの値m30、m31、およびm32を確認するだけです。

あなたの混乱は、実際には列を表しているのに、構造体がフロートを行に配置しているという事実から来ていると思います。

于 2012-03-13T17:18:32.363 に答える
10

これはOpenGL仕様から来ています-

コラムメジャー

混乱のポイントはまさにこれです:他の人が指摘しているように、行ではなく列を示す最初のインデックスで列のメジャーマトリックスにインデックスを付けます

  • m00column = 0、row = 0
  • m01column = 0、row = 1
  • m02column = 0、row = 2

MATLABはおそらく、この混乱に間接的に寄与するために多くのことを行ってきましたが、MATLABは実際に内部データ表現に列メジャーを使用していますが、それでも行メジャーインデックス規則のを使用していx(row,col)ます。なぜ彼らがこれをしたのかわかりません。

また、OpenGLはデフォルトで列ベクトル(MATRIX*VECTOR)を使用することに注意してください。つまり、シェーダーのように、行列に変換するベクトルをポスト乗算することが期待されます。(VECTOR*MATRIX)行メジャー行列の場合とは対照的です。

Cの行メジャー行列と列メジャー行列に関する私の記事を見ると役立つ場合があります

コードで行列をレイアウトする場合、列メジャーは直感に反します

これを見れば見るほど、Cコードのメジャー列で作業するのは間違いだと思います。なぜなら、あなたがしていることを精神的に転置する必要があるからです。コードで行列をレイアウトする場合、言語の左から右への性質により、行ごとに行列を書き出すことが制限されます。

float a[4] = { 1, 2,
               3, 4 };

したがって、非常に自然に、行、マトリックスで指定しているように見えます

1 2
3 4

ただし、列の主要な仕様を使用している場合は、実際にマトリックスを指定しています

1 3
2 4

これは本当に直感に反します。垂直(または「列メジャー」言語)がある場合、コードで列メジャー行列を指定するが簡単です。

これはすべて、Direct3Dのもう1つの回りくどい議論ですか?わかりません、教えてください。

本当に、なぜOpenGLは列の主行列を使用するのですか?

深く掘り下げると、これが行われた理由は、次のようなベクトルによる行列の「乗算後」を可能にするため、つまり、次のような(MATRIX*VECTOR)列(メジャー)ベクトルを使用できるようにするためであると思われます

列の主行列の乗算

┌ 2 8 1 1 ┐ ┌ 2 ┐
│ 2 1 7 2 │ │ 2 │
│ 2 6 5 1 │ │ 2 │
└ 1 9 0 0 ┘ └ 1 ┘

これを行ベクトルを使用する必要があることと比較してください。

行の主行列の乗算

[ 2 2 2 1 ]  ┌ 2 8 1 1 ┐ 
             │ 2 1 7 2 │
             │ 2 6 5 1 │
             └ 1 9 0 0 ┘

行列が行メジャーとして指定されている場合は、行ベクトルを使用し、変換するベクトルを行列に事前に乗算する必要があります。

行優先行列を使用するときに行ベクトルを「使用する」必要がある理由は、一貫したデータ表現です。結局のところ、行ベクトルは1行4列の行列にすぎません。

于 2012-09-17T10:55:18.547 に答える
3

前提Bの問題は、GLKMatrix4のA「行」が水平方向に宣言された4つのフロートのセットであると想定していることです([m00、m01、m02、m03]が最初の「行」になります)。

column次のコードでの値を確認するだけで、それを確認できます。

GLKMatrix3 matrix = {1, 2, 3, 4, 5, 6, 7, 8, 9};
GLKVector3 column = GLKMatrix3GetColumn(m, 0);

注:GLKMatrix3簡単にするために使用しましたが、同じことがに当てはまりますGLKMatrix4

于 2012-03-13T17:20:25.143 に答える