使用三次贝塞尔函数的自定义动画

时间:2015-12-24 16:48:45

标签: c animation math bezier camediatiming

我正在尝试创建一个具有相同动画曲线的自定义动画,就像我使用CAMediaTimingFunction 一样(我正在使用OpenGL进行动画,所以我无法使用它)。我也希望远离UIKit,因为我希望它尽可能多平台。

CAMediaTimingFunction使用立方贝塞尔函数计算从已经过去的时间开始的动画进度。我不知道它是怎么做到的。

根据我的理解,三次贝塞尔函数是参数化定义的,当你试图从它们推导出一个笛卡尔方程时它会变得混乱。

要明确:我想要一个采用x值输入并沿着三次贝塞尔曲线返回y值输出的方法。控制点将被限制在(0,0)到(1,1)。

我计划做的是为每个点使用以下函数两次中的参数方程为贝塞尔曲线生成一个点(例如100)(一次为x ,一次用于y),使用t0的{​​{1}}的100个值

1

这是static inline CGFloat bezierFunc1D(CGFloat t, CGFloat p0, CGFloat p1, CGFloat p2, CGFloat p3) { return (1-t)*(1-t)*(1-t) * p0 + 3 * (1-t)*(1-t) * t * p1 + 3 * (1-t) * t*t * p2 + t*t*t * p3; } p0是控制点的位置,p3是从t0的参数标量。我可以通过预先计算1的平方和立方值来相当容易地优化它。

然后我将使用线性插值来生成一个点数组,其中t的值是线性分离的(例如x),然后使用此数组来定义我的动画进度时间过去了。

这是解决此问题的最佳方法吗?对于相当简单的任务来说,这似乎是一个相当密集的过程,即使它可以在发布时预先计算。

我在this question上看到,回答者建议简单地删除x = 0.01, 0.02... 0.99并将该功能定义为x y但是,这会产生非常不准确的结果,因为从t0.0的线性贝塞尔曲线不会线性动画。

对此有更有效的方法吗?

有没有人知道Apple如何在1.0中实现这一目标,或者是否有一个库可以达到相同的效果?

或者是否有更简单的替代方法可以使用立方贝塞尔函数在动画的输入和输出阶段提供平滑的动画曲线?

1 个答案:

答案 0 :(得分:2)

这就是Apple如何在WebKit中对CSS等效的CAMediaTimingFunction进行采样。感兴趣的功能是double solve(double x, double epsilon),它会返回y的{​​{1}}。

x ± epsilon

来源:https://github.com/WebKit/webkit/blob/67985c34ffc405f69995e8a35f9c38618625c403/Source/WebCore/platform/graphics/UnitBezier.h