1. ホーム
  2. c++

[解決済み] C++とOpenGLの行列順序の混乱(行順と列順)

2023-06-07 17:15:25

質問

行列の定義について、かなり混乱しています。私は行列クラスを持っており、そのクラスは float[16] を保持しており、私は以下の観察に基づいて行長であると仮定しました。

float matrixA[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
float matrixB[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };

matrixA そして matrixB はどちらもメモリ上で同じ線形レイアウトになります (つまり、すべての数字が順番に並んでいます)。によれば http://en.wikipedia.org/wiki/Row-major_order によると、これはロー メジャー レイアウトであることを示しています。

matrixA[0] == matrixB[0][0];
matrixA[3] == matrixB[0][3];
matrixA[4] == matrixB[1][0];
matrixA[7] == matrixB[1][3];

したがって matrixB[0] = 0行目です。 matrixB[1] = 1行目、など。ここでも、ロウ・メジャー・レイアウトを表しています。

私の問題/混乱は、次のような翻訳マトリックスを作成したときに起こります。

1, 0, 0, transX
0, 1, 0, transY
0, 0, 1, transZ
0, 0, 0, 1

というようにメモリ上にレイアウトされる。 { 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 } .

次に glUniformMatrix4fv を呼び出すとき、transpose フラグを GL_FALSE に設定する必要があり、これは、列方向がメジャーであることを示します。

transpose が GL_FALSE である場合、各行列は列のメジャーオーダーで提供されるものと見なされます。 列のメジャーオーダーで提供されると仮定されます.transposeがGL_TRUEの場合、各行列は行のメジャーオーダーで提供されると仮定されます。 である場合、各行列は行の主要な順序で提供されるものとみなされます。

なぜ私の行列は、行のメジャーに見えるのに、列のメジャーとしてOpenGLに渡される必要があるのでしょうか?

どのように解決するのですか?

opengl のドキュメントで使用されている行列表記は、OpenGL の行列のためのメモリ内レイアウトを記述していません。

もしあなたが全体の "行/列-major" のことを落とす/忘れるなら、それはより簡単だと思います。なぜなら、行/列のメジャーに加えて、プログラマーは、表記法に加えて、メモリ内の行列をどのようにレイアウトしたいか(隣接する要素が行を形成するか列を形成するか)を決定することもでき、それが混乱を招くからです。

OpenGLの行列は directx の行列と同じメモリ レイアウト .

x.x x.y x.z 0
y.x y.y y.z 0
z.x z.y z.z 0
p.x p.y p.z 1

または

{ x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1 }

  • x, y, zは行列座標系(グローバル座標系に対するローカル座標系)を記述する3成分ベクトルです。

  • pは行列座標系の原点を表す3成分ベクトル.

つまり、並進行列はこのようにメモリ上にレイアウトされるはずです。

{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }.

そのままにしておけば、あとは簡単でしょう。

---古いopenglのfaqからの引用です。


<ブロッククオート

9.005 OpenGLの行列は列が主役なのか、それとも行が主役なのか?

プログラミングの目的のために、OpenGLの行列は、メモリに連続的にレイアウトされたベースベクトルを持つ16値の配列です。翻訳成分は16要素の行列の13、14、15番目の要素を占め、OpenGL 2.1仕様のセクション2.11.2で説明されているように、インデックスは1から16まで番号付けされています。

列メジャーと行メジャーの違いは、純粋に表記上の慣習です。列専攻の行列を使った後乗算は、行専攻の行列を使った前乗算と同じ結果になることに注意してください。OpenGL仕様とOpenGLリファレンスマニュアルは両方ともcolumn-major記法を使用しています。明確に記述されている限り、どのような記法を使ってもかまいません。

悲しいことに、仕様書と青本におけるcolumn-major形式の使用は、OpenGLプログラミングコミュニティにおける終わりのない混乱をもたらしました。列-長方形表記は、プログラマーが期待するように、行列がメモリ内にレイアウトされないことを示唆しています。