GRASS Programmer's Manual
6.4.2(2012)
|
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 Modelshowing = 0; 00082 00083 void void_func(void) 00084 { 00085 return; 00086 } 00087 00095 void GS_libinit(void) 00096 { 00097 static int first = 1; 00098 00099 G_get_set_window(&wind); 00100 00101 Region[0] = wind.north; 00102 Region[1] = wind.south; 00103 Region[2] = wind.west; 00104 Region[3] = wind.east; 00105 00106 /* scale largest dimension to GS_UNIT_SIZE */ 00107 if ((wind.east - wind.west) > (wind.north - wind.south)) { 00108 Longdim = (wind.east - wind.west); 00109 } 00110 else { 00111 Longdim = (wind.north - wind.south); 00112 } 00113 00114 Gv.scale = GS_UNIT_SIZE / Longdim; 00115 00116 Cxl_func = void_func; 00117 Swap_func = void_func; 00118 00119 if (first) { 00120 gs_init(); 00121 } 00122 00123 first = 0; 00124 00125 return; 00126 } 00127 00135 int GS_get_longdim(float *dim) 00136 { 00137 *dim = Longdim; 00138 00139 G_debug(3, "GS_get_longdim(): dim=%g", *dim); 00140 00141 return (1); 00142 } 00143 00151 int GS_get_region(float *n, float *s, float *w, float *e) 00152 { 00153 *n = Region[0]; 00154 *s = Region[1]; 00155 *w = Region[2]; 00156 *e = Region[3]; 00157 00158 return (1); 00159 } 00160 00167 void GS_set_att_defaults(float *defs, float *null_defs) 00168 { 00169 int i; 00170 00171 G_debug(3, "GS_set_att_defaults"); 00172 00173 for (i = 0; i < MAX_ATTS; i++) { 00174 Default_const[i] = defs[i]; 00175 Default_nulls[i] = null_defs[i]; 00176 } 00177 00178 return; 00179 } 00180 00189 int GS_surf_exists(int id) 00190 { 00191 int i, found = 0; 00192 00193 G_debug(3, "GS_surf_exists(): id=%d", id); 00194 00195 00196 if (NULL == gs_get_surf(id)) { 00197 return (0); 00198 } 00199 00200 for (i = 0; i < Next_surf && !found; i++) { 00201 if (Surf_ID[i] == id) { 00202 found = 1; 00203 } 00204 } 00205 00206 return (found); 00207 } 00208 00219 int GS_new_surface(void) 00220 { 00221 geosurf *ns; 00222 00223 G_debug(3, "GS_new_surface():"); 00224 00225 if (Next_surf < MAX_SURFS) { 00226 ns = gs_get_new_surface(); 00227 gs_init_surf(ns, wind.west + wind.ew_res / 2., 00228 wind.south + wind.ns_res / 2., wind.rows, wind.cols, 00229 wind.ew_res, wind.ns_res); 00230 gs_set_defaults(ns, Default_const, Default_nulls); 00231 00232 /* make default shine current */ 00233 gs_set_att_src(ns, ATT_SHINE, CONST_ATT); 00234 00235 Surf_ID[Next_surf] = ns->gsurf_id; 00236 ++Next_surf; 00237 00238 G_debug(3, " id=%d", ns->gsurf_id); 00239 00240 return (ns->gsurf_id); 00241 } 00242 00243 00244 00245 return (-1); 00246 } 00247 00254 int GS_new_light(void) 00255 { 00256 static int first = 1; 00257 int i; 00258 00259 if (first) { 00260 first = 0; 00261 00262 for (i = 0; i < MAX_LIGHTS; i++) { 00263 Gv.lights[i].position[X] = Gv.lights[i].position[Y] = 0.0; 00264 Gv.lights[i].position[Z] = 1.0; 00265 Gv.lights[i].position[W] = 0.0; /* infinite */ 00266 Gv.lights[i].color[0] = Gv.lights[i].color[1] = 00267 Gv.lights[i].color[2] = 1.0; 00268 Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] = 00269 Gv.lights[i].ambient[2] = 0.2; 00270 Gv.lights[i].shine = 32.0; 00271 } 00272 00273 gsd_init_lightmodel(); 00274 } 00275 00276 if (Numlights < MAX_LIGHTS) { 00277 gsd_deflight(Numlights + 1, &(Gv.lights[Numlights])); 00278 gsd_switchlight(Numlights + 1, 1); 00279 00280 return (++Numlights); 00281 } 00282 00283 return (-1); 00284 } 00285 00295 void GS_setlight_position(int num, float xpos, float ypos, float zpos, 00296 int local) 00297 { 00298 if (num) { 00299 num -= 1; 00300 if (num < Numlights) { 00301 Gv.lights[num].position[X] = xpos; 00302 Gv.lights[num].position[Y] = ypos; 00303 Gv.lights[num].position[Z] = zpos; 00304 Gv.lights[num].position[W] = (float)local; 00305 00306 gsd_deflight(num + 1, &(Gv.lights[num])); 00307 } 00308 } 00309 00310 return; 00311 } 00312 00313 00321 void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos, 00322 int *local) 00323 { 00324 if (num) { 00325 num -= 1; 00326 if (num < Numlights) { 00327 *xpos = Gv.lights[num].position[X]; 00328 *ypos = Gv.lights[num].position[Y]; 00329 *zpos = Gv.lights[num].position[Z]; 00330 *local = (int)Gv.lights[num].position[W]; 00331 00332 } 00333 } 00334 00335 return; 00336 } 00337 00344 void GS_setlight_color(int num, float red, float green, float blue) 00345 { 00346 if (num) { 00347 num -= 1; 00348 if (num < Numlights) { 00349 Gv.lights[num].color[0] = red; 00350 Gv.lights[num].color[1] = green; 00351 Gv.lights[num].color[2] = blue; 00352 00353 gsd_deflight(num + 1, &(Gv.lights[num])); 00354 } 00355 } 00356 00357 return; 00358 } 00359 00366 void GS_getlight_color(int num, float *red, float *green, float *blue) 00367 { 00368 if (num) { 00369 num -= 1; 00370 if (num < Numlights) { 00371 *red = Gv.lights[num].color[0]; 00372 *green = Gv.lights[num].color[1]; 00373 *blue = Gv.lights[num].color[2]; 00374 } 00375 } 00376 00377 return; 00378 } 00379 00388 void GS_setlight_ambient(int num, float red, float green, float blue) 00389 { 00390 if (num) { 00391 num -= 1; 00392 if (num < Numlights) { 00393 Gv.lights[num].ambient[0] = red; 00394 Gv.lights[num].ambient[1] = green; 00395 Gv.lights[num].ambient[2] = blue; 00396 00397 gsd_deflight(num + 1, &(Gv.lights[num])); 00398 } 00399 } 00400 00401 return; 00402 } 00403 00410 void GS_getlight_ambient(int num, float *red, float *green, float *blue) 00411 { 00412 if (num) { 00413 num -= 1; 00414 if (num < Numlights) { 00415 *red = Gv.lights[num].ambient[0]; 00416 *green = Gv.lights[num].ambient[1]; 00417 *blue = Gv.lights[num].ambient[2]; 00418 } 00419 } 00420 00421 return; 00422 } 00423 00424 00428 void GS_lights_off(void) 00429 { 00430 int i; 00431 00432 for (i = 0; i < Numlights; i++) { 00433 gsd_switchlight(i + 1, 0); 00434 } 00435 00436 return; 00437 } 00438 00442 void GS_lights_on(void) 00443 { 00444 int i; 00445 00446 for (i = 0; i < Numlights; i++) { 00447 gsd_switchlight(i + 1, 1); 00448 } 00449 00450 return; 00451 } 00452 00459 void GS_switchlight(int num, int on) 00460 { 00461 if (num) { 00462 num -= 1; 00463 00464 if (num < Numlights) { 00465 gsd_switchlight(num + 1, on); 00466 } 00467 } 00468 00469 return; 00470 } 00471 00478 int GS_transp_is_set(void) 00479 { 00480 return (gs_att_is_set(NULL, ATT_TRANSP) || (FC_GREY == gsd_getfc())); 00481 } 00482 00488 void GS_get_modelposition1(float pos[]) 00489 { 00490 /* TODO: Still needs work to handle other cases */ 00491 /* this is a quick hack to get lighting adjustments debugged */ 00492 /* 00493 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], center); 00494 GS_v3mult(center, 1000); 00495 GS_v3add(center, Gv.from_to[FROM]); 00496 */ 00497 00498 gs_get_datacenter(pos); 00499 gs_get_data_avg_zmax(&(pos[Z])); 00500 00501 G_debug(1, "GS_get_modelposition1(): model position: %f %f %f", 00502 pos[X], pos[Y], pos[Z]); 00503 00504 return; 00505 } 00506 00517 void GS_get_modelposition(float *siz, float *pos) 00518 { 00519 float dist, near_h, dir[3]; 00520 00521 dist = 2. * Gd.nearclip; 00522 00523 near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist; 00524 *siz = near_h / 8.0; 00525 00526 /* prevent clipping - would only happen if fov > ~127 degrees, at 00527 fov = 2.0 * atan(2.0) */ 00528 00529 if (*siz > Gd.nearclip) { 00530 *siz = Gd.nearclip; 00531 } 00532 00533 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir); 00534 00535 pos[X] = Gv.from_to[FROM][X] + dir[X] * dist; 00536 pos[Y] = Gv.from_to[FROM][Y] + dir[Y] * dist; 00537 pos[Z] = Gv.from_to[FROM][Z] + dir[Z] * dist; 00538 00539 return; 00540 } 00541 00542 00554 void GS_set_Narrow(int *pt, int id, float *pos2) 00555 { 00556 geosurf *gs; 00557 float x, y, z; 00558 GLdouble modelMatrix[16], projMatrix[16]; 00559 GLint viewport[4]; 00560 00561 if (GS_get_selected_point_on_surface(pt[X], pt[Y], &id, &x, &y, &z)) { 00562 gs = gs_get_surf(id); 00563 if (gs) { 00564 z = gs->zmax; 00565 pos2[X] = (float)x - gs->ox + gs->x_trans; 00566 pos2[Y] = (float)y - gs->oy + gs->y_trans; 00567 pos2[Z] = (float)z + gs->z_trans; 00568 00569 return; 00570 } 00571 } 00572 else { 00573 gs = gs_get_surf(id); 00574 00575 /* Need to get model matrix, etc 00576 * to run gluUnProject 00577 */ 00578 gsd_pushmatrix(); 00579 gsd_do_scale(1); 00580 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); 00581 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); 00582 glGetIntegerv(GL_VIEWPORT, viewport); 00583 00584 if (gs) { 00585 GLdouble out_near[3], out_far[3]; 00586 GLdouble factor; 00587 GLdouble out[3]; 00588 00589 z = (float)gs->zmax + gs->z_trans; 00590 00591 gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 0., 00592 modelMatrix, projMatrix, viewport, 00593 &out_near[X], &out_near[Y], &out_near[Z]); 00594 gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1., 00595 modelMatrix, projMatrix, viewport, 00596 &out_far[X], &out_far[Y], &out_far[Z]); 00597 00598 glPopMatrix(); 00599 00600 factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]); 00601 00602 out[X] = out_near[X] - ((out_near[X] - out_far[X]) * factor); 00603 out[Y] = out_near[Y] - ((out_near[Y] - out_far[Y]) * factor); 00604 out[Z] = z; 00605 00606 pos2[X] = (float)out[X]; 00607 pos2[Y] = (float)out[Y]; 00608 pos2[Z] = (float)out[Z]; 00609 00610 return; 00611 00612 } 00613 } 00614 return; 00615 } 00616 00623 void GS_draw_X(int id, float *pt) 00624 { 00625 geosurf *gs; 00626 Point3 pos; 00627 float siz; 00628 00629 if ((gs = gs_get_surf(id))) { 00630 GS_get_longdim(&siz); 00631 siz /= 200.; 00632 pos[X] = pt[X] - gs->ox; 00633 pos[Y] = pt[Y] - gs->oy; 00634 _viewcell_tri_interp(gs, pos); 00635 00636 gsd_pushmatrix(); 00637 00638 gsd_do_scale(1); 00639 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans); 00640 gsd_linewidth(1); 00641 00642 if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) { 00643 pos[Z] = gs->att[ATT_TOPO].constant; 00644 gs = NULL; /* tells gpd_obj to use given Z val */ 00645 } 00646 00647 gpd_obj(gs, Gd.bgcol, siz, ST_GYRO, pos); 00648 gsd_flush(); 00649 00650 gsd_popmatrix(); 00651 } 00652 00653 return; 00654 } 00655 00662 void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2) 00663 { 00664 float p1[2], p2[2]; 00665 geosurf *gs; 00666 00667 if ((gs = gs_get_surf(id))) { 00668 p1[X] = x1 - gs->ox; 00669 p1[Y] = y1 - gs->oy; 00670 p2[X] = x2 - gs->ox; 00671 p2[Y] = y2 - gs->oy; 00672 00673 gsd_pushmatrix(); 00674 00675 gsd_do_scale(1); 00676 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans); 00677 gsd_linewidth(1); 00678 00679 gsd_color_func(GS_default_draw_color()); 00680 gsd_line_onsurf(gs, p1, p2); 00681 00682 gsd_popmatrix(); 00683 gsd_flush(); 00684 } 00685 00686 return; 00687 } 00688 00701 int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2, 00702 float *lasp, int n) 00703 { 00704 float p1[2], p2[2]; 00705 geosurf *gs; 00706 int ret = 0; 00707 00708 if ((gs = gs_get_surf(id))) { 00709 p1[X] = x1 - gs->ox; 00710 p1[Y] = y1 - gs->oy; 00711 p2[X] = x2 - gs->ox; 00712 p2[Y] = y2 - gs->oy; 00713 00714 gsd_pushmatrix(); 00715 00716 gsd_do_scale(1); 00717 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans); 00718 gsd_linewidth(1); 00719 gsd_color_func(GS_default_draw_color()); 00720 ret = gsd_nline_onsurf(gs, p1, p2, lasp, n); 00721 gsd_surf2real(gs, lasp); 00722 00723 gsd_popmatrix(); 00724 gsd_flush(); 00725 } 00726 00727 return (ret); 00728 } 00729 00739 void GS_draw_flowline_at_xy(int id, float x, float y) 00740 { 00741 geosurf *gs; 00742 float nv[3], pdir[2], mult; 00743 float p1[2], p2[2], next[2]; 00744 int i = 0; 00745 00746 if ((gs = gs_get_surf(id))) { 00747 p1[X] = x; 00748 p1[Y] = y; 00749 /* multiply by 1.5 resolutions to ensure a crossing ? */ 00750 mult = .1 * (VXRES(gs) > VYRES(gs) ? VXRES(gs) : VYRES(gs)); 00751 00752 GS_coordpair_repeats(p1, p1, 50); 00753 00754 while (1 == GS_get_norm_at_xy(id, p1[X], p1[Y], nv)) { 00755 if (nv[Z] == 1.0) { 00756 if (pdir[X] == 0.0 && pdir[Y] == 0.0) { 00757 break; 00758 } 00759 00760 p2[X] = p1[X] + (pdir[X] * mult); 00761 p2[Y] = p1[Y] + (pdir[Y] * mult); 00762 } 00763 else { 00764 /* use previous direction */ 00765 GS_v2norm(nv); 00766 p2[X] = p1[X] + (nv[X] * mult); 00767 p2[Y] = p1[Y] + (nv[Y] * mult); 00768 pdir[X] = nv[X]; 00769 pdir[Y] = nv[Y]; 00770 } 00771 00772 if (i > 2000) { 00773 break; 00774 } 00775 00776 if (GS_coordpair_repeats(p1, p2, 0)) { 00777 break; 00778 } 00779 00780 /* Think about this: */ 00781 /* degenerate line means edge or level edge ? */ 00782 /* next is filled with last point drawn */ 00783 if (2 > GS_draw_nline_onsurf(id, p1[X], p1[Y], 00784 p2[X], p2[Y], next, 3)) { 00785 break; 00786 } 00787 00788 p1[X] = next[X]; 00789 p1[Y] = next[Y]; 00790 } 00791 00792 G_debug(3, "GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]); 00793 } 00794 00795 return; 00796 } 00797 00806 void GS_draw_fringe(int id, unsigned long clr, float elev, int *where) 00807 { 00808 geosurf *gs; 00809 00810 G_debug(3, "GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d", 00811 id, clr, elev, where[0], where[1], where[2], where[3]); 00812 if ((gs = gs_get_surf(id))) 00813 gsd_display_fringe(gs, clr, elev, where); 00814 00815 } 00816 00817 00831 int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags, 00832 float *range, int *pt) 00833 { 00834 int list_no; 00835 00836 list_no = gsd_put_legend(name, fontbase, size, flags, range, pt); 00837 00838 return (list_no); 00839 } 00840 00849 void GS_draw_list(GLuint list_id) 00850 { 00851 gsd_calllist(list_id); 00852 glFlush(); 00853 return; 00854 } 00855 00862 void GS_draw_all_list(void) 00863 { 00864 gsd_calllists(0); /* not sure if 0 is right - MN */ 00865 glFlush(); 00866 return; 00867 } 00868 00874 void GS_delete_list(GLuint list_id) 00875 { 00876 gsd_deletelist(list_id, 1); 00877 00878 return; 00879 } 00880 00884 void GS_draw_lighting_model1(void) 00885 { 00886 static float center[3]; 00887 float tcenter[3]; 00888 00889 if (!Modelshowing) { 00890 GS_get_modelposition1(center); 00891 } 00892 00893 GS_v3eq(tcenter, center); 00894 00895 gsd_zwritemask(0x0); 00896 gsd_backface(1); 00897 00898 gsd_colormode(CM_AD); 00899 gsd_shademodel(DM_GOURAUD); 00900 gsd_pushmatrix(); 00901 gsd_do_scale(1); 00902 00903 if (Gv.vert_exag) { 00904 tcenter[Z] *= Gv.vert_exag; 00905 gsd_scale(1.0, 1.0, 1. / Gv.vert_exag); 00906 } 00907 00908 gsd_drawsphere(tcenter, 0xDDDDDD, (float)(Longdim / 10.)); 00909 gsd_popmatrix(); 00910 Modelshowing = 1; 00911 00912 gsd_backface(0); 00913 gsd_zwritemask(0xffffffff); 00914 00915 return; 00916 } 00917 00924 void GS_draw_lighting_model(void) 00925 { 00926 static float center[3], size; 00927 float tcenter[3], tsize; 00928 int i, wason[MAX_CPLANES]; 00929 00930 gsd_get_cplanes_state(wason); 00931 00932 for (i = 0; i < MAX_CPLANES; i++) { 00933 if (wason[i]) { 00934 gsd_cplane_off(i); 00935 } 00936 } 00937 00938 00939 if (!Modelshowing) { 00940 GS_get_modelposition(&size, center); 00941 } 00942 00943 GS_v3eq(tcenter, center); 00944 tsize = size; 00945 00946 gsd_zwritemask(0x0); 00947 gsd_backface(1); 00948 00949 gsd_colormode(CM_DIFFUSE); 00950 gsd_shademodel(DM_GOURAUD); 00951 gsd_pushmatrix(); 00952 gsd_drawsphere(tcenter, 0xDDDDDD, tsize); 00953 gsd_popmatrix(); 00954 Modelshowing = 1; 00955 00956 gsd_backface(0); 00957 gsd_zwritemask(0xffffffff); 00958 00959 for (i = 0; i < MAX_CPLANES; i++) { 00960 if (wason[i]) { 00961 gsd_cplane_on(i); 00962 } 00963 } 00964 00965 gsd_flush(); 00966 00967 return; 00968 } 00969 00980 int GS_update_curmask(int id) 00981 { 00982 geosurf *gs; 00983 00984 gs = gs_get_surf(id); 00985 return (gs_update_curmask(gs)); 00986 } 00987 00998 int GS_is_masked(int id, float *pt) 00999 { 01000 geosurf *gs; 01001 Point3 tmp; 01002 01003 if ((gs = gs_get_surf(id))) { 01004 tmp[X] = pt[X] - gs->ox; 01005 tmp[Y] = pt[Y] - gs->oy; 01006 01007 return (gs_point_is_masked(gs, tmp)); 01008 } 01009 01010 return (-1); 01011 } 01012 01016 void GS_unset_SDsurf(void) 01017 { 01018 gsdiff_set_SDref(NULL); 01019 SDref_surf = 0; 01020 01021 return; 01022 } 01023 01032 int GS_set_SDsurf(int id) 01033 { 01034 geosurf *gs; 01035 01036 if ((gs = gs_get_surf(id))) { 01037 gsdiff_set_SDref(gs); 01038 SDref_surf = id; 01039 01040 return (1); 01041 } 01042 01043 return (0); 01044 } 01045 01053 int GS_set_SDscale(float scale) 01054 { 01055 gsdiff_set_SDscale(scale); 01056 01057 return (1); 01058 } 01059 01068 int GS_get_SDsurf(int *id) 01069 { 01070 geosurf *gs; 01071 01072 if ((gs = gsdiff_get_SDref())) { 01073 *id = SDref_surf; 01074 01075 return (1); 01076 } 01077 01078 return (0); 01079 } 01080 01088 int GS_get_SDscale(float *scale) 01089 { 01090 *scale = gsdiff_get_SDscale(); 01091 01092 return (1); 01093 } 01094 01102 int GS_update_normals(int id) 01103 { 01104 geosurf *gs; 01105 01106 gs = gs_get_surf(id); 01107 01108 return (gs_calc_normals(gs)); 01109 } 01110 01123 int GS_get_att(int id, int att, int *set, float *constant, char *mapname) 01124 { 01125 int src; 01126 geosurf *gs; 01127 01128 gs = gs_get_surf(id); 01129 if (gs) { 01130 if (-1 != (src = gs_get_att_src(gs, att))) { 01131 *set = src; 01132 01133 if (src == CONST_ATT) { 01134 *constant = gs->att[att].constant; 01135 } 01136 else if (src == MAP_ATT) { 01137 strcpy(mapname, gsds_get_name(gs->att[att].hdata)); 01138 } 01139 01140 return (1); 01141 } 01142 01143 return (-1); 01144 } 01145 01146 return (-1); 01147 } 01148 01166 int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y) 01167 { 01168 int offset, drow, dcol, vrow, vcol; 01169 float ftmp, pt[3]; 01170 typbuff *buff; 01171 geosurf *gs; 01172 01173 *catstr = '\0'; 01174 gs = gs_get_surf(id); 01175 01176 if (NULL == gs) { 01177 return -1; 01178 } 01179 01180 pt[X] = x; 01181 pt[Y] = y; 01182 01183 gsd_real2surf(gs, pt); 01184 if (gs_point_is_masked(gs, pt)) { 01185 return -1; 01186 } 01187 01188 if (!in_vregion(gs, pt)) { 01189 return -1; 01190 } 01191 01192 if (MAP_ATT != gs_get_att_src(gs, att)) { 01193 sprintf(catstr, _("no category info")); 01194 return -1; 01195 } 01196 01197 buff = gs_get_att_typbuff(gs, att, 0); 01198 01199 vrow = Y2VROW(gs, pt[Y]); 01200 vcol = X2VCOL(gs, pt[X]); 01201 drow = VROW2DROW(gs, vrow); 01202 dcol = VCOL2DCOL(gs, vcol); 01203 01204 offset = DRC2OFF(gs, drow, dcol); 01205 01206 if (GET_MAPATT(buff, offset, ftmp)) { 01207 return 01208 (Gs_get_cat_label(gsds_get_name(gs->att[att].hdata), 01209 drow, dcol, catstr)); 01210 } 01211 01212 sprintf(catstr, _("no data")); 01213 01214 return 1; 01215 } 01216 01229 int GS_get_norm_at_xy(int id, float x, float y, float *nv) 01230 { 01231 int offset, drow, dcol, vrow, vcol; 01232 float pt[3]; 01233 geosurf *gs; 01234 01235 gs = gs_get_surf(id); 01236 01237 if (NULL == gs) { 01238 return (-1); 01239 } 01240 01241 if (gs->norm_needupdate) { 01242 gs_calc_normals(gs); 01243 } 01244 01245 pt[X] = x; 01246 pt[Y] = y; 01247 01248 gsd_real2surf(gs, pt); 01249 if (gs_point_is_masked(gs, pt)) { 01250 return (-1); 01251 } 01252 01253 if (!in_vregion(gs, pt)) { 01254 return (-1); 01255 } 01256 01257 vrow = Y2VROW(gs, pt[Y]); 01258 vcol = X2VCOL(gs, pt[X]); 01259 drow = VROW2DROW(gs, vrow); 01260 dcol = VCOL2DCOL(gs, vcol); 01261 01262 offset = DRC2OFF(gs, drow, dcol); 01263 01264 if (gs->norms) { 01265 FNORM(gs->norms[offset], nv); 01266 } 01267 else { 01268 /* otherwise must be a constant */ 01269 nv[0] = 0.0; 01270 nv[1] = 0.0; 01271 nv[2] = 1.0; 01272 } 01273 01274 return (1); 01275 } 01276 01293 int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y) 01294 { 01295 int offset, drow, dcol, vrow, vcol; 01296 float ftmp, pt[3]; 01297 typbuff *buff; 01298 geosurf *gs; 01299 01300 *valstr = '\0'; 01301 gs = gs_get_surf(id); 01302 01303 if (NULL == gs) { 01304 return -1; 01305 } 01306 01307 pt[X] = x; 01308 pt[Y] = y; 01309 01310 gsd_real2surf(gs, pt); 01311 01312 if (gs_point_is_masked(gs, pt)) { 01313 return -1; 01314 } 01315 01316 if (!in_vregion(gs, pt)) { 01317 return (-1); 01318 } 01319 01320 if (CONST_ATT == gs_get_att_src(gs, att)) { 01321 if (att == ATT_COLOR) { 01322 int r, g, b, i; 01323 01324 i = gs->att[att].constant; 01325 sprintf(valstr, "R%d G%d B%d", 01326 INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b)); 01327 } 01328 else { 01329 sprintf(valstr, "%f", gs->att[att].constant); 01330 } 01331 01332 return 1; 01333 } 01334 else if (MAP_ATT != gs_get_att_src(gs, att)) { 01335 return -1; 01336 } 01337 01338 buff = gs_get_att_typbuff(gs, att, 0); 01339 01340 vrow = Y2VROW(gs, pt[Y]); 01341 vcol = X2VCOL(gs, pt[X]); 01342 drow = VROW2DROW(gs, vrow); 01343 dcol = VCOL2DCOL(gs, vcol); 01344 01345 offset = DRC2OFF(gs, drow, dcol); 01346 01347 if (GET_MAPATT(buff, offset, ftmp)) { 01348 if (att == ATT_COLOR) { 01349 int r, g, b, i; 01350 01351 i = gs_mapcolor(gs_get_att_typbuff(gs, ATT_COLOR, 0), 01352 &(gs->att[ATT_COLOR]), offset); 01353 sprintf(valstr, "R%d G%d B%d", 01354 INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b)); 01355 } 01356 else { 01357 sprintf(valstr, "%f", ftmp); 01358 } 01359 01360 return (1); 01361 } 01362 01363 sprintf(valstr, "NULL"); 01364 01365 return (1); 01366 } 01367 01376 int GS_unset_att(int id, int att) 01377 { 01378 geosurf *gs; 01379 01380 gs = gs_get_surf(id); 01381 gs->mask_needupdate = 1; 01382 01383 return (gs_set_att_src(gs, att, NOTSET_ATT)); 01384 } 01385 01395 int GS_set_att_const(int id, int att, float constant) 01396 { 01397 geosurf *gs; 01398 int ret; 01399 01400 gs = gs_get_surf(id); 01401 ret = (gs_set_att_const(gs, att, constant)); 01402 01403 Gs_update_attrange(gs, att); 01404 01405 return (ret); 01406 } 01407 01419 int GS_set_maskmode(int id, int mode) 01420 { 01421 geosurf *gs; 01422 01423 gs = gs_get_surf(id); 01424 01425 if (gs) { 01426 gs->att[ATT_MASK].constant = mode; 01427 gs->mask_needupdate = 1; 01428 01429 return (mode); 01430 } 01431 01432 return (-1); 01433 } 01434 01444 int GS_get_maskmode(int id, int *mode) 01445 { 01446 geosurf *gs; 01447 01448 gs = gs_get_surf(id); 01449 01450 if (gs) { 01451 *mode = gs->att[ATT_MASK].constant; 01452 01453 return (1); 01454 } 01455 01456 return (-1); 01457 } 01458 01468 int GS_Set_ClientData(int id, void *clientd) 01469 { 01470 geosurf *gs; 01471 01472 gs = gs_get_surf(id); 01473 if (gs) { 01474 gs->clientdata = clientd; 01475 01476 return (1); 01477 } 01478 01479 return (-1); 01480 } 01481 01490 void *GS_Get_ClientData(int id) 01491 { 01492 geosurf *gs; 01493 01494 gs = gs_get_surf(id); 01495 if (gs) { 01496 return (gs->clientdata); 01497 } 01498 01499 return (NULL); 01500 } 01501 01507 int GS_num_surfs(void) 01508 { 01509 return (gs_num_surfaces()); 01510 } 01511 01522 int *GS_get_surf_list(int *numsurfs) 01523 { 01524 int i, *ret; 01525 01526 *numsurfs = Next_surf; 01527 01528 if (Next_surf) { 01529 ret = (int *)G_malloc(Next_surf * sizeof(int)); 01530 01531 for (i = 0; i < Next_surf; i++) { 01532 ret[i] = Surf_ID[i]; 01533 } 01534 01535 return (ret); 01536 } 01537 01538 return (NULL); 01539 } 01540 01549 int GS_delete_surface(int id) 01550 { 01551 int i, j, found = 0; 01552 01553 G_debug(3, "GS_delete_surface"); 01554 01555 if (GS_surf_exists(id)) { 01556 gs_delete_surf(id); 01557 01558 for (i = 0; i < Next_surf && !found; i++) { 01559 if (Surf_ID[i] == id) { 01560 found = 1; 01561 01562 for (j = i; j < Next_surf; j++) { 01563 Surf_ID[j] = Surf_ID[j + 1]; 01564 } 01565 } 01566 } 01567 01568 gv_update_drapesurfs(); 01569 01570 if (found) { 01571 --Next_surf; 01572 return (1); 01573 } 01574 } 01575 01576 return (-1); 01577 } 01578 01579 01590 int GS_load_att_map(int id, const char *filename, int att) 01591 { 01592 geosurf *gs; 01593 unsigned int changed; 01594 unsigned int atty; 01595 const char *mapset; 01596 struct Cell_head rast_head; 01597 int reuse, begin, hdata, ret, neg, has_null; 01598 typbuff *tbuff; 01599 01600 G_debug(3, "GS_load_att_map(): map=%s", filename); 01601 01602 reuse = ret = neg = has_null = 0; 01603 gs = gs_get_surf(id); 01604 01605 if (NULL == gs) { 01606 return -1; 01607 } 01608 01609 gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att || 01610 (gs->nz_topo && ATT_TOPO == att) || 01611 (gs->nz_color && ATT_COLOR == att)); 01612 01613 gs_set_att_src(gs, att, MAP_ATT); 01614 01615 /* Check against maps already loaded in memory */ 01616 /* if to be color attribute: 01617 - if packed color for another surface, OK to reuse 01618 - if unchanged, ok to reuse IF it's of type char (will have lookup) 01619 */ 01620 begin = hdata = 1; 01621 01622 /* Get MAPSET to ensure names are fully qualified */ 01623 mapset = G_find_cell2(filename, ""); 01624 if (mapset == NULL) { 01625 /* Check for valid filename */ 01626 G_warning("Raster map <%s> not found", filename); 01627 return -1; 01628 } 01629 01630 /* Check to see if map is in Region */ 01631 G_get_cellhd(filename, mapset, &rast_head); 01632 if (rast_head.north <= wind.south || 01633 rast_head.south >= wind.north || 01634 rast_head.east <= wind.west || rast_head.west >= wind.east) { 01635 01636 G_warning(_("Raster map <%s> is outside of current region. Load failed."), 01637 G_fully_qualified_name(filename, mapset)); 01638 } 01639 01640 while (!reuse && (0 < hdata)) { 01641 changed = CF_COLOR_PACKED; 01642 atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK; 01643 01644 if (0 < (hdata = gsds_findh(filename, &changed, &atty, begin))) { 01645 01646 G_debug(3, "GS_load_att_map(): %s already has data handle %d.CF=%x", 01647 filename, hdata, changed); 01648 01649 /* handle found */ 01650 if (ATT_COLOR == att) { 01651 if ((changed == CF_COLOR_PACKED) || 01652 (!changed && atty == ATTY_CHAR)) { 01653 reuse = 1; 01654 } 01655 } 01656 else if (atty == ATTY_MASK && att != ATT_MASK) { 01657 reuse = 0; 01658 /* should also free mask data & share new - but need backward 01659 reference? */ 01660 } 01661 else if (!changed) { 01662 reuse = 1; 01663 } 01664 } 01665 01666 begin = 0; 01667 } 01668 01669 if (reuse) { 01670 gs->att[att].hdata = hdata; 01671 gs_set_att_type(gs, att, atty); /* ?? */ 01672 01673 /* free lookup & set to NULL! */ 01674 if (atty == ATTY_INT) { 01675 if (gs->att[att].lookup) { 01676 free(gs->att[att].lookup); 01677 gs->att[att].lookup = NULL; 01678 } 01679 } 01680 /* TODO: FIX THIS stuff with lookup sharing! */ 01681 01682 G_debug(3, "GS_load_att_map(): %s is being reused. hdata=%d", 01683 filename, hdata); 01684 } 01685 else { 01686 G_debug(3, "GS_load_att_map(): %s not loaded in correct form - loading now", 01687 filename); 01688 01689 /* not loaded - need to get new dataset handle */ 01690 gs->att[att].hdata = gsds_newh(filename); 01691 01692 tbuff = gs_get_att_typbuff(gs, att, 1); 01693 01694 /* TODO: Provide mechanism for loading certain attributes at 01695 specified sizes, allow to scale or cap, or scale non-zero */ 01696 if (ATT_MASK == att) { 01697 atty = ATTY_MASK; 01698 } 01699 else { 01700 atty = Gs_numtype(filename, &neg); 01701 } 01702 01703 #ifdef MAYBE_LATER 01704 if (att == ATT_COLOR && atty == ATTY_SHORT) { 01705 atty = (neg ? ATTY_INT : ATTY_SHORT); 01706 } 01707 #endif 01708 01709 if (att == ATT_COLOR && atty == ATTY_SHORT) { 01710 atty = ATTY_INT; 01711 } 01712 01713 if (0 > gs_malloc_att_buff(gs, att, ATTY_NULL)) { 01714 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01715 } 01716 01717 switch (atty) { 01718 case ATTY_MASK: 01719 if (0 > gs_malloc_att_buff(gs, att, ATTY_MASK)) { 01720 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01721 } 01722 01723 ret = Gs_loadmap_as_bitmap(&wind, filename, tbuff->bm); 01724 01725 break; 01726 case ATTY_CHAR: 01727 if (0 > gs_malloc_att_buff(gs, att, ATTY_CHAR)) { 01728 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01729 } 01730 01731 ret = Gs_loadmap_as_char(&wind, filename, tbuff->cb, 01732 tbuff->nm, &has_null); 01733 01734 break; 01735 case ATTY_SHORT: 01736 if (0 > gs_malloc_att_buff(gs, att, ATTY_SHORT)) { 01737 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01738 } 01739 01740 ret = Gs_loadmap_as_short(&wind, filename, tbuff->sb, 01741 tbuff->nm, &has_null); 01742 break; 01743 case ATTY_FLOAT: 01744 if (0 > gs_malloc_att_buff(gs, att, ATTY_FLOAT)) { 01745 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01746 } 01747 01748 ret = Gs_loadmap_as_float(&wind, filename, tbuff->fb, 01749 tbuff->nm, &has_null); 01750 01751 break; 01752 case ATTY_INT: 01753 default: 01754 if (0 > gs_malloc_att_buff(gs, att, ATTY_INT)) { 01755 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01756 } 01757 01758 ret = Gs_loadmap_as_int(&wind, filename, tbuff->ib, 01759 tbuff->nm, &has_null); 01760 break; 01761 01762 } /* Done with switch */ 01763 01764 if (ret == -1) { 01765 gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL); 01766 return -1; 01767 } 01768 01769 G_debug(4, " has_null=%d", has_null); 01770 01771 if (!has_null) { 01772 gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL); 01773 } 01774 else { 01775 gs_update_curmask(gs); 01776 } 01777 01778 } /* end if not reuse */ 01779 01780 if (ATT_COLOR == att) { 01781 #ifdef MAYBE_LATER 01782 if (ATTY_INT == atty) { 01783 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols); 01784 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED); 01785 gs->att[att].lookup = NULL; 01786 } 01787 else { 01788 gs_malloc_lookup(gs, att); 01789 Gs_build_lookup(filename, gs->att[att].lookup); 01790 } 01791 #else 01792 01793 if (ATTY_CHAR == atty) { 01794 if (!gs->att[att].lookup) { 01795 /* might already exist if reusing */ 01796 gs_malloc_lookup(gs, att); 01797 Gs_build_256lookup(filename, gs->att[att].lookup); 01798 } 01799 } 01800 else if (ATTY_FLOAT == atty) { 01801 if (!reuse) { 01802 if (0 > gs_malloc_att_buff(gs, att, ATTY_INT)) { 01803 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map")); 01804 } 01805 01806 Gs_pack_colors_float(filename, tbuff->fb, tbuff->ib, 01807 gs->rows, gs->cols); 01808 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED); 01809 gsds_free_data_buff(gs->att[att].hdata, ATTY_FLOAT); 01810 gs->att[att].lookup = NULL; 01811 } 01812 } 01813 else { 01814 if (!reuse) { 01815 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols); 01816 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED); 01817 gs->att[att].lookup = NULL; 01818 } 01819 } 01820 #endif 01821 } 01822 01823 if (ATT_TOPO == att) { 01824 gs_init_normbuff(gs); 01825 /* S_DIFF: should also check here to see if this surface is a 01826 reference surface for scaled differences, if so update references 01827 to it */ 01828 } 01829 01830 if (ret < 0) { 01831 G_warning(_("Loading failed")); 01832 } 01833 01834 if (-1 == Gs_update_attrange(gs, att)) { 01835 G_warning(_("Error finding range")); 01836 } 01837 01838 return ret; 01839 } 01840 01846 void GS_draw_surf(int id) 01847 { 01848 geosurf *gs; 01849 01850 G_debug(3, "GS_draw_surf(): id=%d", id); 01851 01852 gs = gs_get_surf(id); 01853 if (gs) { 01854 gsd_shademodel(gs->draw_mode & DM_GOURAUD); 01855 01856 if (gs->draw_mode & DM_POLY) { 01857 gsd_surf(gs); 01858 } 01859 01860 if (gs->draw_mode & DM_WIRE) { 01861 gsd_wire_surf(gs); 01862 } 01863 01864 /* TODO: write wire/poly draw routines */ 01865 if (gs->draw_mode & DM_WIRE_POLY) { 01866 gsd_surf(gs); 01867 gsd_wire_surf(gs); 01868 } 01869 } 01870 01871 return; 01872 } 01873 01881 void GS_draw_wire(int id) 01882 { 01883 geosurf *gs; 01884 01885 G_debug(3, "GS_draw_wire(): id=%d", id); 01886 01887 gs = gs_get_surf(id); 01888 01889 if (gs) { 01890 gsd_wire_surf(gs); 01891 } 01892 01893 return; 01894 } 01895 01901 void GS_alldraw_wire(void) 01902 { 01903 geosurf *gs; 01904 int i; 01905 01906 for (i = 0; i < Next_surf; i++) { 01907 if ((gs = gs_get_surf(Surf_ID[i]))) { 01908 gsd_wire_surf(gs); 01909 } 01910 } 01911 01912 return; 01913 } 01914 01918 void GS_alldraw_surf(void) 01919 { 01920 int i; 01921 01922 for (i = 0; i < Next_surf; i++) { 01923 GS_draw_surf(Surf_ID[i]); 01924 } 01925 01926 return; 01927 } 01928 01935 void GS_set_exag(int id, float exag) 01936 { 01937 geosurf *gs; 01938 01939 G_debug(3, "GS_set_exag"); 01940 01941 gs = gs_get_surf(id); 01942 01943 if (gs) { 01944 if (gs->z_exag != exag) { 01945 gs->norm_needupdate = 1; 01946 } 01947 01948 gs->z_exag = exag; 01949 } 01950 01951 return; 01952 } 01953 01959 void GS_set_global_exag(float exag) 01960 { 01961 01962 G_debug(3, "GS_set_global_exag"); 01963 01964 Gv.vert_exag = exag; 01965 /* GL_NORMALIZE */ 01966 /* Only need to update norms gs_norms.c 01967 * if exag is used in norm equation which 01968 * it is not! If GL_NORMALIZE is disabled 01969 * will need to include. 01970 gs_setall_norm_needupdate(); 01971 */ 01972 01973 return; 01974 } 01975 01981 float GS_global_exag(void) 01982 { 01983 G_debug(3, "GS_global_exag(): %g", Gv.vert_exag); 01984 01985 return (Gv.vert_exag); 01986 } 01987 01996 void GS_set_wire_color(int id, int colr) 01997 { 01998 geosurf *gs; 01999 02000 G_debug(3, "GS_set_wire_color"); 02001 02002 gs = gs_get_surf(id); 02003 02004 if (gs) { 02005 gs->wire_color = colr; 02006 } 02007 02008 return; 02009 } 02010 02020 int GS_get_wire_color(int id, int *colr) 02021 { 02022 geosurf *gs; 02023 02024 gs = gs_get_surf(id); 02025 02026 if (gs) { 02027 *colr = gs->wire_color; 02028 02029 return (1); 02030 } 02031 02032 return (-1); 02033 } 02034 02043 int GS_setall_drawmode(int mode) 02044 { 02045 int i; 02046 02047 for (i = 0; i < Next_surf; i++) { 02048 if (0 != GS_set_drawmode(Surf_ID[i], mode)) { 02049 return (-1); 02050 } 02051 } 02052 02053 return (0); 02054 } 02055 02065 int GS_set_drawmode(int id, int mode) 02066 { 02067 geosurf *gs; 02068 02069 G_debug(3, "GS_set_drawmode(): id=%d mode=%d", id, mode); 02070 02071 gs = gs_get_surf(id); 02072 02073 if (gs) { 02074 gs->draw_mode = mode; 02075 02076 return (0); 02077 } 02078 02079 return (-1); 02080 } 02081 02091 int GS_get_drawmode(int id, int *mode) 02092 { 02093 geosurf *gs; 02094 02095 gs = gs_get_surf(id); 02096 02097 if (gs) { 02098 *mode = gs->draw_mode; 02099 02100 return (1); 02101 } 02102 02103 return (-1); 02104 } 02105 02113 void GS_set_nozero(int id, int att, int mode) 02114 { 02115 geosurf *gs; 02116 02117 G_debug(3, "GS_set_nozero"); 02118 02119 gs = gs_get_surf(id); 02120 02121 if (gs) { 02122 if (att == ATT_TOPO) { 02123 gs->nz_topo = mode; 02124 gs->mask_needupdate = 1; 02125 } 02126 02127 if (att == ATT_COLOR) { 02128 gs->nz_color = mode; 02129 gs->mask_needupdate = 1; 02130 } 02131 } 02132 02133 return; 02134 } 02135 02146 int GS_get_nozero(int id, int att, int *mode) 02147 { 02148 geosurf *gs; 02149 02150 G_debug(3, "GS_set_nozero"); 02151 02152 gs = gs_get_surf(id); 02153 02154 if (gs) { 02155 if (att == ATT_TOPO) { 02156 *mode = gs->nz_topo; 02157 } 02158 else if (att == ATT_COLOR) { 02159 *mode = gs->nz_color; 02160 } 02161 else { 02162 return (-1); 02163 } 02164 02165 return (1); 02166 } 02167 02168 return (-1); 02169 } 02170 02180 int GS_setall_drawres(int xres, int yres, int xwire, int ywire) 02181 { 02182 int i; 02183 02184 for (i = 0; i < Next_surf; i++) { 02185 if (0 != GS_set_drawres(Surf_ID[i], xres, yres, xwire, ywire)) { 02186 return (-1); 02187 } 02188 } 02189 02190 return (0); 02191 } 02192 02203 int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire) 02204 { 02205 geosurf *gs; 02206 02207 G_debug(3, "GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d", 02208 id, xres, yres, xwire, ywire); 02209 02210 if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) { 02211 return (-1); 02212 } 02213 02214 gs = gs_get_surf(id); 02215 02216 if (gs) { 02217 if (gs->x_mod != xres || gs->y_mod != yres) { 02218 gs->norm_needupdate = 1; 02219 } 02220 02221 gs->x_mod = xres; 02222 gs->y_mod = yres; 02223 gs->x_modw = xwire; 02224 gs->y_modw = ywire; 02225 } 02226 02227 return (0); 02228 } 02229 02237 void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire) 02238 { 02239 geosurf *gs; 02240 02241 G_debug(3, "GS_get_drawres"); 02242 02243 gs = gs_get_surf(id); 02244 02245 if (gs) { 02246 *xres = gs->x_mod; 02247 *yres = gs->y_mod; 02248 *xwire = gs->x_modw; 02249 *ywire = gs->y_modw; 02250 } 02251 02252 return; 02253 } 02254 02261 void GS_get_dims(int id, int *rows, int *cols) 02262 { 02263 geosurf *gs; 02264 02265 gs = gs_get_surf(id); 02266 02267 if (gs) { 02268 *rows = gs->rows; 02269 *cols = gs->cols; 02270 } 02271 02272 return; 02273 } 02274 02288 int GS_get_exag_guess(int id, float *exag) 02289 { 02290 geosurf *gs; 02291 float guess; 02292 02293 gs = gs_get_surf(id); 02294 guess = 1.0; 02295 02296 /* if gs is type const return guess = 1.0 */ 02297 if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) { 02298 return (1); 02299 } 02300 02301 if (gs) { 02302 if (gs->zrange_nz == 0.0) { 02303 *exag = 0.0; 02304 02305 return (1); 02306 } 02307 02308 G_debug(3, "GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim); 02309 02310 while (gs->zrange_nz * guess / Longdim >= .25) { 02311 guess *= .1; 02312 02313 G_debug(3, "GS_get_exag_guess(): %f", guess); 02314 } 02315 02316 while (gs->zrange_nz * guess / Longdim < .025) { 02317 guess *= 10.; 02318 02319 G_debug(3, "GS_get_exag_guess(): %f", guess); 02320 } 02321 02322 *exag = guess; 02323 02324 return (1); 02325 } 02326 02327 return (-1); 02328 } 02329 02338 void GS_get_zrange_nz(float *min, float *max) 02339 { 02340 int i, first = 1; 02341 geosurf *gs; 02342 02343 for (i = 0; i < Next_surf; i++) { 02344 if ((gs = gs_get_surf(Surf_ID[i]))) { 02345 if (first) { 02346 first = 0; 02347 *min = gs->zmin_nz; 02348 *max = gs->zmax_nz; 02349 } 02350 02351 if (gs->zmin_nz < *min) { 02352 *min = gs->zmin_nz; 02353 } 02354 02355 if (gs->zmax_nz > *max) { 02356 *max = gs->zmax_nz; 02357 } 02358 } 02359 } 02360 02361 G_debug(3, "GS_get_zrange_nz(): min=%g max=%g", *min, *max); 02362 02363 return; 02364 } 02365 02372 void GS_set_trans(int id, float xtrans, float ytrans, float ztrans) 02373 { 02374 geosurf *gs; 02375 02376 G_debug(3, "GS_set_trans"); 02377 02378 gs = gs_get_surf(id); 02379 02380 if (gs) { 02381 gs->x_trans = xtrans; 02382 gs->y_trans = ytrans; 02383 gs->z_trans = ztrans; 02384 } 02385 02386 return; 02387 } 02388 02395 void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans) 02396 { 02397 geosurf *gs; 02398 02399 G_debug(3, "GS_get_trans"); 02400 02401 gs = gs_get_surf(id); 02402 02403 if (gs) { 02404 *xtrans = gs->x_trans; 02405 *ytrans = gs->y_trans; 02406 *ztrans = gs->z_trans; 02407 } 02408 02409 return; 02410 } 02411 02412 02418 unsigned int GS_default_draw_color(void) 02419 { 02420 02421 G_debug(3, "GS_default_draw_color"); 02422 02423 return ((unsigned int)Gd.bgcol); 02424 } 02425 02431 unsigned int GS_background_color(void) 02432 { 02433 return ((unsigned int)Gd.bgcol); 02434 } 02435 02441 void GS_set_draw(int where) 02442 { 02443 Buffermode = where; 02444 02445 switch (where) { 02446 case GSD_BOTH: 02447 gsd_frontbuffer(1); 02448 gsd_backbuffer(1); 02449 02450 break; 02451 case GSD_FRONT: 02452 gsd_frontbuffer(1); 02453 gsd_backbuffer(0); 02454 02455 break; 02456 case GSD_BACK: 02457 default: 02458 gsd_frontbuffer(0); 02459 gsd_backbuffer(1); 02460 02461 break; 02462 } 02463 02464 return; 02465 } 02466 02467 /* 02468 \brief Ready to draw 02469 */ 02470 void GS_ready_draw(void) 02471 { 02472 02473 G_debug(3, "GS_ready_draw"); 02474 02475 gsd_set_view(&Gv, &Gd); 02476 02477 return; 02478 } 02479 02483 void GS_done_draw(void) 02484 { 02485 02486 G_debug(3, "GS_done_draw"); 02487 02488 if (GSD_BACK == Buffermode) { 02489 gsd_swapbuffers(); 02490 } 02491 02492 gsd_flush(); 02493 02494 return; 02495 } 02496 02502 void GS_set_focus(float *realto) 02503 { 02504 02505 G_debug(3, "GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]); 02506 02507 Gv.infocus = 1; 02508 GS_v3eq(Gv.real_to, realto); 02509 02510 gsd_set_view(&Gv, &Gd); 02511 02512 return; 02513 } 02514 02520 void GS_set_focus_real(float *realto) 02521 { 02522 02523 G_get_set_window(&wind); 02524 realto[X] = realto[X] - wind.west - (wind.ew_res / 2.); 02525 realto[Y] = realto[Y] - wind.south - (wind.ns_res / 2.); 02526 02527 Gv.infocus = 1; 02528 GS_v3eq(Gv.real_to, realto); 02529 02530 gsd_set_view(&Gv, &Gd); 02531 02532 return; 02533 } 02534 02535 02545 int GS_get_focus(float *realto) 02546 { 02547 02548 G_debug(3, "GS_get_focus"); 02549 02550 if (Gv.infocus) { 02551 if (realto) { 02552 GS_v3eq(realto, Gv.real_to); 02553 } 02554 } 02555 02556 return (Gv.infocus); 02557 } 02558 02564 void GS_set_focus_center_map(int id) 02565 { 02566 float center[3]; 02567 geosurf *gs; 02568 02569 G_debug(3, "GS_set_focus_center_map"); 02570 02571 gs = gs_get_surf(id); 02572 02573 if (gs) { 02574 center[X] = (gs->xmax - gs->xmin) / 2.; 02575 center[Y] = (gs->ymax - gs->ymin) / 2.; 02576 center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.; 02577 02578 /* not yet working 02579 buff = gs_get_att_typbuff(gs, ATT_TOPO, 0); 02580 offset = gs->rows*gs->cols/2 + gs->cols/2; 02581 if (buff) 02582 { 02583 if (GET_MAPATT(buff, offset, tmp)) 02584 { 02585 center[Z] = tmp; 02586 } 02587 } 02588 */ 02589 02590 GS_set_focus(center); 02591 } 02592 } 02593 02599 void GS_moveto(float *pt) 02600 { 02601 float ft[3]; 02602 02603 G_debug(3, "GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]); 02604 02605 if (Gv.infocus) { 02606 GS_v3eq(Gv.from_to[FROM], pt); 02607 /* 02608 GS_v3eq(Gv.from_to[TO], Gv.real_to); 02609 */ 02610 GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]); 02611 /* update inclination, look_dir if we're keeping these */ 02612 } 02613 else { 02614 GS_v3eq(ft, Gv.from_to[TO]); 02615 GS_v3sub(ft, Gv.from_to[FROM]); 02616 GS_v3eq(Gv.from_to[FROM], pt); 02617 GS_v3eq(Gv.from_to[TO], pt); 02618 GS_v3add(Gv.from_to[TO], ft); 02619 } 02620 02621 return; 02622 } 02623 02629 void GS_moveto_real(float *pt) 02630 { 02631 gsd_real2model(pt); 02632 GS_moveto(pt); 02633 02634 return; 02635 } 02636 02648 int GS_get_zextents(int id, float *min, float *max, float *mid) 02649 { 02650 geosurf *gs; 02651 02652 if (NULL == (gs = gs_get_surf(id))) { 02653 return (-1); 02654 } 02655 02656 G_debug(3, "GS_get_zextents(): id=%d", id); 02657 02658 return (gs_get_zextents(gs, min, max, mid)); 02659 } 02660 02671 int GS_get_zrange(float *min, float *max, int doexag) 02672 { 02673 int ret_surf, ret_vol; 02674 float surf_min, surf_max; 02675 float vol_min, vol_max; 02676 02677 ret_surf = gs_get_zrange(&surf_min, &surf_max); 02678 ret_vol = gvl_get_zrange(&vol_min, &vol_max); 02679 02680 if (ret_surf > 0 && ret_vol > 0) { 02681 *min = (surf_min < vol_min) ? surf_min : vol_min; 02682 *max = (surf_max < vol_max) ? surf_max : vol_max; 02683 } 02684 else if (ret_surf > 0) { 02685 *min = surf_min; 02686 *max = surf_max; 02687 } 02688 else if (ret_vol > 0) { 02689 *min = vol_min; 02690 *max = vol_max; 02691 } 02692 02693 if (doexag) { 02694 *min *= Gv.vert_exag; 02695 *max *= Gv.vert_exag; 02696 } 02697 02698 G_debug(3, "GS_get_zrange(): min=%g max=%g", *min, *max); 02699 return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1)); 02700 } 02701 02707 void GS_get_from(float *fr) 02708 { 02709 GS_v3eq(fr, Gv.from_to[FROM]); 02710 02711 G_debug(3, "GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]); 02712 02713 return; 02714 } 02715 02721 void GS_get_from_real(float *fr) 02722 { 02723 GS_v3eq(fr, Gv.from_to[FROM]); 02724 gsd_model2real(fr); 02725 02726 return; 02727 } 02728 02734 void GS_get_to_real(float *to) 02735 { 02736 float realto[3]; 02737 02738 G_get_set_window(&wind); 02739 GS_get_focus(realto); 02740 to[X] = realto[X] + wind.west + (wind.ew_res / 2.); 02741 to[Y] = realto[Y] + wind.south + (wind.ns_res / 2.); 02742 to[Z] = realto[Z]; 02743 02744 return; 02745 } 02746 02747 02754 void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy) 02755 { 02756 GLint tmp[4]; 02757 GLint num[2]; 02758 02759 gsd_getViewport(tmp, num); 02760 *a = tmp[0]; 02761 *b = tmp[1]; 02762 *c = tmp[2]; 02763 *d = tmp[3]; 02764 *maxx = num[0]; 02765 *maxy = num[1]; 02766 02767 return; 02768 } 02769 02777 void GS_get_to(float *to) 02778 { 02779 G_debug(3, "GS_get_to"); 02780 02781 GS_v3eq(to, Gv.from_to[TO]); 02782 02783 return; 02784 } 02785 02791 void GS_get_viewdir(float *dir) 02792 { 02793 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir); 02794 02795 return; 02796 } 02797 02805 void GS_set_viewdir(float *dir) 02806 { 02807 float tmp[3]; 02808 02809 GS_v3eq(tmp, dir); 02810 GS_v3norm(tmp); 02811 GS_v3eq(Gv.from_to[TO], Gv.from_to[FROM]); 02812 GS_v3add(Gv.from_to[TO], tmp); 02813 02814 GS_set_nofocus(); 02815 gsd_set_view(&Gv, &Gd); 02816 02817 return; 02818 } 02819 02825 void GS_set_fov(int fov) 02826 { 02827 Gv.fov = fov; 02828 02829 return; 02830 } 02831 02837 int GS_get_fov(void) 02838 { 02839 return (Gv.fov); 02840 } 02841 02847 int GS_get_twist(void) 02848 { 02849 return (Gv.twist); 02850 } 02851 02859 void GS_set_twist(int t) 02860 { 02861 Gv.twist = t; 02862 02863 return; 02864 } 02865 02869 void GS_set_nofocus(void) 02870 { 02871 G_debug(3, "GS_set_nofocus"); 02872 02873 Gv.infocus = 0; 02874 02875 return; 02876 } 02877 02883 void GS_set_infocus(void) 02884 { 02885 G_debug(3, "GS_set_infocus"); 02886 02887 Gv.infocus = 1; 02888 02889 return; 02890 } 02891 02897 void GS_set_viewport(int left, int right, int bottom, int top) 02898 { 02899 G_debug(3, "GS_set_viewport(): left=%d, right=%d, " 02900 "bottom=%d, top=%d", left, right, bottom, top); 02901 02902 gsd_viewport(left, right, bottom, top); 02903 02904 return; 02905 } 02906 02921 int GS_look_here(int sx, int sy) 02922 { 02923 float x, y, z, len, los[2][3]; 02924 Point3 realto, dir; 02925 int id; 02926 geosurf *gs; 02927 02928 if (GS_get_selected_point_on_surface(sx, sy, &id, &x, &y, &z)) { 02929 gs = gs_get_surf(id); 02930 if (gs) { 02931 realto[X] = x - gs->ox + gs->x_trans; 02932 realto[Y] = y - gs->oy + gs->y_trans; 02933 realto[Z] = z + gs->z_trans; 02934 GS_set_focus(realto); 02935 02936 return (1); 02937 } 02938 } 02939 else { 02940 if (gsd_get_los(los, (short)sx, (short)sy)) { 02941 len = GS_distance(Gv.from_to[FROM], Gv.real_to); 02942 GS_v3dir(los[FROM], los[TO], dir); 02943 GS_v3mult(dir, len); 02944 realto[X] = Gv.from_to[FROM][X] + dir[X]; 02945 realto[Y] = Gv.from_to[FROM][Y] + dir[Y]; 02946 realto[Z] = Gv.from_to[FROM][Z] + dir[Z]; 02947 GS_set_focus(realto); 02948 02949 return (1); 02950 } 02951 } 02952 02953 return (0); 02954 } 02955 02970 int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x, 02971 float *y, float *z) 02972 { 02973 float los[2][3], find_dist[MAX_SURFS], closest; 02974 Point3 point, tmp, finds[MAX_SURFS]; 02975 int surfs[MAX_SURFS], i, iclose, numhits = 0; 02976 geosurf *gs; 02977 02978 /* returns surface-world coords */ 02979 gsd_get_los(los, (short)sx, (short)sy); 02980 02981 if (!gs_setlos_enterdata(los)) { 02982 G_debug(3, "gs_setlos_enterdata(los): returns false"); 02983 return (0); 02984 } 02985 02986 for (i = 0; i < Next_surf; i++) { 02987 G_debug(3, "id=%d", i); 02988 02989 gs = gs_get_surf(Surf_ID[i]); 02990 02991 /* los_intersect expects surf-world coords (xy transl, no scaling) */ 02992 02993 #if NVIZ_HACK 02994 if (gs_los_intersect1(Surf_ID[i], los, point)) { 02995 #else 02996 if (gs_los_intersect(Surf_ID[i], los, point)) { 02997 #endif 02998 if (!gs_point_is_masked(gs, point)) { 02999 GS_v3eq(tmp, point); 03000 tmp[X] += gs->x_trans; 03001 tmp[Y] += gs->y_trans; 03002 tmp[Z] += gs->z_trans; 03003 find_dist[numhits] = GS_distance(los[FROM], tmp); 03004 gsd_surf2real(gs, point); 03005 GS_v3eq(finds[numhits], point); 03006 surfs[numhits] = Surf_ID[i]; 03007 numhits++; 03008 } 03009 } 03010 } 03011 03012 for (i = iclose = 0; i < numhits; i++) { 03013 closest = find_dist[iclose]; 03014 03015 if (find_dist[i] < closest) { 03016 iclose = i; 03017 } 03018 } 03019 03020 if (numhits) { 03021 *x = finds[iclose][X]; 03022 *y = finds[iclose][Y]; 03023 *z = finds[iclose][Z]; 03024 *id = surfs[iclose]; 03025 } 03026 03027 G_debug(3, "NumHits %d, next %d", numhits, Next_surf); 03028 03029 return (numhits); 03030 } 03031 03038 void GS_set_cplane_rot(int num, float dx, float dy, float dz) 03039 { 03040 gsd_cplane_setrot(num, dx, dy, dz); 03041 03042 return; 03043 } 03044 03051 void GS_set_cplane_trans(int num, float dx, float dy, float dz) 03052 { 03053 gsd_cplane_settrans(num, dx, dy, dz); 03054 03055 return; 03056 } 03057 03058 03064 void GS_draw_cplane(int num) 03065 { 03066 geosurf *gsurfs[MAX_SURFS]; 03067 int nsurfs; 03068 03069 nsurfs = gs_num_surfaces(); 03070 if (2 == nsurfs) { 03071 /* testing */ 03072 gs_getall_surfaces(gsurfs); 03073 gsd_draw_cplane_fence(gsurfs[0], gsurfs[1], num); 03074 } 03075 else { 03076 gsd_draw_cplane(num); 03077 } 03078 03079 return; 03080 } 03081 03091 int GS_draw_cplane_fence(int hs1, int hs2, int num) 03092 { 03093 geosurf *gs1, *gs2; 03094 03095 if (NULL == (gs1 = gs_get_surf(hs1))) { 03096 return (0); 03097 } 03098 03099 if (NULL == (gs2 = gs_get_surf(hs2))) { 03100 return (0); 03101 } 03102 03103 gsd_draw_cplane_fence(gs1, gs2, num); 03104 03105 return (1); 03106 } 03107 03111 void GS_alldraw_cplane_fences(void) 03112 { 03113 int onstate[MAX_CPLANES], i; 03114 03115 gsd_get_cplanes_state(onstate); 03116 03117 for (i = 0; i < MAX_CPLANES; i++) { 03118 if (onstate[i]) { 03119 GS_draw_cplane_fence(Surf_ID[0], Surf_ID[1], i); 03120 } 03121 } 03122 03123 return; 03124 } 03125 03131 void GS_set_cplane(int num) 03132 { 03133 gsd_cplane_on(num); 03134 03135 return; 03136 } 03137 03143 void GS_unset_cplane(int num) 03144 { 03145 gsd_cplane_off(num); 03146 03147 return; 03148 } 03149 03156 void GS_get_scale(float *sx, float *sy, float *sz, int doexag) 03157 { 03158 float zexag; 03159 03160 zexag = doexag ? Gv.vert_exag : 1.; 03161 *sx = *sy = Gv.scale; 03162 *sz = Gv.scale * zexag; 03163 03164 return; 03165 } 03166 03172 void GS_set_fencecolor(int mode) 03173 { 03174 gsd_setfc(mode); 03175 03176 return; 03177 } 03178 03184 int GS_get_fencecolor(void) 03185 { 03186 return gsd_getfc(); 03187 } 03188 03201 int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2, 03202 float *dist, int use_exag) 03203 { 03204 geosurf *gs; 03205 float p1[2], p2[2]; 03206 03207 gs = gs_get_surf(hs); 03208 if (gs == NULL) { 03209 return 0; 03210 } 03211 03212 p1[X] = x1; 03213 p1[Y] = y1; 03214 p2[X] = x2; 03215 p2[Y] = y2; 03216 gsd_real2surf(gs, p1); 03217 gsd_real2surf(gs, p2); 03218 03219 G_debug(3, "GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f", 03220 hs, x1, y1, x2, y2); 03221 return gs_distance_onsurf(gs, p1, p2, dist, use_exag); 03222 } 03223 03232 int GS_save_3dview(const char *vname, int surfid) 03233 { 03234 return (Gs_save_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid))); 03235 } 03236 03245 int GS_load_3dview(const char *vname, int surfid) 03246 { 03247 03248 return (Gs_load_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid))); 03249 03250 /* what to do about lights - I guess, delete all & 03251 create any that exist in 3dview file */ 03252 } 03253 03254 /************************************************************************ 03255 * Following routines use Graphics Library 03256 ************************************************************************/ 03257 03263 void GS_init_view(void) 03264 { 03265 static int first = 1; 03266 03267 G_debug(3, "GS_init_view"); 03268 03269 if (first) { 03270 first = 0; 03271 glMatrixMode(GL_MODELVIEW); 03272 03273 /* OGLXXX doublebuffer: use GLX_DOUBLEBUFFER in attriblist */ 03274 /* glxChooseVisual(*dpy, screen, *attriblist); */ 03275 /* OGLXXX 03276 * ZMIN not needed -- always 0. 03277 * ZMAX not needed -- always 1. 03278 * getgdesc other posiblilties: 03279 * glxGetConfig(); 03280 * glxGetCurrentContext(); 03281 * glxGetCurrentDrawable(); 03282 * GLint gdtmp; 03283 * getgdesc other posiblilties: 03284 * glxGetConfig(); 03285 * glxGetCurrentContext(); 03286 * glxGetCurrentDrawable(); 03287 * GLint gdtmp; 03288 * glDepthRange params must be scaled to [0, 1] 03289 */ 03290 glDepthRange(0.0, 1.0); 03291 glEnable(GL_DEPTH_TEST); 03292 glDepthFunc(GL_LEQUAL); 03293 /* } */ 03294 03295 /* replace these with something meaningful */ 03296 Gv.fov = 450; 03297 Gv.twist = 0; 03298 Gv.from_to[FROM][X] = Gv.from_to[FROM][Y] = 03299 Gv.from_to[FROM][Z] = GS_UNIT_SIZE / 2.; 03300 03301 Gv.from_to[TO][X] = GS_UNIT_SIZE / 2.; 03302 Gv.from_to[TO][Y] = GS_UNIT_SIZE / 2.; 03303 Gv.from_to[TO][Z] = 0.; 03304 Gv.from_to[TO][W] = Gv.from_to[FROM][W] = 1.; 03305 03306 Gv.real_to[W] = 1.; 03307 Gv.vert_exag = 1.; 03308 03309 GS_v3eq(Gv.real_to, Gv.from_to[TO]); 03310 GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]); 03311 03312 /* 03313 Gd.nearclip = 50; 03314 Gd.farclip = 10000.; 03315 */ 03316 Gd.nearclip = 10.; 03317 Gd.farclip = 10000.; 03318 Gd.aspect = (float)GS_get_aspect(); 03319 03320 GS_set_focus(Gv.real_to); 03321 } 03322 03323 return; 03324 } 03325 03331 void GS_clear(int col) 03332 { 03333 G_debug(3, "GS_clear"); 03334 03335 col = col | 0xFF000000; 03336 03337 /* OGLXXX 03338 * change glClearDepth parameter to be in [0, 1] 03339 * ZMAX not needed -- always 1. 03340 * getgdesc other posiblilties: 03341 * glxGetConfig(); 03342 * glxGetCurrentContext(); 03343 * glxGetCurrentDrawable(); 03344 * GLint gdtmp; 03345 */ 03346 glClearDepth(1.0); 03347 glClearColor(((float)((col) & 0xff)) / 255., 03348 (float)((col) >> 8 & 0xff) / 255., 03349 (float)((col) >> 16 & 0xff) / 255., 03350 (float)((col) >> 24 & 0xff) / 255.); 03351 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 03352 03353 Gd.bgcol = col; 03354 Modelshowing = 0; 03355 gsd_flush(); 03356 03357 return; 03358 } 03359 03365 double GS_get_aspect(void) 03366 { 03367 int left, right, bottom, top; 03368 GLint tmp[4]; 03369 03370 /* OGLXXX 03371 * get GL_VIEWPORT: 03372 * You can probably do better than this. 03373 */ 03374 glGetIntegerv(GL_VIEWPORT, tmp); 03375 left = tmp[0]; 03376 right = tmp[0] + tmp[2] - 1; 03377 bottom = tmp[1]; 03378 top = tmp[1] + tmp[3] - 1; 03379 03380 G_debug(3, "GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d", 03381 left, right, top, bottom); 03382 03383 return ((double)(right - left) / (top - bottom)); 03384 } 03385 03393 int GS_has_transparency(void) 03394 { 03395 /* OGLXXX 03396 * getgdesc other posiblilties: 03397 * glxGetConfig(); 03398 * glxGetCurrentContext(); 03399 * glxGetCurrentDrawable(); 03400 * GLint gdtmp; 03401 * blending is ALWAYS supported. 03402 * This function returns whether it is enabled. 03403 * return((glGetIntegerv(GL_BLEND, &gdtmp), gdtmp)); 03404 */ 03405 03406 return (1); 03407 }