《OpelGL编程指南第七版》---对变换的思考

以下是我自己结合书的例子的思考,如有错误,欢迎指正,大家一起学习
OpenGL中矩阵默认为列优先。C/C++中默认是行优先的。也就是说当年你构建一个二维数组时,在内存中是一行一行存储的,顶部的行在更低的地址区。矩阵相乘时,行优先采用我们数学中正确的方式,即一行和一列对应相乘再求和 Cij = ∑ Ain * Bnj。而列优先中计算为一列与一列对应相乘再求和Cij = ∑ Ani * Bnj
比如一个点(x,y,z,w)先平移变换T:(x1,y1,z1),再按Z轴旋转R:θ,则c/c++中变换矩阵存储为

[100x1010y1001z10001] 

[cosθsinθ00sinθcosθ0000100001] 

而OpenGL中存储为

[100001000010x1y1z11] 

[cosθsinθ00sinθcosθ0000100001] 

在C/C++中,变换过程为:

(18)M= [100x1010y1001z10001]×[cosθsinθ00sinθcosθ0000100001]=[cosθsinθ0x1sinθcosθ0y1001z10001]

(41)X=MX= [cosθsinθ0x1sinθcosθ0y1001z10001]×[xyz1]=[xcosθysinθ+x1xsinθ+yycosθ+y1z+z11]

在OpenGL中,变换过程为:

(42)M= [cosθsinθ00sinθcosθ0000100001]×[100001000010x1y1z11]=[cosθsinθ00sinθcosθ000010x1y1z11]

(7)X=XtM= [xyz1]×[cosθsinθ00sinθcosθ000010x1y1z11]=[xcosθysinθ+x1xsinθ+ycosθ+y1z+z11]

因此,假设当前矩阵是C,一系列变换函数指定的矩阵是M1,M2……,Mn,在相乘后,最终的矩阵形式总是C×M1×M2……×Mn,作用到点v上的效果是C×M1×M2……×Mn×v(C/C++ 行×列)。等同于v×Mn×Mn-1……×c(OpenGL 列×列)。这个过程意味着程序调用的最后一个变换函数实际上是首先应用于顶点v的

考虑两个简单变换
《OpelGL编程指南第七版》---对变换的思考
全局固定坐标系
如果根据全局固定坐标系来考虑问题,就必须注意乘法的出现顺序与它们在代码中出现的顺序相反。
《OpelGL编程指南第七版》---对变换的思考

局部移动坐标系统
所有的操作都相对于这个不断变化的坐标系统进行,矩阵乘法很自然地按照它们在代码中出现的顺序进行。(仍然是3-4左侧的变换。代码不用改,思维方式变了一下)

现在我们再回顾一下,整理下思路。我们想实现3-4左侧的效果,先旋转再移动。如果我们代码变换矩阵顺序也是先旋转再移动的话,OpenGL实现时会是先移动再旋转,最后效果是3-4右侧。我们想正确实现变换后物体在X轴上,必须调整代码顺序,即变化矩阵顺序为先移动再旋转。这时再用全局坐标系思考问题要先将变换矩阵顺序倒一下,然后在根据全局的坐标系变化,这样思考很麻烦。所以我们采用局部坐标系思考,先移动,再按照局部坐标系的Z轴旋转,这样矩阵乘法很自然地按照代码中的顺序进行。方便我们思考。所以总结一下就是:
OpenGL每次变换实现的都是全局坐标系的变换,但是当我们在代码中必须将变换矩阵的顺序反过来,这时按语句顺序来理解的话,实现的是局部变换的效果。