画一个可以由鼠标键盘控制的立方体

本节将会再OpenGL中配置一个摄像机,让正方体能够再3D场景中自由移动,同时也会讨论鼠标和键盘输入。OpenGL本身没有相机的概念,我们可以通过把物体往相反的方向移动来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动。
首先需要修改core.vs

#version 330 core
layout(location = 0) in vec3 position;
layout (location = 1) in vec3 color;
uniform mat4 transform;
uniform mat4 view;
uniform mat4 projection;out vec3 outColor;void main()
{gl_Position = projection * view * transform * vec4(position,1.0f);
outColor=color;
}

片源着色器core.fs不用作修改

#version 330 core
in vec3 outColor;
out vec4 color;
void main()
{color = vec4(outColor,1.0f);
}

接下来定义头文件Camera.h

#pragma once
#include<vector>
#define GLFW_STATIC
#include<GL/glew.h>#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>enum Camera_Movement
{FOWARD,BACKWARD,LEFT,RIGHT
};//6个自由度const GLfloat YAW = -90.0f;//
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 6.0f;
const GLfloat SENSITIVITY = 0.25f;//灵敏度
const GLfloat ZOOM = 45.0f;class Camera
{public:Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f),GLfloat yaw = YAW, GLfloat pitch = PITCH):front(glm::vec3(0.0f, 0.0f, -1.0f)), movementSpeed(SPEED),mouseSensitivity(SENSITIVITY), zoom(ZOOM){this->position = position;this->worldUp = up;this->yaw = yaw;this->pitch = pitch;this->updateCameraVectors();}Camera(GLfloat posX,GLfloat posY,GLfloat posZ,GLfloat upX,GLfloat upY,GLfloat upZ,GLfloat yaw = YAW, GLfloat pitch = PITCH) :front(glm::vec3(0.0f, 0.0f, -1.0f)), movementSpeed(SPEED),mouseSensitivity(SENSITIVITY), zoom(ZOOM){this->position = glm::vec3(posX,posY,posZ);this->worldUp = glm::vec3(upX,upY,upZ);this->yaw = yaw;this->pitch = pitch;this->updateCameraVectors();}void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)//时间控制速度{GLfloat velocity = this->movementSpeed * deltaTime;if (direction == FOWARD) {this->position += this->front * velocity;}if (direction == BACKWARD) {this->position -= this->front * velocity;}if (direction == LEFT) {this->position -= this->right * velocity;}if (direction == RIGHT) {this->position += this->right * velocity;}}void ProcessMouseMovement(GLfloat xOffset,GLfloat yOffset){xOffset *= this->mouseSensitivity;yOffset *= this->mouseSensitivity;this->yaw += xOffset;this->pitch += yOffset;this->updateCameraVectors();}void ProcessScroll(GLfloat yOffset){this->zoom += yOffset;}GLfloat GetZoom(){return this->zoom;}glm::mat4 GetViewMatrix(){//视角矩阵return glm::lookAt(this->position, this->position + this->front, this->up);}
private:GLfloat yaw;GLfloat pitch;GLfloat movementSpeed;GLfloat mouseSensitivity;GLfloat zoom;glm::vec3 position;glm::vec3 front;glm::vec3 up;glm::vec3 right;glm::vec3 worldUp;void updateCameraVectors(){//相机的位置和朝向(前、上、右)glm::vec3 front;front.x = cos(glm::radians(this->pitch)) * cos(glm::radians(this->yaw));front.y = sin(glm::radians(this->pitch));front.z = cos(glm::radians(this->pitch)) * sin(glm::radians(this->yaw));this->front = glm::normalize(front);//normalize取单位化this->right = glm::normalize(glm::cross(this->front, this->worldUp));this->up = glm::normalize(glm::cross(this->right, this->front));}
};

欧拉角

欧拉角可以表示3D空间中任何旋转的3个值,由莱昂哈德·欧拉(Leonhard Euler)在18世纪提出。一共有3种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),下面的图片展示了它们的含义:

俯仰角是描述我们如何往上或往下看的角,可以在第一张图中看到。第二张图展示了偏航角,偏航角表示我们往左和往右看的程度。滚转角代表我们如何翻滚摄像机,通常在太空飞船的摄像机中使用。每个欧拉角都有一个值来表示,把三个角结合起来我们就能够计算3D空间中任何的旋转向量了。

对于我们的摄像机系统来说,我们只关心俯仰角和偏航角,所以我们不会讨论滚转角。给定一个俯仰角和偏航角,我们可以把它们转换为一个代表新的方向向量的3D向量。
Shader.h不做改动

#pragma once#include <string.h>
#include <fstream>
#include <sstream>
#include <iostream>#include <GL/glew.h>class Shader
{GLuint vertex, fragment;
public:GLuint Program;Shader(const GLchar* vertexPath, const GLchar* fragmentPath){std::string vertexCode;std::string fragmentCode;std::ifstream vShaderFile;std::ifstream fShaderFile;vShaderFile.exceptions(std::ifstream::badbit);fShaderFile.exceptions(std::ifstream::badbit);try{vShaderFile.open(vertexPath);fShaderFile.open(fragmentPath);std::stringstream vShaderStream, fShaderStream;vShaderStream << vShaderFile.rdbuf();fShaderStream << fShaderFile.rdbuf();vShaderFile.close();fShaderFile.close();vertexCode = vShaderStream.str();fragmentCode = fShaderStream.str();}catch (std::ifstream::failure e){std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl;}const GLchar* vShaderCode = vertexCode.c_str();const GLchar* fShaderCode = fragmentCode.c_str();//compile ShadersGLint success;GLchar infoLog[512];vertex = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex, 1, &vShaderCode, NULL);glCompileShader(vertex);glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertex, 512, NULL, infoLog);std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"<< infoLog << std::endl;}fragment = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment, 1, &fShaderCode, NULL);glCompileShader(fragment);glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragment, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"<< infoLog << std::endl;}this ->Program = glCreateProgram();glAttachShader(this->Program, vertex);glAttachShader(this->Program, fragment);glLinkProgram(this->Program);glGetProgramiv(this->Program, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(this->Program, 512, NULL, infoLog);std::cout << "ERROR::SHADER::PROGRAM::LINK_FAILED\n"<< infoLog << std::endl;}}~Shader() {glDetachShader(this->Program, vertex);glDetachShader(this->Program, fragment);glDeleteShader(vertex);glDeleteShader(fragment);glDeleteProgram(this->Program);}void Use(){glUseProgram(this->Program);}
};

main.cpp

#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include<GLFW/glfw3.h>
#include "Shader.h"
#include "Camera.h"//GLM
#include<glm/glm.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<glm/gtc/type_ptr.hpp>const GLint WIDTH = 800, HEIGHT = 600;void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode);void MouseCallback(GLFWwindow* window, double xPos, double yPos);
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffset);
void DoMovement();GLfloat lastX = 0.0f;
GLfloat lastY = 0.0f;
bool firstMouse = true;bool keys[1024];Camera camera(glm::vec3(0.0f, 0.0f, 2.0f));
GLfloat deltaTime = 0.0f;
GLfloat lastTime = 0.0f;int main()
{glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);int screenWidth, screenHeight;glfwGetFramebufferSize(window, &screenWidth, &screenHeight);if (window == nullptr) {std::cout << "Failed to create GLFW window" <<std::endl;glfwTerminate();return  -1;}glfwMakeContextCurrent(window);glfwSetKeyCallback(window, KeyCallback);glfwSetCursorPosCallback(window, MouseCallback);glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);glfwSetScrollCallback(window,ScrollCallback);glewExperimental = GL_TRUE;if (glewInit() != GLEW_OK) {std::cout << "Failed to initialize GLEW" <<std::endl;glfwTerminate();return -1;}glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//允许深度测试glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);//深度信息小的覆盖信息大的Shader shader = Shader("res/shaders/core.vs","res/shaders/core.fs");Shader lightShader = Shader("res/shaders/light.vs", "res/shaders/light.fs");//CubeGLfloat vertices[] ={//position           //color//back-0.5,-0.5f,-0.5f,   1.0f,0.0f,0.0f,0.5f,-0.5f,-0.5f,   1.0f,0.0f,0.0f,0.5f,0.5f,-0.5f,    1.0f,0.0f,0.0f,0.5f,0.5f,-0.5f,    1.0f,0.0f,0.0f,-0.5f,0.5f,-0.5f,   1.0f,0.0f,0.0f,-0.5f,-0.5f,-0.5f,  1.0f,0.0f,0.0f,//front-0.5,-0.5f,0.5f,   0.0f,1.0f,0.0f,0.5f,-0.5f,0.5f,   0.0f,1.0f,0.0f,0.5f,0.5f,0.5f,    0.0f,1.0f,0.0f,0.5f,0.5f,0.5f,    0.0f,1.0f,0.0f,-0.5f,0.5f,0.5f,   0.0f,1.0f,0.0f,-0.5f,-0.5f,0.5f,  0.0f,1.0f,0.0f,//left-0.5f,0.5f,0.5f,    0.0f,0.0f,1.0f,-0.5f,0.5f,-0.5f,    0.0f,0.0f,1.0f,-0.5f,-0.5f,-0.5f,   0.0f,0.0f,1.0f,-0.5f,-0.5f,-0.5f,   0.0f,0.0f,1.0f,-0.5f,-0.5f,0.5f,    0.0f,0.0f,1.0f,-0.5f,0.5f,0.5f, 0.0f,0.0f,1.0f,//right0.5f,0.5f,0.5f,       0.0f,1.0f,1.0f,0.5f,0.5f,-0.5f, 0.0f,1.0f,1.0f,0.5f,-0.5f,-0.5f,    0.0f,1.0f,1.0f,0.5f,-0.5f,-0.5f,    0.0f,1.0f,1.0f,0.5f,-0.5f,0.5f, 0.0f,1.0f,1.0f,0.5f,0.5f,0.5f,      0.0f,1.0f,1.0f,//bottom-0.5f,-0.5f,-0.5f,   1.0f,0.0f,1.0f,0.5f,-0.5f,-0.5f,    1.0f,0.0f,1.0f,0.5f,-0.5f,0.5f, 1.0f,0.0f,1.0f,0.5f,-0.5f,0.5f, 1.0f,0.0f,1.0f,-0.5f,-0.5f,0.5f,    1.0f,0.0f,1.0f,-0.5f,-0.5f,-0.5f,   1.0f,0.0f,1.0f,//up-0.5f,0.5f,-0.5f,    1.0f,1.0f,0.0f,0.5f,0.5f,-0.5f, 1.0f,1.0f,0.0f,0.5f,0.5f,0.5f,      1.0f,1.0f,0.0f,0.5f,0.5f,0.5f,      1.0f,1.0f,0.0f,-0.5f,0.5f,0.5f, 1.0f,1.0f,0.0f,-0.5f,0.5f,-0.5f,    1.0f,1.0f,0.0f,};GLuint VAO, VBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);GLuint VAO1, VBO1;glGenVertexArrays(1, &VAO1);glGenBuffers(1, &VBO1);glBindVertexArray(VAO1);glBindBuffer(GL_ARRAY_BUFFER, VBO1);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);glBindVertexArray(0);while (!glfwWindowShouldClose(window)) {GLfloat currentTime = glfwGetTime();deltaTime = currentTime - lastTime;lastTime = currentTime;glViewport(0, 0, screenWidth, screenHeight);glfwPollEvents();DoMovement();//在PollEvents后响应glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//用到都要初始化shader.Use();glm::mat4 view = camera.GetViewMatrix();glm::mat4 projection = glm::perspective(glm::radians(camera.GetZoom()),static_cast<GLfloat>(screenWidth) / static_cast<GLfloat>(screenHeight), 0.1f, 100.0f);GLuint viewLoc = glGetUniformLocation(shader.Program, "view");glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));GLuint projectionLoc = glGetUniformLocation(shader.Program, "projection");glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));glm::mat4 transform = glm::mat4(1.0f);//平移transform = glm::translate(transform, glm::vec3(0.0f, 0.4f, 0.0f));//旋转transform = glm::rotate(transform, glm::radians(20.0f)*static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));//缩放transform = glm::scale(transform, glm::vec3(0.5f, 0.5f, 0.5f));GLuint transLoc = glGetUniformLocation(shader.Program, "transform");glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);lightShader.Use();viewLoc = glGetUniformLocation(lightShader.Program, "view");glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));projectionLoc = glGetUniformLocation(lightShader.Program, "projection");glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));transform = glm::mat4(1.0f);transform = glm::rotate(transform, glm::radians(20.0f) * static_cast<GLfloat>(glfwGetTime()), glm::vec3(1.0f, 1.0f, 1.0f));transform = glm::translate(transform, glm::vec3(0.0f, 2.0f, 0.0f));transform = glm::scale(transform, glm::vec3(0.1f, 0.1f, 0.1f));transLoc = glGetUniformLocation(lightShader.Program, "transform");glUniformMatrix4fv(transLoc, 1, GL_FALSE, glm::value_ptr(transform));glBindVertexArray(VAO1);glDrawArrays(GL_TRIANGLES, 0, 36);glBindVertexArray(0);glfwSwapBuffers(window);}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glfwTerminate();return 0;
}void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mode)
{if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE){glfwSetWindowShouldClose(window, GL_TRUE);}if (key >= 0 && key < 1024) {if (action == GLFW_PRESS) {keys[key] = true;}else if (action == GLFW_RELEASE){keys[key] = false;}}
}
void MouseCallback(GLFWwindow* window, double xPos, double yPos)
{if (firstMouse) {lastX = xPos;lastY = yPos;firstMouse = false;}GLfloat xOffset = xPos - lastX;GLfloat yOffset = lastY - yPos;lastX = xPos;lastY = yPos;camera.ProcessMouseMovement(xOffset, yOffset);
}
void DoMovement()
{if (keys[GLFW_KEY_W] || keys[GLFW_KEY_UP]) {//upcamera.ProcessKeyboard(FOWARD,deltaTime);}if (keys[GLFW_KEY_S] || keys[GLFW_KEY_DOWN]) {//downcamera.ProcessKeyboard(BACKWARD, deltaTime);}if (keys[GLFW_KEY_A] || keys[GLFW_KEY_LEFT]) {//leftcamera.ProcessKeyboard(LEFT, deltaTime);}if (keys[GLFW_KEY_D] || keys[GLFW_KEY_RIGHT]) {//rightcamera.ProcessKeyboard(RIGHT, deltaTime);}
}
void ScrollCallback(GLFWwindow* window, double xOffset, double yOffset)
{camera.ProcessScroll(yOffset);
}

运行结果

计算机图形学(七)——画一个可以由鼠标键盘控制的立方体相关推荐

  1. 图形学笔记(八)画一个可以由鼠标和键盘控制的立方体

    画完自己会动的立方体,下面画一个由鼠标和键盘控制的立方体. 一.代码 main.cpp #include <iostream>//GLEW #define GLEW_STATIC #inc ...

  2. 计算机图形学 顶点定义_在计算机图形学中定义一个圆

    计算机图形学 顶点定义 After studying the implementation of lines in computer graphics, we will now be dealing ...

  3. openGL绘制带纹理地球,并实现鼠标键盘控制

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.绘制球体 二.关键代码 球体类(Sphere) 主函数 顶点着色器 片元着色器 显示效果 源码下载 参考 前言 openGL绘制 ...

  4. Mouse Without Borders 一套鼠标键盘控制多台电脑

    当我的桌子上除了笔记本之外还多了一个台式机后,两个鼠标,两个键盘就显得十分多余,于是开始探索怎样用一套鼠标键盘控制多台电脑... 首先搜到的是这玩意--KVM切换器 在他49个赞的诱惑下,我还去淘宝搜 ...

  5. python热键+鼠标键盘控制

    python热键+鼠标键盘控制 应用:ctrl+home自动输入文本:home停止 代码:hotkey 应用:ctrl+home自动输入文本:home停止 代码:hotkey #!/usr/bin/e ...

  6. android 键盘使用教程,用鼠标键盘控制你的Android手机完整图文教程

    网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都可以的,下面给出我的步骤及过程中遇到的几个小问题,供大家参考! 一.鼠标键盘控制手机教程 1.在PC上,安装豌豆荚, ...

  7. android usb鼠标,用鼠标键盘控制你的Android手机完整图文教程

    网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都可以的,下面给出我的步骤及过程中遇到的几个小问题,供大家参考! 一.鼠标键盘控制手机教程 1.在PC上,安装豌豆荚, ...

  8. android键盘管理,用鼠标键盘控制你的Android手机完整图文教程

    32路伺服电机控制器V3.0 官方安装版 类型:编程辅助大小:15.0M语言:中文 评分:7.5 标签: 立即下载 网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都 ...

  9. 一套鼠标键盘控制两台电脑-绝!

    Oliver's R&D Lab C/C++/Linux 一套鼠标键盘控制两台电脑-绝! 这个工具是推荐给双电脑工作人员的,不是的就不用往下看了,嗯. synergy-----按照它主页( h ...

  10. android 方向键控制,如何用鼠标键盘控制你的Android手机

    如何用鼠标键盘控制你的Android手机 网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都可以的,下面给出我的步骤及过程中遇到的`几个小问题,供大家参考! 一.鼠标 ...

最新文章

  1. html 字母列表通讯录,仿微信通讯录字母排序列表
  2. 漫画 | 理解了TCP连接的实现以后,客户端的并发也爆发了!
  3. python画图简单代码-简单画图 - python代码库 - 云代码
  4. 深度学习卷积神经网络大事件一览
  5. 机房防雷接地的黄铜排(黄铜带)与紫铜排(紫铜带)的区别与应用
  6. XX System Test Plan
  7. LeetCode 332. 重新安排行程(欧拉路径)
  8. RNN调试错误:lstm_cell = tf.contrib.rnn.core_rnn_cell.BasicLSTMCell(lstm_size) 方法已失效
  9. 添加Expires头
  10. C语言之预处理探究(一):宏
  11. android触摸进度条,Android仿IOS ViewPager滑动进度条
  12. Python封装的获取文件目录的函数
  13. 程序安全性之配置文件安全
  14. JavaScript使用Modbus协议实现RTU设备连云
  15. VINS-Mono 代码解析——视觉跟踪 feature_trackers
  16. 磁盘被写保护,请去掉写保护或另一张磁盘
  17. 基于高德api的地区全类poi爬取
  18. BouncyCastle使用
  19. NYoj21 三个水杯
  20. 【学习总结】ctf隐写初阶解题思路与方法

热门文章

  1. Python画图之散点图(plt.scatter)
  2. 蓝牙音频传输格式:ACC,SBC,APTX和LDAC
  3. python安卓脚本精灵使用教程_【按键精灵教程】自动安装apk还可以这么用!
  4. Linux 备份与恢复
  5. U盘WPE安装原版Win7系统教程
  6. c语言程序设计第三版朱立华主编课后答案,C语言程序设计习题解析与实验指导...
  7. 程序设计与c语言区别,c语言程序设计和c程序设计有什么区别啊
  8. 史上最全SQL基础知识总结(理论+举例)
  9. 查看tftp服务器上有什么文件,linux查看tftp服务器配置
  10. poi mysql 导出 excel乱码,本地tomcat正常,但liunx poi excel下载却内容乱码问题的解决方法-学派吧...