继续初步学习细分曲线曲面阶段,先是细分曲线,首先接触的是Chaikin细分,其计算规则非常简单,就是一个割角过程,其最终收敛到2次B样条曲线
索性我做了点为了以后工作方便的事情。改写了一下之前的2次B样条曲线
#include<GL/GLUT.H>
#include <windows.h>
#include <math.h>
#include <gl/GL.h>
GLfloat ctrlPoints[4][2] =
{
{ -0.8f, 0.1f }, { -0.4f, 0.6f }, { 0.2f, 0.8f }, { 0.7f, 0.2f }
};
void myDisplay(void){
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(3);
glColor3f(1.0, 0.0, 0.0);
for (int i = 0; i < 4; i++){
glBegin(GL_POINTS);
glVertex2fv(&ctrlPoints[i][0]);
glEnd();
}
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < 4; i++){
glVertex2fv(&ctrlPoints[i][0]);
}
glEnd();
GLfloat ps1[11][2];
GLfloat ps2[11][2];
GLint i = 0;
for (double t = 0.0; t <= 1.0; t += 0.1)
{
double a1 = pow((1 - t), 2) / 2;
double a2 = (1 + 2 * t - 2 * t*t) / 2;
double a3 = t*t / 2;
ps1[i][0] = a1*ctrlPoints[0][0] + a2*ctrlPoints[1][0] + a3*ctrlPoints[2][0];
ps1[i][1] = a1*ctrlPoints[0][1] + a2*ctrlPoints[1][1] + a3*ctrlPoints[2][1];
ps2[i][0] = a1*ctrlPoints[1][0] + a2*ctrlPoints[2][0] + a3*ctrlPoints[3][0];
ps2[i][1] = a1*ctrlPoints[1][1] + a2*ctrlPoints[2][1] + a3*ctrlPoints[3][1];
i = i + 1;
}
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < 11; i++)
{
glVertex2fv(ps1[i]);
}
glEnd();
glBegin(GL_LINE_STRIP);
for (int i = 0; i < 11; i++)
{
glVertex2fv(ps2[i]);
}
glEnd();
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("opengl1");
glutDisplayFunc(&myDisplay);
glutMainLoop();
return 0;
}
然后是现在的Chaikin细分
<pre name="code" class="cpp">#include<GL/GLUT.H>
#include <windows.h>
#include <math.h>
#include <gl/GL.h>
#define N 4
GLfloat ctrlPoints[4][2] =
{
{ -0.8f, 0.1f }, { -0.4f, 0.6f }, { 0.2f, 0.8f }, { 0.7f, 0.2f }
};
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(3);
glColor3f(1.0, 0.0, 0.0);
for (int i = 0; i < 4; i++) {
glBegin(GL_POINTS);
glVertex2fv(&ctrlPoints[i][0]);
glEnd();
}
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < 4; i++) {
glVertex2fv(&ctrlPoints[i][0]);
}
glEnd();
int n1 = N;//表示之前的顶点数
int n = 2 * (N - 2) + 2;//表示细分一次的顶点数
GLfloat ps2[4][30][2];
for (int i = 0; i < 4; i++)
{
ps2[0][i][0] = ctrlPoints[i][0];
ps2[0][i][1] = ctrlPoints[i][1];
}
for (int i = 0; i < 3; i++)
{
ps2[i + 1][0][0] = ps2[i][0][0];
ps2[i + 1][0][1] = ps2[i][0][1];
ps2[i+1][n - 1][0] = ps2[i][n1 - 1][0];
ps2[i+1][n - 1][1] = ps2[i][n1 - 1][1];
//计算中间的点
for (int j = n1 - 2; j > 0; j--)
{
ps2[i+1][2 * j - 1][0] = 3 * ps2[i][j][0] / 4 + ps2[i][j - 1][0] / 4;
ps2[i+1][2 * j - 1][1] = 3 * ps2[i][j][1] / 4 + ps2[i][j - 1][1] / 4;
ps2[i+1][2 * j][0] = 3 * ps2[i][j][0] / 4 + ps2[i][j + 1][0] / 4;
ps2[i+1][2 * j][1] = 3 * ps2[i][j][1] / 4 + ps2[i][j + 1][1] / 4;
}
if (i==0)
glColor3f(1.0, 0.0, 1.0);
else{
if (i==1)
{
glColor3f(0.75, 0.8, 0.3);
}
else glColor3f(0.5, 0.8, 0.8);
}
glBegin(GL_LINE_STRIP);
for (int w = 0; w < n; w++)
{
glVertex2fv(ps2[i+1][w]);
}
glEnd();
n1 = n;
n = 2 * (n - 2) + 2;
}
glFlush();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("opengl1");
glutDisplayFunc(&myDisplay);
glutMainLoop();
return 0;
}
效果如下
附上和上次2次B样条的对比
Chaikin细分 | 2次B样条 |