问题

问题的来源是我想导出一个布料的顶点动画,并让他循环播放。

houdini导出 houdini导出动画_houdini


但问题是,直接模拟出的结果不能保证在我想导出那一段的首帧与末帧一致,这样动画是不循环的,连续播放会看到明显的跳变。我在这里找到了一种简单又直接的方法:

houdini导出 houdini导出动画_houdini导出_02

它的思路很简单:让最末几帧逐渐接近首帧(即逐渐插值到首帧)。
数学化表示的话,就是设定一个 过渡帧数,则:
houdini导出 houdini导出动画_动画_03

其中:lerp 就是插值函数,alpha 是系数,其值为:
houdini导出 houdini导出动画_动画_04

这样,可以保证末帧一定和首帧一样,而在末帧之前的过渡帧数内会逐渐接近首帧。

节点实现

首先,我创建了一个文件夹节点用来封装操作并暴露出接口:

houdini导出 houdini导出动画_动画_05


其中 start 代表首帧,end 代表末帧,transition 代表过渡帧数。在此节点内部,创建一个 Time Shift 节点,用来获取首帧的状态:

houdini导出 houdini导出动画_循环播放_06

最后,就可以创建一个针对于Point的 Attribute Wrangle 节点用来做lerp运算了。

houdini导出 houdini导出动画_houdini导出_07


它的vex代码如下:

int transition = chi("../transition");//过渡帧数
int d = chi("../end") - @Frame;//当前帧到末尾的距离
float alpha = 1.0 - 1.0*d/transition;//插值系数
alpha = clamp(alpha,0,1);//夹定在0到1之间
@P = lerp(@P,@opinput1_P,alpha);

其中的@opinput1_P是个缩略的写法,即获取1号输入(即第二个引脚所连接的输入节点,这里是 shape_of_start)的P属性(即位置)。

效果

houdini导出 houdini导出动画_houdini导出_08

可以看到 90 帧与 130 帧的内容一样,循环播放是没有跳变的。

注意

  • 为了降低过渡的瑕疵,截取动画的部分本来就应该有循环的倾向。
  • “过渡帧数”的最佳值应该经过多次尝试判断出。

另外,这种简单的方法虽然比较直接,但是也有些粗暴。也许在比较复杂的场合中效果不会理想,之后如有机会可以做更多的尝试。