难道这些功能列为主或行主?(Are these functions column-major or

2019-07-22 19:51发布

我比较了使用矩阵3D图形两种不同的线性数学库。 以下是这两个库中的两个类似的翻译功能:

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 ++从SO用户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库)

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

我的眼睛,这两个使用相同的格式,因为在第一指标作为行处理,第二个索引是列。 即,在两者xyz被施加到相同的第一索引。 这将意味着我行重大,因而矩阵乘法左关联的(例如,你通常做rotate * translate的顺序)。

我用的第一个例子多次在左结合上下文并预期它一直在努力。 虽然我没有用过第二,作者说,这是右结合的,但我无法看到两人的格式之间的差异。

Answer 1:

我的眼睛,这两个使用相同的格式,因为在第一指标作为行处理,第二个索引是列。

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

sometype a[n][m];

有连续sometype。这时候Nm个元素。 如果是行或列优先的顺序完全取决于你如何解释索引。 现在的OpenGL定义的4×4矩阵中的以下线性方案要被索引

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

如果应用C ++多维数组的规则,你会添加以下列列名称

   ----> n

|  0 4 8 c
|  1 5 9 d
V  2 6 a e
m  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
a -> 2,2
b -> 2,3
c -> 3,0
d -> 3,1
e -> 3,2
f -> 3,3

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

看看这张图:

轴X,Y和Z基本上是载体。 他们被定义为

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

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

然而写入,因为它是在基质被通过堆叠行向量形成。 而对于矩阵乘法的规则基本上是告诉,由行向量所形成的矩阵,转换行向量成左联乘行向量。 柱主要通过矩阵右结合乘法转换列向量进列向量。

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

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

v_clip = P · V · M · v_local

这种表示法使得它直观地看到发生了什么事情。 此外,在编程键字符=通常由右至左指定分配。 有些编程语言更数学的影响,例如Pascal或Delphi写它:= 。 反正与行为主的顺序,我们不得不把它写

v_clip = v_local · M · V · P

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

所以这就是为什么我们使用列主要格式:它看起来更好。 技术上讲,它可以使用行主要格式,以及完成。 而这是什么都与矩阵的内存布局呢? 那么,当你想使用列优先的顺序标记,那么你要变换矩阵的基本向量的直接访问,而无需通过这些元素提取它们的元素。 与在列主要格式存储号码,所有需要访问一个矩阵的某个基矢量是一个简单的线性存储器偏移量。

我不能代表其他库的代码示例说话,但我强烈认为,它把第一个指数作为慢递增指数为好,这使得它在列的主要工作,如果受到的OpenGL的符号。 记住:列主要与右联排==&主要左关联性。



Answer 2:

发布的片段都不足以回答这个问题。 他们可能是存储在行序行的主要基质,或者存储在列顺序列主矩阵。

如果你看一个向量时如何用适当的矩阵相乘处理它可能会更明显。 在行优先系统,你所期望的矢量被视为一个单一的行矩阵,而在一列主系统会同样是一列矩阵。 这然后决定如何一个向量和矩阵可以被相乘。 你只能乘以一个矩阵右边一个单一的列或左边一排的向量。

GL的惯例是列为主,所以矢量乘以权。 D3D是行主,所以向量行和相乘左侧。

这需要串联变换时要考虑到,让他们以正确的顺序应用。

即:

GL:
    V' = CAMERA * WORLD * LOCAL * V
D3D:
    V' = V * LOCAL * WORLD * CAMERA

不过,他们选择存储他们的矩阵使得在内存中表示实际上是相同的(直到我们进入着色器和一些表述需要进行换位......)



文章来源: Are these functions column-major or row-major?