鼠标输入

一、隐藏并捕捉光标

偏航角和俯仰角是通过鼠标移动获得的,水平的移动影响偏航角,竖直的移动影响俯仰角。

原理是,存储上一帧鼠标的位置,在当前帧中计算鼠标位置与上一帧的位置相差多少。如果水平/竖直差别越大,那么俯仰角或偏航角就改变越大,也就是摄像机需要移动更多的距离。

首先我们应该告诉GLFW,它应该隐藏光标,并捕捉它。

结果:无论我们怎样移动鼠标,光标都不会显示,但它也不会离开窗口。

glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_DISABLED);

二:监听鼠标移动事件

为了计算俯仰角和偏航角,我们需要让GLFW监听鼠标移动事件(和键盘输入相似)。用一个回调函数来完成,函数原型如下:

void mouse_callback(GLFWwindow *window,double xpos,double ypos);

xpos,ypos代表当前鼠标的位置。当我们用GLFW注册了回调函数之后,鼠标一移动mouse_callback函数就会被调用:

1 glfwSetCursorCallback(window,mouse_callback);

三、在处理FPS风格摄像机的鼠标输入的时候,我们必须在最终获取方向向量之前做下面这几步

1、计算鼠标距上一帧的偏移量

2、把偏移量添加到摄像机的俯仰角和偏航角中

3、对俯仰角和偏航角进行最大和最小值的限制

4、计算方向向量

第一步:计算鼠标距上一帧的偏移量,所以必须在程序中存储上一帧的鼠标位置,我们把它的初始值设置为屏幕的中心

1 float lastX = screenWidth/2.0f;
2 float lastY = screenHeight/2.0f;

第二步:在鼠标的回调函数中计算当前帧和上一帧鼠标位置的偏移量:

1 float xoffest = xpos-lastX;
2 float yoffset = lastY - ypos;//注意这里是相反的,因为y坐标是从底部往顶部依次增大的
3 lastX = xpos;
4 lastY = ypos;
5 
6 float sensitivity = 0.05f;
7 xoffest *= sensitivity;
8 yoffest *= sensitivity;

注意我们把偏移量乘以了sensitivity(灵敏度)值。如果我们忽略这个值,鼠标移动就会太大了

俯仰角(Pitch)、偏航角(Yaw)

接下来我们把偏移量加到全局变量pitch和yaw上

1 yaw +=xoffset;
2 pitch +=yoffset;

第三步:给摄像机添加一些限制,这样摄像机就不会发生奇怪的移动了。对于俯仰角,要让用户不能看高于89度的地方(在90度是视角会发生逆转,所以我们把89度看成极限),同样也不允许-89度。

1 if(pitch>89.0f)
2     pitch = 89.0f;
3 if(pitch <-89.0f)
4     pitch = -89.0f;

注意到我们没有给偏航角设置限制,这是因为我们不希望限制用户的水平旋转。

第四步:通过俯仰角和偏航角来计算得到真正的方向向量:

1 glm::vec3 front;
2 front.x = cos(glm::radians(pith))*cos(glm::radians(yaw));
3 front.y = sin(glm::radians(pitch));
4 front.z = cos(glm::radians(pith))*cos(glm::radians(yaw));
5 cameraFront = glm::normolize(front);

计算出来的方向向量就会包含根据鼠标移动计算出来所有的旋转了。

我们可以简单的使用一个bool变量检验我们是否是第一次获取鼠标输入,如果是,那么我们先把鼠标的初始位置更新为xposypos值,这样就能解决这个问题;接下来的鼠标移动就会使用刚进入的鼠标位置坐标来计算偏移量了:

1 if(firstMouse)//这个bool变量初始时是设定为true的
2 {
3     lastX = xpos;
4     lastY = ypos;
5     firstMouse = false;   
6 }

最后的代码应该是这样的:

 1 void mouse_callback(GLFWwindow* window, double xpos, double ypos)
 2 {
 3     if(firstMouse)
 4     {
 5         lastX = xpos;
 6         lastY = ypos;
 7         firstMouse = false;
 8     }
 9 
10     float xoffset = xpos - lastX;
11     float yoffset = lastY - ypos; 
12     lastX = xpos;
13     lastY = ypos;
14 
15     float sensitivity = 0.05;
16     xoffset *= sensitivity;
17     yoffset *= sensitivity;
18 
19     yaw   += xoffset;
20     pitch += yoffset;
21 
22     if(pitch > 89.0f)
23         pitch = 89.0f;
24     if(pitch < -89.0f)
25         pitch = -89.0f;
26 
27     glm::vec3 front;
28     front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
29     front.y = sin(glm::radians(pitch));
30     front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
31     cameraFront = glm::normalize(front);
32 }

三、缩放

实现一个缩放(Zoom)接口。在之前的教程中我们说视野(Field of View)或fov定义了我们可以看到场景中多大的范围。当视野变小时,场景投影出来的空间就会减小,产生放大(Zoom In)了的感觉。我们会使用鼠标的滚轮来放大。与鼠标移动、键盘输入一样,我们需要一个鼠标滚轮的回调函数:

1 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
2 {
3   if(fov >= 1.0f && fov <= 45.0f)
4     fov -= yoffset;
5   if(fov <= 1.0f)
6     fov = 1.0f;
7   if(fov >= 45.0f)
8     fov = 45.0f;
9 }

当滚动鼠标滚轮的时候,yoffset值代表我们竖直滚动的大小。当scroll_callback函数被调用后,我们改变全局变量fov变量的内容。因为45.0f是默认的视野值,我们将会把缩放级别(Zoom Level)限制在1.0f45.0f

我们现在在每一帧都必须把透视投影矩阵上传到GPU,但现在使用fov变量作为它的视野:

projection = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);

最后不要忘记注册鼠标滚轮的回调函数:

glfwSetScrollCallback(window, scroll_callback);

 

转载于:https://www.cnblogs.com/keguniang/p/9949855.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276917.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c#用canny算子做边缘提取_机器视觉学习(三)边缘检测

一、边缘检测二、边缘检测流程三、Canny边缘检测前言边缘检测是图像处理和计算机视觉中&#xff0c;尤其是特征提取中的一个研究领域。有许多方法用于边缘检测&#xff0c;它们的绝大部分可以划分为两类&#xff1a;基于一阶导数首先计算边缘强度&#xff0c; 通常用一阶导数表…

一个有关Update类型的存储过程的问题

CREATE PROCEDURE testupdateproc AS declare id int declare trandate datetime declare tranlimit int update test set trandatetrandate, tranlimittranlimit where test.idid GO 存储过程语句如上&#xff0c;检查语法是没有问题的&#xff0c;但是在程序中执行时却不行…

[20190805]在小程序中使用npm包

小程序是可以使用npm包的 1. 初始化npm&#xff1b;&#xff08;在项目目录下输入&#xff09; npm init 此时项目文件夹会创建一个配置信息的package.json文件 2. 手动新建node_modules文件夹&#xff1b;&#xff08;在项目目录下新建&#xff09; 3. 安装npm包&#xff1b; …

bindresult必须在哪个位置_手机视频剪辑工具哪个好?清爽视频编辑APP有人推荐吗?...

作为一个非常喜欢旅游的人&#xff0c;每次出门在外都喜欢发各种照片&#xff0c;以前发照片觉得就能够表达自己的状态和心情&#xff0c;但是随着时间的变化发现&#xff0c;身边的人都开始喜欢发视频了。此前在飞机上拍摄了一段觉得不错的天空视频&#xff0c;想要制作成短片…

[转] 能ping通,但不能上网.

一、感染了病毒所致这种情况往往表现在打开IE时&#xff0c;在IE界面的左下框里提示&#xff1a;正在打开网页&#xff0c;但老半天没响应。在任务管理器里查看进程&#xff0c;&#xff08;进入方法&#xff0c;把鼠标放在任务栏上&#xff0c;按右键—任务管理器—进程&#…

Gradle打包命令记录

Gradle打包命令记录第一种方式&#xff1a;gradle build执行后在在build/lib下生成war包第二种方式&#xff1a;gradle cleangradle --refresh-dependencies assemble

浅谈ASP中Web页面间的数据传递

【简 介】  基于Web的动态网页设计必会涉及到页面间的数据传递&#xff0c;文章探讨了ASP设计中常用的Web页面间的数据传递方式&#xff0c;分析各种数据传递方式的使用方法、使用场合及优缺点&#xff0c;其都是设计阶段选择数据传递方式考虑的关键 往往使用动态网页技术制作…

变频电源出现故障了怎么办,该如何去诊断呢

在变频电源使用时间过长之后就会出现一些小故障&#xff0c;在出现这些小故障的时候很多人都不知道问题出在哪&#xff0c;今天中港扬盛的技术员教你如何的快速诊断变频电源的故障方法。只有及时的发现&#xff0c;这样就能够有效地去解决变频电源所出现的故障。下面就是变频电…

无法访问你试图使用的功能所在的网络位置_[steam实用工具]解决无法访问商店/社区/好友列表的问题...

[steam实用工具]解决无法访问商店/社区/好友列表的问题在我们使用steam的过程中&#xff0c;由于某些原因&#xff0c;在访问商店/社区/好友列表时会被受到限制。针对这种情况&#xff0c;国内的大神些开发出了以下工具来解决我们访问的难题。本文章中的软件由“羽翼诚"大…

tomcat6.0+mysql5.0+jdk5.0+myeclipse6.0打造JSP开发平台

1.下载tomcat6.0(http://tomcat.apache.org/download-60.cgi), mysql5.0(http://download.mysql.cn/src/2006/0710/5543.html), jdk5.0(http://download.mysql.cn/src/2006/0710/5543.html)以及myeclipse6.0(http://www.myeclipseide.com/module-htmlpages-display-pid-4.html)…

程序设计中的感悟

1. 学习应该从基础打起&#xff0c;不要一开始就尝试最高深的技术。 2. 每看一本书&#xff0c;不要说这章我以前学习过了&#xff0c;也掌握的很好&#xff0c;因此我可以跳过这一章看更重要的了。 3. 对于作业&#xff0c;遇到不会的尽量不要立刻向别人请教。如果实在解决…

(转)用Java获得当前性能信息

(转&#xff09;用Java获得当前性能信息 http://www.blogjava.net/amigoxie/archive/2008/04/30/197564.html在Java中&#xff0c;可以获得总的物理内存、剩余的物理内存、已使用的物理内存等信息&#xff0c;本例讲解如何取得这些信息&#xff0c;并且获得在Windows下的内存使…

docker wsl2启动不了_Docker学习笔记

在笔记本上主要还是想以轻量、方便为主&#xff0c;所以采用的是在WSL2中使用docker的这么一个方案。WSL2我笔记本原来是预装的是WIN10家庭版&#xff0c;需要先升级为专业版&#xff0c;并加入windows预览体验计划。更新完之后&#xff0c;安装WSL&#xff0c;我选择的是Ubunt…

暑假集训-8.06总结

学习内容&#xff1a; 搜索 今日完成题数&#xff08;不包含多校&#xff09;&#xff1a;4 今日看书情况&#xff1a;15页 今日心得&#xff1a; 今天学的是搜索&#xff0c;虽然以前学过&#xff0c;但书上讲的更具体些&#xff0c; 比如说如何去优化搜索的次数等 英语题目好…

网易马进:DDB从分布式数据库到结构化数据中心的架构变迁

导语&#xff1a; 本文根据马进老师在2018年5月10日【第九届中国数据库技术大会(DTCC)】现场演讲内容整理而成。马进 网易 DDB项目负责人来自网易杭研大数据平台组&#xff0c;入职以来先后参与了分布式数据库DDB&#xff0c;缓存NKV&#xff0c;网易数据运河NDC等项目&#xf…

element label动态赋值_浅析 vuerouter 源码和动态路由权限分配

背景上月立过一个 flag&#xff0c;看完 vue-router 的源码&#xff0c;可到后面逐渐发现 vue-router 的源码并不是像很多总结的文章那么容易理解&#xff0c;阅读过你就会发现里面的很多地方都会有多层的函数调用关系&#xff0c;还有大量的 this 指向问题&#xff0c;而且会有…

MessagePack Java 0.6.X List, Map 对象的序列化和反序列化

为了序列化原生的容器对象例如 List 和 Map 对象&#xff0c;你必须使用 Template。 Template 对象是 serializer 和 deserializer 的配对。例如&#xff0c;为了序列化一个 List 对象&#xff0c;在 List 对象中 Integer 对象为元素&#xff0c;你可以使用下面的方法来创建一…

世界领先的界面设计公司:The Skins Factory

该公司的网站&#xff1a; http://www.theskinsfactory.com/skinsfactory/ 该公司诞生于2000年&#xff0c;由一群狂热的界面爱好者&#xff0c;带着对GUI的热情和大胆的洞察力创立。很快&#xff0c;皮肤工厂便成长为世界领先的、真正的、革命性界面解决方案提供商。 更多的精…

HDU 1253 胜利大逃亡 题解

胜利大逃亡 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 44540 Accepted Submission(s): 15483 Problem DescriptionIgnatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡…

lstm需要优化的参数_使用PyTorch手写代码从头构建LSTM,更深入的理解其工作原理...

这是一个造轮子的过程&#xff0c;但是从头构建LSTM能够使我们对体系结构进行更加了解&#xff0c;并将我们的研究带入下一个层次。LSTM单元是递归神经网络深度学习研究领域中最有趣的结构之一&#xff1a;它不仅使模型能够从长序列中学习&#xff0c;而且还为长、短期记忆创建…