在实时渲染场景中的运动物体与复杂地形交互策略

作者:Zhipeng Wang 2009-09-07
原文章地址:http://hi.baidu.com/loserwang/blog/item/9e7ea734ba35f4325ab5f569.html
文章作者:Zhipeng Wang
发布时间:2009-09-07 15:25
请说明文章出处,欢迎转载


一、使用影子对象辨别运动物体的可活动性



为了与场景进行较为真实的交互,以提供良好的视觉和可操作性反馈,针对各种情况进行的运算必不可少。

例如,高度发生徒然变化的区域,默认情况下,部分凸起多边形将阻止运动物体的行进方向,为此需要判断如何指导运动物体的下一步动作,典型的处理方式是令其拉升高度以便越过障碍,但不总是如此。

例如,当墙壁过高,使得运动物体无论如何不应该攀爬而过,为此我创建了“影子对象”,这个影子对象拥有在运动物体“本体”碰撞盒顶部之上相同大小的碰撞盒,设想“本体”碰撞盒的顶部位于运动角色可视形态的膝盖附近,那么“影子对象”的碰撞盒则在其之上。当阻碍物体与“本体”发生碰撞而不与“影子对象”发生碰撞,明显阻碍物体位于较低的位置,当同时测知运动物体在运动中因为受到阻碍而降低的速度不足预期速度的某个比值时,这时候将向运动物体发送抬升高度的命令,直至状态解除。

一个运动物体将因此实际使用两个碰撞盒,以帮助运动物体在场景中更好地进行漫游。

二、碰撞反馈矢量与运动矢量的关系



物体 A 预期以 vector 向量行进,和某一表面碰撞而进行 correct 修正,correct 的单位向量为碰撞表面的平均法线,产生的 result 运动向量总是与表面的切线平行而与法线垂直,即 vector, correct, result 三者构成一个直角三角形。

现在提出命题,已知向量 vector 与 correct 的值,分别为直角三角形的弦和其中一直角边,a 是它们的夹角,当 result 的模为预期运动向量 vector 的模的 1/5,判定为运动物体受到阻碍,如何用不等式表示?

根据命题,可知
|result| / |vector| < 1/5 时,
物体 A 受阻碍,即 sin(a) < 0.2;
而 vector 与 correct 是已知的;
又 cos(a) = |correct| / |vector|,
若 |result| / |vector| = 1/5,
则 |correct| / |vector| = sqrt(24) / 5;
根据余弦的函数曲线图特征,在 a ∈ [0, 180] 时,随着角度增大,余弦值变小;
相似的,正弦值增大,即正弦值趋近于 0,角度 a 趋近于 0,对应的余弦值将增加而趋近于 1,故:
不等式可表示为 |correct| / |vector| > 0.9798...

三、部分 C++ 代码参考

在这段代码中,检测到运动物体受阻时触发的高度修正将包含在一个衰减期间,以便获得更为平滑的视觉及操作反馈。

float valCos = correctional.Mod() / speed.Mod();

static float f = 0; // 实时高度修正值
static float f_0 = 0; // 初始高度修正值

if (f > 0)f -= f_0 * 0.1f;
else f = 0, f_0 = 0;

correctional.y += f;

if (!correctional.IsZero())
{
        if (speed.z && correctionalShadow.Mod() < Epsilon
                && valCos > 0.979795897f) // sqrt(24) / 5
                f_0 = f = fwd_spd; // fwd_spd: 运动物体水平运动速度
               
        obj.SetPosition(obj.GetPosition() + correctional);
        objShadow.SetPosition(obj.GetPosition());

        speed.y += correctional.y; // 维护高度方向的状态
}
最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多