目的
了解Bezier Curve(贝塞尔曲线)的计算方式
本章实现效果如下
贝塞尔曲线是最基本的一种曲线,通常用于计算机图行和图像的处理。可被用来创建平滑弯曲的道路,如同祖玛游戏中弯曲的道路,蜿蜒的河流一样。
通过设置一组从 P0到Pn的点来定义一条贝塞尔曲线,其中n表示曲线的序列点(n=1时为一次,n=2时为二次)。第一个和最后一个点通常是曲线的结束点。如果在两个点之间有控制点的话,控制点通常并不在曲线路径上。
贝塞尔函数在贝塞尔曲线上返回点,以线性插值的概念作为基础。因此,我们首先理解什么是线性插值。
P = P 0 + t ( P 1 − P 0 ) , 0 < = t < = 1 P=P_0+t(P_1-P_0),0<=t<=1 P=P0+t(P1−P0),0<=t<=1
为了能够得到插值点,根据两个点之间的距离进行时间t的积分:
当t=0时,P=P0
当t=1时,P=P1
当t=0.5时,P=(P1-P0)/2
B ( t ) = P 0 + t ∗ ( P 1 − P 0 ) = ( 1 − t ) ∗ P 0 + t ∗ P 1 , 0 < = t < = 1 B(t)=P_0+t*(P_1-P_0)=(1-t)*P_0+t*P_1,0<=t<=1 B(t)=P0+t∗(P1−P0)=(1−t)∗P0+t∗P1,0<=t<=1
B ( t ) = ( 1 − t ) ∗ B p 0 , p 1 ( t ) + t ∗ B p 1 , p 2 ( t ) ; 0 < = t < = 1 B(t)=(1-t)*Bp0,p1(t)+t*Bp1,p2(t);0<=t<=1 B(t)=(1−t)∗Bp0,p1(t)+t∗Bp1,p2(t);0<=t<=1
B ( t ) = ( 1 − t ) [ ( 1 − t ) P 0 + t P 1 ] + t ∗ [ ( 1 − t ) P 1 + t P 2 ] ; 0 < = t < = 1 B(t)=(1-t)[(1-t)P0+tP1]+t*[(1-t)P1+tP2];0<=t<=1 B(t)=(1−t)[(1−t)P0+tP1]+t∗[(1−t)P1+tP2];0<=t<=1
B ( t ) = ( 1 − t ) 2 P 0 + 2 ( 1 − t ) ∗ P 1 ∗ t + t 2 ∗ p 2 ; 0 < = t < = 1 B(t)=(1-t)^2P0+2(1-t)*P1*t+t^2*p2; 0<=t<=1 B(t)=(1−t)2P0+2(1−t)∗P1∗t+t2∗p2;0<=t<=1
B ( t ) = ( 1 − t ) ∗ B p 0 , p 1 , p 2 ( t ) + t ∗ B p 1 , p 2 , p 3 ( t ) ; 0 < = t < = 1 B(t)=(1-t)*Bp0,p1,p2(t)+t*Bp1,p2,p3(t);0<=t<=1 B(t)=(1−t)∗Bp0,p1,p2(t)+t∗Bp1,p2,p3(t);0<=t<=1
B ( t ) = ( 1 − t ) [ ( 1 − t ) 2 ∗ P 0 + 2 ( 1 − t ) ∗ P 1 + t 2 ∗ P 2 ] + t ∗ [ ( 1 − t ) 2 P 1 + 2 ∗ ( 1 − t ) t ∗ P 2 + t 2 P 3 ] ; 0 < = t < = 1 B(t)=(1-t)[(1-t)^2*P0+2(1-t)*P1+t^2*P2]+t*[(1-t)^2P1+2*(1-t)t*P2+t^2P3];0<=t<=1 B(t)=(1−t)[(1−t)2∗P0+2(1−t)∗P1+t2∗P2]+t∗[(1−t)2P1+2∗(1−t)t∗P2+t2P3];0<=t<=1
B ( t ) = ( 1 − t ) 3 ∗ P 0 + 3 ( 1 − t ) 2 ∗ t ∗ p 1 + 3 ∗ ( 1 − t ) ∗ t 2 P 2 + t 3 ∗ P 3 ; 0 < = t < = 1 B(t)=(1-t)^3*P0+3(1-t)^2*t*p1+3*(1-t)*t^2P2+t^3*P3;0<=t<=1 B(t)=(1−t)3∗P0+3(1−t)2∗t∗p1+3∗(1−t)∗t2P2+t3∗P3;0<=t<=1
三次贝塞尔曲线的计算过程动画演示效果如下:
因此,通常根据n来定义贝塞尔曲线的维度;度数为n的贝塞尔曲线可以通过度数为n-1的两条贝塞尔曲线之间点对点的插值获得。
大多数的应用程序中,贝塞尔曲线的使用很频繁。通常情况下,你可能使用较高维度的贝塞尔函数来处理较为复杂的曲线,但是这种做法通常会更加复杂并且会增加计算开销。面对这种情况,我们可以多次使用二次或者三次贝塞尔函数来替代使用高纬度的贝塞尔曲线。在这个Demo中,创建了一个∞形状的曲线,在循环中使用两次三次贝塞尔曲线来完成如下所示的效果:
核心代码如下所示:
依据以下公式:
B ( t ) = ( 1 − t ) 3 ∗ P 0 + 3 ( 1 − t ) 2 ∗ t ∗ p 1 + 3 ∗ ( 1 − t ) ∗ t 2 P 2 + t 3 ∗ P 3 ; 0 < = t < = 1 B(t)=(1-t)^3*P0+3(1-t)^2*t*p1+3*(1-t)*t^2P2+t^3*P3;0<=t<=1 B(t)=(1−t)3∗P0+3(1−t)2∗t∗p1+3∗(1−t)∗t2P2+t3∗P3;0<=t<=1
Vector3 CalculateCubicBezierPoint (float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) {
float u = 1 - t;
float tt = t * t;
float uu = u * u;
float uuu = uu * u;
float ttt = tt * t;
Vector3 p = uuu * p0;
p += 3 * uu * t * p1;
p += 3 * u * tt * p2;
p += ttt * p3;
return p;
}
获取Demo:
扫码关注->历史消息->当前文章末尾->Demo地址:
翻译自:
http://www.theappguruz.com/blog/bezier-curve-in-games