Opengl复习笔记(二)——坐标变换、三维初步入门【内含代码】

上一篇基本复习了一下顶点着色器、片段着色器,能绘制出最基本的带纹理的二维图片。接下来就该介绍三维是怎么一个过程~

简单变换

矩阵基础知识

矩阵是什么?
下面这个就是一个2X3矩阵,图片其实可以认为是这么一个矩阵,里面的元素是rgb像素
在这里插入图片描述
矩阵的运算

矩阵拥有和数值一样的加减乘除运算。
加(减)法(以下分别是跟标量和跟矩阵的加法)
在这里插入图片描述
在这里插入图片描述
矩阵乘法
和数值的乘法
在这里插入图片描述
矩阵相乘
在这里插入图片描述

缩放

假设向量v=(3,2) ,我们可以把向量沿着x轴缩放0.5,沿着y轴缩放2倍,得到的s如下图所示
在这里插入图片描述
可以定义空间的缩放举证如下
在这里插入图片描述

平移

在这里插入图片描述

旋转

9在这里插入图片描述
任意角度旋转(Rx,Ry,Rz)包含任意旋转轴
在这里插入图片描述

矩阵的组合

这个就是注意旋转平移的先后顺序!!!!
矩阵计算的代码可以结合后面介绍的相机计算代码一起放在同一个util文件中

三维系统介绍

我们在观察实际的物体的时候,都是有一个透视效果,也即是近大远小。比如下图所示,实际的轨道其实是2个平行线,但是视觉效果在远方会相交。
在这里插入图片描述

相机

首先我们先看一些材料里常见的计算公式。
在这里插入图片描述
如何去理解这个公式
Mprojection 是投影矩阵
实际我们能观察到的内容,是有一个限制区域的,如下图所示
在这里插入图片描述
能观察到的物体应该是在near plane和far plane所夹的梯形区域内。比如上图中的蓝色小矩形体就不能被摄像头观察到。
通过FOV角度、视角宽高比、近远距离可以定量描述这个区域
通常用到的函数如下,第一个参数是FOV角度,第二个参数是宽高比,第三个参数是近距离,第四个参数是远距离。

glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);

Mview 是观察矩阵
简单来说就是这个摄像机的位置姿态描述。如下图所示
在这里插入图片描述
数学的描述就是look at 矩阵,实际的计算函数如下

glm::mat4 view;
view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));

第一个是位置向量(上图的图1),第二个是定义相机看向的方向(上图的图2),第三个是定义摄像机朝上的向量(上图的图3)

Mmodel 是模型矩阵
定义矩阵平移旋转等变换

Vlocal 是模型顶点数据
这就是模型数据,后面会写这个数据怎么读取

下面是矩阵计算的具体代码:

/*---该文档主要用于数组计算---*/

#include <math.h>
#define PI 3.14159265f

//设置单位矩阵
void setone(float *matrix) 
{
   
	*(matrix + 0) = 1;
	*(matrix + 1) = 0;
	*(matrix + 2) = 0;
	*(matrix + 3) = 0;

	*(matrix + 4) = 0;
	*(matrix + 5) = 1;
	*(matrix + 6) = 0;
	*(matrix + 7) = 0;

	*(matrix + 8) = 0;
	*(matrix + 9) = 0;
	*(matrix + 10) = 1;
	*(matrix + 11) = 0;

	*(matrix + 12) = 0;
	*(matrix + 13) = 0;
	*(matrix + 14) = 0;
	*(matrix + 15) = 1;
}

//向量归一化
void normalize(float *vector) 
{
   
	float matrix = pow(*(vector + 0), 2) + pow(*(vector + 1), 2) + pow(*(vector + 2), 2);
	matrix = pow(matrix, 0.5);
	*(vector + 0) = *(vector + 0) / matrix;
	*(vector + 1) = *(vector + 1) / matrix;
	*(vector + 2) = *(vector + 2) / matrix;
}

//投影矩阵
/*
	float projection[4][4];
	profection(45.0f, 800.0f / 800.0f, 0.1f, 100.0f, *projection);
*/
void profection(float angle, float ar, float zNear, float zFar,float *matrix)
{
   
	float zRange = zFar - zNear;
	float tanHalfFOV = tan(PI * angle / (float)360);
	//float tanHalfFOV = tan(angle);

	*(matrix + 0) = 1.0f / (ar * tanHalfFOV);
	*(matrix + 1) = 0;
	*(matrix + 2) = 0;
	*(matrix + 3) = 0;

	*(matrix + 4) = 0;
	*(matrix + 5) = 1.0f / tanHalfFOV;
	*(matrix + 6) = 0;
	*(matrix + 7) = 0;

	*(matrix + 8) = 0;
	*(matrix + 9) = 0;
	*(matrix + 10) = (-zNear - zFar) / zRange;
	*(matrix + 11) = -1;

	*(matrix + 12) = 0;
	*(matrix + 13) = 0;
	*(matrix + 14) = -2.0f * zFar * zNear / zRange;
	*(matrix + 15) = 0;
}

//绕任意轴旋转角度
/*
	float matrix[4][4];
	setone(*matrix);
	float vector[3] = { 1.0f,1.0f,1.0f };
	rotate(*matrix, angle, vector);
*/
void rotate(float *matrix, float angle, float *vector)
{
   
	float a = PI * angle / (float)180;
	float c = cos(a);
	float s = sin(a);

	normalize(vector);

	float tmp[4][4];
	tmp[0][0] = (*(vector + 0))*(*(vector + 0))*(1 - c) + c;
	tmp[0][1] = (*(vector + 0))*(*(vector + 1))*(1 - c) + (*(vector + 2))*s;
	tmp[0][2] = (*(vector + 0))*(*(vector + 2))*(1 - c) - (*(vector + 1))*s;
	tmp[0][3] = 0;

	tmp[1][0] = (*(vector + 0))*(*(vector + 1))*(1 - c) - (*(vector + 2))*s;
	tmp[1][1] = (*(vector + 1))*(*(vector + 1))*(1 - c) + c;
	tmp[1][2] = (*(vector + 1))*(*(vector + 2))*(1 - c) + (*(vector + 0))*s;
	tmp[1][3] = 0;

	tmp[2][0] = (*(vector + 0))*(*(vector + 2))*(1 - c) + (*(vector + 1))*s;
	tmp[2][1] = (*(vector + 1))*(*(vector + 2))*(1 - c) - (*(vector + 0))*s;
	tmp[2][2] = (*(vector + 2))*(*(vector + 2))*(1 - c) + c;
	tmp[2][3] = 0;

	tmp[3][0] = 0;
	tmp[3][1] = 0;
	tmp[3][2] = 0;
	tmp[3][3] = 1;

	float tmp_m[4][4];

	tmp_m[0][0] = tmp[0][0] * (*(matrix + 0)) + tmp[0][1] * (*(matrix + 4)) + tmp[0][2] * (*(matrix + 8)) + tmp[0][3] * (*(matrix + 12));
	tmp_m[0][1] = tmp[0][0] * (*(matrix + 1)) + tmp[0][1] * (*(matrix + 5)) + tmp[0][2] * (*(matrix + 9)) + tmp[0][3] * (*(matrix + 13));
	tmp_m[0][2] = tmp[0][0] * (*(matrix + 2)) + tmp[0][1] * (*(matrix + 6)) + tmp[0][2] * (*(matrix + 10)) + tmp[0][3] * (*(matrix + 14));
	tmp_m[0][3] = tmp[0][0] * (*(matrix + 3)) + tmp[0][1] * (*(matrix + 7)) + tmp[0][2] * (*(matrix + 11)) + tmp[0][3] * (*(matrix + 15));

	tmp_m[1][0] = tmp[1][0] * (*(matrix + 0)) + tmp[1][1] * (*(matrix + 4)) + tmp[1][2] * (*(matrix + 8)) + tmp[1][3] * (*(matrix + 12));
	tmp_m[1][1] = tmp[1][0] * (*(matrix + 1)) + tmp[1][1] * (*(matrix + 5)) + tmp[1][2] * (*(matrix + 9)) + tmp[1][3] * (*(matrix + 13));
	tmp_m[1][2] = tmp[1][0] * (*(matrix + 2)) + tmp[1][1] * (*(matrix + 6)) + tmp[1][2] * (*(matrix + 10)) + tmp[1][3] * (*(matrix + 14));
	tmp_m[1][3] = tmp[0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值