/* curve.c - Don Yang (uguu.org) lclint 2.5m: 27 errors -boolops -evalorder -paramuse -predboolint -retvalint -retvalother -type 02/21/01 */ #ifdef _WIN32 #include #endif #include #include #include #include #include #include #define WINDOW_WIDTH 512 #define WINDOW_HEIGHT 512 #define WINDOW_POS_X 100 #define WINDOW_POS_Y 100 #define MIN_X -0.5 #define MIN_Y -0.5 #define MAX_X 1.5 #define MAX_Y 1.5 #define RESOLUTION 32 #define MIN_DEGREE 1 #define MAX_DEGREE 16 #define PICK_BUFFER_SIZE 256 static int MouseX, MouseY, MouseB; static int Window, Width, Height; static int Coeff[MAX_DEGREE][MAX_DEGREE], Degree; static double ControlX[MAX_DEGREE], ControlY[MAX_DEGREE]; static int ShowLines, ShowFrame; static GLuint PickBuffer[PICK_BUFFER_SIZE]; static int Selected; static void Display(void); static void Dump(void); static void GenerateCoeff(void); static void Init(void); static void Keyboard(unsigned char c, int u, int v); static void Menu(int action); static void MouseButton(int button, int state, int x, int y); static void MouseMotion(int x, int y); static int Pick(void); static void Reshape(int w, int h); /******************************************************************** main */ int main(int argc, char **argv) { glutInit(&argc, argv); Init(); glutMainLoop(); return 0; } /* main() */ /***************************************************************** Display */ static void Display(void) { static double c[MAX_DEGREE], p[MAX_DEGREE], q[MAX_DEGREE]; double x, y; int i, j; glutSetWindow(Window); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, Width = glutGet(GLUT_WINDOW_WIDTH), Height = glutGet(GLUT_WINDOW_HEIGHT)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(MIN_X, MAX_X, MIN_Y, MAX_Y); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if( ShowFrame ) { glColor3f(0.0f, 0.5f, 0.5f); glBegin(GL_LINE_LOOP); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 0.0f); glVertex3f(1.0f, 0.0f, 0.0f); glEnd(); } if( ShowLines ) { glColor3f(0.0f, 0.5f, 0.5f); glBegin(GL_LINE_STRIP); for(i = 0; i <= Degree; i++) glVertex3d(ControlX[i], ControlY[i], 0.0); glEnd(); } glColor3f(1.0f, 1.0f, 1.0f); glLineWidth(1.0f); glBegin(GL_LINE_STRIP); for(i = 0; i <= RESOLUTION; i++) { q[0] = p[0] = 1; q[1] = 1 - (p[1] = (double)i / RESOLUTION); for(j = 2; j <= Degree; j++) { p[j] = p[j - 1] * p[1]; q[j] = q[j - 1] * q[1]; } x = y = 0; for(j = 0; j <= Degree; j++) { x += ControlX[j] * (c[j] = p[j] * q[Degree - j] * Coeff[Degree][j]); } for(j = 0; j <= Degree; j++) y += ControlY[j] * c[j]; glVertex3d(x, y, 0.0); } glEnd(); glPointSize(5.0f); glBegin(GL_POINTS); glColor3f(1.0f, 0.0f, 0.0f); for(i = 1; i < Degree; i++) glVertex3d(ControlX[i], ControlY[i], 0.0); glColor3f(0.0f, 1.0f, 0.0f); glVertex3d(ControlX[0], ControlY[0], 0.0); glVertex3d(ControlX[Degree], ControlY[Degree], 0.0); glEnd(); glutSwapBuffers(); glFlush(); } /* Display() */ /******************************************************************** Dump */ static void Dump(void) { int i; for(i = 0; i <= Degree; i++) { printf("i=%d\tc=%d\t(%f, %f)\n", i, Coeff[Degree][i], ControlX[i], ControlY[i]); } } /* Dump() */ /*********************************************************** GenerateCoeff */ static void GenerateCoeff(void) { int i, j; for(i = 0; i < MAX_DEGREE; i++) for(j = 0; j < MAX_DEGREE; Coeff[i][j++] = 0); Coeff[1][0] = Coeff[1][1] = 1; for(i = 2; i < MAX_DEGREE; i++) { for(Coeff[i][j = 0] = 1; j < i; j++) Coeff[i][j] = Coeff[i - 1][j - 1] + Coeff[i - 1][j]; Coeff[i][j] = 1; } } /* GenerateCoeff() */ /******************************************************************** Init */ static void Init(void) { int i; glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); glutInitWindowPosition(WINDOW_POS_X, WINDOW_POS_Y); glutSetWindow(Window = glutCreateWindow("Curve edit")); glutDisplayFunc(Display); glutKeyboardFunc(Keyboard); glutMouseFunc(MouseButton); glutMotionFunc(MouseMotion); glutReshapeFunc(Reshape); glutCreateMenu(Menu); glutAddMenuEntry("[l] Toggle lines", 'l'); glutAddMenuEntry("[f] Toggle frame", 'f'); glutAddMenuEntry("[+] Increase degree", '+'); glutAddMenuEntry("[-] Decrease degree", '-'); glutAddMenuEntry("[a] Align endpoints", 'a'); glutAddMenuEntry("[r] Reset", 'r'); glutAddMenuEntry("[q] Quit", 'q'); glutAttachMenu(GLUT_RIGHT_BUTTON); MouseX = MouseY = MouseB = 0; GenerateCoeff(); Degree = 2; for(i = 0; i < MAX_DEGREE; ControlX[i++] = 1); for(i = 0; i < MAX_DEGREE; ControlY[i++] = 0); ControlX[0] = 0; ControlX[1] = 0.5; ControlY[1] = 0.5; Selected = -1; ShowLines = ShowFrame = 1; } /* Init() */ /**************************************************************** Keyboard */ static void Keyboard(unsigned char c, int u, int v) { int i; switch( c ) { case '+': if( Degree < MAX_DEGREE - 1 ) Degree++; break; case '-': if( Degree > MIN_DEGREE ) Degree--; break; case 'r': for(i = 0; i <= Degree; i++) { ControlX[i] = ((double)i) / Degree; ControlY[i] = 0.5; } ControlY[0] = ControlY[Degree] = 0; break; case 'a': ControlX[0] = 0; ControlX[Degree] = 1; ControlY[0] = ControlY[Degree] = 0; break; case 'l': ShowLines = !ShowLines; break; case 'f': ShowFrame = !ShowFrame; break; case 'q': Dump(); exit(EXIT_SUCCESS); default: break; } glutSetWindow(Window); glutPostRedisplay(); } /* Keyboard() */ /******************************************************************** Menu */ static void Menu(int action) { Keyboard((unsigned char)action, 0, 0); } /* Menu() */ /************************************************************* MouseButton */ static void MouseButton(int button, int state, int x, int y) { int hitcount; MouseX = x; MouseY = y; MouseB = (state == GLUT_DOWN) ? button : -1; if( state == GLUT_DOWN ) { if( (MouseB = button) == GLUT_LEFT_BUTTON ) { glSelectBuffer(PICK_BUFFER_SIZE, PickBuffer); if( (hitcount = Pick()) == 0 ) hitcount = Pick(); if( hitcount ) Selected = (int)PickBuffer[3]; else Selected = -1; } } else { MouseB = -1; } } /* MouseButton() */ /************************************************************* MouseMotion */ static void MouseMotion(int x, int y) { MouseX = x; MouseY = y; if( MouseB == GLUT_LEFT_BUTTON ) { if( Selected >= 0 && Selected <= Degree ) { ControlX[Selected] = ((double)((MAX_X - MIN_X) * x)) / Width + MIN_X; ControlY[Selected] = ((double)((MAX_Y - MIN_Y) * (Height - y))) / Height + MIN_Y; } } glutSetWindow(Window); glutPostRedisplay(); } /* MouseMotion() */ /******************************************************************** Pick */ static int Pick(void) { int viewport[4], i; glRenderMode(GL_SELECT); glInitNames(); glPushName(0xffffffff); glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, Width = glutGet(GLUT_WINDOW_WIDTH), Height = glutGet(GLUT_WINDOW_HEIGHT)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); viewport[0] = viewport[1] = 0; viewport[2] = Width; viewport[3] = Height; gluPickMatrix((GLdouble)MouseX, (GLdouble)(Height - MouseY), 16.0, 16.0, viewport); gluOrtho2D(MIN_X, MAX_X, MIN_Y, MAX_Y); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPointSize(7.0f); for(i = 0; i <= Degree; i++) { glLoadName(i); glBegin(GL_POINTS); glVertex3f(ControlX[i], ControlY[i], 0); glEnd(); } glFlush(); return glRenderMode(GL_RENDER); } /* Pick() */ /***************************************************************** Reshape */ static void Reshape(int w, int h) { glutSetWindow(Window); glutPostRedisplay(); } /* Reshape() */