OpenGL:矩阵

矩阵基础知识#

在具体描述如何构建模型矩阵、观察矩阵和投影矩阵之前,我们在这一节先介绍矩阵的各种基础知识(只介绍需要用到的知识)。

矩阵的基本含义#

m×n个数aij(i[1,m],j[1,n])组成的数列被称为m行n列的矩阵A(一般用大写数字表示矩阵):

Amn=[a11a12a13...a1na21a22a23...a2n...............am1am2am3...amn].

值得注意的是有一些特殊的矩阵:

  • m=n时,即矩阵A的行数和列数相等时被称为方阵
  • 当方阵的所有元素中除了对角元素的其余元素为0时,被称为对角矩阵
  • 当对角矩阵的对角元素都为1时,被称为单位矩阵(I
  • 当方阵满足aij=aji时,被称为对称矩阵

矩阵的运算#

矩阵与标量的乘法:矩阵中每个元素与标量相乘

α×Amn=[α×a11α×a12α×a13...α×a1nα×a21α×a22α×a23...α×a2n...............α×am1α×am2α×am3...α×amn].

矩阵加法:只有两个矩阵的维度一致时才能进行加法

Amn+Bmn=[a11a12a13...a1na21a22a23...a2n...............am1am2am3...amn]+[b11b12b13...b1nb21b22b23...b2n...............bm1bm2bm3...bmn]=[a11+b11a12+b12a13+b13...a1n+b1na21+b21a22+b22a23+b23...a2n+b2n...............am1+bm1am2+bm2am3+bm3...amn+bmn].

根据公式也可以推导得到:

  • A+B=B+A.
  • A+B+C=A+(B+C).
矩阵减法:可以进行如下简单变换

AB=A+(1)×B.

矩阵乘法:矩阵乘法是有顺序的,只有第一个矩阵的列数与第二个矩阵的行数相等时才能进行乘法运算,即Amn×Bnk=Cmk

Amn×Bnk=[a11a12a13...a1na21a22a23...a2n...............am1am2am3...amn]×[b11b12b13...b1kb21b22b23...b2k...............bn1bn2bn3...bnk]=[i=1na1i×bi1i=1na1i×bi2i=1na1i×bi3...i=1na1i×biki=1na2i×bi1i=1na2i×bi2i=1na2i×bi3...i=1na2i×bik...............i=1nami×bi1i=1nami×bi2i=1nami×bi3...i=1nami×bik].

可以发现矩阵的乘法就是cij=t=1nait×btj,即矩阵A的第i行组成的行向量与矩阵B的第j列组成的列向量进行内积。这也是为什么矩阵相乘要求第一个矩阵的列数等于第二个矩阵的行数。也可以看到矩阵乘法是有顺序的,即A×BB×A.

根据公式可以推导出:

  • A×B×C=A×(B×C).
  • A×(B+C)=A×B+A×C.
  • (A+B)×C=A×C+B×C.
  • 矩阵乘法不满足交换律!
转置:即将矩阵的翻转

Amn=[a11a12a13...a1na21a22a23...a2n...............am1am2am3...amn]=[a11a21a31...am1a12a22a32...am2...............a1na2na3n...amn].

可以看到一个m行n列的矩阵转置后变成了一个n行m列的矩阵。我们也可以说对称矩阵即其转置等于本身的矩阵:A=A.

有时候矩阵的转置也写为:AT.

由公式可以推导:

  • (A×B)=A×B.

矩阵变换#

齐次坐标#

假设目前在三维坐标中存在某个顶点(x,y,z),为了方便进行坐标的位移变换,我们额外添加一个维度将其转换为齐次坐标(x,y,z,1),注意这里虽然是四维坐标,但仍然代表着三维空间中的某个点。

平移变换#

现在期望将顶点(x,y,z),平移至新的顶点(x+a,y+b,z+c),那么可以构建如下的变换矩阵:

P=[100a010b001c0001].

此时对于原始顶点的齐次坐标α=(x,y,z,1),就可以通过简单的矩阵乘法进行变换(注意矩阵乘法顺序,要左乘变换矩阵):

α=P×α=[100a010b001c0001]×[xyz1]=[x+ay+bz+c1].

我们就得到了新的顶点的齐次坐标α=(x+a,y+b,z+c,1).

缩放变换#

现在期望针对顶点(x,y,z)的每一个维度分别进行缩放,分别扩大a,b,c倍,形成新的顶点即(a×x,b×y,c×z),可以构建如下的变换矩阵:

P=[a0000b0000c00001].

此时对于原始顶点的齐次坐标α=(x,y,z,1),就可以通过简单的矩阵乘法进行变换(注意矩阵乘法顺序,要左乘变换矩阵):

α=P×α=[a0000b0000c00001]×[xyz1]=[a×xb×yc×z1].

我们就得到了新的顶点的齐次坐标α=(a×x,b×y,c×z,1).

旋转变换#

我们直接考虑三维坐标旋转(相对于原点),由于对每个轴的旋转不一样,我们分别讨论绕x、y和z轴旋转的变换矩阵:

绕x轴逆时针旋转α#

如上图所示,点a绕x轴逆时针旋转α变为新的点a。不妨设点a距离原点为ρ,那么原始点a的坐标如下:

x=xy=ρcosβz=ρsinβ

旋转后的点a的坐标为:

x=xy=ρcos(α+β)=ρcosαcosβρsinαsinβ=ycosαzsinαz=ρsin(α+β)=ρsinαcosβ+ρcosαsinβ=ysinα+zcosα

因此绕x轴逆时针旋转α的变换矩阵为:

P=[10000cosαsinα00sinαcosα00001].

绕y轴逆时针旋转α#

如上图所示,点a绕y轴逆时针旋转α变为新的点a。不妨设点a距离原点为ρ,那么原始点a的坐标如下:

x=ρsinβy=yz=ρcosβ

旋转后的点a的坐标为:

x=ρsin(α+β)=ρsinαcosβ+ρcosαsinβ=xcosα+zsinαy=yz=ρcos(α+β)=ρcosαcosβρsinαsinβ=xsinα+zcosα

因此绕y轴逆时针旋转α的变换矩阵为:

P=[cosα0sinα00100sinα0cosα00001].

绕z轴逆时针旋转α#

如上图所示,点a绕z轴逆时针旋转α变为新的点a。不妨设点a距离原点为ρ,那么原始点a的坐标如下:

x=ρcosβy=ρsinβz=z

旋转后的点a的坐标为:

x=ρcos(α+β)=ρcosαcosβρsinαsinβ=xcosαysinαy=ρsin(α+β)=ρsinαcosβ+ρcosαsinβ=xsinα+ycosαz=z

因此绕y轴逆时针旋转α的变换矩阵为:

P=[cosαsinα00sinαcosα0000100001].

矩阵的组合#

使用矩阵进行变换的真正力量在于,根据矩阵之间的乘法,我们可以把多个变换组合到一个矩阵中。让我们看看我们是否能生成一个变换矩阵,让它组合多个变换。假设我们有一个顶点(x,y,z),我们希望将其缩放2倍,然后位移(1,2,3)个单位。我们需要一个位移和缩放矩阵来完成这些变换。结果的变换矩阵看起来像这样:

PTrans.Scale=[1001010200130001]×[2000020000020001]=[2001020200230001].

注意,当矩阵相乘时我们先写位移再写缩放变换的。矩阵乘法是不遵守交换律的,这意味着它们的顺序很重要。当矩阵相乘时,在最右边的矩阵是第一个与向量相乘的,所以你应该从右向左读这个乘法。建议您在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。比如,如果你先位移再缩放,位移的向量也会同样被缩放(译注:比如向某方向移动2米,2米也许会被缩放成1米)!

作者:Warren-j1an

出处:https://www.cnblogs.com/warren-j1an/p/18244434

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   warren-j1an  阅读(77)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示