键盘wsad控制相机位移,鼠标左键按下控制相机旋转
效果如下
代码如下
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <sstream>
  6. #include <GL/glew.h>
  7. #include <GL/freeglut.h>
  8. #include <glm/glm.hpp>
  9. #include <glm/gtc/matrix_transform.hpp>
  10.  
  11. using namespace std;
  12. using namespace glm;
  13.  
  14. const char* vsShaderName = "shader.vs";//顶点着色器
  15. const char* fsShaderName = "shader.fs";//片元着色器
  16.  
  17. GLuint VBO;//顶点缓冲对象
  18. GLuint IBO;//索引缓冲对象
  19. static GLfloat *vertices;//顶点数组
  20. static unsigned int *indices; //索引数组
  21. GLuint ShaderProgram;
  22. GLuint MatrixID;
  23. int windowWidth = 800;
  24. int windowHeight = 800;
  25. //相机参数
  26. glm::mat4 ViewMatrix;//视图矩阵
  27. glm::mat4 ProjectionMatrix; //投影矩阵
  28. glm::mat4 MVP;//模型视图矩阵
  29. glm::mat4 ModelMatrix;//模型矩阵
  30. glm::vec3 position = glm::vec3(5, 5, 5); //相机位置
  31. float horizontalAngle = 3.14f;
  32. float verticalAngle = 0.0f;
  33. float initialFoV = 45.0f; //相机视场角
  34. float speed = 0.05f; //平移速度
  35. float mouseSpeed = 0.005f;
  36. int mouseX, mouseY;//鼠标位置 窗口坐标
  37. bool mouseLeftDown=false;//鼠标左键按下
  38.  
  39. // 传递键盘事件
  40. static void SpecialKeyboardCB(unsigned char Key, int x, int y)
  41. {
  42. glm::vec3 direction(
  43. cos(verticalAngle) * sin(horizontalAngle),
  44. sin(verticalAngle),
  45. cos(verticalAngle) * cos(horizontalAngle)
  46. );
  47. glm::vec3 right = glm::vec3(
  48. sin(horizontalAngle - 3.14f / 2.0f),
  49. 0,
  50. cos(horizontalAngle - 3.14f / 2.0f)
  51. );
  52. glm::vec3 up = glm::cross(right, direction);
  53.  
  54. switch (Key) {
  55. case 'w':
  56. position += direction * speed;
  57. //fprintf(stderr, "up \n");
  58. break;
  59. case 'd':
  60. position += right * speed;
  61. //fprintf(stderr, "right \n");
  62. break;
  63. case 's':
  64. position -= direction * speed;
  65. //fprintf(stderr, "down \n");
  66. break;
  67. case 'a':
  68. position -= right * speed;
  69. //fprintf(stderr, "left \n");
  70. break;
  71. case 27:
  72. exit(1);
  73. break;
  74. default:
  75. break;
  76. //fprintf(stderr, "Unimplemented GLUT key\n");
  77. //exit(1);
  78. }
  79.  
  80. float FoV = initialFoV;
  81. ProjectionMatrix = glm::perspective(glm::radians(FoV), (float)windowWidth /(float) windowHeight, 0.1f, 100.0f);
  82. ViewMatrix = glm::lookAt(
  83. position,
  84. position + direction,
  85. up
  86. );
  87. ModelMatrix = glm::mat4(1.0);
  88. MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
  89. glutPostRedisplay();//设置窗口重绘
  90. }
  91.  
  92. //传递鼠标事件
  93. void mouseCB(int button, int state, int x, int y)
  94. {
  95. if (button == GLUT_LEFT_BUTTON)
  96. {
  97. if (state == GLUT_DOWN)
  98. {
  99. mouseLeftDown = true;
  100. mouseX = x;
  101. mouseY = y;
  102. }
  103. else if (state == GLUT_UP)
  104. {
  105. mouseLeftDown = false;
  106. }
  107. }
  108. }
  109.  
  110. //传递鼠标位置
  111. static void mouseMotionCB(int x, int y)
  112. {
  113. if (mouseLeftDown == true)
  114. {
  115. horizontalAngle += mouseSpeed * float(x - mouseX);
  116. verticalAngle += mouseSpeed * float(y - mouseY);
  117. mouseX = x;
  118. mouseY = y;
  119. SpecialKeyboardCB(0, 0, 0);
  120. }
  121. }
  122.  
  123. //渲染回调函数
  124. void RenderScenceCB() {
  125. // 清空颜色缓存
  126. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  127. glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
  128. glEnableVertexAttribArray(0);
  129. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  130. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
  131. glDrawArrays(GL_LINES, 0, 40*4);
  132. glDisableVertexAttribArray(0);
  133. //交换前后缓存
  134. glutSwapBuffers();
  135. }
  136.  
  137. //创建顶点
  138. static void CreateVertexBuffer()
  139. {
  140. vertices = new GLfloat[40*3];
  141. for (size_t i = 0; i < 10; i++)
  142. {
  143. vertices[i * 12] = 0;
  144. vertices[i * 12 + 1] = 0;
  145. vertices[i * 12 + 2] = i;
  146.  
  147. vertices[i * 12 + 3] = 9;
  148. vertices[i * 12 + 4] = 0;
  149. vertices[i * 12 + 5] = i;
  150.  
  151. vertices[i * 12 + 6] = i;
  152. vertices[i * 12 + 7] = 0;
  153. vertices[i * 12 + 8] = 0;
  154.  
  155. vertices[i * 12 + 9] = i;
  156. vertices[i * 12 + 10] = 0;
  157. vertices[i * 12 + 11] = 9;
  158. }
  159. glGenBuffers(1, &VBO);
  160. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  161. glBufferData(GL_ARRAY_BUFFER, 40*3* sizeof(GLfloat), vertices, GL_STATIC_DRAW);
  162. }
  163.  
  164. static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
  165. {
  166. // 根据shader类型参数定义两个shader对象
  167. GLuint ShaderObj = glCreateShader(ShaderType);
  168. // 检查是否定义成功
  169. if (ShaderObj == 0) {
  170. fprintf(stderr, "Error creating shader type %d\n", ShaderType);
  171. exit(0);
  172. }
  173. // 定义shader的代码源
  174. const GLchar* p[1];
  175. p[0] = pShaderText;
  176. GLint Lengths[1];
  177. Lengths[0] = strlen(pShaderText);
  178. glShaderSource(ShaderObj, 1, p, Lengths);
  179. glCompileShader(ShaderObj);// 编译shader对象
  180. // 检查和shader相关的错误
  181. GLint success;
  182. glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
  183. if (!success) {
  184. GLchar InfoLog[1024];
  185. glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
  186. fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
  187. exit(1);
  188. }
  189. // 将编译好的shader对象绑定到program object程序对象上
  190. glAttachShader(ShaderProgram, ShaderObj);
  191. }
  192.  
  193. // 编译着色器函数
  194. static void CompileShaders()
  195. {
  196. // 创建着色器程序
  197. ShaderProgram = glCreateProgram();
  198. // 检查是否创建成功
  199. if (ShaderProgram == 0) {
  200. fprintf(stderr, "Error creating shader program\n");
  201. exit(1);
  202. }
  203. // 存储着色器文本的字符串
  204. string vs, fs;
  205. // 分别读取着色器文件中的文本到字符串
  206. std::ifstream VertexShaderStream(vsShaderName, std::ios::in);
  207. if (VertexShaderStream.is_open()) {
  208. std::stringstream sstr;
  209. sstr << VertexShaderStream.rdbuf();
  210. vs = sstr.str();
  211. VertexShaderStream.close();
  212. }
  213. else {
  214. printf("Error to open %s\n", vsShaderName);
  215. getchar();
  216. exit(0);
  217. }
  218. std::ifstream FragmentShaderStream(fsShaderName, std::ios::in);
  219. if (FragmentShaderStream.is_open()) {
  220. std::stringstream sstr;
  221. sstr << FragmentShaderStream.rdbuf();
  222. fs = sstr.str();
  223. FragmentShaderStream.close();
  224. }
  225.  
  226. // 添加顶点着色器和片段着色器
  227. AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
  228. AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
  229. // 链接shader着色器程序,并检查程序相关错误
  230. GLint Success = 0;
  231. GLchar ErrorLog[1024] = { 0 };
  232. glLinkProgram(ShaderProgram);
  233. glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
  234. if (Success == 0) {
  235. glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
  236. fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
  237. exit(1);
  238. }
  239. // 检查验证在当前的管线状态程序是否可以被执行
  240. glValidateProgram(ShaderProgram);
  241. glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
  242. if (!Success) {
  243. glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
  244. fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
  245. exit(1);
  246. }
  247. // 设置到管线声明中来使用上面成功建立的shader程序
  248. glUseProgram(ShaderProgram);
  249. MatrixID = glGetUniformLocation(ShaderProgram, "gWVP");
  250. }
  251.  
  252. int main(int argc, char ** argv) {
  253. // 初始化GLUT
  254. glutInit(&argc, argv);
  255. // 显示模式:双缓冲、RGBA
  256. glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
  257. glutInitWindowSize(windowWidth, windowHeight);
  258. glutInitWindowPosition(100, 100);
  259. glutCreateWindow("CameraTest");
  260. GLenum res = glewInit();
  261. if (res != GLEW_OK) {
  262. fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
  263. return 1;
  264. }
  265. // 开始渲染
  266. glutDisplayFunc(RenderScenceCB);
  267. // 注册键盘事件
  268. glutKeyboardFunc(SpecialKeyboardCB);
  269. //注册鼠标事件
  270. glutMouseFunc(mouseCB);
  271. glutMotionFunc(mouseMotionCB);
  272. mouseX = windowWidth / 2;
  273. mouseY = windowHeight / 2;
  274. // 缓存清空后的颜色值
  275. glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  276. //创建顶点
  277. CreateVertexBuffer();
  278. // 编译着色器
  279. CompileShaders();
  280. //开启深度测试
  281. glEnable(GL_DEPTH_TEST);
  282. // 通知开始GLUT的内部循环
  283. glutMainLoop();
  284. delete vertices;
  285. return 0;
  286. }
  1. #version 330
  2. layout (location = 0) in vec3 Position;
  3. uniform mat4 gWVP;
  4. out vec3 Color;
  5. void main()
  6. {
  7. gl_Position = gWVP * vec4(Position, 1.0);
  8. Color = Position/10;
  9. }
  1. #version 330
  2. out vec3 FragColor;
  3. in vec3 Color;
  4. void main()
  5. {
  6. FragColor = Color;
  7. }

本文链接https://www.cnblogs.com/gucheng/p/10139299.html

opengl鼠标键盘控制相机漫游的更多相关文章

  1. 【Unity3D】使用鼠标键盘控制Camera视角(即时战略类游戏视角):缩近,拉远,旋转

    今天写一个demo,要用到鼠标键盘控制三维视角,因此写了个脚本用于控制. 该脚本可以用于即时战略类游戏的视角,提供了缩进,拉伸,旋转.同时按住鼠标右键不放,移动鼠标可以实现第一人称视角的效果. usi ...

  2. C#模拟鼠标键盘控制其他窗口(一)

    编写程序模拟鼠标和键盘操作可以方便的实现你需要的功能,而不需要对方程序为你开放接口.比如,操作飞信定时发送短信等.我之前开发过飞信耗子,用的是对飞信协议进行抓包,然后分析协议,进而模拟协议的执行,开发 ...

  3. synergy一个鼠标键盘控制多台电脑

    有些时候我们同时操作多台电脑,但是我们只用一个鼠标和一个键盘,如果通过转换器啊或者是多个鼠标键盘就非常不方便了 下面我介绍一下通过安装synergy这个软件来给开发人员提供方便 这个软件安装比较简单, ...

  4. 一个鼠标键盘控制两台甚至多台主机的方法--Synergy

    在多台主机,不同系统中操作.避免了更换键鼠的麻烦.即使下面图中的功能. 鼠标同时在三台或者多台主机之间进行移动,而且是无缝滑动,鼠标直接从左滑倒右,而且支持,这台电脑复制,另一台黏贴.非常的方便实用. ...

  5. 用鼠标键盘来控制你的Android手机——同屏显示简单教程

    今天在微博上看到有人用电脑鼠标操作iPhone手机玩打飞机游戏,非常炫,虽然自己用的不是iPhone,但相信Android手机肯定也能实现这样的功能,于是网上各种搜索方法,终于看到了一篇试用成功的帖子 ...

  6. 【198】Synergy - 鼠标键盘共享软件

    参考:Synergy X64 v1.7.4 官方最新版 参考:Synergy安装方法 功能介绍: 可以将配置局域网的电脑实现同一个鼠标键盘控制两台电脑,效果类似一台电脑使用双屏的效果,键盘会根据鼠标的 ...

  7. 关于MFC与OpenGL结合绘图区域用鼠标来控制图形的移动的坑

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11773171.html 之前开发的导入多个模型,旋转,分别移动什么什么的,都是在纯OpenGL ...

  8. 用代码控制鼠标键盘(C#语言)

    前些时间想做一个鼠标点击器,用到了这些知识. 下面整理记录一下. ps.感谢各位大神 下面直接上代码 1.鼠标的控制 class MouseMove { #region MouseEvent [Sys ...

  9. OpenGL之路(八)加入�光照效果和键盘控制

    在opengl中加入�光照的效果,可用键盘控制放大缩小 w键放大 s键缩小 d键开关灯 预览效果例如以下: 源代码例如以下: #include <gl/glut.h> #include & ...

随机推荐

  1. Css案例整理

    1.实现两个div并排显示 案例:checkbox的标题和内容需要并排显示,checkbox竖向排列 <head> <style type="text/css"& ...

  2. 关于静态资源放在CDN上

    https://www.netlify.com/ https://app.netlify.com/signup?_ga=2.194141613.1097457726.1543799087-101005 ...

  3. 基于SSM框架的通用权限框架设计

     1. 整体解决方案概述    1.1 权限整体解决方案概述     权限设计主要有一下几大部分组成:     PassPort:    针对现在系统的分析,系统之间有部分信息是共享的,这部分信息将由 ...

  4. BZOJ 4013/Luogu P3240 [HNOI2015] 实验比较 (树形DP)

    题目传送门 分析 放一个dalao博客: xyz32768 的博客,看完再回来看本蒟蒻的口胡吧(其实嘛-不回来也行) 精髓是合并的方案数的计算,至于为什么是Ci−1j−1\large C_{i-1}^ ...

  5. tap 事件会触发两次问题

    因项目中使用 coffeeScript (http://coffee-script.org/),此处记录下用 coffeeScript 语法解决 tap 事件触发两次的问题. 在 id="b ...

  6. 定时器TIM,pwm

    一.定时器 1.     定义 设置等待时间,到达后则执行指定操作的硬件. 2.    STM32F407的定时器有以下特征 具有基本的定时功能,也有PWM输出(灯光控制.电机的转速).脉冲捕获功能( ...

  7. 51nod 1051

    * 最大子矩阵 * sum[i][j] 表示第 i 行前 j 列的和,即每一行的前缀 * i,j 指针枚举列,k指针枚举行 * Now 记录当前枚举的子矩阵的价值 * 由于记录了前缀信息,一旦 Now ...

  8. 关于openstack 网络相关的文章收集

    journalctl工具基础介绍(你需要这个的.) https://blog.51cto.com/13598893/2072212 新版devstack使用systemd的方式来管理OpenStack ...

  9. 如何更改电脑ip

    首先打开控制面板==>点击网络和internet==>点击网络和共享中心==>点击更改适配器设置==>右键无线连接或宽带连接(视情况而定)==>属性==>双击ipv ...

  10. codeforces gym #101161F-Dictionary Game(字典树+树上删边游戏)

    题目链接: http://codeforces.com/gym/101161/attachments 题意: 给一个可以变化的字典树 在字典树上删边 如果某条边和根节点不连通那么这条边也删除 谁没得删 ...