目的
了解Bezier Curve(贝塞尔曲线)的计算方式
预览
本章实现效果如下
![](http://www.theappguruz.com/app/uploads/2015/07/bezier_animation.gif)
简介
贝塞尔曲线是最基本的一种曲线,通常用于计算机图行和图像的处理。可被用来创建平滑弯曲的道路,如同祖玛游戏中弯曲的道路,蜿蜒的河流一样。
通过设置一组从 P0到Pn的点来定义一条贝塞尔曲线,其中n表示曲线的序列点(n=1时为一次,n=2时为二次)。第一个和最后一个点通常是曲线的结束点。如果在两个点之间有控制点的话,控制点通常并不在曲线路径上。
- 贝塞尔曲线包含两个控制点(即n=2)的贝塞尔曲线称之为线性贝塞尔曲线
- 贝塞尔曲线包含三个控制点(即n=3)的贝塞尔曲线称之为二次贝塞尔曲线
- 贝塞尔曲线包含四个控制的(即n=4)得贝塞尔曲线称之为立方贝塞尔曲线
贝塞尔函数在贝塞尔曲线上返回点,以线性插值的概念作为基础。因此,我们首先理解什么是线性插值。
线性插值
- 线性插值是介于两个点之间在不同的t时间点获得得一个值,其中0<t<1,Unity3D中的Mathf.Lerp()函数就是基于此。
其公式为:
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
线性贝塞尔曲线
- 线性贝塞尔曲线有两个控制点,分别为P0和P1,线性贝塞尔曲线即为介于两个控制点之间的一条直线。该曲线相当于线性插值,其实现公式如下:
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
- 线性贝塞尔曲线的计算过程动画演示效果如下:
二次贝塞尔曲线
- 二次贝塞尔曲线有三个控制点,二次贝塞尔曲线是两个线性贝塞尔曲线点对点插值的结果。对于给定的三个点P0、P1、P2,二次贝塞尔曲线是两个点之间的插值,即P0到P1之间的线性插值和P1到P2之间的线性插值;因此,二次贝塞尔曲线的计算公式如下:
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
- 二次贝塞尔曲线的计算过程动画演示效果如下:
三次贝塞尔曲线
- 三次贝塞尔曲线有四个控制点;三次贝塞尔曲线是一系列介于两个二次贝塞尔的点对点的插值。对于给定的四个点P0,P1,P2,P3,三次贝塞尔曲线是两个点之间的线性插值,即P0,P1,P2之间的二次贝塞尔曲线和P1,P2,P3之间的二次贝塞尔曲线;因此,三次贝塞尔曲线的计算公式如下:
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
大多数的应用程序中,贝塞尔曲线的使用很频繁。通常情况下,你可能使用较高维度的贝塞尔函数来处理较为复杂的曲线,但是这种做法通常会更加复杂并且会增加计算开销。面对这种情况,我们可以多次使用二次或者三次贝塞尔函数来替代使用高纬度的贝塞尔曲线。在这个Demo中,创建了一个∞形状的曲线,在循环中使用两次三次贝塞尔曲线来完成如下所示的效果:
![](http://www.theappguruz.com/app/uploads/2015/07/cubic-bezier-function-demo.png)
核心代码如下所示:
依据以下公式:
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地址:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190311151842918.jpg)
翻译自: