Bézier曲线专题

Computer Graphics, Animaition, OpenGL, DirectX, OpenCL
回复
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

Bézier曲线专题

帖子 523066680 »

编辑:523066680
代码:523066680

首先是求一条直线上的均匀分布的点
  • void PointOnLine(float *A, float *B, float t, float *vtx )
    {
    vtx[0] = (B[0] - A[0]) * t + A[0];
    vtx[1] = (B[1] - A[1]) * t + A[1];
    }
    比方说从起点到末点取10个点(分9段):
    float a[2] = {-200.0, 0.0  };
    float b[2] = { 200.0, 200.0};
    float parts = 9.0;
    float vtx[2];

    for (float step = 0.0; step <= parts; step += 1.0 )
    {
    t = step / parts; //进度 t
    PointOnLine( a, b, t, vtx ); //计算坐标保存到vtx
    DrawPoint( vtx ); //画点
    }
    样图:加了颜色
    Line.png
    (1.55 KiB) 已下载 920 次
二次 Bézier 曲线
  • 在画线(L1)的基础上,增加一个连接点,形成第二条直线L2,连接两个线段某个进度(t)上的点L1(t), L2(t),到线段L3,
    然后在 L3 上面取进度(t)的点,t 从 0.0 到 1.0, L3(t) 上的点的集合即为 2次 Bezier 曲线 上的点(还是看动图吧)。
    float a[2] = {-100.0, 0.0  };
    float b[2] = { 0.0, 100.0};
    float c[2] = { 100.0, 0.0 };
    float parts = 9.0;
    float pt_on_ab[2];
    float pt_on_bc[2];
    float vtx[2];

    glBegin(GL_POINTS);
    for (float step = 0.0; step <= parts; step += 1.0 )
    {
    t = step / parts;
    glColor3f(1.0-t, t, 0.0);
    PointOnLine( a, b, t, pt_on_ab ); // ab线段 上指定进度(t)的点 1
    PointOnLine( b, c, t, pt_on_bc ); // bc线段 上指定进度(t)的点 2
    PointOnLine( pt_on_ab, pt_on_bc, t, vtx ); // 求出点1点2 直线上指定进度(t)的点
    glVertex2fv( vtx );
    }
    glEnd();
    QuadraticCurve.png
    (1.03 KiB) 已下载 926 次
    做个动态的演示,其实一切都是在直线上生成的点:
    QuadBezier.gif
    (97.24 KiB) 已下载 922 次
三次 Bézier 曲线
  • 还是在上一次的基础上,增加一个控制点/坐标,用abcd已经不合适了,改用数组,v1 v2 v3 表示顶点的层次
    static float cpv1[4][3] = 
    {
    -200.0, 0.0, 0.0,
    -200.0, 200.0, 0.0,
    200.0, 200.0, 0.0,
    200.0, 0.0, 0.0
    };

    float cpv2[3][3];
    float cpv3[2][3];

    float vtx[2];
    float parts = 19.0;

    for (float step = 0.0; step <= parts; step += 1.0 )
    {
    t = step / parts;
    PointOnLine( cpv1[0], cpv1[1], t, cpv2[0] );
    PointOnLine( cpv1[1], cpv1[2], t, cpv2[1] );
    PointOnLine( cpv1[2], cpv1[3], t, cpv2[2] );

    PointOnLine( cpv2[0], cpv2[1], t, cpv3[0] );
    PointOnLine( cpv2[1], cpv2[2], t, cpv3[1] );

    PointOnLine( cpv3[0], cpv3[1], t, vtx );
    DrawPoint( vtx );
    }
    动图演示:
    cubicCurve.gif
    (63.92 KiB) 已下载 902 次
任意多个控制点/n阶Bezier曲线路径 (n>=2)
  • 通过2次曲线和3次曲线可以发现,任意多次的曲线可以通过递归调用实现。
    void PointOnLine( float *A, float *B, float t, float *vtx )
    {
    vtx[0] = (B[0] - A[0]) * t + A[0];
    vtx[1] = (B[1] - A[1]) * t + A[1];
    vtx[2] = (B[2] - A[2]) * t + A[2];
    }

    void subCurve( float cp[][3], int n, float t, float vtx[3] )
    {
    static int i;
    float (*pt)[3] = (float (*)[3]) malloc( (n-1) * 3 * sizeof(float));

    if ( n > 2)
    {
    for ( i = 0; i < n-1; i++ )
    {
    PointOnLine( cp[i], cp[i+1], t, pt[i] );
    }
    subCurve( pt, n-1, t, vtx );
    }
    else
    {
    PointOnLine( cp[0], cp[1], t, vtx );
    }
    free(pt);
    }
    调用示例:
    static float cp[][3] = 
    {
    -100.0, -100.0, 0.0,
    -200.0, -50.0, 0.0,
    -100.0, 100.0, 0.0,
    20.0, 150.0, 0.0,
    200.0, 50.0, 0.0,
    150.0, 0.0, 0.0
    };

    float vtx[3];
    float parts = 19.0;
    int n_cp = sizeof(cp)/sizeof(cp[0]);

    for (float step = 0.0; step <= parts; step += 1.0 )
    {
    t = step / parts;
    subCurve( cp, n_cp, t, vtx );
    DrawPoint(vtx);
    }
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

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

帖子 523066680 »

surface3.png
(46.74 KiB) 已下载 860 次
surface2.png
(39.05 KiB) 已下载 860 次
surface1.png
(21.51 KiB) 已下载 860 次
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 0 访客