标签:opengl
解决三维建模软件中摄像机旋转的问题
我们看到很多3D建模软件都可以很方便地对摄像机进行旋转,比如说Blender,通过按下鼠标中键,就可以很方便地对摄像机进行旋转。在学习了几年OpenGL之后,我也想要模仿这一点做出类似的功能。但是当研究的时候,遇到了一些困难。
蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44828475。欢迎同行前来探讨。
此前了解到,这些建模软件对于三维建模中的摄像机的定义是:拥有位置(position)、观察点(look at)以及向上的向量(up),此外还有近裁面(z near)、远裁面(z far)、宽高比(aspect ratio)以及视野(field of view)。其中前三者构成了视图矩阵(view matrix),后四者构成了投影矩阵(projection matrix)。这里我说一下如何当摄像机绕着观察点旋转时视图矩阵是如何改变的。
1、 当鼠标按下时,我们必须记录当前摄像机的位置以及向上的向量,因为我们接下来旋转时要改变的就是这两个向量;
2、 在旋转时,我们需要计算position– lookat向量与Y轴形成的平面的法向量,这里我们称之为side向量,因为我们实际中旋转的一部分是在这个平面内进行的。
3、 计算旋转矩阵,首先如果鼠标往左右移动了,旋转矩阵沿着y轴正方向旋转-x角度;如果鼠标往上下移动了,旋转矩阵沿着side向量旋转-y角度。注意顺序很重要,如果两者颠倒顺序了,那么旋转出来的效果就不是我所见的三维建模软件那样的效果了;
4、 紧接着计算对position变换的矩阵:首先平移lookat向量,让lookat位于原点;接着乘以第三步计算的旋转矩阵,在后来执行反向操作,将lookat变回原来的位置。
5、 将第四步计算出来的变换矩阵左乘我们暂存的position,得到新的position,将第三步计算出来的旋转矩阵左乘我们暂存的up向量,得到新的up。这里说明的是,当我们将position从side和y轴形成的面旋转到另外一个新的position的时候,如果up向量不发生改变,模型的显示就会出现前后颠倒的现象。所以改变up向量的朝向也是非常有必要的。
6、 最后根据新计算出来的position和up,来计算视图矩阵。
下面的一段代码展示了这一个过程如何操作的:
void MouseCamera::startRotate( void ) { m_prevPosition = m_position; m_prevUp = m_up; } void MouseCamera::rotate( qreal x, qreal y ) { QMatrix4x4 transformMatrix, rotateMatrix; const QVector3D yUp = QVector3D( 0.0f, 1.0f, 0.0f ); QVector3D side = QVector3D::crossProduct( m_lookAt - m_prevPosition, yUp ).normalized( ); rotateMatrix.rotate( -x, yUp ); rotateMatrix.rotate( -y * m_prevUp.y( ), side ); transformMatrix.translate( m_lookAt );// 首先平移,让lookAt位于原点 transformMatrix *= rotateMatrix; transformMatrix.translate( -m_lookAt );// 再平移回来 m_position = transformMatrix * m_prevPosition; QVector3D prevUp = m_up; m_up = rotateMatrix * m_prevUp; emit positionChanged( ); if ( m_up != prevUp ) emit upChanged( ); calculateViewMatrix( ); }
标签:opengl
原文地址:http://blog.csdn.net/gamesdev/article/details/44828475