还是关于矩阵的碎碎念,接上篇:思考:矩阵及变换,以及矩阵在DirectX和OpenGL中的运用问题:左乘/右乘,行优先/列优先,...
纯粹个人观点,欢迎探讨:
5。矩阵的级联顺序与坐标系的关系:
1). 变换的时候,坐标系的选取是必需的物体的方位都是相对的,选定参考坐标系才能描述方位。一般参考坐标系可以分为两种:1.全局/固定坐标系 2.局部坐标系/物体坐标系。故名思义,前者是固定不动的,后者是随物体方位变化而变化的。
举个例子:伸出左手,手掌水平,掌心向上,大拇指向左,其余四指向前。此时选定物体的局部坐标系(Cl(Ol,Xl,Yl,Zl))为:掌心为原点(Ol),X轴(Xl)指向四指指向,Z(Zl)轴指向大拇指指向,Y轴(Yl)指向掌心向上。全局坐标系(Cg(Og,Xg,Yg,Zg))选定为和本地坐标系重合。那么,移动你的左手,局部坐标系就会随手而动。全局坐标系还是原先的方位。为什么选定坐标系对于变换重要?因为相对于哪种坐标系做变换得出的结果是不一定相同的。
还是上面那个例子:现在开始做变换,给你个指令:沿X轴旋转手掌90度使得掌心向右,然后手掌沿Y轴向+Y方向移动10厘米。
你做完后,得出的结果可能有3种:
1. 手的位置比原先高了10厘米,这部分人居多。
2. 手的位置比原先靠右10厘米,这部分人居少。
3. 还有部分数人傻在那,变换不来,这部分人其实不傻。
其实这个变换指令没有指定参考坐标系,是变换不出来的。1类的是自己选了全局坐标系,2类是选了局部坐标系,3类的没自己选。
所以,变换的时候,坐标系的选取是必需的。
2). 级联顺序与坐标系选取的关系
回到矩阵变换,一般我们说的对物体X进行M1变换,即X’= X*M1 (使用Column Matrix约定),隐含了选取全局坐标系的约定。单一变换的没有级联顺序的问题。如果再进行一个M2变换,此时,X’= X*M1*M2 还是X’= X*M2*M1呢?我们可能都知道是X’= X*M1*M2。显然嘛,先做的变换先乘,但深层的原因是什么呢?答案是隐含的全局坐标系的选定,如果选定的是局部坐标系,那么X’= X*M2’*M1’。后面一个变换反而要先进行。不信,看例子:
还是手掌例子,先旋转后平移, 给你个指令:沿Xg轴旋转手掌90度使得掌心向右,然后手掌沿Yg轴向+Yg方向移动10厘米。
这下清楚不过了,完成后手掌比原先高了10厘米。此时变换公式:X’= X*R(Xg)*T(Yg)
现在,指令是参考局部坐标系,变换顺序是反向的,先平移后旋转:
手掌沿Yl轴向+Yl方向移动10厘米,然后沿Xl轴旋转手掌90度使得掌心向右。
看看完成后的结果,手是不是和上面的方位一样?此时变换公式:X’= X*T(Yl)*R(Xl)
正序级联是相对于全局坐标系,逆序级联相对于局部坐标系,殊途同归。下次有变换矩阵需要级联的时候,先看看变换的矩阵是相对于全局还是局部的坐标系。
一般规律:假定对物体X施加M1变换和M2变换,两个变换矩阵均为相对于全局坐标系。有:
X’ = X*M1(g)*M2(g)
可以看作是将X先经过M1(g)变换,再进行M2(g)变换,得到X’
由矩阵的结合律,上面等式等价于:
X’ = X*M2(g)*(M2(g)-1*M1(g)*M2(g)) (M2(g)-1为M2(g)的逆矩阵)
所以,这个过程也可以这么看,先对X进行M2(g)(也即M2(l))变换(M2(g)为相对于全局坐标系,但此时全局和局部坐标系的重合,所以M2(g)=M2(l)),再对X进行M2(g)-1*M1(g)*M2(g)变换(也即M1(l)变换),这个变换实际上相当于先将物体退回到原方位(此刻局部坐标系退回到原始方位,也就是全局坐标系方位)进行M1(g)变换后,再进行M2(g)变换回来。M2(g)-1*M1(g)*M2(g)整体的效果就是相对于此时的局部坐标系的进行M1(l)变换。故:
X’ = X*M2(l)*M1(l)
即,如果将变换认为是相对于局部坐标系而进行的,那么矩阵级联顺序正好相反。
(注:上面推导有个这样的前提:即初始变换时,选定局部坐标系和全局坐标系重合。如果局部坐标系是一般选取,即局部坐标系相对于全局坐标系的变换M(l/g) != Identity呢,答案是结论一样。因为M(l/g)可以认作是对于物体的变换。将X换成X(new)=X*M(l/g)而已。)
3). 如何选取,如何级联
碰到的场景:
l 人手的运动
手有很多关节,每个关节的一端可以绕着关节处运动,关节本身也可以运动,要表达手指尖相对于人体的运动,使用相对于局部坐标系(关节)的变换比选取全局坐标系(人体)的变换要简单清晰得多。
比如:一个从手臂下垂到做出向上抬手手的动作之间,现在用矩阵变换来表达手掌的变换(X->X’)。
如果你选定局部坐标系(各个关节)做变换,那么其表达就是:
上手臂绕肩关节旋转90度(M1(肩)),下手臂绕肘关节转45度(M2(肘)),手掌绕踝关节转30度(M3(踝)),那么:
X’ = X*M3(踝)*M2(肘)*M1(肩)
(注意和X’ = X*M1(肩)*M2(肘)*M3(踝)的不同)
如果你选定全局坐标系(人体/肩关节)做变换,那么其表达就是:
上手臂绕肩关节旋转90度(M1(肩)),下手臂绕肩关节(M2(肩)), 手掌绕肩关节(M3(肩))。。绕不过来了吧(M2(肩), M3(肩)很难表示出来)
X’ = X*M1(肩)*M2(肩)*M3(肩)
l 矩阵分解与 级联顺序
|R 0|
|T 1|
= R*T (先进行旋转变换,后进行平移变换, 基于global坐标系)
= T*R (先进行平移变换,后进行旋转变换, 基于local坐标系)
= R*T' (先进行旋转变换,后进行平移变换, 基于local坐标系, T'= R-1*T*R)
= T*R' (先进行平移变换,后进行旋转变换, 基于global坐标系, R' = T-1*R*T)
4). 结论
注意矩阵级联顺序和坐标系选取的关系。在整体/部分相对运动较多的地方,选取局部坐标系描述变换。