#include #include #include /* * newbezier.c: cubic bezier curve using GLU NURBS renderer * * Of necessity, this is 2D. * All calcs are 3d, though. * * A bezier curve is an open uniform spline curve. Replicate the endpoint knots * as needed and you can render it as a NURBS curve. * * 3/31/03 pjf * */ #define NP 4 #define STRIDE 3 #define ORDER 4 GLfloat p[4][3] = { { -0.5, 0.0, 0.0 }, {-0.15, -0.5, 0.0 }, { 0.15, 0.5, 0.0 }, { 0.5, 0.0, 0.0 }}; #define NKNOTS 8 GLfloat knots[8] = { 0,0,0,0,1,1,1,1}; int ww,hh; GLUnurbsObj *nurb; /* display callback */ void display() { int i; glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0,1.0,1.0); gluBeginCurve(nurb); gluNurbsCurve(nurb,NKNOTS,knots,STRIDE,&p[0][0],ORDER,GL_MAP1_VERTEX_3); gluEndCurve(nurb); // now draw boxes around control points glColor3f(1.0,0.3,0.3); for (i=0;i<4;i++) { GLfloat x = p[i][0] - 0.02; GLfloat y = p[i][1] - 0.02; GLfloat z = p[i][2]; glBegin(GL_LINE_LOOP); glVertex3f(x,y,z); glVertex3f(x+0.04,y,z); glVertex3f(x+0.04,y+0.04,z); glVertex3f(x,y+0.04,z); glEnd(); } // now draw wectors from end points to tangent control points glColor3f(0.2,1.0,0.2); glBegin(GL_LINES); glVertex3f(p[0][0],p[0][1],p[0][2]); glVertex3f(p[1][0],p[1][1],p[1][2]); glVertex3f(p[2][0],p[2][1],p[2][2]); glVertex3f(p[3][0],p[3][1],p[3][2]); glEnd(); glFlush(); } int curcp = -1; /* mouse: called when a mouse button is pressed or released. btn identifies which button; state identifies "press" or "release" */ void mouse(int btn, int state, int x, int y) { //fprintf(stderr,"mouse: btn %d, state %d, location (%d,%d).\n",btn,state,x,y); if (state==GLUT_UP) { // up curcp = -1; } else { int i; float xmouse=2.0*x/ww - 1.0; float ymouse=2.0*(hh-y)/hh - 1.0; float zmouse=0.0; //fprintf(stderr,"Mousedown @ %f %f\n",xmouse,ymouse); float d; for(i=0;i<4;i++) { float d=(xmouse-p[i][0])*(xmouse-p[i][0]) + (ymouse-p[i][1])*(ymouse-p[i][1]) + (zmouse-p[i][2])*(zmouse-p[i][2]); if (d<0.007) break; }; if (i<4) { // valid hit curcp = i; }; } } /* called initially (before first call to display()) and whenever the window is resized */ void reshape(int w, int h) { fprintf(stderr,"reshape: new size %d x %d.\n",w,h); // must update viewport and clipping planes glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0); glMatrixMode(GL_MODELVIEW); ww=w; hh=h; } void motion(int x, int y) { float xmouse=2.0*x/ww - 1.0; float ymouse=2.0*(hh-y)/hh - 1.0; float zmouse = 0.0; //fprintf(stderr,"Motion: loc (%d %d).\n",x,y); //fprintf(stderr,"Motion @ %f %f\n",xmouse,ymouse); if (curcp == -1) return; p[curcp][0] = xmouse; p[curcp][1] = ymouse; p[curcp][2] = zmouse; glutPostRedisplay(); } void init(void) { nurb = gluNewNurbsRenderer(); gluNurbsProperty(nurb,GLU_SAMPLING_TOLERANCE,2.0); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB); glutInitWindowSize(500, 500); glutCreateWindow(argv[0]); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMouseFunc(mouse); glutMotionFunc(motion); init(); glutMainLoop(); return 0; }