今天有个任务,是使得NPC随着玩家转动,主要就是计算NPC的朝向问题。
在Ogre空间内(Y垂直向上,下面是XOZ平面),假设NPC在点P1(x1,z1),玩家在点P2(x2,z2);那么如果NPC面向玩家该怎么办呢?其实就是求NPC绕着Y轴逆时针旋转的成角(Yaw)问题,NPC初始方向是面向屏幕(即Z正半轴)。
解:
设P1与P2之间的连线为L(方向是P1指向P2,即NPC面朝向玩家);
假设L与Z正半轴的成角为θ, P1与P2之间的距离为dist。下面分情况讨论:
(1) 当 θ∈[0, PI/2) 时,
cosθ = (z2-z1)/dist
===>>> arccos((z2-z1)/dist) = θ ∈ [0, PI/2) //ok,因为反余弦函数值域是[0,PI]
(2) 当 θ∈[PI/2, PI) 时,
这里δ是L与X正半轴的夹角(锐角)
cosθ = cos(PI/2 + δ) = - sinδ = - (z1-z2)/dist = (z2-z1)/dist
===>>> arccos((z2-z1)/dist) = θ ∈ [PI/2, PI)
(3) 当 θ∈[PI, 3/2*PI) 时,
这里δ是L与Z负半轴的夹角(锐角)
cosθ = cos(PI + δ) = - cosδ = - (z1-z2)/dist = (z2-z1)/dist
又因为:cos(2*PI-θ) = cos(-θ) = cosθ = (z2-z1)/dist
===>>> arccos((z2-z1)/dist) = 2*PI-θ ∈ (PI/2, PI]
(4) 当 θ∈[3/2*PI, 2*PI) 时,
这里δ是L与Z正半轴的夹角(锐角)
cosθ = cos(2*PI - δ) = cosδ = (z2-z1)/dist
又因为:cos(2*PI-θ) = cos(-θ) = cosθ = (z2-z1)/dist
===>>> arccos((z2-z1)/dist) = 2*PI-θ ∈ (0, PI/2]
上面中(1)和(2)类似,都满足x2 >= x1; (3)和(4)类似,都满足 x2 < x1.
****************************************************************
从程序计算角度,就可以这样做了:
设 arccos((z2-z1)/dist) = value;
if x2 >= x1
value 就等于θ,即 θ = value;
else
value 就等于2*PI-θ,即 θ = 2*PI - value;
求出θ 后,就可以调用CObject::SetRotate(θ)来设置NPC的朝向啦。
也即:
if x2 >= x1
CObject::SetRotate(value);
else
CObject::SetRotate(2*PI - value) = CObject::SetRotate( - value); //因为是旋转角度,所以可以加减任意个2*PI。