Opengl入门基础(七)-数学基础

opengl除了基础的模型构建和贴图,还需要进行位置变换,缩放等功能,之前定义的顶点坐标(0,0.5,0),纹理坐标(0,0.5)实际上是一个向量,而对多个坐标构成的模型进行变换、缩放实际上是向量与矩阵相乘的结果,这涉及一些向量和矩阵的基础数学知识:

向量

Opengl只涉及三维,这里讨论的向量在一维到三维,三维向量如下:

向量的二维坐标,即z为0,向量的两个属性:大小和方向,通常默认(0,0,0)为初始点,一个向量为(1,2,3),即:自(0,0,0)出发,指向(1,2,3)点的一个向量(向量是有方向的,但是方向不影响向量的值),但是也可以自己定义出发点,比如从(0,0,1)为初始点,(1,2,3)为终点。


向量和标量的计算

标量,理解为一个数,1,3,5这都是标量,数学里是没有向量与标量的计算的,但是Opengl里的很多数学库都支持,举个例子:

向量与标量的计算包括:加减乘除

向量的取反

向量的正负,只影响方向,对向量取反,即逆转方向

向量和向量的计算

向量和向量的计算包括:加减

向量的加法满足平行四边形法则和三角形法则,向量之间的计算实际上是向量的合成,以二维向量的计算为例,(2,1)+(1,3)=(3,4),实际上反应在图上是:

向量的长度

一个初始点为 (,,)(x1,y1,c1),终点为 (,,)(x2,y2,c2) 的向量,他的长度为 (a1−a2)2+(b1−b2)2+(c1−c2)2

向量的乘法

向量相乘,比较特殊的有点乘和叉乘

点乘,即向量的数乘结果乘以余弦值:

x1¯∗x2¯=||x¯1||∗||x¯2||∗cosθ

叉乘,是为了,在三维空间中,生成两个不平行向量的正交向量,正交简单理解即垂直。

C、D是两个不平行的向量,两者进行叉乘获得向量E,向量E正交与B、D

叉乘计算公式:

矩阵

矩阵就是一个矩形的数字、符号或表达式数组。矩阵中每一项叫做矩阵的元素(Element)。

一个2×2矩阵:

矩阵通过(i, j)进行索引,i是行,j是列

矩阵的计算

矩阵与标量的计算

即矩阵的每个元素对标量的计算,计算包括:加减乘除

矩阵与矩阵的计算

矩阵与矩阵之间的加减,即矩阵元素之间的加减,通常的矩阵加法被定义在两个相同大小的矩阵。

矩阵相乘需要遵循的规则:

  1. 只有当左侧矩阵的列数与右侧矩阵的行数相等,两个矩阵才能相乘。
  2. 矩阵相乘不遵守交换律,也就是说A⋅B≠B⋅A

矩阵的乘法是一系列乘法和加法组合的结果,它使用到了左侧矩阵的行和右侧矩阵的列,结果矩阵的第[1,1]元素:

a1∗b1+a2∗b4 即第一个矩阵的第一行 a1a2 乘以第二个矩阵的第一列 b1b4 ,同样第[1,2],即即第一个矩阵的第一行 a1a2 乘以第二个矩阵的第二列 b2b5 ...

矩阵与向量

opengl里面定义的顶点坐标(0,0.5,0)是一个向量,它也是一个3*1的矩阵,形式如下:

所以矩阵与向量的计算,实际上是矩阵与N*1矩阵的计算,按照之前矩阵相乘的定义,这个计算矩阵应该是个1*M或者M*N的格式(我们常用的是M*N,实际上,是N *N)

缩放、位移与旋转

模型的位置和体积都是顶点与矩阵的相乘

缩放

对于顶点与矩阵的计算实现缩放,可以参考这个例子

顶点,即向量(0,0.5,0)乘的为单位矩阵,计算结果不变,如果单位矩阵乘以0.5,再与向量相乘,向量结果将缩小一倍,如下

同样,如果所有顶点坐标都与以上的矩阵相乘,那么模型体积就能缩小一倍,这就是缩放。

位移

要实现顶点的位移,就是让顶点向量统一增加某个数,看起来就像是:

实现方式:

基于单位矩阵

要移动 顶点x1y1z1的 x2y2z2 距离,就在单位矩阵最后一列的对应位置加上对应的距离。

这样定义的一个矩阵就是位移矩阵,有了位移矩阵我们就可以在3个方向(x、y、z)上移动物体,它是我们的变换工具箱中非常有用的一个变换矩阵。

旋转

向量的旋转,简单理解就是向量围绕一个轴,进行了 α 度的偏转,通常情况下是个三维空间,也就是旋转涉及x、y、z轴,与缩放、位移一样,需要乘以矩阵实现,因为涉及三个轴的旋转,所以不同的旋转需要乘以不同的矩阵,情况如下:

围绕x轴旋转pitch:α 度的偏转

围绕y轴旋转Yaw: α 度的偏转

围绕z轴旋转Roll: α 度的偏转

这里不解释这些矩阵是如何得到的,感兴趣的可以搜索下线性代数的相关知识,但是需要注意的是,以上实现的都是单次旋转,通常情况,需要多次旋转,比如先围绕x轴,再围绕y轴

这会导致万向节死锁问题,即当三个万向节其中两个的轴发生重合时,会失去一个自由度的情形。简单理解就是,当模型绕着x轴旋转90°后,它的z轴和y轴旋转就是同一个方向,产生了旋转死锁,采用矩阵旋转是无法避免万向节死锁问题,使用四元数可以避免,关于四元数是比较复杂的一种实现方式,作为入门,最好还是先理解矩阵,刚刚提到的万向节死锁问题,常常是因为将x、y、z轴多个旋转矩阵的多个步骤的复合导致的,当顶点 (x1,y1,z1) 需要旋转到某个位置,可以直接对照位置实现对应旋转轴 (xr,yr,zr) 的一次变换,实现方式如下:

矩阵的组合

采用矩阵实现缩放、位移和旋转,一个很重要的因素在于,矩阵可以实现组合,例如:

将顶点数据乘以上面组合后的矩阵,数据同时完成了放大两倍,平移(a,b,c)的位移。

 

https://zhuanlan.zhihu.com/p/484734712

 

posted @   imxiangzi  阅读(100)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示