• OpenGL系列(六)摄像机


        在 OpenGL系列(六)变换 中,一个目标物体经过模型矩阵、观察矩阵和投影矩阵的变换才能正常显示出来,其中模型矩阵主要针对目标物体,它会影响物体的位姿。观察矩阵和投影矩阵主要针对观察者而已,这两个变换决定了观察者以怎样的视角观察世界,可以把观察者比作一台摄像机,摄像机拍摄景象的角度由观察矩阵和投影矩阵决定。

        在本例中要实现摄像机类Camera,该类主要向外提供观察矩阵和投影矩阵,类定义如下。

    1. class Camera {
    2. public:
    3. Camera();
    4. virtual ~Camera();
    5. glm::mat4 getViewMatrix();
    6. virtual glm::mat4 getProjectionMatrix();
    7. private:
    8. glm::vec3 mPosition = glm::vec3(0.0f,0.0f,1.0f);
    9. glm::vec3 mUp = glm::vec3(0.0f,1.0f,0.0f);
    10. glm::vec3 mRight = glm::vec3(1.0f,0.0f,0.0f);
    11. };

       在Camera类主要成员如下。

    1. mPosition表示摄像机的位置。
    2. mUp表示摄像机上方的方向。
    3. mRight表示摄像机右边的方向。
    4. getViewMatrix返回观察矩阵。
    5. getProjectionMatrix返回投影矩阵。

    投影矩阵有两种,一种是正交投影矩阵,一种是透视投影,因此可以从Camera派生出两个子类,一个是OrthographicCamera表示正交投影摄像机,一个是PerspectiveCamera表示透视投影摄像机。

    正交投影摄像机类为OrthographicCamera,定义如下。

    1. class OrthographicCamera: public Camera{
    2. public:
    3. OrthographicCamera(float left,
    4. float right,
    5. float top,
    6. float bottom,
    7. float near,
    8. float far);
    9. ~OrthographicCamera();
    10. glm::mat4 getProjectionMatrix() override;
    11. private:
    12. float mLeft{0.0f};
    13. float mRight{0.0f};
    14. float mTop{0.0f};
    15. float mBottom{0.0f};
    16. float mNear{0.0f};
    17. float mFar{0.0f};
    18. };

    OrthographicCamera主要成员解析如下。

    mLeft、mRight、mTop、mBottom、mNear、mFar分别表示裁剪空间的左、右、上、下、近、远。

    getProjectionMatrix重新了父类的方法,返回正交投影摄像机的投影矩阵。

    透视投影摄像机类为PerspectiveCamera,定义如下。

    1. class PerspectiveCamera: public Camera{
    2. public:
    3. PerspectiveCamera(float fovy, float aspect, float near, float far);
    4. ~PerspectiveCamera();
    5. glm::mat4 getProjectionMatrix() override;
    6. private:
    7. float mFovy{0.0f};
    8. float mAspect{0.0f};
    9. float mNear{0.0f};
    10. float mFar{0.0f};
    11. };

    PerspectiveCamera主要成员解析如下。

    1. mFovy表示视张角
    2. mAspect表示宽高比
    3. mNear表示近裁剪面
    4. mFar表示远裁剪面。

    类定义完后,接下来实现返回观察矩阵和投影矩阵。

    观察矩阵的计算方法如下。

    1. glm::mat4 Camera::getViewMatrix(){
    2. glm::vec3 front = glm::cross(mUp,mRight);
    3. glm::vec3 center = mPosition + front;
    4. return glm::lookAt(mPosition,center,mUp);
    5. }

        观察矩阵的计算步骤如下。

    1. 对mUp和mRight进行叉乘得到向前的向量
    2. 当前位置加上向前向量得到观察的中心点,只要沿着该向量向前任何一个点都可以作为观察中心点。
    3. 通过lookAt返回观察矩阵,第1个参数是摄像机的位置,第2个参数是观察中心点,第3个参数是摄像机向上的向量

       正交投影摄像机和透视投影摄像机的观察矩阵是一样的,所以放到父类Camera实现,但是投影矩阵就有差异,所以放到各自子类实现。

        正交投影摄像机的投影矩阵实现如下。

    1. glm::mat4 OrthographicCamera::getProjectionMatrix() {
    2. return glm::ortho(mLeft,mRight,mBottom,mTop,mNear,mFar);
    3. }

        调用glm的ortho即可返回正交投影矩阵。

        透视投影摄像机的投影矩阵实现如下。

    1. glm::mat4 PerspectiveCamera::getProjectionMatrix() {
    2. return glm::perspective(glm::radians(mFovy),mAspect,mNear,mFar);
    3. }

        调用glm的perspective可返回投影投影矩阵。

    该示例的工程已经上传到,地址如下

    示例工程代码

       在开发过程中,首先要确定射线机的类型,以确定是创建OrthographicCamera对象还是PerspectiveCamera对象,摄像机对象创建好以后,一般不会修改投影矩阵,但是经过修改摄像机的观察角度,通过对Camera的mPosition、mRight和mUp可以改变观察的角度。有以下情况。

       修改mPosition可以摄像机的前后左右上下移动。

       修改mUp可以实现类似点头的效果。

      修改mRight可以实现摇头的效果

       同时修改mUp和mRight可以实现观察角度的左右倾斜。

      同时修改mPosition和mRight可以实现围绕某个点左右转动,假设围绕转动的点是某个物体的中心点,转动一圈可以观察到物体前后左右4个面

       同时修改mPosition和mUp可以实现围绕某个点上下转动,转动一圈可以观察某个物体的上、下、前、后4个面。

  • 相关阅读:
    【夯实算法基础】树形DP入门详解+多道例题剖析
    重新审视 ChatGPT 和 Elasticsearch:RAG 真正将应用程序紧密结合在一起
    持续更新 BUUCTF——PWN
    《windows 程序设计》读书笔记 二
    Centos 源码编译 tigervnc
    Java学习笔记(二):封装、继承、多态
    OpenGL进阶(一)之帧缓冲FrameBuffer
    【整合】LSTM 时间序列预测任务 Time-Series-stock (模拟实现股票走势预测)
    Android-树形选择列表
    使用jmeter进行接口测试
  • 原文地址:https://blog.csdn.net/leesino/article/details/140052398