线性代数:矩阵变换图形(二维平移缩放旋转)

        紧接上一篇:http://blog.csdn.net/yinhun2012/article/details/79566148

        前面我们从理论上理解了图形学中图形的变换过程,具体可以理解为如果要对一个图形A进行变换,那么存在图形A所处的相同原点的仿射空间SpaceA(或者说仿射空间SpaceA中原点处存在一个图形A),这时候我们暂时忽略图形A,只考虑SpaceA经过各种变换最终变换成另一个仿射空间SpaceB(或者说变换后的仿射空间SpaceA与另一个仿射空间SpaceB重合),因为仿射空间SpaceA变换后可能被伸缩或者被旋转同时又移动了,那么仿射空间SpaceA中的图形A同时跟着被变换成了另外的样子,如下图:

        

        想像一下,假设把你自己当作一个“图形”,这时候出现一个任务,就是让躺在床上的你从家里出发去公司坐在办公椅上上班写代码,你应该怎么做呢,首先你要起床(从平躺的向量变成竖着的向量,这就经历了一个人体旋转的过程),然后出发,经过一条长长的街道xxx路(从xxx路的起点路口到xxx路的终点路口,这就经历了一个人体平移的过程),然后拐弯进入yyy路并且继续行走(这就经历了人体旋转加人体平移两个过程),然后进入公司走到办公椅前坐下(从竖着站立状态变成坐下的坐立状态,这可以人为人体进行了形变缩放)。

        这么一看,我们对于变换的理解就可以分解为旋转、平移、缩放三个过程。

        前面我们对齐次坐标的理解,知道了旋转和缩放这两个过程可以通过矩阵T进行线性变换处理,但是平移却是需要将矩阵T扩充“平移维度”得到矩阵T'才能进行线性变换处理,所以数学上我们处理n维空间的图形变换就要使用n+1维齐次坐标以及n+1行n+1列矩阵来得到。接下来我们就来具体推导二维仿射坐标系下的旋转/平移/缩放。

        1.矩阵操作仿射坐标系旋转,还是老办法,建立单位圆进行逆时针旋转θ角(三角函数中规定逆时针旋转为正角)的旋转矩阵辅助推导,如下图:

            

        我们通过矩阵T_rotate旋转变换仿射坐标系xoy到x1oy1,矩阵T_rotate的推导也是通过建立线性方程组解方程得到T_rotate的未知数。那么仿射坐标系所“容纳”的原点图形也就跟着变换了。因为旋转变换不需要额外扩充成齐次坐标表示也能进行变换,所以我们忽略“平移维度”。 

        2.矩阵操作仿射坐标系缩放,建立辅助单位圆,如下图:

        

        上面我们首先推导了标准缩放,也就是xy缩放比例K相同,接下来缩放比例不同x缩放m/y缩放n,依旧是通过建立矩阵T_scale以及转换成线性方程组就很容易得到矩阵T_scale了。

        3.矩阵操作仿射坐标系平移,特殊情况来了!前面我们讲过仿射坐标系平移是不能直接进行线性变换的,而需要扩充平移维度进行辅助计算,如下图:

        

        同样的,因为二维平移只有xy轴两个方向,我们建立仿射坐标系观察,同时扩充“平移维度”,建立矩阵T_translate和线性方程组,就能得到我们需要的平移矩阵T_translate。

        前面我们推了二维情况下仿射坐标系旋转,缩放,平移的变换矩阵T_rotate,T_scale,T_translate,但是三个矩阵太不规范了,有的是2x2有的是3x3,有的使用了齐次坐标,有的又只使用了普通坐标,这对我们程序中进行计算是非常不友好的。之前我们说了平移变换是通过扩充“平移维度”来处理的,并不影响“旋转维度”和“缩放维度”,同时GPU设计的重要指标之一就是极快速处理4x4及以下的矩阵计算,所以我们通过将T_rotate和T_scale扩充维度到T_translate的行列数,用来统一传入GPU进行处理。

        扩充方式如下图:

        

        这里我们只需要将“平移维度”填入“旋转维度”和“缩放维度”就行了,如果不放心的话我们就验证一下扩充后的矩阵的计算结果,如下图:

        

缩放矩阵同理也可以计算出来结果。

        这么一来我们就把旋转平移缩放的变换全部使用齐次坐标和3x3矩阵给统一化了,但是我们还是觉得麻烦,因为我处理一个图形变换居然还需要使用三个矩阵去分别计算,我们能不能直接把这三个矩阵通过什么方法变成一个呢,接下来我们来观察矩阵乘法的性质,继续由简入难。

        假设我们有两个2x2的矩阵T1,T2来变换一个2x1的矩阵V(2x1的矩阵也就是一个二维向量),按照平常方法我们肯定就是先使用T1*V变换得到V1,然后再使用T2*V1变换得到V2,整个过程我们记为T2*(T1*V)。我们希望优化中间环节,尽量少的直接将V带入运算,希望变换成(T2*T1)*V,先将T2*T1得到矩阵T3,然后将T3*V变换得到V2,此时我们的问题就变成T2*T1得到的矩阵T3是否起到了T1、T2分别变换V相同的作用。

        我们知道矩阵A*矩阵B的规则就是矩阵A的行m与矩阵B的列n的元素分别相乘再相加最终得到的元素放置于结果矩阵C的m行n列中,那么上面的问题矩阵T1*V得到的V1再使用T2*V1得到的结果和T2*T1得到T3*V的结果相同,因为这种矩阵乘法的计算规律在独立出每个行列计算后得到单个元素的分解式符合乘法分配律(c*(a+b) = c*a + c*b)运算然后拆分组合成另外的乘法分配律的组合体,这时候我们必须通过实际运算来观察,因为红色语言的描叙都过于复杂到无法直接心算,如下图:

       

        最后的乘法分配组合经过分解拆分继续组合成乘法分配律组合体。

       这时候我们可以将原本的旋转平移缩放三次矩阵操作T_rotate*(T_translate*(T_scale*Vector))变化成T_all(T_all = T_rotate*(T_translate*T_scale)) *Vector,保证Vector经过一个矩阵的一次变换达到目标。

        



        

        

        

        

        

                        

        

        

  • 14
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值