Bézier曲线专题

Computer Graphics, Animaition, OpenGL, DirectX, OpenCL
头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

Bézier曲线专题

帖子 #1 523066680 » 2016年12月07日 10:02

编辑:523066680
代码:523066680

首先是求一条直线上的均匀分布的点

    1. void PointOnLine(float *A, float *B, float t, float *vtx )
    2. {
    3.     vtx[0] = (B[0] - A[0]) * t + A[0];
    4.     vtx[1] = (B[1] - A[1]) * t + A[1];
    5. }

    比方说从起点到末点取10个点(分9段):

    Code: [全选] [展开/收缩] [Download] (Untitled.cpp)
    1. float a[2] = {-200.0, 0.0  };
    2. float b[2] = { 200.0, 200.0};
    3. float parts = 9.0;
    4. float vtx[2];
    5.  
    6. for (float step = 0.0; step <= parts; step += 1.0 )
    7. {
    8.     t = step / parts;             //进度 t
    9.     PointOnLine( a, b, t, vtx );  //计算坐标保存到vtx
    10.     DrawPoint( vtx );             //画点
    11. }

    样图:加了颜色

    Line.png
    Line.png (1.55 KiB) 查看 833 次
    Line.png
    Line.png (1.55 KiB) 查看 833 次
二次 Bézier 曲线

    在画线(L1)的基础上,增加一个连接点,形成第二条直线L2,连接两个线段某个进度(t)上的点L1(t), L2(t),到线段L3,
    然后在 L3 上面取进度(t)的点,t 从 0.0 到 1.0, L3(t) 上的点的集合即为 2次 Bezier 曲线 上的点(还是看动图吧)。

    1. float a[2] = {-100.0, 0.0  };
    2. float b[2] = {   0.0, 100.0};
    3. float c[2] = { 100.0, 0.0  };
    4. float parts = 9.0;
    5. float pt_on_ab[2];
    6. float pt_on_bc[2];
    7. float vtx[2];
    8.  
    9. glBegin(GL_POINTS);
    10. for (float step = 0.0; step <= parts; step += 1.0 )
    11. {
    12.     t = step / parts;
    13.     glColor3f(1.0-t, t, 0.0);
    14.     PointOnLine( a, b, t, pt_on_ab );           // ab线段 上指定进度(t)的点 1
    15.     PointOnLine( b, c, t, pt_on_bc );           // bc线段 上指定进度(t)的点 2
    16.     PointOnLine( pt_on_ab, pt_on_bc, t, vtx );  // 求出点1点2 直线上指定进度(t)的点
    17.     glVertex2fv( vtx );
    18. }
    19. glEnd();


    QuadraticCurve.png
    QuadraticCurve.png (1.03 KiB) 查看 839 次
    QuadraticCurve.png
    QuadraticCurve.png (1.03 KiB) 查看 839 次

    做个动态的演示,其实一切都是在直线上生成的点:

    QuadBezier.gif
    QuadBezier.gif (97.24 KiB) 查看 835 次
    QuadBezier.gif
    QuadBezier.gif (97.24 KiB) 查看 835 次

三次 Bézier 曲线

    还是在上一次的基础上,增加一个控制点/坐标,用abcd已经不合适了,改用数组,v1 v2 v3 表示顶点的层次
    Code: [全选] [展开/收缩] [Download] (Untitled.cpp)
    1. static float cpv1[4][3] =
    2. {
    3.     -200.0,   0.0, 0.0,
    4.     -200.0, 200.0, 0.0,
    5.      200.0, 200.0, 0.0,
    6.      200.0, 0.0, 0.0
    7. };
    8.  
    9. float cpv2[3][3];
    10. float cpv3[2][3];
    11.  
    12. float vtx[2];
    13. float parts = 19.0;
    14.  
    15. for (float step = 0.0; step <= parts; step += 1.0 )
    16. {
    17.     t = step / parts;
    18.     PointOnLine( cpv1[0], cpv1[1], t, cpv2[0] );
    19.     PointOnLine( cpv1[1], cpv1[2], t, cpv2[1] );
    20.     PointOnLine( cpv1[2], cpv1[3], t, cpv2[2] );
    21.  
    22.     PointOnLine( cpv2[0], cpv2[1], t, cpv3[0] );
    23.     PointOnLine( cpv2[1], cpv2[2], t, cpv3[1] );
    24.  
    25.     PointOnLine( cpv3[0], cpv3[1], t, vtx );
    26.     DrawPoint( vtx );
    27. }

    动图演示:
    cubicCurve.gif
    cubicCurve.gif (63.92 KiB) 查看 815 次
    cubicCurve.gif
    cubicCurve.gif (63.92 KiB) 查看 815 次

任意多个控制点/n阶Bezier曲线路径 (n>=2)

    通过2次曲线和3次曲线可以发现,任意多次的曲线可以通过递归调用实现。

    Code: [全选] [展开/收缩] [Download] (Untitled.cpp)
    1. void PointOnLine( float *A, float *B, float t, float *vtx )
    2. {
    3.     vtx[0] = (B[0] - A[0]) * t + A[0];
    4.     vtx[1] = (B[1] - A[1]) * t + A[1];
    5.     vtx[2] = (B[2] - A[2]) * t + A[2];
    6. }
    7.  
    8. void subCurve( float cp[][3], int n, float t, float vtx[3] )
    9. {
    10.     static int i;
    11.     float (*pt)[3] = (float (*)[3]) malloc( (n-1) * 3 * sizeof(float));
    12.  
    13.     if ( n > 2)
    14.     {
    15.         for ( i = 0; i < n-1; i++ )
    16.         {
    17.             PointOnLine( cp[i], cp[i+1], t, pt[i] );
    18.         }
    19.         subCurve( pt, n-1, t, vtx );
    20.     }
    21.     else
    22.     {
    23.         PointOnLine( cp[0], cp[1], t, vtx );
    24.     }
    25.     free(pt);
    26. }

    调用示例:

    Code: [全选] [展开/收缩] [Download] (Untitled.cpp)
    1. static float cp[][3] =
    2. {
    3.     -100.0, -100.0, 0.0,
    4.     -200.0, -50.0, 0.0,
    5.     -100.0, 100.0, 0.0,
    6.       20.0, 150.0, 0.0,
    7.      200.0,  50.0, 0.0,
    8.      150.0,  0.0, 0.0
    9. };
    10.  
    11. float vtx[3];
    12. float parts = 19.0;
    13. int   n_cp  = sizeof(cp)/sizeof(cp[0]);
    14.  
    15. for (float step = 0.0; step <= parts; step += 1.0 )
    16. {
    17.     t = step / parts;
    18.     subCurve( cp, n_cp, t, vtx );
    19.     DrawPoint(vtx);
    20. }


头像
523066680
Administrator
Administrator
帖子: 404
注册时间: 2016年07月19日 12:14
拥有现金: 锁定
储蓄: 锁定
Has thanked: 38 times
Been thanked: 52 times
联系:

曲面2 Re: Bézier曲线专题

帖子 #2 523066680 » 2016年12月16日 19:45

surface3.png
surface3.png (46.74 KiB) 查看 773 次
surface3.png
surface3.png (46.74 KiB) 查看 773 次


surface2.png
surface2.png (39.05 KiB) 查看 773 次
surface2.png
surface2.png (39.05 KiB) 查看 773 次


surface1.png
surface1.png (21.51 KiB) 查看 773 次
surface1.png
surface1.png (21.51 KiB) 查看 773 次


回到 “计算机图形”

在线用户

用户浏览此论坛: 没有注册用户 和 2 访客