#include #include #include /*******************************************************/ /* */ /* This demo tries to give intuition about parametric */ /* curves by drawing cubics X(t), Y(t) and (X(t),Y(t)) */ /* specified by the user. */ /* */ /* Run the program and type 'h' to see instructions */ /* on user interface. */ /* */ /* Note: on start up x(t) and Y(t) are constant so */ /* (X(t),Y(t)) is a point. */ /* Good values to try are x coeff 20, -10, 0, 2 and */ /* y coeff -8, 3, 5, 5 */ /********************************************************/ // function prototypes void display(void); void reshape(int width, int height); void keyboard(unsigned char key, int x, int y); void motion(int x, int y); void init(void); void idle(void); float xCoeff[4]={0, 0, 0, 5}; float yCoeff[4]={0, 0, 0, 5}; bool rotate = false; bool animate = false; // width and height of screen in world coordinates const float width =40; const float height = 40; float timeT; float step=0; float stdStep=.0005; int main(int argc, char **argv) { // set up window glutInitWindowSize(400, 400); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB ); glutCreateWindow("Parametric Quadratic in 2D"); // register callback functions glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); // initalize opengl parameters init(); keyboard('h',0,0); // loop until something happens glutMainLoop(); return 0; } void init() { // initialize viewing system glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-width/2.0, width/2.0, -height/2.0, height/2.0) ; glMatrixMode(GL_MODELVIEW); // shading model glEnable(GL_SMOOTH); // initialize background color to black glClearColor(0.0,0.0,0.0,0.0); // set pointsize glPointSize(3); } void reshape(int newWidth, int newHeight) { newWidth; newHeight; // preserve aspect ratio if (newWidth < newHeight) glViewport(0,0,newWidth,newWidth); else glViewport(0,0,newHeight,newHeight); } void display() { float t,tPrime; const float samples=50; // clear buffers glClear(GL_COLOR_BUFFER_BIT ); glLoadIdentity(); if (animate==true) { timeT += step; if (timeT > 1) { animate=false; glutIdleFunc(NULL); } } // on the left half of the screen we'll draw the X(t) and Y(t) glPushMatrix(); glTranslatef(-width/3.0f,height/8.0f,0); if (rotate == true) { glTranslatef(0, height/4.0f,0); glRotatef(-90,0,0,1); } glColor3f(0,0,1); glBegin(GL_LINE_STRIP); for (tPrime=0; tPrime<=samples; tPrime++) { t=tPrime/samples; glVertex2f(10* t, xCoeff[0]*t*t*t + xCoeff[1]*t*t + xCoeff[2]*t + xCoeff[3]); } glEnd(); glColor3f(1,1,1); glBegin(GL_LINE_STRIP); glVertex2f(0,10); glVertex2f(0,0); glVertex2f(10,0); glEnd(); if (animate == true && timeT<10) { glColor3f(1,0,1); glBegin(GL_LINES); glVertex2f(10*timeT,-5); glVertex2f(10*timeT,10); glEnd(); } glPopMatrix(); glPushMatrix(); glTranslatef(-width/3.0,-height/3.0,0); glColor3f(0,1,0); glBegin(GL_LINE_STRIP); for (tPrime=0; tPrime<=samples; tPrime++) { t=tPrime/samples; glVertex2f(10 * t, yCoeff[0]*t*t*t + yCoeff[1]*t*t + yCoeff[2]*t + yCoeff[3]); } glEnd(); glColor3f(1,1,1); glBegin(GL_LINE_STRIP); glVertex2f(0,10); glVertex2f(0,0); glVertex2f(10,0); glEnd(); if (animate == true && timeT<10) { glColor3f(1,0,1); glBegin(GL_LINES); glVertex2f(10*timeT,-5); glVertex2f(10*timeT,10); glEnd(); } glPopMatrix(); glPushMatrix(); glColor3f(1,0,0); glTranslatef(width/8.0,0,0); glColor3f(1,0,0); glBegin(GL_LINE_STRIP); for (tPrime=0; tPrime<=samples; tPrime++) { t=tPrime/samples; glVertex2f(xCoeff[0]*t*t*t + xCoeff[1]*t*t + xCoeff[2]*t + xCoeff[3], yCoeff[0]*t*t*t + yCoeff[1]*t*t + yCoeff[2]*t + yCoeff[3]); } glEnd(); glColor3f(1,1,1); glBegin(GL_LINE_STRIP); glVertex2f(0,10); glVertex2f(0,0); glVertex2f(10,0); glEnd(); if (animate == true && timeT<10) { glColor3f(1,0,1); glBegin(GL_POINTS); t = timeT; glVertex2f(xCoeff[0]*t*t*t + xCoeff[1]*t*t + xCoeff[2]*t + xCoeff[3], yCoeff[0]*t*t*t + yCoeff[1]*t*t + yCoeff[2]*t + yCoeff[3]); glEnd(); } glPopMatrix(); // draw to screen glutSwapBuffers(); } void idle() { glutPostRedisplay(); } void keyboard(unsigned char key, int mouseX, int mouseY) { float a,b,c,d; switch (key){ case 'a': animate = true; glutIdleFunc(idle); timeT=0; step = stdStep; break; case ' ': if (animate == true) { if (step > 0) step = 0; else step = stdStep; } break; case 'x': case 'X': cout << "Enter coefficients a, b, c, and d for x(t): "; cin >> a >> b >> c >> d; xCoeff[0]=a; xCoeff[1]=b; xCoeff[2]=c; xCoeff[3]=d; break; case 'y': case 'Y': cout << "Enter coefficients a, b, c, and d for (t): "; cin >> a >> b >> c >> d; yCoeff[0]=a; yCoeff[1]=b; yCoeff[2]=c; yCoeff[3]=d; break; case 'r': rotate = !rotate; break; case 's': cout << "Current animation time step is " << stdStep << "." << endl; cout << "Enter new time step: " << endl; cin >> stdStep; break; case 'h': cout << "Curves on left are quadratic polynomials X(t) and Y(t)." << endl; cout << "Curve on right is (X(t),Y(t))." << endl; cout << "Use 'x' or 'y' to change coefficients of X(t) or Y(t)." << endl; cout << "Use 'r' to rotate X(t)." << endl; cout << "Use 'a' to animate t-tracker across curves." << endl; cout << "Use ' ' to pause and restart animation." << endl; cout << "Use 's' to change speed of animation." << endl; cout << "Use '?' to print current polynomials." << endl; cout << "Use 'h' to repeat this message." << endl; break; case '?': cout << "X(t): " << xCoeff[0] << " * t^3 + " << xCoeff[1] << " * t^2 +" << xCoeff[2] << " t + " << xCoeff[3] << endl; cout << "Y(t): " << yCoeff[0] << " * t^3 + " << yCoeff[1] << " * t^2 +" << yCoeff[2] << " t + " << yCoeff[3] << endl; break; default: break; } glutPostRedisplay(); }