摄像机/观察空间

程序执行效果

摄像机代码

// 摄像机
view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
ourShader.setMat4("view", view);

实际上就是得到一个View Matrix,这样就可以传送给shader program用于计算从本地坐标系向投影坐标系、剪裁坐标系进行转换。

glm::lookAt(eye, center, up)

eye实际上就是摄像机的位置
center就是摄像机的方向
up就是上轴

eye -> cameraPos
center -> cameraPos + cameraFront
up -> cameraUp

摄像机的位置很好理解,就是3D空间中的一个点P(Vector3{x, y, z})
那么方向的量就是A(Vector3{x, y, z})到B(Vector3{x, y, z})指向(tail, head指向) [下面的代码叫方向向量不恰当,因为是相反的]
我们将两个点的空间坐标通过向量的标准化求得方向(空间的点不是向量,和长度一样是标量):

1、cameraPos:
vec3(0.0, 0.0, 3.0);

2、cameraFront:
vec3(0.0, 0.0, -1.0); // z 轴相反的方向为摄像机向前

3、cameraPos - cameraFront:
v1 = vec3(x: 0.0, y: 0.0, z: 3.0) , v2 = vec3(x: 0.0, y: 0.0, z: -1.0)
(v1) + (-v2) = (0.0, 0.0, 3.0 + -0.0, -0.0, 1.0)
(0.0, 0.0, 4.0)
如果是相加的话:
cameraPos - cameraFront = (0.0, 0.0, 2.0)

4、cameraDirection = glm::normalize(cameraPos + cameraFront) // 也可以不用这样,直接将cameraPos + cameraFront作为方向
模等于0的向量成为0向量,模等于1的向量叫做单位向量。注意零向量的方向是任意的。由一个向量v求与它同方向的单位向量过程称为标准化(normalization),这个单位向量成为标准化向量(normalized vector)。
公式:
vector normalize = v|v| (v≠0)
carmeraDirection = (0.0, 0.0, 1.0)

5、cameraUp
右轴:
我们需要的另一个向量是一个右向量(Right Vector),它代表摄像机空间的x轴的正方向。为获取右向量我们需要先使用一个小技巧:先定义一个上向量(Up Vector)。接下来把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量(如果我们交换两个向量叉乘的顺序就会得到相反的指向x轴负方向的向量):
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
现在我们已经有了x轴向量和z轴向量,获取一个指向摄像机的正y轴向量就相对简单了:我们把右向量和方向向量进行叉乘:
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

cameraUp = cross(cameraDirection, cross(up, cameraDirection))

glm::cross是求向量的叉积(向量乘法的叉乘)的:

cameraUp = (0, 1, 0) // Y axis its Up axis

glm::vec3 Pos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 Target = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 Direction = glm::normalize(Pos - Target);
glm::vec3 Up = glm::vec3(0.0f, 1.0f, 0.0f);
glm::vec3 Right = glm::normalize(glm::cross(Up, Direction));
glm::vec3 CamUp = glm::cross(Direction, Right);

6、得到了摄像机的向量后,我们通过LookAt Matrix来求得View Matrix:

R -> Right Vector右向量
U -> Up 是上向量(Up axis)
D -> Direction 方向向量
P -> Camera Position 摄像机的位置(空间中的点坐标)
求出的矩阵就是我们需要的View Coordinate(Space)需要的View Matrix

摄像机的移动

FPS游戏中我们通常用WSAD,来控制前进、后退、左移、右移。
实际上是对摄像机的位置进行操作,上面提到的cameraPos。
移动设计到一个变量,就是速度(我们暂时没有使用物理公式求速度,这里属于均速位移)
front(position) = front(position) + speed * position

back(position) = back(position) - speed * position

left(position) = left(position) - normalize(cross(front, up)) * speed;

right(position) = right(position) + normalize(cross(front, up)) * speed;

代码如下:

GLfloat cameraSpeed = 2.5 * deltaTime;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)cameraPos += cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)cameraPos -= cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;

欧拉角与摄像机鼠标控制视野转动

欧拉角

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

关于俯仰、滚转、偏航,玩过模拟飞行的,例如DCS或则Falcon,Simulated flight X的肯定会了解这个,而上图也是用了一个纸飞机来展示,在模拟飞行中,实际上也是这样控制的,无非就是多了物理学应用,对空气动力学进行一定模拟实现。
而这里我们解决的是使用俯仰与偏航完成摄像机的视角控制(现在新的一些FPS游戏中也可以控制滚转来控制偏头射击(Q、E控制))。


如果我们把斜边边长定义为1,我们就能知道邻边的长度是cos x/h=cos x/1=cos x,它的对边是sin y/h=sin y/1=sin y。这样我们获得了能够得到x和y方向长度的通用公式,它们取决于所给的角度。我们使用它来计算方向向量的分量:

弧度转角度:角度 = 弧度 * (180.0 / PI)
角度转弧度:弧度 = 角度 * (PI / 180.0)
PI派约等于:3.14159265359

sin(pitch * PI / 180.0)
我们可以初始化pitch为0.0
转半圈会旋转360/2 = 180度,向右旋转1/5圈表示向右旋转360/5 = 72度。

代码如下:

direction.y = sin(glm::radians(pitch));

这里我们只更新了y值,仔细观察x和z分量也被影响了。从三角形中我们可以看到它们的值等于:

direction.x = cos(glm::radians(pitch));
direction.z = cos(glm::radians(pitch));

就像俯仰角的三角形一样,我们可以看到x分量取决于cos(yaw)的值,z值同样取决于偏航角的正弦值。把这个加到前面的值中,会得到基于俯仰角和偏航角的方向向量:

// 译注:direction代表摄像机的前轴(Front),这个前轴是上面图中第一个展示
direction.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw)); 第二个摄像机的方向向量是相反的
direction.y = sin(glm::radians(pitch));
direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));

全部代码

OpenGL LookAt、Camera摄像机相关推荐

  1. Unity3D基础知识之Camera摄像机及其属性

    Unity3D基础知识之摄像机Camera 一.简介 Camera:附加了摄像机Camera组件的游戏对象,向玩家捕获和显示世界的设备,同时在一个场景中摄像机的数量不限. 组件:Transform:变 ...

  2. Unity2019学习:常用功能--Camera摄像机

    Camera摄像机游戏对象是Unity场景中最重要的游戏对象.每个场景至少需要一个激活的Camera摄像机游戏对象,否则无法显示.玩家或者用户能看到的内容都是通过Camera摄像机游戏对象来展示的.添 ...

  3. Cocos 技术派 05 | Camera 摄像机详解

    往期技术派文章: 第01期<野蛮人大作战>从开发到上线 第02期 Cocos Creator 2.0 摄像机的灵活运用 第03期 插件推荐 CC_inspector + 第04期 实时竞技 ...

  4. 用于OpenGl的Camera类(QT实现的3D摄像机类)

    最近在搞QT上的OPENGL,有好多库都要自己写啊 哐哧哐哧写了一大顿,已经写好了,回过头来记录一下 这篇讲的时关于opengl自由摄像机的问题 写摄像机的思路是,写一个万能的摄像机基类,可以支持各种 ...

  5. opengl 教程(15) 摄像机控制(2)

    原帖地址:http://ogldev.atspace.co.uk/www/tutorial15/tutorial15.html 本篇教程中,我们将实现鼠标控制摄像机的方位.摄像机可以有多个自由度(所谓 ...

  6. OpenGL LookAt函数理解

    前言:记录OpenGL学习过程中的一些知识点,以个人理解为主. LookAt函数将顶点的世界空间坐标转换为观察空间坐标,实际上是以相机为原点重新定义的三维空间. glm::mat4 LookAt(gl ...

  7. Unity Camera摄像机组件

    Clear Flags:摄像机的背景模式 Skybox:天空盒(默认选项),屏幕空白处显示当前摄像机的天空盒,没有天空盒则会显示背景色 Solid Color:空白处显示默认设置的背景色 Depth ...

  8. unity摄影机depth模式_Unity3D Camera 摄像机属性详解

    unity3d 摄像机参数 1. Clear Flags: 清除标记.决定屏幕的哪部分将被清除.一般用户使用对台摄像机来 描绘不同游戏对象的情况,有 3 中模式选择: Skybox : 天空盒. 默认 ...

  9. 【Modern OpenGL】摄像机系统 Camera

    说明:跟着learnopengl的内容学习,不是纯翻译,只是自己整理记录.  强烈推荐原文,无论是内容还是排版. 原文链接  本文地址:http://blog.csdn.net/aganlengzi/ ...

最新文章

  1. 测试时代诚聘软件测试讲师,欢迎有志之士加入!!职位要求:
  2. SAP BW BEx工具集简单介绍【AV+PPT】
  3. 区块链分布式账本Hyperledger Fabric介绍
  4. nio java 内核拷贝_大文件拷贝,试试NIO的内存映射
  5. Python自学之乐-Python字典实现简单的三级菜单
  6. 自定义UISearchBar的背景图
  7. sql另一个安装程序实例已在运行_SQL 经典实例
  8. 两个人投票的c语言程序,设计网页投票器(二)《精通Unix下C语言编程与项目实践》之十...
  9. 网络编程demo之Udp和URL
  10. 最全银行IT核心系统:研究框架(165页)
  11. dedesmc 手机端生成静态页
  12. 如何判定括号是否匹配
  13. 群晖NAS设备安装和基础操作详细流程(例:DS920+)
  14. fgo升级经验计算机,命运冠位指定狗粮本每日经验表 fgo国服狗粮本刷取技巧攻略[多图]...
  15. OLED 屏幕的使用
  16. DOTA数据集介绍(论文A Large-scale Dataset for Object Detection in Aerial Images)
  17. flowable工作流架构介绍及集成实现
  18. NoSQL数据库与分布式缓存对比:同工异曲
  19. 堆和栈的区别 之 数据结构和内存
  20. Java_运动员和教练案例代码实现

热门文章

  1. IKBC键盘Win键失效的解决办法
  2. 82ip网 - 每日更新50万HTTP和HTTPS代理IP!
  3. iPhone忘记访问限制密码的解决方案
  4. 群晖download station中添加BT搜索引擎
  5. 股票量化分析工具QTYX使用攻略——北上资金持仓选股(更新2.5.8)
  6. filevault(电子仓库)自动切换文件夹以及文档最大值设置
  7. Mounty 1.10免费版(NTFS硬盘工具)支持big sur
  8. php框架laravel win10,composer 安装Laravel (win10)
  9. 学学拍照姿势!(别只懂得插裤袋,哈哈)
  10. 利用Java实现将华氏温度转换为摄氏温度