在 OpenGL系列(六)变换 中,一个目标物体经过模型矩阵、观察矩阵和投影矩阵的变换才能正常显示出来,其中模型矩阵主要针对目标物体,它会影响物体的位姿。观察矩阵和投影矩阵主要针对观察者而已,这两个变换决定了观察者以怎样的视角观察世界,可以把观察者比作一台摄像机,摄像机拍摄景象的角度由观察矩阵和投影矩阵决定。
在本例中要实现摄像机类Camera,该类主要向外提供观察矩阵和投影矩阵,类定义如下。
- class Camera {
- public:
- Camera();
- virtual ~Camera();
- glm::mat4 getViewMatrix();
- virtual glm::mat4 getProjectionMatrix();
- private:
- glm::vec3 mPosition = glm::vec3(0.0f,0.0f,1.0f);
- glm::vec3 mUp = glm::vec3(0.0f,1.0f,0.0f);
- glm::vec3 mRight = glm::vec3(1.0f,0.0f,0.0f);
-
- };
在Camera类主要成员如下。
投影矩阵有两种,一种是正交投影矩阵,一种是透视投影,因此可以从Camera派生出两个子类,一个是OrthographicCamera表示正交投影摄像机,一个是PerspectiveCamera表示透视投影摄像机。
正交投影摄像机类为OrthographicCamera,定义如下。
- class OrthographicCamera: public Camera{
- public:
- OrthographicCamera(float left,
- float right,
- float top,
- float bottom,
- float near,
- float far);
- ~OrthographicCamera();
-
- glm::mat4 getProjectionMatrix() override;
-
- private:
- float mLeft{0.0f};
- float mRight{0.0f};
- float mTop{0.0f};
- float mBottom{0.0f};
- float mNear{0.0f};
- float mFar{0.0f};
- };
OrthographicCamera主要成员解析如下。
mLeft、mRight、mTop、mBottom、mNear、mFar分别表示裁剪空间的左、右、上、下、近、远。
getProjectionMatrix重新了父类的方法,返回正交投影摄像机的投影矩阵。
透视投影摄像机类为PerspectiveCamera,定义如下。
- class PerspectiveCamera: public Camera{
- public:
- PerspectiveCamera(float fovy, float aspect, float near, float far);
- ~PerspectiveCamera();
-
- glm::mat4 getProjectionMatrix() override;
- private:
- float mFovy{0.0f};
- float mAspect{0.0f};
- float mNear{0.0f};
- float mFar{0.0f};
- };
PerspectiveCamera主要成员解析如下。
类定义完后,接下来实现返回观察矩阵和投影矩阵。
观察矩阵的计算方法如下。
- glm::mat4 Camera::getViewMatrix(){
- glm::vec3 front = glm::cross(mUp,mRight);
- glm::vec3 center = mPosition + front;
- return glm::lookAt(mPosition,center,mUp);
- }
观察矩阵的计算步骤如下。
正交投影摄像机和透视投影摄像机的观察矩阵是一样的,所以放到父类Camera实现,但是投影矩阵就有差异,所以放到各自子类实现。
正交投影摄像机的投影矩阵实现如下。
- glm::mat4 OrthographicCamera::getProjectionMatrix() {
- return glm::ortho(mLeft,mRight,mBottom,mTop,mNear,mFar);
- }
调用glm的ortho即可返回正交投影矩阵。
透视投影摄像机的投影矩阵实现如下。
- glm::mat4 PerspectiveCamera::getProjectionMatrix() {
- return glm::perspective(glm::radians(mFovy),mAspect,mNear,mFar);
- }
调用glm的perspective可返回投影投影矩阵。
该示例的工程已经上传到,地址如下
在开发过程中,首先要确定射线机的类型,以确定是创建OrthographicCamera对象还是PerspectiveCamera对象,摄像机对象创建好以后,一般不会修改投影矩阵,但是经过修改摄像机的观察角度,通过对Camera的mPosition、mRight和mUp可以改变观察的角度。有以下情况。
修改mPosition可以摄像机的前后左右上下移动。
修改mUp可以实现类似点头的效果。
修改mRight可以实现摇头的效果
同时修改mUp和mRight可以实现观察角度的左右倾斜。
同时修改mPosition和mRight可以实现围绕某个点左右转动,假设围绕转动的点是某个物体的中心点,转动一圈可以观察到物体前后左右4个面
同时修改mPosition和mUp可以实现围绕某个点上下转动,转动一圈可以观察某个物体的上、下、前、后4个面。