发明内容
本发明的主要目的在于,提供一种动画中动态骨骼的实现方法和装置,在本发明的作用下,通过控制动态骨骼的移动,能够使得所对应的动画模型的移动更为逼真地符合视觉效果。
根据本发明的一个方面,提供了一种动画中动态骨骼的实现方法,包括:创建针对目标对象的骨骼关节树,其中,骨骼关节树中直接相连的两个关节中更接近根节点的关节为父关节,更远离根关节的关节为子关节;计算骨骼关节树中的关节在下一帧的位置信息;针对骨骼关节树中的至少一个子关节,将该子关节从当前帧到下一帧的位置变换转换为绕该子关节的父关节的旋转变换,从而通过旋转变换,将子关节移动到其下一帧的位置。
由此,通过将关节的位置变换转换为绕其父关节的旋转变换,可以使得运动过程更加平滑,改善视觉效果。
优选地,计算骨骼关节树中的关节在下一帧的位置信息可以包括:计算预定作用力下骨骼关节树中的关节在下一帧的位置信息,其中,预定作用力可以包括下列至少一项:重力;关节移动过程中受到的与移动方向相反的阻力;以及来自周围环境的干扰力。
由此,可以计算在骨骼关节树中的关节在受到重力、干扰力、阻力等外力作用下在下一帧的位置信息,使得计算出的位置信息能够准确地反映关节的实际运动情况。
优选地,计算预定作用力下骨骼关节树中的关节在下一帧的位置信息可以包括:使用如下位置计算公式计算关节在下一帧的位置信息posn+1,
posn+1=posn+(posn-posn-1)*(1-r)+(gv+d)*Δt2
其中,posn+1为关节在下一帧的位置信息,posn为关节在当前帧的位置信息,posn-1为关节在上一帧的位置信息,r为阻力作用下的阻力系数,0≤r≤1,gv为重力在关节的长度方向上的法向方向上的重力分力作用下的加速度,d为干扰力作用下的加速度,Δt为上一帧与当前帧之间的时间间隔。
优选地,该实现方法还可以包括:使用如下第一修正公式对计算得到的关节在下一帧的位置信息posn+1进行修正,
其中,pos'n+1为关节经过补偿后在下一帧的位置信息,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。
由此,通过第一位置修正公式可以使得关节的长度在关节的运动过程中保持不变。
优选地,将子关节在下一帧的位置信息与当前帧的位置信息之间的位置变换转换为绕该子关节的父关节的旋转变换可以包括:根据子关节在当前帧的位置信息,确定从父关节到子关节的当前方向向量;根据子关节在下一帧的位置信息以及当前帧的位置信息,确定子关节在其父关节坐标系下的移动向量;根据当前方向向量和移动向量,获取绕父关节进行旋转变换的四元数。由此,可以使用四元数来表示绕子关节的父关节的旋转变换。
优选地,将子关节在下一帧的位置信息与当前帧的位置信息之间的位置变换转换为绕该子关节的父关节的旋转变换还可以包括:使用四元数插值算法对四元数进行插值运算,以得到缓冲四元数;基于缓冲四元数对父关节和子关节进行旋转变换。
通过对四元数进行插值运算,可以对旋转进行缓冲过滤,以使得运动关节所对应的动画模型的运动更加柔顺平滑。
优选地,该实现方法还可以包括:消除旋转变换在子关节与其父关节构成的轴向方向上的分量;通过消除后的旋转变换,将子关节移动到其下一帧的位置。由此,可以避免子关节的自转造成的关节绞绕问题。
优选地,该实现方法还可以包括:在检测到计算得到的关节在下一帧的位置信息与目标碰撞体发生碰撞的情况下,对关节的位置信息进行修正,以使得修正后关节在下一帧的位置信息基本满足以下条件:修正后关节位于目标碰撞体的边缘;修正后关节到其父关节之间的关节臂的长度不变。
由此,可以避免出现模型穿透的问题,比如人物在跑动过程中,衣服的飘动穿透了皮肤、头发在人物播放跑动动作会嵌入后背等等,这些都是违背现实世界物体的运动规律的,对视觉体验造成严重的影响。
优选地,关节与目标碰撞体均为具有预定半径的球体,对关节的位置信息进行修正可以包括:使用如下第二修正公式对关节的位置进行修正:
其中,pos”n+1为关节进行修正后在下一帧的位置信息,c1为关节修正前在下一帧的位置信息,c2为碰撞体的位置信息,r1为关节的半径,r2为碰撞体的半径,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。
优选地,该实现方法还可以包括:从与根关节直接相连的关节开始,逐级计算骨骼关节树中的关节在下一帧的位置信息、将该关节在下一帧的位置信息与当前帧的位置信息之间的位置变换转换为绕该关节的父关节的旋转变换。
由此,通过循环体的形式从根骨骼关节下的子关节开始进行迭代运算,以此模拟整个骨骼动画的运动轨迹。如此一来,既满足了各骨骼关节运算的独立性,又保证了整棵骨骼关节树运算的顺序性。
根据本发明的一种动画中动态骨骼的实现装置,包括:骨骼关节树创建模块,用于创建针对目标对象的骨骼关节树,其中,骨骼关节树中直接相连的两个关节中更接近根节点的关节为父关节,更远离根关节的关节为子关节;计算模块,用于计算骨骼关节树中的关节在下一帧的位置信息;旋转变换模块,用于针对骨骼关节树中的至少一个子关节,将该子关节从当前帧到下一帧的位置变换转换为绕该子关节的父关节的旋转变换,从而通过旋转变换,将子关节移动到其下一帧的位置。
优选地,计算模块计算预定作用力下骨骼关节树中的关节在下一帧的位置信息,预定作用力可以包括下列至少一项:重力;关节移动过程中受到的与移动方向相反的阻力;以及来自周围环境的干扰力。
优选地,计算模块使用如下位置计算公式计算关节在下一帧的位置信息posn+1,posn+1=posn+(posn-posn-1)*(1-r)+(gv+d)*Δt2
其中,posn+1为关节在下一帧的位置信息,posn为关节在当前帧的位置信息,posn-1为关节在上一帧的位置信息,r为阻力作用下的阻力系数,0≤r≤1,gv为重力在关节的长度方向上的法向方向上的重力分力作用下的加速度,d为干扰力作用下的加速度,Δt为上一帧与当前帧之间的时间间隔。
优选地,实现装置还可以包括:第一修正模块,用于使用如下第一修正公式对计算得到的关节在下一帧的位置信息posn+1进行修正,
其中,pos'n+1为关节经过补偿后在下一帧的位置信息,posp为关节的父关节的位置信息,len为为关节到其父关节之间的关节臂的长度。
优选地,旋转变换模块可以包括:当前方向向量确定模块,用于根据子关节在当前帧的的位置信息,确定从父关节到子关节的当前方向向量;移动向量确定模块,用于根据子关节在下一帧的的位置信息以及当前帧的位置信息,确定子关节在其父关节坐标系下的移动向量;四元数获取模块,用于根据方向向量和移动向量,获取绕父关节进行旋转变换的四元数。
优选地,旋转变换模块还可以包括:插值运算模块,用于使用四元数插值算法对四元数进行插值运算,以得到缓冲四元数,旋转模块,用于基于缓冲四元数对父关节和子关节进行旋转变换。
优选地,旋转变换模块还用于消除旋转变换在子关节与其父关节构成的轴向方向上的分量,通过消除后的旋转变换,将子关节移动到其下一帧的位置。
优选地,实现装置还可以包括:第二修正模块,用于在检测到计算得到的关节在下一帧的位置信息与目标碰撞体发生碰撞的情况下,对关节的位置信息进行修正,以使得修正后关节在下一帧的位置信息基本满足以下条件:修正后关节位于目标碰撞体的边缘;修正后关节到其父关节之间的关节臂的长度不变。
优选地,第二修正模块可以使用如下第二修正公式对关节的位置进行修正:
其中,pos”n+1为关节进行修正后在下一帧的位置信息,c1为关节修正前在下一帧的位置信息,c2为碰撞体的位置信息,r1为关节的半径,r2为碰撞体的半径,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。
优选地,计算模块从根关节开始逐级计算骨骼关节树中的关节在下一帧的位置信息,旋转变换模块从与根关节直接相连的关节开始,逐级将该关节在下一帧的位置信息与当前帧的位置信息之间的位置变换转换为绕该关节的父关节的旋转变换。
本发明的动画中动态骨骼的实现方法和装置,通过计算关节在下一帧的位置信息,将关节的位置变换转换为绕该关节的父关节的旋转变换,从而通过所述旋转变换,将关节移动到其下一帧的位置,可以使得运动过程更加平滑,改善视觉效果。
具体实施方式
下面将参照附图更详细地描述本公开的优选实施方式。虽然附图中显示了本公开的优选实施方式,然而应该理解,可以以各种形式实现本公开而不应被这里阐述的实施方式所限制。相反,提供这些实施方式是为了使本公开更加透彻和完整,并且能够将本公开的范围完整地传达给本领域的技术人员。
在详细介绍本发明前,首先对本发明涉及的一些背景术语做以简要说明。
多边形网格(Polygon Mesh):简称网格,是在三维电脑绘图中用来表示立体模型的一种结构,包括顶点、面、法线、切线、顶点颜色、纹理坐标等一系列基础数据的定义。
骨骼蒙皮动画(Skeletal Animation):简称骨骼动画,其原理为:在每一帧的动画播放过程中,动画关键帧数据驱动骨骼关节变换(包括位移、旋转、缩放),然后结合蒙皮信息,骨骼关节进一步驱动网格顶点的变换,以此完成模型动画的模拟。一个骨骼动画模型通常包括骨骼关节(Joint)层次结构数据,网格数据,网格蒙皮数据和骨骼的动画(关键帧)数据。相比于其他动画类似(如顶点动画、变形动画)具有数据简明、占用存储空间少、制作便捷、支持动态生成序列帧、支持正向反向动力学等诸多优点。
蒙皮信息(Skin Info):简称蒙皮,一种三维动画制作过程中使用到的技术手段,由于骨骼关节与网格顶点在结构设计上是相互独立的,为了实现骨骼关节对网格顶点的控制,需要一种桥接数据来指定它们之间的关联性,即骨骼关节对周围哪些顶点产生影响以及影响权重是多少,这种将模型各网格顶点绑定骨骼关节并指定权重的技术叫做蒙皮;生成的数据结构称为蒙皮信息。
万向节死锁(Gimbal Lock):简称万向锁,当使用欧拉角构件刚体在三维欧几里得空间中的有限转动时,三个旋转轴中的两个轴发生重合时,会失去一个自由度的情形。
静态骨骼动画:指模型的骨骼关节的运动轨迹是固定不变的,通常由美术制作人员负责设计并以特定的文件格式输出的动画类型,是相对于动态骨骼而言的。
下面首先结合图1就本发明的动画中动态骨骼的实现方法的基本流程做简要说明。参见图1,在步骤S110,创建针对目标对象的骨骼关节树。
本发明所针对的目标对象可以是多种类型的动画模型,例如可以是动画人物、人物的头发、人物所持有的武器、以及动画环境中的其它物体如植物、动物、云朵等等。
由于本发明的主要目的在于使得动画模型的运动在视觉上更加逼真,因此,本发明所针对的目标对象可以优选地是某个动画物体中需要进行移动的部分。例如,目标对象可以是动画人物的头发、裙子、所持有的鞭子等等。如图2所示,针对图中左边的头发模型,可以右图所示的构建骨骼关节树,右图中的圆球即表示所构建的骨骼关节树中的每个骨骼关节,相邻两个圆球之间的白色线段可以视为相邻关节之间的关节臂。
创建针对目标对象的骨骼关节树的过程为本领域技术人员所公知,这里不再详述。需要说明的是,骨骼关节树的创建过程可以由制作动画的美术制作人员开发,并且出于调试效率与控制粒度的需求,所构建的骨骼关节树中的每个关节可以绑定一个脚本进行参数的控制,包括阻力系数、碰撞半径、目标碰撞体(即需要进行穿透规避评估的碰撞体)。例如,骨骼关节树中的每个关节都可以绑定包括中心位置坐标、半径、所受拖拽力、所涉及的目标碰撞体等参数的脚本,以便实时模拟运动轨迹,同时方便对参数进行调整。
可以将所创建的骨骼关节树中直接相连的两个关节中更接近根关节的关节为父关节,更远离根关节的关节为子关节。骨骼关节树中没有子关节的关节可以称为叶子关节,最顶端的关节为根关节。
在创建完成骨骼关节树后,针对骨骼关节树中的一个关节,可以顺序执行步骤S120、步骤S130。
在步骤S120,计算该关节在下一帧的位置信息。此处需要说明的是,本发明中所计算的关节的位置信息可以是骨骼动画中的世界坐标系下的位置信息。
在步骤S130,将该关节从当前帧到下一帧的位置变换转换为绕该关节的父关节的旋转变换,从而通过旋转变换,可以将子关节移动到其下一帧的位置。将关节的位置变换转换为该关节的父关节的旋转变换的具体实现过程将在下文详细说明,这里暂不叙述。
需要说明的是,步骤S130所针对的关节主要是骨骼关节树中的非根关节。这是因为,根关节一般是动态骨骼与静态骨骼的交汇处,根关节的运动轨迹主要由静态骨骼动画决定。例如,头部可以认为是根关节,头发属于头部的子关节,头部的运动状态应该由其父关节躯干(静态骨骼)决定。因此,对于根关节的位置变换,可以不执行本发明的动态骨骼的实现方法,而由美术预先设定,或者是游戏里的动画控制器设定。
至此,结合图1、图2简要说明了利用本发明实现骨骼关节树中的一个关节在下一帧的移动的过程。在利用本发明实现骨骼关节树中多个关节的移动时,可以由上到下逐级进行。如图3所示,方法开始于步骤S210,从与根关节直接连接的关节(即根关节的子关节)开始,计算关节在下一帧的位置信息(步骤S220),然后将该关节的位置变换转化为绕该关节的父关节的旋转变换(步骤S230),由此完成了对根关节的子关节的处理,在完成后,可以判断该关节是否为最底层的叶子关节(步骤S240),如果是,则处理结束(步骤S250),如果不是,则可以继续对该关节的子关节执行步骤S220、步骤S230的处理,直到处理完骨骼关节树中的叶子关节为止。其中,步骤S220、步骤S230的处理过程与图1中的步骤S120、步骤S130相同,这里不再赘述。
如上文所述,根关节一般是动态骨骼与静态骨骼的交汇处,根关节的运动轨迹主要由静态骨骼动画决定,因此对于根关节可以仅确定其在下一帧的位置信息,而不进行旋转变换。
也就是说,可以从与根关节直接相连的关节开始,逐级计算骨骼关节树中的关节在下一帧的位置信息、将该关节在下一帧的位置信息与当前帧的位置信息之间的位置变换转换为绕该关节的父关节的旋转变换。
根据上文对本发明的描述可知,本发明的动态骨骼的实现方法主要包括三个步骤:创建骨骼关节树、计算关节的位置变换、将关节的位置变换转换为父关节的旋转变换。其中,关节骨骼关节树的创建过程为本领域技术人员所公知,这里不再赘述。下面分别就“计算关节的位置变换”、“关节的位置变换转换为父关节的旋转变换”的具体实现做进一步说明。
一、计算关节的位置变换
下面主要从算法的选择、外力的干扰以及碰撞的规避三方面进行说明。
1.1算法的选择
在游戏开发过程中,常常需要控制各种物体进行移动,如人物角色、子弹等等,最为常用的方法便是使用欧拉方法,也叫欧拉折线法,即在每一帧中记录物体的位置与速度,与帧间间隔结合运算来预测下一帧物体的位置,于是物体就“动”起来了。
定义物体当前位置为x,下一步位置为x',当前速度为v,下一步速度为v',加速度为a,质量为m以及所受到的力为F,则有
欧拉方法的几何解析就是将物体的整个移动过程分割为无数个小段,通过迭代式地计算每一段路线,最后将所有这些路线“累加”在一起,以近似的模拟物体的运动轨迹。然而改变物体运动轨迹的力一般都是持续进行的,而不是断续进行的。比如一个受重力影响垂直降落的物体,在下坠的过程中,基速度的变化是平滑递增的,而不是公式所表述的在帧末才考虑速度的变更,这无形中会造成物体运动轨迹的失真。虽然通过降低帧间的绘制间隔可以让速度的变更更为平滑,但跳跃式计算造成的误差还是依然存在。其次,因为物体最新的位置是将之前无数个小段的计算结果的累加,而中间每小段的计算都存在一定的误差,这就导致了最终的计算结果也包含了无数个小段误差的累加,即误差存在放大效应,这进一步造成物体运动轨迹的失真。
在数学和计算机科学中,欧拉方法,是一种解决数值常微分方程的最基本的一阶数值方法,是一种常用于计算非线性动力学的显式求解法(Explicit Method),而显式求解法的缺点就是步长对结果的准确性影响较大,步长越大,准确性越差。
韦尔莱算法是经典力学(牛顿力学)中经典的积分方法,是对牛顿第二定律(运动方程)在计算机上运用的一种数值积分方法。一般情况下,它有三种表述形式:位置积分方程,蛙跳积分方程和速度积分方程,本提案需要使用到的是位置积分方程。与欧拉方法不同,韦尔莱位置积分方程通过物体当前位置和上一步的位置来预测物体下一步的位置,假设物体在第n步的移动加速度为an、移动速度vn、位置xn,时间步长为Δt则有:
假设物体在移动过程中,加速度a和时间步长Δt是固定不变的,结合
有
xn+1=xn+(xn-xn-1)+a*Δt2=2xn-xn-1+a*Δt2
这就是经典的韦尔莱位置积分方程,通过公式可以看出,为求下一步物体所在的位置,需要具备的因子有加速度a、时间步长Δt、当前所在位置xn和上一步所在位置xn-1。显然,在游戏运行过程中,如果加速度是固定的情况下,其他三个因子可以完美地跟游戏的绘制过程结合在一起,即xn为物体当前帧所在的位置,xn-1为物体上一帧所在的位置,Δt为两帧之间的时间差。因为a、xn-1和Δt已知,所以通过改变物体当前帧的位置xn即可对物体的移动轨迹实现控制,这在交互类游戏中很是常见,比如橡皮球掉到地上表面出现收缩后膨胀的表现、风吹动布匹时出现的飘扬舞动的效果,都可以通过方程的运算来模拟。
韦尔莱算法不仅计算效率快(跟欧拉方法一样快),而且其误差等级达到了4阶精度(欧拉方法的误差等级只有1阶精度)。相比之下,使用欧拉方法则“笨拙”得多,物体受力状态如何、当前帧的速度是多少,这些“包袱”都需要一一计算得出,然后再代入到方程求得结果,运算效率因此变得低效。
1.2、外力的干扰
通过上文的分析可知,可以使用韦尔莱算法计算关节在下一帧的位置。其中,关节在运动的过程中一般会受到重力、阻力、干扰力(如风)等力的作用。除此之外,因为每帧对关节的位置都进行偏移运算,所以对关节的长度(即从当前关节到父关节之间的关节臂的长度)也要进行修正处理,以确保在骨骼动作播放过程,每个关节的长度都是一直不变的。当然,有些骨骼动画会带有关节伸缩的需求,但这不在本发明的讨论范围之内。具体的运算过程如下:
1.2.1、重力模拟
由于物体的受重力影响的表现是以坠落加速度的形式体现的。出于简化模型的目的,本提案用一个浮点数来表示关节受重力影响的权重,通常为一个负数。如果关节在下坠过程中受到的空气阻力越大,则权重越小,反之亦然。由于关节之间的长度不变性,因此关节的运动轨迹受重力的影响需要结合力的分解进行分析,如图4所示,一般情况下重力g向量与AB关节向量u是不平行的,因为B关节在运动过程中,其与父关节A的长度保持不变,即u向量的长度不变,因此重力g向量可分解为两个正交向量:对AB运动有贡献的分量垂直于u向量,设为gv,对AB运动无贡献的分量平行于u向量,设为gu。有
g=gu+gv
合并两式,可得
gv即为重力g对关节运动产生影响的部分。出于简化计算的目的,不考虑重力加速度的影响,可以直接将gv作为变化因素并入公式计算之中。
1.2.2、干扰力摸拟
一般情况下,角色所受干扰力主要指来自于风等自然因素的影响,具有随机性,包括随机的方向、随机的力度和随机的持续时间。本发明可以采用噪声来模拟这三个因素。此因素是可选的,如果模型在场景中不受任何干扰力影响,可以忽略。
1.2.3、阻力模拟
每个关节在运动的过程中都会受到阻力的影响,关节的运动幅度随着关节的传递表现得越来越小,阻力的方向与运动的方向相反。为了简化运算,本提案使用一个浮点数来表示受阻力影响下运行幅度的衰减程度,其范围在[0,1]区间,0表示无衰减,即完全不受阻力影响,1表示全衰减,即在阻力的影响下关节运动幅度为零。
假设d为干扰力作用下的加速度,gv为重力在关节的长度方向上的法向方向上的重力分力作用下的加速度,r为阻力作用下的阻力系数,0≤r≤1,结合上面的韦尔莱公式有
posn+1=posn+(posn-posn-1)*(1-r)+(gv+d)*Δt2 (1)
其中,posn+1为关节在下一帧的位置信息,posn为关节在当前帧的位置信息,posn-1为关节在上一帧的位置信息,Δt为上一帧与当前帧之间的时间间隔。posn+1、posn、posn-1、gv、d可以均是矢量,r为标量。
公式(1)为综合了重力、阻力以及干扰力三种外力作用下的位置计算公式,在实际计算中,如果需要忽略某个或某几个作用力,去除公式(1)中相应的参量即可。例如,如果忽略重力的影响,gv的取值为零,此时有posn+1=posn+(posn-posn-1)*(1-r)+d*Δt2。
图5示出了叠加各因素后头发的运动效果图。其中,图中的圆点即为骨骼关节,图5中的四幅图由左到右依次为标准形态(不考虑外力作用下的形态)、叠加重力的形态、进一步叠加干扰力的形态、进一步叠加阻力的形态。
1.2.4、位置修正
可以使用如下第一位置修正公式对计算得到的关节在下一帧的位置信息posn+1进行修正,
其中,pos'n+1为关节经过补偿后在下一帧的位置信息,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。pos'n+1即为每帧中关节在原有速度移动的情况下受各力影响以及进行修正后所处的新位置。
第一位置修正公式中的运算为矢量运算,|posn+1-posp|表示posn+1到posp的距离(欧氏距离),表示posn+1到posp的单位方向向量,表示从父关节的位置向posn+1到posp的方向向量上移动一个关节长度的距离。
1.3、穿透规避
在利用上述公式得到了骨骼关节树中的关节在各种力作用下的实时位置后。考虑到部分关节与外界环境存在交互的可能,而模型顶点随骨骼关节运行过程中,其运行轨迹是在运行过程中实时计算的,有一定的随机性,这就意味着可能出现模型穿透的问题,比如人物在跑动过程中,衣服的飘动穿透了皮肤、头发在人物播放跑动动作会嵌入后背等等,这些都是违背现实世界物体的运动规律的,对视觉体验造成严重的影响。
因此,还需要对关节定义相应的约束碰撞体,进行碰撞规避运算,即在骨骼关节完成位置变换运算后进行穿透规避运算以便对关节位置作出校正。此处可以通过关节上的脚本来指定约束碰撞体,例如可以在脚本上为关节指定一个或多个约束碰撞体。如图6A所示,可以指定模型图中的两只手的上臂与下臂部分为约束碰撞体,图6A中示出的球体即为我们定义的约束碰撞体。
通过以上的定义规划之后,图6A中动画模型的头发在运行状态下,关节的运动轨迹就会一直受到碰撞体影响,约束在一定范围内。由于不同关节的规避需求可能不同,所以每个需要约束的关节均可以定义各自的约束碰撞体。
另外,除使用球体进行碰撞检测外,也可以使用胶囊体作为目标碰撞体。在绑定碰撞体时,对于近似球体或胶囊体的模型部位,我们可以直接分别绑定球形碰撞体或胶囊形碰撞体来定义碰撞区域。而对于无规则形体的部件,可以采用多个球体或胶囊体连接定义的形式来处理。如图6B所示,人体模型的手臂由上手臂与下手臂组成,此时可以通过两个胶囊体连接来定义碰撞区域。
下面分别就球体和球体之间进行碰撞的检测、规避,球体和胶囊体之间进行碰撞的检测、规避进行说明,应该知道,对于其它模型的碰撞也可以参考本发明的方法进行相应的处理,这里不再赘述。
1.3.1、判定球体与球体是否碰撞
对于每个需要检测碰撞的关节,可以通过定义一个球体(包括球心与半径)来指定它的碰撞区域以及它需要检测的其他碰撞体区域(如肢体),也是以球体的形式进行规划。可以根据两个球体半径之和与球心距离的关系,判断它们是否发生碰撞。
如图7所示,假设关节的位置为c1,半径为r1,目标碰撞体位置为c2,半径为r2,关节与目标碰撞体发生碰撞时,两者的距离D=|c1-c2|。
当D=|c1-c2|<r1+r2时,表明关节发生碰撞,需要进行位置校正,方法就是将关节的位置往目标碰撞体的反方向移动,直至满足D=|c1-c2|=r1+r2。
而为了规避碰撞,同时保持关节的长度不变,避免模型伸缩的情况出现,还需要对规避碰撞后的位置进行修正。
因此,在检测到计算得到的关节在下一帧的位置信息与目标碰撞体发生碰撞的情况下,对关节的位置信息进行修正时,需要满足或基本满足以下条件:①、修正后关节位于目标碰撞体的边缘;②、修正后关节到其父关节之间的关节臂的长度不变。
基于上述两个限制条件,可以使用如下第二修正公式对关节的位置进行校正,
其中,pos”n+1为关节进行修正后在下一帧的位置信息,c1为关节修正前在下一帧的位置信息,c2为碰撞体的位置信息,r1为关节的半径,r2为碰撞体的半径,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。
posp、c1、c2可以均为三维向量,公式(2)中的运算可以为矢量运算,|c1-c2|表示c1到c2的距离(欧氏距离),表示c1到c2的单位方向向量,表示从目标碰撞体的圆心出发,以c1-c2为方向,以r1+r2为目标长度进行偏移,由此使得关节位于目标碰撞体的外部边缘,然后基于关节长度len、父关节的位置进一步对其进行修正即可得到上述公式(2)。
由此,利用公式(2)对关节进行修正,可以保证关节长度不变的前提下,沿着目标碰撞体边缘放置关节。通过蒙皮变换后,模型的表面就会按关节的位置“覆盖”在目标碰撞体的边缘上。例如,可以使得人物模型在跑动过程中,头发只会披在后背上或者随风飘动起来,不会出现穿透皮肤的问题。
1.3.2、判定球体与胶囊体是否碰撞
在使用胶囊体作为目标碰撞体时,需要判定球体与胶囊体的碰撞检测。判定两者发生碰撞的主要方法就是将球心往胶囊体的轴进行投影,通过计算投影位置与球心的距离长度是否达到胶囊体半径进行判定。
具体如图8所示,假设球体的球心为C、半径为Rs,胶囊体的两个球心为M、N,半径为Rc,球体球心在胶囊体上的投影点为P,如果P点位于MN之间,则判定DPC=|P-C|<Rs+Rc
如果P点位于MN之外,会有两种情况,靠近M点或靠近N点。如果靠近M点,则判定DMC=|M-C|<Rs+Rc
如果P点靠近N点,同理DNC=|N-C|<Rs+Rc
至此,可以确定球与胶囊体是否发生碰撞。同样,为了实现碰撞规避,需要对球(骨骼关节)进行位置校正,基本方法与上文1.3.1节球体的处理是一样的,这里不再赘述。
在模型的某些部件绑定碰撞体后,动态骨骼关节在模拟运动轨迹时就会计算是否与这些碰撞体发生碰撞,一旦发生碰撞,就会采用上文的规避公式进行位置修正。如图9所示,左图是头发定义碰撞体之前各骨骼关节的形态,它们以顺滑的姿态逐个排列;右图是定义了碰撞体(球体)后各骨骼关节的形态,因受碰撞体影响,整个骨骼链路出现的弯曲,特别是第三个骨骼关节,在对碰撞体进行碰撞规避中,它对骨骼关节的排列的影响是最大的。
最后需要说明的是,穿透规避只在需要约束特定部件的关节运动范围时才需要采用,一般是由美术或策划决定。如果没有这方面的需求,则可以不指定约束碰撞体。
二、旋转变换
2.1、四元数的获取
在得到每个关节在各种力作用以及规避碰撞体的约束下的实时位置后,可以使用这些新的关节位置来控制模型各顶点按前后帧的变换进行移动,以表现出模型的动画效果。
但由于向量的变换插值并不是平滑的,因此可以借助一个数学工具——四元数来实现。四元数通常用来表示3D动画中的旋转变换,其最大的特点就是它表示的变换插值是一个球面线性插值,是平滑的。因此,可以将关节的位置变换转换为父关节的旋转变换,该旋转变换可以由四元数表示。
关于四元数的概念为本领域技术人员所公知,这里不再赘述。下面主要就根据关节的位置变换确定四元数的一种可行的方式进行说明,下面述及的四元数的确定方式仅是一种示例性说明,应该知道,还可以有其它多种确定四元数的方式,这里不再赘述。
具体来说,可以根据关节在当前帧的位置信息,确定从父关节Np到子节点N的当前方向向量为V’,V’可以视为是父关节坐标系下的子关节的朝向向量。其中,这里父关节Np的位置为所确定的父关节Np在下一帧的位置。
根据子关节在下一帧的的位置信息以及当前帧的位置信息,可以确定子关节在其父关节坐标系下的移动向量ΔV。
根据当前方向向量为V’和移动向量ΔV就可以确定四元数。例如可以使用四元数函数Quaternion(V’,ΔV)确定绕父关节进行旋转变换的四元数Rotp。四元数Rotp的旋转轴可以是过父关节的多种方向的旋转轴,优选地,可以是过父关节的垂直于ΔV和V’构成的平面的垂线。
2.1、四元数插值
考虑到某些动作的幅度较大,关节之间的旋转角度在两帧之间也随着变大,为此,可以对旋转进行缓冲过滤,以使得运动关节所对应的动画模型的运动更加柔顺平滑。
因此,可以使用四元数插值算法对四元数进行插值运算,以得到缓冲四元数,然后可以基于缓冲四元数对父关节和子关节进行旋转变换。例如,可以通过四元数插值函数Quaternion.Lerp来获取缓冲四元数DeltaRot:
DeltaRot=Quaternion.Lerp(Quaternion.identity,Rotp)
由于骨骼动画的模型顶点位置由骨骼关节变换决定,因此可以将上面的四元数作为关节的旋转变换分量以完成关节的动画控制,然后以此类推,对模型整棵关节树进行类似的处理,可以完成每帧骨骼关节变换的运算。
通过对四元数进行插值处理,基于插值处理后的四元数所对应的旋转变换控制关节运动可以使得模型的运动更加柔顺平滑。如图10所示,三幅图中最左边的图为未经旋转变换后的形态,中间的图为没有进行插值过滤后旋转变换后的形态,最右边的图为进行差值过滤后再进行旋转变换后的形态,可以看出,经过插值过滤可以使得头发的运动更加柔顺平滑。
2.2、修复关节的绞绕问题
经过关节的旋转变换后,模型在关节的驱动下,逼真地模拟了各种力的作用下的物理运动。但是,由于每一帧关节的位置都是基于前一帧状态进行叠加运算得来,并且最终以旋转变换的形式表示,即四元数。而每一个旋转变换都可能要对关节所在轴向作自转变换,经过一帧又一帧的累加,最终关节的可能形成较大的自转变换,甚至触发万向锁现象,如图11中左边三幅图所示,头发a处的关节虽然朝向正确,但经过一系列动画帧的播放后,累积的误差造成了自转轴分量出现明显的偏差,由于头发a处的关节发生了自转,造成a处的头发随之发生转动,对视觉体验造成严重的影响。
为了解决这个问题,可以为每个关节定义一个旋转约束轴,关节所在的轴向可以作为旋转约束轴的方向。此处关节所在的轴向,可以认为是关节与其父关节构成的轴向方向,例如,假设父关节的位置为P,子关节的位置为A,则PA可以认为是关节所在的轴向。
对于获取的四元数所对应的旋转变换,可以对旋转变换在旋转约束轴的方向上的分量进行过滤,以此去除自转变换部分。例如,可以将获取的四元数转换为欧拉角,然后对欧拉角在关节的轴向(即旋转约束轴的方向)上的分量进行过滤。例如,假设关节的轴向为X轴,可以在关节的局部坐标系下对它的旋转变换对应的欧拉角的X分量进行过滤,即执行:bone.localEuler.x=0。图11中最右边的附图示出了经过过滤后的头发的示意图,如图所示,经过对关节的轴向的分量进行过滤,可以有效修复关节绞绕问题。
至此,详细说明了本发明的动画中动态骨骼的实现方法的具体实现过程。图12、图13是示出了利用本发明进行处理后的效果图。
参见图12,在本测试案例中,圆点为骨骼关节,白色线段为骨骼长度,使用网格视图,图中一个女孩一边拿着皮鞭一边跑动着,跑动过程中,骨骼关节也会随着右手的动作计算关节摆动的幅度并更新皮鞭模型各顶点的位置。
参见图13,在本测试案例中,显示的是在模拟风力影响下头发的摆动效果,图中圆点为骨骼关节,白色线段为骨骼长度,从网格视图可以看到,由于风使用噪声来模拟,具有随机性,所以头发的飘动也是随机的。
图14是示出了根据本发明一实施例的动画中动态骨骼的实现装置的功能框图。其中,实现装置300的功能模块可以由实现本发明原理的硬件、软件或硬件和软件的结合来实现。本领域技术人员可以理解的是,图13所描述的功能模块可以组合起来或者划分成子模块,从而实现上述发明的原理。因此,本文的描述可以支持对本文描述的功能模块的任何可能的组合、或者划分、或者更进一步的限定。
图14所示的实现装置300可以用来执行图1所示的实现方法,下面仅就实现装置300可以具有的功能模块以及各功能模块可以执行的操作做简要说明,对于其中涉及的细节部分可以参见上文结合图1的描述,这里不再赘述。
参见图14,实现装置300包括骨骼关节树创建模块310、计算模块320以及旋转变换模块330。
骨骼关节树创建模块310用于创建针对目标对象的骨骼关节树,其中,骨骼关节树中直接相连的两个关节中更接近根节点的关节为父关节,更远离根关节的关节为子关节;
计算模块320用于计算骨骼关节树中的关节在下一帧的位置信息;
旋转变换模块330用于针对骨骼关节树中的至少一个子关节,将该子关节在下一帧的位置信息与当前帧的位置信息之间的位置变换转换为绕该子关节的父关节的旋转变换,从而通过旋转变换,将子关节移动到其下一帧的位置。
计算模块320可以计算预定作用力下所述骨骼关节树中的关节在下一帧的位置信息,预定作用力包括下列至少一项:重力;关节移动过程中受到的与移动方向相反的阻力;以及来自周围环境的干扰力。
具体地,计算模块320可以使用如下位置计算公式计算关节在下一帧的位置信息posn+1,posn+1=posn+(posn-posn-1)*(1-r)+(gv+d)*Δt2
其中,posn+1为关节在下一帧的位置信息,posn为关节在当前帧的位置信息,posn-1为关节在上一帧的位置信息,r为阻力作用下的阻力系数,0≤r≤1,gv为重力在关节的长度方向上的法向方向上的重力分力作用下的加速度,d为干扰力作用下的加速度,Δt为上一帧与当前帧之间的时间间隔。
如图14所示,作为本发明的一个优选实施例,实现装置300还可以包括第一修正模块340。第一修正模块340用于使用如下第一修正公式对计算得到的关节在下一帧的位置信息posn+1进行修正,
其中,pos'n+1为关节经过补偿后在下一帧的位置信息,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。
如图14所示,作为本发明的一个优选实施例,旋转变换模块330可以包括:当前方向向量确定模块331、移动向量确定模块332以及四元数获取模块333。
当前方向向量确定模块331用于根据子关节在当前帧的的位置信息,确定从父关节到子关节的当前方向向量。
移动向量确定模块332用于根据子关节在下一帧的的位置信息以及当前帧的位置信息,确定子关节在其父关节坐标系下的移动向量。
四元数获取模块333用于根据方向向量和移动向量,获取绕父关节进行旋转变换的四元数。
如图14所示,旋转变换模块330还可以包括插值运算模块334和旋转模块335。
插值运算模块334用于使用四元数插值算法对四元数进行插值运算,以得到缓冲四元数,旋转模块335用于基于缓冲四元数对父关节和子关节进行旋转变换。
作为本发明的一个优选实施例,旋转变换模块330还用于消除旋转变换在子关节与其父关节构成的轴向方向上的分量,通过消除后的旋转变换,将子关节移动到其下一帧的位置。
如图14所示,作为本发明的一个优选实施例,实现装置300还可以包括第二修正模块350。第二修正模块350用于在检测到计算得到的关节在下一帧的位置信息与目标碰撞体发生碰撞的情况下,对关节的位置信息进行修正,以使得修正后关节在下一帧的位置信息基本满足以下条件:修正后关节位于目标碰撞体的边缘;修正后关节到其父关节之间的关节臂的长度不变。
具体地,第二修正模块350可以使用如下第二修正公式对关节的位置进行修正:
其中,pos”n+1为关节进行修正后在下一帧的位置信息,c1为关节修正前在下一帧的位置信息,c2为碰撞体的位置信息,r1为关节的半径,r2为碰撞体的半径,posp为关节的父关节的位置信息,len为关节到其父关节之间的关节臂的长度。
上文中已经参考附图详细描述了根据本发明的动画中动态骨骼的实现方法和实现装置。
此外,根据本发明的方法还可以实现为一种计算机程序,该计算机程序包括用于执行本发明的上述方法中限定的上述各步骤的计算机程序代码指令。或者,根据本发明的方法还可以实现为一种计算机程序产品,该计算机程序产品包括计算机可读介质,在该计算机可读介质上存储有用于执行本发明的上述方法中限定的上述功能的计算机程序。本领域技术人员还将明白的是,结合这里的公开所描述的各种示例性逻辑块、模块、电路和算法步骤可以被实现为电子硬件、计算机软件或两者的组合。
附图中的流程图和框图显示了根据本发明的多个实施例的系统和方法的可能实现的体系架构、功能和操作。在这点上,流程图或框图中的每个方框可以代表一个模块、程序段或代码的一部分,所述模块、程序段或代码的一部分包含一个或多个用于实现规定的逻辑功能的可执行指令。也应当注意,在有些作为替换的实现中,方框中所标记的功能也可以以不同于附图中所标记的顺序发生。例如,两个连续的方框实际上可以基本并行地执行,它们有时也可以按相反的顺序执行,这依所涉及的功能而定。也要注意的是,框图和/或流程图中的每个方框、以及框图和/或流程图中的方框的组合,可以用执行规定的功能或操作的专用的基于硬件的系统来实现,或者可以用专用硬件与计算机指令的组合来实现。
以上已经描述了本发明的各实施例,上述说明是示例性的,并非穷尽性的,并且也不限于所披露的各实施例。在不偏离所说明的各实施例的范围和精神的情况下,对于本技术领域的普通技术人员来说许多修改和变更都是显而易见的。本文中所用术语的选择,旨在最好地解释各实施例的原理、实际应用或对市场中的技术的改进,或者使本技术领域的其它普通技术人员能理解本文披露的各实施例。