正向运动学和反向运动学
上次制作的骨骼动画例子程序并不完美,我在程序里面也说了,因为没有牵涉到反向运动学的知识,所以人物运动起来感觉脚无法收缩、头发无法飘逸的感觉。其实在现实中这样的情况是要避免的,但是由于在动画设计的时候要指定每一个关节,显得非常费事。所以引入了反向运动学这个概念。在介绍反向运动学之前,首先让我们看一下正向运动学。
原创文章,反对未声明的引用。原博客地址:http://blog.csdn.net/gamesdev/article/details/13991063
正向运动学,通俗来说是给定父骨骼位置以及它的变换来得出子骨骼的位置以及变换,打一个比方,就像运动手臂,可以带动手肘,进而带动手掌运动。正向运动学的概念是非常容易理解的,实现起来也比较方便,即在场景中先绘制父骨骼,应用父骨骼的变换,然后根据这个变换绘制子骨骼,以此类推。我们可以用下面伪代码来表示:
PushMatrix( ); RenderParentBone( ); ApplyParentTransform( ); PushMatrix( ); RenderChildBone( ); ApplyChildTransform( ); …… PopMatrix( ); PopMatrix( );
反向运动学(InverseKinematics),又称逆运动学,与正向运动学的概念不同,是以子骨骼的位置和变换反推父骨骼的位置和变换,相比正向运动学来说,概念稍难理解。同样打一个比方,我们拽着玩具机械臂的一头进行运动,可以看到机械臂的各个关节都跟着进行运动。下面有几个视频介绍了反向运动学,大家可以看看。
反向运动学的概念知道了后,我们该思考一下如何实现反向运动学,即给定n个骨骼以及n-1个关节形成一个关节链,已知末端关节的位置和首端关节的位置求出中间关节的位置。目前网络上有关反向运动学的资料偏少,可能这是一个存在时间并不长的课题吧。我所看到的中文资料仅限于二维的AS3相关实现,于是开始研究在三维条件下反向运动学的实现。
这里有一些参考资料,如果大家感兴趣的话,可以下载,我也是在研究这么多资料之后才开始着手实现的。
解决三维中反向运动学的问题的方法是分析型(一称解析型)的和数值型方法。分析型的方法给出了一个完整的求解思路,可是求解的效率不高,尤其是反向运动学的关节链很长的时候,在实时演算的领域(比如说游戏领域)就不是一个可行的方法。数值型方法是一个好方法,它类似于启发式搜索的方法,即先试错然后逐步修正,最终得到近似解。下面简单介绍一下数值型方法中两种解法:循环坐标下降(cyclic coordinate decent)法和雅可比矩阵(Jacobian matrix)法。
雅可比矩阵法描述了整个关节链,每一个矩阵的列表示了每个关节的末端变化。解雅可比矩阵可不是一件容易事情,所以这只在非实时领域或者高级IK解算器中会得到使用。
循环坐标下降法是一种简单而可行的办法,它由关节链的末端出发,层层向上递推旋转到目标位置,而且层层迭代以确保准确性,但是效果可能并不好,常常发生在与末端关节连接的关节上,导致的是扭转变形的关节链。但是速度还是有保证的。
我在研究了几种方法之后觉得还是从循环坐标下降方法开始研究,于是在参考资料和前辈们的源码帮助下制作出了下面的演示程序。