一、概述
观察空间经常被称为 OpenGL 的摄像机(Camera),所以有时也称为摄像机空间(Camera Space)或眼空间(Eye Space)。观察空间是将世界空间座标转化为用户视野前方的座标而产生的结果。因此观察空间就是从摄像机的视角所观察到的空间。而这通常是由一系列的位移和旋转的组合来完成,平移/旋转场景从而使得特定的对象被变换到摄像机的前方。这些组合在一起的变换通常存储在一个观察矩阵(View Matrix)里,它被用来将世界座标变换到观察空间,这一过程亦称视图变换。
二、定义一个相机
相机位置:Position
相机上方向:Up direction
相机观察方向:Look-at direction
三、观察矩阵(View Matrix)
这里定义 为相机的位置座标, 为相机的上方向单位向量, 为相机朝向单位向量。下面是得到一个观察矩阵的步骤
- 将相机位置移动到原点
- 将 旋转到 轴
- 将 旋转到 轴
- 将 ( 叉乘 得到的向量)旋转到 轴
根据定义变换矩阵可等价于
将相机移到原点可得平移矩阵
计算旋转矩阵,这个过程太过复杂不好实现,但最终相机的方向与座标轴相同,所以我们可以先求出旋转矩阵的逆矩阵。因此旋转变换将 旋转到 轴, 旋转到 轴, 旋转到 可转换为
旋转到 , 旋转到 , 旋转到 ,最终结得到结果如下
如何校验矩阵的正确性?这里使用的都是单位向量,比如用 轴单位向量 与上述变换矩阵相乘,可得 ,其余的校验同理可得。根据矩阵的数学性质可得旋转矩阵的最终结果为
综上可得
四、LookAt 函数
在图形学中常使用 LookAt 函数来构造观察矩阵,LookAt 方法需要需要一个位置、目标和上向量
inline mat4 LookAt(const vec4& eye, const vec4& at, const vec4& up)
{
vec4 n = normalize(eye - at); // 等价于上图的 -g
vec4 r = vec4(normalize(cross(up, n)), 0.0); // g x t
vec4 t = vec4(normalize(cross(n, r)), 0.0); // t
vec4 d = vec4(0.0, 0.0, 0.0, 1.0);
mat4 c = mat4(r, t, n, d);
return c * Translate(-eye);
}
参考资料
[1]:Games101_Lecture_04:https://www.bilibili.com/video/BV1X7411F744?p=4
[2]:LookAt 函数源码:https://github.com/WarZhan/Graphics-Demo/blob/master/Octahedra/mat.h
欢迎关注个人公众号,实时推送最新博文!