第五章 opengl之摄像机

摄像机

OpenGL本身没有摄像机(Camera)的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动。

摄像机/观察空间

  1. 首先获取摄像机位置,就是世界空间中的一个指向摄像机位置的向量。
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
  1. 摄像机方向
    指的是摄像机指向的方向。假如让摄像机指向原点,则用原点向量减去摄像机位置向量,能得到摄像机的指向向量。则可以得到摄像机指向z轴负方向,可以通过交换相减的顺序,得到一个指向摄像机正z轴的方向向量:
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);
  1. 右轴
    需要另一个向量叫做右向量,代码摄像机空间的x轴的正方形。
    首先需要先定义一个上向量,把上向量和第二步得到的方向向量进行叉乘,可以得到一个同时垂直于两向量的一个向量。则可以得到指向x轴正方向的那个向量:
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); 
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));
  1. 上轴
    当前已经有了x和z轴向量,获取一个指向摄像机的正y轴向量即可。
    把右向量和方向向量进行叉乘:
glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

使用这些摄像机向量我们就可以创建一个LookAt矩阵了,它在创建摄像机的时候非常有用。

Look At矩阵

使用矩阵的优点之一是:因为使用了3个相互垂直的轴定义了一个坐标空间。可以用这3个轴外加一个平移向量来创建一个矩阵,可以用这个矩阵乘以任何向量将其变换到那个坐标空间。上述是LookAt的作用。

现在可以通过上面的三个相互垂直的轴,外加一个定义摄像机空间的位置坐标,就可以创建LookAt矩阵:
GLM提供支持,我们只需要定义一个摄像机位置,一个目标位置,一个表示世界空间中的上向量的向量(就说算右向量使用的那个上向量)

glm::mat4 view;
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));

glm::LookAt函数需要一个位置、目标和上向量。它会创建一个和在上一节使用的一样的观察矩阵。

举例:让摄像机在场景中旋转,把摄像机的注视点始终保持在(0,0,0)
需要为旋转的那个圆圈,中每一点都创建一个x和z坐标,代表圆圈上的一点,不动y轴。通过重新计算x和z坐标,会遍历圆圈上的所有点。

假设这个圆圈的半径是radius,每次渲染迭代中使用GLFW的glfwGetTime函数重新创建观察矩阵,来扩大这个圆:

float radius = 10.0f;
float camX = sin(glfwGetTime()) * radius;
float camZ = cos(glfwGetTime()) * radius;
glm::mat4 view;
view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0)); 

自由移动

实现摄像机的主动且自由的移动。需要设置一个摄像机的系统
先定义摄像机变量:

glm::vec3 cameraPos   = glm::vec3(0.0f, 0.0f,  3.0f);
glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 cameraUp    = glm::vec3(0.0f, 1.0f,  0.0f);

LookAt函数如下:

view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);

我们首先将摄像机位置设置为之前定义的cameraPos。方向是当前的位置加上我们刚刚定义的方向向量。这样能保证无论我们怎么移动,摄像机都会注视着目标方向。让我们摆弄一下这些向量,在按下某些按钮时更新cameraPos向量。
我们已经为GLFW的键盘输入定义过一个processInput函数了,我们来新添加几个需要检查的按键命令:

void processInput(GLFWwindow *window)
{
   
    ...
    float cameraSpeed = 0.05f; // adjust accordingly
    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
        cameraPos += cameraSpeed * cameraFront;
    if (glfwGetKey
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值