OpenGL - Coordinate Systems

从顶点坐标到我们最终看到的效果,中间要经历多个坐标系的转换:
在这里插入图片描述

对于我们来讲,只需要关注三个矩阵即可:Vclip=Mprojection⋅Mview⋅Mmodel⋅Vlocal

  • Mmodel:将局部坐标转为世界坐标的矩阵,注意此时的平移是以物体本身的坐标系为基准的
  • Mview:将世界坐标以摄像机的视角进行转换,比如向右平移,实际上视图会向左平移
  • Mprojection:对观察坐标进行投影

Camera/View space

通过view matrix,将世界坐标系相对摄像机的位置和方向进行转换,就可以得到view space。摄像机在世界坐标系的位置定义如下:
在这里插入图片描述
注意摄像机计算 Right 向量时采用的是右手系,如果 cross 相反时左右移动也会相反。

glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);  
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); 
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

有了位置信息之后,可以计算出LookAt matrix
在这里插入图片描述
利用glm可以更便捷的构造出该矩阵:

glm::mat4 view;
// Position Target Up
view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), 
  		   glm::vec3(0.0f, 0.0f, 0.0f), 
  		   glm::vec3(0.0f, 1.0f, 0.0f));

Walk around

移动视图其实是改变摄像机的位置,具体代码可以参照 -> 👉

Look around

Euler angles

在这里插入图片描述
俯仰角(pitch)是描述我们如何往上或往下看的角,可以在第一张图中看到。第二张图展示了偏航角(yaw),表示我们往左和往右看的程度。滚转角(roll)代表我们如何翻滚摄像机,通常在太空飞船的摄像机中使用。
鼠标左右移动改变了yaw,上下移动改变了pitch,变换的坐标可以计算为:

glm::vec3 direction;
// yaw 在xz平面, pitch 在yz平面
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
direction.y = sin(glm::radians(pitch));
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));

front向量就是摄像头看向的方向。这与现实中的摄像头的镜头相当,决定了摄像头的视线方向。

偏航角和俯仰角是用来控制视觉的方向的。偏航角决定了摄像机向左或向右转,就像控制方向盘一样;俯仰角决定了摄像机向上或向下旋转。

使用三角函数cossin将这两个角度转换为一个三维向量,这就是所说的计算出的坐标向量。这个向量指向的方向就是摄像头的前方。

摄像机的 viewMatrix 也可以用(float4x4(translation: target) * float4x4(rotationYXZ: rotation)).inverse

为了理解为什么视图矩阵是这样计算的,我们首先需要理解在3D中,摄像机其实并没有移动和旋转:世界中所有的物体都围绕摄像机旋转和移动,而摄像机总是在坐标原点并朝向-z方向。也就是说,所有的物体都要应用一个变换,这个变换产生的效果看起来就像是摄像机在移动和旋转。

假设我们将摄像机放在世界坐标中的target位置,并绕Y轴X轴rotation旋转,那么物体要经历的变换就是先绕Y轴X轴旋转-rotation,然后在世界中平移-target。在矩阵变换中,我们要做的是将摄像机的旋转作用在物体上,然后将摄像机的平移作用在物体上,这就需要首先用rotation计算旋转矩阵,然后用target计算平移矩阵,最后得到的矩阵其实就是物体需要的变换。

然而,在3D中,我们通常对物体应用的变换都是模型矩阵,视图矩阵,以及透视矩阵。为了遵循这个习惯,我们需要做的就是求出float4x4(translation: target) * float4x4(rotationYXZ: rotation)的逆矩阵,这个逆矩阵就是视图矩阵。

Zoom

进行透射投影即可起到放大缩小的效果,具体代码可以参照 -> 👉

Camera Class

方便使用,我们可以把摄像机的功能封装起来 -> 👉 ,使用方法 -> 👉

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值