贝塞尔曲线
2014-09-03 01:46
183 查看
贝塞尔曲线
一.相遇Bezier曲线
在写这篇文章的时候,我正在广州一家游戏公司从事客户端的研发工作,使用Cocos2dx引擎。在游戏的开发过程中,有时候需要让对象沿着一条光滑的曲线运动,比如说怒气粒子沿着光滑的曲线运动到UI层的指定怒气槽。关于曲线的实现,直接调用Cocos2dx引擎中类CCBezierBy的API接口:staticCCBezierBy* create(float t, const ccBezierConfig& c)
该接口需要曲线运动的时间t以及贝塞尔曲线的结构为ccBezierConfig的参数c.
引擎中ccBezierConfig定义如下:
/** @typedef bezier configuration structure */ typedef struct _ccBezierConfig { //! end position of the bezier CCPoint endPosition; //! Bezier control point 1 CCPoint controlPoint_1; //! Bezier control point 2 CCPoint controlPoint_2; } ccBezierConfig;
简而言之,ccBezierConfig结构定义了三阶贝塞尔曲线的4个控制点: 起点(0,0), 控制点controlPoint_1, controlPoint_2和结束点endPosition.(当然,其中(0,0)点是隐藏知识)
转到其update函数中看看:
void CCBezierBy::update(float time) { if (m_pTarget) { float xa = 0; float xb = m_sConfig.controlPoint_1.x; float xc = m_sConfig.controlPoint_2.x; float xd = m_sConfig.endPosition.x; float ya = 0; float yb = m_sConfig.controlPoint_1.y; float yc = m_sConfig.controlPoint_2.y; float yd = m_sConfig.endPosition.y; float x = bezierat(xa, xb, xc, xd, time); float y = bezierat(ya, yb, yc, yd, time); #if CC_ENABLE_STACKABLE_ACTIONS CCPoint currentPos = m_pTarget->getPosition(); CCPoint diff = ccpSub(currentPos, m_previousPosition); m_startPosition = ccpAdd( m_startPosition, diff); CCPoint newPos = ccpAdd( m_startPosition, ccp(x,y)); m_pTarget->setPosition(newPos); m_previousPosition = newPos; #else m_pTarget->setPosition(ccpAdd( m_startPosition, ccp(x,y))); #endif // !CC_ENABLE_STACKABLE_ACTIONS } }
可以看出,在知道了4个点p0, p1, p2, p3后,贝塞尔曲线在各个维度上的计算公式由bezierat(p0, p1, p2, p3)给出.
转到实现,其实现细节如下:
// Bezier cubic formula: // ((1 - t) + t)3 = 1 // Expands to… // (1 - t)3 + 3t(1-t)2 + 3t2(1 - t) + t3 = 1 static inline float bezierat( float a, float b, float c, float d, float t ) { return (powf(1-t,3) * a + 3*t*(powf(1-t,2))*b + 3*powf(t,2)*(1-t)*c + powf(t,3)*d ); }
好,这就是和Bezier曲线的正式相遇,到现在,只知道了所谓的3阶Bezier曲线的一个应用,那么,它究竟是什么样的一条曲线?
二.贝塞尔曲线初探
为了给对函数不太理解的朋友一些入门, 我这里用一个例子描述一下接下来内容所要表达的意思:接下来的内容, 要做的事情就是:假定贝塞尔曲线的表达式是y=f(u),0≤u≤1, 其表达式是怎么样的?
举个例子: 我们都知道抛物线的表达式是
y=f(x)=ax^2 + bx + c (a≠0) 也就是说,给定一个x值, 就确定了一点(x,[b]ax^2 + bx + c)[/b]
于是,当x取遍R上的每一个值,那么函数也就确定了其每一点, 其图像因此确定.
那么你懂了这个以后, 接下来的工作内容为,给定一个u, 请确定Bezier曲线上的一点(u, Bezier(u))
也就是确定y = Bezier(u)
[b]0≤u≤1的函数解析式.[/b]
1.de Casteljau's 算法
根据Bezier曲线的结构,一个重要的任务是:对于给定的u,0≤u≤1,如何确定贝塞尔曲线上的一点Bezier(u) ?1.1 线段u分点
从A点出发,B为终点的向量为B-A, 假若u是0~1之间的一个数,那么u*(B-A)是向量B-A的u倍,加上起点A,那么向量 A+u(B-A)确定了点C, 且它分线段AB的比例为u:(1-u).由于C=A+u(B-A)=(1-u)A + uB,我们称:
线段AB的u分点C的表达式为 C=(1-u)A + uB
1.2 de Casteljau's 算法
n阶贝塞尔曲线有n+1个控制点.当n=1时, 也就是贝塞尔曲线只由两个点P0, P1决定,直接取线段u分点,得到Bezier(u)=(1-u)P0 + uP1, 于是1阶Bezier曲线就是连接P0和P1的线段.
当n=2时,贝塞尔曲线由三个点P0,P1,P2决定,
先对P0和P1取线段u分点,
得到P10 = (1-u)P0 + uP1,
再对P1和P2取线段u分点,
得到P11 =(1-u)P1 + uP2,
于是得到两条线段上的两个u分点P10和[b]P11[/b],
对于两个u分点P10和P11, 再取线段u分点,
得到P20 = (1-u)P10 + uP11
= (1-u)((1-u)P0 + uP1) + u((1-u)P1
+ uP2)=(1-u)^2P0 + 2(1-u)uP1
+ u^2P2
而P20即为贝塞尔曲线在u时的点;
即: Bezier(u) = (1-u)^2P0
+ 2(1-u)uP1 + u^2P2
当n时, 贝塞尔曲线由n+1个点P0, P1,P2, ..., Pn决定.
分别对线段P0P1, P1P2, ..., Pn-1Pn取线段u分点, 得到n个点P10,
P11, ... P1n-1
分别对线段P10P11,
... P1n-2P1n-1取线段u分点,
得到n-1个点P20, P21, ... P2n-2
......
分别对Pn-10Pn-11取线段u分点,
得到最后1个点Pn0. 这个点即为Bezier曲线在给定u时的点.
此过程可以由递归式:
表示.
而我们所求即为i=n, j=0时的值:
(此公式可以应用数学归纳法并利用递推公式证明)
至此, 在Coco2dx引擎中关于Bezier曲线的计算方法,就很明朗了, 它就是3阶的贝塞尔曲线:
其系数恰是3阶二项展开式的系数.
二.Bezier曲线的性质
2.1 系数性质
Bezier曲线其系数为下面的二项展开式第K项的系数:因此二项式系数拥有的性质,它都有,包括但不限于[权性: 系数和为1].
2.2 曲线性质
2.2.1对称性
Bezier曲线的全部控制顶点位置不变,但次序颠倒,那么其曲线形状不变,参数u变为1-u.即
2.2.2仿射不变性
即对于贝塞尔曲线做任意的仿射变换A, 可以将A作用在各个控制顶点上后再线性求和.这点重要的性质, 意味着对Bezier曲线做几何变换是极其便利的.
举个例子, 当一个物体a在某个坐标系内做贝塞尔曲线运动, 而这个坐标系同时在做一个旋转运动,那么,如果旋转变换如果为R(theta), 那么该旋转变换可以相应作用在控制定点上;
2.2.3其他
略.三.以下是参考的资料:
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html相关文章推荐
- OGER SDK研究之一 Demo_BezierPath (贝塞尔曲线平滑补丁)
- Flash/Flex学习笔记(20):贝塞尔曲线
- 曲线之美(一)贝塞尔曲线
- 数学之美--贝塞尔曲线
- 贝塞尔曲线
- Win32 绘图基础 -- 绘制直线、边框、贝塞尔曲线、填充、裁剪
- 贝塞尔曲线,以及用鼠标和贝塞尔曲线交互
- C++ 生成三次贝塞尔曲线
- 匀速贝塞尔曲线运动(续)
- 贝塞尔曲线.简单推导与用opengl实现动态画出。
- 写点贝塞尔曲线
- cocos2d-x 贝塞尔曲线的简单运用(CCBezierTo,CCBezierBy)
- CSS3 timing-function 贝塞尔曲线
- iOS开发之画图板(贝塞尔曲线)
- 2014-11-8Android学习------Android 仿真翻页效果实现原理学习--------贝塞尔曲线(三)
- 关于cocos2d-x中的一些动作的简单使用(淡入淡出,贝塞尔曲线等)
- CSS3 贝塞尔曲线实现
- IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
- IOS用CGContextRef画各种图形(文字、圆、直线、弧线、矩形、扇形、椭圆、三角形、圆角矩形、贝塞尔曲线、图片)
- 贝塞尔曲线 (Bézier curve) 理论及绘制方法