3.5 曲线上的简单运动
对于曲线上任意的点P,指定该点处法平面上的一个向量作为法向量,然后结合该点处的切向量通过向量外积得到副法向量,由此可以建立一个局部坐标系。这里指定法向量N 为up向量,代表垂直的轴向;副法向量B为right向量,代表左右轴向;切向量T为forward向量,代表前后轴向。
由曲线引导的运动,这里定义为不“脱离”曲线的运动,即物体的运动必须要有对应的曲线上的线速度vs。首先由该线速度计算出在曲线上向前(或向后,由速度的符号而定)经过t后移动到达的新点P及其局部坐标系(T,B,N),然后以此作为物体运动位置新的基准,并且保证物体运动后的位置位于点P的法平面上,所以任意时刻的运动位置总是处在曲线上某点的法平面上,即曲线的“旁侧”。我们注意到,这种运动计算方式只关心当前曲线上的基准点及其局部坐标系,以及经过t 后的曲线上的基准点及其局部坐标系,而基准点和局部坐标系是否由曲线得来并不重要,所以在实现物理模块时可以和具体的曲线解耦,仅以基准点及其局部坐标系数据作为物理模块的输入。
在具体实例上,这里只讨论在实际游戏中实现的跑动和跳跃(跌落)两种运动。在这两种运动中,曲线还有地面的作用,阻止物体的不断下落;基准点局部坐标系的up向量的负方向为重力的方向。
3.5.1 跑动
曲线上的跑动需要处理悬空(跌落)问题,以及碰到障碍物的问题。
悬空主要有两种情况,一种是遇到较陡的向下的坡,一种是走出支撑物的外沿,二者可以用统一的方式处理。
设当前的基准点和局部坐标系为,经过t 后新的基准点和局部坐标系为,当前对象位置为Loci,相对于新的基准点的高差为
当遇到较陡的向下的坡或者在高出曲线的支撑物上移动时,有H >0,此时先尝试将对象移动到点PH:
然后从该位置沿着-Ni+1方向在跌落阈值FH范围内测试是否存在碰撞体可以作为支撑物:如果存在支撑物,若,则沿着-Ni+1方向移动到和支撑物接触的位置,若,则直接移动到曲线上的点Pi+1;如果不存在支撑物,若,则从跑动状态转为跌落状态,结束本帧的处理,若,则移动到曲线上的点P i+1。对于H≤0的情况,曲线为平直的或上坡,可以直接将对象移动到点Pi+1。
在移动对象的过程中,可能碰上带有碰撞的障碍物。根据位移向量和碰撞体表面法线的关系以及接触位置可以分为两类:一类是无法沿着接触表面移动或绕过的障碍物,导致当前的运动发生截断,停留在接触的位置上,阻止对象继续产生位移;另一类是可以沿着接触表面滑动或绕过的障碍物,这种情况无法将对象移动到预期的位置,但是可以持续移动到基准点的法平面上。一般的商业引擎对这样的情况都有处理,如Unity3D的CharacterController。
3.5.2 跳跃
跳跃状态的触发来自跑动状态的转换(自然跌落)和玩家(主动跳跃)。
一般场合下的跳跃会分成水平和垂直两个方向分别处理,曲线上的跳跃也做相同的处理,其中水平速度分量始终为曲线上的线速度,是一种曲线上投影速度恒定的做法,与对象实际经过的位移过程无关。所以,同时运动且具有相同水平速度的两个对象,无论实际运动路径如何,总是处在相同基准点的法平面上。
同跑动,设当前的基准点和局部坐标系为,经过t 后新的基准点和局部坐标系为++++,当前对象位置为Loci。由Loci和Ni可以构建一个平面:
该平面和直线
的交点记为PNN,显然PNN在Pi+1的法平面上。这里将对象移动到PNN,位移向量
和Pi的切平面平行,可以看作是原水平运动方向Ti被引导曲线改变了方向,围绕Ni发生了旋转,使其指向新的基准点Pi+1的N轴。
对于垂直方向,根据重力加速度更新速度的标量值:
使用新的基准点Pi+1的-Ni+1向量作为重力方向计算垂直方向的位移向量:
最终的位置为
在下落过程中如果遇到可以作为支撑的碰撞体,则转为跑动状态。其他碰撞体的处理方式类似于跑动。
3.5.3 相邻路径的切换
跑酷类游戏有切换跑道的操作。得益于物理计算与具体曲线的解耦,路径的切换也可以对物理计算透明。
设当前路径曲线为,切换的目标路径曲线为,触发切换路径时,设当前在上的基准点为,其法平面为
计算该法平面与曲线的交点,该交点对应的曲线参数为,局部坐标系为。该点为基准点在上的等位点,在此将路径切换到,且从等位点开始接替在上的移动计算。路径的切换不能瞬间完成,需要一个将对象从路径移动到路径的过程。为此,将变换到上基准点的局部坐标系下,这里设其变换后的值为,在对象完全移动到路径之前,将和(O, X, Y, Z)(O为局部坐标系的原点(0,0,0), X, Y, Z 为局部坐标系的三个坐标轴(1,0,0), (0,1,0), (0,0,1))插值的结果转换到世界坐标系,作为当前基准点及关联的局部坐标系输入给物理模块。将变换到上基准点的局部坐标系下,好处是路径切换一旦开始,就只与目标路径相关,源路径如何变化不会影响切换的过程,例如,在路径的切换过程中两条路径走向了不同方向。图3.4展示了路径切换的过程,其中绿色虚线为实际的移动路径,由和(O, X, Y, Z)插值而来;橙色虚线表示转换到局部坐标系后发生路径切换时的的基准点。
图3.4 路径切换插值轨迹
3.5.4 曲线上的旋转插值
每一个路点都有位置和旋转属性。旋转可以分解出三个坐标轴,所以物理计算所依赖的基准点局部坐标系(T, B, N)可以通过分解基准点处的旋转获得,而基准点处的旋转通过对两个路点的旋转插值获得。根据不同的需求,还可以选择插值得到的旋转是否对齐到曲线的切线。旋转插值对比如图3.5所示。
图3.5 旋转插值对比
对于二次曲线构成的路径而言,需要注意相机的旋转最好不要和曲线的切线相关联(如将镜头对齐到曲线上),而是独立计算相机的运动。由于二次曲线只有C1连续,相机的朝向和曲线的切线方向关联会令镜头朝向的变化产生人眼可察觉的生硬感。