在OpenGL的图形化界面中不可避免会使用到鼠标的操作,而想让视角跟着鼠标一起移动并不是一件方便的事。为了达到这个目的需要根据鼠标的移动不断地改变gluLookAt函数中传入的参数,以改变视角。而要使视角的变化与鼠标移动的方向大小均一致,需要进行一定的矩阵计算。为此我们自己写了个(三维)Vector类,实现了基本的向量运算,包括点乘(运算符重载*)和叉乘(OuterProduct函数),以及一个友元函数Transform,接受一个4*4的矩阵和一个Vector做为参数,返回一个矩阵左乘该向量的结果。我的程序的实现方法完全是按照教科书的实现:先用WorldToView矩阵将坐标从绝对坐标转化到观察者坐标,再进行需要的旋转,最后再用ViewToWorld矩阵将坐标恢复到世界坐标。
以下代码中theWorld是我定义的一个世界,其中的lastx和lasty用于记录上次鼠标指向的坐标(从而计算和当前xy的距离差,计算LookAt方向),m_Eye,m_Center和m_Up分别对应gluLookAt的9个参数。需要注意的是在旋转过程中的不变量:m_Eye一直固定,在水平旋转时m_Up的值不变,而vRight(视角向右的向量)的值会变化;而竖直旋转时则正好相反,vRight不变而m_Up变了。所以旋转的时候分两步,分别进行水平和竖直旋转,每一步结束后根据不变的量修复改变了的量。
void OnMouseMove(int x, int y)
{
FixMouse(x, y);
GLdouble HorizontalAngle = (GLdouble)(theWorld.lastx - x) / theWorld.