从零实现3D图像引擎:(7)矩阵函数库

来源:互联网 发布:手机淘宝分享宝贝链接 编辑:程序博客网 时间:2024/05/17 21:51

1. 数学分析

1) 矩阵到底是什么,用它来干嘛?

 千万不要把矩阵想复杂了,说白了,他和算盘是一类东西,矩阵根本就没有实际意义,他就是个数学工具而已,就好像敲算盘,珠子上上下下的按照一定的规律去拨弄,就能得到结果一样,矩阵是数学家们发明的一个工具,这个工具也有一系列规则,通过这些规则也可以计算出一些结果,只不过他不像算盘是用来做数字加减乘除用的,他是用来求解方程组的。学习完了矩阵的运算规则,就可以发现,所有对向量、点坐标的变换都可以通过矩阵运算来完成,这也是为什么3D图像的运算与矩阵息息相关了。

 

比如方程组:

x + 2y = 3

4x + 5y = 6

就可以用三个矩阵来表示他们。

 

系数矩阵:A =

| 1  2 |

| 4  5 |

 

变量矩阵:B =

| x |

| y |

 

常量矩阵:C =

| 3 |

| 6 |

 

所以上面的方程组也可以写成是:A * B = C

所以解方程组的问题也变成了求B。后面我会介绍到矩阵的逆,就会说到如何用A和C矩阵来求B。

 

 

2) 单位矩阵

定义:矩阵的主对角线所有元素都是1,其余都是0。用I表示。

如:

| 1  0 |

| 0  1 |

或:

| 1  0  0 |

| 0  1  0 |

| 0  0  1 |

单位矩阵的重要用途是因为他满足下面的公式:

A * I = I * A = A

 

 

3) 零矩阵

非常简单:

| 0  0 |

| 0  0 |

所有元素都是零。

 

 

4) 矩阵加法和减法

两个矩阵的相应元素相加或相减即可。

 

 

5) 矩阵的转置

将矩阵的行和列元素交换,就是转置,比如A =

| 0  1  2 |

| 3  4  5 |

的转置为 A' =

| 0  3 |

| 1  4 |

| 2  5 |

 

 

6) 矩阵与标量相乘

每个元素都乘以标量即可。

 

 

7) 矩阵与矩阵相乘

并不是任意两个矩阵都可以相乘的,矩阵A和矩阵B相乘,只有它们的内维数相等,才有意义。

比如,A是m×nj矩阵,那么B必须是n×r矩阵。

运算法则是:A*B=C,那么Cij = A中第i行的向量与B中第j列的向量的点积。

比如A =

| 0  1 |

| 2  3 |

 

B =

| 0  1  2 |

| 3  4  5 |

 

那么C =

| (0,1).(0,3)  (0,1).(1,4)  (0,1).(2,5) |

| (2,3).(0,3)  (2,3).(1,4)  (2,3).(2,5) |  =

 

| (0*0+1*3)  (0*1+1*4)  (0*2+1*5) |

| (2*0+3*3)  (2*1+3*4)  (2*2+3*5) |  =

 

|  3   4  5  |

|  9 14 19 |

 

8) 矩阵运算定律

1. A + B = B + A

2. A + (B + C) = (A + B) + C

3. A * (B * C) = (A * B)  * C

4. A * (B + C) = A * B + A * C

5. k * (A + B) = k * A+ k * B

6. (A + B) * C = A * C + B * C

7. A * I = I * A = A

 

注意:矩阵一般不满足乘法交换律,即 A * B 一般不等于 B * A

 

 

9) 矩阵的行列式

行列式来源:每一个方形矩阵可以和一个成为矩阵的行列式的实数相对应,这个数值将可以告诉我们矩阵是否是奇异的。

矩阵A的行列式表示为det(A)

在实际应用中,我们需要通过求行列式来求矩阵的逆,所以行列式的意义非常重大。

具体如何通过上面的来源来推导出求行列式的公式,在任何一本线性代数数上都有,我就省略了。公式如下:

对于n×n矩阵A,

det(A) = a11  (当n=1)

det(A) = a11 * A11 + a12 * A12 + ... + a1n * A1n  (当n>1时)

其中A1j = (-1)的1+j次方 * detA(M1j)  (其中j = 1, ... , n)

为第一行元素的余子式

 

说点具体的吧,2×2矩阵

| a  b |

| c  d |

的行列式为det(A) = a*d - b*c

 

3×3矩阵

| a00  a01  a02 |

| a10  a11  a12 |

| a20  a21  a22 |

的行列式为det(A) = a00*a11*a22 + a01*a12*a20 + a02*a10*a21 - a02*a11*a20 - a01*a10*a22 - a00*a12*a21

这个公式是使用克莱姆法则求出的,为什么上面我介绍余子式,因为使用克莱姆法则来求3×3矩阵的行列式要进行9次乘法和5次加法。但如果我们使用余子式来求行列式,则可以减少两次乘法:

det(A) = a00*(a11*a22 - a21*a12) - a01*(a10*a22 - a20*a12) - a02*(a10*a21 - a20*a11)

 

 

10) 矩阵的逆

定义:对于矩阵A,有矩阵A-1,使得A * A-1 = I,则A-1为矩阵A的逆。其实这个A-1就是A的乘法逆元。

数学上还有这种说法:如果一个n×n矩阵,如果不存在乘法逆元,则称这个矩阵是奇异的。

他的作用十分重要,比如上面说的方程组:

A * B = C,求矩阵B

那么通过将方程两边同时乘以A-1,则:

(A-1 * A) * B = A-1 * C

B = A-1 * C,这样就可以求得B了。

 

 

2. 代码实现

1) 我提供了1×3、1×4、3×3、4×4矩阵,因为对于2D点或向量,可以使用齐次坐标在3×3矩阵中存放,同理,对于3D点或向量可以使用齐次坐标在4×4矩阵中存放,所以只需要写上面这4种矩阵的运算函数,就可以满足所有的3D矩阵变换了。这次我把以前写的向量的结构体也做了修改,因为向量、点,通常可以表示为一个1×3或1×4矩阵,所以我把他们的内存结构修改为和矩阵的相同,以便直接强制转换。

下面是矩阵结构体的定义:

 

下面是对原向量和点的结构体的修改:

 

 

 2) 矩阵操作函数实现

 

 

 

3. 代码下载

完整项目代码下载:>>点击进入下载页<<

 

 

 

 

原创粉丝点击