/* do_zoom.c -- This file contains routines to dump series of enlarged images to ppm */ /* gsf includes */ #define USE_GL_NORMALIZE #include /* Nvision includes */ #include "interface.h" /* Standard includes*/ #include #include #include #ifdef OPENGL_X11 #include #include #include static Display *dpy; static Window root; static GLXContext ctx_orig; #ifdef HAVE_PBUFFERS static GLXPbuffer pbuffer; #endif #ifdef HAVE_PIXMAPS Pixmap pixmap; static GLXPixmap glxpixmap; #endif #endif /* OPENGL_X11 */ extern void swap_togl(void); /**********************************************/ int Nstart_zoom_cmd(Nv_data * data, /* Local data */ Tcl_Interp * interp, /* Current interpreter */ int argc, /* Number of arguments */ char **argv /* Argument strings */ ) { int a, b, c, d; int a_orig, b_orig, c_orig, d_orig; int maxx, maxy; int img_width, img_height; int row, col, i, j, k, m; int XX, YY, var_i; int cnt=1; double aspect; char pref[64], filename[1024], cmd[1024], cmd2[1024]; char inform_text[128]; #if defined(OPENGL_X11) && (defined(HAVE_PBUFFERS) || defined(HAVE_PIXMAPS)) int os_w ; int os_h ; #endif /* Parse arguments */ if (argc != 4) { interp->result = "Error: should be Nstart_zoom file_name width height"; return (TCL_ERROR); } /* Get Filename*/ strcpy(pref, argv[1]); /* get display aspect */ GS_zoom_setup(&a_orig, &b_orig, &c_orig, &d_orig, &maxx, &maxy); aspect = (double) (c_orig-a_orig)/(d_orig-b_orig); /* create off-screen context if possible */ #if defined(OPENGL_X11) && (defined(HAVE_PBUFFERS) || defined(HAVE_PIXMAPS)) os_w = atoi(argv[2]); os_h = atoi(argv[3]); if (aspect > 1.) { /* width is greater than height */ if ( ( (os_w / aspect) - (int) (os_w / aspect) ) > .5) os_h = (int) (os_w / aspect) + 1; else os_h = (os_w / aspect); } else { if ( ( (os_h * aspect) - (int)(os_h * aspect) ) > .5) os_w = (int) (os_h * aspect) + 1; else os_w = (int) (os_h * aspect); } Create_OS_Ctx(os_w, os_h); #endif GS_zoom_setup(&a, &b, &c, &d, &maxx, &maxy); /* Calculate Maximum possible output size */ if (aspect > 1.) { if ( ( (maxx / aspect) - (int) (maxx / aspect) ) > .5) maxy = (int) (maxx / aspect) + 1; else maxy = (int) (maxx / aspect); var_i = (int) (maxx/(c-a)) + 1; } else { if ( ( (maxy * aspect) - (int)(maxy * aspect) ) > .5) maxx = (int) (maxy * aspect) + 1; else maxx = (int) (maxy * aspect); var_i = (int)(maxy/(d-b))+1; } fprintf(stderr, "Final Assembled Image will be %d x %d\n", maxx, maxy); /* Set X & Y to zero for lower left corner */ XX = YY = 0; /* Set output image width & height */ img_width = c; img_height = d; /* Cycle through tiles according to Zoom factor */ for (row = 1; row <= var_i; row++) { for (col = 1; col <= var_i; col++) { GS_set_viewport(XX, maxx, YY, maxy); Ndraw_all_together_cmd(data, interp, argc, argv); sprintf(filename, "%s_%d_%d.ppm", pref, row, col); /* Re-set image width or height if required */ if ((maxx + XX) < c) img_width = maxx + XX; if ((maxy + YY) < d) img_height = maxy + YY; /* Save tile to file */ sprintf(inform_text, "inform \"Writing Tile %d of %d\"", cnt,(var_i*var_i) ); Tcl_Eval(interp, inform_text); fprintf(stderr, "Writing Tile %d of %d\n", cnt,(var_i*var_i) ); GS_write_zoom(filename, img_width, img_height); XX -= c; cnt++; } /* Done col */ /* Reset XX and img_width */ XX = 0; img_width = c; YY -= d; } /* done row */ /* Done writing ppm tiles */ /* Cat ppm tiles together */ sprintf(inform_text, "inform \"Assembling Tiles\""); Tcl_Eval(interp, inform_text); fprintf(stderr, "Assembling Tiles\n"); strcpy(cmd2, "pnmcat -tb "); k = var_i; for (i = 1; i <= var_i; i++) { strcpy(cmd, "pnmcat -lr "); for (j = 1; j <= var_i; j++) { sprintf(filename, "%s_%d_%d.ppm ", pref, i, j); strcat(cmd, filename); } sprintf(filename, "> %stmp%d.ppm", pref, i); strcat(cmd, filename); sprintf(filename, "%stmp%d.ppm ", pref, k); strcat(cmd2, filename); if (system(cmd) != 0) { fprintf(stderr, "pnmcat failed to create assembled image\n"); fprintf(stderr, "Check that pnmcat is installed and path is set\n"); } else { for (m = 1; m <= var_i; m++) { sprintf(filename, "%s_%d_%d.ppm", pref, i, m); remove(filename); } } k--; } sprintf(filename, "> %s.ppm", pref); strcat(cmd2, filename); if (system(cmd2) != 0) { fprintf(stderr, "pnmcat failed to create assembled images\n"); fprintf(stderr, "Check that pnmcat is installed and path is set\n"); } else { for (m = 1; m <= var_i; m++) { sprintf(filename, "%stmp%d.ppm", pref, m); remove(filename); } } GS_set_viewport(a_orig, c_orig, b_orig, d_orig); #if defined(OPENGL_X11) && (defined(HAVE_PBUFFERS) || defined(HAVE_PIXMAPS)) Destroy_OS_Ctx(); #endif sprintf(inform_text, "inform \"Finished rendering max. size image\""); Tcl_Eval(interp, inform_text); return (TCL_OK); } /******************************************** * callbacks for PBuffer and GLXPixmap to * swap buffers *********************************************/ void swap_os(void) { #ifdef OPENGL_X11 #ifdef HAVE_PBUFFERS if (pbuffer) { glXSwapBuffers(dpy, pbuffer); return; } #endif #ifdef HAVE_PIXMAPS if (glxpixmap) glXSwapBuffers(dpy, glxpixmap); #endif #endif } /******************************************** * open an off-screen render context ********************************************/ int Create_OS_Ctx(int width, int height) { #if defined(OPENGL_X11) && (defined(HAVE_PBUFFERS) || defined(HAVE_PIXMAPS)) int scr; #ifdef HAVE_PBUFFERS GLXFBConfig *fbc; int elements; int pbuf_attrib[200]; int pbuf_cnt; #endif #ifdef HAVE_PIXMAPS XVisualInfo *vi; Colormap cmap; int att[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None }; GLXContext ctx; #endif dpy = XOpenDisplay(NULL); if (dpy == NULL) { fprintf(stderr, "XOpenDisplay Failed!\n"); return (-1); } scr = DefaultScreen(dpy); root = RootWindow(dpy, scr); ctx_orig = glXGetCurrentContext(); if (ctx_orig == NULL) { fprintf(stderr, "Unable to get current context\n"); return (-1); } #ifdef HAVE_PBUFFERS #if defined(GLX_PBUFFER_WIDTH) && defined(GLX_PBUFFER_HEIGHT) if (getenv("GRASS_GLX_PBUFFERS")) { fprintf(stderr, "Creating PBuffer Using GLX 1.3\n"); fbc = glXChooseFBConfig(dpy, scr, 0, &elements); if (fbc) { pbuf_cnt = 0; pbuf_attrib[pbuf_cnt++] = GLX_PBUFFER_WIDTH; pbuf_attrib[pbuf_cnt++] = width + 1; pbuf_attrib[pbuf_cnt++] = GLX_PBUFFER_HEIGHT; pbuf_attrib[pbuf_cnt++] = height + 1; pbuf_attrib[pbuf_cnt++] = None; pbuffer = glXCreatePbuffer(dpy, fbc[0], pbuf_attrib); if (pbuffer) glXMakeContextCurrent(dpy, pbuffer, pbuffer, ctx_orig); } } #endif #endif #ifdef HAVE_PIXMAPS #ifdef HAVE_PBUFFERS if (!pbuffer) #endif if (getenv("GRASS_GLX_PIXMAPS")) { fprintf(stderr, "Create PixMap Using GLX 1.1\n"); vi = glXChooseVisual(dpy, scr, att); if (vi == NULL) { fprintf(stderr, "Unable to get Visual\n"); return (-1); } ctx = glXCreateContext(dpy, vi, NULL, GL_FALSE); if (ctx == NULL) { fprintf(stderr, "Unable to create context\n"); return (-1); } cmap = XCreateColormap(dpy, RootWindow(dpy,vi->screen), vi->visual, AllocNone); pixmap = XCreatePixmap(dpy, RootWindow(dpy, vi->screen), width, height, vi->depth); if (!pixmap) { fprintf(stderr, "Unable to create pixmap\n"); return (-1); } glxpixmap = glXCreateGLXPixmap(dpy, vi, pixmap); glXMakeCurrent(dpy, glxpixmap, ctx); } #endif if (!pbuffer && !glxpixmap) return 1; /* hide togl canvas before init_ctx * This prevents bindings from re-initializing * togl */ hide_togl_win(); /* Initalize off screen context */ if ( init_ctx() != 1) { fprintf(stderr, "Error: Failed to Initiailze drawing area\n"); return (-1); } GS_set_swap_func(swap_os); GS_set_viewport(0, width, 0, height); GS_set_draw(GSD_BACK); GS_ready_draw(); GS_alldraw_wire(); GS_done_draw(); return (1); #else fprintf(stderr, "It appears that X is not available!\n"); return (-1); #endif /* defined(OPENGL_X11) && (defined(HAVE_PBUFFERS) || defined(HAVE_PIXMAPS)) */ } /***************************************************** * destroy off-screen context *****************************************************/ int Destroy_OS_Ctx(void) { #ifdef OPENGL_X11 #ifdef HAVE_PBUFFERS if (pbuffer) { fprintf(stderr, "GLX -- destroy pbuffer\n"); glXMakeCurrent(dpy, None, NULL); glXDestroyPbuffer(dpy, pbuffer); pbuffer = None; GS_set_swap_func(swap_togl); show_togl_win(); return (1); } #endif #ifdef HAVE_PIXMAPS if (glxpixmap) { fprintf(stderr, "Destroy Pixmap and GLXPixmap\n"); glXMakeCurrent(dpy, None, NULL); glXDestroyGLXPixmap(dpy, glxpixmap); glxpixmap = None; XFreePixmap(dpy, pixmap); pixmap = None; GS_set_swap_func(swap_togl); show_togl_win(); return (1); } #endif #endif /* OPENGL_X11 */ XCloseDisplay(dpy); dpy = NULL; return (1); } /***************************************************** * Initialize graphics (lights) for new context *****************************************************/ int init_ctx(void) { float x, y, z; int num, w; float r, g, b; glMatrixMode(GL_MODELVIEW); glDepthRange(0.0, 1.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); /* There should be two lights -- one stationary * light overhead, and the user defined light */ gsd_init_lightmodel(); /* Get and set light atts */ for (num = 1; num < 3; num++) { GS_getlight_position(num, &x, &y, &z, &w); GS_setlight_position(num, x, y, z, w); GS_getlight_color(num, &r, &g, &b); GS_setlight_color(num, r, g, b); GS_getlight_ambient(num, &r, &g, &b); GS_setlight_ambient(num, r, g, b); } GS_lights_on(); return(1); }