第4章:矩阵基础与线性变换
好,咱们今天来聊聊矩阵。说实话,我第一次接触矩阵的时候,脑子里全是问号——这玩意儿不就是一堆数字排排坐吗?后来做动画做多了才明白,矩阵其实是图形变换的「万能遥控器」。你想想看,屏幕上那个小方块怎么放大、怎么旋转、怎么歪着扭着,背后都是矩阵在干活。
4.1 2x2矩阵的定义
先看最简单的2x2矩阵长什么样:
[ a b ]
[ c d ]
嗯,就四个数字。但别小看它。每个数字都代表一个「指令」。我个人习惯把矩阵想象成一个函数机器——你扔进去一个坐标(x, y),它吐出来一个新坐标(x', y')。
具体怎么算的?看公式:
x' = a*x + b*y
y' = c*x + d*y
说白了就是线性组合。原来那个点的x和y,分别乘以不同的系数,再加起来。这就是线性变换的本质。
核心理解:矩阵的每一列,其实代表变换后的基向量。第一列(a, c)是x轴基向量(1,0)变换后的位置,第二列(b, d)是y轴基向量(0,1)变换后的位置。
我在项目中遇到过一个问题:为什么有时候矩阵算出来的坐标会超出屏幕?后来发现是忘了考虑平移。2x2矩阵只能处理线性变换,平移得靠3x3矩阵。这个后面会讲,先记住这个坑。
4.2 缩放矩阵
缩放是最直观的变换。你想把一个图形拉宽或压扁,用缩放矩阵:
[ sx 0 ]
[ 0 sy ]
sx是x方向的缩放倍数,sy是y方向的。如果sx=2,那图形在x方向就变成两倍宽。
举个例子:点(3, 4)经过sx=2, sy=0.5的缩放:
x' = 2*3 + 0*4 = 6
y' = 0*3 + 0.5*4 = 2
结果变成(6, 2)。x拉长了,y压扁了。
小技巧:如果sx和sy相等,就是等比缩放。如果不相等,图形就会变形。做动画时,我经常用不等比缩放来模拟「挤压」效果,比如弹跳球落地那一瞬间的压扁。
4.3 旋转矩阵
旋转稍微复杂一点,涉及三角函数。绕原点逆时针旋转θ角度的矩阵是:
[ cosθ -sinθ ]
[ sinθ cosθ ]
为什么会这样?你想想看,点(1,0)旋转θ后变成(cosθ, sinθ),点(0,1)旋转θ后变成(-sinθ, cosθ)。这两列正好就是旋转矩阵的两列。
来个实际例子:点(1, 0)旋转90度(θ=90°):
cos90° = 0, sin90° = 1
x' = 0*1 + (-1)*0 = 0
y' = 1*1 + 0*0 = 1
结果(0, 1),完美。从x轴正方向转到了y轴正方向。
注意:CSS和Canvas中的旋转方向是顺时针的,而数学上默认是逆时针。我曾经因为这个搞反了旋转方向,调试了半天才发现是角度符号的问题。建议统一用数学标准,到具体平台再转换。
4.4 切变矩阵
切变可能比较陌生,但效果你肯定见过——就是那种把正方形拉成平行四边形的感觉。x方向切变矩阵:
[ 1 shx ]
[ 0 1 ]
shx是切变系数。点(x, y)变换后变成(x + shx*y, y)。你看,y坐标不变,x坐标根据y的值偏移了。y越大,偏移越多。
y方向切变类似:
[ 1 0 ]
[ shy 1 ]
点(x, y)变成(x, shy*x + y)。
我记得有一次做翻页动画,想模拟纸张被拉扯的效果,就是用切变矩阵实现的。配合缩放,效果还挺自然。
4.5 矩阵乘法与复合变换
单个变换太单调了。实际做动画,往往要缩放+旋转+切变一起上。这时候就需要矩阵乘法。
两个2x2矩阵相乘的规则:
[ a b ] [ e f ] [ a*e+b*g a*f+b*h ]
[ c d ] * [ g h ] = [ c*e+d*g c*f+d*h ]
说白了就是「行乘列」。左边矩阵的行,依次乘右边矩阵的列,加起来。
重点来了:矩阵乘法不满足交换律。A*B不等于B*A。顺序很重要。
实战经验:先旋转再平移,和先平移再旋转,结果完全不同。我刚开始做动画时,经常搞混顺序,导致图形飞到奇怪的位置。后来养成了一个习惯:从右往左读变换顺序。比如矩阵M = T * R,意思是先应用R(旋转),再应用T(平移)。
举个复合变换的例子:先缩放(sx=2, sy=1),再旋转45度。
缩放矩阵S:
[ 2 0 ]
[ 0 1 ]
旋转矩阵R(cos45°≈0.707, sin45°≈0.707):
[ 0.707 -0.707 ]
[ 0.707 0.707 ]
复合矩阵M = R * S:
[ 0.707*2 + (-0.707)*0 0.707*0 + (-0.707)*1 ] [ 1.414 -0.707 ]
[ 0.707*2 + 0.707*0 0.707*0 + 0.707*1 ] = [ 1.414 0.707 ]
这个复合矩阵就同时包含了缩放和旋转的效果。
优化建议:如果多个变换要应用到大量顶点上,先把所有矩阵乘成一个复合矩阵,再一次性应用到每个顶点。这样能省掉大量重复计算。我在做粒子系统时,就是先把所有变换合并,性能提升很明显。
4.6 总结一下
这一章的内容,说白了就是三件事:
- 矩阵是变换的数学表达——四个数字控制一个线性变换
- 三种基本变换——缩放、旋转、切变,各有各的矩阵形式
- 复合变换靠矩阵乘法——顺序决定结果,从右往左读
嗯,到这里矩阵的基础就打好了。下一章我们会把这些矩阵应用到实际的动画坐标变换中,到时候你就能看到这些数字是怎么让图形动起来的。
记住一句话:矩阵不是用来背的,是用来理解变换的。你只要理解了每一列代表基向量的去向,矩阵在你眼里就不再是一堆数字,而是一个活生生的变换指令集。