欢迎访问:常州市武进区嘉泽中心小学网站 !今天是:
栏目列表
您现在的位置是:首页>>教师>>计算机技术>>程序设计>>游戏开发>>文章内容
Inside out: Camera
发布时间:2008-11-20   点击:   来源:本站原创   录入者:佚名
 

Inside out: Camera

丁欧南

 

Keyword:[OpenGL Camera][FPS 场景][第一人称射击场景]

我是一名OpenGL初学者,刚刚弄懂Camera的实作方法,愿与初学者共享,与高手探讨.如需要此文完整代码,或要转载,请发邮件给我.


A.约定

    1. sin cos 等的引数全用弧度制

    2. 使用OpenGL 右手定则

    3. 矩阵(Matrix)书写规范:

       平移(Translation)部分位于最后一行,你可以不加修改地把矩阵写入自己的OpenGL 代码

       例:

       [A11  A12  A13  A14]

       [A21  A22  A23  A24]  

       [A31  A32  A33  A34]

       [A41  A42  A43  A44]

       float matrix[]={A11,A12,A13,A14,A21,A22,A23,A24,A31,A32,A33,A34,A41,A42,A43,A44};

    4. *:点积(Dot Product) ×:叉积(Cross Product)

B.概念

    大家都知道gluLookAt,它有三类(每类3个)共9个引数:

    void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,

                                GLdouble centerx,GLdouble centery,GLdouble centerz,

                               GLdouble upx,GLdouble upy,GLdouble upz);

    你需要分别指定这三类引数,才能完成Camera变换.

    1.视线:你不用在gluLookAt中指定视线(从眼到被视物体的向量),但在变换视点(尤其是旋转时),所作的许多          操作都是针对它进行的,

                 后面将给出如何计算视线向量的公式.

    a.视点:即gluLookAt中eye*的那三个引数,视点指的是一条从原点到眼位置的向量.

                从你的座位上站起来,这时你改变的就是视点.

    b.视目标:即gluLookAt中center*的那三个引数,视目标指的是一条从原点到被视物体的向量.

                     水平转动你的脖子,这时你所作的就是改变视目标.

    c.仰视向量:即gluLookAt中up*的那三个引数,仰视向量指的是头顶的朝向.

                        竖直抬起头(‘向上看’),这时改变的就是仰视向量.

                        [一般来讲,仰视向量用(0,1,0)就可以了,不用再仔细考虑它]

                       

     2.很明显,由向量减法 视线 view,视点 pos,视目标 tar

             view=tar-pos;

     3.Camera的变换也就是改变视线位置(前进或后退),方向(转头)

     4.Camera变换Pipeline:

         Ⅰ   由pos,tar 计算出 view

         Ⅱ   变换view

         Ⅲ   将view的x,y,z分量传回pos和tar

         Ⅳ   将pos,tar,up传给gluLookAt

C.平移

      平移是最简单的,它起的作用是游戏者的前进与后退,你会发现平移其实就是平行移动视线,方向不变.

      如下图:
                                      

      代码讲解:

           void Move(float speed) {     //speed:指定每按一下键前进多少,我取的是0.3

              Vector view=tar-pos;     //取得view,Vector不是std::vector

              pos.x+=speed*view.x; pos.z+=speed*view.z;

              tar.x+=speed*view.x; tar.z+=speed*view.z;

           }                       

         //我只希望在平面上移动,所以没有y分量的事.


D.旋转

    旋转就是转头操作,比较复杂,一点一点来.

   D1.绕任意轴旋转一条向量

           

     Vup⊥Vperp  |Vup|=|Vperp|=|Vaux|  Vproj⊥Vperp  n∥Vproj  n为单位向量

     绕n旋转V θ度到V’, 求V’

    

     Vproj=|Vproj|/|n| n

     n*V=|n||V|cosβ     cosβ=|Vproj|/|V|   |Vproj|=|V|cosβ

     n*V=|n||Vproj|         |Vproj|=(n*V)/|n|

     Vproj=(n*V)/|n|2 n       因为 n 为单位向量

     所以 Vproj=n*V n

    

     Vperp=V-Vproj=V-n*V n

     Vup=Vperp×n=(V-n*V n)×n=V×n-n*V(n×n)=V×n

    

     Vaux=-sin(θ-90)Vperp+cos(θ-90)Vup=sin(90-θ)Vperp+cos(90-θ)Vup

             =cosθVperp+sinθVup=cosθ(V-n*V n)+sinθ(V×n)

    

     V’=Vperp+Vaux=n*v n+cosθ(V-n*V n)+sinθ(V×n)

 

  D2.水平转头

        水平转头即在XZ平面上绕竖直方向旋转view向量

                         

         可看出pos无变化,y分量亦无变化.

         XZ平面的旋转矩阵:

                    [ cosθ  0   -sinθ  ]

                    [ 0          1    0          ]

          [ sinθ   0    cosθ ]

      取得view:  view=tar-pos;
      旋转view:

                                                  [cosθ  0  -sinθ ]

          [view.x  view.y  view.z]  [0           1   0        ]

                                                  [sinθ   0   cosθ]

          =[view.x*cosθ+view.z*sinθ  view.y  -view.x*sinθ+view.z*cosθ]
      传回tar值:

         tar’=pos+view’;

 

  D3.竖直转头

        竖直转头即在YZ平面上以垂直于view的直线为轴旋转view向量

       侧视示意图:
                             
                                   

      鸟瞰示意图:
 
                                        

     取得view: view=tar-pos;

     取得 axis: 即旋转view (-π/2)

                                                    [0   0   1]

             [view.x  view.y  view.z] [0   1   0]

                                                    [-1  0   0]

              =[-view.z  view.y  view.x]

     为了用上D1中求得的公式,把axis归一化(Normalize)

     绕axis旋转view: (套用D1最后得出的公式)

             view’=axis*view axis+cosθ(view-axis*view axis)+sinθ(view×axis);
   更新tar值:

            tar’=pos+view;

E.鼠标滑动角度计算

   我们注意到进行旋转Camera时,需要向程序提供转过的角度(2个)

   一个是水平转动角度(转头),一个是竖直转动角度(抬头或低头)

   这样计算:

      鼠标滑过的距离其实是view向量终点滑过的距离

      用滑过的距离(s),view向量的长度(l),求得水平角(a),竖直角(b)

      a=arc tan s.x/l    b=arc tan s.y/l

 

 





 

 
附件:
    关闭窗口
    打印文档
    账号登录
    保持登录 忘记密码?
    账号与武进教师培训平台同步