/* Demonstration of motion blur: teapot falling off a table. This rendering uses increasingly larger coefficients, so that the later images are stronger. Unfortunately, the first image nearly disappears, even when there are only three frames. Written by Caroline Geiersbach and Scott D. Anderson scott.anderson@acm.org Summer 2003 Fall 2004, Added callbacks to increase/decrease NumFrames. */ #include #include #include /* Draws a parson's table with the origin at the outer lower corner of the back left leg, because the table lies in the +++ octant. The table is drawn in the current color, with the given dimensions. The height corresponds to the y axis, x and z are width and depth, respectively. The legs are square, with the given size. */ void drawTable(float width, float height, float depth, float topThickness, float legSize) { // draw the top glPushMatrix(); // divide by two because the origin of the cube is in its center glTranslatef(width/2,height-topThickness/2,depth/2); glScalef(width,topThickness,depth); glutSolidCube(1); glPopMatrix(); float legY=(height-legSize)/2; // y coord of cube origin for a leg float legH=height-legSize; // height of a leg // back left leg; origin at back left corner glPushMatrix(); glTranslatef(legSize/2,legY,legSize/2); glScalef(legSize,legH,legSize); glutSolidCube(1); glPopMatrix(); // back right leg glPushMatrix(); glTranslatef(width-legSize/2,legY,legSize/2); glScalef(legSize,legH,legSize); glutSolidCube(1); glPopMatrix(); // front left leg glPushMatrix(); glTranslatef(legSize/2,legY,depth-legSize/2); glScalef(legSize,legH,legSize); glutSolidCube(1); glPopMatrix(); // front right leg glPushMatrix(); glTranslatef(width-legSize/2,legY,depth-legSize/2); glScalef(legSize,legH,legSize); glutSolidCube(1); glPopMatrix(); } bool UseAccum = false; bool Small = false; /* The parameter is used to compute the position of the teapot. It should be in the range 0-1. */ void drawScene(float parameter) { twError(); glEnable(GL_LIGHTING); glShadeModel(GL_SMOOTH); twError(); printf("parameter = %f\n",parameter); // this is saddle brown, according to rgb.txt twTriple tableColor = {139/255.0, 69/255.0, 19/255.0}; twColor(tableColor,0.5,5); drawTable(10,8,10,1,1); glPushMatrix(); // falling teapot is to the left of the table (x=11), near the front // legs (z=9). The parameter interpolates between the following // heights float height0; // start height float height1; // end height if(Small) { height0 = 4.2; height1 = 4.5; } else { height0 = 7.5; height1 = 3.5; } // Interpolate the height between height0 and height1 glTranslatef(12, height0+parameter*(height1-height0), 9); // falling teapot is rotating around the z axis. float angle0; // start angle float angle1; // end angle if(Small) { angle0=-60; angle1=-64; } else { angle0 = -20; angle1 = -60; } // Interpolate between angle0 and angle1 glRotatef(angle0+parameter*(angle1-angle0), 0,0,1); twError(); // this color is royal blue, according to rgb.txt twTriple teapotColor = {65/255.0, 105/255.0, 255/255.0}; twColor(teapotColor,0.8,32); glutSolidTeapot(1); glPopMatrix(); twError(); } float NumFrames = 3; // draw this many frames float SummationTotal = NumFrames*(NumFrames+1)/2; // This display function is the "ordinary" one. It draws the scene // NumFrames times, but doesn't play any tricks with the accumulation // buffer. void display1(void) { twDisplayInit(0,0,0); twCamera(); for(int frame=0; frame<=NumFrames-1; frame++) { // this parameter will be 0-1 drawScene(frame/(NumFrames-1)); } twError(); glFlush(); glutSwapBuffers(); } // This display function is the one for motion blur. It draws the scene // NumFrames times, summing them using the accumulation buffer. The sum // is a weighted sum, where the weights add to one and increase linearly. void displayN(void) { // We use floats for the following, even though they are integers, // because the computation of the parameter then involves no type // coercion problems. float frame; // Clear the accumulation buffer. Clearing it to other values has // bizarre effects, so always clear to zero, at least if you're using // GL_ACCUM glClearAccum(0,0,0,0); glClear(GL_ACCUM_BUFFER_BIT); for(frame=0; frame2) { NumFrames--; SummationTotal = NumFrames*(NumFrames+1)/2; } break; } glutPostRedisplay(); } void myInit() { twBoundingBox(0,24,0,8,0,10); twMainInit(); twTriple lightPos = {13,13,13}; twGrayLight(GL_LIGHT0, lightPos, 0.3,0.8,0.8); twAmbient(1.0); glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE); glEnable(GL_LIGHT0); twKeyCallback('m',keys,"toggle motion blur"); twKeyCallback('s',keys,"toggle small motion"); twKeyCallback('+',keys,"increase frames"); twKeyCallback('-',keys,"decrease frames"); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_ACCUM | GLUT_DEPTH); twInitWindowSize(600,600); glutCreateWindow(argv[0]); glutDisplayFunc(display1); myInit(); glutMainLoop(); return 0; }