难道这些功能列为主或行主? [英] Are these functions column-major or row-major?

查看:151
本文介绍了难道这些功能列为主或行主?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我比较两个不同的线性数学库使用矩阵3D图形。这里有两个类似的翻译从两个库的功能:

 静态Matrix4< T>翻译(T X,Tÿ,T Z)
{
    Matrix4米;
    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;
    返回米;
}
 

(三从SO用户prideout ++库)

 静态内嵌无效mat4x4_translate(mat4x4 T,浮法X,浮动Y,浮Z)
{
mat4x4_identity(T);
T [3] [0] = X;
T [3] [1] = Y;
T [3] [2] = Z;
 }
 

(从SO用户datenwolf linmath C库)

我是新来这个东西,但我知道,矩阵乘法的顺序很大程度上取决于是否使用的是列为主或行的主要格式。

要自己的眼睛,这两个都使用相同的格式,在该在第一索引被视为行,第二个索引是列。即,在两者的 XYZ 被施加到相同的第一索引。这将意味着对我行重大,因而矩阵乘法是左关联的(例如,你通常做旋转*翻译顺序)。

我已经使用了第一示例多次在左结合上下文,它已被工作正常。虽然我没有用过第二,作者说,这是右结合的,但我无法看到两人的格式之间的差异。

解决方案
  

要自己的眼睛,这两个都使用相同的格式,在该在第一索引被视为行,第二个索引是列。

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

  SOMETYPE一​​个[N] [M]。
 

N 的时间的 M 的的的 sometype。这时候的相继元素。如果是的行或列优先的顺序完全取决于你如何跨preT指数。现在的OpenGL定义了4×4矩阵在下面的线性方式被编入索引

  0 4 8℃
1 5 9天
2 6 A E
3 7 b˚F
 

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

  ----> ñ

| 0 4 8℃
| 1 5 9天
V 2 6 A E
米3 7 b˚F
 

这重新映射线性指数为2元组

  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
一个 - > 2,2
b  - > 2,3
C  - > 3,0
ð - > 3,1
Ë - > 3,2
的F  - > 3,3
 

好了,OpenGL和一些数学库使用列优先顺序,罚款。但为什么这种方式与通常的数学打破常规,在 M <子> I,J 的指数指定的行和 Ĵ列?因为它是让事情看起来更好。你看,矩阵只是一堆载体。可以和平时形成向量的坐标基本系统。

看一看这张图:

的轴X,Y,Z是基本矢量。他们被定义为

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

瞬间,简化版,即在那里看起来像一个矩阵?的确如此,事实上它的的!

然而写成它是矩阵已经通过叠置行向量形成。而对于矩阵乘法的规则基本上是告诉,由行向量组成的矩阵,转换行矢量到左联乘行向量。列主要矩阵变换列向量为列向量由右结合乘法。

现在这不是一个真正的问题,因为左结合可以做同样的东西,右结合能,你就必须换为列的行(即转),一切都和反向操作数的顺序。但是离开了&LT;>右排&LT;>列在其中,我们写的东西只是符号约定

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

  v_clip = P·V·并购·v_local
 

这个符号使得它直观地看到发生了什么事情。此外,在编程按键字符 = 通常指定分配从右到左。有些编程语言更数学的影响,如帕斯卡或德尔福,并将其写入:= 。反正与行为主的顺序,我们就必须把它写

  v_clip = v_local·并购·V&CenterDot; P
 

和广大数学乡亲,这看起来不自然。因为,在技术上M,V和P其实线性算(是的,他们还矩阵和线性变换)和运营商始终​​是平等/分配和变量之间走了。

所以这就是为什么我们使用列主要格式:它看起来更好。从技术上讲它可以使用行主要格式做得好。而这是什么都与矩阵的内存布局?好吧,如果你想使用一列大订单的符号,那么你要直接进入变换矩阵的基向量,而不让他们通过元素提取出来的元素。与在一个列主要格式存储号码,所有需要访问一个矩阵的某个基矢量是一个简单的线性存储器偏移量

我不能为其他库的code例如说话,但我强烈认为,它把第一个索引为较慢递增指数为好,这使得它在列的主要工作,如果受到OpenGL的符号。请记住:列重大和放大器;右联排==主要和放大器;左关联性。

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;
}

(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;
 }

(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.

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.

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];

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

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

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

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.

Have a look at this picture:

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

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

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.

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天全站免登陆