www.pudn.com > terra-0_7.zip > gui.cc
#include#include #include #include "glHacks.h" #include "terra.h" #include "gui.h" int mesh_view; int surf_view; int will_draw_dem = False; // Prototype for our hack below. // void xglutKeepAspect(float width, float height); //////////////////////////////////////////////////////////////////////// // // Mesh functions // //////////////////////////////////////////////////////////////////////// #define MESH_MENU_EPS 1000 #define MESH_MENU_TIN 1001 #define MESH_MENU_OBJ 1002 #define MESH_MENU_DEM 1003 static void mesh_main_menu(int value) { switch( value ) { case MESH_MENU_EPS: generate_output("out.eps", EPSfile); break; case MESH_MENU_TIN: generate_output("out.tin", TINfile); break; case MESH_MENU_OBJ: generate_output("out.obj", OBJfile); break; case MESH_MENU_DEM: generate_output("out.pgm", DEMfile); default: break; } } static void mesh_toggle_menu(int value) { int *val = (int *)value; *val = !(*val); glutPostRedisplay(); } static void create_mesh_menus() { int toggle = glutCreateMenu(mesh_toggle_menu); glutAddMenuEntry("Draw DEM data", (int)&will_draw_dem); int main = glutCreateMenu(mesh_main_menu); glutAddSubMenu("Toggle", toggle); glutAddMenuEntry("Output Mesh EPS", MESH_MENU_EPS); glutAddMenuEntry("Output Surface TIN", MESH_MENU_TIN); glutAddMenuEntry("Output Surface OBJ", MESH_MENU_OBJ); glutAddMenuEntry("Output Approximate DEM", MESH_MENU_DEM); glutAttachMenu(GLUT_RIGHT_BUTTON); } static void draw_edge(Edge *e, void *) { Vec2& org = e->Org(); Vec2& dest = e->Dest(); glV(org[X], org[Y]); glV(dest[X], dest[Y]); } static void draw_dem() { Map *bits = DEM; glPixelZoom((float)glutGet(GLUT_WINDOW_WIDTH) / (float)DEM->width , -(float)glutGet(GLUT_WINDOW_HEIGHT) / (float)DEM->height); glRasterPos3f(0, 0, 0); static GLenum type_map[] = {GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT }; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); float scale = (float)((1< depth) - 1) / (DEM->max - DEM->min); glPixelTransferf(GL_RED_SCALE, scale); glPixelTransferf(GL_GREEN_SCALE, scale); glPixelTransferf(GL_BLUE_SCALE, scale); float bias = -DEM->min/(DEM->max - DEM->min); glPixelTransferf(GL_RED_BIAS, bias); glPixelTransferf(GL_GREEN_BIAS, bias); glPixelTransferf(GL_BLUE_BIAS, bias); //!! // WARNING: // We are assuming that the map will never be a RealMap // GLenum type = type_map[((bits->depth)>>3)-1]; glDrawPixels(bits->width, bits->height, GL_LUMINANCE, type, bits->getBlock()); } void mesh_display() { glClear( GL_COLOR_BUFFER_BIT ); if( will_draw_dem ) draw_dem(); glBegin(GL_LINES); glC(1.0, 0.15, 0.15); mesh->overEdges(draw_edge); glEnd(); } static inline void redisplay_all(int other) { glutPostRedisplay(); glutSetWindow(other); glutPostRedisplay(); } void mesh_mouse(int button, int state, int x, int y) { if( state == GLUT_DOWN ) { if( button == GLUT_LEFT_BUTTON ) { GLdouble u, v, z; int win_height = glutGet(GLUT_WINDOW_HEIGHT); glUnproject(x, win_height-y, 0, &u, &v, &z); if( u<0 ) u = 0; if( v<0 ) v = 0; if( u>(DEM->width-1) ) u = DEM->width-1; if( v>(DEM->height-1) ) v = DEM->height-1; Vec2 p(u,v); cout << "Inserting point: " << p << endl; mesh->insert(p); redisplay_all(surf_view); } else if( button == GLUT_MIDDLE_BUTTON ) { display_greedy_insertion(mesh_display); redisplay_all(surf_view); } } } //////////////////////////////////////////////////////////////////////// // // Surface functions // //////////////////////////////////////////////////////////////////////// static void synthesize_normal(const Vec3& p1, const Vec3& p2,const Vec3& p3) { // We explicitly declare these (rather than putting them in a // Vector) so that they can be allocated into registers. real v1x = p2[X]-p1[X], v1y = p2[Y]-p1[Y], v1z = p2[Z]-p1[Z]; real v2x = p3[X]-p2[X], v2y = p3[Y]-p2[Y], v2z = p3[Z]-p2[Z]; // // NOTE: We do not unitize the normal vectors here because // they will be normalized in the graphics pipeline. // We have to enable GL_NORMALIZE because of the height // scaling we're doing. So why bother normalizing now // when they're just going to get munged? // glN(v1y*v2z - v1z*v2y, v1z*v2x - v1x*v2z, v1x*v2y - v1y*v2x); } void render_face(Triangle& T, void *) { const Vec2& p1 = T.point1(); const Vec2& p2 = T.point2(); const Vec2& p3 = T.point3(); Vec3 v1(p1, DEM->eval(p1[X],p1[Y])); Vec3 v2(p2, DEM->eval(p2[X],p2[Y])); Vec3 v3(p3, DEM->eval(p3[X],p3[Y])); synthesize_normal(v1, v2, v3); glV(v1[X], v1[Y], v1[Z]); glV(v2[X], v2[Y], v2[Z]); glV(v3[X], v3[Y], v3[Z]); } static long statex, statey; static enum {NoDrag, Spin, Dolly, Zoom } dragging = NoDrag; static float rotx = 0, roty = 0, rotz = 0; void surf_display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); float w = (float)DEM->width; float h = (float)DEM->height; float cx = w / 2.0f; float cy = h / 2.0f; float cz = (float)DEM->min + (float)(DEM->max - DEM->min) / 2.0f; glRotatef(rotx, 1.0, 0.0, 0.0); glRotatef(roty, 0.0, 1.0, 0.0); glRotatef(rotz, 0.0, 0.0, 1.0); glScalef(1.0f, 1.0f, (float)height_scale); glTranslatef(-cx, -cy, -cz); glScalef(1.0f, -1.0f, 1.0f); glTranslatef(0.0f, 1-h, 0.0f); glBegin(GL_TRIANGLES); mesh->overFaces(render_face); glEnd(); glPopMatrix(); glutSwapBuffers(); } void surf_mouse(int button, int state, int x, int y) { if( state == GLUT_UP ) { dragging = NoDrag; return; } statex = x; statey = y; switch( button ) { case GLUT_LEFT_BUTTON: dragging = Spin; break; case GLUT_MIDDLE_BUTTON: dragging = Dolly; break; case GLUT_RIGHT_BUTTON: dragging = Zoom; break; } } void surf_motion(int x, int y) { switch( dragging ) { case Spin: rotx += (float)(y - statey); roty += (float)(x - statex); statex = x; statey = y; glutPostRedisplay(); break; case Dolly: glMatrixMode(GL_PROJECTION); glTranslatef((float)(x - statex), (float)(statey - y), 0.0f); statex = x; statey = y; glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); break; case Zoom: glMatrixMode(GL_PROJECTION); glTranslatef(0, 0, (float)(y - statey)); statey = y; glMatrixMode(GL_MODELVIEW); glutPostRedisplay(); break; default: break; } } void init_surf_view(GreedySubdivision& mesh) { glClearColor(0.3125, 0.3125, 1.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); ////////////////////// // // Define viewing parameters // Map& map = mesh.getData(); real width = (real)map.width; real height = (real)map.height; real depth = map.max - map.min; xglutKeepAspect(width, height); glMatrixMode(GL_PROJECTION); gluPerspective(45.0, width/height, 0.1, 10*depth); gluLookAt(0, 0, depth, 0, 0, 0, 0, 1, 0); glMatrixMode(GL_MODELVIEW); ////////////////////// // // Define lighting parameters // glShadeModel(GL_SMOOTH); GLfloat mat_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; GLfloat mat_diffuse[] = { 0.6, 0.6, 0.6, 1.0 }; // GLfloat mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); // glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); GLfloat light_pos[] = { 1.0, 0.0, 1.0, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_pos); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); } void gui_init() { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); surf_view = glutCreateWindow("TERRA: Surface"); init_surf_view(*mesh); glutDisplayFunc(surf_display); glutMouseFunc(surf_mouse); glutMotionFunc(surf_motion); // --------------------------------------------------------------------- glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); mesh_view = glutCreateWindow("TERRA: Mesh"); xglutKeepAspect(DEM->width, DEM->height); create_mesh_menus(); glutDisplayFunc(mesh_display); glutMouseFunc(mesh_mouse); glMatrixMode(GL_PROJECTION); gluOrtho2D(-1, DEM->width,DEM->height, -1); // gluOrtho2D(0, DEM->width-1, DEM->height-1, 0); glMatrixMode(GL_MODELVIEW); glClearColor(0.0, 0.0, 0.0, 0.0); } void gui_interact() { glutMainLoop(); } //////////////////////////////////////////////////////////////////////// // // WARNING: Entering hack zone! // // GLUT does not provide a function for setting the aspect // ratio of a window. We want to do this. Hence the following. // //////////////////////////////////////////////////////////////////////// extern "C" { #include } void xglutKeepAspect(float width, float height) { Window win; XSizeHints hints; if( __glutCurrentWindow ) { win = __glutCurrentWindow->win; hints.flags = PAspect; hints.min_aspect.x = hints.max_aspect.x = (int)(1000*width); hints.min_aspect.y = hints.max_aspect.y = (int)(1000*height); XSetWMNormalHints(__glutDisplay, win, &hints); } }