• 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个面。

  • 相关阅读:
    C. Build Permutation(构造/数论)
    改造xxl-job适配nacos注册中心
    归并排序与计数排序(含代码)
    《管理学》试卷
    DolphinScheduler V3.1.8 海豚调度器【概述、安装、功能介绍、项目运用、邮箱预警设置】轻松拿捏!
    项目git commit时卡主不良代码:husky让Git检查代码规范化工作
    【龙芯固件】ACPI表中I2C资源
    Segment Routing IPv6简介
    项目文章 | 总石油烃-重金属污染与土壤微生态系统:细菌多样性、组装和生态功能研究
    cookie、localStorage 和sessionStorage
  • 原文地址:https://blog.csdn.net/leesino/article/details/140052398