我对矩阵定义感到非常困惑。我有一个矩阵类,它包含一个 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 时,我需要将转置标志设置为 GL_FALSE,表明它是列优先的,否则无法正确应用诸如平移/缩放等转换:
如果 transpose 为 GL_FALSE,则假定每个矩阵以列主要顺序提供。如果 transpose 为 GL_TRUE,则假定每个矩阵以行主要顺序提供。
为什么我的矩阵(看起来是行优先的)需要作为列优先传递给 OpenGL?
原文由 Mark Ingram 发布,翻译遵循 CC BY-SA 4.0 许可协议
opengl 文档中使用的矩阵表示法没有描述 OpenGL 矩阵的内存布局
如果您认为放弃/忘记整个“行/列主要”的事情会更容易。这是因为除了行/列专业之外,程序员还可以决定他希望如何在内存中布置矩阵(相邻元素是形成行还是列),除了符号之外,这会增加混乱。
OpenGL 矩阵 与 directx 矩阵具有相同的内存布局。
或者
x、y、z 是描述矩阵坐标系(相对于全局坐标系内的局部坐标系)的 3 分量向量。
p 是描述矩阵坐标系原点的三分量向量。
这意味着翻译矩阵应该像这样在内存中布局:
把它留在那里,其余的应该很容易。
—来自旧的opengl常见问题解答–
我将更新这个 9 岁的答案。
数学矩阵定义为
m x n
矩阵。其中m
是 行 数,n
是 _列数_。为了完整起见,行是水平的,列是垂直的。当用数学符号Mij
表示矩阵元素时,第一个元素( ---j
i
)是行索引,第二个元素( —00982d4a78641e621f524802d5ab60d 是列索引)当两个矩阵相乘时,即A(m x n) * B(m1 x n1)
,得到的矩阵具有第一个参数的行数(A
)和第二个参数的列数(B
),并且第一个参数 (A
) 的列数必须与第二个参数 (B
) 的行数匹配。所以n == m1
。到目前为止清楚,是吗?现在,关于内存布局。您可以通过两种方式存储矩阵。行优先和列优先。 Row-major 意味着有效地你有一个又一个线性排列的行。所以,元素从左到右,一行接一行。有点像英文文本。 Column-major 意味着有效地你有一个又一个线性排列的 _列_。所以元素从左上角开始,从上到下。
例子:
现在,这是有趣的部分!
有两种方法可以将 3d 变换存储在矩阵中。正如我之前提到的,3d 中的矩阵本质上存储坐标系基向量和位置。因此,您可以将这些向量存储在矩阵的行或列中。当它们存储为列时,您将矩阵与列向量相乘。像这样。
但是,您也可以将这些向量存储为行,然后将行向量与矩阵相乘:
所以。约定#1 经常出现在数学课本中。约定 #2 在某个时候出现在 DirectX sdk 中。两者都是有效的。
关于这个问题,如果您使用约定#1,那么您的矩阵是列优先的。如果您使用约定 #2,那么它们是行专业的。但是,两种情况下的内存布局是相同的
这就是为什么我说在 9 年前更容易记住哪个元素是哪个元素。