/* motionblur.c - by Tom McReynolds, SGI */
/* Using the accumulation buffer for motion blur. */
#include <GL/glaux.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
const GLdouble FRUSTDIM = 100.f;
const GLdouble FRUSTNEAR = 320.f;
const GLdouble FRUSTFAR = 660.f;
GLfloat *make_texture(int maxs,int maxt) {
int s,t;
static GLfloat *texture;
texture =(GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
for(t = 0; t < maxt; t++) {
for(s = 0; s < maxs; s++) {
texture[s + maxs * t] =(float)(((s >> 4) & 0x1) ^((t >> 4) & 0x1)); } }
return(texture);
}
enum {SPHERE = 1,CONE};
void render(GLfloat dx,GLfloat dy,GLfloat dz) {
static GLfloat wall_mat[] = {1.f,1.f,1.f,1.f};
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,wall_mat);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glNormal3f(0.f,1.f,0.f);
glTexCoord2i(0,0);
glVertex3f(-100.f,-100.f,-320.f);
glTexCoord2i(1,0);
glVertex3f(100.f,-100.f,-320.f);
glTexCoord2i(1,1);
glVertex3f(100.f,-100.f,-640.f);
glTexCoord2i(0,1);
glVertex3f(-100.f,-100.f,-640.f);
glEnd();
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glNormal3f(1.f,0.f,0.f);
glVertex3f(-100.f,-100.f,-320.f);
glVertex3f(-100.f,-100.f,-640.f);
glVertex3f(-100.f,100.f,-640.f);
glVertex3f(-100.f,100.f,-320.f);
glNormal3f(-1.f,0.f,0.f);
glVertex3f(100.f,-100.f,-320.f);
glVertex3f(100.f,100.f,-320.f);
glVertex3f(100.f,100.f,-640.f);
glVertex3f(100.f,-100.f,-640.f);
glNormal3f(0.f,-1.f,0.f);
glVertex3f(-100.f,100.f,-320.f);
glVertex3f(-100.f,100.f,-640.f);
glVertex3f(100.f,100.f,-640.f);
glVertex3f(100.f,100.f,-320.f);
glNormal3f(0.f,0.f,1.f);
glVertex3f(-100.f,-100.f,-640.f);
glVertex3f(100.f,-100.f,-640.f);
glVertex3f(100.f,100.f,-640.f);
glVertex3f(-100.f,100.f,-640.f);
glEnd();
glPushMatrix();
glTranslatef(-60.f + dx,-60.f + dy,-420.f + dz);
glScalef(2.0f,2.0f,2.0f) ;
glCallList(SPHERE);
glPopMatrix();
glPushMatrix();
glTranslatef(20.f + dx,-80.f + dy,-600.f + dz);
glScalef(2.0f,2.0f,2.0f) ;
glCallList(CONE);
glPopMatrix();
if( glGetError() )
printf("Oops! I screwed up my OpenGL calls somewhere\n");
glFlush();
}
enum {NONE,FIELD};
int rendermode = NONE;
void CALLBACK redraw(void) {
int i;
int max;
GLfloat dx,dy,dz;
dx = .5f;
dy = 1.f;
dz = -2.f;
glPushMatrix();
switch(rendermode) {
case NONE : render(0.f,0.f,0.f);
break;
case FIELD : max = 16;
glClear(GL_ACCUM_BUFFER_BIT);
for ( i = 0 ; i < max ; i++) {
render(dx * i,dy * i,dz * i);
glAccum(GL_ACCUM,1.f/max); }
glAccum(GL_RETURN,1.f);
break; }
glPopMatrix();
auxSwapBuffers();
}
const int TEXDIM = 256;
void CALLBACK myReshape(int w,int h) {
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-FRUSTDIM,FRUSTDIM,-FRUSTDIM,FRUSTDIM,FRUSTNEAR,FRUSTFAR);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void CALLBACK keySpace(void) {
if ( rendermode == NONE )
rendermode = FIELD ;
else
rendermode = NONE ;
redraw();
}
void init(void) {
GLfloat *tex;
static GLfloat lightpos[] = {50.f,50.f,-320.f,1.f};
static GLfloat sphere_mat[] = {1.f,.5f,0.f,1.f};
static GLfloat cone_mat[] = {0.f,.5f,1.f,1.f};
GLUquadricObj *sphere,*cone,*base;
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0,GL_POSITION,lightpos);
glCullFace(GL_BACK);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glNewList(SPHERE,GL_COMPILE);
sphere = gluNewQuadric();
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,sphere_mat);
gluSphere(sphere,20.f,20,20);
gluDeleteQuadric(sphere);
glEndList();
glNewList(CONE,GL_COMPILE);
cone = gluNewQuadric();
base = gluNewQuadric();
glRotatef(-90.f,1.f,0.f,0.f);
glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,cone_mat);
gluDisk(base,0.,20.,20,1);
gluCylinder(cone,20.,0.,60.,20,20);
gluDeleteQuadric(cone);
gluDeleteQuadric(base);
glEndList();
tex = make_texture(TEXDIM,TEXDIM);
glTexImage2D(GL_TEXTURE_2D,0,1,TEXDIM,TEXDIM,0,GL_RED,GL_FLOAT,tex);
free(tex);
}
int main(int argc,char **argv) {
auxInitDisplayMode(AUX_DOUBLE|AUX_RGBA|AUX_DEPTH|AUX_ACCUM);
auxInitPosition(0,0,300,300);
auxInitWindow("Motion blur") ;
init();
auxKeyFunc(AUX_SPACE,keySpace) ;
auxReshapeFunc(myReshape);
auxMainLoop(redraw);
return(0);
}