OpenGL 变换

OpenGL 变换

我们现在知道如何创建对象,为它们着色或赋予它们一个详细的外观,但它们仍然没有那么有趣,因为它们都是静态对象。我们可以尝试通过更改其顶点并重新配置每个帧的缓冲区来移动它们,但这很麻烦,并且需要相当多的处理能力。有更好的方法来转换对象,这是通过使用(多个)矩阵来实现的。

矩阵是非常强大的数学结构,起初看起来很可怕,但一旦你习惯了它们,它们被证明是非常有用的。在讨论矩阵时,我们将不得不深入学习一些数学知识。

然而,要充分理解变换,我们首先必须在讨论矩阵之前深入研究向量。本章的重点是为您提供我们以后主题需要的基本数学背景。

向量

在最基本的定义中,向量是方向,仅此而已。一个向量同时具有方向和大小(也称为其强度或长度)。你可以把向量想像成宝藏地图上的方向:“向左走10步,现在向北走3步,向右走5步”:这里’左’是方向和’10步’是向量的大小。因此,宝藏图的方向包含 3 个向量。向量可以具有任何维度,但我们通常使用 2 到 4 维。如果向量具有 2 个维度,它表示平面上的方向(想想 2D 图形),当它有 3 个维度时,它可以代表 3D 世界中的任何方向。

下面将看到 3 个向量,其中每个向量(x,y)在 2D 图中用箭头表示。用2D(而不是3D)显示向量更直观,你可以认为2D向量作为Z=0 的3D向量。
在这里插入图片描述
因为向量只有大小和方向两个要素,起点并不在内,所以我们可以认为向量w和向量v是相同的。本文中向量用粗斜体字来表示,比如之前的向量w和向量v,例如:
在这里插入图片描述

向量运算

标量

和一个标量进行计算是最简单的一种运算了,加减乘除都可以(除数不能是0)。计算方式就是用向量的每个分量和标量进行一次运算,得出的一个新向量就是计算的结果。
在这里插入图片描述

向量取反

向量取反操作直接把向量的方向变反了,对向量的大小并没有什么影响,运算方式非常简单。
在这里插入图片描述

向量加减

向量相加操作就是把两个向量的相应分量相加,得到一个新的向量。
在这里插入图片描述
向量相减操作就是把两个向量的对应分量相减,得到一个新的向量。
在这里插入图片描述

长度

为了计算矢量的长度/大小,我们使用勾股定理。
在这里插入图片描述
在这里插入图片描述

向量乘法

向量乘法两种特殊的乘法运算,点乘(w · v)和叉乘(w x v)。
点乘
两个向量的点乘结果是两个向量长度的乘积再乘上夹角的cos值,像这样:
在这里插入图片描述
叉乘
叉乘定义在3D空间中,因为叉乘以两个非平行向量作为输入,结果向量方向是与两个相乘的向量都垂直的。在2D空间里,你无法找到一个能与两条相交的直线都垂直的直线,但在3D空间中可以!
在这里插入图片描述
向量叉乘公式:
在这里插入图片描述

矩阵

所谓矩阵,基本上就是一个矩形数组,这个数组中可能有数字、符号或者表达式。矩阵中的每一项被称为矩阵的一个元素。举一个2x3的矩阵例子来看:
在这里插入图片描述
矩阵可以通过索引获取其某个位置的元素,例如 :索引(i,j)表示第i行第j列的元素。这也就是为什么上面的矩阵被称为2 x 3的矩阵,因为它是2行3列。引用矩阵元素可能会和表示坐标上的点相混淆,一个(2,1)的位置表示x=2,y=1,而一个(2,1)的矩阵索引表示row = 2, column = 1,刚好和位置坐标相反。

矩阵加减

和标量
矩阵可以和一个标量相加或相减。方式是用矩阵的每一个分量去加或者减这个标量:
标量加法
在这里插入图片描述
和矩阵
当一个矩阵和另一个矩阵相加或者相减的时候,情况也很简单,只要将两个矩阵对应的分量相加或者相减就行了。
在这里插入图片描述
在这里插入图片描述
你可能会问,如果两个矩阵的维数(所谓维数,就是矩阵的行数和列数)不同,那该怎么加减呢?没错,不同维数的矩阵的加减操作没有意义,所以在数学上,我们就禁止不同维数的矩阵进行加减操作!

矩阵乘法

和标量
和标量的乘法非常简单,只需要把标量和矩阵的每个元素相乘,得到一个新的矩阵就行了。
在这里插入图片描述
和矩阵
在矩阵相乘之前,有两个最基本的原则:

  • 相乘的两个矩阵,第一个矩阵的列数必须要等于第二个矩阵的行数
  • 矩阵相乘不满足交换律,也就是说A · B != B · A
    在这里插入图片描述
    我们可以看到,矩阵的乘法是第一个矩阵的行,乘以第二个矩阵的列,对应元素相乘然后求和(这就是为什么有第一条原则的原因了!)。

这里我们给出了行列数相同的矩阵乘法示例,根据规则,矩阵行列数不同,也能进行运算。两个可以相乘的矩阵(注意哦,前提是可以相乘!)的运算结果也是一个矩阵,这个结果矩阵的行数等于第一个矩阵,列数等于第二个矩阵(想象一下用一个矩阵乘以一个向量,得到的结果也必定是一个向量)。

矩阵与向量相乘

单位矩阵
所谓单位矩阵就是除了从左上角到右下角对角线上的元素都是1,其余元素都是0的矩阵。一个单位矩阵和一个向量相乘,结果还是那个向量,就像任何数乘以1都不会对其有啥改变。
在这里插入图片描述
缩放
我们可以构造一个矩阵来对向量进行缩放,除了对各个坐标进行统一缩放,我们还能通过给不同的坐标设置不同缩放因子这种方法对各个坐标进行不统一的缩放。
在这里插入图片描述
如果S1,S2,S3不相同,那就是不统一缩放(改变方向),如果相同,那就是统一缩放(不改变方向)。注意,保留第四个缩放因子为1。
平移
要想平移一个向量,只要在这个矩阵的最后一列放上我们需要平移的量就行了,当然最后一个必须还是1,像这样:
在这里插入图片描述
旋转

旋转稍微有点复杂。首先我们要了解的是,如何定义一个旋转?有人可能会问,旋转还要定义吗?直接往左或者往右转个90度不就完了吗?但实际没那么简单,因为在数学世界中,角度有两种表示方法:角度或者弧度。我们熟悉的都是用角度来表示,一圈有360度。而在数学世界里,弧度也是非常常用的,一圈是2Π。为了便于理解,我们用角度来说明。

角度和弧度可以相互转换,具体的公式是:
角度= 弧度 * (180.0f / Π)
弧度= 角度 * (Π / 180.0f)
Π的精度最好高一点,以免出现误差,通常把它设置为:3.14159265359。

在3D世界中,当我们需要将一个向量进行旋转,我们就需要确定三样东西:

  • 绕着什么旋转
  • 往哪个方向旋转
  • 旋转多少度

理论上,我们可以绕任意轴旋转,不过在计算的时候,我们通常把绕任意轴旋转的操作分解成绕三条主轴旋转。通过一些三角变换函数,计算出绕某一个主轴的变换结果,然后将这些操作结合起来,组成绕任意轴旋转的操作。下面直接给出绕3个轴旋转的变换公式:

绕X轴旋转:
在这里插入图片描述
绕Y轴旋转:
在这里插入图片描述
绕Z轴旋转:
在这里插入图片描述
使用旋转矩阵,我们可以围绕三个主轴之一变换位置向量。例如,要围绕任意的 3D 轴旋转,我们可以通过先围绕 X 轴旋转,然后是 Y,然后 Z 来组合所有 3 个轴。然而,这很快引入了一个叫做万向锁的问题。我们不会讨论细节,但更好的解决方案是围绕任意的单位轴旋转,例如 (0.662,0.2,0.722)(请注意,这是一个单位向量),而不是结合旋转矩阵。这样的矩阵存在,并给出下面与(Rx,Ry,Rz)作为任意旋转轴:
在这里插入图片描述

实战演练

了解了这么多基础知识,但我们是要学OpenGL的,花太多的时间在实现数学基础知识上显然和我们的初衷背道而驰,所以,我们直接找一个数学库用,叫做:GLM。

到GLM的网站去下载0.9.8版本的数学库(不要下最新的0.9.9版本,和我们的代码不兼容)。下载解压后,把头文件根目录(glm目录,不是解压缩后的glm文件夹,而是在里面的glm文件夹)复制到你的includes目录下面就可以了。

设置完后,我们需要在代码中包含需要的头文件。

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include<iostream>
using namespace std;

int main() {
   
	glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);
	glm::mat4 trans = glm::mat4(1.0f);
	trans = glm::translate(trans, glm::vec3(1.0f, 1.0f, 0.0f));
	vec = trans * vec;
	cout << vec.x <<","<< vec.y<<"," << vec.z << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值