/***************************************************************************** * * * visualize3D - given a gird in arcascii format, this program will display * * the terrain in 3D using OpenGL * * * * run as: visualize3D * * * * Author: Jonathan Todd * * * *****************************************************************************/ #include #include #include #include #include "visualize3D.h" #ifdef __APPLE__ #include #else #include #endif GLfloat red[3] = {1.0, 0.0, 0.0}; GLfloat green[3] = {0.0, 1.0, 0.0}; GLfloat blue[3] = {0.0, 0.0, 1.0}; GLfloat black[3] = {0.0, 0.0, 0.0}; GLfloat white[3] = {1.0, 1.0, 1.0}; GLfloat gray[3] = {0.5, 0.5, 0.5}; GLfloat yellow[3] = {1.0, 1.0, 0.0}; GLfloat magenta[3] = {1.0, 0.0, 1.0}; GLfloat cyan[3] = {0.0, 1.0, 1.0}; GLfloat pos[3] = {0,0,0}; GLfloat theta[3] = {0,0,0}; GLint fillmode = 0; Grid *grid; // global grid structure int resolution = 64; // 1 is best resolution, 2 is 1/2 the resolution of 1... int colorStyle = 0; // Specifies the color to display float maxZ = 1.0; // specifies the max value for the z coordinate int window_width = 500; int window_height = 500; // main // int main(int argc, char** argv) { // Validate the number of arguments if (argc != 2){ printf("usage: visualize2D intput-grid\n"); return 1; } // import grid grid = importGrid(argv[1]); // print grid info printGrid(grid); // open a window glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(window_width, window_height); glutInitWindowPosition(100,100); glutCreateWindow(argv[0]); /* camera is at (0,0,0) looking along negative y axis */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60, 1 /* aspect */, 1, 10.0); /* the frustrum is from z=-1 to z=-10 */ glMatrixMode(GL_MODELVIEW); glEnable(GL_DEPTH_TEST); // OpenGL init glClearColor(0, 0, 0, 0); // set background color black // callback functions glutMotionFunc(mouse); glutDisplayFunc(display); glutKeyboardFunc(keypress); //glutReshapeFunc(reshape); // creat menu glutCreateMenu(main_menu); glutAddMenuEntry("Fill/Outline", 1); glutAddMenuEntry("Change Color", 2); glutAddMenuEntry("Quit", 3); glutAttachMenu(GLUT_LEFT_BUTTON); // event handler glutMainLoop(); return 0; } // min - return the min of two ints // int min(int x, int y){ return (xnrows > grid->ncols){ interval = 2.0/grid->nrows; x1 = -((interval*grid->ncols)/2); y1 = 1; } else{ interval = 2.0/grid->ncols; x1 = -1; y1 = ((interval*grid->nrows)/2); } x = x1; y = y1; // loop through the data and draw 2 triangles per cell marked by top left // corner (x,y). Drawn in clockwise rotation for(i=0;inrows;i+=resolution){ for(j=0;jncols;j+=resolution){ mincols=min(grid->ncols-1-j,resolution); minrows=min(grid->nrows-1-i,resolution); // draw upper left triangle glBegin(GL_POLYGON); color_map(grid->data[i][j]); glVertex3f(x,y,z_map(grid->data[i][j])); color_map(grid->data[i][j+mincols]); glVertex3f(x+interval*mincols,y,z_map(grid->data[i][j+mincols])); color_map(grid->data[i+minrows][j]); glVertex3f(x,y-interval*minrows,z_map(grid->data[i+minrows][j])); glEnd(); // draw lower right triangle glBegin(GL_POLYGON); color_map(grid->data[i][j+mincols]); glVertex3f(x+interval*mincols,y,z_map(grid->data[i][j+mincols])); color_map(grid->data[i+minrows][j+mincols]); glVertex3f(x+interval*mincols,y-interval*minrows, z_map(grid->data[i+minrows][j+mincols])); color_map(grid->data[i+minrows][j]); glVertex3f(x,y-interval*minrows,z_map(grid->data[i+minrows][j])); glEnd(); // move to the next column x+=interval*resolution; } // move back to the first column and the next row x = x1; y-=interval*resolution; } } // z_map - map height into a viewable z range (ie -1.0 to -10.0) // float z_map(int h){ if(h == grid->nodata) return 0; else return (maxZ/(grid->max-grid->min))*(h-grid->min); } // color_map - set the color based on a given height // void color_map(int h){ float c; c = (1.0/(grid->max-grid->min))*(h-grid->min); // If nodata color white if (h == grid->nodata) glColor3f(0,0,0); // Greyscale else if(colorStyle) glColor3f(c,c,c); // Rainbow else { if(c < (1.0/5)) glColor3f(1-(5*c),1,0); if(c < 2.0/5 && c >= 1.0/5) glColor3f(0,1,(c-(1.0/5))*5); if(c < 3.0/5 && c >= 2.0/5) glColor3f(0,((3.0/5)-c)*5,1); if(c < 4.0/5 && c >= 3.0/5) glColor3f((c-(3.0/5))*5,0,1); if(c <= 5.0/5 && c >= 4.0/5) glColor3f(1,0,(1-c)*5); } } // display - controls what is drawn to the screen // void display(void) { // clear window glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // Look at terrain from a better perspective: get a top down view, with z // the up axis gluLookAt(1, 0, 3, 0, 0, 0, 0, 0, 1); /* modeling*/ glRotatef(theta[0], 1,0,0); glRotatef(theta[1], 0,1,0); glRotatef(theta[2], 0,0,1); glTranslatef(pos[0], pos[1], pos[2]); draw_grid(); /* execute the drawing commands */ glFlush(); } // mouse - assigns action to mouse events // void mouse(int x, int y){ pos[0]=(x-(window_width/2.0))/(window_width/2.0); pos[1]=-(y-(window_height/2.0))/(window_height/2.0); glutPostRedisplay(); } // reshape - assigns action to resizing the window // void reshape(int w, int h){ window_width = w; window_height = h; } // keypress - assigns actioins to keypresses // void keypress(unsigned char key, int x, int y) { float i = .05; switch(key) { /* various object rotations: */ case 'e': maxZ -= 0.1; glutPostRedisplay(); break; case 'E': maxZ += 0.1; glutPostRedisplay(); break; case 'x': theta[0] += 5.0; //glRotatef(5.0, 1, 0, 0); glutPostRedisplay(); break; case 'y': theta[1] += 5.0; //glRotatef(5.0, 0, 1, 0); glutPostRedisplay(); break; case 'z': theta[2] += 5.0; //glRotatef(5.0, 0, 0, 1); glutPostRedisplay(); break; case 'X': theta[0] -= 5.0; //glRotatef(-5.0, 1, 0, 0); glutPostRedisplay(); break; case 'Y': theta[1] -= 5.0; //glRotatef(-5.0, 0, 1, 0); glutPostRedisplay(); break; case 'Z': theta[2] -= 5.0; //glRotatef(-5.0, 0, 0, 1); glutPostRedisplay(); break; case 'b': pos[2] -= 0.5; //glTranslatef(0,0, -0.5); glutPostRedisplay(); break; case 'f': pos[2] += 0.5; //glTranslatef(0,0, 0.5); glutPostRedisplay(); break; case 'd': pos[1] -= 0.5; //glTranslatef(0,0.5,0); glutPostRedisplay(); break; case 'u': pos[1] += 0.5; //glTranslatef(0,-0.5,0); glutPostRedisplay(); break; case 'l': pos[0] -= 0.5; glutPostRedisplay(); break; case 'r': pos[0] += 0.5; glutPostRedisplay(); break; case 'q': exit(0); break; case '>': // increase resolution if(resolution > 1){ resolution /= 2; glutPostRedisplay(); } break; case '<': // decrease resolution if(resolution < grid->max){ resolution *= 2; glutPostRedisplay(); } break; } } // main_menu - creates a menu // void main_menu(int value) { switch (value){ case 1: /* toggle outline/fill */ fillmode = !fillmode; break; case 2: // Change color style colorStyle = !colorStyle; break; case 3: exit(0); } glutPostRedisplay(); } // importGrid - brings grid file into an array // Grid *importGrid(char *path) { FILE *inputf; int i,j,value; // Validate input file if ((inputf = fopen(path, "r"))== NULL){ printf("mult: can't open %s\n",path); exit(1); } // Input file info into the grid structure Grid *g = (Grid *) malloc(sizeof(Grid)); g->name = path; int scan = fscanf(inputf,"%*s%d%*s%d%*s%f%*s%f%*s%d%*s%d", &g->ncols,&g->nrows,&g->x, &g->y,&g->cellsize,&g->nodata); if(scan==0){ printf("mult: trouble reading input file!\n"); exit(1); } // Dynamically allocate array for data if((g->data = (int**) malloc((g->nrows)*sizeof(int*)))==NULL){ printf("mult: insufficient memory"); exit(1); } for(i=0;inrows;i++){ if((g->data[i] = (int*) malloc((g->ncols)*sizeof(int)))==NULL){ printf("mult: insufficient memory"); exit(1); } } // Put data into the array and calculate max & min g->min = 9999999; g->max = 0; for(i=0;inrows;i++){ for(j=0;jncols;j++){ if(fscanf(inputf,"%d",&value)!=EOF){ if(value < g->min && value != g->nodata) g->min = value; if(value > g->max) g->max = value; g->data[i][j]=value; } else{ printf("mult: data file is corrupt"); exit(1); } } } // Close file fclose(inputf); // Return grid return g; } // printGrid - Print the grid info // void printGrid(Grid *g){ printf("\nGrid Info:\n\n"); printf("Name: %s\n",g->name); printf("Number of Columns: %u\n",g->ncols); printf("Number of Rows: %u\n",g->nrows); printf("Lat Lon X Corner: %f\n",g->x); printf("Lat Lon Y Corner: %f\n",g->y); printf("Cell size: %u\n",g->cellsize); printf("No data value: %d\n",g->nodata); printf("Min value: %d\n",g->min); printf("Max value: %d\n",g->max); }