1.问题
矩阵在计算机图形学中有着重要的地位,刚开始学习时很容易被矩阵乘法的先后顺序所困扰,因为这里存在很多因素,比如什么是列矩阵和行矩阵,两种矩阵在做变换时会有什么差别?什么是列优先和行优先?矢量左乘矩阵和右乘矩阵是怎么定义的?
2.列矩阵和行矩阵
列矩阵(column major)和行矩阵(row major)是数学上的概念,和电脑无关,它只是一套约定(convention),按照矢量和矩阵的乘法运算时,矢量是列矢还是行矢命名,这里只说4x4矩阵。齐次矢量可以看成是一个1x4的矩阵,就是行矢;或者4x1的矩阵,就是列矢。
列矩阵变换矢量时,用矩阵乘以列矢量(M * v),如下。其中1、2、3为三个轴向矢量。
| x1 x2 x3 xt | | x |
| y1 y2 y3 yt | * | y |
| z1 y2 y3 zt | | z |
| 0 0 0 1 | | w |
列矩阵之间乘法组合时,组合顺序为从右到左。例如依次做放缩S、旋转R、平移T,则组合为T * R * S。
行矩阵变换矢量时,用行矢量乘以矩阵(v * M),如下。其中1、2、3为三个轴向矢量。
| x1 y1 z1 0 |
| x y z w | * | x2 y2 z2 0 |
| x3 y3 z3 0 |
| xt yt zt 1 |
行矩阵之间乘法组合时,组合顺序为从左到右。例如依次做放缩S、旋转R、平移T,则组合为S * R * T。
3.列矩阵和行矩阵
列优先存储(column major storage)和行优先存储(row major storage)是计算机上的概念,指多维数组的元素在内存中的排列顺序。
对应到矩阵上,按内存地址顺序编号,则列优先存储的顺序为
| 1 5 9 13 |
| 2 6 10 14 |
| 3 7 11 15 |
| 4 8 12 16 |
行优先存储的顺序为
| 1 2 3 4 |
| 5 6 7 8 |
| 9 10 11 12 |
| 13 14 15 16 |
4.左乘和右乘
左乘(left multiplication, pre-multication)和右乘(right multiplication, post-multication),这里的左右、pre/post,指的是矢量和矩阵相乘时,矢量的位置。对标量和矩阵相乘时,指标量的位置。
说简单点,左乘(又称前乘)就是乘在左边(即乘号前),右乘(又称后乘)就是乘在右边(即乘号后).
比如说,A左乘E即AE
5.Opengl和D3D中的矩阵
Opengl采用的是列优先,D3D采用的是行优先。
抛开不同底层实现的差异,我们在进行模型视图变换时,一般的顺序都是先缩放,然后旋转,最后进行平移,这样才能达到正确的变换效果。因此对于opengl,V`=T*R*S*V,但是对于D3D,V`=V*S*R*T。
6.OSG中的矩阵
osg的底层为opengl,但是在其矩阵实现时,是按照行矩阵来实现,矩阵的内部存储使用一个二维数组,这样在glLoadMatrix访问的刚好是osg的矩阵的的转置,可以这样理解这个区别:
对于opengl,V`=M*V,根据矩阵运算法则:V`转置 = V转置 * M转置,矢量的转置不影响我们的使用,这样我们可以在osg中把矩阵当成行矩阵对待,因此在变换顺序上为S * R * T,这样也更符合从左到右的习惯。