OpenGL入门第四次实验 几何变换(一)

链接: https://pan.baidu.com/s/1cBTTbbzRCVBCX_H4jf6qMA 提取码: kj8w
一、实验原理
本次实验利用OpenGL的GLFW库以及glm进行几何变换操作,实现了作业的两个要求。
GLFW是一个用于OpenGL应用程序开发的可移植库。它处理与OpenGL上下文创建、窗口管理、分辨率切换、键盘、鼠标、操纵杆和时间输入以及基本线程设施相关的系统特定任务。
GLEW能自动识别当前平台所支持的全部OpenGL高级扩展涵数。只要包含glew.h头文件,就能使用gl,glu,glext,wgl,glx的全部函数。GLEW支持目前流行的各种操作系统
glm常用的数据类型:
vec2 二维向量vec3 三维向量vec4 四维向量
mat2 二阶矩阵mat3 三阶矩阵mat4 四阶矩阵
glm::translate() 创建一个平移矩阵,第一个参数是目标矩阵,第二个参数是平移的方向向量
glm::rotate() 创建一个将点绕某个轴旋转x弧度的旋转矩阵,第一个参数是弧度,第二个参数是旋转轴
glm::scale() 创建一个缩放矩阵,第一个参数是目标矩阵,第二个参数是缩放系数

二、实验代码说明
1、定义新的VAO和VBO来缓存数据。
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);

unsigned int VBO2, VAO2, EBO2;
glGenVertexArrays(1, &VAO2);
glGenBuffers(1, &VBO2);
glGenBuffers(1, &EBO2);

glBindVertexArray(VAO2);

glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO2);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

2、两个四边形的transform变换矩阵操作
// create transformations
glm::mat4 transform = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
transform = glm::rotate(transform, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));

	glm::mat4 transform2 = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
	transform2 = glm::translate(transform2, glm::vec3(-0.5f, 0.5f, 0.0f));
	//transform2 = glm::rotate(transform2, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
	transform2 = glm::scale(transform2, glm::vec3(sin(glfwGetTime()), sin(glfwGetTime()), sin(glfwGetTime())));
	
	

	// get matrix's uniform location and set matrix
	ourShader.use();
	unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");
	glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform));
	// render container
	glBindVertexArray(VAO);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

	unsigned int transformLoc2 = glGetUniformLocation(ourShader.ID, "transform");
	glUniformMatrix4fv(transformLoc2, 1, GL_FALSE, glm::value_ptr(transform2));

	glBindVertexArray(VAO2);
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

三、实验运行结果(包含用户输入和输出)

1、 在程序中将平移变换和旋转变换交换顺序,看看有什么变化并且解释一下变化的原因。
平移和旋转操作交换顺序之后,由原本的先平移到(0.5,-0.5)的位置,再开始绕图形中心轴开始旋转,变成了先开始旋转,再将图形平移到(0.5,-0.5)的位置,但是后者的旋转并不是绕图形本身的中心。
由于矩阵相乘是不满足交换律的,所以先平移再旋转和先旋转再平移的结果不一样很正常,旋转变换矩阵确定之后,它的旋转中心轴就随之确定了,不再跟随后面的变换移动,第一次先平移后,还未进行旋转操作,旋转轴默认在图形的中心;
而第二次变换是先旋转,转轴确定之后,图形矩阵乘上平移变换矩阵把图形本身移动了,但是转轴还是原来的位置。
在这里插入图片描述
在这里插入图片描述
图1 先旋转后平移图像
2、 请试着再次调用glDrawElements画出第二个位置位于窗口左上角的同样形状的四边形(通过使用translate几何变换来设置第二个四边形的位置),该四边形不用旋转,而是要使得该四边形的大小能够随着时间有规律的缩放(可以考虑使用sin或cos函数,即将四边形的缩放系数设置为系统时间的sin函数)。
通过设置两个VAO和VBO,进行两个图形的初始化。
在这里插入图片描述
图3 图形初始化代码

然后设置另外一个transform2的变换矩阵实现另一个四边形的变化;这个变换矩阵先将图形平移到窗口左上角,再根据系统时间的正弦值进行缩放操作,实现缩放动画。
在这里插入图片描述在这里插入图片描述

图4 新建矩阵变换实现代码
最后也和VAO、VBO、EBO一样释放掉新开辟的空间。

结果截图如下:
在这里插入图片描述
在这里插入图片描述

图5 第二小题结果截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值