QT之OpenGL摄像机
- 1. 概述
- 1.1 摄像机创建
- 2. 旋转(欧拉角)
- 3. demo示例
- 4. 参考
1. 概述
OpenGL
本身没有摄像机(Camera)
的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉。
当我们讨论摄像机/观察空间(Camera/View Space)
的时候,是在讨论以摄像机的视角作为场景原点时场景中所有的顶点坐标:观察矩阵把所有的世界坐标变换为相对于摄像机位置与方向的观察坐标。
正z轴是指向屏幕外,如果我们希望摄像机向后移动,我们就沿着z轴的正方向移动
1.1 摄像机创建
因此OpenGL
想达到摄像机的效果,就要首先需要创建一个摄像机坐标系,用来表示摄像机本身,步骤如下:
-
指定
Camera
的位置QVector3D(0.0f,0.0f,3.0f)
-
指定摄像机指向的方向,现在让摄像机朝向原点
(0.0f,0.0f,0.0f)
此时摄像机的方向向量(Direction Vector)
应当是(0.0f,0.0f,0.0f) - (0.0f,0.0f,3.0f)
,即方向向量指向Z
轴的负方向,
但我们希望它指向摄像机的Z
轴正方向,因此使用方向向量(Direction Vector)
表示指向摄像机Z
轴正方向的向量(0.0f,0.0f,3.0f) - (0.0f,0.0f,0.0f)
auto directionVector = QVector3D(0.0f,0.0f,3.0f)-QVector3D(0.0f,0.0f,0.0f);
-
至此我们有了一个摄像机的方向,接下来处理
X
轴
使用右向量(Right Vector)
,代表摄像机空间的X
轴的正方向,为了得到一个垂直于Z
轴的X
轴,首先顶一个上向量(Up Vector)
既Y
轴(0.0f, 1.0f, 0.0f)
,最后将Y
轴与Z
进行叉乘得出X
轴auto upVector = QVector3D(0.0f, 1.0f, 0.0f); auto rightVector = QVector3D::crossProduct(upVector, directionVector);
-
最后需要一个垂直于
XZ
平面的Y
轴,此时将X
轴与Z
轴叉乘即可得出垂直于XZ
平面的Y
轴auto resultUpVector =QVector3D::crossProduct(directionVector, rightVector)
-
使用摄像机向量创建LookAt矩阵
使用矩阵的好处之一是如果使用3个相互垂直(或非线性)的轴定义了一个坐标空间,可以用这3个轴外加一个平移向量来创建一个矩阵,并且可以用这个矩阵乘以任何向量来将其变换到那个坐标空间。这正是LookAt矩阵所做的,LookAt矩阵如下:
其中R
是右向量,U
是上向量,D
是方向向量P
是摄像机位置向量。注意,位置向量是相反的,因为我们最终希望把世界平移到与我们自身移动的相反方向。把这个LookAt矩阵作为观察矩阵可以很高效地把所有世界坐标变换到刚刚定义的观察空间。前四步我们算出了,方向向量,右向量与向上向量,但定义的值只有一个
摄像机位置
、摄像机方向向量
及一个向上的向量
,而lookAt()
函数同样需要这三个参数,此函数就会进行以上四步的 运算。void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
2. 旋转(欧拉角)
欧拉角(Euler Angle)是可以表示3D空间中任何旋转的3个值,由莱昂哈德·欧拉(Leonhard Euler)在18世纪提出。一共有3种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),下面的图片展示了它们的含义:
-
俯仰角(pitch):是描述我们如何往上或往下看的角,其绕
X
轴旋转,在旋转时YZ
坐标将被改变 -
偏航角(yaw):表示我们往左和往右看的程度,其绕
Y
轴旋转,在旋转时XZ
坐标将被改变 -
滚转角(roll):代表我们如何翻滚摄像机,通常在太空飞船的摄像机中使用。其
绕Z
轴旋转,在旋转时XY
坐标将被改变
用欧拉角描述物体的旋转时会存在一个问题——万向死锁
,有关欧拉角及万向死锁的解释请看这个视频,这里简要概括如下:
- 旋转的顺序不同,最终的姿态也会不同(这里以
pitch -> yaw -> roll
顺序表述) - 欧拉角描述的是一个旋转变换,而不是旋转过程。即在给定三个角度的情况下,
从初始姿态旋转变换到最终姿态
,仅此而已。 - 将最不可能旋转90°的旋转角(尽可能避免),放置在中间,即
yaw -> pitch -> roll
的旋转顺序
3. demo示例
W
、A
、S
、D
进行移动- 滚轮进行缩放
- 鼠标按下时移动鼠标图形也发生转动
camera demo 代码
4. 参考
OpenGL摄像机