//////////////////////////////////////////////////// // anim.cpp // Template code for drawing an interesting animation. //////////////////////////////////////////////////// #ifdef WIN32 #include #endif #include #include #include #include #include void nextFrame(); void save_image(int frame); void instructions(); const int STRLEN = 100; typedef char STR[STRLEN]; int Win[2]; // window (x,y) size #define PI 3.1415926535897 #define X 0 #define Y 1 #define Z 2 double t = 0.0; double tStep = 0.05; double dt = tStep; double tMax = 1.0; int animating = 0; int recording = 0; double eye[3] = {1.5, 2.0, 10.0}; ////////////////////////////////////////////////////// // *************************************************** // * You should change these lines to reflect the number // * of degrees of freedom in your animation // *************************************************** ////////////////////////////////////////////////////// #define MAXDOF 3 int cur_dof = 0; double dof[MAXDOF] = { 0.0, 0.0, 0.0 }; char *dofName[MAXDOF] = { "base azimuth", "arm elevation", "eye y" }; enum { BASE_ANGLE, ARM_ANGLE, EYE_Y }; ////////////////////////////////////////////////////// // *************************************************** // * You should change these lines to reflect the number // * of cubic curves used to control your degrees of freedom. // * These are initialized in init_curves(). // * NOTE: Here, simple linear interpolation is used. // * You should define cubic curves instead. // *************************************************** ////////////////////////////////////////////////////// #define MAXCURVES 4 typedef struct { double a[MAXDOF][4]; double len; } curve; curve dofHistory[MAXCURVES]; ////////////////////////////////////////////////////// // PROC: choose_dof() // DOES: prepares another degree of freedom for editing. ////////////////////////////////////////////////////// void choose_dof(int step) { cur_dof += step; if (cur_dof < 0) cur_dof = 0; if (cur_dof >= MAXDOF) cur_dof = MAXDOF-1; printf("Active: %s\n",dofName[cur_dof]); } ////////////////////////////////////////////////////// // PROC: change_dof() // DOES: increases or decreases current degree of freedom variable. ////////////////////////////////////////////////////// void change_dof(double increment) { dof[cur_dof] += increment; printf(" %s: %6.2lf\n",dofName[cur_dof],dof[cur_dof]); glutPostRedisplay(); } ////////////////////////////////////////////////////// // PROC: glut_key_action() // DOES: this function gets called for any keypresses ////////////////////////////////////////////////////// void glut_key_action(unsigned char key, int x, int y) { switch (key) { case 'q': case 27: exit(0); case 's': save_image(-1); break; case 'r': recording ^= 1; if (recording) printf("Recording ON\n"); else printf("Recording OFF\n"); break; case ',': case '+': animating = 0; t -= tStep; nextFrame(); break; case '.': case '-': animating = 0; t += tStep; nextFrame(); break; case ' ': animating = !animating; break; case '<': animating = 1; dt = -tStep; break; case '>': animating = 1; dt = tStep; break; case '8': choose_dof(+1); break; case '2': choose_dof(-1); break; case '4': change_dof(-0.1); break; case '6': change_dof(+0.1); break; case '1': change_dof(-0.01); break; case '3': change_dof(+0.01); break; case '7': change_dof(-1.0); break; case '9': change_dof(+1.0); break; case 'h': case '?': instructions(); break; } } ////////////////////////////////////////////////////// // *************************************************** // * You should change this function to use the // * curve coefficients for your animation. // *************************************************** ////////////////////////////////////////////////////// void init_curves() { int i,j; /* * No quadratic or cubic terms in this example. */ for (i=0; i=0; y-- ) { glReadPixels(0,y,Win[0],1,GL_RGB,GL_UNSIGNED_BYTE, (GLvoid *) pixels); fwrite(pixels, 3, Win[0], fp); } fclose(fp); } /********************************************************* PROC: myinit() DOES: performs most of the OpenGL intialization -- change these with care, if you must. **********************************************************/ void myinit(void) { GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 }; GLfloat lmodel_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f }; GLfloat local_view[] = { 0.0 }; /**** set lighting parameters ****/ glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_POSITION, position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); /* glFrontFace (GL_CW); */ glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); } /********************************************************* PROC: set_colour(); DOES: sets all material properties to the given colour -- don't change **********************************************************/ void set_colour(float r, float g, float b) { float ambient = 0.2f; float diffuse = 0.7f; float specular = 0.4f; GLfloat mat[4]; /**** set ambient lighting parameters ****/ mat[0] = ambient*r; mat[1] = ambient*g; mat[2] = ambient*b; mat[3] = 1.0; glMaterialfv (GL_FRONT, GL_AMBIENT, mat); /**** set diffuse lighting parameters ******/ mat[0] = diffuse*r; mat[1] = diffuse*g; mat[2] = diffuse*b; mat[3] = 1.0; glMaterialfv (GL_FRONT, GL_DIFFUSE, mat); /**** set specular lighting parameters *****/ mat[0] = specular*r; mat[1] = specular*g; mat[2] = specular*b; mat[3] = 1.0; glMaterialfv (GL_FRONT, GL_SPECULAR, mat); glMaterialf (GL_FRONT, GL_SHININESS, 0.5); } /********************************************************* PROC: display() DOES: this gets called by the event handler to draw the scene, so this is where you need to build your scene -- make your changes and additions here Add other procedures if you like. **********************************************************/ void display(void) { eye[Y] = dof[EYE_Y]; glLoadIdentity(); gluLookAt (eye[X], eye[Y], eye[Z], 0.0,0.0,0.0, 0.0,1.0,0.0); /* glClearColor (red, green, blue, alpha */ /* Ignore the meaning of the 'alpha' value for now */ glClearColor(0.7f,0.7f,0.9f,1.0f); /* set the background colour */ /* OK, now clear the screen with the background colour */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* draw the base */ glRotated(360.0*dof[BASE_ANGLE], 0.0, 1.0, 0.0); set_colour(1, 1, 0.6f); /* yellow */ glPushMatrix(); glScaled(1.0, 2.0, 1.0); glutSolidCube(1.0); glPopMatrix(); /* draw the arm */ set_colour(1, 0.5f, 0.5f); /* pink */ glTranslated(0.5, 1.0, 0.0); glRotated(180.0*dof[ARM_ANGLE], 0.0, 0.0, 1.0); glTranslated(0.5, -1.0, 0.0); glPushMatrix(); glScalef(1.0f, 2.0f, 1.0f); glutSolidCube(1.0); glPopMatrix(); glFlush(); glutSwapBuffers(); } /********************************************************* PROC: myReshape() DOES: handles the window being resized -- don't change **********************************************************/ void myReshape(int w, int h) { Win[0] = w; Win[1] = h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /*** this defines the field of view of the camera ***/ /*** Making the first 4 parameters larger will give ***/ /*** a larger field of view, therefore making the ***/ /*** objects in the scene appear smaller ***/ glFrustum(-1,1,-1,1,4,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /*** this sets the virtual camera ***/ /*** gluLookAt( x,y,z, x,y,z x,y,z ); ***/ /*** camera look-at camera-up ***/ /*** pos'n point vector ***/ /*** place camera at (x=4, y=6, z=20), looking at origin, y-axis being up ***/ gluLookAt(eye[X],eye[Y],eye[Z], 0,0,0, 0,1,0); } void idle() { if (animating) { t += dt; if (t > tMax) { t = tMax; return; } if (t < 0.0) { t = 0.0; return; } nextFrame(); if (recording) { int frame = (int)(t / tStep + 0.5); save_image(frame); } } } ////////////////////////////////////////////////////// // This is called when it's time to draw the next frame. ////////////////////////////////////////////////////// void nextFrame() { int i,iCurve,j,k; double tStart,tp,d; // // Make sure time is in bounds // if (t > tMax) t = tMax; if (t < 0.0) t = 0.0; // // Find the cubic curve that contains the current time point. // iCurve = 0; tStart = 0.0; for (i=0; i=0; k--) d = (d*tp) + dofHistory[iCurve].a[j][k]; dof[j] = d; } printf("t=%6.2lf\n",t); for (i=0; i play forwards\n"); printf(" < play backwards\n"); printf("space stop/start animation\n"); printf(" r stop/start recording frames\n"); printf(" . or + step forwards one frame\n"); printf(" , or - step backwards one frame\n"); printf("\n"); printf("Hierarchy controls: use numeric keypad, with Num-Lock ON\n"); printf("7: dof -= 1 8: next dof 9: dof += 1\n"); printf("4: dof -= 0.1 6: dof += 0.1\n"); printf("1: dof -= 0.01 2: prev dof 3: dof += 0.01\n"); } /********************************************************* PROC: main() DOES: calls initialization, then hands over control to the event handle, which calls display() whenever the screen needs to be redrawn **********************************************************/ int main(int argc, char** argv) { glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition (0, 0); glutInitWindowSize(196,196); glutCreateWindow(argv[0]); myinit(); init_curves(); glutReshapeFunc (myReshape); glutKeyboardFunc( glut_key_action ); instructions(); glutIdleFunc(idle); glutDisplayFunc(display); glutMainLoop(); return 0; // never reached }