/* * $Id: gsd_wire.c,v 2.1 2006/02/09 03:08:57 glynn Exp $ */ /* gsd.c Bill Brown, USACERL January 1993 */ #include #include #include "gsget.h" #include "rowcol.h" /* #define TRACE_DFUNCS */ #define DO_ARROWS /************************************************************************/ /* Notes on exageration: vertical exageration is of two forms: 1) global exageration (from geoview struct) 2) vertical exageration for each surface - not implemented */ /************************************************************************/ /* may need to add more parameters to tell it which window or off_screen * pixmap to draw into. nah - just have one current (OpenGL limitation) */ int gsd_wire_surf(geosurf * surf) { int desc, ret; #ifdef TRACE_DFUNCS { Gs_status("gsd_wire_surf"); } #endif desc = ATT_TOPO; switch (gs_get_att_src(surf, desc)) { case NOTSET_ATT: ret = (-1); break; case MAP_ATT: if (surf->draw_mode & DM_GRID_WIRE) ret = (gsd_wire_surf_map(surf)); /* draw mesh */ else ret = (gsd_coarse_surf_map(surf)); /* draw coarse surf */ #ifdef DO_ARROWS /* gsd_wire_arrows(surf); */ #endif break; case CONST_ATT: ret = (gsd_wire_surf_const(surf, surf->att[desc].constant)); break; case FUNC_ATT: ret = (gsd_wire_surf_func(surf, surf->att[desc].user_func)); break; default: ret = (-1); break; } return (ret); } /************************************************************************/ int gsd_wire_surf_map(geosurf * surf) { int check_mask, check_color; typbuff *buff, *cobuff; int xmod, ymod, row, col, cnt, xcnt, ycnt, x1off; long offset, y1off; float pt[4], xres, yres, ymax, zexag; int col_src, curcolor; gsurf_att *coloratt; #ifdef TRACE_DFUNCS { Gs_status("gsd_wire_surf_map"); } #endif buff = gs_get_att_typbuff(surf, ATT_TOPO, 0); cobuff = gs_get_att_typbuff(surf, ATT_COLOR, 0); gs_update_curmask(surf); check_mask = surf->curmask ? 1 : 0; /* checks ATT_TOPO & ATT_COLOR no_zero flags, make a mask from each, combine it/them with any current mask, put in typbuff: if(surf->att[ATT_TOPO].constant) */ xmod = surf->x_modw; ymod = surf->y_modw; xres = xmod * surf->xres; yres = ymod * surf->yres; ymax = (surf->rows - 1) * surf->yres; xcnt = 1 + (surf->cols - 1) / xmod; ycnt = 1 + (surf->rows - 1) / ymod; gsd_pushmatrix(); gsd_do_scale(1); gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans); zexag = surf->z_exag; gsd_colormode(CM_COLOR); /* will need to check for color source of FUNC_ATT & NOTSET_ATT, or else use more general and inefficient gets */ check_color = (surf->wire_color == WC_COLOR_ATT); if (check_color) { coloratt = &(surf->att[ATT_COLOR]); col_src = surf->att[ATT_COLOR].att_src; if (col_src != MAP_ATT) { if (col_src == CONST_ATT) { gsd_color_func((int) surf->att[ATT_COLOR].constant); } else { gsd_color_func(surf->wire_color); } check_color = 0; } } else { gsd_color_func(surf->wire_color); } /* would also be good to check if colormap == surfmap, to increase speed */ for (row = 0; row < ycnt; row++) { pt[Y] = ymax - row * yres; y1off = row * ymod * surf->cols; gsd_bgnline(); cnt = 0; for (col = 0; col < xcnt; col++) { pt[X] = col * xres; x1off = col * xmod; offset = x1off + y1off; if (check_mask) { if (BM_get(surf->curmask, col * xmod, row * ymod)) { gsd_endline(); gsd_bgnline(); cnt = 0; continue; } } GET_MAPATT(buff, offset, pt[Z]); if (check_color) { curcolor = gs_mapcolor(cobuff, coloratt, offset); gsd_color_func(curcolor); /* could use this & skip the GET if colordata == elevdata gsd_color_func(gs_fastmapcolor(cobuff, coloratt, offset, (int)pt[Z])); */ } pt[Z] = pt[Z] * zexag; gsd_vert_func(pt); if (cnt == 255) { gsd_endline(); gsd_bgnline(); cnt = 0; gsd_vert_func(pt); } cnt++; } gsd_endline(); } for (col = 0; col < xcnt; col++) { pt[X] = col * xres; x1off = col * xmod; gsd_bgnline(); cnt = 0; for (row = 0; row < ycnt; row++) { pt[Y] = ymax - row * yres; y1off = row * ymod * surf->cols; offset = x1off + y1off; if (check_mask) { if (BM_get(surf->curmask, col * xmod, row * ymod)) { gsd_endline(); gsd_bgnline(); cnt = 0; continue; } } GET_MAPATT(buff, offset, pt[Z]); if (check_color) { curcolor = gs_mapcolor(cobuff, coloratt, offset); gsd_color_func(curcolor); /* could use this & skip the GET if colordata == elevdata gsd_color_func(gs_fastmapcolor(coloratt, offset, (int)pt[Z])); */ } pt[Z] = pt[Z] * zexag; gsd_vert_func(pt); if (cnt == 255) { gsd_endline(); gsd_bgnline(); cnt = 0; gsd_vert_func(pt); } cnt++; } gsd_endline(); } gsd_popmatrix(); gsd_colormode(CM_DIFFUSE); return (1); } /************************************************************************/ int gsd_wire_surf_const(geosurf * surf, float k) { int do_diff, check_mask, check_color; int xmod, ymod, row, col, cnt, xcnt, ycnt, x1off; long offset, y1off; float pt[4], xres, yres, ymax, zexag; int col_src; gsurf_att *coloratt; typbuff *cobuff; #ifdef TRACE_DFUNCS { Gs_status("gsd_wire_surf_const"); } #endif cobuff = gs_get_att_typbuff(surf, ATT_COLOR, 0); gs_update_curmask(surf); check_mask = surf->curmask ? 1 : 0; do_diff = (NULL != gsdiff_get_SDref()); xmod = surf->x_modw; ymod = surf->y_modw; xres = xmod * surf->xres; yres = ymod * surf->yres; xcnt = 1 + (surf->cols - 1) / xmod; ycnt = 1 + (surf->rows - 1) / ymod; ymax = (surf->rows - 1) * surf->yres; gsd_pushmatrix(); gsd_do_scale(1); gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans); zexag = surf->z_exag; gsd_colormode(CM_COLOR); /* will need to check for color source of FUNC_ATT & NOTSET_ATT, or else use more general and inefficient gets */ check_color = (surf->wire_color == WC_COLOR_ATT); if (check_color) { coloratt = &(surf->att[ATT_COLOR]); col_src = surf->att[ATT_COLOR].att_src; if (col_src != MAP_ATT) { if (col_src == CONST_ATT) { gsd_color_func((int) surf->att[ATT_COLOR].constant); } else { gsd_color_func(surf->wire_color); } check_color = 0; } } else { gsd_color_func(surf->wire_color); } pt[Z] = k * zexag; for (row = 0; row < ycnt; row++) { pt[Y] = ymax - row * yres; y1off = row * ymod * surf->cols; gsd_bgnline(); cnt = 0; for (col = 0; col < xcnt; col++) { pt[X] = col * xres; x1off = col * xmod; offset = x1off + y1off; if (check_mask) { if (BM_get(surf->curmask, col * xmod, row * ymod)) { gsd_endline(); gsd_bgnline(); cnt = 0; continue; } } if (check_color) { gsd_color_func(gs_mapcolor(cobuff, coloratt, offset)); } if (do_diff) { pt[Z] = gsdiff_do_SD(k * zexag, offset); } gsd_vert_func(pt); if (cnt == 255) { gsd_endline(); gsd_bgnline(); cnt = 0; gsd_vert_func(pt); } cnt++; } gsd_endline(); } for (col = 0; col < xcnt; col++) { pt[X] = col * xres; x1off = col * xmod; gsd_bgnline(); cnt = 0; for (row = 0; row < ycnt; row++) { pt[Y] = ymax - row * yres; y1off = row * ymod * surf->cols; offset = x1off + y1off; if (check_mask) { if (BM_get(surf->curmask, col * xmod, row * ymod)) { gsd_endline(); gsd_bgnline(); cnt = 0; continue; } } if (check_color) { gsd_color_func(gs_mapcolor(cobuff, coloratt, offset)); } if (do_diff) { pt[Z] = gsdiff_do_SD(k * zexag, offset); } gsd_vert_func(pt); if (cnt == 255) { gsd_endline(); gsd_bgnline(); cnt = 0; gsd_vert_func(pt); } cnt++; } gsd_endline(); } gsd_popmatrix(); gsd_colormode(CM_DIFFUSE); return (1); } /************************************************************************/ int gsd_wire_surf_func(geosurf * gs, int (*user_func) ()) { return (1); } /************************************************************************/ /* need to do Zexag scale of normal for arrow direction, drawing routine unexags z for arrow */ int gsd_wire_arrows(geosurf * surf) { typbuff *buff, *cobuff; int check_mask, check_color; int xmod, ymod, row, col, xcnt, ycnt; long offset, y1off; float tx, ty, tz, sz; float n[3], pt[4], xres, yres, ymax, zexag; int col_src, curcolor; gsurf_att *coloratt; #ifdef TRACE_DFUNCS { Gs_status("gsd_norm_arrows"); } #endif /* avoid scaling by zero */ GS_get_scale(&tx, &ty, &tz, 1); if (tz == 0.0) { return (0); } sz = GS_global_exag(); gs_update_curmask(surf); check_mask = surf->curmask ? 1 : 0; /* checks ATT_TOPO & ATT_COLOR no_zero flags, make a mask from each, combine it/them with any current mask, put in surf->curmask: */ check_color = 1; coloratt = &(surf->att[ATT_COLOR]); col_src = surf->att[ATT_COLOR].att_src; if (col_src != MAP_ATT) { if (col_src == CONST_ATT) { curcolor = (int) surf->att[ATT_COLOR].constant; } else { curcolor = surf->wire_color; } check_color = 0; } buff = gs_get_att_typbuff(surf, ATT_TOPO, 0); cobuff = gs_get_att_typbuff(surf, ATT_COLOR, 0); xmod = surf->x_modw; ymod = surf->y_modw; xres = xmod * surf->xres; yres = ymod * surf->yres; ymax = (surf->rows - 1) * surf->yres; xcnt = 1 + (surf->cols - 1) / xmod; ycnt = 1 + (surf->rows - 1) / ymod; gsd_pushmatrix(); gsd_do_scale(1); gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans); zexag = surf->z_exag; /* CURRENTLY ALWAYS 1.0 */ gsd_colormode(CM_COLOR); for (row = 0; row < ycnt; row++) { pt[Y] = ymax - row * yres; y1off = row * ymod * surf->cols; for (col = 0; col < xcnt; col++) { pt[X] = col * xres; offset = col * xmod + y1off; if (check_mask) { if (BM_get(surf->curmask, col * xmod, row * ymod)) { continue; } } FNORM(surf->norms[offset], n); GET_MAPATT(buff, offset, pt[Z]); pt[Z] *= zexag; if (check_color) { curcolor = gs_mapcolor(cobuff, coloratt, offset); } gsd_arrow(pt, curcolor, xres * 2, n, sz, surf); } /* ea col */ } /* ea row */ gsd_popmatrix(); gsd_colormode(CM_DIFFUSE); return (1); } /*********************************************************** * New (TEST) wire routine that draws low res surface * Based on new Trinagle Fan routine * Resolution is a function of current surface resolution * times wire resolution * TODO - normals have to be recalculated before proper low * res surface can be drawn * In window optimization has been removed *************************************************************/ int gsd_coarse_surf_map(geosurf * surf) { int check_mask, check_color, check_transp; int check_material, check_emis, check_shin; typbuff *buff, *cobuff, *trbuff, *embuff, *shbuff; int xmod, ymod; int row, col, xcnt, ycnt; long y1off, y2off, y3off; long offset2[10]; float pt2[10][2]; int ii; float x1, x2, x3, y1, y2, y3, tx, ty, tz, ttr; float n[3], pt[4], xres, yres, ymax, zexag; int em_src, sh_src, trans_src, col_src, curcolor; gsurf_att *ematt, *shatt, *tratt, *coloratt; int datarow1, datacol1, datarow2, datacol2, datarow3, datacol3; float kem, ksh, pkem, pksh; unsigned int ktrans; int step_val = 2 * surf->x_modw; /* should always be factor of 2 for fan */ int start_val = surf->x_modw; /* ensure normals are correct */ gs_calc_normals(surf); /* avoid scaling by zero */ GS_get_scale(&tx, &ty, &tz, 1); if (tz == 0.0) { return (gsd_surf_const(surf, 0.0)); } /* else if (surf->z_exag == 0.0) { return(gsd_surf_const(surf, surf->z_min)); } NOT YET IMPLEMENTED */ buff = gs_get_att_typbuff(surf, ATT_TOPO, 0); cobuff = gs_get_att_typbuff(surf, ATT_COLOR, 0); gs_update_curmask(surf); check_mask = surf->curmask ? 1 : 0; /* checks ATT_TOPO & ATT_COLOR no_zero flags, make a mask from each, combine it/them with any current mask, put in surf->curmask: */ xmod = surf->x_mod; ymod = surf->y_mod; xres = xmod * surf->xres; yres = ymod * surf->yres; ymax = (surf->rows - 1) * surf->yres; xcnt = VCOLS(surf); ycnt = VROWS(surf); gsd_pushmatrix(); gsd_do_scale(1); gsd_translate(surf->x_trans, surf->y_trans, surf->z_trans); zexag = surf->z_exag; gsd_colormode(CM_DIFFUSE); /* CURRENTLY ALWAYS 1.0 */ #ifdef CALC_AREA sz = GS_global_exag(); #endif /* TODO: get rid of (define) these magic numbers scaling the attribute vals */ check_transp = 0; tratt = &(surf->att[ATT_TRANSP]); ktrans = (255 << 24); trans_src = surf->att[ATT_TRANSP].att_src; if (CONST_ATT == trans_src && surf->att[ATT_TRANSP].constant != 0.0) { ktrans = (255 - (int) surf->att[ATT_TRANSP].constant) << 24; gsd_blend(1); gsd_zwritemask(0x0); } else if (MAP_ATT == trans_src) { trbuff = gs_get_att_typbuff(surf, ATT_TRANSP, 0); check_transp = trbuff ? 1 : 0; gsd_blend(1); gsd_zwritemask(0x0); } check_emis = 0; ematt = &(surf->att[ATT_EMIT]); kem = 0.0; pkem = 1.0; em_src = surf->att[ATT_EMIT].att_src; if (CONST_ATT == em_src) { kem = surf->att[ATT_EMIT].constant / 255.; } else if (MAP_ATT == em_src) { embuff = gs_get_att_typbuff(surf, ATT_EMIT, 0); check_emis = embuff ? 1 : 0; } check_shin = 0; shatt = &(surf->att[ATT_SHINE]); ksh = 0.0; pksh = 1.0; sh_src = surf->att[ATT_SHINE].att_src; if (CONST_ATT == sh_src) { ksh = surf->att[ATT_SHINE].constant / 255.; gsd_set_material(1, 0, ksh, kem, 0x0); } else if (MAP_ATT == sh_src) { shbuff = gs_get_att_typbuff(surf, ATT_SHINE, 0); check_shin = shbuff ? 1 : 0; } /* will need to check for color source of FUNC_ATT & NOTSET_ATT, or else use more general and inefficient gets */ check_color = 1; coloratt = &(surf->att[ATT_COLOR]); col_src = surf->att[ATT_COLOR].att_src; if (col_src != MAP_ATT) { if (col_src == CONST_ATT) { curcolor = (int) surf->att[ATT_COLOR].constant; } else { curcolor = surf->wire_color; } check_color = 0; } check_material = (check_shin || check_emis || (kem && check_color)); /* would also be good to check if colormap == surfmap, to increase speed */ /* will also need to set check_transp, check_shine, etc & fix material */ for (row = start_val; row <= ycnt-start_val; row+=step_val) { datarow1 = row * ymod; datarow2 = (row - (step_val/2)) * ymod; datarow3 = (row + (step_val/2)) * ymod; y1 = ymax - row*yres; y2 = ymax - (row-(step_val/2))*yres; y3 = ymax - (row+(step_val/2))*yres; y1off = row * ymod * surf->cols; y2off = (row - (step_val/2)) * ymod * surf->cols; y3off = (row + (step_val/2)) * ymod * surf->cols; for (col = start_val; col <= xcnt-start_val; col+=step_val) { datacol1 = col * xmod; datacol2 = (col - (step_val/2)) * xmod; datacol3 = (col + (step_val/2)) * xmod; x1 = col*xres; x2 = (col-(step_val/2))*xres; x3 = (col+(step_val/2))*xres; /* Do not need BM_get because GET_MAPATT calls * same and returns zero if masked */ offset2[0] = y1off+datacol1; /* fan center */ pt2[0][X] = x1; pt2[0][Y] = y1; /* fan center */ pt[X]=pt2[0][X]; pt[Y] = pt2[0][Y]; if ( !GET_MAPATT(buff, offset2[0], pt[Z]) ) continue; /* masked */ pt[Z] *= zexag; offset2[1] = y2off+datacol2; offset2[2] = y2off+datacol1; offset2[3] = y2off+datacol3; offset2[4] = y1off+datacol3; offset2[5] = y3off+datacol3; offset2[6] = y3off+datacol1; offset2[7] = y3off+datacol2; offset2[8] = y1off+datacol2; offset2[9] = y2off+datacol2; /* repeat 1st corner to close */ pt2[1][X] = x2; pt2[1][Y] = y2; pt2[2][X] = x1; pt2[2][Y] = y2; pt2[3][X] = x3; pt2[3][Y] = y2; pt2[4][X] = x3; pt2[4][Y] = y1; pt2[5][X] = x3; pt2[5][Y] = y3; pt2[6][X] = x1; pt2[6][Y] = y3; pt2[7][X] = x2; pt2[7][Y] = y3; pt2[8][X] = x2; pt2[8][Y] = y1; pt2[9][X] = x2; pt2[9][Y] = y2; /* repeat 1st corner to close */ /* Run through triangle fan */ gsd_bgntfan(); for (ii = 0; ii < 10; ii++) { if ( ii > 0) { pt[X]=pt2[ii][X]; pt[Y] = pt2[ii][Y]; if ( !GET_MAPATT(buff, offset2[ii], pt[Z]) ) continue; pt[Z] *= zexag; } FNORM(surf->norms[offset2[ii]], n); if (check_color) curcolor = gs_mapcolor(cobuff, coloratt, offset2[ii]); if (check_transp) { GET_MAPATT(trbuff, offset2[ii], ttr); ktrans = (char) SCALE_ATT(tratt, ttr, 0, 255); ktrans = (char) (255 - ktrans) << 24; } if (check_material) { if (check_emis) { GET_MAPATT(embuff, offset2[ii], kem); kem = SCALE_ATT(ematt, kem, 0., 1.); } if (check_shin) { GET_MAPATT(shbuff, offset2[ii], ksh); ksh = SCALE_ATT(shatt, ksh, 0., 1.); } if (pksh != ksh || pkem != kem || (kem && check_color)) { pksh = ksh; pkem = kem; gsd_set_material(check_shin, check_emis, ksh, kem, curcolor); } } gsd_litvert_func(n, ktrans | curcolor, pt); } /* close ii loop */ gsd_endtfan(); } /* end col */ } /* end row */ gsd_popmatrix(); /* gsd_colormode(CM_DIFFUSE); */ gsd_blend(0); gsd_zwritemask(0xffffffff); return (0); }