OpenGL:为3D立方体设置动画

 

 Application.cpp

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
#include <iostream>
#include <fstream>
#include "Utils.h"
#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace std;

#define numVAOs 1
#define numVBOs 2

float cameraX, cameraY, cameraZ;//相机的空间位置
float cubeLocX, cubeLocY, cubeLocZ;
GLuint renderingProgram;
GLuint vao[numVAOs];//顶点数组对象
GLuint vbo[numVBOs];//顶点缓冲对象
//GLuint offsetLoc;
float x = 0.0f;    // 三角形在x轴的位置
float inc = 0.01f; // 移动三角形的偏移量

//分配在display()函数中使用的变量空间,这样他们就不必在渲染过程中分配
GLuint mvLoc, projLoc;
int width, height;
float aspect;
glm::mat4 pMat, vMat, mMat, mvMat;//透视矩阵、视图矩阵、模型矩阵和MV矩阵
glm::mat4 tMat, rMat;//平移矩阵、旋转矩阵

void setupVertices(void) {  //36个顶点,12个三角形,组成了放置在原点的2*2*2立方体
	float vertexPositions[108] = {
		-1.0f,  1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
		1.0f, -1.0f, -1.0f, 1.0f,  1.0f, -1.0f, -1.0f,  1.0f, -1.0f,
		1.0f, -1.0f, -1.0f, 1.0f, -1.0f,  1.0f, 1.0f,  1.0f, -1.0f,
		1.0f, -1.0f,  1.0f, 1.0f,  1.0f,  1.0f, 1.0f,  1.0f, -1.0f,
		1.0f, -1.0f,  1.0f, -1.0f, -1.0f,  1.0f, 1.0f,  1.0f,  1.0f,
		-1.0f, -1.0f,  1.0f, -1.0f,  1.0f,  1.0f, 1.0f,  1.0f,  1.0f,
		-1.0f, -1.0f,  1.0f, -1.0f, -1.0f, -1.0f, -1.0f,  1.0f,  1.0f,
		-1.0f, -1.0f, -1.0f, -1.0f,  1.0f, -1.0f, -1.0f,  1.0f,  1.0f,
		-1.0f, -1.0f,  1.0f,  1.0f, -1.0f,  1.0f,  1.0f, -1.0f, -1.0f,
		1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,  1.0f,
		-1.0f,  1.0f, -1.0f, 1.0f,  1.0f, -1.0f, 1.0f,  1.0f,  1.0f,
		1.0f,  1.0f,  1.0f, -1.0f,  1.0f,  1.0f, -1.0f,  1.0f, -1.0f
	};

	glGenVertexArrays(1, vao);//创建顶点数组对象
	glBindVertexArray(vao[0]);//将vao标记为“活跃”
	glGenBuffers(numVBOs, vbo);//创建顶点缓冲对象

	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	//将包含顶点数据的数组复制进活跃缓冲区
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
}

void init(GLFWwindow* window) {
	renderingProgram = Utils::createShaderProgram("vertShader.glsl", "fragShader.glsl");

	glfwGetFramebufferSize(window, &width, &height);
	aspect = (float)width / (float)height;
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);

	cameraX = 0.0f; cameraY = 0.0f; cameraZ = 8.0f;
	//cubeLocX = 0.0f; cubeLocY = -2.0f; cubeLocZ = 0.0f;
	setupVertices();
}

void display(GLFWwindow* window, double currentTime) {
	glClear(GL_DEPTH_BUFFER_BIT);//清除缓冲区
	glClear(GL_COLOR_BUFFER_BIT);//清除颜色

	glUseProgram(renderingProgram);

	//获取MV矩阵和投影矩阵的统一变量
	mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
	projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
	//构建视图矩阵
	vMat = glm::translate(glm::mat4(1.0f), glm::vec3(-cameraX, -cameraY, -cameraZ));
	//使用当前时间来计算x轴,y轴,z轴坐标的不同变换
	tMat = glm::translate(glm::mat4(1.0f), 
		glm::vec3(sin(0.35f * currentTime) * 2.0f, 
			cos(0.52f * currentTime) * 2.0f, sin(0.7f * currentTime) * 2.0f));
	//用1.75来调整旋转速度
	rMat = glm::rotate(glm::mat4(1.0f), 1.75f * (float)currentTime, glm::vec3(0.0f, 1.0f, 0.0f));
	rMat = glm::rotate(rMat, 1.75f * (float)currentTime, glm::vec3(1.0f, 0.0f, 0.0f));
	rMat = glm::rotate(rMat, 1.75f * (float)currentTime, glm::vec3(0.0f, 0.0f, 1.0f));
	//顺序决定先旋转再平移
	mMat = tMat * rMat;
	//mMat = rMat * tMat;
	mvMat = vMat * mMat;

	//将透视矩阵和MV矩阵复制给相应的统一变量
	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));

	//将VBO关联给顶点着色器中相应的顶点属性
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);//标记第0个缓冲区为“活跃”
	glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);//将第0个属性关联到缓冲区
	glEnableVertexAttribArray(0);//启用第0个顶点属性

	//调整OpenGL设置,绘制模型
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glDrawArrays(GL_TRIANGLES, 0, 36);

}

void window_size_callback(GLFWwindow* win, int newWidth, int newHeight) {
	aspect = (float)newWidth / (float)newHeight;
	glViewport(0, 0, newWidth, newHeight);
	pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);
}

int main(void) {
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(600, 600, "翻滚正方形", NULL, NULL);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);
	//该函数设置指定窗口的大小回调,当窗口调整大小时调用该回调。回调提供了窗口内容区域的大小(以屏幕坐标表示)
	glfwSetWindowSizeCallback(window, window_size_callback);

	init(window);

	while (!glfwWindowShouldClose(window)) {
		display(window, glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}

 Utils.cpp和Utils.h
见这个链接

fragShader.glsl 文件内容:

#version 430
//输入顶点着色器中的颜色
in vec4 varyingColor;
//输出片段颜色
out vec4 color;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

void main(void)
{	color = varyingColor;
}

vertShader.glsl 文件内容:

#version 430

layout (location=0) in vec3 position;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;

out vec4 varyingColor;

void main(void)
{
    gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
    //根据顶点的位置赋予颜色
    varyingColor = vec4(position,1.0) * 0.5 + vec4(0.5,0.5,0.5,0.5);
} 

 

课程简介:本课程详细讲解基于Assimp C++库的模型读取模块,并且做了关于动画理论、关键帧插值、骨骼动画矩阵原理、骨骼动画读取与播放等知识的详细讲解,对于游戏行业或者三维可视化从业人员会有比较大的帮助。目前很多公司已经开始构建自己的底层图形引擎,其中动画就是重要的一个版块,本课程可以让学员从原理层面以及底层代码层面了解FBX、OBJ模型的读取本质,并且梳理程序架构,编写骨骼动画。2 课程解决优势:很多同学学习骨骼动画苦于无法找到详细的资料,其中卡主的问题点也比比皆是,比如FBX内嵌材质的读取,骨骼动画各类矩阵的应用,理论结合模型读取库读出来的数据如何一一对应等。我们的课程可以带领大家从原理+实践的角度进行学习,每一个知识点都会:a 推导基础公式及原理 b 一行一行进行代码实践从而能够保证每位同学都学有所得,能够看得懂,学得会,用得上,并且能够培养自主研究的能力。3 学习课程所得:学习本课程完毕之后,学员可以全方位的完全了解基于Assimp库的模型读取结构,了解每一个变量背后的含义,并且课程拥有随堂附赠的源代码,保证同学可以随时根据老师的代码纠正自己的错误。跟随课程一行一行写完代码的同学,可以获得自己的模型读取代码库,并且深度理解骨骼动画的原理与模型读取原理 本课程含有全源代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值