贝塞尔曲线应用

Draw a Smooth Curve through a Set of 2D Points with Bezier Primitives

cflw_cpp/cflw代码库/cflw图形_d2d助手.cpp

How to draw a smooth curve through a set of 2D points with Bezier methods?

bw2009/bwchart/bezier.cpp/GetCurveControlPoints

求高手解答 贝塞尔曲线问题
①在动画控制中,一般使用三次贝塞尔曲线控制动画的“完成度”而不是“运动速度”,我相信楼主问的也是用贝塞尔曲线控制动画“完成度”的问题;

beziel.png

上图是我做贝塞尔曲线编辑器。在一般的动画完成度编辑器中,x轴代表的是时间完成度,y轴代表动画完成度,x和y都在[0, 1]区间内。当x=1时,y=1,y值代表的并不是“运动速度”。

②贝塞尔曲线中除了有已知的4个坐标点,还有3个可变参数: t,x,y。其中t代表曲线的完成度(1%-100%),t对应一个或者多个(x, y)坐标点(因为4个已知坐标点被控制在了一定区间内,所以贝塞尔曲线编辑器中t仅仅对应一个(x, y)坐标);

③在已知t的情况下求解x和y是很容易的,但是已知x求y是非常困难的

④正面去求值很困难,那就需要换一种方式去近似地去求值了(后面附代码)。

**值得一提的是,Cocos2d-x中有贝塞尔曲线控制动画完成度的类,但实际上这个功能的实现却是错误的。**
**在CCTweenFunction.cpp中的bezieratFunction中可以看到在求解动作完成度y时错误地把x当做了t。**
**所有x坐标值都完全不参与计算过程**。
但由于在这种情况下t和y是正相关的,和x也是正相关的,所以也很难看出来动画有什么问题

两个解决方案
**1.使用CCActionEase.cpp的EaseBezierAction类糊弄过去;**
**2.自己求解贝塞尔曲线来控制动画的完成度**:首先需要采样,假设采样步长是0.1,那么t = 0.1、0.2、0.3… 的条件下求解x和y的值,设为x1,y1,x2,y2,x3,y3…;然后进行线性插值,已知目前的时间完成度x,可以求解出x所在的区间[xn, xn+1],y的值就在[yn, yn+1]之间,线性插值就可以得到近似结果。Lua版本的代码如附件,只有求解贝塞尔曲线的部分,具体的动画控制需要再编码完成。
[BezierCurve.zip](https://forum.cocos.org/uploads/default/original/2X/f/f23340efec3019edf20b644d121c06370634dd6a.zip) (1.2 KB)

三阶贝塞尔曲线,控制点水平坐标等分,且Y值和对应的固定点一致时

Pbezier=P0⋅(1−t)3+3P1⋅(1−t)2⋅t+3P2⋅(1−t)⋅t2+P3⋅t3 //(t2 t3是t的2次和3次的意思)
假如 四个点分别是(0.0, 1.0), (d, 1.0), (1.0 - d, 0.0),和(1.0, 0.0) =>
Pbezier=((3t−9t2+6t3)⋅d+3t2−2t3,1−3t2+2t3)
  • 贝塞尔曲线可以拟合到smoothstep函数的形式

参考:在Unity的UI中绘制等宽的贝赛尔曲线
证明:

[https://www.desmos.com/calculator/fxgwaxa0l7?lang=zh-CN](https://www.desmos.com/calculator/fxgwaxa0l7?lang=zh-CN)

[https://www.desmos.com/calculator/wwwz88ko1r?lang=zh-CN](https://www.desmos.com/calculator/wwwz88ko1r?lang=zh-CN)

Pbezier=P0⋅(1−t)3+3P1⋅(1−t)2⋅t+3P2⋅(1−t)⋅t2+P3⋅t3 //(t2 t3是t的2次和3次的意思)

(0.0,0.0), (d, 0.0), (1.0 - d, 1.0),和(1.0, 1.0)

3d⋅(1−t)2⋅t + 3(1.0 - d)⋅(1−t)⋅t2 + t3

3dt-6dt2 + 3dt3 + 3(1.0 - d)t2 - 3(1.0 - d)t3 + t3

3d-3+3d+1 6d-2 t3

-6d +3-3d -9d +3 t2

3dt

当d= 1/3,x = t;

3⋅(1−t)⋅t2+t3 = 3t2 - 2t3
得证
  • smoothstep在变速曲线里的应用


    曲线变速.jpeg

曲线变速.jpeg

公式调试网站:
https://www.desmos.com/calculator/sqppsdisl8?lang=zh-CN
f(x)为smoothstep函数
Q(x) 为变速进度函数。X轴为播放变速后视频的时间,Y轴表示变速进度;
Z(x) 为初始速度为0.1,结束速度为0.9的瞬时速度函数。 X轴为播放变速后视频的时间,Y轴表示此时刻的瞬时速度;
F(x) 为Z(x)函数的积分,表示当前播放的长度。 X轴为播放变速后视频的时间,Y轴表示此时刻播到了原视频的第几秒;
R为定积分的减法形式。表示当前时间段内播放了多少秒

上面的网站也可以直接画控制点。如把以下控制点直接粘贴,就可以直观看出是怎样的一系列贝塞尔曲线:

 (0.0000000000,0.1000000000)
 (0.0000000000,0.1000000000)
 (1.6572717167,0.1000000000)
 (4.9718151501,7.0900000000)
 (3.3145434334,7.0900000000)
 (7.8372575211,7.0900000000)
 (13.5681422632,0.6000000000)
 (10.7026998922,0.6000000000)
 (14.5202490657,0.6000000000)
 (16.4244626706,0.5900000000)
 (15.4723566895,0.5900000000)
 (16.4244626706,0.5900000000)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容