OPenGL 内部摄像机(Inside out:Camera)

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.绕任意轴旋转一条向量

 
 V up⊥V perp  |V up|=|V perp|=|V aux| V proj⊥V perp  n∥V proj  n为单位向量

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

V proj=|V proj|/|n| n

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

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

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

所以 Vproj=n*V n

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

V up=V perp×n=(V-n*V n)×n=V×n-n*V(n×n)=V×n
V aux=-sin(θ-90)V perp+cos(θ-90)V up=sin(90-θ)V perp+cos(90-θ)V up
=cosθV perp+sinθV up=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








 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值