joh*_*ers 1 math 3d graphics transformation linear-algebra
我正在使用矩阵比较两个不同的3D图形线性数学库.以下是两个库中两个类似的Translate函数:
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;
}
Run Code Online (Sandbox Code Playgroud)
(SO用户骄傲的c ++库)
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;
}
Run Code Online (Sandbox Code Playgroud)
(来自SO用户datenwolf的linmath c库)
我是新手,但我知道矩阵乘法的顺序很大程度上取决于你是使用列主要还是行主要格式.
在我看来,这两个是使用相同的格式,因为在第一个索引被视为行,第二个索引是列.也就是说,在两者中x y z
都应用于相同的第一索引.这对我来说意味着行主要,因此矩阵乘法是左关联的(例如,你通常rotate * translate
按照这个顺序进行).
我在左关联上下文中多次使用了第一个示例,并且它已按预期工作.虽然我没有使用第二个,但作者说这是正确的关联,但我很难看到两者格式之间的差异.
在我看来,这两个是使用相同的格式,因为在第一个索引被视为行,第二个索引是列.
外观可能是欺骗性的,但事实上linmath.h中的第一个索引就是列.C和C++在如此定义的多维数组中指定
sometype a[n][m];
Run Code Online (Sandbox Code Playgroud)
有Ñ倍米的元件sometype.这时候连续.如果是行或列主要顺序,则仅取决于您如何解释索引.现在,OpenGL定义了4×4矩阵,以便在以下线性方案中进行索引
0 4 8 c
1 5 9 d
2 6 a e
3 7 b f
Run Code Online (Sandbox Code Playgroud)
如果应用C++多维数组的规则,则添加以下列行指定
----> n
| 0 4 8 c
| 1 5 9 d
V 2 6 a e
m 3 7 b f
Run Code Online (Sandbox Code Playgroud)
将线性指数重新映射为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
Run Code Online (Sandbox Code Playgroud)
好吧,OpenGL和一些数学库使用列主要排序,很好.但是为什么这样做并打破通常的数学约定,在M i中,j指数i指定行,j指定列?因为它使东西看起来更好.你看,矩阵只是一堆向量.可以并且通常形成坐标基础系统的向量.
看看这张图:
轴X,Y和Z基本上是矢量.它们被定义为
X = (1,0,0)
Y = (0,1,0)
Z = (0,0,1)
Run Code Online (Sandbox Code Playgroud)
那一刻,那不就是身份矩阵吗?的确如此,事实上它是!
然而,因为它是通过堆叠行向量形成矩阵而写的.矩阵乘法的规则基本上表明,由行向量形成的矩阵通过左关联乘法将行向量变换为行向量.列主矩阵通过右关联乘法将列向量变换为列向量.
现在这不是一个真正的问题,因为左关联可以做与右关联相同的东西,你只需要交换行的列(即转置)所有内容并颠倒操作数的顺序.但是左<>右行<>列只是我们写东西的符号约定.
典型的数学符号是(例如)
v_clip = P · V · M · v_local
Run Code Online (Sandbox Code Playgroud)
这种表示法使其直观地显示正在发生的事情.此外,在编程中,关键字符=
通常指定从右到左的分配.一些编程语言在数学上受到影响,比如Pascal或Delphi并编写它:=
.无论如何有行主要排序,我们必须写它
v_clip = v_local · M · V · P
Run Code Online (Sandbox Code Playgroud)
对大多数数学家来说,这看起来不自然.因为从技术上讲,M,V和P实际上是线性算子(是的,它们也是矩阵和线性变换),运算符总是介于相等/赋值和变量之间.
这就是为什么我们使用列主要格式:它看起来更好.从技术上讲,它也可以使用行主格式来完成.这与矩阵的内存布局有什么关系?好吧,当你想使用列主要顺序表示法时,你想要直接访问变换矩阵的基矢量,而不是让它们逐个元素地提取它们.通过以列主格式存储数字,访问矩阵的某个基本向量所需的全部是线性存储器中的简单偏移.
我不能代表另一个库的代码示例,但我强烈假设它将第一个索引视为较慢的递增索引,这使得它在使用OpenGL符号时可以在专栏中工作.请记住:列主要和右侧关联性==行主要和左侧关联性.