矩阵相乘可以实现复合变换,就比如先位移再旋转、先旋转在位移,或着连续位移。
接下来咱们先看一下两个矩阵是如何相乘的。
矩阵乘以矩阵的结果还是矩阵,我们可以通过矩阵库验证一下矩阵相乘的规律。
1.使用three.js的Matrix4 对象建立矩阵
const a=new Matrix4().set(
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10,11,
12,13,14,15
)
const b=new Matrix4().set(
0, 10, 20, 30,
40, 50, 60, 70,
80, 90, 100,110,
120,130,140,150
)
注:set()方法里输入的矩阵是行主序的,但elements 输出的矩阵是列主序的。
const ca=a.elements
console.log(ca);
[
0, 4, 8, 12,
1, 5, 9, 13,
2, 6, 10, 14,
3, 7, 11, 15
]
const cb=b.elements
console.log(cb);
[
0, 40, 80, 120,
10, 50, 90, 130,
20, 60, 100, 140,
30, 70, 110, 150
]
2.让矩阵a乘以矩阵b
const c=a.multiply(b)
console.log(c.elements);
[
560, 1520, 2480, 3440,
620, 1740, 2860, 3980,
680, 1960, 3240, 4520,
740, 2180, 3620, 5060
]
分析一下结果
560=0*0 +1*40+2*80 +3*120
620=0*10+1*50+2*90 +3*130
680=0*20+1*60+2*100+3*140
740=0*30+1*70+2*110+3*150
1520=4*0 +5*40+6*80 +7*120
1740=4*10+5*50+6*90 +7*130
……
到此,我们应该能总结出矩阵a乘以矩阵b规律,以列主序的ca、cb为例:
先遍历ca的每一列,再遍历cb的每一行,将ca的每一列乘以cb的每一行,按照列主序排列后得到的结果。
或者,先遍历ca的每一行,再遍历cb的每一列,将ca的每一行乘以cb的每一列,按照行主序排列后得到的结果。
我们验证一下后者:
const cc=[]
for(let y=0;y<16;y+=4){
const [ax,ay,az,aw]=[ca[y],ca[y+1],ca[y+2],ca[y+3]]
for (let x=0;x<4;x++){
console.log(x);
const [bx,by,bz,bw]=[cb[x],cb[x+4],cb[x+8],cb[x+12]]
cc.push(ax*bx+ay*by+az*bz+aw*bw)
}
}
console.log(cc);
[
560, 1520, 2480, 3440,
620, 1740, 2860, 3980,
680, 1960, 3240, 4520,
740, 2180, 3620, 5060
]
其结果和矩阵库一致。
3.通过上面的规则可知,矩阵的乘法不满足结合律,即矩阵a乘以矩阵b不一定等于矩阵b乘以矩阵a。