35 #include <grass/config.h>
37 #if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
40 #elif defined(OPENGL_AQUA)
41 #include <OpenGL/gl.h>
42 #include <OpenGL/glu.h>
45 #include <grass/gis.h>
46 #include <grass/gstypes.h>
47 #include <grass/glocale.h>
63 static int Surf_ID[MAX_SURFS];
64 static int Next_surf = 0;
65 static int SDref_surf = 0;
68 static float Default_const[MAX_ATTS];
69 static float Default_nulls[MAX_ATTS];
75 static float Region[4];
78 static struct Cell_head wind;
79 static int Buffermode;
80 static int Numlights = 0;
81 static int Modelshowing = 0;
101 Region[0] = wind.north;
102 Region[1] = wind.south;
103 Region[2] = wind.west;
104 Region[3] = wind.east;
107 if ((wind.east - wind.west) > (wind.north - wind.south)) {
108 Longdim = (wind.east - wind.west);
111 Longdim = (wind.north - wind.south);
114 Gv.scale = GS_UNIT_SIZE / Longdim;
139 G_debug(3,
"GS_get_longdim(): dim=%g", *dim);
171 G_debug(3,
"GS_set_att_defaults");
173 for (i = 0; i < MAX_ATTS; i++) {
174 Default_const[i] = defs[i];
175 Default_nulls[i] = null_defs[i];
193 G_debug(3,
"GS_surf_exists(): id=%d",
id);
200 for (i = 0; i < Next_surf && !found; i++) {
201 if (Surf_ID[i] ==
id) {
223 G_debug(3,
"GS_new_surface():");
225 if (Next_surf < MAX_SURFS) {
228 wind.south + wind.ns_res / 2., wind.rows, wind.cols,
229 wind.ew_res, wind.ns_res);
235 Surf_ID[Next_surf] = ns->gsurf_id;
238 G_debug(3,
" id=%d", ns->gsurf_id);
240 return (ns->gsurf_id);
256 static int first = 1;
262 for (i = 0; i < MAX_LIGHTS; i++) {
263 Gv.lights[i].position[
X] = Gv.lights[i].position[
Y] = 0.0;
264 Gv.lights[i].position[Z] = 1.0;
265 Gv.lights[i].position[W] = 0.0;
266 Gv.lights[i].color[0] = Gv.lights[i].color[1] =
267 Gv.lights[i].color[2] = 1.0;
268 Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] =
269 Gv.lights[i].ambient[2] = 0.2;
270 Gv.lights[i].shine = 32.0;
276 if (Numlights < MAX_LIGHTS) {
280 return (++Numlights);
300 if (num < Numlights) {
301 Gv.lights[num].position[
X] = xpos;
302 Gv.lights[num].position[
Y] = ypos;
303 Gv.lights[num].position[Z] = zpos;
304 Gv.lights[num].position[W] = (float)local;
326 if (num < Numlights) {
327 *xpos = Gv.lights[num].position[
X];
328 *ypos = Gv.lights[num].position[
Y];
329 *zpos = Gv.lights[num].position[Z];
330 *local = (int)Gv.lights[num].position[W];
348 if (num < Numlights) {
349 Gv.lights[num].color[0] = red;
350 Gv.lights[num].color[1] = green;
351 Gv.lights[num].color[2] = blue;
370 if (num < Numlights) {
371 *red = Gv.lights[num].color[0];
372 *green = Gv.lights[num].color[1];
373 *blue = Gv.lights[num].color[2];
392 if (num < Numlights) {
393 Gv.lights[num].ambient[0] = red;
394 Gv.lights[num].ambient[1] = green;
395 Gv.lights[num].ambient[2] = blue;
414 if (num < Numlights) {
415 *red = Gv.lights[num].ambient[0];
416 *green = Gv.lights[num].ambient[1];
417 *blue = Gv.lights[num].ambient[2];
432 for (i = 0; i < Numlights; i++) {
446 for (i = 0; i < Numlights; i++) {
464 if (num < Numlights) {
501 G_debug(1,
"GS_get_modelposition1(): model position: %f %f %f",
502 pos[
X], pos[
Y], pos[Z]);
519 float dist, near_h, dir[3];
521 dist = 2. * Gd.nearclip;
523 near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
529 if (*siz > Gd.nearclip) {
535 pos[
X] = Gv.from_to[
FROM][
X] + dir[
X] * dist;
536 pos[
Y] = Gv.from_to[
FROM][
Y] + dir[
Y] * dist;
537 pos[Z] = Gv.from_to[
FROM][Z] + dir[Z] * dist;
558 GLdouble modelMatrix[16], projMatrix[16];
565 pos2[
X] = (float)x - gs->ox + gs->x_trans;
566 pos2[Y] = (
float)y - gs->oy + gs->y_trans;
567 pos2[Z] = (float)z + gs->z_trans;
580 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
581 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
582 glGetIntegerv(GL_VIEWPORT, viewport);
585 GLdouble out_near[3], out_far[3];
589 z = (float)gs->zmax + gs->z_trans;
591 gluUnProject((GLdouble) pt[
X], (GLdouble) pt[Y], (GLdouble) 0.,
592 modelMatrix, projMatrix, viewport,
593 &out_near[
X], &out_near[
Y], &out_near[Z]);
594 gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1.,
595 modelMatrix, projMatrix, viewport,
596 &out_far[X], &out_far[Y], &out_far[Z]);
600 factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
602 out[
X] = out_near[
X] - ((out_near[
X] - out_far[
X]) * factor);
603 out[
Y] = out_near[
Y] - ((out_near[
Y] - out_far[
Y]) * factor);
606 pos2[
X] = (float)out[X];
607 pos2[
Y] = (float)out[Y];
608 pos2[Z] = (float)out[Z];
632 pos[
X] = pt[
X] - gs->ox;
633 pos[
Y] = pt[
Y] - gs->oy;
643 pos[Z] = gs->att[ATT_TOPO].constant;
647 gpd_obj(gs, Gd.bgcol, siz, ST_GYRO, pos);
742 float nv[3], pdir[2],
mult;
743 float p1[2], p2[2], next[2];
756 if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
760 p2[
X] = p1[
X] + (pdir[
X] *
mult);
761 p2[
Y] = p1[
Y] + (pdir[
Y] *
mult);
766 p2[
X] = p1[
X] + (nv[
X] *
mult);
767 p2[
Y] = p1[
Y] + (nv[
Y] *
mult);
784 p2[X], p2[Y], next, 3)) {
792 G_debug(3,
"GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
810 G_debug(3,
"GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
811 id, clr, elev, where[0], where[1], where[2], where[3]);
832 float *range,
int *pt)
886 static float center[3];
904 tcenter[Z] *= Gv.vert_exag;
926 static float center[3], size;
927 float tcenter[3], tsize;
928 int i, wason[MAX_CPLANES];
932 for (i = 0; i < MAX_CPLANES; i++) {
959 for (i = 0; i < MAX_CPLANES; i++) {
1004 tmp[
X] = pt[
X] - gs->ox;
1005 tmp[
Y] = pt[
Y] - gs->oy;
1123 int GS_get_att(
int id,
int att,
int *
set,
float *constant,
char *mapname)
1133 if (src == CONST_ATT) {
1134 *constant = gs->att[att].constant;
1136 else if (src == MAP_ATT) {
1168 int offset, drow, dcol, vrow, vcol;
1193 sprintf(catstr, _(
"no category info"));
1204 offset =
DRC2OFF(gs, drow, dcol);
1209 drow, dcol, catstr));
1212 sprintf(catstr, _(
"no data"));
1231 int offset, drow, dcol, vrow, vcol;
1241 if (gs->norm_needupdate) {
1262 offset =
DRC2OFF(gs, drow, dcol);
1265 FNORM(gs->norms[offset], nv);
1295 int offset, drow, dcol, vrow, vcol;
1321 if (att == ATT_COLOR) {
1324 i = gs->att[att].constant;
1325 sprintf(valstr,
"R%d G%d B%d",
1329 sprintf(valstr,
"%f", gs->att[att].constant);
1345 offset =
DRC2OFF(gs, drow, dcol);
1348 if (att == ATT_COLOR) {
1352 &(gs->att[ATT_COLOR]), offset);
1353 sprintf(valstr,
"R%d G%d B%d",
1357 sprintf(valstr,
"%f", ftmp);
1363 sprintf(valstr,
"NULL");
1381 gs->mask_needupdate = 1;
1426 gs->att[ATT_MASK].constant = mode;
1427 gs->mask_needupdate = 1;
1451 *mode = gs->att[ATT_MASK].constant;
1474 gs->clientdata = clientd;
1496 return (gs->clientdata);
1526 *numsurfs = Next_surf;
1529 ret = (
int *)G_malloc(Next_surf *
sizeof(
int));
1531 for (i = 0; i < Next_surf; i++) {
1532 ret[i] = Surf_ID[i];
1551 int i, j, found = 0;
1553 G_debug(3,
"GS_delete_surface");
1558 for (i = 0; i < Next_surf && !found; i++) {
1559 if (Surf_ID[i] ==
id) {
1562 for (j = i; j < Next_surf; j++) {
1563 Surf_ID[j] = Surf_ID[j + 1];
1593 unsigned int changed;
1596 struct Cell_head rast_head;
1597 int reuse, begin, hdata, ret, neg, has_null;
1600 G_debug(3,
"GS_load_att_map(): map=%s", filename);
1602 reuse = ret = neg = has_null = 0;
1609 gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
1610 (gs->nz_topo && ATT_TOPO == att) ||
1611 (gs->nz_color && ATT_COLOR == att));
1624 if (mapset ==
NULL) {
1626 G_warning(
"Raster map <%s> not found", filename);
1632 if (rast_head.north <= wind.south ||
1633 rast_head.south >= wind.north ||
1634 rast_head.east <= wind.west || rast_head.west >= wind.east) {
1636 G_warning(_(
"Raster map <%s> is outside of current region. Load failed."),
1640 while (!reuse && (0 < hdata)) {
1641 changed = CF_COLOR_PACKED;
1642 atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
1644 if (0 < (hdata =
gsds_findh(filename, &changed, &atty, begin))) {
1646 G_debug(3,
"GS_load_att_map(): %s already has data handle %d.CF=%x",
1647 filename, hdata, changed);
1650 if (ATT_COLOR == att) {
1651 if ((changed == CF_COLOR_PACKED) ||
1652 (!changed && atty == ATTY_CHAR)) {
1656 else if (atty == ATTY_MASK && att != ATT_MASK) {
1661 else if (!changed) {
1670 gs->att[att].hdata = hdata;
1674 if (atty == ATTY_INT) {
1675 if (gs->att[att].lookup) {
1676 free(gs->att[att].lookup);
1677 gs->att[att].lookup =
NULL;
1682 G_debug(3,
"GS_load_att_map(): %s is being reused. hdata=%d",
1686 G_debug(3,
"GS_load_att_map(): %s not loaded in correct form - loading now",
1690 gs->att[att].hdata =
gsds_newh(filename);
1696 if (ATT_MASK == att) {
1704 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1705 atty = (neg ? ATTY_INT : ATTY_SHORT);
1709 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1714 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1720 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1728 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1732 tbuff->nm, &has_null);
1737 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1741 tbuff->nm, &has_null);
1745 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1749 tbuff->nm, &has_null);
1755 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1759 tbuff->nm, &has_null);
1769 G_debug(4,
" has_null=%d", has_null);
1780 if (ATT_COLOR == att) {
1782 if (ATTY_INT == atty) {
1785 gs->att[att].lookup =
NULL;
1789 Gs_build_lookup(filename, gs->att[att].lookup);
1793 if (ATTY_CHAR == atty) {
1794 if (!gs->att[att].lookup) {
1800 else if (ATTY_FLOAT == atty) {
1803 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1807 gs->rows, gs->cols);
1810 gs->att[att].lookup =
NULL;
1817 gs->att[att].lookup =
NULL;
1823 if (ATT_TOPO == att) {
1850 G_debug(3,
"GS_draw_surf(): id=%d",
id);
1856 if (gs->draw_mode & DM_POLY) {
1860 if (gs->draw_mode & DM_WIRE) {
1865 if (gs->draw_mode & DM_WIRE_POLY) {
1885 G_debug(3,
"GS_draw_wire(): id=%d",
id);
1906 for (i = 0; i < Next_surf; i++) {
1922 for (i = 0; i < Next_surf; i++) {
1944 if (gs->z_exag != exag) {
1945 gs->norm_needupdate = 1;
1962 G_debug(3,
"GS_set_global_exag");
1964 Gv.vert_exag = exag;
1983 G_debug(3,
"GS_global_exag(): %g", Gv.vert_exag);
1985 return (Gv.vert_exag);
2000 G_debug(3,
"GS_set_wire_color");
2005 gs->wire_color = colr;
2027 *colr = gs->wire_color;
2047 for (i = 0; i < Next_surf; i++) {
2069 G_debug(3,
"GS_set_drawmode(): id=%d mode=%d",
id, mode);
2074 gs->draw_mode = mode;
2098 *mode = gs->draw_mode;
2122 if (att == ATT_TOPO) {
2124 gs->mask_needupdate = 1;
2127 if (att == ATT_COLOR) {
2128 gs->nz_color = mode;
2129 gs->mask_needupdate = 1;
2155 if (att == ATT_TOPO) {
2156 *mode = gs->nz_topo;
2158 else if (att == ATT_COLOR) {
2159 *mode = gs->nz_color;
2184 for (i = 0; i < Next_surf; i++) {
2207 G_debug(3,
"GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
2208 id, xres, yres, xwire, ywire);
2210 if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
2217 if (gs->x_mod != xres || gs->y_mod != yres) {
2218 gs->norm_needupdate = 1;
2248 *xwire = gs->x_modw;
2249 *ywire = gs->y_modw;
2302 if (gs->zrange_nz == 0.0) {
2308 G_debug(3,
"GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
2310 while (gs->zrange_nz * guess / Longdim >= .25) {
2313 G_debug(3,
"GS_get_exag_guess(): %f", guess);
2316 while (gs->zrange_nz * guess / Longdim < .025) {
2319 G_debug(3,
"GS_get_exag_guess(): %f", guess);
2343 for (i = 0; i < Next_surf; i++) {
2351 if (gs->zmin_nz < *min) {
2355 if (gs->zmax_nz > *max) {
2361 G_debug(3,
"GS_get_zrange_nz(): min=%g max=%g", *min, *max);
2381 gs->x_trans = xtrans;
2382 gs->y_trans = ytrans;
2383 gs->z_trans = ztrans;
2404 *xtrans = gs->x_trans;
2405 *ytrans = gs->y_trans;
2406 *ztrans = gs->z_trans;
2421 G_debug(3,
"GS_default_draw_color");
2423 return ((
unsigned int)Gd.bgcol);
2433 return ((
unsigned int)Gd.bgcol);
2488 if (GSD_BACK == Buffermode) {
2505 G_debug(3,
"GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
2524 realto[
X] = realto[
X] - wind.west - (wind.ew_res / 2.);
2525 realto[
Y] = realto[
Y] - wind.south - (wind.ns_res / 2.);
2556 return (Gv.infocus);
2569 G_debug(3,
"GS_set_focus_center_map");
2574 center[
X] = (gs->xmax - gs->xmin) / 2.;
2575 center[
Y] = (gs->ymax - gs->ymin) / 2.;
2576 center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
2603 G_debug(3,
"GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
2656 G_debug(3,
"GS_get_zextents(): id=%d",
id);
2673 int ret_surf, ret_vol;
2674 float surf_min, surf_max;
2675 float vol_min, vol_max;
2680 if (ret_surf > 0 && ret_vol > 0) {
2681 *min = (surf_min < vol_min) ? surf_min : vol_min;
2682 *max = (surf_max < vol_max) ? surf_max : vol_max;
2684 else if (ret_surf > 0) {
2688 else if (ret_vol > 0) {
2694 *min *= Gv.vert_exag;
2695 *max *= Gv.vert_exag;
2698 G_debug(3,
"GS_get_zrange(): min=%g max=%g", *min, *max);
2699 return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
2711 G_debug(3,
"GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
2740 to[
X] = realto[
X] + wind.west + (wind.ew_res / 2.);
2741 to[
Y] = realto[
Y] + wind.south + (wind.ns_res / 2.);
2899 G_debug(3,
"GS_set_viewport(): left=%d, right=%d, "
2900 "bottom=%d, top=%d", left, right, bottom, top);
2923 float x, y, z, len, los[2][3];
2931 realto[
X] = x - gs->ox + gs->x_trans;
2932 realto[
Y] = y - gs->oy + gs->y_trans;
2933 realto[Z] = z + gs->z_trans;
2944 realto[
X] = Gv.from_to[
FROM][
X] + dir[
X];
2945 realto[
Y] = Gv.from_to[
FROM][
Y] + dir[
Y];
2946 realto[Z] = Gv.from_to[
FROM][Z] + dir[Z];
2973 float los[2][3], find_dist[MAX_SURFS], closest;
2974 Point3
point, tmp, finds[MAX_SURFS];
2975 int surfs[MAX_SURFS], i, iclose, numhits = 0;
2982 G_debug(3,
"gs_setlos_enterdata(los): returns false");
2986 for (i = 0; i < Next_surf; i++) {
3000 tmp[
X] += gs->x_trans;
3001 tmp[
Y] += gs->y_trans;
3002 tmp[Z] += gs->z_trans;
3005 GS_v3eq(finds[numhits], point);
3006 surfs[numhits] = Surf_ID[i];
3012 for (i = iclose = 0; i < numhits; i++) {
3013 closest = find_dist[iclose];
3015 if (find_dist[i] < closest) {
3021 *x = finds[iclose][
X];
3022 *y = finds[iclose][
Y];
3023 *z = finds[iclose][Z];
3024 *
id = surfs[iclose];
3027 G_debug(3,
"NumHits %d, next %d", numhits, Next_surf);
3066 geosurf *gsurfs[MAX_SURFS];
3113 int onstate[MAX_CPLANES], i;
3117 for (i = 0; i < MAX_CPLANES; i++) {
3160 zexag = doexag ? Gv.vert_exag : 1.;
3161 *sx = *sy = Gv.scale;
3162 *sz = Gv.scale * zexag;
3202 float *dist,
int use_exag)
3219 G_debug(3,
"GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
3220 hs, x1, y1, x2, y2);
3265 static int first = 1;
3271 glMatrixMode(GL_MODELVIEW);
3290 glDepthRange(0.0, 1.0);
3291 glEnable(GL_DEPTH_TEST);
3292 glDepthFunc(GL_LEQUAL);
3299 Gv.from_to[
FROM][Z] = GS_UNIT_SIZE / 2.;
3301 Gv.from_to[TO][
X] = GS_UNIT_SIZE / 2.;
3302 Gv.from_to[TO][
Y] = GS_UNIT_SIZE / 2.;
3303 Gv.from_to[TO][Z] = 0.;
3304 Gv.from_to[TO][W] = Gv.from_to[
FROM][W] = 1.;
3309 GS_v3eq(Gv.real_to, Gv.from_to[TO]);
3317 Gd.farclip = 10000.;
3335 col = col | 0xFF000000;
3347 glClearColor(((
float)((col) & 0xff)) / 255.,
3348 (
float)((col) >> 8 & 0xff) / 255.,
3349 (
float)((col) >> 16 & 0xff) / 255.,
3350 (
float)((col) >> 24 & 0xff) / 255.);
3351 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
3367 int left, right, bottom, top;
3374 glGetIntegerv(GL_VIEWPORT, tmp);
3376 right = tmp[0] + tmp[2] - 1;
3378 top = tmp[1] + tmp[3] - 1;
3380 G_debug(3,
"GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
3381 left, right, top, bottom);
3383 return ((
double)(right - left) / (top - bottom));