/*****************************************************************************/ /* */ /* F I S T : Fast, Industrial-Strength Triangulation */ /* */ /*****************************************************************************/ /* */ /* (C) Martin Held */ /* (C) Universitaet Salzburg, Salzburg, Austria */ /* */ /* This code is not in the public domain. All rights reserved! Please make */ /* sure to read the full copyright statement contained in api_functions.cpp. */ /* */ /*****************************************************************************/ #ifdef GRAPHICS //Uncomment this to enable text printing in opengl environments #define OGL_ENABLE_TEXT #ifdef OGL_ENABLE_TEXT #include int enableText = 0; #endif /* */ /* get standard libraries */ /* */ #include //#define MARTINS_FLASH_DEMO #include #include #include #include #ifdef MARTINS_FLASH_DEMO #include #endif /* */ /* get OpenGL include files */ /* */ #ifdef __APPLE__ #include #else #include /* glut.h includes gl.h and glu.h */ #endif /* */ /* get my header files */ /* */ #include "fpkernel.h" #include "martin.h" #include "graphics.h" #include "ext_appl_defs.h" #include "defs.h" #include "header.h" #include "api_fist.h" /* */ /* some global constants */ /* */ #define XNumPixel 900 #define YNumPixel 900 #define XPosition 0 #define YPosition 0 #define Radius 4.0 #define ESC 27 #if !defined(GLUT_WHEEL_UP) # define GLUT_WHEEL_UP 3 # define GLUT_WHEEL_DOWN 4 #endif /* */ /* prototypes of functions provided in this file */ /* */ void InitializeGraphics(int argc, char *argv[], global_struct *all); void ProcessGraphicsEvents(void); /* */ /* OpenGL-specific declarations */ /* */ static int my_window = NIL; #ifdef MARTINS_FLASH_DEMO static boolean flash_demo = true; static boolean triang_computed = false; #endif static boolean poly_started = false; static boolean zoom = false; static boolean query = false; static boolean query_seg = false; static boolean query_pnt = false; static boolean full_screen_mode = false; static boolean one_corner_received = false; static boolean left_mouse_button_down = false; static machine_double xl, yl, xr, yr; static machine_double scale, xm, ym; static GLint im, jm; static coord start, end; static GLint pix_i1, pix_j1; static GLint x_pos = XPosition, y_pos = YPosition; static GLint x_size = XNumPixel, y_size = YNumPixel; static GLint width_pxl = XNumPixel, height_pxl = YNumPixel; static GLint old_mouse_x, old_mouse_y; typedef struct { GLdouble r; GLdouble g; GLdouble b; GLdouble a; } tcolor; static tcolor colors[10]; static int BGcolor = Black; static boolean tri_filled = true; typedef enum {quit, togglePNT, toggleFill, zoomIn, zoomOut, unZoom} oglMenu; static global_struct *ogl_all; /* */ /* OpenGL-specific graphics functions */ /* */ void FreeGraphics(void) { if (my_window != NIL) glutDestroyWindow(my_window); return; } void ResetRubberLine() { one_corner_received = false; return; } void SetUpColorTable(boolean color_graphics) { int i; if (color_graphics) { colors[Green].r = 0.0; colors[Green].g = 0.1; colors[Green].b = 0.0; colors[Green].a = 0.0; colors[Blue].r = 0.0; colors[Blue].g = 0.0; colors[Blue].b = 1.0; colors[Blue].a = 0.0; colors[White].r = 1.0; colors[White].g = 1.0; colors[White].b = 1.0; colors[White].a = 0.0; colors[Red].r = 1.0; colors[Red].g = 0.0; colors[Red].b = 0.0; colors[Red].a = 0.0; colors[Cyan].r = 0.0; colors[Cyan].g = 1.0; colors[Cyan].b = 1.0; colors[Cyan].a = 0.0; colors[Yellow].r = 1.0; colors[Yellow].g = 1.0; colors[Yellow].b = 0.0; colors[Yellow].a = 0.0; colors[Orange].r = 1.0; colors[Orange].g = 165.0 / 255.0; colors[Orange].b = 0.0; colors[Orange].a = 0.0; colors[Magenta].r = 1.0; colors[Magenta].g = 0.0; colors[Magenta].b = 1.0; colors[Magenta].a = 0.0; colors[Black].r = 0.0; colors[Black].g = 0.0; colors[Black].b = 0.0; colors[Black].a = 0.0; colors[NoColor].r = 0.0; colors[NoColor].g = 0.0; colors[NoColor].b = 0.0; colors[NoColor].a = 0.0; colors[Gray].r = 0.6; colors[Gray].g = 0.6; colors[Gray].b = 0.6; colors[Gray].a = 0.6; BGcolor = Black; } else { for (i = 0; i < NumColors; ++i) { colors[i].r = 0.0; colors[i].g = 0.0; colors[i].b = 0.0; colors[i].a = 0.0; } colors[White].r = 1.0; colors[White].g = 1.0; colors[White].b = 1.0; colors[White].a = 0.0; BGcolor = White; } return; } void SetBB(machine_double xl_bb, machine_double yl_bb, machine_double xr_bb, machine_double yr_bb) { xl = xl_bb; xr = xr_bb; yl = yl_bb; yr = yr_bb; return; } /* */ /* maps world coordinates to window pixels; the origin of the window is */ /* assumed to be located in the lower-left corner. im and jm denote the */ /* pixel coordinates of the rectangle's center (with world coordinates xm */ /* and ym). */ /* */ void MapWorldCoordinates(machine_double x, machine_double y, GLint *pix_i, GLint *pix_j) { *pix_i = im + (x - xm) * scale; *pix_j = jm + (y - ym) * scale; return; } /* */ /* maps window pixels to world coordinates; the origin of the window is */ /* assumed to be located in the lower-left corner. im and jm denote the */ /* pixel coordinates of the rectangle's center (with world coordinates xm */ /* and ym). */ /* */ void MapWindowCoordinates(GLint pix_i, GLint pix_j, machine_double *x, machine_double *y) { *x = ((machine_double) (pix_i - im)) / scale + xm; *y = ((machine_double) (pix_j - jm)) / scale + ym; return; } void AdjustClipCoords(void) { MapWindowCoordinates(0, 0, &xl, &yl); MapWindowCoordinates(width_pxl, height_pxl, &xr, &yr); return; } void InitializeMapping(void) { machine_double scale_x, scale_y; /* */ /* compute a scale factor such that the real-world data inside the */ /* bounding box [xl,xr] times [yl,yr] fits nicely into a window of size */ /* width_pxl times height_pxl, without causing distortion. */ /* */ scale_x = (machine_double) width_pxl / (ZERO_D + xr - xl); scale_y = (machine_double) height_pxl / (ZERO_D + yr - yl); if (scale_x <= scale_y) scale = scale_x; else scale = scale_y; assert(scale > 0.0); /* */ /* obtain the coordinates of the center in real-world and screen space */ /* */ xm = (xl + xr) / 2.0; ym = (yl + yr) / 2.0; im = width_pxl / 2; jm = height_pxl / 2; /* */ /* adjust the bounding box such that it reflects the real-world region */ /* that will be visible on the screen */ /* */ AdjustClipCoords(); return; } void DefineCamera(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(xl, xr, yl, yr); return; } void DefineView(void) { InitializeMapping(); DefineCamera(); return; } void UpdateScaleData(void) { machine_double delta_x, delta_y; delta_x = (TO_MDOUBLE(ogl_all->bb_max.x) - TO_MDOUBLE(ogl_all->bb_min.x)) / 16.0; delta_y = (TO_MDOUBLE(ogl_all->bb_max.y) - TO_MDOUBLE(ogl_all->bb_min.y)) / 16.0; SetBB(TO_MDOUBLE(ogl_all->bb_min.x - delta_x), TO_MDOUBLE(ogl_all->bb_min.y - delta_y), TO_MDOUBLE(ogl_all->bb_max.x + delta_x), TO_MDOUBLE(ogl_all->bb_max.y + delta_y)); DefineView(); return; } void FlushDisplay(void) { //glFlush(); glutSwapBuffers(); return; } void DrawRectangle(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, GLdouble r1, GLdouble g1, GLdouble b1, GLdouble a1, GLdouble r2, GLdouble g2, GLdouble b2, GLdouble a2, boolean filled, GLint stipple_factor, GLushort stipple_pattern) { if (filled) { glColor4d(r1, g1, b1, a1); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glRectd(x1, y1, x2, y2); glLineWidth(2.0); } glColor4d(r2, g2, b2, a2); if (stipple_pattern != 0xFFFF) { glEnable(GL_LINE_STIPPLE); glLineStipple(stipple_factor, stipple_pattern); glLineWidth(1.0); } else { glDisable(GL_LINE_STIPPLE); } glBegin(GL_LINE_LOOP); glVertex2d(x1, y1); glVertex2d(x2, y1); glVertex2d(x2, y2); glVertex2d(x1, y2); glEnd(); glLineWidth(1.0); return; } void DrawRect(coord pnt1, coord pnt2, int obj_color, boolean filled, GLint stipple_factor, GLushort stipple_pattern) { DrawRectangle(pnt1.x, pnt1.y, pnt2.x, pnt2.y, colors[obj_color].r, colors[obj_color].g, colors[obj_color].b, colors[obj_color].a, colors[obj_color].r, colors[obj_color].g, colors[obj_color].b, colors[obj_color].a, filled, stipple_factor, stipple_pattern); return; } void DrawTriangle(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, GLdouble x3, GLdouble y3, GLdouble r1, GLdouble g1, GLdouble b1, GLdouble a1, GLdouble r2, GLdouble g2, GLdouble b2, GLdouble a2, boolean filled, GLint stipple_factor, GLushort stipple_pattern) { if (filled) { glColor4d(r2, g2, b2, a2); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glBegin(GL_TRIANGLES); glVertex2d(x1, y1); glVertex2d(x2, y2); glVertex2d(x3, y3); glEnd(); glLineWidth(0.0); } glColor4d(r1, g1, b1, a1); if (stipple_pattern != 0xFFFF) { glEnable(GL_LINE_STIPPLE); glLineStipple(stipple_factor, stipple_pattern); glLineWidth(1.0); } else { glDisable(GL_LINE_STIPPLE); } glBegin(GL_LINE_LOOP); glVertex2d(x1, y1); glVertex2d(x2, y2); glVertex2d(x3, y3); glEnd(); glLineWidth(1.0); return; } void DrawTri(point pnt1, point pnt2, point pnt3, int color1, int color2) { DrawTriangle(TO_MDOUBLE(pnt1.x), TO_MDOUBLE(pnt1.y), TO_MDOUBLE(pnt2.x), TO_MDOUBLE(pnt2.y), TO_MDOUBLE(pnt3.x), TO_MDOUBLE(pnt3.y), colors[color1].r, colors[color1].g, colors[color1].b, colors[color1].a, colors[color2].r, colors[color2].g, colors[color2].b, colors[color2].a, tri_filled, 1, 0xFFFF); return; } void DrawSegment(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2, GLdouble r, GLdouble g, GLdouble b, GLdouble a, GLdouble line_width, GLint stipple_factor, GLushort stipple_pattern) { glColor4d(r, g, b, a); glLineWidth(line_width); if (stipple_pattern != 0xFFFF) { glEnable(GL_LINE_STIPPLE); glLineStipple(stipple_factor, stipple_pattern); } else { glDisable(GL_LINE_STIPPLE); } glBegin(GL_LINES); glVertex2d(x1, y1); glVertex2d(x2, y2); glEnd(); return; } void DrawSeg(point pnt1, point pnt2, int color) { DrawSegment(TO_MDOUBLE(pnt1.x), TO_MDOUBLE(pnt1.y), TO_MDOUBLE(pnt2.x), TO_MDOUBLE(pnt2.y), colors[color].r, colors[color].g, colors[color].b, colors[color].a, 1.0, 1, 0xFFFF); return; } void DrawPoint(GLdouble x1, GLdouble y1, GLdouble r, GLdouble g, GLdouble b, GLdouble a, GLfloat pnt_size) { glColor4d(r, g, b, a); glPointSize(pnt_size); glBegin(GL_POINTS); glVertex2d(x1, y1); glEnd(); return; } void DrawPnt(point pnt, int color) { DrawPoint(TO_MDOUBLE(pnt.x), TO_MDOUBLE(pnt.y), colors[color].r, colors[color].g, colors[color].b, colors[color].a, Radius); return; } void DrawText(point pnt, int color, char* text) { char *c; glColor4d(colors[color].r, colors[color].g, colors[color].b, colors[color].a); glRasterPos2f(TO_MDOUBLE(pnt.x), TO_MDOUBLE(pnt.y)); for (c=text; *c != '\0'; c++) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *c); } return; } void QuickDisplay() { glClear(GL_COLOR_BUFFER_BIT); Redraw(ogl_all); /* */ /* draw "rubber bands" to indicate objects that are currently been drawn */ /* by moving the mouse */ /* */ if (one_corner_received) { if (zoom) { DrawRect(start, end, Magenta, false, 1, 0x00FF); } else if (poly_started) { DrawSegment(start.x, start.y, end.x, end.y, colors[PolyColor].r, colors[PolyColor].g, colors[PolyColor].b, colors[PolyColor].a, 1.0, 1, 0x00FF); } } glutSwapBuffers(); return; } void ResetGraphicsData(void) { one_corner_received = false; zoom = false; query = false; poly_started = false; if (ogl_all->rt_opt.graphics) { glClear(GL_COLOR_BUFFER_BIT); glutPostRedisplay(); } return; } void UnZoom(void) { UpdateScaleData(); glutPostRedisplay(); return; } void ZoomOut(void) { scale *= 0.5; AdjustClipCoords(); DefineCamera(); glutPostRedisplay(); return; } void ZoomIn(void) { scale *= 2.0; AdjustClipCoords(); DefineCamera(); glutPostRedisplay(); return; } void ZoomInOnMouse(GLint mouse_x, GLint mouse_y) { double delta_x, delta_y; delta_x = (xr - xl)/width_pxl; delta_y = (yr - yl)/height_pxl; xr += (mouse_x - width_pxl/2)*delta_x; xl += (mouse_x - width_pxl/2)*delta_x; yr -= (mouse_y - height_pxl/2)*delta_y; yl -= (mouse_y - height_pxl/2)*delta_y; DefineView(); ZoomIn(); delta_x = (xr - xl)/width_pxl; delta_y = (yr - yl)/height_pxl; xr -= (mouse_x - width_pxl/2)*delta_x; xl -= (mouse_x - width_pxl/2)*delta_x; old_mouse_x = mouse_x; yr += (mouse_y - height_pxl/2)*delta_y; yl += (mouse_y - height_pxl/2)*delta_y; old_mouse_y = mouse_y; DefineView(); glutPostRedisplay(); } void ZoomOutOnMouse(GLint mouse_x, GLint mouse_y) { double delta_x, delta_y; delta_x = (xr - xl)/width_pxl; delta_y = (yr - yl)/height_pxl; xr += (mouse_x - width_pxl/2)*delta_x; xl += (mouse_x - width_pxl/2)*delta_x; yr -= (mouse_y - height_pxl/2)*delta_y; yl -= (mouse_y - height_pxl/2)*delta_y; DefineView(); ZoomOut(); delta_x = (xr - xl)/width_pxl; delta_y = (yr - yl)/height_pxl; xr -= (mouse_x - width_pxl/2)*delta_x; xl -= (mouse_x - width_pxl/2)*delta_x; old_mouse_x = mouse_x; yr += (mouse_y - height_pxl/2)*delta_y; yl += (mouse_y - height_pxl/2)*delta_y; old_mouse_y = mouse_y; DefineView(); glutPostRedisplay(); } void ScrollLeft(void) { machine_double delta; delta = (xr - xl) / 8.0; xr -= delta; xl -= delta; DefineView(); glutPostRedisplay(); return; } void ScrollRight(void) { machine_double delta; delta = (xr - xl) / 8.0; xr += delta; xl += delta; DefineView(); glutPostRedisplay(); return; } void ScrollUp(void) { machine_double delta; delta = (yr - yl) / 8.0; yr += delta; yl += delta; DefineView(); glutPostRedisplay(); return; } void ScrollDown(void) { machine_double delta; delta = (yr - yl) / 8.0; yr -= delta; yl -= delta; DefineView(); glutPostRedisplay(); return; } void TrackLine(GLint pix_i2, GLint pix_j2, machine_double *x1, machine_double *y1, machine_double *x2, machine_double *y2) { MapWindowCoordinates(pix_i1, pix_j1, x1, y1); MapWindowCoordinates(pix_i2, pix_j2, x2, y2); return; } void TrackRectangle(GLint pix_i2, GLint pix_j2, machine_double *x1, machine_double *y1, machine_double *x2, machine_double *y2) { if (pix_i1 == pix_i2) pix_i2 += 1; if (pix_j1 == pix_j2) pix_j2 += 1; if (pix_i1 < pix_i2) { if (pix_j1 < pix_j2) { MapWindowCoordinates(pix_i1, pix_j1, x1, y1); MapWindowCoordinates(pix_i2, pix_j2, x2, y2); } else { MapWindowCoordinates(pix_i1, pix_j2, x1, y1); MapWindowCoordinates(pix_i2, pix_j1, x2, y2); } } else { if (pix_j1 < pix_j2) { MapWindowCoordinates(pix_i2, pix_j1, x1, y1); MapWindowCoordinates(pix_i1, pix_j2, x2, y2); } else { MapWindowCoordinates(pix_i2, pix_j2, x1, y1); MapWindowCoordinates(pix_i1, pix_j1, x2, y2); } } return; } void ZoomToRegion(GLint pix_i2, GLint pix_j2) { machine_double new_xl, new_xr, new_yl, new_yr; if (one_corner_received) { TrackRectangle(pix_i2, pix_j2, &new_xl, &new_yl, &new_xr, &new_yr); SetBB(new_xl, new_yl, new_xr, new_yr); DefineView(); zoom = false; one_corner_received = false; glutPostRedisplay(); } else { pix_i1 = pix_i2; pix_j1 = pix_j2; one_corner_received = true; } return; } void ToggleScreenMode(void) { full_screen_mode = !full_screen_mode; if (full_screen_mode) { /* */ /* save current parameters and go to full-screen mode */ /* */ x_pos = glutGet((GLenum)GLUT_WINDOW_X); y_pos = glutGet((GLenum)GLUT_WINDOW_Y); x_size = glutGet((GLenum)GLUT_WINDOW_WIDTH); y_size = glutGet((GLenum)GLUT_WINDOW_HEIGHT); glutFullScreen(); width_pxl = glutGet((GLenum)GLUT_WINDOW_WIDTH); height_pxl = glutGet((GLenum)GLUT_WINDOW_HEIGHT); } else { /* */ /* restore old settings */ /* */ glutReshapeWindow(x_size, y_size); glutPositionWindow(x_pos, y_pos); width_pxl = x_size; height_pxl = y_size; } glViewport(0, 0, width_pxl, height_pxl); DefineView(); glutPostRedisplay(); return; } void ClosePolygon(global_struct *all, int curr_loop, boolean *new_input) { iolistdef *iolist = &all->c_iolist; datadef *data = &all->c_data; listdef *list = &all->c_list; redrawdef *redraw = &all->c_redraw; if (iolist->new_pnts >= 3) { assert(iolist->first_pnt >= 0); assert(iolist->first_pnt != iolist->last_pnt); assert(iolist->last_pnt >= 0); AddEdgeToBuffer(redraw, iolist->last_pnt, iolist->first_pnt, PolyColor); DrawSeg(data->points[iolist->last_pnt], data->points[iolist->first_pnt], PolyColor); *new_input = true; DeleteHook(list, curr_loop); } else { DecrementLoops(list); if (iolist->new_pnts >= 1) { DecrementPoints(data); DecrementPntBuffer(redraw); } if (iolist->new_pnts == 2) { DecrementPoints(data); DecrementPntBuffer(redraw); DecrementEdgeBuffer(redraw); } FIST_Warning("No polygon to close!"); } iolist->first_pnt = NIL; iolist->last_pnt = NIL; iolist->new_pnts = 0; return; } void HandleKeyPress(unsigned char key, GLint pix_i1, GLint pix_j1) { (void) pix_i1; (void) pix_j1; zoom = false; switch (key) { case '?': /* */ /* prepare for interactive debug query */ /* */ query = true; break; case 'c': case 'C': /* */ /* close polygon */ /* */ if (poly_started) { poly_started = false; one_corner_received = false; ClosePolygon(ogl_all, ogl_all->curr_loop_main, &ogl_all->new_input); glutPostRedisplay(); } break; case 'd': case 'D': /* */ /* delete; clear drawing canvas and reset all variables */ /* */ ResetAll(ogl_all); break; #ifdef EXPR_WRAPPER case 'e' : case 'E' : /* */ /* toogle the returncore variable */ /* */ returncore = !returncore; break; #endif case 'f': case 'F': /* */ /* toggle the filling of the triangles */ /* */ tri_filled = !tri_filled; glutPostRedisplay(); break; case 'h': case 'H': /* */ /* print help message */ /* */ Help(); EvalError(); break; case 'i': case 'I': /* */ /* zoom in */ /* */ ZoomIn(); break; case 'm': case 'M': /* */ /* toggle the drawing of the vertex markers */ /* */ ogl_all->draw_pnts = !ogl_all->draw_pnts; glutPostRedisplay(); break; case '1': /* */ /* toggle the drawing of the vertex markers */ /* */ ogl_all->draw_point_idx = !ogl_all->draw_point_idx; glutPostRedisplay(); break; case 'o': case 'O': /* */ /* zoom out */ /* */ ZoomOut(); break; case 'p': case 'P': /* */ /* read data from the graphics window */ /* */ if (query) { query = false; query_pnt = true; } else { /* */ /* start new polygon */ /* */ query = false; one_corner_received = false; if (!poly_started) { poly_started = true; ogl_all->curr_loop_main = MakeLoopHeader(&ogl_all->c_list); ResetRubberLine(); } } break; case 'q': case 'Q': case ESC: /* */ /* termination of program */ /* */ StatisticsFIST(ogl_all); FIST_TerminateProgram(ogl_all); FreeGraphics(); exit(0); break; case 'r' : case 'R' : /* */ /* refresh window */ /* */ glutPostRedisplay(); break; case 's': case 'S': if (query) { query = false; query_seg = true; } break; case 't': case 'T': /* */ /* compute triangulation */ /* */ one_corner_received = false; query = false; if (!ogl_all->done) { if (poly_started) { ClosePolygon(ogl_all, ogl_all->curr_loop_main, &ogl_all->new_input); poly_started = false; glutPostRedisplay(); } Compute(ogl_all); } ogl_all->new_input = false; if (ogl_all->done) glutPostRedisplay(); else FlushDisplay(); break; case 'u': case 'U': /* */ /* unzoom */ /* */ UnZoom(); break; case 'z': case 'Z': /* */ /* prepare for zooming */ /* */ zoom = true; query = false; poly_started = false; one_corner_received = false; break; default: FIST_Warning("HandleKeyPress() - unknown key pressed!\n"); break; } return; } void IdleFunction(void) { #ifdef MARTINS_FLASH_DEMO if (flash_demo) { if (triang_computed) { sleep(3); HandleKeyPress('q', 0, 0); } else { if (ogl_all->c_data.num_pnts < 10000) sleep(1); triang_computed = true; HandleKeyPress('t', 0, 0); } } #endif return; } void HandleMouseMotion(GLint mouse_x, GLint mouse_y) { GLint pix_j2 = height_pxl - mouse_y; double delta_x, delta_y; if (one_corner_received) { if (zoom) { TrackRectangle(mouse_x, pix_j2, &start.x, &start.y, &end.x, &end.y); glutPostRedisplay(); } else if (poly_started) { TrackLine(mouse_x, pix_j2, &start.x, &start.y, &end.x, &end.y); glutPostRedisplay(); } } else if(left_mouse_button_down) { delta_x = (xr - xl)/width_pxl; delta_y = (yr - yl)/height_pxl; if(old_mouse_x - mouse_x != 0) { xr += delta_x*(old_mouse_x - mouse_x); xl += delta_x*(old_mouse_x - mouse_x); old_mouse_x = mouse_x; } if(old_mouse_y - mouse_y != 0) { yr -= delta_y*(old_mouse_y - mouse_y); yl -= delta_y*(old_mouse_y - mouse_y); old_mouse_y = mouse_y; } DefineView(); glutPostRedisplay(); } return; } void HandleReshape(GLint width, GLint height) { width_pxl = width; height_pxl = height; glViewport(0, 0, width_pxl, height_pxl); DefineView(); glutPostRedisplay(); return; } void HandleSpecialKeys(int key, GLint pix_i1, GLint pix_j1) { (void) pix_i1; (void) pix_j1; switch (key) { case GLUT_KEY_F1: /* */ /* toggle full-screen mode */ /* */ ToggleScreenMode(); break; case GLUT_KEY_LEFT: /* */ /* scroll to the left */ /* */ ScrollLeft(); break; case GLUT_KEY_UP: /* */ /* scroll to the left */ /* */ ScrollUp(); break; case GLUT_KEY_RIGHT: /* */ /* scroll to the left */ /* */ ScrollRight(); break; case GLUT_KEY_DOWN: /* */ /* scroll to the left */ /* */ ScrollDown(); break; default: FIST_Warning("HandleSpecialKeys() - key of unkown type!\n"); break; } return; } void HandleMenu(int item) { switch (item) { case quit: HandleKeyPress('q', 0, 0); break; case zoomIn: HandleKeyPress('i', 0, 0); break; case zoomOut: HandleKeyPress('o', 0, 0); break; case unZoom: HandleKeyPress('u', 0, 0); break; } return; } void HandleZoomMenu(int item) { switch (item) { case zoomIn: HandleKeyPress('i', 0, 0); break; case zoomOut: HandleKeyPress('o', 0, 0); break; case unZoom: HandleKeyPress('u', 0, 0); break; } return; } void ChangeMenuItem(boolean *item_flag, const char* menuString, int item) { char my_string[100]; my_string[0] = '\0'; strcat(my_string, menuString); if (*item_flag) { *item_flag = false; strcat(my_string, ": on"); glutChangeToMenuEntry(item, my_string, item); } else { *item_flag = true; strcat(my_string, ": off"); glutChangeToMenuEntry(item, my_string, item); } glutPostRedisplay(); return; } void HandleViewMenu(int item) { switch (item) { case togglePNT: ChangeMenuItem(&ogl_all->draw_pnts, "Points/vertices", togglePNT); break; case toggleFill: ChangeMenuItem(&tri_filled, "Triangles filled", toggleFill); break; } glutPostRedisplay(); return; } void ProcessMouseClick(global_struct *all, int curr_loop, int x, int y) { iolistdef *iolist = &all->c_iolist; listdef *list = &all->c_list; redrawdef *redraw = &all->c_redraw; datadef *data = &all->c_data; machine_double xc1, yc1; int i; list_ind ind; MapWindowCoordinates(x, y, &xc1, &yc1); #ifdef EXT_APPL_SITES i = StorePnt(data, xc1, yc1, eas_NIL); #else i = StorePnt(data, xc1, yc1); #endif AddPntToBuffer(redraw, i, PntsColor); end.x = xc1; end.y = yc1; if (iolist->first_pnt < 0) { iolist->first_pnt = i; iolist->last_pnt = i; iolist->last_ind = list->loops[curr_loop]; start = end; } else { AddEdgeToBuffer(redraw, iolist->last_pnt, i, PolyColor); DrawSeg(data->points[iolist->last_pnt], data->points[i], PolyColor); iolist->last_pnt = i; } DrawPnt(data->points[i], PntsColor); ind = MakeNode(list, i); InsertAfter(list, iolist->last_ind, ind); iolist->last_ind = ind; ++iolist->new_pnts; return; } void HandleMouseButton(int button, int state, GLint pix_i2, GLint pix_j2) { // double x2, y2; switch (button) { case GLUT_LEFT_BUTTON : if(state == GLUT_UP) { left_mouse_button_down = false; pix_j2 = height_pxl - pix_j2; if (zoom) { ZoomToRegion(pix_i2, pix_j2); } /* else if (query_pnt || query_seg || query_nde) { MapWindowCoordinates(pix_i2, pix_j2, &x2, &y2); if (query_pnt) FindClosestPnt(x2, y2); else if (query_seg) FindClosestSeg(x2, y2); query_pnt = query_seg = query = false; glutPostRedisplay(); } */ else if (poly_started) { /* */ /* read mouse input from graphics window */ /* */ ProcessMouseClick(ogl_all, ogl_all->curr_loop_main, pix_i2, pix_j2); one_corner_received = true; pix_i1 = pix_i2; pix_j1 = pix_j2; FlushDisplay(); //glutPostRedisplay(); } } else if(state == GLUT_DOWN) { /* pan scene round with the left mouse button */ left_mouse_button_down = true; old_mouse_x = pix_i2; old_mouse_y = pix_j2; } break; case GLUT_WHEEL_UP: if (state != GLUT_UP) { ZoomInOnMouse(pix_i2, pix_j2); } break; case GLUT_WHEEL_DOWN: if (state != GLUT_UP) { ZoomOutOnMouse(pix_i2, pix_j2); } break; default: break; } return; } void InitializeGraphics(int argc, char *argv[], global_struct *all) { int mainMenu, zoomMenu, viewMenu; char window_name[80]; /* */ /* make the structure "all" known to my graphics routines */ /* */ ogl_all = all; /* */ /* graphics start-up */ /* */ glutInit(&argc, argv); /* init OpenGL */ glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); /* double buffering, and RGB colors */ /* */ /* set window position and size */ /* */ glutInitWindowSize(width_pxl, height_pxl);/* XNumPixel x YNumPixel window */ glutInitWindowPosition(x_pos, y_pos); /* upper-left corner of window */ /* */ /* window creation */ /* */ sprintf(window_name, "%9s %3s (C) M. Held %9s", FIST_GetProgName(), FIST_GetProgVersion(), FIST_GetProgYear()); my_window = glutCreateWindow(window_name); if (ogl_all->rt_opt.full_screen) { glutFullScreen(); /* Go to full screen */ width_pxl = glutGet((GLenum)GLUT_WINDOW_WIDTH); height_pxl = glutGet((GLenum)GLUT_WINDOW_HEIGHT); full_screen_mode = true; } /* */ /* init graphics variables */ /* */ SetUpColorTable(ogl_all->rt_opt.color_graphics); glViewport(0, 0, width_pxl, height_pxl); glClearColor(colors[BGcolor].r, /* set background color */ colors[BGcolor].g, colors[BGcolor].b, colors[BGcolor].a); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glLineWidth(1.0); /* */ /* initialize the bounding box of the data */ /* */ ogl_all->bb_min.x = xl = 0.0; ogl_all->bb_min.y = yl = 0.0; ogl_all->bb_max.x = xr = (machine_double) width_pxl; ogl_all->bb_max.y = yr = (machine_double) height_pxl; SetBoundingBox(&ogl_all->c_data, &ogl_all->bb_min, &ogl_all->bb_max); UpdateScaleData(); old_mouse_x = (int)width_pxl/2; old_mouse_y = (int)height_pxl/2; glutWarpPointer(old_mouse_x, old_mouse_y); /* */ /* input event selection */ /* */ glutDisplayFunc(QuickDisplay); glutKeyboardFunc(HandleKeyPress); glutReshapeFunc(HandleReshape); glutMouseFunc(HandleMouseButton); glutMotionFunc(HandleMouseMotion); glutPassiveMotionFunc(HandleMouseMotion); glutSpecialFunc(HandleSpecialKeys); #ifdef MARTINS_FLASH_DEMO if (flash_demo) glutIdleFunc(IdleFunction); #endif /* */ /* create menus */ /* */ zoomMenu = glutCreateMenu(HandleZoomMenu); glutAddMenuEntry("Zoom in", zoomIn); glutAddMenuEntry("Zoom out", zoomOut); glutAddMenuEntry("Unzoom", unZoom); viewMenu = glutCreateMenu(HandleViewMenu); if (ogl_all->draw_pnts) glutAddMenuEntry("Points/vertices: off", togglePNT); else glutAddMenuEntry("Points/vertices: on", togglePNT); if (tri_filled) glutAddMenuEntry("Triangles filled: off", toggleFill); else glutAddMenuEntry("Triangles filled: on", toggleFill); mainMenu = glutCreateMenu(HandleMenu); glutAddSubMenu("Zoom in/out", zoomMenu); glutAddSubMenu("Toggle display parameters", viewMenu); glutAddMenuEntry("Quit", quit); glutAttachMenu(GLUT_RIGHT_BUTTON); (void) mainMenu; return; } void ProcessGraphicsEvents(void) { UpdateScaleData(); glutMainLoop(); /* OpenGL's event-handling loop */ return; } #endif /* GRAPHICS */