#include "Angel.h"
#include "TriMesh.h"
#include <vector>
#include <string>
//#include "main.h"
using namespace std;
const int X_AXIS = 0;
const int Y_AXIS = 1;
const int Z_AXIS = 2;
const int TRANSFORM_SCALE = 0;
const int TRANSFORM_ROTATE = 1;
const int TRANSFORM_TRANSLATE = 2;
const double DELTA_DELTA = 0.3; // Delta的变化率
const double DEFAULT_DELTA = 0.5; // 默认的Delta值
double scaleDelta = DEFAULT_DELTA;
double rotateDelta = DEFAULT_DELTA;
double translateDelta = DEFAULT_DELTA;
glm::vec3 scaleTheta(1.0, 1.0, 1.0); // 缩放控制变量
glm::vec3 rotateTheta(0.0, 0.0, 0.0); // 旋转控制变量
glm::vec3 translateTheta(0.0, 0.0, 0.0); // 平移控制变量
int currentTransform = TRANSFORM_ROTATE; // 设置当前变换
int mainWindow;
//------------------------------------------------------------------------
bool isplaying = true; // 动画状态
int rotationAxis = X_AXIS; // 当前旋转轴,默认为 X 轴
int rotationTime = 1000; // 每1000帧旋转一次
string currentModel ="cow";
struct openGLObject
{
// 顶点数组对象
GLuint vao;
// 顶点缓存对象
GLuint vbo;
// 着色器程序
GLuint program;
// 着色器文件
std::string vshader;
std::string fshader;
// 着色器变量
GLuint pLocation;
GLuint cLocation;
GLuint matrixLocation;
GLuint darkLocation;
};
openGLObject cube_object;
TriMesh* cube = new TriMesh();
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void bindObjectAndData(TriMesh* mesh, openGLObject& object, const std::string& vshader, const std::string& fshader) {
// 创建顶点数组对象
glGenVertexArrays(1, &object.vao); // 分配1个顶点数组对象
glBindVertexArray(object.vao); // 绑定顶点数组对象
// 创建并初始化顶点缓存对象
glGenBuffers(1, &object.vbo);
glBindBuffer(GL_ARRAY_BUFFER, object.vbo);
glBufferData(GL_ARRAY_BUFFER,
mesh->getPoints().size() * sizeof(glm::vec3) + mesh->getColors().size() * sizeof(glm::vec3),
NULL,
GL_STATIC_DRAW);
// @TODO: Task3-修改完TriMesh.cpp的代码成后再打开下面注释,否则程序会报错
glBufferSubData(GL_ARRAY_BUFFER, 0, mesh->getPoints().size() * sizeof(glm::vec3), &mesh->getPoints()[0]);
glBufferSubData(GL_ARRAY_BUFFER, mesh->getPoints().size() * sizeof(glm::vec3), mesh->getColors().size() * sizeof(glm::vec3), &mesh->getColors()[0]);
object.vshader = vshader;
object.fshader = fshader;
object.program = InitShader(object.vshader.c_str(), object.fshader.c_str());
// 从顶点着色器中初始化顶点的位置
object.pLocation = glGetAttribLocation(object.program, "vPosition");
glEnableVertexAttribArray(object.pLocation);
glVertexAttribPointer(object.pLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
// 从顶点着色器中初始化顶点的颜色
object.cLocation = glGetAttribLocation(object.program, "vColor");
glEnableVertexAttribArray(object.cLocation);
glVertexAttribPointer(object.cLocation, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(mesh->getPoints().size() * sizeof(glm::vec3)));
// 获得矩阵存储位置
object.matrixLocation = glGetUniformLocation(object.program, "matrix");
}
void init()
{
std::string vshader, fshader;
// 读取着色器文件路径
vshader = "shaders/vshader.glsl";
fshader = "shaders/fshader.glsl";
//cube->generateCube();
//cube->readOff("./Models/cow.off");
if (currentModel == "cow") {
cube->readOff("./Models/cow.off");
}
else {
cube->generateCube();
}
bindObjectAndData(cube, cube_object, vshader, fshader);
// 设置背景色为黑色
glClearColor(0.0, 0.0, 0.0, 1.0);
}
// 渲染函数
void display()
{
// 清空颜色缓冲和深度缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(cube_object.program);
glBindVertexArray(cube_object.vao);
// 初始化变换矩阵 glm::mat4表示 4x4 矩阵
glm::mat4 m(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
// @TODO: Task4-在此处修改函数,计算最终的变换矩阵
// 调用函数传入三种变化的变化量,累加得到变化矩阵
// 注意三种变化累加的顺序
// 构建旋转矩阵
glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0), rotateTheta.x, glm::vec3(1.0, 0.0, 0.0))
* glm::rotate(glm::mat4(1.0), rotateTheta.y, glm::vec3(0.0, 1.0, 0.0))
* glm::rotate(glm::mat4(1.0), rotateTheta.z, glm::vec3(0.0, 0.0, 1.0));
// 构建缩放矩阵
glm::mat4 scaleMatrix = glm::scale(glm::mat4(1.0), glm::vec3(scaleTheta.x, scaleTheta.y, scaleTheta.z));
// 构建平移矩阵
glm::mat4 translateMatrix = glm::translate(glm::mat4(1.0), glm::vec3(translateTheta.x, translateTheta.y, translateTheta.z));
// 按照平移、旋转、缩放的顺序相乘得到最终的变换矩阵
m = translateMatrix * rotationMatrix * scaleMatrix;
// 传递变换矩阵到着色器
glUniformMatrix4fv(cube_object.matrixLocation, 1, GL_FALSE, glm::value_ptr(m));
// 绘制立方体中的各个三角形
glDrawArrays(GL_TRIANGLES, 0, cube->getPoints().size());
}
// 通过Delta值更新Theta
// axis 表示坐标轴,sign 表示增加或减少
// currentTransform 表示当前变换类型
void updateTheta(int axis, int sign) {
switch (currentTransform) {
// 根据变换类型,增加或减少某种变换的变化量
case TRANSFORM_SCALE:
//增加或减少缩放的 Theta 值
scaleTheta[axis] += sign * scaleDelta;
break;
case TRANSFORM_ROTATE:
//增加或减少旋转的 Theta 值
rotateTheta[axis] += sign * rotateDelta;
break;
case TRANSFORM_TRANSLATE:
//增加或减少平移的 Theta 值
translateTheta[axis] += sign * translateDelta;
break;
}
}
// 复原Theta和Delta
void resetTheta()
{
scaleTheta = glm::vec3(1.0, 1.0, 1.0); //scaleTheta 表示缩放变换的角度
rotateTheta = glm::vec3(0.0, 0.0, 0.0);
translateTheta = glm::vec3(0.0, 0.0, 0.0);
scaleDelta = DEFAULT_DELTA; //缩放变换的单位变化量
rotateDelta = DEFAULT_DELTA;
translateDelta = DEFAULT_DELTA;
}
// 更新变化Delta值
void updateDelta(int sign)
{
switch (currentTransform) {
// 根据变化类型增加或减少每一次变化的单位变化量
case TRANSFORM_SCALE:
scaleDelta += sign * DELTA_DELTA;
break;
case TRANSFORM_ROTATE:
rotateDelta += sign * DELTA_DELTA;
break;
case TRANSFORM_TRANSLATE:
translateDelta += sign * DELTA_DELTA;
break;
}
}
void cleanData();
// 处理键盘输入的回调函数
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
switch (key)
{
// 退出。
case GLFW_KEY_ESCAPE:
if (action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE);
break;
// 1:缩放模式
case GLFW_KEY_1:
if (action == GLFW_PRESS) currentTransform = TRANSFORM_SCALE;
break;
// 2: 旋转模式
case GLFW_KEY_2:
if (action == GLFW_PRESS) currentTransform = TRANSFORM_ROTATE;
break;
// 3: 移动模式
case GLFW_KEY_3:
if (action == GLFW_PRESS) currentTransform = TRANSFORM_TRANSLATE;
break;
// 4: 绘制线。
case GLFW_KEY_4:
if (action == GLFW_PRESS) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
break;
// 5: 绘制面。
case GLFW_KEY_5:
if (action == GLFW_PRESS) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
break;
// Q: 增加 x。
case GLFW_KEY_Q:
if (action == GLFW_PRESS || action == GLFW_REPEAT) updateTheta(X_AXIS, 1);
break;
// A: 减少 x。
case GLFW_KEY_A:
if (action == GLFW_PRESS || action == GLFW_REPEAT) updateTheta(X_AXIS, -1);
break;
// W: 增加 y。
case GLFW_KEY_W:
if (action == GLFW_PRESS || action == GLFW_REPEAT) updateTheta(Y_AXIS, 1);
break;
// S: 减少 y。
case GLFW_KEY_S:
if (action == GLFW_PRESS || action == GLFW_REPEAT) updateTheta(Y_AX

草海桐
- 粉丝: 665
- 资源: 11
最新资源
- FPGA纯Verilog编解码CameraLink视频的设计与实现:从HDMI解码到CameraLink模拟循环验证,FPGA纯Verilog编解码CameraLink视频循环验证方案介绍,FPGA纯
- GDB调试神器指南:5步定位C程序中的幽灵bug.pdf
- Linux系统编程入门:用C实现多进程通信的聊天室项目.pdf
- Linux环境编程实战:Vim+GCC调试技巧大公开.pdf
- Linux环境下的C语言开发:GCC、Vim调试全流程详解.pdf
- Makefile编写入门:3步让你的C项目告别重复编译.pdf
- Rust程序员眼中的C语言:安全编程的兼容性与改造策略.pdf
- Linux系统编程入门:用C语言实现文件批量处理器.pdf
- switch-case深度解析:为什么你的break总在捣乱?.pdf
- STM32开发入门:用C语言点亮你的第一个LED.pdf
- switch-case的隐藏BUG:break缺失引发的系统崩溃实录.pdf
- Valgrind内存检测实战:让程序不再薛定谔的崩溃.pdf
- Switch-case使用误区大揭秘:break缺失引发的血泪教训.pdf
- Valgrind内存检测:揪出C程序中的隐藏炸弹.pdf
- VSCode+C编译器配置指南:打造高效开发环境.pdf
- VSCode+C插件配置指南:智能提示、自动补全、一键调试.pdf
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈


