GRASS Programmer's Manual  6.5.svn(2012)-r51648
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
GS2.c
Go to the documentation of this file.
00001 
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <math.h>
00034 
00035 #include <grass/config.h>
00036 
00037 #if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
00038 #include <GL/gl.h>
00039 #include <GL/glu.h>
00040 #elif defined(OPENGL_AQUA)
00041 #include <OpenGL/gl.h>
00042 #include <OpenGL/glu.h>
00043 #endif
00044 
00045 #include <grass/gis.h>
00046 #include <grass/gstypes.h>
00047 #include <grass/glocale.h>
00048 
00049 #include "gsget.h"
00050 #include "rowcol.h"
00051 #include "rgbpack.h"
00052 
00053 /* Hack to make NVIZ2.2 query functions.("What's Here" and "Look at")
00054  * to work.
00055  * Uses gs_los_intersect1() instead of gs_los_intersect().
00056  * Pierre de Mouveaux - 31 oct. 1999. p_de_mouveaux@hotmail.com.
00057  */
00058 #define NVIZ_HACK 1
00059 
00060 int gsd_getViewport(GLint *, GLint *);
00061 
00062 /* array of surface ids */
00063 static int Surf_ID[MAX_SURFS];
00064 static int Next_surf = 0;
00065 static int SDref_surf = 0;
00066 
00067 /* attributes array */
00068 static float Default_const[MAX_ATTS];
00069 static float Default_nulls[MAX_ATTS];
00070 
00071 /* largest dimension */
00072 static float Longdim;
00073 
00074 /* N, S, W, E */
00075 static float Region[4];
00076 static geoview Gv;
00077 static geodisplay Gd;
00078 static struct Cell_head wind;
00079 static int Buffermode;
00080 static int Numlights = 0;
00081 static int Resetlight = 1;
00082 static int Modelshowing = 0;
00083 
00084 void void_func(void)
00085 {
00086     return;
00087 }
00088 
00096 void GS_libinit(void)
00097 {
00098     static int first = 1;
00099 
00100     G_get_set_window(&wind);
00101 
00102     Region[0] = wind.north;
00103     Region[1] = wind.south;
00104     Region[2] = wind.west;
00105     Region[3] = wind.east;
00106 
00107     /* scale largest dimension to GS_UNIT_SIZE */
00108     if ((wind.east - wind.west) > (wind.north - wind.south)) {
00109         Longdim = (wind.east - wind.west);
00110     }
00111     else {
00112         Longdim = (wind.north - wind.south);
00113     }
00114 
00115     Gv.scale = GS_UNIT_SIZE / Longdim;
00116 
00117     G_debug(1, "GS_libinit(): n=%f s=%f w=%f e=%f scale=%f first=%d",
00118             Region[0], Region[1], Region[2], Region[3], Gv.scale, first);
00119     
00120     Cxl_func = void_func;
00121     Swap_func = void_func;
00122 
00123     
00124     if (first) {
00125         gs_init();
00126     }
00127 
00128     first = 0;
00129 
00130     return;
00131 }
00132 
00140 int GS_get_longdim(float *dim)
00141 {
00142     *dim = Longdim;
00143 
00144     G_debug(3, "GS_get_longdim(): dim=%g", *dim);
00145 
00146     return (1);
00147 }
00148 
00156 int GS_get_region(float *n, float *s, float *w, float *e)
00157 {
00158     *n = Region[0];
00159     *s = Region[1];
00160     *w = Region[2];
00161     *e = Region[3];
00162 
00163     return (1);
00164 }
00165 
00172 void GS_set_att_defaults(float *defs, float *null_defs)
00173 {
00174     int i;
00175 
00176     G_debug(3, "GS_set_att_defaults");
00177 
00178     for (i = 0; i < MAX_ATTS; i++) {
00179         Default_const[i] = defs[i];
00180         Default_nulls[i] = null_defs[i];
00181     }
00182 
00183     return;
00184 }
00185 
00194 int GS_surf_exists(int id)
00195 {
00196     int i, found = 0;
00197 
00198     G_debug(3, "GS_surf_exists(): id=%d", id);
00199 
00200 
00201     if (NULL == gs_get_surf(id)) {
00202         return (0);
00203     }
00204 
00205     for (i = 0; i < Next_surf && !found; i++) {
00206         if (Surf_ID[i] == id) {
00207             found = 1;
00208         }
00209     }
00210 
00211     return (found);
00212 }
00213 
00224 int GS_new_surface(void)
00225 {
00226     geosurf *ns;
00227 
00228     G_debug(3, "GS_new_surface():");
00229 
00230     if (Next_surf < MAX_SURFS) {
00231         ns = gs_get_new_surface();
00232         gs_init_surf(ns, wind.west + wind.ew_res / 2.,
00233                      wind.south + wind.ns_res / 2., wind.rows, wind.cols,
00234                      wind.ew_res, wind.ns_res);
00235         gs_set_defaults(ns, Default_const, Default_nulls);
00236 
00237         /* make default shine current */
00238         gs_set_att_src(ns, ATT_SHINE, CONST_ATT);
00239 
00240         Surf_ID[Next_surf] = ns->gsurf_id;
00241         ++Next_surf;
00242 
00243         G_debug(3, "    id=%d", ns->gsurf_id);
00244 
00245         return (ns->gsurf_id);
00246     }
00247 
00248 
00249 
00250     return (-1);
00251 }
00252 void GS_set_light_reset(int i)
00253 {
00254     Resetlight = i;
00255     if (i)
00256         Numlights = 0;
00257 }
00258 int GS_get_light_reset(void)
00259 {
00260     return Resetlight;
00261 }
00268 int GS_new_light(void)
00269 {
00270     int i;
00271 
00272     if (GS_get_light_reset()) {
00273 
00274         GS_set_light_reset(0);
00275 
00276         for (i = 0; i < MAX_LIGHTS; i++) {
00277             Gv.lights[i].position[X] = Gv.lights[i].position[Y] = 0.0;
00278             Gv.lights[i].position[Z] = 1.0;
00279             Gv.lights[i].position[W] = 0.0;     /* infinite */
00280             Gv.lights[i].color[0] = Gv.lights[i].color[1] =
00281                 Gv.lights[i].color[2] = 1.0;
00282             Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] =
00283                 Gv.lights[i].ambient[2] = 0.2;
00284             Gv.lights[i].shine = 32.0;
00285         }
00286 
00287         gsd_init_lightmodel();
00288     }
00289 
00290     if (Numlights < MAX_LIGHTS) {
00291         gsd_deflight(Numlights + 1, &(Gv.lights[Numlights]));
00292         gsd_switchlight(Numlights + 1, 1);
00293 
00294         return ++Numlights;
00295     }
00296 
00297     return -1;
00298 }
00299 
00309 void GS_setlight_position(int num, float xpos, float ypos, float zpos,
00310                           int local)
00311 {
00312     if (num) {
00313         num -= 1;
00314         if (num < Numlights) {
00315             Gv.lights[num].position[X] = xpos;
00316             Gv.lights[num].position[Y] = ypos;
00317             Gv.lights[num].position[Z] = zpos;
00318             Gv.lights[num].position[W] = (float)local;
00319 
00320             gsd_deflight(num + 1, &(Gv.lights[num]));
00321         }
00322     }
00323 
00324     return;
00325 }
00326 
00327 
00335 void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos,
00336                           int *local)
00337 {
00338     if (num) {
00339         num -= 1;
00340         if (num < Numlights) {
00341             *xpos = Gv.lights[num].position[X];
00342             *ypos = Gv.lights[num].position[Y];
00343             *zpos = Gv.lights[num].position[Z];
00344             *local = (int)Gv.lights[num].position[W];
00345 
00346         }
00347     }
00348 
00349     return;
00350 }
00351 
00358 void GS_setlight_color(int num, float red, float green, float blue)
00359 {
00360     if (num) {
00361         num -= 1;
00362         if (num < Numlights) {
00363             Gv.lights[num].color[0] = red;
00364             Gv.lights[num].color[1] = green;
00365             Gv.lights[num].color[2] = blue;
00366 
00367             gsd_deflight(num + 1, &(Gv.lights[num]));
00368         }
00369     }
00370 
00371     return;
00372 }
00373 
00380 void GS_getlight_color(int num, float *red, float *green, float *blue)
00381 {
00382     if (num) {
00383         num -= 1;
00384         if (num < Numlights) {
00385             *red = Gv.lights[num].color[0];
00386             *green = Gv.lights[num].color[1];
00387             *blue = Gv.lights[num].color[2];
00388         }
00389     }
00390 
00391     return;
00392 }
00393 
00402 void GS_setlight_ambient(int num, float red, float green, float blue)
00403 {
00404     if (num) {
00405         num -= 1;
00406         if (num < Numlights) {
00407             Gv.lights[num].ambient[0] = red;
00408             Gv.lights[num].ambient[1] = green;
00409             Gv.lights[num].ambient[2] = blue;
00410 
00411             gsd_deflight(num + 1, &(Gv.lights[num]));
00412         }
00413     }
00414 
00415     return;
00416 }
00417 
00424 void GS_getlight_ambient(int num, float *red, float *green, float *blue)
00425 {
00426     if (num) {
00427         num -= 1;
00428         if (num < Numlights) {
00429             *red = Gv.lights[num].ambient[0];
00430             *green = Gv.lights[num].ambient[1];
00431             *blue = Gv.lights[num].ambient[2];
00432         }
00433     }
00434 
00435     return;
00436 }
00437 
00438 
00442 void GS_lights_off(void)
00443 {
00444     int i;
00445 
00446     for (i = 0; i < Numlights; i++) {
00447         gsd_switchlight(i + 1, 0);
00448     }
00449 
00450     return;
00451 }
00452 
00456 void GS_lights_on(void)
00457 {
00458     int i;
00459 
00460     for (i = 0; i < Numlights; i++) {
00461         gsd_switchlight(i + 1, 1);
00462     }
00463 
00464     return;
00465 }
00466 
00473 void GS_switchlight(int num, int on)
00474 {
00475     if (num) {
00476         num -= 1;
00477 
00478         if (num < Numlights) {
00479             gsd_switchlight(num + 1, on);
00480         }
00481     }
00482 
00483     return;
00484 }
00485 
00492 int GS_transp_is_set(void)
00493 {
00494     return (gs_att_is_set(NULL, ATT_TRANSP) || (FC_GREY == gsd_getfc()));
00495 }
00496 
00502 void GS_get_modelposition1(float pos[])
00503 {
00504     /* TODO: Still needs work to handle other cases */
00505     /* this is a quick hack to get lighting adjustments debugged */
00506     /*
00507        GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], center);
00508        GS_v3mult(center, 1000);
00509        GS_v3add(center, Gv.from_to[FROM]);
00510      */
00511 
00512     gs_get_datacenter(pos);
00513     gs_get_data_avg_zmax(&(pos[Z]));
00514 
00515     G_debug(1, "GS_get_modelposition1(): model position: %f %f %f",
00516             pos[X], pos[Y], pos[Z]);
00517 
00518     return;
00519 }
00520 
00531 void GS_get_modelposition(float *siz, float *pos)
00532 {
00533     float dist, near_h, dir[3];
00534 
00535     dist = 2. * Gd.nearclip;
00536 
00537     near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
00538     *siz = near_h / 8.0;
00539 
00540     /* prevent clipping - would only happen if fov > ~127 degrees, at
00541        fov = 2.0 * atan(2.0) */
00542 
00543     if (*siz > Gd.nearclip) {
00544         *siz = Gd.nearclip;
00545     }
00546 
00547     GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
00548 
00549     pos[X] = Gv.from_to[FROM][X] + dir[X] * dist;
00550     pos[Y] = Gv.from_to[FROM][Y] + dir[Y] * dist;
00551     pos[Z] = Gv.from_to[FROM][Z] + dir[Z] * dist;
00552 
00553     return;
00554 }
00555 
00556 
00568 void GS_set_Narrow(int *pt, int id, float *pos2)
00569 {
00570     geosurf *gs;
00571     float x, y, z;
00572     GLdouble modelMatrix[16], projMatrix[16];
00573     GLint viewport[4];
00574 
00575     if (GS_get_selected_point_on_surface(pt[X], pt[Y], &id, &x, &y, &z)) {
00576         gs = gs_get_surf(id);
00577         if (gs) {
00578             z = gs->zmax;
00579             pos2[X] = (float)x - gs->ox + gs->x_trans;
00580             pos2[Y] = (float)y - gs->oy + gs->y_trans;
00581             pos2[Z] = (float)z + gs->z_trans;
00582 
00583             return;
00584         }
00585     }
00586     else {
00587         gs = gs_get_surf(id);
00588 
00589         /* Need to get model matrix, etc 
00590          * to run gluUnProject
00591          */
00592         gsd_pushmatrix();
00593         gsd_do_scale(1);
00594         glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
00595         glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
00596         glGetIntegerv(GL_VIEWPORT, viewport);
00597 
00598         if (gs) {
00599             GLdouble out_near[3], out_far[3];
00600             GLdouble factor;
00601             GLdouble out[3];
00602 
00603             z = (float)gs->zmax + gs->z_trans;
00604 
00605             gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 0.,
00606                          modelMatrix, projMatrix, viewport,
00607                          &out_near[X], &out_near[Y], &out_near[Z]);
00608             gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1.,
00609                          modelMatrix, projMatrix, viewport,
00610                          &out_far[X], &out_far[Y], &out_far[Z]);
00611 
00612             glPopMatrix();
00613 
00614             factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
00615 
00616             out[X] = out_near[X] - ((out_near[X] - out_far[X]) * factor);
00617             out[Y] = out_near[Y] - ((out_near[Y] - out_far[Y]) * factor);
00618             out[Z] = z;
00619 
00620             pos2[X] = (float)out[X];
00621             pos2[Y] = (float)out[Y];
00622             pos2[Z] = (float)out[Z];
00623 
00624             return;
00625 
00626         }
00627     }
00628     return;
00629 }
00630 
00637 void GS_draw_X(int id, float *pt)
00638 {
00639     geosurf *gs;
00640     Point3 pos;
00641     float siz;
00642 
00643     if ((gs = gs_get_surf(id))) {
00644         GS_get_longdim(&siz);
00645         siz /= 200.;
00646         pos[X] = pt[X] - gs->ox;
00647         pos[Y] = pt[Y] - gs->oy;
00648         _viewcell_tri_interp(gs, pos);
00649 
00650         gsd_pushmatrix();
00651 
00652         gsd_do_scale(1);
00653         gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
00654         gsd_linewidth(1);
00655 
00656         if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
00657             pos[Z] = gs->att[ATT_TOPO].constant;
00658             gs = NULL;          /* tells gpd_obj to use given Z val */
00659         }
00660 
00661         gpd_obj(gs, Gd.bgcol, siz, ST_GYRO, pos);
00662         gsd_flush();
00663 
00664         gsd_popmatrix();
00665     }
00666 
00667     return;
00668 }
00669 
00676 void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2)
00677 {
00678     float p1[2], p2[2];
00679     geosurf *gs;
00680 
00681     if ((gs = gs_get_surf(id))) {
00682         p1[X] = x1 - gs->ox;
00683         p1[Y] = y1 - gs->oy;
00684         p2[X] = x2 - gs->ox;
00685         p2[Y] = y2 - gs->oy;
00686 
00687         gsd_pushmatrix();
00688 
00689         gsd_do_scale(1);
00690         gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
00691         gsd_linewidth(1);
00692 
00693         gsd_color_func(GS_default_draw_color());
00694         gsd_line_onsurf(gs, p1, p2);
00695 
00696         gsd_popmatrix();
00697         gsd_flush();
00698     }
00699 
00700     return;
00701 }
00702 
00715 int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2,
00716                          float *lasp, int n)
00717 {
00718     float p1[2], p2[2];
00719     geosurf *gs;
00720     int ret = 0;
00721 
00722     if ((gs = gs_get_surf(id))) {
00723         p1[X] = x1 - gs->ox;
00724         p1[Y] = y1 - gs->oy;
00725         p2[X] = x2 - gs->ox;
00726         p2[Y] = y2 - gs->oy;
00727 
00728         gsd_pushmatrix();
00729 
00730         gsd_do_scale(1);
00731         gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
00732         gsd_linewidth(1);
00733         gsd_color_func(GS_default_draw_color());
00734         ret = gsd_nline_onsurf(gs, p1, p2, lasp, n);
00735         gsd_surf2real(gs, lasp);
00736 
00737         gsd_popmatrix();
00738         gsd_flush();
00739     }
00740 
00741     return (ret);
00742 }
00743 
00753 void GS_draw_flowline_at_xy(int id, float x, float y)
00754 {
00755     geosurf *gs;
00756     float nv[3], pdir[2], mult;
00757     float p1[2], p2[2], next[2];
00758     int i = 0;
00759 
00760     if ((gs = gs_get_surf(id))) {
00761         p1[X] = x;
00762         p1[Y] = y;
00763         /* multiply by 1.5 resolutions to ensure a crossing ? */
00764         mult = .1 * (VXRES(gs) > VYRES(gs) ? VXRES(gs) : VYRES(gs));
00765 
00766         GS_coordpair_repeats(p1, p1, 50);
00767 
00768         while (1 == GS_get_norm_at_xy(id, p1[X], p1[Y], nv)) {
00769             if (nv[Z] == 1.0) {
00770                 if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
00771                     break;
00772                 }
00773 
00774                 p2[X] = p1[X] + (pdir[X] * mult);
00775                 p2[Y] = p1[Y] + (pdir[Y] * mult);
00776             }
00777             else {
00778                 /* use previous direction */
00779                 GS_v2norm(nv);
00780                 p2[X] = p1[X] + (nv[X] * mult);
00781                 p2[Y] = p1[Y] + (nv[Y] * mult);
00782                 pdir[X] = nv[X];
00783                 pdir[Y] = nv[Y];
00784             }
00785 
00786             if (i > 2000) {
00787                 break;
00788             }
00789 
00790             if (GS_coordpair_repeats(p1, p2, 0)) {
00791                 break;
00792             }
00793 
00794             /* Think about this: */
00795             /* degenerate line means edge or level edge ? */
00796             /* next is filled with last point drawn */
00797             if (2 > GS_draw_nline_onsurf(id, p1[X], p1[Y],
00798                                          p2[X], p2[Y], next, 3)) {
00799                 break;
00800             }
00801 
00802             p1[X] = next[X];
00803             p1[Y] = next[Y];
00804         }
00805 
00806         G_debug(3, "GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
00807     }
00808 
00809     return;
00810 }
00811 
00820 void GS_draw_fringe(int id, unsigned long clr, float elev, int *where)
00821 {
00822     geosurf *gs;
00823 
00824     G_debug(3, "GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
00825             id, clr, elev, where[0], where[1], where[2], where[3]);
00826     if ((gs = gs_get_surf(id)))
00827         gsd_display_fringe(gs, clr, elev, where);
00828 
00829 }
00830 
00831 
00845 int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags,
00846                    float *range, int *pt)
00847 {
00848     int list_no;
00849 
00850     list_no = gsd_put_legend(name, fontbase, size, flags, range, pt);
00851 
00852     return (list_no);
00853 }
00854 
00863 void GS_draw_list(GLuint list_id)
00864 {
00865     gsd_calllist(list_id);
00866     glFlush();
00867     return;
00868 }
00869 
00876 void GS_draw_all_list(void)
00877 {
00878     gsd_calllists(0);           /* not sure if 0 is right - MN */
00879     glFlush();
00880     return;
00881 }
00882 
00888 void GS_delete_list(GLuint list_id)
00889 {
00890     gsd_deletelist(list_id, 1);
00891 
00892     return;
00893 }
00894 
00898 void GS_draw_lighting_model1(void)
00899 {
00900     static float center[3];
00901     float tcenter[3];
00902 
00903     if (!Modelshowing) {
00904         GS_get_modelposition1(center);
00905     }
00906 
00907     GS_v3eq(tcenter, center);
00908 
00909     gsd_zwritemask(0x0);
00910     gsd_backface(1);
00911 
00912     gsd_colormode(CM_AD);
00913     gsd_shademodel(DM_GOURAUD);
00914     gsd_pushmatrix();
00915     gsd_do_scale(1);
00916 
00917     if (Gv.vert_exag) {
00918         tcenter[Z] *= Gv.vert_exag;
00919         gsd_scale(1.0, 1.0, 1. / Gv.vert_exag);
00920     }
00921 
00922     gsd_drawsphere(tcenter, 0xDDDDDD, (float)(Longdim / 10.));
00923     gsd_popmatrix();
00924     Modelshowing = 1;
00925 
00926     gsd_backface(0);
00927     gsd_zwritemask(0xffffffff);
00928 
00929     return;
00930 }
00931 
00938 void GS_draw_lighting_model(void)
00939 {
00940     static float center[3], size;
00941     float tcenter[3], tsize;
00942     int i, wason[MAX_CPLANES];
00943 
00944     gsd_get_cplanes_state(wason);
00945 
00946     for (i = 0; i < MAX_CPLANES; i++) {
00947         if (wason[i]) {
00948             gsd_cplane_off(i);
00949         }
00950     }
00951 
00952 
00953     if (!Modelshowing) {
00954         GS_get_modelposition(&size, center);
00955     }
00956 
00957     GS_v3eq(tcenter, center);
00958     tsize = size;
00959 
00960     gsd_zwritemask(0x0);
00961     gsd_backface(1);
00962 
00963     gsd_colormode(CM_DIFFUSE);
00964     gsd_shademodel(DM_GOURAUD);
00965     gsd_pushmatrix();
00966     gsd_drawsphere(tcenter, 0xDDDDDD, tsize);
00967     gsd_popmatrix();
00968     Modelshowing = 1;
00969 
00970     gsd_backface(0);
00971     gsd_zwritemask(0xffffffff);
00972 
00973     for (i = 0; i < MAX_CPLANES; i++) {
00974         if (wason[i]) {
00975             gsd_cplane_on(i);
00976         }
00977     }
00978 
00979     gsd_flush();
00980 
00981     return;
00982 }
00983 
00994 int GS_update_curmask(int id)
00995 {
00996     geosurf *gs;
00997 
00998     gs = gs_get_surf(id);
00999     return (gs_update_curmask(gs));
01000 }
01001 
01012 int GS_is_masked(int id, float *pt)
01013 {
01014     geosurf *gs;
01015     Point3 tmp;
01016 
01017     if ((gs = gs_get_surf(id))) {
01018         tmp[X] = pt[X] - gs->ox;
01019         tmp[Y] = pt[Y] - gs->oy;
01020 
01021         return (gs_point_is_masked(gs, tmp));
01022     }
01023 
01024     return (-1);
01025 }
01026 
01030 void GS_unset_SDsurf(void)
01031 {
01032     gsdiff_set_SDref(NULL);
01033     SDref_surf = 0;
01034 
01035     return;
01036 }
01037 
01046 int GS_set_SDsurf(int id)
01047 {
01048     geosurf *gs;
01049 
01050     if ((gs = gs_get_surf(id))) {
01051         gsdiff_set_SDref(gs);
01052         SDref_surf = id;
01053 
01054         return (1);
01055     }
01056 
01057     return (0);
01058 }
01059 
01067 int GS_set_SDscale(float scale)
01068 {
01069     gsdiff_set_SDscale(scale);
01070 
01071     return (1);
01072 }
01073 
01082 int GS_get_SDsurf(int *id)
01083 {
01084     geosurf *gs;
01085 
01086     if ((gs = gsdiff_get_SDref())) {
01087         *id = SDref_surf;
01088 
01089         return (1);
01090     }
01091 
01092     return (0);
01093 }
01094 
01102 int GS_get_SDscale(float *scale)
01103 {
01104     *scale = gsdiff_get_SDscale();
01105 
01106     return (1);
01107 }
01108 
01116 int GS_update_normals(int id)
01117 {
01118     geosurf *gs;
01119 
01120     gs = gs_get_surf(id);
01121 
01122     return (gs_calc_normals(gs));
01123 }
01124 
01137 int GS_get_att(int id, int att, int *set, float *constant, char *mapname)
01138 {
01139     int src;
01140     geosurf *gs;
01141 
01142     gs = gs_get_surf(id);
01143     if (gs) {
01144         if (-1 != (src = gs_get_att_src(gs, att))) {
01145             *set = src;
01146 
01147             if (src == CONST_ATT) {
01148                 *constant = gs->att[att].constant;
01149             }
01150             else if (src == MAP_ATT) {
01151                 strcpy(mapname, gsds_get_name(gs->att[att].hdata));
01152             }
01153 
01154             return (1);
01155         }
01156 
01157         return (-1);
01158     }
01159 
01160     return (-1);
01161 }
01162 
01180 int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y)
01181 {
01182     int offset, drow, dcol, vrow, vcol;
01183     float ftmp, pt[3];
01184     typbuff *buff;
01185     geosurf *gs;
01186 
01187     *catstr = '\0';
01188     gs = gs_get_surf(id);
01189 
01190     if (NULL == gs) {
01191         return -1;
01192     }
01193 
01194     pt[X] = x;
01195     pt[Y] = y;
01196 
01197     gsd_real2surf(gs, pt);
01198     if (gs_point_is_masked(gs, pt)) {
01199         return -1;
01200     }
01201 
01202     if (!in_vregion(gs, pt)) {
01203         return -1;
01204     }
01205 
01206     if (MAP_ATT != gs_get_att_src(gs, att)) {
01207         sprintf(catstr, _("no category info"));
01208         return -1;
01209     }
01210 
01211     buff = gs_get_att_typbuff(gs, att, 0);
01212 
01213     vrow = Y2VROW(gs, pt[Y]);
01214     vcol = X2VCOL(gs, pt[X]);
01215     drow = VROW2DROW(gs, vrow);
01216     dcol = VCOL2DCOL(gs, vcol);
01217 
01218     offset = DRC2OFF(gs, drow, dcol);
01219     
01220     if (GET_MAPATT(buff, offset, ftmp)) {
01221         return
01222             (Gs_get_cat_label(gsds_get_name(gs->att[att].hdata),
01223                               drow, dcol, catstr));
01224     }
01225 
01226     sprintf(catstr, _("no data"));
01227 
01228     return 1;
01229 }
01230 
01243 int GS_get_norm_at_xy(int id, float x, float y, float *nv)
01244 {
01245     int offset, drow, dcol, vrow, vcol;
01246     float pt[3];
01247     geosurf *gs;
01248 
01249     gs = gs_get_surf(id);
01250 
01251     if (NULL == gs) {
01252         return (-1);
01253     }
01254 
01255     if (gs->norm_needupdate) {
01256         gs_calc_normals(gs);
01257     }
01258 
01259     pt[X] = x;
01260     pt[Y] = y;
01261 
01262     gsd_real2surf(gs, pt);
01263     if (gs_point_is_masked(gs, pt)) {
01264         return (-1);
01265     }
01266 
01267     if (!in_vregion(gs, pt)) {
01268         return (-1);
01269     }
01270 
01271     vrow = Y2VROW(gs, pt[Y]);
01272     vcol = X2VCOL(gs, pt[X]);
01273     drow = VROW2DROW(gs, vrow);
01274     dcol = VCOL2DCOL(gs, vcol);
01275 
01276     offset = DRC2OFF(gs, drow, dcol);
01277 
01278     if (gs->norms) {
01279         FNORM(gs->norms[offset], nv);
01280     }
01281     else {
01282         /* otherwise must be a constant */
01283         nv[0] = 0.0;
01284         nv[1] = 0.0;
01285         nv[2] = 1.0;
01286     }
01287 
01288     return (1);
01289 }
01290 
01307 int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y)
01308 {
01309     int offset, drow, dcol, vrow, vcol;
01310     float ftmp, pt[3];
01311     typbuff *buff;
01312     geosurf *gs;
01313 
01314     *valstr = '\0';
01315     gs = gs_get_surf(id);
01316     
01317     if (NULL == gs) {
01318         return -1;
01319     }
01320 
01321     pt[X] = x;
01322     pt[Y] = y;
01323 
01324     gsd_real2surf(gs, pt);
01325 
01326     if (gs_point_is_masked(gs, pt)) {
01327         return -1;
01328     }
01329 
01330     if (!in_vregion(gs, pt)) {
01331         return (-1);
01332     }
01333 
01334     if (CONST_ATT == gs_get_att_src(gs, att)) {
01335         if (att == ATT_COLOR) {
01336             int r, g, b, i;
01337 
01338             i = gs->att[att].constant;
01339             sprintf(valstr, "R%d G%d B%d",
01340                     INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
01341         }
01342         else {
01343             sprintf(valstr, "%f", gs->att[att].constant);
01344         }
01345 
01346         return 1;
01347     }
01348     else if (MAP_ATT != gs_get_att_src(gs, att)) {
01349         return -1;
01350     }
01351 
01352     buff = gs_get_att_typbuff(gs, att, 0);
01353 
01354     vrow = Y2VROW(gs, pt[Y]);
01355     vcol = X2VCOL(gs, pt[X]);
01356     drow = VROW2DROW(gs, vrow);
01357     dcol = VCOL2DCOL(gs, vcol);
01358 
01359     offset = DRC2OFF(gs, drow, dcol);
01360 
01361     if (GET_MAPATT(buff, offset, ftmp)) {
01362         if (att == ATT_COLOR) {
01363             int r, g, b, i;
01364 
01365             i = gs_mapcolor(gs_get_att_typbuff(gs, ATT_COLOR, 0),
01366                             &(gs->att[ATT_COLOR]), offset);
01367             sprintf(valstr, "R%d G%d B%d",
01368                     INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
01369         }
01370         else {
01371             sprintf(valstr, "%f", ftmp);
01372         }
01373 
01374         return (1);
01375     }
01376 
01377     sprintf(valstr, "NULL");
01378 
01379     return (1);
01380 }
01381 
01390 int GS_unset_att(int id, int att)
01391 {
01392     geosurf *gs;
01393 
01394     gs = gs_get_surf(id);
01395     gs->mask_needupdate = 1;
01396 
01397     return (gs_set_att_src(gs, att, NOTSET_ATT));
01398 }
01399 
01409 int GS_set_att_const(int id, int att, float constant)
01410 {
01411     geosurf *gs;
01412     int ret;
01413 
01414     gs = gs_get_surf(id);
01415     ret = (gs_set_att_const(gs, att, constant));
01416 
01417     Gs_update_attrange(gs, att);
01418 
01419     return (ret);
01420 }
01421 
01433 int GS_set_maskmode(int id, int mode)
01434 {
01435     geosurf *gs;
01436 
01437     gs = gs_get_surf(id);
01438 
01439     if (gs) {
01440         gs->att[ATT_MASK].constant = mode;
01441         gs->mask_needupdate = 1;
01442 
01443         return (mode);
01444     }
01445 
01446     return (-1);
01447 }
01448 
01458 int GS_get_maskmode(int id, int *mode)
01459 {
01460     geosurf *gs;
01461 
01462     gs = gs_get_surf(id);
01463 
01464     if (gs) {
01465         *mode = gs->att[ATT_MASK].constant;
01466 
01467         return (1);
01468     }
01469 
01470     return (-1);
01471 }
01472 
01482 int GS_Set_ClientData(int id, void *clientd)
01483 {
01484     geosurf *gs;
01485 
01486     gs = gs_get_surf(id);
01487     if (gs) {
01488         gs->clientdata = clientd;
01489 
01490         return (1);
01491     }
01492 
01493     return (-1);
01494 }
01495 
01504 void *GS_Get_ClientData(int id)
01505 {
01506     geosurf *gs;
01507 
01508     gs = gs_get_surf(id);
01509     if (gs) {
01510         return (gs->clientdata);
01511     }
01512 
01513     return (NULL);
01514 }
01515 
01521 int GS_num_surfs(void)
01522 {
01523     return (gs_num_surfaces());
01524 }
01525 
01536 int *GS_get_surf_list(int *numsurfs)
01537 {
01538     int i, *ret;
01539 
01540     *numsurfs = Next_surf;
01541 
01542     if (Next_surf) {
01543         ret = (int *)G_malloc(Next_surf * sizeof(int));
01544 
01545         for (i = 0; i < Next_surf; i++) {
01546             ret[i] = Surf_ID[i];
01547         }
01548 
01549         return (ret);
01550     }
01551 
01552     return (NULL);
01553 }
01554 
01563 int GS_delete_surface(int id)
01564 {
01565     int i, j, found;
01566     
01567     found = FALSE;
01568     
01569     G_debug(1, "GS_delete_surface(): id=%d", id);
01570     
01571     if (GS_surf_exists(id)) {
01572         gs_delete_surf(id);
01573         for (i = 0; i < Next_surf && !found; i++) {
01574             if (Surf_ID[i] == id) {
01575                 found = TRUE;
01576 
01577                 for (j = i; j < Next_surf; j++) {
01578                     Surf_ID[j] = Surf_ID[j + 1];
01579                 }
01580             }
01581         }
01582         
01583         gv_update_drapesurfs();
01584 
01585         if (found) {
01586             --Next_surf;
01587             return 1;
01588         }
01589     }
01590 
01591     return -1;
01592 }
01593 
01594 
01605 int GS_load_att_map(int id, const char *filename, int att)
01606 {
01607     geosurf *gs;
01608     unsigned int changed;
01609     unsigned int atty;
01610     const char *mapset;
01611     struct Cell_head rast_head;
01612     int reuse, begin, hdata, ret, neg, has_null;
01613     typbuff *tbuff;
01614 
01615     G_debug(3, "GS_load_att_map(): map=%s", filename);
01616 
01617     reuse = ret = neg = has_null = 0;
01618     gs = gs_get_surf(id);
01619 
01620     if (NULL == gs) {
01621         return -1;
01622     }
01623 
01624     gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
01625                            (gs->nz_topo && ATT_TOPO == att) ||
01626                            (gs->nz_color && ATT_COLOR == att));
01627 
01628     gs_set_att_src(gs, att, MAP_ATT);
01629 
01630     /* Check against maps already loaded in memory   */
01631     /* if to be color attribute:
01632        - if packed color for another surface, OK to reuse
01633        - if unchanged, ok to reuse IF it's of type char (will have lookup)
01634      */
01635     begin = hdata = 1;
01636 
01637     /* Get MAPSET to ensure names are fully qualified */
01638     mapset = G_find_cell2(filename, "");
01639     if (mapset == NULL) {
01640         /* Check for valid filename */
01641         G_warning("Raster map <%s> not found", filename);
01642         return -1;
01643     }
01644     
01645     /* Check to see if map is in Region */
01646     G_get_cellhd(filename, mapset, &rast_head);
01647     if (rast_head.north <= wind.south ||
01648         rast_head.south >= wind.north ||
01649         rast_head.east <= wind.west || rast_head.west >= wind.east) {
01650 
01651         G_warning(_("Raster map <%s> is outside of current region. Load failed."),
01652                   G_fully_qualified_name(filename, mapset));
01653     }
01654 
01655     while (!reuse && (0 < hdata)) {
01656         changed = CF_COLOR_PACKED;
01657         atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
01658 
01659         if (0 < (hdata = gsds_findh(filename, &changed, &atty, begin))) {
01660 
01661             G_debug(3, "GS_load_att_map(): %s already has data handle %d.CF=%x",
01662                     filename, hdata, changed);
01663 
01664             /* handle found */
01665             if (ATT_COLOR == att) {
01666                 if ((changed == CF_COLOR_PACKED) ||
01667                     (!changed && atty == ATTY_CHAR)) {
01668                     reuse = 1;
01669                 }
01670             }
01671             else if (atty == ATTY_MASK && att != ATT_MASK) {
01672                 reuse = 0;
01673                 /* should also free mask data & share new - but need backward
01674                    reference? */
01675             }
01676             else if (!changed) {
01677                 reuse = 1;
01678             }
01679         }
01680 
01681         begin = 0;
01682     }
01683 
01684     if (reuse) {
01685         gs->att[att].hdata = hdata;
01686         gs_set_att_type(gs, att, atty); /* ?? */
01687 
01688         /* free lookup  & set to NULL! */
01689         if (atty == ATTY_INT) {
01690             if (gs->att[att].lookup) {
01691                 free(gs->att[att].lookup);
01692                 gs->att[att].lookup = NULL;
01693             }
01694         }
01695         /* TODO: FIX THIS stuff with lookup sharing! */
01696 
01697         G_debug(3, "GS_load_att_map(): %s is being reused. hdata=%d",
01698                 filename, hdata);
01699     }
01700     else {
01701         G_debug(3, "GS_load_att_map(): %s not loaded in correct form - loading now",
01702                 filename);
01703 
01704         /* not loaded - need to get new dataset handle */
01705         gs->att[att].hdata = gsds_newh(filename);
01706 
01707         tbuff = gs_get_att_typbuff(gs, att, 1);
01708 
01709         /* TODO: Provide mechanism for loading certain attributes at
01710            specified sizes, allow to scale or cap, or scale non-zero */
01711         if (ATT_MASK == att) {
01712             atty = ATTY_MASK;
01713         }
01714         else {
01715             atty = Gs_numtype(filename, &neg);
01716         }
01717 
01718 #ifdef MAYBE_LATER
01719         if (att == ATT_COLOR && atty == ATTY_SHORT) {
01720             atty = (neg ? ATTY_INT : ATTY_SHORT);
01721         }
01722 #endif
01723 
01724         if (att == ATT_COLOR && atty == ATTY_SHORT) {
01725             atty = ATTY_INT;
01726         }
01727 
01728         if (0 > gs_malloc_att_buff(gs, att, ATTY_NULL)) {
01729             G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01730         }
01731 
01732         switch (atty) {
01733         case ATTY_MASK:
01734             if (0 > gs_malloc_att_buff(gs, att, ATTY_MASK)) {
01735                 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01736             }
01737 
01738             ret = Gs_loadmap_as_bitmap(&wind, filename, tbuff->bm);
01739             
01740             break;
01741         case ATTY_CHAR:
01742             if (0 > gs_malloc_att_buff(gs, att, ATTY_CHAR)) {
01743                 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01744             }
01745 
01746             ret = Gs_loadmap_as_char(&wind, filename, tbuff->cb,
01747                                      tbuff->nm, &has_null);
01748 
01749             break;
01750         case ATTY_SHORT:
01751             if (0 > gs_malloc_att_buff(gs, att, ATTY_SHORT)) {
01752                 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01753             }
01754 
01755             ret = Gs_loadmap_as_short(&wind, filename, tbuff->sb,
01756                                       tbuff->nm, &has_null);
01757             break;
01758         case ATTY_FLOAT:
01759             if (0 > gs_malloc_att_buff(gs, att, ATTY_FLOAT)) {
01760                 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01761             }
01762 
01763             ret = Gs_loadmap_as_float(&wind, filename, tbuff->fb,
01764                                       tbuff->nm, &has_null);
01765 
01766             break;
01767         case ATTY_INT:
01768         default:
01769             if (0 > gs_malloc_att_buff(gs, att, ATTY_INT)) {
01770                 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01771             }
01772 
01773             ret = Gs_loadmap_as_int(&wind, filename, tbuff->ib,
01774                                     tbuff->nm, &has_null);
01775             break;
01776 
01777         }                       /* Done with switch */
01778 
01779         if (ret == -1) {
01780             gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
01781             return -1;
01782         }
01783 
01784         G_debug(4, "  has_null=%d", has_null);
01785 
01786         if (!has_null) {
01787             gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
01788         }
01789         else {
01790             gs_update_curmask(gs);
01791         }
01792 
01793     }                           /* end if not reuse */
01794 
01795     if (ATT_COLOR == att) {
01796 #ifdef MAYBE_LATER
01797         if (ATTY_INT == atty) {
01798             Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
01799             gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
01800             gs->att[att].lookup = NULL;
01801         }
01802         else {
01803             gs_malloc_lookup(gs, att);
01804             Gs_build_lookup(filename, gs->att[att].lookup);
01805         }
01806 #else
01807 
01808         if (ATTY_CHAR == atty) {
01809             if (!gs->att[att].lookup) {
01810                 /* might already exist if reusing */
01811                 gs_malloc_lookup(gs, att);
01812                 Gs_build_256lookup(filename, gs->att[att].lookup);
01813             }
01814         }
01815         else if (ATTY_FLOAT == atty) {
01816             if (!reuse) {
01817                 if (0 > gs_malloc_att_buff(gs, att, ATTY_INT)) {
01818                     G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
01819                 }
01820 
01821                 Gs_pack_colors_float(filename, tbuff->fb, tbuff->ib,
01822                                      gs->rows, gs->cols);
01823                 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
01824                 gsds_free_data_buff(gs->att[att].hdata, ATTY_FLOAT);
01825                 gs->att[att].lookup = NULL;
01826             }
01827         }
01828         else {
01829             if (!reuse) {
01830                 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
01831                 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
01832                 gs->att[att].lookup = NULL;
01833             }
01834         }
01835 #endif
01836     }
01837 
01838     if (ATT_TOPO == att) {
01839         gs_init_normbuff(gs);
01840         /* S_DIFF: should also check here to see if this surface is a
01841            reference surface for scaled differences, if so update references
01842            to it */
01843     }
01844 
01845     if (ret < 0) {
01846         G_warning(_("Loading failed"));
01847     }
01848 
01849     if (-1 == Gs_update_attrange(gs, att)) {
01850         G_warning(_("Error finding range"));
01851     }
01852 
01853     return ret;
01854 }
01855 
01861 void GS_draw_surf(int id)
01862 {
01863     geosurf *gs;
01864 
01865     G_debug(3, "GS_draw_surf(): id=%d", id);
01866 
01867     gs = gs_get_surf(id);
01868     if (gs) {
01869         gsd_shademodel(gs->draw_mode & DM_GOURAUD);
01870 
01871         if (gs->draw_mode & DM_POLY) {
01872             gsd_surf(gs);
01873         }
01874 
01875         if (gs->draw_mode & DM_WIRE) {
01876             gsd_wire_surf(gs);
01877         }
01878 
01879         /* TODO: write wire/poly draw routines */
01880         if (gs->draw_mode & DM_WIRE_POLY) {
01881             gsd_surf(gs);
01882             gsd_wire_surf(gs);
01883         }
01884     }
01885 
01886     return;
01887 }
01888 
01896 void GS_draw_wire(int id)
01897 {
01898     geosurf *gs;
01899 
01900     G_debug(3, "GS_draw_wire(): id=%d", id);
01901 
01902     gs = gs_get_surf(id);
01903 
01904     if (gs) {
01905         gsd_wire_surf(gs);
01906     }
01907 
01908     return;
01909 }
01910 
01916 void GS_alldraw_wire(void)
01917 {
01918     geosurf *gs;
01919     int i;
01920 
01921     for (i = 0; i < Next_surf; i++) {
01922         if ((gs = gs_get_surf(Surf_ID[i]))) {
01923             gsd_wire_surf(gs);
01924         }
01925     }
01926 
01927     return;
01928 }
01929 
01933 void GS_alldraw_surf(void)
01934 {
01935     int i;
01936 
01937     for (i = 0; i < Next_surf; i++) {
01938         GS_draw_surf(Surf_ID[i]);
01939     }
01940 
01941     return;
01942 }
01943 
01950 void GS_set_exag(int id, float exag)
01951 {
01952     geosurf *gs;
01953 
01954     G_debug(3, "GS_set_exag");
01955 
01956     gs = gs_get_surf(id);
01957 
01958     if (gs) {
01959         if (gs->z_exag != exag) {
01960             gs->norm_needupdate = 1;
01961         }
01962 
01963         gs->z_exag = exag;
01964     }
01965 
01966     return;
01967 }
01968 
01974 void GS_set_global_exag(float exag)
01975 {
01976 
01977     G_debug(3, "GS_set_global_exag");
01978 
01979     Gv.vert_exag = exag;
01980     /* GL_NORMALIZE */
01981     /* Only need to update norms gs_norms.c
01982      * if exag is used in norm equation which
01983      * it is not! If GL_NORMALIZE is disabled
01984      * will need to include.
01985      gs_setall_norm_needupdate();
01986      */
01987 
01988     return;
01989 }
01990 
01996 float GS_global_exag(void)
01997 {
01998     G_debug(3, "GS_global_exag(): %g", Gv.vert_exag);
01999 
02000     return (Gv.vert_exag);
02001 }
02002 
02011 void GS_set_wire_color(int id, int colr)
02012 {
02013     geosurf *gs;
02014 
02015     G_debug(3, "GS_set_wire_color");
02016 
02017     gs = gs_get_surf(id);
02018 
02019     if (gs) {
02020         gs->wire_color = colr;
02021     }
02022 
02023     return;
02024 }
02025 
02035 int GS_get_wire_color(int id, int *colr)
02036 {
02037     geosurf *gs;
02038 
02039     gs = gs_get_surf(id);
02040 
02041     if (gs) {
02042         *colr = gs->wire_color;
02043 
02044         return (1);
02045     }
02046 
02047     return (-1);
02048 }
02049 
02058 int GS_setall_drawmode(int mode)
02059 {
02060     int i;
02061 
02062     for (i = 0; i < Next_surf; i++) {
02063         if (0 != GS_set_drawmode(Surf_ID[i], mode)) {
02064             return (-1);
02065         }
02066     }
02067 
02068     return (0);
02069 }
02070 
02080 int GS_set_drawmode(int id, int mode)
02081 {
02082     geosurf *gs;
02083 
02084     G_debug(3, "GS_set_drawmode(): id=%d mode=%d", id, mode);
02085 
02086     gs = gs_get_surf(id);
02087 
02088     if (gs) {
02089         gs->draw_mode = mode;
02090 
02091         return (0);
02092     }
02093 
02094     return (-1);
02095 }
02096 
02106 int GS_get_drawmode(int id, int *mode)
02107 {
02108     geosurf *gs;
02109 
02110     gs = gs_get_surf(id);
02111 
02112     if (gs) {
02113         *mode = gs->draw_mode;
02114 
02115         return (1);
02116     }
02117 
02118     return (-1);
02119 }
02120 
02128 void GS_set_nozero(int id, int att, int mode)
02129 {
02130     geosurf *gs;
02131 
02132     G_debug(3, "GS_set_nozero");
02133 
02134     gs = gs_get_surf(id);
02135 
02136     if (gs) {
02137         if (att == ATT_TOPO) {
02138             gs->nz_topo = mode;
02139             gs->mask_needupdate = 1;
02140         }
02141 
02142         if (att == ATT_COLOR) {
02143             gs->nz_color = mode;
02144             gs->mask_needupdate = 1;
02145         }
02146     }
02147 
02148     return;
02149 }
02150 
02161 int GS_get_nozero(int id, int att, int *mode)
02162 {
02163     geosurf *gs;
02164 
02165     G_debug(3, "GS_set_nozero");
02166 
02167     gs = gs_get_surf(id);
02168 
02169     if (gs) {
02170         if (att == ATT_TOPO) {
02171             *mode = gs->nz_topo;
02172         }
02173         else if (att == ATT_COLOR) {
02174             *mode = gs->nz_color;
02175         }
02176         else {
02177             return (-1);
02178         }
02179 
02180         return (1);
02181     }
02182 
02183     return (-1);
02184 }
02185 
02195 int GS_setall_drawres(int xres, int yres, int xwire, int ywire)
02196 {
02197     int i;
02198 
02199     for (i = 0; i < Next_surf; i++) {
02200         if (0 != GS_set_drawres(Surf_ID[i], xres, yres, xwire, ywire)) {
02201             return (-1);
02202         }
02203     }
02204 
02205     return (0);
02206 }
02207 
02218 int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire)
02219 {
02220     geosurf *gs;
02221 
02222     G_debug(3, "GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
02223             id, xres, yres, xwire, ywire);
02224 
02225     if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
02226         return (-1);
02227     }
02228 
02229     gs = gs_get_surf(id);
02230 
02231     if (gs) {
02232         if (gs->x_mod != xres || gs->y_mod != yres) {
02233             gs->norm_needupdate = 1;
02234         }
02235 
02236         gs->x_mod = xres;
02237         gs->y_mod = yres;
02238         gs->x_modw = xwire;
02239         gs->y_modw = ywire;
02240     }
02241 
02242     return (0);
02243 }
02244 
02252 void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire)
02253 {
02254     geosurf *gs;
02255 
02256     G_debug(3, "GS_get_drawres");
02257 
02258     gs = gs_get_surf(id);
02259 
02260     if (gs) {
02261         *xres = gs->x_mod;
02262         *yres = gs->y_mod;
02263         *xwire = gs->x_modw;
02264         *ywire = gs->y_modw;
02265     }
02266 
02267     return;
02268 }
02269 
02276 void GS_get_dims(int id, int *rows, int *cols)
02277 {
02278     geosurf *gs;
02279 
02280     gs = gs_get_surf(id);
02281 
02282     if (gs) {
02283         *rows = gs->rows;
02284         *cols = gs->cols;
02285     }
02286 
02287     return;
02288 }
02289 
02303 int GS_get_exag_guess(int id, float *exag)
02304 {
02305     geosurf *gs;
02306     float guess;
02307 
02308     gs = gs_get_surf(id);
02309     guess = 1.0;
02310 
02311     /* if gs is type const return guess = 1.0 */
02312     if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
02313         return (1);
02314     }
02315 
02316     if (gs) {
02317         if (gs->zrange_nz == 0.0) {
02318             *exag = 0.0;
02319 
02320             return (1);
02321         }
02322 
02323         G_debug(3, "GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
02324 
02325         while (gs->zrange_nz * guess / Longdim >= .25) {
02326             guess *= .1;
02327 
02328             G_debug(3, "GS_get_exag_guess(): %f", guess);
02329         }
02330 
02331         while (gs->zrange_nz * guess / Longdim < .025) {
02332             guess *= 10.;
02333 
02334             G_debug(3, "GS_get_exag_guess(): %f", guess);
02335         }
02336 
02337         *exag = guess;
02338 
02339         return (1);
02340     }
02341 
02342     return (-1);
02343 }
02344 
02353 void GS_get_zrange_nz(float *min, float *max)
02354 {
02355     int i, first = 1;
02356     geosurf *gs;
02357 
02358     for (i = 0; i < Next_surf; i++) {
02359         if ((gs = gs_get_surf(Surf_ID[i]))) {
02360             if (first) {
02361                 first = 0;
02362                 *min = gs->zmin_nz;
02363                 *max = gs->zmax_nz;
02364             }
02365 
02366             if (gs->zmin_nz < *min) {
02367                 *min = gs->zmin_nz;
02368             }
02369 
02370             if (gs->zmax_nz > *max) {
02371                 *max = gs->zmax_nz;
02372             }
02373         }
02374     }
02375 
02376     G_debug(3, "GS_get_zrange_nz(): min=%g max=%g", *min, *max);
02377 
02378     return;
02379 }
02380 
02387 void GS_set_trans(int id, float xtrans, float ytrans, float ztrans)
02388 {
02389     geosurf *gs;
02390 
02391     G_debug(3, "GS_set_trans");
02392 
02393     gs = gs_get_surf(id);
02394 
02395     if (gs) {
02396         gs->x_trans = xtrans;
02397         gs->y_trans = ytrans;
02398         gs->z_trans = ztrans;
02399     }
02400 
02401     return;
02402 }
02403 
02410 void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
02411 {
02412     geosurf *gs;
02413 
02414     G_debug(3, "GS_get_trans");
02415 
02416     gs = gs_get_surf(id);
02417 
02418     if (gs) {
02419         *xtrans = gs->x_trans;
02420         *ytrans = gs->y_trans;
02421         *ztrans = gs->z_trans;
02422     }
02423 
02424     return;
02425 }
02426 
02427 
02433 unsigned int GS_default_draw_color(void)
02434 {
02435 
02436     G_debug(3, "GS_default_draw_color");
02437 
02438     return ((unsigned int)Gd.bgcol);
02439 }
02440 
02446 unsigned int GS_background_color(void)
02447 {
02448     return ((unsigned int)Gd.bgcol);
02449 }
02450 
02456 void GS_set_draw(int where)
02457 {
02458     Buffermode = where;
02459 
02460     switch (where) {
02461     case GSD_BOTH:
02462         gsd_frontbuffer(1);
02463         gsd_backbuffer(1);
02464 
02465         break;
02466     case GSD_FRONT:
02467         gsd_frontbuffer(1);
02468         gsd_backbuffer(0);
02469 
02470         break;
02471     case GSD_BACK:
02472     default:
02473         gsd_frontbuffer(0);
02474         gsd_backbuffer(1);
02475 
02476         break;
02477     }
02478 
02479     return;
02480 }
02481 
02482 /*
02483    \brief Ready to draw
02484  */
02485 void GS_ready_draw(void)
02486 {
02487 
02488     G_debug(3, "GS_ready_draw");
02489 
02490     gsd_set_view(&Gv, &Gd);
02491 
02492     return;
02493 }
02494 
02498 void GS_done_draw(void)
02499 {
02500 
02501     G_debug(3, "GS_done_draw");
02502 
02503     if (GSD_BACK == Buffermode) {
02504         gsd_swapbuffers();
02505     }
02506 
02507     gsd_flush();
02508 
02509     return;
02510 }
02511 
02517 void GS_set_focus(float *realto)
02518 {
02519 
02520     G_debug(3, "GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
02521 
02522     Gv.infocus = 1;
02523     GS_v3eq(Gv.real_to, realto);
02524 
02525     gsd_set_view(&Gv, &Gd);
02526 
02527     return;
02528 }
02529 
02535 void GS_set_focus_real(float *realto)
02536 {
02537 
02538     G_get_set_window(&wind);
02539     realto[X] = realto[X] - wind.west - (wind.ew_res / 2.);
02540     realto[Y] = realto[Y] - wind.south - (wind.ns_res / 2.);
02541 
02542     Gv.infocus = 1;
02543     GS_v3eq(Gv.real_to, realto);
02544 
02545     gsd_set_view(&Gv, &Gd);
02546 
02547     return;
02548 }
02549 
02550 
02560 int GS_get_focus(float *realto)
02561 {
02562 
02563     G_debug(3, "GS_get_focus");
02564 
02565     if (Gv.infocus) {
02566         if (realto) {
02567             GS_v3eq(realto, Gv.real_to);
02568         }
02569     }
02570 
02571     return (Gv.infocus);
02572 }
02573 
02579 void GS_set_focus_center_map(int id)
02580 {
02581     float center[3];
02582     geosurf *gs;
02583 
02584     G_debug(3, "GS_set_focus_center_map");
02585 
02586     gs = gs_get_surf(id);
02587 
02588     if (gs) {
02589         center[X] = (gs->xmax - gs->xmin) / 2.;
02590         center[Y] = (gs->ymax - gs->ymin) / 2.;
02591         center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
02592 
02593         /* not yet working
02594            buff = gs_get_att_typbuff(gs, ATT_TOPO, 0);
02595            offset = gs->rows*gs->cols/2 + gs->cols/2;
02596            if (buff)
02597            {
02598            if (GET_MAPATT(buff, offset, tmp))
02599            {
02600            center[Z] = tmp;
02601            }
02602            }
02603          */
02604 
02605         GS_set_focus(center);
02606     }
02607 }
02608 
02614 void GS_moveto(float *pt)
02615 {
02616     float ft[3];
02617 
02618     G_debug(3, "GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
02619 
02620     if (Gv.infocus) {
02621         GS_v3eq(Gv.from_to[FROM], pt);
02622         /*
02623            GS_v3eq(Gv.from_to[TO], Gv.real_to);
02624          */
02625         GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
02626         /* update inclination, look_dir if we're keeping these */
02627     }
02628     else {
02629         GS_v3eq(ft, Gv.from_to[TO]);
02630         GS_v3sub(ft, Gv.from_to[FROM]);
02631         GS_v3eq(Gv.from_to[FROM], pt);
02632         GS_v3eq(Gv.from_to[TO], pt);
02633         GS_v3add(Gv.from_to[TO], ft);
02634     }
02635 
02636     return;
02637 }
02638 
02644 void GS_moveto_real(float *pt)
02645 {
02646     gsd_real2model(pt);
02647     GS_moveto(pt);
02648 
02649     return;
02650 }
02651 
02663 int GS_get_zextents(int id, float *min, float *max, float *mid)
02664 {
02665     geosurf *gs;
02666 
02667     if (NULL == (gs = gs_get_surf(id))) {
02668         return (-1);
02669     }
02670 
02671     G_debug(3, "GS_get_zextents(): id=%d", id);
02672 
02673     return (gs_get_zextents(gs, min, max, mid));
02674 }
02675 
02686 int GS_get_zrange(float *min, float *max, int doexag)
02687 {
02688     int ret_surf, ret_vol;
02689     float surf_min, surf_max;
02690     float vol_min, vol_max;
02691 
02692     ret_surf = gs_get_zrange(&surf_min, &surf_max);
02693     ret_vol = gvl_get_zrange(&vol_min, &vol_max);
02694 
02695     if (ret_surf > 0 && ret_vol > 0) {
02696         *min = (surf_min < vol_min) ? surf_min : vol_min;
02697         *max = (surf_max < vol_max) ? surf_max : vol_max;
02698     }
02699     else if (ret_surf > 0) {
02700         *min = surf_min;
02701         *max = surf_max;
02702     }
02703     else if (ret_vol > 0) {
02704         *min = vol_min;
02705         *max = vol_max;
02706     }
02707 
02708     if (doexag) {
02709         *min *= Gv.vert_exag;
02710         *max *= Gv.vert_exag;
02711     }
02712 
02713     G_debug(3, "GS_get_zrange(): min=%g max=%g", *min, *max);
02714     return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
02715 }
02716 
02722 void GS_get_from(float *fr)
02723 {
02724     GS_v3eq(fr, Gv.from_to[FROM]);
02725 
02726     G_debug(3, "GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
02727 
02728     return;
02729 }
02730 
02736 void GS_get_from_real(float *fr)
02737 {
02738     GS_v3eq(fr, Gv.from_to[FROM]);
02739     gsd_model2real(fr);
02740 
02741     return;
02742 }
02743 
02749 void GS_get_to_real(float *to)
02750 {
02751     float realto[3];
02752 
02753     G_get_set_window(&wind);
02754     GS_get_focus(realto);
02755     to[X] = realto[X] + wind.west + (wind.ew_res / 2.);
02756     to[Y] = realto[Y] + wind.south + (wind.ns_res / 2.);
02757     to[Z] = realto[Z];
02758 
02759     return;
02760 }
02761 
02762 
02769 void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy)
02770 {
02771     GLint tmp[4];
02772     GLint num[2];
02773 
02774     gsd_getViewport(tmp, num);
02775     *a = tmp[0];
02776     *b = tmp[1];
02777     *c = tmp[2];
02778     *d = tmp[3];
02779     *maxx = num[0];
02780     *maxy = num[1];
02781 
02782     return;
02783 }
02784 
02792 void GS_get_to(float *to)
02793 {
02794     G_debug(3, "GS_get_to");
02795 
02796     GS_v3eq(to, Gv.from_to[TO]);
02797 
02798     return;
02799 }
02800 
02806 void GS_get_viewdir(float *dir)
02807 {
02808     GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
02809 
02810     return;
02811 }
02812 
02820 void GS_set_viewdir(float *dir)
02821 {
02822     float tmp[3];
02823 
02824     GS_v3eq(tmp, dir);
02825     GS_v3norm(tmp);
02826     GS_v3eq(Gv.from_to[TO], Gv.from_to[FROM]);
02827     GS_v3add(Gv.from_to[TO], tmp);
02828 
02829     GS_set_nofocus();
02830     gsd_set_view(&Gv, &Gd);
02831 
02832     return;
02833 }
02834 
02840 void GS_set_fov(int fov)
02841 {
02842     Gv.fov = fov;
02843 
02844     return;
02845 }
02846 
02852 int GS_get_fov(void)
02853 {
02854     return (Gv.fov);
02855 }
02856 
02862 int GS_get_twist(void)
02863 {
02864     return (Gv.twist);
02865 }
02866 
02874 void GS_set_twist(int t)
02875 {
02876     Gv.twist = t;
02877 
02878     return;
02879 }
02880 
02884 void GS_set_rotation(double angle, double x, double y, double z)
02885 {
02886     Gv.rotate.rot_angle = angle;
02887     Gv.rotate.rot_axes[0] = x;
02888     Gv.rotate.rot_axes[1] = y;
02889     Gv.rotate.rot_axes[2] = z;
02890     Gv.rotate.do_rot = 1;
02891 
02892     return;
02893 }
02894 
02898 void GS_unset_rotation(void)
02899 {
02900     Gv.rotate.do_rot = 0;
02901 }
02902 
02906 void GS_init_rotation(void)
02907 {
02908     int i;
02909 
02910     for (i = 0; i < 16; i++) {
02911         if (i == 0 || i == 5 || i == 10 || i == 15)
02912             Gv.rotate.rotMatrix[i] = 1.0;
02913         else
02914             Gv.rotate.rotMatrix[i] = 0.0;
02915     }
02916     Gv.rotate.rot_angle = 0.0;
02917     Gv.rotate.rot_axes[0] = 0.0;
02918     Gv.rotate.rot_axes[1] = 0.0;
02919     Gv.rotate.rot_axes[2] = 0.0;
02920     Gv.rotate.do_rot = 0;
02921     
02922 }
02926 void GS_get_rotation_matrix(double *matrix)
02927 {
02928     int i;
02929 
02930     for (i = 0; i < 16; i++) {
02931         matrix[i] = Gv.rotate.rotMatrix[i];
02932     }
02933 }
02934 
02938 void GS_set_rotation_matrix(double *matrix)
02939 {
02940     int i;
02941 
02942     for (i = 0; i < 16; i++) {
02943         Gv.rotate.rotMatrix[i] = matrix[i];
02944     }
02945 }
02946 
02950 void GS_set_nofocus(void)
02951 {
02952     G_debug(3, "GS_set_nofocus");
02953 
02954     Gv.infocus = 0;
02955 
02956     return;
02957 }
02958 
02964 void GS_set_infocus(void)
02965 {
02966     G_debug(3, "GS_set_infocus");
02967 
02968     Gv.infocus = 1;
02969 
02970     return;
02971 }
02972 
02978 void GS_set_viewport(int left, int right, int bottom, int top)
02979 {
02980     G_debug(3, "GS_set_viewport(): left=%d, right=%d, "
02981             "bottom=%d, top=%d", left, right, bottom, top);
02982 
02983     gsd_viewport(left, right, bottom, top);
02984 
02985     return;
02986 }
02987 
03002 int GS_look_here(int sx, int sy)
03003 {
03004     float x, y, z, len, los[2][3];
03005     Point3 realto, dir;
03006     int id;
03007     geosurf *gs;
03008 
03009     if (GS_get_selected_point_on_surface(sx, sy, &id, &x, &y, &z)) {
03010         gs = gs_get_surf(id);
03011         if (gs) {
03012             realto[X] = x - gs->ox + gs->x_trans;
03013             realto[Y] = y - gs->oy + gs->y_trans;
03014             realto[Z] = z + gs->z_trans;
03015             GS_set_focus(realto);
03016 
03017             return (1);
03018         }
03019     }
03020     else {
03021         if (gsd_get_los(los, (short)sx, (short)sy)) {
03022             len = GS_distance(Gv.from_to[FROM], Gv.real_to);
03023             GS_v3dir(los[FROM], los[TO], dir);
03024             GS_v3mult(dir, len);
03025             realto[X] = Gv.from_to[FROM][X] + dir[X];
03026             realto[Y] = Gv.from_to[FROM][Y] + dir[Y];
03027             realto[Z] = Gv.from_to[FROM][Z] + dir[Z];
03028             GS_set_focus(realto);
03029 
03030             return (1);
03031         }
03032     }
03033 
03034     return (0);
03035 }
03036 
03051 int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x,
03052                                      float *y, float *z)
03053 {
03054     float los[2][3], find_dist[MAX_SURFS], closest;
03055     Point3 point, tmp, finds[MAX_SURFS];
03056     int surfs[MAX_SURFS], i, iclose, numhits = 0;
03057     geosurf *gs;
03058 
03059     /* returns surface-world coords */
03060     gsd_get_los(los, (short)sx, (short)sy);
03061 
03062     if (!gs_setlos_enterdata(los)) {
03063         G_debug(3, "gs_setlos_enterdata(los): returns false");
03064         return (0);
03065     }
03066 
03067     for (i = 0; i < Next_surf; i++) {
03068         G_debug(3, "id=%d", i);
03069 
03070         gs = gs_get_surf(Surf_ID[i]);
03071 
03072         /* los_intersect expects surf-world coords (xy transl, no scaling) */
03073 
03074 #if NVIZ_HACK
03075         if (gs_los_intersect1(Surf_ID[i], los, point)) {
03076 #else
03077         if (gs_los_intersect(Surf_ID[i], los, point)) {
03078 #endif
03079             if (!gs_point_is_masked(gs, point)) {
03080                 GS_v3eq(tmp, point);
03081                 tmp[X] += gs->x_trans;
03082                 tmp[Y] += gs->y_trans;
03083                 tmp[Z] += gs->z_trans;
03084                 find_dist[numhits] = GS_distance(los[FROM], tmp);
03085                 gsd_surf2real(gs, point);
03086                 GS_v3eq(finds[numhits], point);
03087                 surfs[numhits] = Surf_ID[i];
03088                 numhits++;
03089             }
03090         }
03091     }
03092 
03093     for (i = iclose = 0; i < numhits; i++) {
03094         closest = find_dist[iclose];
03095 
03096         if (find_dist[i] < closest) {
03097             iclose = i;
03098         }
03099     }
03100 
03101     if (numhits) {
03102         *x = finds[iclose][X];
03103         *y = finds[iclose][Y];
03104         *z = finds[iclose][Z];
03105         *id = surfs[iclose];
03106     }
03107 
03108     G_debug(3, "NumHits %d, next %d", numhits, Next_surf);
03109 
03110     return (numhits);
03111 }
03112 
03119 void GS_set_cplane_rot(int num, float dx, float dy, float dz)
03120 {
03121     gsd_cplane_setrot(num, dx, dy, dz);
03122 
03123     return;
03124 }
03125 
03132 void GS_set_cplane_trans(int num, float dx, float dy, float dz)
03133 {
03134     gsd_cplane_settrans(num, dx, dy, dz);
03135 
03136     return;
03137 }
03138 
03139 
03145 void GS_draw_cplane(int num)
03146 {
03147     geosurf *gsurfs[MAX_SURFS];
03148     int nsurfs;
03149 
03150     nsurfs = gs_num_surfaces();
03151     if (2 == nsurfs) {
03152         /* testing */
03153         gs_getall_surfaces(gsurfs);
03154         gsd_draw_cplane_fence(gsurfs[0], gsurfs[1], num);
03155     }
03156     else {
03157         gsd_draw_cplane(num);
03158     }
03159 
03160     return;
03161 }
03162 
03172 int GS_draw_cplane_fence(int hs1, int hs2, int num)
03173 {
03174     geosurf *gs1, *gs2;
03175 
03176     if (NULL == (gs1 = gs_get_surf(hs1))) {
03177         return (0);
03178     }
03179 
03180     if (NULL == (gs2 = gs_get_surf(hs2))) {
03181         return (0);
03182     }
03183 
03184     gsd_draw_cplane_fence(gs1, gs2, num);
03185 
03186     return (1);
03187 }
03188 
03192 void GS_alldraw_cplane_fences(void)
03193 {
03194     int onstate[MAX_CPLANES], i;
03195 
03196     gsd_get_cplanes_state(onstate);
03197 
03198     for (i = 0; i < MAX_CPLANES; i++) {
03199         if (onstate[i]) {
03200             GS_draw_cplane_fence(Surf_ID[0], Surf_ID[1], i);
03201         }
03202     }
03203 
03204     return;
03205 }
03206 
03212 void GS_set_cplane(int num)
03213 {
03214     gsd_cplane_on(num);
03215 
03216     return;
03217 }
03218 
03224 void GS_unset_cplane(int num)
03225 {
03226     gsd_cplane_off(num);
03227 
03228     return;
03229 }
03230 
03237 void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
03238 {
03239     float zexag;
03240 
03241     zexag = doexag ? Gv.vert_exag : 1.;
03242     *sx = *sy = Gv.scale;
03243     *sz = Gv.scale * zexag;
03244 
03245     return;
03246 }
03247 
03253 void GS_set_fencecolor(int mode)
03254 {
03255     gsd_setfc(mode);
03256 
03257     return;
03258 }
03259 
03265 int GS_get_fencecolor(void)
03266 {
03267     return gsd_getfc();
03268 }
03269 
03282 int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2,
03283                               float *dist, int use_exag)
03284 {
03285     geosurf *gs;
03286     float p1[2], p2[2];
03287     
03288     gs = gs_get_surf(hs);
03289     if (gs == NULL) {
03290         return 0;
03291     }
03292     
03293     p1[X] = x1;
03294     p1[Y] = y1;
03295     p2[X] = x2;
03296     p2[Y] = y2;
03297     gsd_real2surf(gs, p1);
03298     gsd_real2surf(gs, p2);
03299 
03300     G_debug(3, "GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
03301             hs, x1, y1, x2, y2);
03302     return gs_distance_onsurf(gs, p1, p2, dist, use_exag);
03303 }
03304 
03313 int GS_save_3dview(const char *vname, int surfid)
03314 {
03315     return (Gs_save_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
03316 }
03317 
03326 int GS_load_3dview(const char *vname, int surfid)
03327 {
03328 
03329     return (Gs_load_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
03330 
03331     /* what to do about lights - I guess, delete all &
03332        create any that exist in 3dview file */
03333 }
03334 
03335 /************************************************************************
03336 * Following routines use Graphics Library
03337 ************************************************************************/
03338 
03344 void GS_init_view(void)
03345 {
03346     int i;
03347     static int first = 1;
03348 
03349     G_debug(3, "GS_init_view");
03350 
03351     if (first) {
03352         first = 0;
03353         glMatrixMode(GL_MODELVIEW);
03354 
03355         /* OGLXXX doublebuffer: use GLX_DOUBLEBUFFER in attriblist */
03356         /* glxChooseVisual(*dpy, screen, *attriblist); */
03357         /* OGLXXX
03358          * ZMIN not needed -- always 0.
03359          * ZMAX not needed -- always 1.
03360          * getgdesc other posiblilties:
03361          *      glxGetConfig();
03362          *      glxGetCurrentContext();
03363          *      glxGetCurrentDrawable();
03364          * GLint gdtmp;
03365          * getgdesc other posiblilties:
03366          *      glxGetConfig();
03367          *      glxGetCurrentContext();
03368          *      glxGetCurrentDrawable();
03369          * GLint gdtmp;
03370          * glDepthRange params must be scaled to [0, 1]
03371          */
03372         glDepthRange(0.0, 1.0);
03373         glEnable(GL_DEPTH_TEST);
03374         glDepthFunc(GL_LEQUAL);
03375         /* } */
03376 
03377         /* replace these with something meaningful */
03378         Gv.fov = 450;
03379         Gv.twist = 0;
03380 
03381         GS_init_rotation();
03382 
03383         Gv.from_to[FROM][X] = Gv.from_to[FROM][Y] =
03384             Gv.from_to[FROM][Z] = GS_UNIT_SIZE / 2.;
03385 
03386         Gv.from_to[TO][X] = GS_UNIT_SIZE / 2.;
03387         Gv.from_to[TO][Y] = GS_UNIT_SIZE / 2.;
03388         Gv.from_to[TO][Z] = 0.;
03389         Gv.from_to[TO][W] = Gv.from_to[FROM][W] = 1.;
03390 
03391         Gv.real_to[W] = 1.;
03392         Gv.vert_exag = 1.;
03393 
03394         GS_v3eq(Gv.real_to, Gv.from_to[TO]);
03395         GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
03396 
03397         /*
03398            Gd.nearclip = 50;
03399            Gd.farclip = 10000.;
03400          */
03401         Gd.nearclip = 10.;
03402         Gd.farclip = 10000.;
03403         Gd.aspect = (float)GS_get_aspect();
03404 
03405         GS_set_focus(Gv.real_to);
03406     }
03407 
03408     return;
03409 }
03410 
03416 void GS_clear(int col)
03417 {
03418     G_debug(3, "GS_clear");
03419 
03420     col = col | 0xFF000000;
03421 
03422     /* OGLXXX
03423      * change glClearDepth parameter to be in [0, 1]
03424      * ZMAX not needed -- always 1.
03425      * getgdesc other posiblilties:
03426      *      glxGetConfig();
03427      *      glxGetCurrentContext();
03428      *      glxGetCurrentDrawable();
03429      * GLint gdtmp;
03430      */
03431     glClearDepth(1.0);
03432     glClearColor(((float)((col) & 0xff)) / 255.,
03433                  (float)((col) >> 8 & 0xff) / 255.,
03434                  (float)((col) >> 16 & 0xff) / 255.,
03435                  (float)((col) >> 24 & 0xff) / 255.);
03436     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
03437 
03438     Gd.bgcol = col;
03439     Modelshowing = 0;
03440     gsd_flush();
03441 
03442     return;
03443 }
03444 
03450 double GS_get_aspect(void)
03451 {
03452     int left, right, bottom, top;
03453     GLint tmp[4];
03454 
03455     /* OGLXXX
03456      * get GL_VIEWPORT:
03457      * You can probably do better than this.
03458      */
03459     glGetIntegerv(GL_VIEWPORT, tmp);
03460     left = tmp[0];
03461     right = tmp[0] + tmp[2] - 1;
03462     bottom = tmp[1];
03463     top = tmp[1] + tmp[3] - 1;
03464 
03465     G_debug(3, "GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
03466             left, right, top, bottom);
03467 
03468     return ((double)(right - left) / (top - bottom));
03469 }
03470 
03478 int GS_has_transparency(void)
03479 {
03480     /* OGLXXX
03481      * getgdesc other posiblilties:
03482      *      glxGetConfig();
03483      *      glxGetCurrentContext();
03484      *      glxGetCurrentDrawable();
03485      * GLint gdtmp;
03486      * blending is ALWAYS supported.
03487      * This function returns whether it is enabled.
03488      * return((glGetIntegerv(GL_BLEND, &gdtmp), gdtmp));
03489      */
03490 
03491     return (1);
03492 }