/* * Load colors from a file. */ static void load_colors( LUI_COLORBAR *cb ) { char filename[1000]; /* 16Nov05 Phil McDonald */ char *p_tmp; /* end PM */ FILE *f; float min, max; int i, j, r[MAX_TABLE], g[MAX_TABLE], b[MAX_TABLE], a[MAX_TABLE]; float val; int entries; printf("Enter filename to load colors from: "); fgets(filename,1000,stdin); /* 16Nov05 Phil McDonald */ if ((p_tmp = strchr (filename, '\n')) != NULL) *p_tmp = '\0'; /* end PM */ if (filename[0]==0) { printf("Load aborted\n"); return; } f = fopen( filename, "r" ); if (!f) { printf("Error: couldn't open %s for reading\n", filename ); return; } fscanf( f, "%d %f %f %f %f\n", &entries, &min, &max, &cb->params[CURVE], &cb->params[BIAS] ); for (i=0;i<cb->table_size;i++) { fscanf( f, "%d %d %d %d\n", &r[i], &g[i], &b[i], &a[i] ); } fclose(f); /* now map colors from range specified in file to the range in */ /* the color widget */ for (i=0;i<entries;i++) { /* convert i to a value in [cb->minval,cb->maxval] */ val = cb->minval + (float) i / (float) entries * (cb->maxval-cb->minval); /* convert val to j in [0..cb->table_size] */ j = (int) (cb->table_size * (val-min) / (max-min)); if (j<0) j = 0; else if (j>=cb->table_size) j = cb->table_size-1; cb->table[i] = PACK_COLOR( r[j], g[j], b[j], a[j] ); } printf("Done\n"); }
/* * Given an XEvent, process it if it pertains to a ColorBar, else do * nothing with it. * Input: event - the X event * Output: whichcb - which colorbar this event pertained to. * Return: 1 - if color table was changed. * 2 - if reset key was pressed * 3 - if <shift>+reset key was pressed * 0 - if no change */ static int colorbar_process( LUI_COLORBAR *cb, XEvent *event ) { static int p1 = 0, p2 = 0, p3 = 0, p4 = 0; /* red, green, blue, alpha */ static int pentry; int i, modify, entry, result; static int move_marker; result = modify = 0; if (event->type==KeyPress) { char keybuf[50]; KeySym key; XComposeStatus compose; int count; count = XLookupString( &event->xkey, keybuf, 50, &key, &compose ); if (count==1) { if (keybuf[0]=='r') { /* Reset RGB */ cb->params[DRAWFLAG] = 0.0; result = LUI_RGB_RESET; } else if (keybuf[0]=='R') { /* Reset alpha */ result = LUI_ALPHA_RESET; cb->params[DRAWFLAG] = 0.0; } else if (keybuf[0]=='c' || keybuf[0]=='C') { /* Copy current colors to clipboard */ copy_colors( cb ); } else if (keybuf[0]=='p' || keybuf[0]=='P') { /* Paste clipboard colors to current color widget */ paste_colors( cb ); LUI_ColorBarRedraw( cb ); result = LUI_RGB_CHANGE | LUI_ALPHA_CHANGE; cb->params[DRAWFLAG] = 0.0; result = LUI_RGB_CHANGE | LUI_ALPHA_CHANGE; } /* WLH 7-18-96 */ else if (keybuf[0]=='s' || keybuf[0]=='S') { /* save colors to a file */ save_colors( cb ); } else if (keybuf[0]=='l' || keybuf[0]=='L') { /* load colors from a file */ load_colors( cb ); LUI_ColorBarRedraw( cb ); return 1; } else { /* if unused key, toggle help display */ cb->helpflag = !cb->helpflag; LUI_ColorBarRedraw( cb ); } } else if (key == XK_Left) { /* rotate left */ cb->params[BIAS] -= 0.03/cb->params[CURVE]; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } else if (key == XK_Right) { /* rotate right */ cb->params[BIAS] += 0.03/cb->params[CURVE]; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } else if (key == XK_Up) { /* expand color map */ if (event->xkey.state & ANY_MODIFIER) { cb->params[ALPHAPOW] -= 0.1; if (cb->params[ALPHAPOW]<0.0) cb->params[ALPHAPOW] = 0.0; result = LUI_ALPHA_SHAPE; cb->params[DRAWFLAG] = 0.0; } else { cb->params[CURVE] -= 0.1; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } } else if (key == XK_Down) { /* compress color map */ if (event->xkey.state & ANY_MODIFIER) { cb->params[ALPHAPOW] += 0.1; result = LUI_ALPHA_SHAPE; cb->params[DRAWFLAG] = 0.0; } else { cb->params[CURVE] += 0.1; result = LUI_RGB_SHAPE; cb->params[DRAWFLAG] = 0.0; } } } else if (event->type==Expose && event->xexpose.count==0) { LUI_ColorBarRedraw( cb ); result = 0; } else if (event->type==ConfigureNotify) { /* MJK 4.15.99 */ LUI_ColorBarSetSize( cb, event->xconfigure.width, event->xconfigure.height ); result = 0; } else if (event->type==ButtonPress ) { if (event->xbutton.y<cb->wedge_y) { /* change color function */ move_marker = 0; } else { /* change marker position */ move_marker = 1; } /* determine which curve to modify */ if (event->xbutton.state&ANY_MODIFIER) { p4 = 1; } else { if (event->xbutton.button==Button1) p1 = 1; if (event->xbutton.button==Button2) p2 = 1; if (event->xbutton.button==Button3) p3 = 1; } pentry = x_to_index( cb, event->xbutton.x ); modify = 1; } else if (event->type==ButtonRelease) { if (p1 || p2 || p3) { result = LUI_RGB_CHANGE; } else { result = LUI_ALPHA_CHANGE; } if (event->xbutton.button==Button1) p1 = 0; if (event->xbutton.button==Button2) p2 = 0; if (event->xbutton.button==Button3) p3 = 0; p4 = 0; } else if (event->type==MotionNotify) { /* Flush extra MotionNotify events */ while (QLength(LUI_Display)>0) { XEvent next; XPeekEvent(LUI_Display, &next); if (next.type!=MotionNotify) break; XNextEvent(LUI_Display, event); } modify = 1; } /* Modify one or more of the color curves */ if (modify && (p1 || p2 || p3 || p4)) { /* calculate which entry in color table to change */ entry = x_to_index( cb, event->xbutton.x ); /* update */ if (move_marker) { /* changing marker position */ cb->markerpos = entry; redraw_marker( cb ); } else { /* changing color graph */ int a, b, value; value = y_to_intensity( cb, event->xbutton.y ); if (pentry<=entry) { a = pentry; b = entry; } else { a = entry; b = pentry; } /* update entries from 'pentry' to 'entry' */ for (i=a; i<=b; i++) { int red, green, blue, alpha; red = UNPACK_RED(cb->table[i]); green = UNPACK_GREEN(cb->table[i]); blue = UNPACK_BLUE(cb->table[i]); alpha = UNPACK_ALPHA(cb->table[i]); if (p1) { /* modify red */ red = value; } if (p2) { /* modify green */ green = value; } if (p3) { /* modify blue */ blue = value; } if (p4) { /* modify alpha */ alpha = value; } /* change the color table entry */ cb->table[i] = PACK_COLOR(red,green,blue,alpha); } /* for */ /* redraw the color curves */ if (pentry<entry) redraw_range( cb, pentry-1, entry+1 ); else redraw_range( cb, entry-1, pentry+1 ); pentry = entry; if (p4) { /* update min,max alpha values */ cb->minalpha = 256; cb->maxalpha = 0; for (i=0;i<cb->table_size;i++) { int a = UNPACK_ALPHA( cb->table[i] ); if (a<cb->minalpha) cb->minalpha = a; if (a>cb->maxalpha) cb->maxalpha = a; } } if (p4) { result = LUI_ALPHA_MODIFY; /* result = LUI_ALPHA_CHANGE; */ } else { result = LUI_RGB_MODIFY; /* result = LUI_RGB_CHANGE; */ } cb->params[DRAWFLAG] = 1.0; } } /*modify*/ if (result!=0 && cb->callback) { (*cb->callback)(cb, result); } return result; }
void draw_tick_marks( Display_Context dtx ) { float verts[2][3]; /* base and up vectors for text drawn along x,y,z axes. */ static float bx[3] = { 0.05, 0.0, 0.0 }, ux[3] = { 0.0, 0.05, 0.05 }; /* static float by[3] = { -0.035, 0.0, -0.035 }, uy[3] = { 0.0, 0.07, 0.0 }; static float bz[3] = { -0.035, -0.035, 0.0 }, uz[3] = { 0.0, 0.0, 0.07 }; */ float tick_inc, i, row, col, lev; char str[100]; /* set depth cueing & line color */ /* MJK 3.29.99 */ if (dtx->Reversed) { set_color( PACK_COLOR(0,0,0,255) ); } else { set_color( dtx->BoxColor ); } set_depthcue( dtx->DepthCue ); /* go in the order.. low south side, low east side, go counter-clock-wise, then high south side, couterclockwise, then southeast side, and work coutner-clockwise, so there are 12 sides to loop through */ dtx->tick_do[0] = 1; dtx->tick_type[0] = 1; dtx->tick_num[0] = 10; if (dtx->tick_do[0]) { tick_inc = (float)(dtx->Nc)/(float)(dtx->tick_num[0]-1); row = dtx->Nr-1; lev = 0; for (i = tick_inc; i < dtx->Nc; i += tick_inc) { col = i; vis5d_gridPRIME_to_xyzPRIME(dtx->dpy_context_index, 0, 0, row, col, lev, &verts[0][0], &verts[0][1], &verts[0][2]); verts[1][0] = verts[0][0]; verts[1][1] = verts[0][1] - 0.05; verts[1][2] = verts[0][2] - 0.062; polyline( verts, 2); if (dtx->tick_type[0] == 0) { float lat, lon, hgt; vis5d_gridPRIME_to_geo(dtx->dpy_context_index, 0, 0, row, col, lev, &lat, &lon, &hgt); /*float2string(lon, str); */ if (strlen(str) <2) { plot_string( str, verts[1][0]-.009, verts[1][1]-.05, verts[1][2]-0.062, bx, ux, 0); } else if (strlen(str) <4) { plot_string( str, verts[1][0]-.02, verts[1][1]-.05, verts[1][2]-0.062, bx, ux, 0); } else { plot_string( str, verts[1][0]-.05, verts[1][1]-.05, verts[1][2]-0.062, bx, ux, 0); } } else if (dtx->tick_type[0] == 1) { /* float2string(col, str); */ if (strlen(str) <2) { plot_string( str, verts[1][0]-.009, verts[1][1]-.05, verts[1][2]-0.062, bx, ux, 0); } else if (strlen(str) <4) { plot_string( str, verts[1][0]-.02, verts[1][1]-.05, verts[1][2]-0.062, bx, ux, 0); } else { plot_string( str, verts[1][0]-.05, verts[1][1]-.05, verts[1][2]-0.062, bx, ux, 0); } } } } }
/* * Draw the 3-D box. * Input: it - time step. */ void draw_box( Display_Context dtx, int it ) { /* base and up vectors for text drawn along x,y,z axes. */ static float bx[3] = { 0.05, 0.0, 0.0 }, ux[3] = { 0.0, 0.05, 0.05 }; static float by[3] = { -0.035, 0.0, -0.035 }, uy[3] = { 0.0, 0.07, 0.0 }; static float bz[3] = { -0.035, -0.035, 0.0 }, uz[3] = { 0.0, 0.0, 0.07 }; float x1, y1, z1, x2, y2, z2; char str[100], xdir1[8], xdir2[8], ydir1[8], ydir2[8]; /* set depth cueing & line color */ /* MJK 3.29.99 */ if (dtx->Reversed) { set_color( PACK_COLOR(0,0,0,255) ); } else { set_color( dtx->BoxColor ); } /*MiB*/ xdir1[0] = ' '; xdir2[0] = ' '; xdir1[1] = '\0'; xdir2[1] = '\0'; ydir1[0] = ' '; ydir2[0] = ' '; ydir1[1] = '\0'; ydir2[1] = '\0'; set_depthcue( dtx->DepthCue ); if(dtx->NumBoxVerts > 0) { if (dtx->Reversed) { draw_multi_lines( dtx->NumBoxVerts, dtx->BoxVerts, PACK_COLOR(0,0,0,255) ); } else { draw_multi_lines( dtx->NumBoxVerts, dtx->BoxVerts, dtx->BoxColor ); } } if (dtx->TickMarks) { /* Draw axis labels. */ if (dtx->CoordFlag) { x1 = 1.0; x2 = (float) dtx->Nc; y1 = 1.0; y2 = (float) dtx->Nr; z1 = 1.0; z2 = (float) dtx->MaxNl; } else { x1 = dtx->WestBound; x2 = dtx->EastBound; y1 = dtx->NorthBound; y2 = dtx->SouthBound; /*MiB 03/2001 limit range to -180, 180 */ if (x1 < -180.) { x1 = 360. + x1; } if (x2 < -180.) { x2 = 360. + x2; } if (x1 > 180.) { x1 = -360. + x1; } if (x2 > 180.) { x2 = -360. + x2; } /*MiB 03/2001 Define East/West */ if (x1 > 0.) { xdir1[0] = 'W'; } else { xdir1[0] = 'E'; x1 = x1 *(-1.); } if (x2 > 0.) { xdir2[0] = 'W'; } else { xdir2[0] = 'E'; x2 = x2 *(-1.); } /*MiB 03/2001 Define North/South */ if (y1 > 0.) { ydir1[0] = 'N'; } else { ydir1[0] = 'S'; y1 = y1 *(-1.); } if (y2 > 0.) { ydir2[0] = 'N'; } else { ydir2[0] = 'S'; y2 = y2 *(-1.); } #ifdef LEVELTYPES z1 = dtx->BottomCoordinate; z2 = dtx->TopCoordinate; #else z1 = dtx->BottomBound; z2 = dtx->TopBound; #endif z1 = VERT(z1); z2 = VERT(z2); } if (dtx->CursorX - dtx->Xmin > 0.1 || dtx->DisplayCursor==0) { /* MJK 12.02.98 */ float2string (dtx, 0, x1, str); /*MiB*/ strcat(str,xdir1); plot_string( str, dtx->Xmin-0.02, dtx->Ymin-0.1, dtx->Zmin-0.125, bx, ux, 0 ); } if (dtx->Xmax - dtx->CursorX > 0.1 || dtx->DisplayCursor==0) { /* MJK 12.02.98 */ float2string (dtx, 0, x2, str); /*MiB*/ strcat(str,xdir2); plot_string( str, dtx->Xmax-0.05, dtx->Ymin-0.1, dtx->Zmin-0.125, bx, ux, 0 ); } if (dtx->Ymax - dtx->CursorY > 0.1 || dtx->DisplayCursor==0) { /* MJK 12.02.98 */ float2string (dtx, 1, y1, str); /*MiB*/ strcat(str,ydir1); plot_string( str, dtx->Xmin-0.075, dtx->Ymax-0.03, dtx->Zmin-0.075, by, uy, 1 ); } if (dtx->CursorY-dtx->Ymin > 0.1 || dtx->DisplayCursor==0) { /* MJK 12.02.98 */ float2string (dtx, 2, y2, str); /*MiB*/ strcat(str,ydir2); plot_string( str, dtx->Xmin-0.075, dtx->Ymin-0.02, dtx->Zmin-0.075, by, uy, 1 ); } if (dtx->CursorZ-dtx->Zmin > 0.1 || dtx->DisplayCursor==0) { /* MJK 12.02.98 */ float2string (dtx, 2, z1, str); plot_string( str, dtx->Xmin-0.07, dtx->Ymin-0.07, dtx->Zmin+0.005, bz, uz, 1 ); } if (dtx->Zmax-dtx->CursorZ > 0.1 || dtx->DisplayCursor==0) { /* MJK 12.02.98 */ float2string(dtx, 2, z2, str); plot_string( str, dtx->Xmin-0.07, dtx->Ymin-0.07, dtx->Zmax+0.005, bz, uz, 1 ); } } set_depthcue( 0 ); }
/* * Initialize the topography color table. * Input: ct - the color table * size - number of entries in the table * minhgt, maxhgt - the range of height values */ void init_topo_color_table( unsigned int ct[], int size, float minhgt, float maxhgt ) { #define OCEAN #ifdef OCEAN /* Change submitted by Mike McCann to give better under-water */ /* topography colors. */ static float red[7] = { 5.0, 45.0, 20.0, 20.0, 70.0, 165.0, 200.0}; static float green[7] = {10.0, 50.0, 170.0,170.0, 200.0, 42.0, 200.0}; static float blue[7] = {30.0,150.0, 42.0, 42.0, 0.0, 42.0, 200.0}; static float range[7] = {-5.0, -0.020,-0.015, 0.0, 0.1, 1.0, 2.8}; #else static float red[4] = { 20.0, 70.0, 165.0, 200.0}; static float green[4] = {170.0, 200.0, 42.0, 200.0}; static float blue[4] = { 42.0, 0.0, 42.0, 200.0}; static float range[4] = { 0.0, 0.1, 1.0, 2.8}; #endif int i, j; float x0, x1; float r, g, b, dr, dg, db; /* initialize to all white to start */ for (i=0;i<size-1;i++) { ct[i] = 0xffffffff; } ct[size-1] = PACK_COLOR( 25, 25, 255, 255 ); /* r=25, g=25, b=255 */ #ifdef OCEAN for (i=0;i<6;i++) { #else for (i=0;i<3;i++) { #endif if (minhgt==maxhgt) { r = g = b = 0; dr = dg = db = 0; x0 = x1 = 0; } else { x0 = (range[i] - minhgt) / (maxhgt - minhgt) * (float)(size-1); x1 = (range[i+1] - minhgt) / (maxhgt - minhgt) * (float)(size-1); dr = (red[i+1]-red[i]) / (x1-x0); dg = (green[i+1]-green[i]) / (x1-x0); db = (blue[i+1]-blue[i]) / (x1-x0); r = red[i]; g = green[i]; b = blue[i]; } for (j=(int) x0; j<(int) x1; j++) { if (j>=0 && j<size-1) { ct[j] = PACK_COLOR( (int) r, (int) g, (int) b, 0xff ); } r += dr; g += dg; b += db; } } } /* * Generate the topography quadmesh. This must be called after the * grid data set has been loaded. * Input: toponame - name of topography file * textureflag - 1 = use texture mapping, 0 = don't texture map * hi_res - 1=high resolution topography, 0=normal resolution * Return: 1 = ok, 0 = error */ int init_topo( Display_Context dtx, char *toponame, int textureflag, int hi_res ) { double dx, dy; float lat, lon; float topo_dlat, topo_dlon; float *topoheight; int i, j; int topoflag = -1; int qr, qc; uint_1 *indexes; struct Topo *topo; /* MJK 12.02.98 begin */ if (dtx->UserTopoFlag) { topoflag = read_user_topo( dtx, toponame ); if (topoflag == 0) return 0; } if (topoflag == -1) { topoflag = read_topo( dtx->topo, toponame ); } topo = dtx->topo; /* MJK 12.02.98 end */ if (!topoflag && !textureflag) { return 0; } /* qrows, qcols - size of topography quadmesh in rows and columns */ if (topo->Topo_cols==dtx->Nc && topo->Topo_rows==dtx->Nr) { /* use same topography resolution as grid resolution */ qc = topo->Topo_cols; qr = topo->Topo_rows; } else { int maxverts = hi_res ? HI_RES_VERTS : LO_RES_VERTS; float r; if(((dtx->Xmax - dtx->Xmin)*(dtx->Ymax - dtx->Ymin))==0){ fprintf(stderr,"Error in init_topo %f %f %f %f\n",dtx->Xmax,dtx->Xmin,dtx->Ymax,dtx->Ymin); return -1; } r = sqrt( (float) maxverts / ((dtx->Xmax - dtx->Xmin)*(dtx->Ymax - dtx->Ymin)) ); qc = (int) (r * (dtx->Xmax - dtx->Xmin) + 0.5); qr = (int) (r * (dtx->Ymax - dtx->Ymin) + 0.5); } /* allocate space for topography vertex and color arrays */ if (topo->TopoVertex){ free(topo->TopoVertex); free(topo->TopoNormal); free(topo->TopoTexcoord); free(topo->TopoFlatVertex); /* MJK 12.02.98 begin */ for (i = 0; i <= MAXTIMES; i++) { if (topo->TopoIndexes[i] != NULL) free (topo->TopoIndexes[i]), topo->TopoIndexes[i] = NULL; } /* MJK 12.02.98 end */ /* free(topo->TopoIndexes[MAXTIMES]); */ } topo->TopoVertex = (float *) malloc( qr*qc*3*sizeof(float) ); topo->TopoNormal = (float *) malloc( qr*qc*3*sizeof(float) ); topo->TopoTexcoord = (float *) malloc( qr*qc*2*sizeof(float) ); topo->TopoFlatVertex = (float *) malloc( qr*qc*3*sizeof(float) ); topoheight = (float *) malloc( qr*qc*sizeof(float) ); /* topoheight = (float *) allocate( dtx, qr*qc*sizeof(float) ); */ indexes = malloc( qr*qc*1*sizeof(uint_1) ); topo->TopoIndexes[MAXTIMES] = indexes; /* * Compute topography vertices. */ if (dtx->CurvedBox==0) { /* Rectangular box: generate vertices in graphics coords */ int k; float x, y, z; /* MJK 12.15.98 */ double xx, yy, texture_s, texture_t, delta_s, delta_t; dx = (dtx->Xmax-dtx->Xmin) / (float) (qc-1); dy = (dtx->Ymax-dtx->Ymin) / (float) (qr-1); delta_s = 1.0 / (float) (qc-1); delta_t = 1.0 / (float) (qr-1); /* calculate sampling size */ if (topo->Topo_cols==dtx->Nc && topo->Topo_rows==dtx->Nr) { topo->LatSample = topo->LonSample = 1; } else { topo_dlat = (topo->Topo_northlat-topo->Topo_southlat) / topo->Topo_rows; topo->LatSample = CLAMP( (int) (2.0*dy/topo_dlat), 2, 20 ); topo_dlon = (topo->Topo_westlon-topo->Topo_eastlon) / topo->Topo_cols; topo->LonSample = CLAMP( (int) (2.0*dx/topo_dlon), 2, 20 ); } k = 0; yy = dtx->Ymax; texture_t = 0.0; for (i=0; i<qr; i++) { xx = dtx->Xmin; texture_s = 0.0; y = yy; for (j=0; j<qc; j++) { int water; float hgt; x = xx; xyzPRIME_to_geo( dtx, -1, -1, x, y, 0.0, &lat, &lon, &hgt ); hgt = elevation( dtx, dtx->topo, lat, lon, &water ) / 1000.0; /* hgt in km */ /* MJK 2.17.99 z = height_to_zPRIME( dtx, hgt ); */ z = height_to_zTOPO( dtx, hgt ); /* WLH 3 Nov 98 - kludge topo for inverted VERT_GENERIC */ if (dtx->VerticalSystem == VERT_GENERIC && dtx->TopBound < dtx->BottomBound) { z = dtx->Zmin + hgt / (dtx->BottomBound-dtx->TopBound) * (dtx->Zmax-dtx->Zmin); } z = ABS(dtx->Zmin - z) < 0.01 ? dtx->Zmin+0.01 : z; topo->TopoVertex[k*3+0] = x; topo->TopoVertex[k*3+1] = y; topo->TopoVertex[k*3+2] = z; topoheight[k] = hgt; /* save topo height at this vertex */ /* if water flag is set, index will be 255 */ indexes[k] = (water) ? 255 : 0; topo->TopoFlatVertex[k*3+0] = x; topo->TopoFlatVertex[k*3+1] = y; topo->TopoFlatVertex[k*3+2] = dtx->Zmin; topo->TopoTexcoord[k*2+0] = texture_s; topo->TopoTexcoord[k*2+1] = texture_t; k++; xx += dx; texture_s += delta_s; } yy -= dy; texture_t += delta_t; } } else { /* Curved box: generate vertices in geographic coordinates */ float lat, lon; double latlat, lonlon; double dlat, dlon; int k; float texture_s, texture_t, delta_s, delta_t; dlat = (dtx->NorthBound - dtx->SouthBound) / (float) (qr-1); dlon = (dtx->WestBound - dtx->EastBound) / (float) (qc-1); delta_s = 1.0 / (float) (qc-1); delta_t = 1.0 / (float) (qr-1); k = 0; latlat = dtx->NorthBound; texture_t = 0.0; for (i=0; i<qr; i++) { lonlon = dtx->WestBound; lat = latlat; texture_s = 0.0; for (j=0; j<qc; j++) { int water; float hgt, x, y, z; lon = lonlon; hgt = elevation( dtx, dtx->topo, lat, lon, &water ) / 1000.0; /* hgt in km */ /* MJK 2.17.99 geo_to_xyzPRIME( dtx, -1, -1, 1, &lat, &lon, &hgt, &x, &y, &z ); */ geo_to_xyzTOPO( dtx, -1, -1, 1, &lat, &lon, &hgt, &x, &y, &z ); topo->TopoVertex[k*3+0] = x; topo->TopoVertex[k*3+1] = y; topo->TopoVertex[k*3+2] = z; topoheight[k] = hgt; /* if water flag is set, index will be 255 */ indexes[k] = (water) ? 255 : 0; hgt = dtx->BottomBound; /* MJK 2.17.99 geo_to_xyzPRIME( dtx, -1, -1, 1, &lat, &lon, &hgt, &x, &y, &z ); */ geo_to_xyzTOPO( dtx, -1, -1, 1, &lat, &lon, &hgt, &x, &y, &z ); topo->TopoFlatVertex[k*3+0] = x; topo->TopoFlatVertex[k*3+1] = y; topo->TopoFlatVertex[k*3+2] = z; topo->TopoTexcoord[k*2+0] = texture_s; topo->TopoTexcoord[k*2+1] = texture_t; k++; lonlon -= dlon; texture_s += delta_s; } latlat -= dlat; texture_t += delta_t; } } /* Find MinTopoHgt and MaxTopoHgt */ topo->MinTopoHgt = 10000.0; topo->MaxTopoHgt = -10000.0; for (i=0;i<qr*qc;i++) { if (topoheight[i]<topo->MinTopoHgt) { topo->MinTopoHgt = topoheight[i]; } if (topoheight[i]>topo->MaxTopoHgt) { topo->MaxTopoHgt = topoheight[i]; } } /* Compute topography color table indexes. */ for (i=0;i<qr*qc;i++) { float hgt = topoheight[i]; if (indexes[i]!=255) { /* if not water */ if (topo->MinTopoHgt==topo->MaxTopoHgt) { indexes[i] = 0; } else { int index; index = (int) ( (hgt-topo->MinTopoHgt) / (topo->MaxTopoHgt-topo->MinTopoHgt) * 254.0 ); indexes[i] = CLAMP( index, 0, 254 ); } } } /* done with topoheight array */ free( topoheight ); /* compute quadmesh normal vectors */ { float *qnorm; qnorm = (float *) malloc( qc * qr * 3 * sizeof(float) ); /* qnorm = (float *) allocate( dtx, qc * qr * 3 * sizeof(float) ); */ /* step 1: compute surface normal for each quadrilateral. */ for (i=0;i<qr-1;i++) { for (j=0;j<qc-1;j++) { float a[3], b[3]; int index; index = (i*qc+j)*3; /* a is the down vector, b is the right vector */ a[0] = topo->TopoVertex[index+qc*3+0] - topo->TopoVertex[index+0]; a[1] = topo->TopoVertex[index+qc*3+1] - topo->TopoVertex[index+1]; a[2] = topo->TopoVertex[index+qc*3+2] - topo->TopoVertex[index+2]; b[0] = topo->TopoVertex[index+3+0] - topo->TopoVertex[index+0]; b[1] = topo->TopoVertex[index+3+1] - topo->TopoVertex[index+1]; b[2] = topo->TopoVertex[index+3+2] - topo->TopoVertex[index+2]; /* a cross b is the quad's facet normal */ qnorm[index+0] = a[1]*b[2]-a[2]*b[1]; qnorm[index+1] = -a[0]*b[2]+a[2]*b[0]; qnorm[index+2] = a[0]*b[1]-a[1]*b[0]; } } /* step 2: compute vertex normals by averaging adjacent */ /* quadrilateral normals. */ for (i=0;i<qr;i++) { for (j=0;j<qc;j++) { float n[3], mag; int index; index = (i*qc+j)*3; n[0] = n[1] = n[2] = 0.0; /* upper-left quad */ if (i>0 && j>0) { n[0] += qnorm[ index-qc*3-3+0 ]; n[1] += qnorm[ index-qc*3-3+1 ]; n[2] += qnorm[ index-qc*3-3+2 ]; } /* upper-right quad */ if (i>0 && j<qc-1) { n[0] += qnorm[ index-qc*3+0 ]; n[1] += qnorm[ index-qc*3+1 ]; n[2] += qnorm[ index-qc*3+2 ]; } /* lower-left quad */ if (i<qr-1 && j>0) { n[0] += qnorm[ index-3+0 ]; n[1] += qnorm[ index-3+1 ]; n[2] += qnorm[ index-3+2 ]; } /* lower-right quad */ if (i<qr-1 && j<qc-1) { n[0] += qnorm[ index+0 ]; n[1] += qnorm[ index+1 ]; n[2] += qnorm[ index+2 ]; } mag = sqrt( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] ); if (mag>0.0) { mag = 1.0 / mag; topo->TopoNormal[index+0] = n[0] * mag; topo->TopoNormal[index+1] = n[1] * mag; topo->TopoNormal[index+2] = n[2] * mag; } } } free (qnorm); /* deallocate( dtx, qnorm, qc * qr * 3 * sizeof(float) ); */ } topo->qcols = qc; topo->qrows = qr; /* Define the initial quadmesh vertex colors */ if(dtx->ColorTable[VIS5D_TOPO_CT]==NULL){ dtx->ColorTable[VIS5D_TOPO_CT] = (struct ColorTable *) calloc(1,sizeof(struct ColorTable)); } init_topo_color_table( dtx->ColorTable[VIS5D_TOPO_CT]->Colors[MAXVARS*VIS5D_MAX_CONTEXTS], 256, topo->MinTopoHgt, topo->MaxTopoHgt ); topo->TopoColorVar = -1; /* MJK 12.02.98 */ make_topo_strips (dtx); return 1; }
/* * Draw the topography. * Input: time - the timestep number * texture_flag - 0=no texture, 1=texture map * flat_flag - 0=draw w/ topo heights, 1=draw flat */ void draw_topo( Display_Context dtx, int time, int texture_flag, int flat_flag ) { /* MJK 12.02.98 begin */ int i, j, n, ir, ic, nr, nc, nr2, nc2; int_vert2 *verts; int_1 *norms; uint_1 *color; /* MJK 12.02.98 end */ struct Topo *topo; topo = dtx->topo; set_color( 0xffffffff ); if (flat_flag) { if (texture_flag) { /* flat texture map */ use_texture( dtx, time ); texture_quadmeshnorm( topo->qrows, topo->qcols, (void*) topo->TopoFlatVertex, NULL, (void*) topo->TopoTexcoord ); } else { /* draw nothing */ } } else { if (texture_flag) { /* textured topo */ use_texture( dtx, time ); texture_quadmeshnorm( topo->qrows, topo->qcols, (void*) topo->TopoVertex, (void*) topo->TopoNormal, (void*) topo->TopoTexcoord ); } else { /* untextured topo */ uint_1 *indexes; unsigned int *color_table; if (topo->TopoColorVar<0) { color_table = dtx->ColorTable[VIS5D_TOPO_CT]->Colors[MAXVARS*VIS5D_MAX_CONTEXTS]; indexes = topo->TopoIndexes[MAXTIMES]; } else { color_table = dtx->ColorTable[VIS5D_TOPO_CT]->Colors[ topo->TopoColorVarOwner * MAXVARS + topo->TopoColorVar ]; indexes = topo->TopoIndexes[time]; if (!indexes) { indexes = topo->TopoIndexes[MAXTIMES]; } } /* MJK 12.02.98 begin */ if (topo->TopoStripsVerts == NULL) return; if (topo->TopoStripsNorms == NULL) return; verts = topo->TopoStripsVerts; norms = topo->TopoStripsNorms; nr = topo->qrows; nc = topo->qcols; nr2 = nr * 2; nc2 = nc * 2; n = (nr > nc) ? nr : nc; color = (uint_1 *) malloc ((n * 2 * sizeof (uint_1))); if (color == NULL) return; /* topography */ j = 0; i = nc; for (ir = 1; ir < nr; ir++) { n = 0; for (ic = 0; ic < nc; ic++) { color[n++] = indexes[i++]; color[n++] = indexes[j++]; } draw_colored_triangle_strip (nc2, (void *) verts, (void *) norms, color, color_table, 255); verts += nc2 * 3; norms += nc2 * 3; } if (topo->DisplayTopoBase) { unsigned int base_color = TOPO_BASE_COLOR; int norm_dir = 1; /* MJK 3.29.99 */ clipping_off(); n = (nr > nc) ? nr : nc; memset (color, 0, (n * 2 * sizeof (uint_1))); /* MJK reversed this 2.16.99 norm_dir = (topo->TopoBaseLev < 0.0) ? -1 : 1; */ /* MJK 3.29.99 don't know why this is here norm_dir = (topo->TopoBaseLev < 0.0) ? -1 : 1; */ norm_dir = 1; /* north side */ if ((check_face_norm(verts) * norm_dir > 0)) draw_colored_triangle_strip (nc2, (void *) verts, (void *) norms, color, &base_color, 255); verts += nc2 * 3; norms += nc2 * 3; /* south side */ if ((check_face_norm(verts) * norm_dir) > 0) draw_colored_triangle_strip (nc2, (void *) verts, (void *) norms, color, &base_color, 255); verts += nc2 * 3; norms += nc2 * 3; /* west side */ if ((check_face_norm(verts) * norm_dir) > 0) draw_colored_triangle_strip (nr2, (void *) verts, (void *) norms, color, &base_color, 255); verts += nr2 * 3; norms += nr2 * 3; /* east side */ if ((check_face_norm(verts) * norm_dir) > 0) draw_colored_triangle_strip (nr2, (void *) verts, (void *) norms, color, &base_color, 255); verts += nr2 * 3; norms += nr2 * 3; /* bottom */ if ((check_face_norm(verts) * norm_dir) > 0) { float r, g, b, a, fac = 0.90; /* color the bottom slightly darker than the sides */ r = (((float) UNPACK_RED (base_color)) / 255.0) * fac; g = (((float) UNPACK_GREEN (base_color)) / 255.0) * fac; b = (((float) UNPACK_BLUE (base_color)) / 255.0) * fac; a = ((float) UNPACK_ALPHA (base_color)) / 255.0; base_color = PACK_COLOR ((int) (r * 255.0), (int) (g * 255.0), (int) (b * 255.0), (int) (a * 255.0)); for (ir = 1; ir < nr; ir++) { draw_colored_triangle_strip (nc2, (void *) verts, (void *) norms, color, &base_color, 255); verts += nc2 * 3; norms += nc2 * 3; } } /* MJK 3.29.99 */ clipping_on(); } free (color); } } }