#include "GL/glut.h" #include #include // array of control points, first four are initialized GLfloat ctrlpoints[100][3] = { {-100.0,-100.0, -20.0},{-50.0,50.0, -20.0},{50.0,-50.0,-20.0},{100.0,100.0,-20.0}}; int width=500,height=500; bool c1=false; bool cDisplay=false; void init(); void display(); void reshape(int w, int h); void mouse(int button, int state, int x, int y); void keyboard(unsigned char key, int x, int y); int round(float x); int currpoint=3; int numctrlpoints=4; enum {pointentry, notpointentry}; int currstate=notpointentry; int newpoints=0; main(int argc, char* argv[]) { /* set up window */ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE ); glutInitWindowSize(width,height); glutInitWindowPosition(100,100); glutCreateWindow("Bezier Curves"); /* initialize state */ init(); cerr << "Right click to select control point.\nLeft click to place control point.\n"; /* register call back functions */ glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutKeyboardFunc(keyboard); /* wait until something happens */ glutMainLoop(); return 1; } void init() { /* clear color is black */ glClearColor(0.0,0.0,0.0,0.0); /* define the viewing system */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-250.0, 250.0, -250.0, 250.0, 10.0, 50.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glShadeModel(GL_FLAT); glEnable(GL_MAP1_VERTEX_3); glLineStipple(1,0xAAA); } void display() { int i,j; glClear(GL_COLOR_BUFFER_BIT); // draw the polyline approximating the bezier curve glColor3f(1.0,1.0,1.0); for(j= 0; j 1) otherpoint = currpoint-2; if (c1 == true && currpoint%3 ==2 && numctrlpoints > currpoint+2) otherpoint = currpoint+2; if (c1 == true && currpoint%3 ==0 && currpoint>0 && numctrlpoints > currpoint+2) { otherpoint = currpoint+1; otherotherpoint = currpoint-1; } if (i!=currpoint && i!=otherpoint && i!=otherotherpoint) glVertex3fv(&ctrlpoints[i][0]); } if (currpoint!=-1) { glColor3f(1.0,0.0,0.0); glVertex3fv(&ctrlpoints[currpoint][0]); } if (otherpoint!=-1) { glColor3f(0.0,0.0,1.0); glVertex3fv(&ctrlpoints[otherpoint][0]); } if (otherotherpoint!=-1) { glColor3f(0.0,1.0,0.0); glVertex3fv(&ctrlpoints[otherotherpoint][0]); } glEnd(); // draw the control point lines if (cDisplay==true) { glEnable(GL_LINE_STIPPLE); glColor3f(0.5,0.5,0.5); for (i=0;i4) { numctrlpoints -= 3; if (currpoint >= numctrlpoints) currpoint=numctrlpoints-1; } else cerr << "Can't eliminate first set of control points.\n"; } else { if (newpoints >0) newpoints --; else { glutSetWindowTitle("BezierCurves"); currstate=notpointentry; } } glutPostRedisplay(); break; case 'c': case 'C': c1 = !c1; glutPostRedisplay(); break; case 'l': case 'L': cDisplay = !cDisplay; glutPostRedisplay(); break; default: break; } return; } void mouse(int button, int state, int x, int y) { int i; float fx, fy; double d, dx, dy, dz; double distance; fx=(float)(x*500.0)/(float) width -250.0; fy=(float) (height-y)*500.0/(float) height -250.0; int mods=glutGetModifiers(); if (mods == GLUT_ACTIVE_CTRL) cout << "control activated" << endl; if (mods == GLUT_ACTIVE_SHIFT) cout << " shift activated" << endl; if (mods == GLUT_ACTIVE_ALT) cout << " alt activated" << endl; // entering new points if (currstate == pointentry && state == GLUT_DOWN) { ctrlpoints[numctrlpoints+newpoints][0]=fx; ctrlpoints[numctrlpoints+newpoints][1]=fy; ctrlpoints[numctrlpoints+newpoints][2]=-20.0; newpoints++; if (newpoints == 3) { numctrlpoints+=3; currpoint=numctrlpoints-1; newpoints=0; currstate=notpointentry; glutSetWindowTitle("Bezier Curves"); } glutPostRedisplay(); // cerr << "Adding Point (" << round(fx) <<"," << round(fy) << ").\n"; return; } // choosing new current point if (button==GLUT_RIGHT_BUTTON && state==GLUT_DOWN) { // find control point to move d=(double) 2*(width+height); currpoint=-1; for (i=0;i distance) { d=distance; currpoint=i; } } glutPostRedisplay(); } // moving current point if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { if (currpoint == -1) cerr << "You must choose point to move.\n"; else { ctrlpoints[currpoint][0]= fx; ctrlpoints[currpoint][1]= fy; if (c1 == true && currpoint%3 == 1 && currpoint > 1) { // move corresponding control point fx = ctrlpoints[currpoint-1][0]*2.0 - ctrlpoints[currpoint][0]; fy = ctrlpoints[currpoint-1][1]*2.0 - ctrlpoints[currpoint][1]; ctrlpoints[currpoint-2][0]=fx; ctrlpoints[currpoint-2][1]=fy; } if (c1 == true && currpoint%3 == 2 && numctrlpoints > currpoint+2) { // move corresponding control point fx = ctrlpoints[currpoint+1][0]*2.0 - ctrlpoints[currpoint][0]; fy = ctrlpoints[currpoint+1][1]*2.0 - ctrlpoints[currpoint][1]; ctrlpoints[currpoint+2][0]=fx; ctrlpoints[currpoint+2][1]=fy; } if (c1 == true && currpoint%3 == 0 && currpoint > 0 && numctrlpoints > currpoint+2) { // move corresponding control point fx = ctrlpoints[currpoint][0]*2.0 - ctrlpoints[currpoint-1][0]; fy = ctrlpoints[currpoint][1]*2.0 - ctrlpoints[currpoint-1][1]; ctrlpoints[currpoint+1][0]=fx; ctrlpoints[currpoint+1][1]=fy; } glutPostRedisplay(); } } return; } int round(float x) { if (x>=0.0) return (int) (x+0.5); return (int) (x-0.5); }