/* * Laura Toma * Rajiv Wickremesinghe */ #include #include #include #ifdef __APPLE__ #include #else #include #endif #include #include #include "matrix.h" #include "tools.h" GLubyte *gridData = NULL; int gridWidth; int gridHeight; int nx = 80, ny = 80; /* number of grid cells to draw */ int timer_active = 0; double gridZScale = 1.0; int gridLines = 1; int timerfuncmode = 0; int list_invalid = 0; int light_on = 0; int subject = 0; GLfloat theta[3]; GLfloat closeup = 0; GLfloat yaw = 0; GLfloat pitch = 0; /* ********************************************************************** */ void linein(); void timerfunc(); /* change the coordinates from (-1,1) to (1,0) to place the imagemap properly. * use the scale to tile many images. */ float tex_coord(float n) { return 1 - (n+1)/2 ; } void readPPM(char *file, GLubyte **map, int *width, int *height) { FILE *fp; char buf[BUFSIZ]; int i,j,k; int n; GLubyte *grid; int is_pgm = 0; printf("reading %s...\n", file); fp = fopen(file, "r"); if(!fp) { perror(file); exit(1); } fgets(buf, BUFSIZ, fp); /* skip header (P2) */ if(strncmp(buf, "P2", 2) == 0) { is_pgm = 1; } else if(strncmp(buf, "P3", 2) == 0) { is_pgm = 0; } else { fprintf(stderr, "%s: parse error\n", file); exit(1); } fgets(buf, BUFSIZ, fp); /* skip comment(s) */ while(buf[0] == '#') { fgets(buf, BUFSIZ, fp); } { int w, h; sscanf(buf, "%d%d", &w, &h); *width = w; *height = h; printf("width=%d, height=%d\n", w, h); if(w==0 || h==0) { fprintf(stderr, "%s: bad file size\n", file); exit(1); } } fgets(buf, BUFSIZ, fp); *map = (GLubyte *)calloc(*height * *width * 4, sizeof(GLubyte)); assert(*map); /* read in data */ grid = *map; for(i=0; i< *height; i++) { for(j=0; j< *width; j++) { if(is_pgm) { int items = fscanf(fp, "%d", &n); if(items != 1) { fprintf(stderr, "%s: file read error\n", file); exit(1); } *grid++ = (GLubyte)n; *grid++ = (GLubyte)n; *grid++ = (GLubyte)n; } else for(k=0;k<3;k++) { int items = fscanf(fp, "%d", &n); if(items != 1) { fprintf(stderr, "%s: file read error\n", file); exit(1); } *grid++ = (GLubyte)n; } *grid++ = (GLubyte)255; //(*map)[(i* *width+j)*4+3]= (GLubyte)255; } } fclose(fp); } void readGrid(char *file) { readPPM(file, &gridData, &gridWidth, &gridHeight); } void drawSolidSphere(GLfloat rad) { GLUquadricObj *q1; int f; int lines = 0; glPolygonMode(GL_FRONT, (lines?GL_LINE:GL_FILL)); f = (lines?2:1); q1 = gluNewQuadric(); assert(q1); //gluQuadricOrientation(q1, GLU_OUTSIDE); gluQuadricDrawStyle(q1, (GLenum)(lines?GLU_LINE:GLU_FILL)); gluQuadricNormals(q1, (GLenum)GLU_SMOOTH); gluSphere(q1, rad, f*12, f*8); } void init_light() { /* GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; */ /* GLfloat mat_shininess[] = { 0.0 }; */ GLfloat light_position[] = { 1, 1, 10, 0.0 }; /* GLfloat light_ambient[] = {0.3, 0.1, 0.1, 1.0}; */ GLfloat mat_diffuse[] = { 1, 1, 1, 1.0 }; /* glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); */ /* glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); */ glLightfv(GL_LIGHT0, GL_DIFFUSE, mat_diffuse); glLightfv(GL_LIGHT0, GL_POSITION, light_position); //glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); /* glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 1.0); */ /* glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5); */ glColorMaterial(GL_FRONT, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING);; glTranslatef(light_position[0], light_position[1], light_position[2]); //drawSolidSphere(0.2); glColor3f (0.0, 1.0, 1.0); glutWireCube(0.1); glEnable(GL_LIGHT0); if(light_on) { glEnable(GL_LIGHTING); } //printf("initialized lighting\n"); } void init(char *file){ readGrid(file); glClearColor(0, 0, 0, 0); /* Background color = Black*/ glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); //glDepthFunc(GL_LEQUAL); /* antialias lines */ glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glLineStipple(1, 0xCCCC); } /* return the color vector to use for these grid values */ GLfloat * color(GLfloat value, GLfloat *c) { int i; int is_black = 1; double v; for(i=0; i<3; i++) { v = (double)value; c[i] = v; if(v > 0.01) { is_black = 0; } } /* make sure we can see all the lines XXX */ if(is_black) { c[2] = 0.5; } //printf("color: %d -> %f\n", value, v); return c; } /* ********************************************************************** */ /* drawing functions */ void draw_grid(void) { GLfloat c[4]; /* color */ static grid_t *sampledGrid = NULL; face_t *face; static triangulation_t *tr; glTranslatef(-1, -1, 0); glScalef(2.0/nx, 2.0/ny, 1); glScalef(1, 1, gridZScale); if(light_on) { glEnable(GL_NORMALIZE); /* expensive, but needed w/ scaling grr */ } if(list_invalid && sampledGrid) { free(sampledGrid); trFree(tr); sampledGrid = NULL; list_invalid = 0; } if(!sampledGrid) { sampledGrid = sample_grid(gridData, gridWidth, gridHeight, nx, ny); assert(sampledGrid); tr = grid2triangulation(sampledGrid); } glBegin(GL_TRIANGLES); TAILQ_FOREACH(face, &tr->flist, flist_link) { int k; vertex_t *vertex; for(k=0; k<3; k++) { vertex = face->vertices[k]; glNormal3fv(vertex->normal); glColor3fv(color(vertex->pt[2], c)); glVertex3fv(vertex->pt); } } glEnd(); return; } void display(void) { glPushMatrix(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1,1,1); //glLineWidth(1); glLoadIdentity(); /* do translations and rotation of the head*/ glTranslatef(0, 0, closeup); glRotatef(yaw, 0, 1, 0); glRotatef(pitch, 1, 0, 0); /* setup the viewpoint */ gluLookAt(0, -2, 2, /* eye */ 0, 0, 0, /* center */ 0, 0, 1); /* up */ /* don't rotate the light, so do it here */ glPushMatrix(); init_light(); glPopMatrix(); /* do the rotations of the object */ glRotatef(theta[0], 1, 0, 0); glRotatef(theta[1], 0, 1, 0); glRotatef(theta[2], 0, 0, 1); glPolygonMode(GL_FRONT_AND_BACK, (gridLines?GL_LINE:GL_FILL)); /* if(list_invalid) { */ /* fprintf(stderr, "making list...\n");r */ /* glDeleteLists(1, 1); */ /* glNewList(1, GL_COMPILE); */ /* draw_grid(); */ /* glEndList(); */ /* list_invalid = 0; */ /* } */ /* glCallList(1); */ switch(subject) { case 0: glPushMatrix(); draw_grid(); glPopMatrix(); break; case 1: glPushMatrix(); drawSolidSphere(0.5); glPopMatrix(); break; } //done: // glFlush(); glPopMatrix(); glutSwapBuffers(); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 0.01, 20.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void keypress(unsigned char key, int x, int y) { switch(key) { case '[': /* reduce number of segments drawn */ nx /= 2; ny /= 2; list_invalid = 1; glutPostRedisplay(); break; case ']': nx *= 2; ny *= 2; list_invalid = 1; glutPostRedisplay(); break; case 'I': /* reset to start view */ theta[0] = theta[1] = theta[2] = 0; yaw = 0; glutPostRedisplay(); break; /* flying */ case 'j': yaw -= 1; glutPostRedisplay(); break; case 'k': yaw += 1; glutPostRedisplay(); break; case 'i': pitch -= 1; glutPostRedisplay(); break; case 'm': pitch += 1; glutPostRedisplay(); break; /* various rotations: */ case 'x': //glRotatef(5.0, 1, 0, 0); theta[0] += 5; glutPostRedisplay(); break; case 'y': //glRotatef(5.0, 0, 1, 0); theta[1] += 5; glutPostRedisplay(); break; case 'z': //glRotatef(5.0, 0, 0, 1); theta[2] += 5; glutPostRedisplay(); break; case 'X': //glRotatef(-5.0, 1, 0, 0); theta[0] -= 5; glutPostRedisplay(); break; case 'Y': //glRotatef(-5.0, 0, 1, 0); theta[1] -= 5; glutPostRedisplay(); break; case 'Z': //glRotatef(-5.0, 0, 0, 1); theta[2] -= 5; glutPostRedisplay(); break; case 'b': case '-': closeup -= 0.25; glutPostRedisplay(); break; case 'f': case '+': case '=': closeup += 0.25; glutPostRedisplay(); break; case 'l': light_on ^= 1; if(light_on) { glEnable(GL_LIGHTING); } else { glDisable(GL_LIGHTING); } list_invalid = 1; glutPostRedisplay(); break; case 'S': subject++; if(subject == 2) { subject = 0; } glutPostRedisplay(); break; /* animate */ case 'a': timer_active = 1; //glutTimerFunc(100 /*ms*/, timerfunc, 2); timerfuncmode |= 2; glutIdleFunc(timerfunc); break; case 'r': timer_active = 1; //glutTimerFunc(100 /*ms*/, timerfunc, 1); timerfuncmode |= 1; glutIdleFunc(timerfunc); break; case 's': timer_active = 0; timerfuncmode = 0; break; case 'g': gridLines ^= 1; glutPostRedisplay(); break; case 'q': /* quit */ exit(0); break; default: //printf("char = %d\n", key); break; } } void specialkey(int key, int x, int y) { switch(key) { case GLUT_KEY_DOWN: pitch += 1; //closeup -= 0.25; glutPostRedisplay(); break; case GLUT_KEY_UP: pitch -= 1; //closeup += 0.25; glutPostRedisplay(); break; case GLUT_KEY_LEFT: yaw -= 1; glutPostRedisplay(); break; case GLUT_KEY_RIGHT: yaw += 1; glutPostRedisplay(); break; } } void timerfunc() { // static double theta = 0.0; static int up = 1; int done = 0; int now, elapsed_ms; static int lastFrameTime; double step_modifier = 1.0; /* always call linein */ linein(); if(!timer_active) { lastFrameTime = -1; glutIdleFunc(linein); return; } now = glutGet(GLUT_ELAPSED_TIME); elapsed_ms = now - lastFrameTime; if(lastFrameTime > 0) { step_modifier = elapsed_ms / 10; } lastFrameTime = now; if(timerfuncmode & 1) { //theta += 0.1; /* wrap XXX */ /* should be rate limited */ theta[2] += step_modifier * .3; } if(timerfuncmode & 2) { //gridLines = 1; if(up) { gridZScale += step_modifier * 0.004; } else { gridZScale -= step_modifier * 0.004; } //list_invalid = 1; if((gridZScale >= 1.0 && up) || (gridZScale <= 0.0 && !up)) { done = 1; if(up) gridLines = 0; up ^= 1; timerfuncmode &= ~2; //timerfuncmode |= 1; /* start rotate */ } } if(!timerfuncmode) { //glutTimerFunc(100 /*ms*/, timerfunc, value); timer_active = 0; //glutIdleFunc(NULL); } glutPostRedisplay(); } /* ********************************************************************** */ /* main */ #include "io.h" void linein() { char buf[BUFSIZ]; int n; n = asyncGetLine(buf, BUFSIZ); if(n > 0) { fprintf(stderr, "(%c): %s\n", buf[0], buf); keypress(buf[0], 0, 0); } if(n < 0) { exit(0); } } int main(int argc, char **argv) { glutInit(&argc, argv); if(argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); fprintf(stderr, " must be an ascii pgm\n"); exit(1); } //glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500, 500); glutInitWindowPosition(100,100); glutCreateWindow(argv[1]); init(argv[1]); glutReshapeFunc(reshape); glutDisplayFunc(display); glutKeyboardFunc(keypress); glutSpecialFunc(specialkey); timer_active = 1; //glutTimerFunc(100 /*ms*/, timerfunc, 2); timerfuncmode = 2; glutIdleFunc(timerfunc); /* glutIdleFunc(linein); */ glutMainLoop(); return 0; }