计算机图形学(七)——画一个可以由鼠标键盘控制的立方体
画一个可以由鼠标键盘控制的立方体
本节将会再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);
}
运行结果
计算机图形学(七)——画一个可以由鼠标键盘控制的立方体相关推荐
- 图形学笔记(八)画一个可以由鼠标和键盘控制的立方体
画完自己会动的立方体,下面画一个由鼠标和键盘控制的立方体. 一.代码 main.cpp #include <iostream>//GLEW #define GLEW_STATIC #inc ...
- 计算机图形学 顶点定义_在计算机图形学中定义一个圆
计算机图形学 顶点定义 After studying the implementation of lines in computer graphics, we will now be dealing ...
- openGL绘制带纹理地球,并实现鼠标键盘控制
openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.绘制球体 二.关键代码 球体类(Sphere) 主函数 顶点着色器 片元着色器 显示效果 源码下载 参考 前言 openGL绘制 ...
- Mouse Without Borders 一套鼠标键盘控制多台电脑
当我的桌子上除了笔记本之外还多了一个台式机后,两个鼠标,两个键盘就显得十分多余,于是开始探索怎样用一套鼠标键盘控制多台电脑... 首先搜到的是这玩意--KVM切换器 在他49个赞的诱惑下,我还去淘宝搜 ...
- python热键+鼠标键盘控制
python热键+鼠标键盘控制 应用:ctrl+home自动输入文本:home停止 代码:hotkey 应用:ctrl+home自动输入文本:home停止 代码:hotkey #!/usr/bin/e ...
- android 键盘使用教程,用鼠标键盘控制你的Android手机完整图文教程
网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都可以的,下面给出我的步骤及过程中遇到的几个小问题,供大家参考! 一.鼠标键盘控制手机教程 1.在PC上,安装豌豆荚, ...
- android usb鼠标,用鼠标键盘控制你的Android手机完整图文教程
网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都可以的,下面给出我的步骤及过程中遇到的几个小问题,供大家参考! 一.鼠标键盘控制手机教程 1.在PC上,安装豌豆荚, ...
- android键盘管理,用鼠标键盘控制你的Android手机完整图文教程
32路伺服电机控制器V3.0 官方安装版 类型:编程辅助大小:15.0M语言:中文 评分:7.5 标签: 立即下载 网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都 ...
- 一套鼠标键盘控制两台电脑-绝!
Oliver's R&D Lab C/C++/Linux 一套鼠标键盘控制两台电脑-绝! 这个工具是推荐给双电脑工作人员的,不是的就不用往下看了,嗯. synergy-----按照它主页( h ...
- android 方向键控制,如何用鼠标键盘控制你的Android手机
如何用鼠标键盘控制你的Android手机 网上大都是91助手for android来连接手机和电脑,我自己比较偏向于豌豆荚,都可以的,下面给出我的步骤及过程中遇到的`几个小问题,供大家参考! 一.鼠标 ...
最新文章
- html 字母列表通讯录,仿微信通讯录字母排序列表
- 漫画 | 理解了TCP连接的实现以后,客户端的并发也爆发了!
- python画图简单代码-简单画图 - python代码库 - 云代码
- 深度学习卷积神经网络大事件一览
- 机房防雷接地的黄铜排(黄铜带)与紫铜排(紫铜带)的区别与应用
- XX System Test Plan
- LeetCode 332. 重新安排行程(欧拉路径)
- RNN调试错误:lstm_cell = tf.contrib.rnn.core_rnn_cell.BasicLSTMCell(lstm_size) 方法已失效
- 添加Expires头
- C语言之预处理探究(一):宏
- android触摸进度条,Android仿IOS ViewPager滑动进度条
- Python封装的获取文件目录的函数
- 程序安全性之配置文件安全
- JavaScript使用Modbus协议实现RTU设备连云
- VINS-Mono 代码解析——视觉跟踪 feature_trackers
- 磁盘被写保护,请去掉写保护或另一张磁盘
- 基于高德api的地区全类poi爬取
- BouncyCastle使用
- NYoj21 三个水杯
- 【学习总结】ctf隐写初阶解题思路与方法
热门文章
- Python画图之散点图(plt.scatter)
- 蓝牙音频传输格式:ACC,SBC,APTX和LDAC
- python安卓脚本精灵使用教程_【按键精灵教程】自动安装apk还可以这么用!
- Linux 备份与恢复
- U盘WPE安装原版Win7系统教程
- c语言程序设计第三版朱立华主编课后答案,C语言程序设计习题解析与实验指导...
- 程序设计与c语言区别,c语言程序设计和c程序设计有什么区别啊
- 史上最全SQL基础知识总结(理论+举例)
- 查看tftp服务器上有什么文件,linux查看tftp服务器配置
- poi mysql 导出 excel乱码,本地tomcat正常,但liunx poi excel下载却内容乱码问题的解决方法-学派吧...