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说:

以列优先顺序排列的矩阵元素的一维数组。

前提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实际上不是 Column Major,并且文档是错误的。


现在,我应该指出,我实际上并不相信这个结论,但这两个前提似乎很合理。真的,我最不信任前提 B,但是将“行”定义为垂直而“列”定义为水平似乎很奇怪。有人可以解释一下吗?

4

3 回答 3

11

声明有点混乱,但矩阵按列主要顺序排列。结构中的四行代表矩阵中的列,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 的另一个迂回论证吗?我不知道,你告诉我。

真的,为什么 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 中的“行”是一组水平声明的 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 回答