D3D中使用鼠标控制摄像机旋转

           最近想仿一个CS游戏,在实现用鼠标控制摄像机旋转时遇到了难题。在网上搜了些资料,但感觉描述不清楚,答非所问。有的只贴上了代码,没有对相关技术予以说明,实在很难读懂其核心技术。昨天弄了一天,结果旋转的很糟糕,就像无头苍蝇似的,无法控制。今天早晨躺在床上想了一下,突然明白错在什么地方了。坐标旋转的时候要绕Y轴旋转,而不能饶Up方向旋转,因为Up会随着绕right轴旋转而改变,所以整体旋转实难控制。想到这里,就迫不急待的起床了,吃完早点,到实验楼修正了下旋转方式,结果一切正常!

        设我们的摄像机有三个方向look、up、right,则我们可以控制摄像机在三维空间中做任意角度的变换。如果要用鼠标来控制摄像机旋转,那么我们需要根据鼠标的移动量来更新这三个方向向量,从而达到摄像机跟随鼠标移动而变换。

        鼠标的移动是二维的:水平移动(x方向),垂直移动(y方向)(注:此处xy是窗口设备坐标系。)。那么鼠标的一个微小移动量总可以分解成x和y方向的移动分量,我们根据y方向的移动分量,来设制摄像机绕right方向进行相应角度的旋转,即可实现摄像机视野上下移动;而根据x方向的移动分量,来设置摄像机绕Y轴(世界坐标系)方向进行相应角度的旋转,即可实现摄像机视野水平移动(左右移动)。

以下是算法伪代码:

point = getCursorPos()
dx = point.x - pointOld.x
dy = point.y - pointOld.y
pointOld = point
rotationRight(camera,dy*scaleY)//scale为缩放系数
rotationY(camera,dx*scaleX)

        如果想要持续让摄像机左转,那么上面的算法还不可以实现,因为鼠标移动到窗口边缘时就不能继续移动了。这个解决办法也很简单,我们可以将鼠标坐标锁定。即,每次更新完成后,将鼠标坐标移动到某一点,通常把该点设置到窗口中央。

pointOld.x = wndWidth/2
pointOld.y = wndHeight/2
point = getCursorPos()
dx = point.x - pointOld.x
dy = point.y - pointOld.y
rotationRight(camera,dy*scaleY)
rotationY(camera,dx*scaleX)
setCursorPos(pointOld)//锁定坐标到窗口中央
        此时,需要使鼠标隐身,否则会看到它不停地闪烁。如果还想加入一个射击靶心,可以简单的在锁定点贴一张纹理,或者根据鼠标选取算法,在选取射线上使用“广告板”技术绘制一张纹理。

        通常摄像机上下旋转的时候,我们不想让他拥有360°的灵活性,而应该限制在某一角度范围如(-pi/4 ~ pi/4)。我们需要记录它的相对旋转角度,如果设初始状态时摄像机上下旋转的角度为0,那么我们需要累加它的所有上下旋转角度值(注:上为正、下位负,或者反过来),如果角度值超过界限范围,则将角度值绑定到界限边界。

rotationRight(camera,angle)
{
    fRotAngRight += angle
    if(fRotAngRight > bound) fRotAngRight = bound
    else if(fRotAngRight < -bound) fRotAngRight = -bound
}
        如果我们的旋转动作都由旋转角度来替代,那么程序中的look、right、up向量将会无效,如果要取得方向向量,则要根据旋转角度和初始方向状态进行相应的旋转计算后才可得到。
        使用旋转角度替代实时旋转,还有一个好处,我们可以很方便的将旋转计算方式在方向向量计算方式和四元数旋转计算方式之间切换。


        本文仅代表个人观点,不代表通用技术。希望各位高手可以提供自己的看法,我们共同交流。希望本文对大家有所帮助。

你可能感兴趣的:(游戏,算法,UP,360)