/* graphics.pex.c */ /* Graphics functions for PEX */ /* [ SGJ: What is this file for? It seems to be superceded by graphics.pex.c, and it was never used in the original Makefile ] */ /* * Vis5D system for visualizing five dimensional gridded data sets. * Copyright (C) 1990 - 2000 Bill Hibbard, Johan Kellum, Brian Paul, * Dave Santek, and Andre Battaiola. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * As a special exception to the terms of the GNU General Public * License, you are permitted to link Vis5D with (and distribute the * resulting source and executables) the LUI library (copyright by * Stellar Computer Inc. and licensed for distribution with Vis5D), * the McIDAS library, and/or the NetCDF library, where those * libraries are governed by the terms of their own licenses. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "../config.h" #ifdef HAVE_PEX #include #include #include #include #include #include #include #include #include #include #include #include "globals.h" #include "graphics.h" #include "matrix.h" typedef float Matrix[4][4]; /*** Private Variables: ***/ static float Scale; static Matrix ModelMat, InvModelMat, ProjMat; static PEXMatrix IdMat = { {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0} }; static int Perspective = 0; static Context current_ctx = NULL; /******** PEX includes and variables *********/ #define VERTS_PER_CALL 400 static PEXRenderer Renderer; static PEXRendererAttributes RendererAttrs; static PEXMatrix InvertYMatrix; static int InvertY; static PEXMatrix MCtoDCMatrix; static PEXMatrix DCtoMCMatrix; void init_graphics2( void ) { HQR_available = 0; Perspec_available = 1; } void terminate_graphics( void ) { } void free_graphics( Display_Context dtx ) { /* TODO */ } void context_init( Context ctx, long win_id, int width, int height ) { /* nothing for PEX */ } int CheckAlphaSupport (display, window) Display *display; Window window; { int status, j, found; int enum_types[1]; unsigned long *enum_counts; PEXEnumTypeDesc *enum_values, *p_enum; /* Determine whether the Renderer can support alpha blending. */ enum_types[0] = PEXHPETTransparencyMethod; status = PEXGetEnumTypeInfo (display, window, 1, enum_types, PEXETCounts|PEXETIndex, &enum_counts, &enum_values); if (!status) { fprintf(stderr, "inquiry of enumerated types failed - exiting\n"); exit(1); } p_enum = enum_values; found = False; for (j=0; jindex) == ((unsigned short) PEXHPTransparencyMethodAlphaBlend)) { found = True; } } PEXFreeEnumInfo (1, enum_counts, enum_values); return found; } /* CheckAlphaSupport */ int make_big_window( char *title, int xpos, int ypos, int width, int height) { PEXUtVisualCriteria VisualCriteria; XVisualInfo VisualInfo; XStandardColormap ColormapInfo; PEXColorApproxEntry ColorApproxInfo; unsigned int UnmetCriteria; Atom StandardPropertyAtom; int PexUtReturn; PEXUtWindowSpecification WindowSpecification; XColor Background; PEXExtensionInfo *ExtensionInfo; char Error[81]; XWindowAttributes window_attrs; Window wmain; unsigned long RenderMask, PipeMask[3]; PEXPCAttributes PipelineAttrs; if (BigWindow){ printf("BigWindow already exists, so not making it again!!\n"); return 0; } if (PEXInitialize(GfxDpy, &ExtensionInfo, 80, Error) != 0) { printf("PEXInitialize failed: %s\n", Error); exit(-1); } WindowSpecification.attr_mask = CWEventMask; WindowSpecification.attrs.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | VisibilityChangeMask; WindowSpecification.title = title; WindowSpecification.size_hints.x = xpos; WindowSpecification.size_hints.y = ypos; WindowSpecification.size_hints.width = width; WindowSpecification.size_hints.height = height; WindowSpecification.size_hints.max_width = width; WindowSpecification.size_hints.max_height = height; /* WindowSpecification.size_hints.flags = USSize | USPosition | PMaxSize; */ WindowSpecification.size_hints.flags = USSize | USPosition; if (DisplayMatrix == 11 && BigWindow != NULL){ WindowSpecification.parent = RootWindow(GfxDpy,GfxScr); } else { WindowSpecification.parent = BigWindow; } WindowSpecification.parent = RootWindow(GfxDpy,GfxScr); WindowSpecification.border_width = 0; WindowSpecification.background_color_name = "black"; WindowSpecification.border_color_name = "black"; VisualCriteria.hard_criteria_mask = 0; VisualCriteria.soft_criteria_mask = 0; VisualCriteria.soft_criteria_mask |= PEXUtStandardColormapProperty; VisualCriteria.standard_colormap_property = True; VisualCriteria.hard_criteria_mask |= PEXUtDoubleBufferingCapability; VisualCriteria.double_buffering_capability = True; /* ** Try to find a visual with PEX double-buffering. */ PexUtReturn = PEXUtCreateWindowAndColormap( GfxDpy, GfxScr, &VisualCriteria, &WindowSpecification, &wmain, &VisualInfo, &ColormapInfo, &ColorApproxInfo, &UnmetCriteria, &StandardPropertyAtom, &Background); /* ** If PEXUtCreateWindowAndColormap() was unable to find a visual, ** try again for a visual that doesn't support double-buffering. */ if ( PexUtReturn == PEXUtCriteriaFailure ) { VisualCriteria.hard_criteria_mask = 0; PexUtReturn = PEXUtCreateWindowAndColormap( GfxDpy, GfxScr, &VisualCriteria, &WindowSpecification, &wmain, &VisualInfo, &ColormapInfo, &ColorApproxInfo, &UnmetCriteria, &StandardPropertyAtom, &Background); } /* ** If PEXUtCreateWindowAndColormap() was still unable to create a window, ** report an error and exit. */ if ( ( PexUtReturn != PEXUtSuccess ) && ( PexUtReturn != PEXUtQualifiedSuccess ) ) { printf("Error: couldn't open 3-D window\n"); exit(-1); } if (XGetWindowAttributes(GfxDpy, wmain, &window_attrs) == 0) { printf("Error: couldn't get window attributes\n"); exit(-1); } BigWindow = wmain; BigWinWidth = window_attrs.width; BigWinHeight = window_attrs.height; /* set pointer shape */ XDefineCursor( GfxDpy, wmain, XCreateFontCursor(GfxDpy,XC_top_left_arrow) ); PipeMask[0] = PipeMask[1] = PipeMask[2] = 0; PEXSetPCAttributeMask(PipeMask, PEXPCCharHeight); PipelineAttrs.char_height = 9.0; PEXSetPCAttributeMask(PipeMask, PEXPCInteriorStyle); PipelineAttrs.interior_style = PEXInteriorStyleSolid; PEXSetPCAttributeMask(PipeMask, PEXPCSurfaceColor); PipelineAttrs.surface_color.type = PEXColorTypeRGB; PipelineAttrs.surface_color.value.rgb.red = 1.0; PipelineAttrs.surface_color.value.rgb.green = 1.0; PipelineAttrs.surface_color.value.rgb.blue = 1.0; PEXSetPCAttributeMask(PipeMask, PEXPCReflectionModel); PipelineAttrs.reflection_model = PEXReflectionSpecular; PEXSetPCAttributeMask(PipeMask, PEXPCReflectionAttr); PipelineAttrs.reflection_attr.ambient = 1; PipelineAttrs.reflection_attr.diffuse = 1; PipelineAttrs.reflection_attr.transmission = 0; PipelineAttrs.reflection_attr.specular = 1; PipelineAttrs.reflection_attr.specular_conc = 30; PipelineAttrs.reflection_attr.specular_color.type = PEXColorTypeRGB; PipelineAttrs.reflection_attr.specular_color.value.rgb.red = 1; PipelineAttrs.reflection_attr.specular_color.value.rgb.green = 1; PipelineAttrs.reflection_attr.specular_color.value.rgb.blue = 1; PEXSetPCAttributeMask(PipeMask, PEXPCSurfaceInterp); PipelineAttrs.surface_interp = PEXSurfaceInterpColor; PEXSetPCAttributeMask(PipeMask, PEXPCHLHSRIdentifier); PipelineAttrs.hlhsr_id = PEXHLHSRIDEnable; PEXSetPCAttributeMask(PipeMask, PEXPCDepthCueIndex); PipelineAttrs.depth_cue_index = 0; RendererAttrs.pipeline_context = PEXCreatePipelineContext(GfxDpy, PipeMask, &PipelineAttrs); RendererAttrs.clear_image = True; RendererAttrs.clear_z = True; RendererAttrs.background_color.type = PEXColorTypeRGB; RendererAttrs.background_color.value.rgb.red = 0.0; RendererAttrs.background_color.value.rgb.green = 0.0; RendererAttrs.background_color.value.rgb.blue = 0.0; RendererAttrs.hlhsr_mode = PEXHLHSRZBuffer; RendererAttrs.light_table = PEXCreateLookupTable(GfxDpy, wmain, PEXLUTLight); if (RendererAttrs.light_table == 0) { printf( "Unable to create PEX light table\n" ); exit(-1); } RendererAttrs.view_table = PEXCreateLookupTable(GfxDpy, wmain, PEXLUTView); if (RendererAttrs.view_table == 0) { printf( "Unable to create PEX view table\n" ); exit(-1); } RendererAttrs.depth_cue_table = PEXCreateLookupTable(GfxDpy, wmain, PEXLUTDepthCue); if (RendererAttrs.depth_cue_table == 0) { printf( "Unable to create PEX depth cue table\n" ); exit(-1); } RenderMask = PEXRAHLHSRMode | PEXRABackgroundColor | PEXRAClearImage | PEXRAClearZ | PEXRALightTable | PEXRAViewTable | PEXRADepthCueTable | PEXRAPipelineContext; { PEXLightEntry lights[3]; PEXTableIndex lights_on[1]; /* Define the ambient light. */ lights[0].type = PEXLightAmbient; lights[0].color.type = PEXColorTypeRGB; lights[0].color.value.rgb.red = 0.2; lights[0].color.value.rgb.green = 0.2; lights[0].color.value.rgb.blue = 0.2; /* Define a directional light. */ lights[1].type = PEXLightWCVector; lights[1].direction.x = 0; lights[1].direction.y = 0; lights[1].direction.z = 10; lights[1].color.type = PEXColorTypeRGB; lights[1].color.value.rgb.red = 0.8; lights[1].color.value.rgb.green = 0.8; lights[1].color.value.rgb.blue = 0.8; /* Define another directional light. */ lights[2] = lights[1]; lights[2].direction.z = -10; /* Add the lights to the light table. */ /* PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 1, 1, PEXLUTLight, lights ); PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 2, 1, PEXLUTLight, lights ); PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 3, 1, PEXLUTLight, lights ); */ PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 1, 3, PEXLUTLight, lights ); /* enable ambient light */ /* lights_on[0] = 1;*/ /* PEXSetLightSourceState(GfxDpy, Renderer, PEXOCRender, 1, lights_on, 0, (PEXTableIndex*)NULL ); */ } { PEXDepthCueEntry DepthCues[2]; /* Define the no depth cue entry. */ DepthCues[0].mode = False; DepthCues[0].front_plane = 1.0; DepthCues[0].front_scaling = 1.0; DepthCues[0].back_plane = 0.0; DepthCues[0].back_scaling = 0.2; DepthCues[0].color.type = PEXColorTypeRGB; DepthCues[0].color.value.rgb.red = 0.0; DepthCues[0].color.value.rgb.green = 0.0; DepthCues[0].color.value.rgb.blue = 0.0; /* Define the depth cue entry. */ DepthCues[1].mode = True; DepthCues[1].front_plane = 1.0; DepthCues[1].front_scaling = 1.0; DepthCues[1].back_plane = 0.0; DepthCues[1].back_scaling = 0.2; DepthCues[1].color.type = PEXColorTypeRGB; DepthCues[1].color.value.rgb.red = 0.0; DepthCues[1].color.value.rgb.green = 0.0; DepthCues[1].color.value.rgb.blue = 0.0; /* Add the depth cues to the table. */ PEXSetTableEntries(GfxDpy, RendererAttrs.depth_cue_table, 0, 2, PEXLUTDepthCue, DepthCues); } Renderer = PEXCreateRenderer(GfxDpy, wmain, RenderMask, &RendererAttrs); if (Renderer == 0) { printf( "Unable to create PEX renderer\n" ); exit(-1); } XSync(GfxDpy, False); resize_3d_window(width, height); return wmain; } /* * Make a 3-D graphics window. * Input: * ctx - the Vis5D context * title - window title string * xpos,ypos - position in pixel from upper-left corner * width, height - width and height of window in pixels * Return: X window pointer or NULL. */ int make_3d_window( Display_Context dtx, char *title, int xpos, int ypos, int width, int height ) { PEXUtVisualCriteria VisualCriteria; XVisualInfo VisualInfo; XStandardColormap ColormapInfo; PEXColorApproxEntry ColorApproxInfo; unsigned int UnmetCriteria; Atom StandardPropertyAtom; int PexUtReturn; PEXUtWindowSpecification WindowSpecification; XColor Background; PEXExtensionInfo *ExtensionInfo; char Error[81]; XWindowAttributes window_attrs; Window wmain; unsigned long RenderMask, PipeMask[3]; PEXPCAttributes PipelineAttrs; current_ctx = ctx; if (PEXInitialize(GfxDpy, &ExtensionInfo, 80, Error) != 0) { printf("PEXInitialize failed: %s\n", Error); exit(-1); } WindowSpecification.attr_mask = CWEventMask; WindowSpecification.attrs.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | VisibilityChangeMask; WindowSpecification.title = title; WindowSpecification.size_hints.x = xpos; WindowSpecification.size_hints.y = ypos; WindowSpecification.size_hints.width = width; WindowSpecification.size_hints.height = height; WindowSpecification.size_hints.max_width = width; WindowSpecification.size_hints.max_height = height; /* WindowSpecification.size_hints.flags = USSize | USPosition | PMaxSize; */ WindowSpecification.size_hints.flags = USSize | USPosition; if (DisplayMatrix == 11 && BigWindow != NULL){ WindowSpecification.parent = RootWindow(GfxDpy,GfxScr); } else { WindowSpecification.parent = BigWindow; } WindowSpecification.parent = RootWindow(GfxDpy,GfxScr); WindowSpecification.border_width = 0; WindowSpecification.background_color_name = "black"; WindowSpecification.border_color_name = "black"; VisualCriteria.hard_criteria_mask = 0; VisualCriteria.soft_criteria_mask = 0; VisualCriteria.soft_criteria_mask |= PEXUtStandardColormapProperty; VisualCriteria.standard_colormap_property = True; VisualCriteria.hard_criteria_mask |= PEXUtDoubleBufferingCapability; VisualCriteria.double_buffering_capability = True; /* ** Try to find a visual with PEX double-buffering. */ PexUtReturn = PEXUtCreateWindowAndColormap( GfxDpy, GfxScr, &VisualCriteria, &WindowSpecification, &wmain, &VisualInfo, &ColormapInfo, &ColorApproxInfo, &UnmetCriteria, &StandardPropertyAtom, &Background); /* ** If PEXUtCreateWindowAndColormap() was unable to find a visual, ** try again for a visual that doesn't support double-buffering. */ if ( PexUtReturn == PEXUtCriteriaFailure ) { VisualCriteria.hard_criteria_mask = 0; PexUtReturn = PEXUtCreateWindowAndColormap( GfxDpy, GfxScr, &VisualCriteria, &WindowSpecification, &wmain, &VisualInfo, &ColormapInfo, &ColorApproxInfo, &UnmetCriteria, &StandardPropertyAtom, &Background); } /* ** If PEXUtCreateWindowAndColormap() was still unable to create a window, ** report an error and exit. */ if ( ( PexUtReturn != PEXUtSuccess ) && ( PexUtReturn != PEXUtQualifiedSuccess ) ) { printf("Error: couldn't open 3-D window\n"); exit(-1); } if (XGetWindowAttributes(GfxDpy, wmain, &window_attrs) == 0) { printf("Error: couldn't get window attributes\n"); exit(-1); } ctx->GfxWindow = wmain; ctx->WinWidth = window_attrs.width; ctx->WinHeight = window_attrs.height; ctx->FontHeight = (int) 9.0; /*TODO FIX*/ ctx->FontDescent = (int) 0.1; /* set pointer shape */ XDefineCursor( GfxDpy, wmain, XCreateFontCursor(GfxDpy,XC_top_left_arrow) ); PipeMask[0] = PipeMask[1] = PipeMask[2] = 0; PEXSetPCAttributeMask(PipeMask, PEXPCCharHeight); PipelineAttrs.char_height = 9.0; PEXSetPCAttributeMask(PipeMask, PEXPCInteriorStyle); PipelineAttrs.interior_style = PEXInteriorStyleSolid; PEXSetPCAttributeMask(PipeMask, PEXPCSurfaceColor); PipelineAttrs.surface_color.type = PEXColorTypeRGB; PipelineAttrs.surface_color.value.rgb.red = 1.0; PipelineAttrs.surface_color.value.rgb.green = 1.0; PipelineAttrs.surface_color.value.rgb.blue = 1.0; PEXSetPCAttributeMask(PipeMask, PEXPCReflectionModel); PipelineAttrs.reflection_model = PEXReflectionSpecular; PEXSetPCAttributeMask(PipeMask, PEXPCReflectionAttr); PipelineAttrs.reflection_attr.ambient = 1; PipelineAttrs.reflection_attr.diffuse = 1; PipelineAttrs.reflection_attr.transmission = 0; PipelineAttrs.reflection_attr.specular = 1; PipelineAttrs.reflection_attr.specular_conc = 30; PipelineAttrs.reflection_attr.specular_color.type = PEXColorTypeRGB; PipelineAttrs.reflection_attr.specular_color.value.rgb.red = 1; PipelineAttrs.reflection_attr.specular_color.value.rgb.green = 1; PipelineAttrs.reflection_attr.specular_color.value.rgb.blue = 1; PEXSetPCAttributeMask(PipeMask, PEXPCSurfaceInterp); PipelineAttrs.surface_interp = PEXSurfaceInterpColor; PEXSetPCAttributeMask(PipeMask, PEXPCHLHSRIdentifier); PipelineAttrs.hlhsr_id = PEXHLHSRIDEnable; PEXSetPCAttributeMask(PipeMask, PEXPCDepthCueIndex); PipelineAttrs.depth_cue_index = 0; RendererAttrs.pipeline_context = PEXCreatePipelineContext(GfxDpy, PipeMask, &PipelineAttrs); RendererAttrs.clear_image = True; RendererAttrs.clear_z = True; RendererAttrs.background_color.type = PEXColorTypeRGB; RendererAttrs.background_color.value.rgb.red = 0.0; RendererAttrs.background_color.value.rgb.green = 0.0; RendererAttrs.background_color.value.rgb.blue = 0.0; RendererAttrs.hlhsr_mode = PEXHLHSRZBuffer; RendererAttrs.light_table = PEXCreateLookupTable(GfxDpy, wmain, PEXLUTLight); if (RendererAttrs.light_table == 0) { printf( "Unable to create PEX light table\n" ); exit(-1); } RendererAttrs.view_table = PEXCreateLookupTable(GfxDpy, wmain, PEXLUTView); if (RendererAttrs.view_table == 0) { printf( "Unable to create PEX view table\n" ); exit(-1); } RendererAttrs.depth_cue_table = PEXCreateLookupTable(GfxDpy, wmain, PEXLUTDepthCue); if (RendererAttrs.depth_cue_table == 0) { printf( "Unable to create PEX depth cue table\n" ); exit(-1); } RenderMask = PEXRAHLHSRMode | PEXRABackgroundColor | PEXRAClearImage | PEXRAClearZ | PEXRALightTable | PEXRAViewTable | PEXRADepthCueTable | PEXRAPipelineContext; { PEXLightEntry lights[3]; PEXTableIndex lights_on[1]; /* Define the ambient light. */ lights[0].type = PEXLightAmbient; lights[0].color.type = PEXColorTypeRGB; lights[0].color.value.rgb.red = 0.2; lights[0].color.value.rgb.green = 0.2; lights[0].color.value.rgb.blue = 0.2; /* Define a directional light. */ lights[1].type = PEXLightWCVector; lights[1].direction.x = 0; lights[1].direction.y = 0; lights[1].direction.z = 10; lights[1].color.type = PEXColorTypeRGB; lights[1].color.value.rgb.red = 0.8; lights[1].color.value.rgb.green = 0.8; lights[1].color.value.rgb.blue = 0.8; /* Define another directional light. */ lights[2] = lights[1]; lights[2].direction.z = -10; /* Add the lights to the light table. */ /* PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 1, 1, PEXLUTLight, lights ); PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 2, 1, PEXLUTLight, lights ); PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 3, 1, PEXLUTLight, lights ); */ PEXSetTableEntries( GfxDpy, RendererAttrs.light_table, 1, 3, PEXLUTLight, lights ); /* enable ambient light */ /* lights_on[0] = 1;*/ /* PEXSetLightSourceState(GfxDpy, Renderer, PEXOCRender, 1, lights_on, 0, (PEXTableIndex*)NULL ); */ } { PEXDepthCueEntry DepthCues[2]; /* Define the no depth cue entry. */ DepthCues[0].mode = False; DepthCues[0].front_plane = 1.0; DepthCues[0].front_scaling = 1.0; DepthCues[0].back_plane = 0.0; DepthCues[0].back_scaling = 0.2; DepthCues[0].color.type = PEXColorTypeRGB; DepthCues[0].color.value.rgb.red = 0.0; DepthCues[0].color.value.rgb.green = 0.0; DepthCues[0].color.value.rgb.blue = 0.0; /* Define the depth cue entry. */ DepthCues[1].mode = True; DepthCues[1].front_plane = 1.0; DepthCues[1].front_scaling = 1.0; DepthCues[1].back_plane = 0.0; DepthCues[1].back_scaling = 0.2; DepthCues[1].color.type = PEXColorTypeRGB; DepthCues[1].color.value.rgb.red = 0.0; DepthCues[1].color.value.rgb.green = 0.0; DepthCues[1].color.value.rgb.blue = 0.0; /* Add the depth cues to the table. */ PEXSetTableEntries(GfxDpy, RendererAttrs.depth_cue_table, 0, 2, PEXLUTDepthCue, DepthCues); } Renderer = PEXCreateRenderer(GfxDpy, wmain, RenderMask, &RendererAttrs); if (Renderer == 0) { printf( "Unable to create PEX renderer\n" ); exit(-1); } XSync(GfxDpy, False); if (PEXUtDBConfig(GfxDpy, wmain, True, &Background, False, &ctx->db_win)) { ctx->use_db = False; ctx->db_win = wmain; } else { ctx->use_db = True; } XSync(GfxDpy, False); ctx->has_blending = CheckAlphaSupport(GfxDpy, ctx->db_win); resize_3d_window(width, height); return wmain; } void set_current_window( Context ctx ) { current_ctx = ctx; } int set_3d_font( Context ctx, char *name, int size ) { /*TODO */ } void set_pointer( int p ) { if (p) { /* make busy cursor */ XDefineCursor( GfxDpy, current_ctx->GfxWindow, XCreateFontCursor(GfxDpy,XC_watch) ); } else { XDefineCursor( GfxDpy, current_ctx->GfxWindow, XCreateFontCursor(GfxDpy,XC_top_left_arrow) ); } } int save_formats( void ) { return VIS5D_XWD; } int save_3d_window( char *filename, int format ) { FILE *f; set_pointer(1); /* Make an X window dump file (.xwd) */ f = fopen(filename,"w"); if (f) { Window_Dump( GfxDpy, GfxScr, current_ctx->GfxWindow, f ); fclose(f); set_pointer(0); return 1; } else { printf("Error unable to open %s for writing\n", filename); set_pointer(0); return 0; } } int print_3d_window( void ) { static char xwd_file[] = "/usr/tmp/Vis5d_image.xwd"; char cmd[1000]; FILE *f; set_pointer(1); /* Make an X window dump file (.xwd) */ f = fopen(xwd_file,"w"); if (f) { printf("Writing X window dump: %s\n", xwd_file); Window_Dump( GfxDpy, GfxScr, current_ctx->GfxWindow, f ); fclose(f); /* Use xpr to print the window dump */ if (!installed("xpr")) return 0; sprintf(cmd,"xpr -device ps %s | lpr\n", xwd_file ); printf("Executing: %s\n", cmd ); system(cmd); /* delete xwd file */ unlink( xwd_file ); printf("Done.\n"); set_pointer(0); return 1; } else { printf("Error unable to open %s for writing\n", xwd_file); set_pointer(0); return 0; } } void clear_color( unsigned int bgcolor ) { unsigned long mask = PEXRABackgroundColor; float r, g, b; r = UNPACK_RED(bgcolor)/255.0; g = UNPACK_GREEN(bgcolor)/255.0; b = UNPACK_BLUE(bgcolor)/255.0; RendererAttrs.background_color.type = PEXColorTypeRGB; RendererAttrs.background_color.value.rgb.red = r; RendererAttrs.background_color.value.rgb.green = g; RendererAttrs.background_color.value.rgb.blue = b; PEXChangeRenderer( GfxDpy, Renderer, mask, &RendererAttrs ); } void clear_3d_window( void ) { /* Clear is implicit in BeginRendering in set_3d. */ } /* * Called when window size changes. */ void resize_3d_window( int width, int height ) { /* printf("resize %d %d\n", width, height );*/ current_ctx->WinWidth = width; current_ctx->WinHeight = height; PEXUtDBResize( GfxDpy, current_ctx->GfxWindow ); { float ratio, delta; if( width > height) { ratio = (float)width / (float)height; delta = (1.0 / ratio) * 0.5; RendererAttrs.npc_subvolume.min.x = 0; RendererAttrs.npc_subvolume.min.y = 0.5 - delta; RendererAttrs.npc_subvolume.min.z = 0; RendererAttrs.npc_subvolume.max.x = 1.0; RendererAttrs.npc_subvolume.max.y = 0.5 + delta; RendererAttrs.npc_subvolume.max.z = 1.0; } else { ratio = (float)height / (float)width; delta = (1.0 / ratio) * 0.5; RendererAttrs.npc_subvolume.min.x = 0.5 - delta; RendererAttrs.npc_subvolume.min.y = 0; RendererAttrs.npc_subvolume.min.z = 0; RendererAttrs.npc_subvolume.max.x = 0.5 + delta; RendererAttrs.npc_subvolume.max.y = 1.0; RendererAttrs.npc_subvolume.max.z = 1.0; } PEXChangeRenderer(GfxDpy, Renderer, PEXRANPCSubVolume, &RendererAttrs); } { PEXViewEntry views[2]; PEXCoord2D view_window[2]; double view_plane, front_plane, back_plane; PEXCoord prp; PEXNPCSubVolume viewport; static PEXCoord view_ref_pt = {0.0, 0.0, 0.0}; static PEXVector view_plane_normal = {0.0, 0.0, 1.0}; static PEXVector view_up_vec = {0,1,0}; PEXViewOrientationMatrix( &view_ref_pt, &view_plane_normal, &view_up_vec, views[0].orientation ); PEXViewOrientationMatrix( &view_ref_pt, &view_plane_normal, &view_up_vec, views[1].orientation ); /* ** The view mapping parameters. */ view_window[0].x = 0; view_window[0].y = 0; view_window[1].x = width-1; view_window[1].y = height-1; prp.x = view_window[1].x / 2.0; prp.y = view_window[1].y / 2.0; prp.z = 4.0; front_plane = 1; view_plane = 0; back_plane = -1; viewport.min.x = RendererAttrs.npc_subvolume.min.x; viewport.max.x = RendererAttrs.npc_subvolume.max.x; viewport.min.y = RendererAttrs.npc_subvolume.min.y; viewport.max.y = RendererAttrs.npc_subvolume.max.y; viewport.min.z = 0; viewport.max.z = 1; PEXViewMappingMatrix(view_window, &viewport, False, &prp, view_plane, back_plane, front_plane, views[0].mapping); views[0].clip_flags = PEXClippingAll; views[0].clip_limits = viewport; view_window[0].x = -1; view_window[0].y = -1; view_window[1].x = 1; view_window[1].y = 1; front_plane = 1; view_plane = 0; back_plane = -1; prp.x = 0.0; prp.y = 0.0; prp.z = 5.0; PEXViewMappingMatrix(view_window, &viewport, False, &prp, view_plane, back_plane, front_plane, views[1].mapping); views[1].clip_flags = PEXClippingAll; views[1].clip_limits = viewport; PEXSetTableEntries(GfxDpy, RendererAttrs.view_table, 0, 2, PEXLUTView, (PEXPointer) views); } } void swap_3d_window( void ) { PEXEndRendering(GfxDpy, Renderer, True); if (current_ctx->use_db) { current_ctx->db_win = PEXUtDBSwap( GfxDpy, current_ctx->GfxWindow, False); } XSync (GfxDpy, False); } static void decomposition(xform3, pivot) PEXMatrix xform3; int pivot[4]; /* Performs the Lu decomposition for Gaussian elimination with partial * pivoting. On entry: * xform3 - array to be decomposed * On exit: * xform3 - contains the LU decomposition * pivot - contains the pivot history...the original position numbers * of the pivoted rows. */ { register int i, j, step; register float temp, mfact; /*temp & row multiplication factor*/ register float abs_istep, abs_maxstep; /*used to get absolute values*/ register int itemp, max; /*temp & maximum coefficient*/ for (i = 0; i <= 3; i++) pivot[i] = i; for (step = 0; step <= 3; step++) { max = step; for (i = step + 1; i <= 3; i++) { abs_istep = xform3[i][step]; if (abs_istep < 0.0) abs_istep = -abs_istep; abs_maxstep = xform3[max][step]; if (abs_maxstep < 0.0) abs_maxstep = -abs_maxstep; if (abs_istep > abs_maxstep) max = i; } if (xform3[max][step] == 0.0) { printf("Couldn't invert a transform.\n"); exit(-1); } if (max != step) { for (j = 0; j <= 3; j++) { temp = xform3[step][j]; xform3[step][j] = xform3[max][j]; xform3[max][j] = temp; } itemp = pivot[step]; pivot[step] = pivot[max]; pivot[max] = itemp; } for (i = step + 1; i <= 3; i++) { mfact = -xform3[i][step] / xform3[step][step]; xform3[i][step] = -mfact; for (j = step + 1; j <= 3; j++) xform3[i][j] = mfact * xform3[step][j] + xform3[i][j]; } } } static void solve(xform3, col, result, pivot) PEXMatrix xform3; float col[4], result[4]; int pivot[4]; { register int solv, i; float sum; /*used for computing a sum while backsolving*/ float y[4]; /*used for computing Ly=Pb*/ /*Solve for y in Ly=Pb*/ for (solv = 0; solv <= 3; solv++) { sum = 0.0; for (i = 0; i <= solv - 1; i++) sum = sum + y[i] * xform3[solv][i]; y[solv] = col[pivot[solv]] - sum; } /*Solve for x in Ux=y*/ for (solv = 3; solv >= 0; solv--) { sum = 0.0; for (i = solv + 1; i <= 3; i++) sum += result[i] * xform3[solv][i]; result[solv] = (y[solv] - sum) / xform3[solv][solv]; } } static void compute_inverse(xform1, xform2) PEXMatrix xform1, xform2; { int pivot[4]; /*pivot history - used to remember original*/ /*row numbers of the pivoted rows*/ float idcol[4]; /*columns of the identity matrix*/ float result[4]; /*inverse is solved one column at a time*/ register int i, j; PEXMatrix txform; /*temp copy of xform1*/ memcpy(txform, xform1, sizeof(PEXMatrix)); decomposition(txform, pivot); /*Solve system with columns of identity matrix as solutions*/ for (i = 0; i <= 3; i++) { for (j = 0; j <= 3; j++) idcol[j] = 0.0; idcol[i] = 1.0; solve(txform, idcol, result, pivot); /* Resultant columns are the columns of inverse matrix*/ for (j = 0; j <= 3; j++) xform2[j][i] = result[j]; } } /* * Setup for 3-D rendering */ void set_3d( int perspective, float frontclip, float zoom, float *modelmat ) { PEXViewEntry view; PEXCoord2D view_window[2]; double view_plane, front_plane, back_plane; PEXCoord prp; PEXNPCSubVolume viewport; static PEXCoord view_ref_pt = {0.0, 0.0, 0.0}; static PEXVector view_plane_normal = {0.0, 0.0, 1.0}; static PEXVector view_up_vec = {0,1,0}; PEXMatrix global; register int i, j; PEXTableIndex lights_on[3]; PEXVector ShiftVector, ScaleVector; PEXMatrix TranslateMatrix, ScaleMatrix, InvertZMatrix, NPCtoXCMatrix; PEXDeviceCoord DCViewPort[2]; float FrontClip; /* This also clears the window */ PEXBeginRendering(GfxDpy, current_ctx->db_win, Renderer); InvertY = False; Perspective = perspective; Scale = zoom; FrontClip = 1.0 - 2.0*frontclip; /*TODO: verify*/ if (FrontClip < -0.9) { /* to prevent front plane == back plane */ FrontClip = -0.9; } /* ** The view mapping parameters. */ prp.x = 0.0; prp.y = 0.0; prp.z = 5.0; front_plane = zoom * 1.75 * FrontClip; /* prp must be outside front clip plane */ if (front_plane > 4.9) front_plane = 4.9; view_plane = 0.0; back_plane = -zoom * 1.75 /* * FrontClip */; viewport.min.x = 0; viewport.max.x = 1; viewport.min.y = 0; viewport.max.y = 1; viewport.min.z = 0; viewport.max.z = 1; view_window[0].x = -1.5; view_window[0].y = -1.5; view_window[1].x = 1.5; view_window[1].y = 1.5; PEXViewOrientationMatrix(&view_ref_pt, &view_plane_normal, &view_up_vec, view.orientation); PEXViewMappingMatrix(view_window, &viewport, Perspective, &prp, view_plane, back_plane, front_plane, view.mapping); view.clip_flags = PEXClippingAll; view.clip_limits = viewport; PEXSetTableEntries(GfxDpy, RendererAttrs.view_table, 1, 1, PEXLUTView, (PEXPointer) &view); PEXSetViewIndex(GfxDpy, Renderer, PEXOCRender, 1); RendererAttrs.hlhsr_mode = PEXHLHSRZBuffer; PEXChangeRenderer(GfxDpy, Renderer, PEXRAHLHSRMode, &RendererAttrs); if ( current_ctx->has_blending ) { unsigned long mask[2]; PEXHPRendererAttributes hp_attrs; mask[0] = 0; mask[1] = 0; PEXHPSetRendererAttributeMask(mask, PEXHPRATransparencyMethod); if (current_ctx->AlphaBlend) { hp_attrs.transparency_method = (unsigned long) PEXHPTransparencyMethodAlphaBlend; } else { hp_attrs.transparency_method = (unsigned long) PEXHPTransparencyMethodScreenDoor; } PEXHPChangeRenderer( GfxDpy, Renderer, mask, &hp_attrs); PEXHPSetAlphaBlendFunction( GfxDpy, Renderer, PEXOCRender, PEXHPAlphaBlendFunctionSimpleAlpha); } /* Turn the lights on. */ lights_on[0] = 1; lights_on[1] = 2; lights_on[2] = 3; PEXSetLightSourceState(GfxDpy, Renderer, PEXOCRender, 3, lights_on, 0, (PEXTableIndex*)NULL ); /* Transpose matrix. */ for (i=0; i<4; i++) { for (j=0; j<4; j++) { global[i][j] = modelmat[j*4+i]; } } /* Change the model matrix so a z range of 0 to 1 becomes 1 to 0 */ ScaleVector.x = ScaleVector.y = ScaleVector.z = Scale; PEXScale(&ScaleVector, ScaleMatrix); PEXMatrixMult(ScaleMatrix, global, global); PEXSetGlobalTransform(GfxDpy, Renderer, PEXOCRender, global); /* Create inverse matrix to use in project and unproject. */ DCViewPort[0].x = DCViewPort[0].y = DCViewPort[0].z = 0.0; DCViewPort[1].x = current_ctx->WinWidth; DCViewPort[1].y = current_ctx->WinHeight; DCViewPort[1].z = 1.0; PEXNPCToXCTransform(&viewport, DCViewPort, current_ctx->WinHeight, NPCtoXCMatrix); PEXMatrixMult(view.orientation, global, MCtoDCMatrix); PEXMatrixMult(view.mapping, MCtoDCMatrix, MCtoDCMatrix); PEXMatrixMult(NPCtoXCMatrix, MCtoDCMatrix, MCtoDCMatrix); compute_inverse(MCtoDCMatrix, DCtoMCMatrix); } /*** set_2d *********************************************************** This is to be called prior to any 2-D rendering calls. **********************************************************************/ void set_2d( void ) { PEXVector ShiftVector, ScaleVector; PEXMatrix TranslateMatrix, ScaleMatrix; /* Change the model matrix so a y range of 0 to Height becomes Height to 0 */ InvertY = True; ScaleVector.x = 1.0; ScaleVector.y = -1.0; ScaleVector.z = 1.0; PEXScale(&ScaleVector, ScaleMatrix); ShiftVector.x = 0.0; ShiftVector.y = current_ctx->WinHeight; ShiftVector.z = 0.0; PEXTranslate(&ShiftVector, TranslateMatrix); PEXMatrixMult(TranslateMatrix, ScaleMatrix, InvertYMatrix); PEXSetGlobalTransform(GfxDpy, Renderer, PEXOCRender, InvertYMatrix); PEXSetViewIndex(GfxDpy, Renderer, PEXOCRender, 0); RendererAttrs.hlhsr_mode = PEXHLHSROff; PEXChangeRenderer(GfxDpy, Renderer, PEXRAHLHSRMode, &RendererAttrs); } /*** project ********************************************************** Use current transformation and viewing information to project a point p from 3-D graphics coordinates to 2-D window coordinates in [0,WinWidth-1]x[0,WinHeight-1]. Input: p - 3-D point in graphics space Output: x, y - 2-D point in window pixel coordinates. **********************************************************************/ void project( float p[3], float *x, float *y ) { PEXCoord DC[1], MC[1]; MC[0].x = p[0]; MC[0].y = p[1]; MC[0].z = p[2]; PEXTransformPoints(MCtoDCMatrix, 1, MC, DC); *x = DC[0].x; *y = DC[0].y; } /*** unproject ******************************************************** Given a 2-D window coordinate in [0,WinWidth-1]x[0,WinHeight-1], return the parametric equation of a line in 3-D such that the projection of the line from 3-D to 2-D is a point at the window coordinate. Input: x, y - window coordinate. Output: p, d - parametric equation of line: l = p + t*d NOTE, d will have unit length **********************************************************************/ void unproject( float x, float y, float p[3], float d[3] ) { PEXCoord DC[2], MC[2]; float scale; DC[0].x = x; DC[0].y = y; DC[0].z = 1.0; DC[1].x = x; DC[1].y = y; DC[1].z = 0.0; PEXTransformPoints(DCtoMCMatrix, 2, DC, MC); p[0] = MC[0].x; p[1] = MC[0].y; p[2] = MC[0].z; d[0] = MC[1].x - MC[0].x; d[1] = MC[1].y - MC[0].y; d[2] = MC[1].z - MC[0].z; scale = 1.0 / sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]); d[0] *= scale; d[1] *= scale; d[2] *= scale; } static void enable_lighting( int onoff ) { PEXTableIndex lights[3]; lights[0] = 1; lights[1] = 2; lights[2] = 3; if (onoff) { PEXSetReflectionModel( GfxDpy, Renderer, PEXOCRender, PEXReflectionDiffuse /*Specular*/ ); } else { PEXSetReflectionModel( GfxDpy, Renderer, PEXOCRender, PEXReflectionNone ); } } void transparency_mode( Context ctx, int mode ) { if (mode==1) { ctx->AlphaBlend = 1; } else { ctx->AlphaBlend = 0; } } void set_color( unsigned int c ) { PEXColor color; PEXReflectionAttributes reflection; float alpha; color.rgb.red = UNPACK_RED(c) * 1.0 / 255.0; color.rgb.green = UNPACK_GREEN(c) * 1.0 / 255.0; color.rgb.blue = UNPACK_BLUE(c) * 1.0 / 255.0; PEXSetLineColor(GfxDpy, Renderer, PEXOCRender, PEXColorTypeRGB, &color); PEXSetSurfaceColor(GfxDpy, Renderer, PEXOCRender, PEXColorTypeRGB, &color); PEXSetTextColor(GfxDpy, Renderer, PEXOCRender, PEXColorTypeRGB, &color); alpha = UNPACK_ALPHA(c) * 1.0 / 255.0; reflection.ambient = 1; reflection.diffuse = 1; reflection.transmission = 1.0 - alpha; reflection.specular = 1; reflection.specular_conc = 30; reflection.specular_color.type = PEXColorTypeRGB; reflection.specular_color.value.rgb.red = 1; reflection.specular_color.value.rgb.green = 1; reflection.specular_color.value.rgb.blue = 1; PEXSetReflectionAttributes(GfxDpy, Renderer, PEXOCRender, &reflection); if (reflection.transmission > 0.0) { if (RendererAttrs.hlhsr_mode == PEXHLHSRZBuffer) { /* Make transparent primitives not update the Z buffer so they won't completely obscure later transparent primitives. */ { static int init=False, hsroff; if(!init){init=True; hsroff=(getenv("HSROFF")!=NULL);} if(hsroff) { RendererAttrs.hlhsr_mode = PEXHLHSROff; PEXChangeRenderer(GfxDpy, Renderer, PEXRAHLHSRMode, &RendererAttrs); } } RendererAttrs.hlhsr_mode = PEXHPHLHSRZBufferReadOnly; PEXChangeRenderer(GfxDpy, Renderer, PEXRAHLHSRMode, &RendererAttrs); } } else { if (RendererAttrs.hlhsr_mode == PEXHPHLHSRZBufferReadOnly) { /* Make opaque primitives update the Z buffer. */ RendererAttrs.hlhsr_mode = PEXHLHSRZBuffer; PEXChangeRenderer(GfxDpy, Renderer, PEXRAHLHSRMode, &RendererAttrs); } } } void set_depthcue( int onoff ) { if (onoff) { PEXSetDepthCueIndex(GfxDpy, Renderer, PEXOCRender, 1); } else { PEXSetDepthCueIndex(GfxDpy, Renderer, PEXOCRender, 0); } } void set_line_width( double w ) { PEXSetLineWidth(GfxDpy, Renderer, PEXOCRender, w); } void set_pretty( int onoff ) { } void start_aa_pass( int n ) { /* nothing */ } void end_aa_pass( int n ) { /* nothing */ } /**********************************************************************/ /*** Drawing Functions ***/ /**********************************************************************/ void draw_isosurface( int n, #ifdef BIG_GFX uint_4 *index, #else uint_2 *index, #endif int_2 verts[][3], int_1 norms[][3], unsigned int color ) { int i, j, k, remaining_points; PEXArrayOfVertex data; PEXArrayOfFacetData facet_data; /* a dummy */ PEXVertexNormal vertex_data[VERTS_PER_CALL]; float vscale = 1.0/VERTEX_SCALE; float nscale = 1.0/NORMAL_SCALE; enable_lighting(1); set_color( color ); remaining_points = n; k = 0; data.normal = vertex_data; facet_data.normal = NULL; while (remaining_points > VERTS_PER_CALL) { for (i=0; i 2) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 2) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 2) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 2) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 1) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 1) { for (i=0; iZmin; vertex_data[1].x = x; vertex_data[1].y = y; vertex_data[1].z = z + current_ctx->Zmin; PEXPolyline( GfxDpy, Renderer, PEXOCRender, 2, vertex_data ); vertex_data[0].x = x-0.05; vertex_data[0].y = y; vertex_data[0].z = z + current_ctx->Zmax; vertex_data[1].x = x+0.05; vertex_data[1].y = y; vertex_data[1].z = z + current_ctx->Zmax; PEXPolyline( GfxDpy, Renderer, PEXOCRender, 2, vertex_data ); vertex_data[0].x = x; vertex_data[0].y = y-0.05; vertex_data[0].z = z + current_ctx->Zmax; vertex_data[1].x = x; vertex_data[1].y = y+0.05; vertex_data[1].z = z + current_ctx->Zmax; PEXPolyline( GfxDpy, Renderer, PEXOCRender, 2, vertex_data ); } } #ifdef JUNK /*** polytrinorm ****************************************************** Draw a polytriangle strip with normals. **********************************************************************/ void polytrinorm( vert, norm, n ) float vert[][3]; float norm[][3]; int n; { register int i, index, remaining_points; PEXArrayOfVertex data; PEXArrayOfFacetData facet_data; /* a dummy */ PEXVertexNormal vertex_data[VERTS_PER_CALL]; remaining_points = n; index = 0; data.normal = vertex_data; facet_data.normal = NULL; while (remaining_points > VERTS_PER_CALL) { for (i=0; i 2) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 2) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 1) { for (i=0; i VERTS_PER_CALL) { for (i=0; i 1) { for (i=0; iWinHeight - ypos; PEXText2D(GfxDpy, Renderer, PEXOCRender, &origin, strlen(str), str); if (InvertY) PEXSetGlobalTransform(GfxDpy, Renderer, PEXOCRender, InvertYMatrix); } int text_width( char *str ) { PEXStringData strings[1]; PEXTextExtent *extents; int width; strings[0].length = strlen(str); strings[0].ch = str; extents = PEXQueryTextExtents(GfxDpy, Renderer, 1, PEXPathRight, 1.0, 0.0, 9.0, PEXHAlignNormal, PEXVAlignNormal, 1, strings); if (extents == NULL) { printf("Unable to inquire text extent\n"); exit(-1); } width = extents->upper_right.x - extents->lower_left.x + 1; XFree(extents); return width; } int begin_object( void ) { return 0; } void end_object( void ) { } void call_object( int obj ) { } void delete_object( int objnum ) { } #endif /* HAVE_PEX */