/* Petit programme C+OpenGL destiné ŕ montrer les courbes de subdivision. On peut contrôler chaque point de contrôle. Se compile simplement par cc -o subdiv subdiv.c -L/usr/X11R6/lib -lGL -lGLU -lglut -lXmu -lm */ #include #include #ifdef __APPLE__ #include #else #include #endif #include int beginx, beginy, width, height; float beginPoint[2]; float controlPoints[7][2] = {{-0.9, -0.9}, {-0.8, -0.5}, {-0.7, 0}, {0, 0}, {0.7, 0} , {0.5, 0.8}, {0.9, 0.9}}; float refinesPoints[100][2]; int indexCtrlPt = 0; int refine(float inputPoints[7][2], int numInput, float newPoints[100][2]) { int i, i_2, i_1; int numNewPoints = (numInput * 2) - 1; for (i = 0; i < numNewPoints; i++) { newPoints[i][0] = 0; newPoints[i][1] = 0; } for (i = 0; i < numNewPoints; i++) { if (i % 2 == 0) { newPoints[i][0] = inputPoints[i/2][0]; newPoints[i][1] = inputPoints[i/2][1]; } else { i_2 = i/2 - 1; i_1 = i/2; if (i_2 < 0) i_2 = 0; if (i_1 < 0) i_1 = 0; newPoints[i][0] += -(1.0f/16.0f)*inputPoints[i_2][0]; newPoints[i][1] += -(1.0f/16.0f)*inputPoints[i_2][1]; newPoints[i][0] += (9.0f/16.0f)*inputPoints[i_1][0]; newPoints[i][1] += (9.0f/16.0f)*inputPoints[i_1][1]; i_2 = i/2 + 2; i_1 = i/2 + 1; if (i_2 > numInput - 1) i_2 = numInput - 1; if (i_1 > numInput - 1) i_1 = numInput - 1; newPoints[i][0] += (9.0f/16.0f)*inputPoints[i_1][0]; newPoints[i][1] += (9.0f/16.0f)*inputPoints[i_1][1]; newPoints[i][0] += -(1.0f/16.0f)*inputPoints[i_2][0]; newPoints[i][1] += -(1.0f/16.0f)*inputPoints[i_2][1]; } } return numNewPoints; } int converge() { int np; float interm[100][2]; np = refine(controlPoints, 7, interm); np = refine(interm, np, refinesPoints); np = refine(refinesPoints, np, interm); np = refine(interm, np, refinesPoints); return np; } void drawObject() { int i; int np; /* Les points */ glPointSize(8.0); glColor3f(1.0, 0.0, 0.0); glBegin(GL_POINTS); for (i = 0; i < 7; i++) { if (i == indexCtrlPt) glColor3f(1.0, 1.0, 0.0); else glColor3f(1.0, 0.0, 0.0); glVertex2fv(controlPoints[i]); } glEnd(); /* les lignes */ glColor3f(1.0, 1.0, 1.0); glLineWidth(1.0); glLineStipple(1, 0xff); glBegin(GL_LINES); for (i = 0; i < 6; i++) { glVertex2fv(controlPoints[i]); glVertex2fv(controlPoints[i+1]); } glEnd(); glLineStipple(1, 0xffff); /* Les courbes */ glLineWidth(3.0); np = converge(); glColor3f(0, 0, 1); glBegin(GL_LINES); for (i = 0; i < np - 1; i++) { glVertex2fv(refinesPoints[i]); glVertex2fv(refinesPoints[i+1]); } glEnd(); } void mouse(int button, int state, int x, int y) { if (state == GLUT_DOWN) { beginx = x; beginy = y; beginPoint[0] = controlPoints[indexCtrlPt][0]; beginPoint[1] = controlPoints[indexCtrlPt][1]; } glutPostRedisplay(); } void motion(int x, int y) { int i; controlPoints[indexCtrlPt][0] = beginPoint[0] + 2*(x - beginx)/(float)width; controlPoints[indexCtrlPt][1] = beginPoint[1] - 2*(y - beginy)/(float) height; for (i = 0; i < 2; i++) { if (controlPoints[indexCtrlPt][i] > 1.0) controlPoints[indexCtrlPt][i] = 1.0; if (controlPoints[indexCtrlPt][i] < -1.0) controlPoints[indexCtrlPt][i] = -1.0; } glutPostRedisplay(); } void printHelp() { printf("A small program to show Subdivision curves\n\n"); } void parsekey(unsigned char key, int x, int y) { switch (key) { case 27: exit(0); case ' ': break; default: return; } glutPostRedisplay(); } void parsekey_special(int key, int x, int y) { switch (key) { case GLUT_KEY_UP: indexCtrlPt++; if (indexCtrlPt > 6) indexCtrlPt = 0; break; case GLUT_KEY_DOWN: indexCtrlPt--; if (indexCtrlPt < 0) indexCtrlPt = 6; break; case GLUT_KEY_RIGHT: indexCtrlPt++; if (indexCtrlPt > 6) indexCtrlPt = 0; break; case GLUT_KEY_LEFT: indexCtrlPt--; if (indexCtrlPt < 0) indexCtrlPt = 6; break; default: return; } glutPostRedisplay(); } void myReshape(int w, int h) { int xmin, ymin; xmin = 0; ymin = 0; if (w > h) { xmin = (w-h)/2; w = h; } else { ymin = (h-w)/2; h = w; } width = w; height = h; glViewport(xmin, ymin, w, h); glutPostRedisplay(); } void display(void) { glPushMatrix(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); drawObject(); glutSwapBuffers(); glPopMatrix(); } void myinit(void) { glLoadIdentity(); glClearColor(0.0, 0.0, 0.6, 1.0); glEnable(GL_LINE_STIPPLE); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE | GLUT_MULTISAMPLE | GLUT_STENCIL); glutCreateWindow("Subdivision curves"); glutDisplayFunc(display); glutInitWindowSize(1200, 1200); glutInitWindowPosition(200, 0); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(parsekey); glutSpecialFunc(parsekey_special); glutReshapeFunc(myReshape); printHelp(); glutSwapBuffers(); glutMainLoop(); return 0; }