这些函数是列优先还是行优先? [英] Are these functions column-major or row-major?

查看:24
本文介绍了这些函数是列优先还是行优先?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用矩阵比较用于 3D 图形的两个不同的线性数学库.以下是来自两个库的两个相似的 Translate 函数:

I'm comparing two different linear math libraries for 3D graphics using matrices. Here are two similar Translate functions from the two libraries:

static Matrix4<T> Translate(T x, T y, T z)
{
    Matrix4 m;
    m.x.x = 1; m.x.y = 0; m.x.z = 0; m.x.w = 0;
    m.y.x = 0; m.y.y = 1; m.y.z = 0; m.y.w = 0;
    m.z.x = 0; m.z.y = 0; m.z.z = 1; m.z.w = 0;
    m.w.x = x; m.w.y = y; m.w.z = z; m.w.w = 1;
    return m;
}

(来自 SO 用户骄傲的 C++ 库)

(c++ library from SO user prideout)

static inline void mat4x4_translate(mat4x4 T, float x, float y, float z)
{    
mat4x4_identity(T);
T[3][0] = x;
T[3][1] = y;
T[3][2] = z;
 }

(来自 SO 用户 datenwolf 的 linmath c 库)

(linmath c library from SO user datenwolf)

我是这方面的新手,但我知道矩阵乘法的顺序在很大程度上取决于您使用的是列优先格式还是行优先格式.

I'm new to this stuff but I know that the order of matrix multiplication depends a lot on whether you are using a column-major or row-major format.

在我看来,这两个使用相同的格式,即第一个索引被视为行,第二个索引是列.也就是说,在两个x y z 中被应用到相同的第一个索引.这对我来说意味着行优先,因此矩阵乘法是左关联的(例如,您通常会按该顺序执行 rotate * translate).

To my eyes, these two are using the same format, in that in both the first index is treated as the row, the second index is the column. That is, in both the x y z are applied to the same first index. This would imply to me row-major, and thus matrix multiplication is left associative (for example, you'd typically do a rotate * translate in that order).

我在左关联上下文中多次使用第一个示例,并且它一直按预期工作.虽然我没有使用过第二种,但作者说它是右结合的,但我很难看出两者格式之间的区别.

I have used the first example many times in a left associative context and it has been working as expected. While I have not used the second, the author says it is right-associative, yet I'm having trouble seeing the difference between the formats of the two.

推荐答案

在我看来,这两个使用相同的格式,即第一个索引被视为行,第二个索引是列.

To my eyes, these two are using the same format, in that in both the first index is treated as the row, the second index is the column.

看起来可能是骗人的,但实际上 linmath.h 中的第一个索引是列.C 和 C++ 指定在这样定义的多维数组中

The looks may be deceiving, but in fact the first index in linmath.h is the column. C and C++ specify that in a multidimensional array defined like this

sometype a[n][m];

nmsometype 元素连续.如果它是行或列主要顺序完全取决于您如何解释索引.现在 OpenGL 定义了 4×4 矩阵以下列线性方案进行索引

there are n times m elements of sometype in succession. If it is row or column major order solely depends on how you interpret the indices. Now OpenGL defines 4×4 matrices to be indexed in the following linear scheme

0 4 8 c
1 5 9 d
2 6 a e
3 7 b f

如果您应用 C++ 多维数组的规则,您将添加以下列行指定

If you apply the rules of C++ multidimensional arrays you'd add the following column row designation

   ----> n

|  0 4 8 c
|  1 5 9 d
V  2 6 a e
m  3 7 b f

将线性索引重新映射为 2 元组

Which remaps the linear indices into 2-tuples of

0 -> 0,0
1 -> 0,1
2 -> 0,2
3 -> 0,3
4 -> 1,0
5 -> 1,1
6 -> 1,2
7 -> 1,3
8 -> 2,0
9 -> 2,1
a -> 2,2
b -> 2,3
c -> 3,0
d -> 3,1
e -> 3,2
f -> 3,3

好的,OpenGL 和一些数学库使用列主要排序,很好.但是为什么要这样做并打破通常的数学约定,即在 Mi,j 中,索引 i 指定行而 j 列?因为它让事情看起来更好.你看,矩阵只是一堆向量.可以并且通常确实形成坐标基础系统的向量.

Okay, OpenGL and some math libraries use column major ordering, fine. But why do it this way and break with the usual mathematical convention that in Mi,j the index i designates the row and j the column? Because it is make things look nicer. You see, matrix is just a bunch of vectors. Vectors that can and usually do form a coordinate base system.

看看这张照片:

X、Y 和 Z 轴本质上是向量.它们被定义为

The axes X, Y and Z are essentially vectors. They are defined as

X = (1,0,0)
Y = (0,1,0)
Z = (0,0,1)

瞬间,上面的那个看起来像一个单位矩阵吗?确实如此,事实上它

Moment, does't that up there look like a identity matrix? Indeed it does and in fact it is!

然而,矩阵是通过堆叠行向量形成的.矩阵乘法的规则本质上是,由行向量组成的矩阵,通过左关联乘法将行向量转换为行向量.列主矩阵通过右结合乘法将列向量转换为列向量.

However written as it is the matrix has been formed by stacking row vectors. And the rules for matrix multiplication essentially tell, that a matrix formed by row vectors, transforms row vectors into row vectors by left associative multiplication. Column major matrices transform column vectors into column vectors by right associative multiplication.

现在这不是一个真正的问题,因为左关联可以做和右关联一样的事情,你只需要交换列的行(即转置)所有内容并反转操作数的顺序.然而,左<>右行<>列只是我们写东西的符号约定.

Now this is not really a problem, because left associative can do the same stuff as right associative can, you just have to swap rows for columns (i.e. transpose) everything and reverse the order of operands. However left<>right row<>column are just notational conventions in which we write things.

典型的数学符号是(例如)

And the typical mathematical notation is (for example)

v_clip = P · V · M · v_local

这种表示法可以直观地看到正在发生的事情.此外,在编程中,键字符 = 通常指定从右到左的分配.一些编程语言更受数学影响,如 Pascal 或 Delphi,将其编写为 :=.无论如何,对于行主要排序,我们必须编写它

This notation makes it intuitively visible what's going on. Furthermore in programming the key character = usually designates assignment from right to left. Some programming languages are more mathematically influenced, like Pascal or Delphi and write it :=. Anyway with row major ordering we'd have to write it

v_clip = v_local · M · V · P

对于大多数数学爱好者来说,这看起来很不自然.因为,从技术上讲,M、V 和 P 实际上是线性运算符(是的,它们也是矩阵和线性变换)并且运算符总是介于等式/赋值和变量之间.

and to the majority of mathematical folks this looks unnatural. Because, technically M, V and P are in fact linear operators (yes they're also matrices and linear transforms) and operators always go between the equality / assignment and the variable.

这就是我们使用列主要格式的原因:它看起来更好.从技术上讲,它也可以使用行主要格式来完成.这与矩阵的内存布局有什么关系?好吧,当您想使用列主序表示法时,您需要直接访问转换矩阵的基向量,而无需它们逐个元素地提取它们.通过以列主要格式存储数字,访问矩阵的某个基向量所需要的只是线性内存中的一个简单偏移量.

So that's why we use column major format: It looks nicer. Technically it could be done using row major format as well. And what does this have to do with the memory layout of matrices? Well, When you want to use a column major order notation, then you want direct access to the base vectors of the transformation matrices, without having them to extract them element by element. With storing numbers in a column major format, all it takes to access a certain base vector of a matrix is a simple offset in linear memory.

我不能说其他库的代码示例,但我强烈假设,它也将第一个索引视为较慢的递增索引,这使得它在受制于OpenGL.记住:专栏专业&右结合==行主要&左结合性.

I can't speak for the code example of the other library, but I'd strongly assume, that it treats first index as the slower incrementing index as well, which makes it work in column major if subjected to the notations of OpenGL. Remember: column major & right associativity == row major & left associativity.

这篇关于这些函数是列优先还是行优先?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆