行矩阵和列矩阵
在图形处理中,矩阵操作时最基本的操作,但是不同的系统中对矩阵的存储是不同,比如OpenGL和Cg中就是不一样的:
比如一个4x4矩阵
[m11,m12,m13,m14
m21,m22,m23,m24
m31,m32,m33,m34
m41,m42,m43,m44]
在实现中通常将其存储为一个一维的线性数组如float matrix【16】或者float* matrix。
在opengl中这个matrix中数据的顺序是先遍历列的,线性存储为{m11,m21,m31,m41,m12,m22,m32…},这被称为矩阵的列序存储。
GLM数据库采用的是列序存储。
Directx的数学库是行序存储。 opengl和hlsl都要求矩阵是列序存储。
左手坐标系与右手坐标系
Direct3D使用的是左手坐标系,而OpenGL与我们平日接触到的数学使用的则是右手坐标系:
纹理坐标系和屏幕坐标系
为了避免混淆,这里直说Direct3D的。由于Direct3D支持3D纹理,纹理坐标系实际上是可以有三个维度的,如下图所示。只不过我们绝大多数情况使用的仅仅是2D纹理,故只需要考虑X轴和Y轴的部分。
屏幕坐标系(2D)与纹理坐标系的X轴、Y轴朝向是一致的。
矩阵乘法
我的理解,矩阵乘法本质上就是大家说的线性变换,这种线性变换就是投影。
在这里我产生了两种思考方式,一是顺向思考,二是逆向思考。以旋转矩阵为例
- 顺向思考,想象向量随着矩阵一起旋转,矩阵m顺时针变换成为m’(m’ = m的各个基向量旋转后),V的数据依然不变,只是V现在是m’下面的坐标,并且V跟着M一起顺时针变化了。现在求V在原来的空间坐标下(世界坐标)的值v’,v’即v顺指针旋转后的坐标。
v’ = v * m’ //右乘行矩阵
这个m’也就是常说的local space或者model space。
顺向思考适合计算在世界空间下坐标点在经过平移旋转等变换后的新的坐标。 - 逆向思考,想象矩阵旋转但是向量没有旋转。
比如你有一个向量V矩阵M。
现在矩阵M绕y轴顺时针旋转了n°,为M’。
那么VM’=V’。 V’就是V在矩阵M’这个坐标系下的新的坐标。坐标系顺时针转了n°,也可以看成是V逆时针转了n°。也就是V’ = V逆时针转n°的坐标。
可推,如果你想得到V顺指针转n°的结果V’。 V’ = V* 逆(M顺指针转n度)
求的是原来的坐标在新的空间M’下的坐标。所以用的是M变换为M’的逆矩阵,即从M’变为M
逆向思考适合计算有一个新的观察坐标系,计算世界空间下的点在新的坐标系下的坐标。例如求lookat矩阵。
行矩阵和列矩阵
行矩阵:每一行是基向量
列矩阵:每一列是基向量
如果是左乘,向量应该乘行矩阵
如果是右乘的。应该乘列矩阵
分清行矩阵/列矩阵和行主序/列主序的区别
左乘还是右乘
不考虑计算机图形学,我们上学时学到的矩阵写法一般是行主序,那么其有投影意义的应该是右乘。即
M([x, y, z]) * v = v’