今天发现一个问题。
在一个粒子中,模拟一根棍子的弯曲参数,但是这根棍子会自己移动,且移动动画是外部指定的。模拟之后,播放动画发现,网格与模拟结果(用线框显示)不重合。
产生这种现象的原因在于maya的节点求值机制。
在模拟过程中,是不断进行以下步骤:
1. maya自动对节点网络求值。包括粒子系统状态更新,动力学系统模拟
2. 进行有限元模拟,算出网格顶点的位置、速度、加速度等结果
3. 把结果写入下一帧
4. 跳到下一帧
结果要写入下一帧的原因是:要保证maya内建的动力学系统在模拟时和播放模拟结果时都有相同的结果。
做到这一点是十分重要的,因为若一个粒子在模拟过程的某时刻碰到有限元棍子,而在播放过程的相同时刻还未碰到,则会出现棍子在粒子未碰到时便提前变速的现象。这对效果的影响是很大的。
由于maya内建动力学系统的求值过程先于有限元模拟过程(见上述步骤),所以若要保持结果相同,在第i帧,动力学系统在模拟时和在播放结果时必须获得相同的输入。所以模拟结果必须写入下一帧。
但是,rig系统的特性会导致一个问题,这个特性是:rig网格的顶点位置是由
1. 模拟参数p
2. 外部参数p0 (例如用户设置的关键帧)
共同决定的。
在此条件下,第i帧的模拟结果(q、v、a、p等)是针对这一帧的外在参数p0的。而在i+1帧,这些外在参数已经发生变化。于是,上图中线框显示的有限元网格(记录了第i帧的模拟结果)与maya根据第i帧参数p[i]与第i+1帧的外在参数p0[i+1]算出来的网格,便会存在明显的差异。
这样的一个直接后果是,由于第i帧的外力(例如,场的力)依赖于模拟结果的顶点位置,所以外力的大小会有误差。
一个解决办法是,在模拟之前,更新上一帧传过来模拟结果。具体是用模拟出的参数值,算出此时的新位置、新速度、新加速度,并修改RigStatus状态变量的模拟结果。