Computer Graphics, Animaition, OpenGL, DirectX, OpenCL
-
523066680
- Administrator
- 帖子: 573
- 注册时间: 2016年07月19日 12:14
-
联系:
帖子
由 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 ); //画点
}
样图:加了颜色
二次 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();
做个动态的演示,其实一切都是在直线上生成的点:
三次 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 );
}
动图演示:
任意多个控制点/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);
}