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 Resetlight = 1;
82 static int Modelshowing = 0;
102 Region[0] = wind.north;
103 Region[1] = wind.south;
104 Region[2] = wind.west;
105 Region[3] = wind.east;
108 if ((wind.east - wind.west) > (wind.north - wind.south)) {
109 Longdim = (wind.east - wind.west);
112 Longdim = (wind.north - wind.south);
115 Gv.scale = GS_UNIT_SIZE / Longdim;
117 G_debug(1,
"GS_libinit(): n=%f s=%f w=%f e=%f scale=%f first=%d",
118 Region[0], Region[1], Region[2], Region[3], Gv.scale, first);
144 G_debug(3,
"GS_get_longdim(): dim=%g", *dim);
176 G_debug(3,
"GS_set_att_defaults");
178 for (i = 0; i < MAX_ATTS; i++) {
179 Default_const[i] = defs[i];
180 Default_nulls[i] = null_defs[i];
198 G_debug(3,
"GS_surf_exists(): id=%d",
id);
205 for (i = 0; i < Next_surf && !found; i++) {
206 if (Surf_ID[i] ==
id) {
228 G_debug(3,
"GS_new_surface():");
230 if (Next_surf < MAX_SURFS) {
233 wind.south + wind.ns_res / 2., wind.rows, wind.cols,
234 wind.ew_res, wind.ns_res);
240 Surf_ID[Next_surf] = ns->gsurf_id;
243 G_debug(3,
" id=%d", ns->gsurf_id);
245 return (ns->gsurf_id);
276 for (i = 0; i < MAX_LIGHTS; i++) {
277 Gv.lights[i].position[
X] = Gv.lights[i].position[
Y] = 0.0;
278 Gv.lights[i].position[Z] = 1.0;
279 Gv.lights[i].position[W] = 0.0;
280 Gv.lights[i].color[0] = Gv.lights[i].color[1] =
281 Gv.lights[i].color[2] = 1.0;
282 Gv.lights[i].ambient[0] = Gv.lights[i].ambient[1] =
283 Gv.lights[i].ambient[2] = 0.2;
284 Gv.lights[i].shine = 32.0;
290 if (Numlights < MAX_LIGHTS) {
314 if (num < Numlights) {
315 Gv.lights[num].position[
X] = xpos;
316 Gv.lights[num].position[
Y] = ypos;
317 Gv.lights[num].position[Z] = zpos;
318 Gv.lights[num].position[W] = (float)local;
340 if (num < Numlights) {
341 *xpos = Gv.lights[num].position[
X];
342 *ypos = Gv.lights[num].position[
Y];
343 *zpos = Gv.lights[num].position[Z];
344 *local = (int)Gv.lights[num].position[W];
362 if (num < Numlights) {
363 Gv.lights[num].color[0] = red;
364 Gv.lights[num].color[1] = green;
365 Gv.lights[num].color[2] = blue;
384 if (num < Numlights) {
385 *red = Gv.lights[num].color[0];
386 *green = Gv.lights[num].color[1];
387 *blue = Gv.lights[num].color[2];
406 if (num < Numlights) {
407 Gv.lights[num].ambient[0] = red;
408 Gv.lights[num].ambient[1] = green;
409 Gv.lights[num].ambient[2] = blue;
428 if (num < Numlights) {
429 *red = Gv.lights[num].ambient[0];
430 *green = Gv.lights[num].ambient[1];
431 *blue = Gv.lights[num].ambient[2];
446 for (i = 0; i < Numlights; i++) {
460 for (i = 0; i < Numlights; i++) {
478 if (num < Numlights) {
515 G_debug(1,
"GS_get_modelposition1(): model position: %f %f %f",
516 pos[
X], pos[
Y], pos[Z]);
533 float dist, near_h, dir[3];
535 dist = 2. * Gd.nearclip;
537 near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
543 if (*siz > Gd.nearclip) {
549 pos[
X] = Gv.from_to[
FROM][
X] + dir[
X] * dist;
550 pos[
Y] = Gv.from_to[
FROM][
Y] + dir[
Y] * dist;
551 pos[Z] = Gv.from_to[
FROM][Z] + dir[Z] * dist;
572 GLdouble modelMatrix[16], projMatrix[16];
579 pos2[
X] = (float)x - gs->ox + gs->x_trans;
580 pos2[Y] = (
float)y - gs->oy + gs->y_trans;
581 pos2[Z] = (float)z + gs->z_trans;
594 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
595 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
596 glGetIntegerv(GL_VIEWPORT, viewport);
599 GLdouble out_near[3], out_far[3];
603 z = (float)gs->zmax + gs->z_trans;
605 gluUnProject((GLdouble) pt[
X], (GLdouble) pt[Y], (GLdouble) 0.,
606 modelMatrix, projMatrix, viewport,
607 &out_near[
X], &out_near[
Y], &out_near[Z]);
608 gluUnProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) 1.,
609 modelMatrix, projMatrix, viewport,
610 &out_far[X], &out_far[Y], &out_far[Z]);
614 factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
616 out[
X] = out_near[
X] - ((out_near[
X] - out_far[
X]) * factor);
617 out[
Y] = out_near[
Y] - ((out_near[
Y] - out_far[
Y]) * factor);
620 pos2[
X] = (float)out[X];
621 pos2[
Y] = (float)out[Y];
622 pos2[Z] = (float)out[Z];
646 pos[
X] = pt[
X] - gs->ox;
647 pos[
Y] = pt[
Y] - gs->oy;
657 pos[Z] = gs->att[ATT_TOPO].constant;
661 gpd_obj(gs, Gd.bgcol, siz, ST_GYRO, pos);
756 float nv[3], pdir[2],
mult;
757 float p1[2], p2[2], next[2];
770 if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
774 p2[
X] = p1[
X] + (pdir[
X] *
mult);
775 p2[
Y] = p1[
Y] + (pdir[
Y] *
mult);
780 p2[
X] = p1[
X] + (nv[
X] *
mult);
781 p2[
Y] = p1[
Y] + (nv[
Y] *
mult);
798 p2[X], p2[Y], next, 3)) {
806 G_debug(3,
"GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
824 G_debug(3,
"GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
825 id, clr, elev, where[0], where[1], where[2], where[3]);
846 float *
range,
int *pt)
900 static float center[3];
918 tcenter[Z] *= Gv.vert_exag;
940 static float center[3],
size;
941 float tcenter[3], tsize;
942 int i, wason[MAX_CPLANES];
946 for (i = 0; i < MAX_CPLANES; i++) {
973 for (i = 0; i < MAX_CPLANES; i++) {
1018 tmp[
X] = pt[
X] - gs->ox;
1019 tmp[
Y] = pt[
Y] - gs->oy;
1147 if (src == CONST_ATT) {
1148 *constant = gs->att[att].constant;
1150 else if (src == MAP_ATT) {
1182 int offset, drow, dcol, vrow, vcol;
1207 sprintf(catstr, _(
"no category info"));
1218 offset =
DRC2OFF(gs, drow, dcol);
1223 drow, dcol, catstr));
1226 sprintf(catstr, _(
"no data"));
1245 int offset, drow, dcol, vrow, vcol;
1255 if (gs->norm_needupdate) {
1276 offset =
DRC2OFF(gs, drow, dcol);
1279 FNORM(gs->norms[offset], nv);
1309 int offset, drow, dcol, vrow, vcol;
1335 if (att == ATT_COLOR) {
1338 i = gs->att[att].constant;
1339 sprintf(valstr,
"R%d G%d B%d",
1343 sprintf(valstr,
"%f", gs->att[att].constant);
1359 offset =
DRC2OFF(gs, drow, dcol);
1362 if (att == ATT_COLOR) {
1366 &(gs->att[ATT_COLOR]), offset);
1367 sprintf(valstr,
"R%d G%d B%d",
1371 sprintf(valstr,
"%f", ftmp);
1377 sprintf(valstr,
"NULL");
1395 gs->mask_needupdate = 1;
1440 gs->att[ATT_MASK].constant =
mode;
1441 gs->mask_needupdate = 1;
1465 *mode = gs->att[ATT_MASK].constant;
1488 gs->clientdata = clientd;
1510 return (gs->clientdata);
1540 *numsurfs = Next_surf;
1543 ret = (
int *)G_malloc(Next_surf *
sizeof(
int));
1545 for (i = 0; i < Next_surf; i++) {
1546 ret[i] = Surf_ID[i];
1569 G_debug(1,
"GS_delete_surface(): id=%d",
id);
1573 for (i = 0; i < Next_surf && !found; i++) {
1574 if (Surf_ID[i] ==
id) {
1577 for (j = i; j < Next_surf; j++) {
1578 Surf_ID[j] = Surf_ID[j + 1];
1608 unsigned int changed;
1611 struct Cell_head rast_head;
1612 int reuse, begin, hdata, ret, neg, has_null;
1615 G_debug(3,
"GS_load_att_map(): map=%s", filename);
1617 reuse = ret = neg = has_null = 0;
1624 gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
1625 (gs->nz_topo && ATT_TOPO == att) ||
1626 (gs->nz_color && ATT_COLOR == att));
1639 if (mapset ==
NULL) {
1641 G_warning(
"Raster map <%s> not found", filename);
1647 if (rast_head.north <= wind.south ||
1648 rast_head.south >= wind.north ||
1649 rast_head.east <= wind.west || rast_head.west >= wind.east) {
1651 G_warning(_(
"Raster map <%s> is outside of current region. Load failed."),
1655 while (!reuse && (0 < hdata)) {
1656 changed = CF_COLOR_PACKED;
1657 atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
1659 if (0 < (hdata =
gsds_findh(filename, &changed, &atty, begin))) {
1661 G_debug(3,
"GS_load_att_map(): %s already has data handle %d.CF=%x",
1662 filename, hdata, changed);
1665 if (ATT_COLOR == att) {
1666 if ((changed == CF_COLOR_PACKED) ||
1667 (!changed && atty == ATTY_CHAR)) {
1671 else if (atty == ATTY_MASK && att != ATT_MASK) {
1676 else if (!changed) {
1685 gs->att[att].hdata = hdata;
1689 if (atty == ATTY_INT) {
1690 if (gs->att[att].lookup) {
1691 free(gs->att[att].lookup);
1692 gs->att[att].lookup =
NULL;
1697 G_debug(3,
"GS_load_att_map(): %s is being reused. hdata=%d",
1701 G_debug(3,
"GS_load_att_map(): %s not loaded in correct form - loading now",
1705 gs->att[att].hdata =
gsds_newh(filename);
1711 if (ATT_MASK == att) {
1719 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1720 atty = (neg ? ATTY_INT : ATTY_SHORT);
1724 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1729 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1735 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1743 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1747 tbuff->nm, &has_null);
1752 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1756 tbuff->nm, &has_null);
1760 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1764 tbuff->nm, &has_null);
1770 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1774 tbuff->nm, &has_null);
1784 G_debug(4,
" has_null=%d", has_null);
1795 if (ATT_COLOR == att) {
1797 if (ATTY_INT == atty) {
1800 gs->att[att].lookup =
NULL;
1804 Gs_build_lookup(filename, gs->att[att].lookup);
1808 if (ATTY_CHAR == atty) {
1809 if (!gs->att[att].lookup) {
1815 else if (ATTY_FLOAT == atty) {
1818 G_fatal_error(_(
"GS_load_att_map(): Out of memory. Unable to load map"));
1822 gs->rows, gs->cols);
1825 gs->att[att].lookup =
NULL;
1832 gs->att[att].lookup =
NULL;
1838 if (ATT_TOPO == att) {
1865 G_debug(3,
"GS_draw_surf(): id=%d",
id);
1871 if (gs->draw_mode & DM_POLY) {
1875 if (gs->draw_mode & DM_WIRE) {
1880 if (gs->draw_mode & DM_WIRE_POLY) {
1900 G_debug(3,
"GS_draw_wire(): id=%d",
id);
1921 for (i = 0; i < Next_surf; i++) {
1937 for (i = 0; i < Next_surf; i++) {
1959 if (gs->z_exag != exag) {
1960 gs->norm_needupdate = 1;
1977 G_debug(3,
"GS_set_global_exag");
1979 Gv.vert_exag = exag;
1998 G_debug(3,
"GS_global_exag(): %g", Gv.vert_exag);
2000 return (Gv.vert_exag);
2015 G_debug(3,
"GS_set_wire_color");
2020 gs->wire_color = colr;
2042 *colr = gs->wire_color;
2062 for (i = 0; i < Next_surf; i++) {
2084 G_debug(3,
"GS_set_drawmode(): id=%d mode=%d",
id, mode);
2089 gs->draw_mode =
mode;
2113 *mode = gs->draw_mode;
2137 if (att == ATT_TOPO) {
2139 gs->mask_needupdate = 1;
2142 if (att == ATT_COLOR) {
2143 gs->nz_color =
mode;
2144 gs->mask_needupdate = 1;
2170 if (att == ATT_TOPO) {
2171 *mode = gs->nz_topo;
2173 else if (att == ATT_COLOR) {
2174 *mode = gs->nz_color;
2199 for (i = 0; i < Next_surf; i++) {
2222 G_debug(3,
"GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
2223 id, xres, yres, xwire, ywire);
2225 if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
2232 if (gs->x_mod != xres || gs->y_mod != yres) {
2233 gs->norm_needupdate = 1;
2263 *xwire = gs->x_modw;
2264 *ywire = gs->y_modw;
2318 if (gs->zrange_nz == 0.0) {
2324 G_debug(3,
"GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
2326 while (gs->zrange_nz * guess / Longdim >= .25) {
2329 G_debug(3,
"GS_get_exag_guess(): %f", guess);
2332 while (gs->zrange_nz * guess / Longdim < .025) {
2335 G_debug(3,
"GS_get_exag_guess(): %f", guess);
2359 for (i = 0; i < Next_surf; i++) {
2367 if (gs->zmin_nz < *min) {
2371 if (gs->zmax_nz > *max) {
2377 G_debug(3,
"GS_get_zrange_nz(): min=%g max=%g", *min, *max);
2397 gs->x_trans = xtrans;
2398 gs->y_trans = ytrans;
2399 gs->z_trans = ztrans;
2420 *xtrans = gs->x_trans;
2421 *ytrans = gs->y_trans;
2422 *ztrans = gs->z_trans;
2437 G_debug(3,
"GS_default_draw_color");
2439 return ((
unsigned int)Gd.bgcol);
2449 return ((
unsigned int)Gd.bgcol);
2504 if (GSD_BACK == Buffermode) {
2521 G_debug(3,
"GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
2540 realto[
X] = realto[
X] - wind.west - (wind.ew_res / 2.);
2541 realto[
Y] = realto[
Y] - wind.south - (wind.ns_res / 2.);
2572 return (Gv.infocus);
2585 G_debug(3,
"GS_set_focus_center_map");
2590 center[
X] = (gs->xmax - gs->xmin) / 2.;
2591 center[
Y] = (gs->ymax - gs->ymin) / 2.;
2592 center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
2619 G_debug(3,
"GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
2672 G_debug(3,
"GS_get_zextents(): id=%d",
id);
2689 int ret_surf, ret_vol;
2690 float surf_min, surf_max;
2691 float vol_min, vol_max;
2696 if (ret_surf > 0 && ret_vol > 0) {
2697 *min = (surf_min < vol_min) ? surf_min : vol_min;
2698 *max = (surf_max < vol_max) ? surf_max : vol_max;
2700 else if (ret_surf > 0) {
2704 else if (ret_vol > 0) {
2710 *min *= Gv.vert_exag;
2711 *max *= Gv.vert_exag;
2714 G_debug(3,
"GS_get_zrange(): min=%g max=%g", *min, *max);
2715 return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
2727 G_debug(3,
"GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
2756 to[
X] = realto[
X] + wind.west + (wind.ew_res / 2.);
2757 to[
Y] = realto[
Y] + wind.south + (wind.ns_res / 2.);
2887 Gv.rotate.rot_angle = angle;
2888 Gv.rotate.rot_axes[0] = x;
2889 Gv.rotate.rot_axes[1] =
y;
2890 Gv.rotate.rot_axes[2] = z;
2891 Gv.rotate.do_rot = 1;
2901 Gv.rotate.do_rot = 0;
2911 for (i = 0; i < 16; i++) {
2912 if (i == 0 || i == 5 || i == 10 || i == 15)
2913 Gv.rotate.rotMatrix[i] = 1.0;
2915 Gv.rotate.rotMatrix[i] = 0.0;
2917 Gv.rotate.rot_angle = 0.0;
2918 Gv.rotate.rot_axes[0] = 0.0;
2919 Gv.rotate.rot_axes[1] = 0.0;
2920 Gv.rotate.rot_axes[2] = 0.0;
2921 Gv.rotate.do_rot = 0;
2931 for (i = 0; i < 16; i++) {
2932 matrix[i] = Gv.rotate.rotMatrix[i];
2943 for (i = 0; i < 16; i++) {
2944 Gv.rotate.rotMatrix[i] = matrix[i];
2981 G_debug(3,
"GS_set_viewport(): left=%d, right=%d, "
2982 "bottom=%d, top=%d", left, right, bottom, top);
3005 float x,
y, z, len, los[2][3];
3013 realto[
X] = x - gs->ox + gs->x_trans;
3014 realto[
Y] = y - gs->oy + gs->y_trans;
3015 realto[Z] = z + gs->z_trans;
3026 realto[
X] = Gv.from_to[
FROM][
X] + dir[
X];
3027 realto[
Y] = Gv.from_to[
FROM][
Y] + dir[
Y];
3028 realto[Z] = Gv.from_to[
FROM][Z] + dir[Z];
3055 float los[2][3], find_dist[MAX_SURFS], closest;
3056 Point3
point, tmp, finds[MAX_SURFS];
3057 int surfs[MAX_SURFS], i, iclose, numhits = 0;
3064 G_debug(3,
"gs_setlos_enterdata(los): returns false");
3068 for (i = 0; i < Next_surf; i++) {
3082 tmp[
X] += gs->x_trans;
3083 tmp[
Y] += gs->y_trans;
3084 tmp[Z] += gs->z_trans;
3087 GS_v3eq(finds[numhits], point);
3088 surfs[numhits] = Surf_ID[i];
3094 for (i = iclose = 0; i < numhits; i++) {
3095 closest = find_dist[iclose];
3097 if (find_dist[i] < closest) {
3103 *x = finds[iclose][
X];
3104 *y = finds[iclose][
Y];
3105 *z = finds[iclose][Z];
3106 *
id = surfs[iclose];
3109 G_debug(3,
"NumHits %d, next %d", numhits, Next_surf);
3148 geosurf *gsurfs[MAX_SURFS];
3195 int onstate[MAX_CPLANES], i;
3199 for (i = 0; i < MAX_CPLANES; i++) {
3242 zexag = doexag ? Gv.vert_exag : 1.;
3243 *sx = *sy = Gv.scale;
3244 *sz = Gv.scale * zexag;
3284 float *dist,
int use_exag)
3301 G_debug(3,
"GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
3302 hs, x1, y1, x2, y2);
3347 static int first = 1;
3353 glMatrixMode(GL_MODELVIEW);
3372 glDepthRange(0.0, 1.0);
3373 glEnable(GL_DEPTH_TEST);
3374 glDepthFunc(GL_LEQUAL);
3384 Gv.from_to[
FROM][Z] = GS_UNIT_SIZE / 2.;
3386 Gv.from_to[TO][
X] = GS_UNIT_SIZE / 2.;
3387 Gv.from_to[TO][
Y] = GS_UNIT_SIZE / 2.;
3388 Gv.from_to[TO][Z] = 0.;
3389 Gv.from_to[TO][W] = Gv.from_to[
FROM][W] = 1.;
3394 GS_v3eq(Gv.real_to, Gv.from_to[TO]);
3402 Gd.farclip = 10000.;
3420 col = col | 0xFF000000;
3432 glClearColor(((
float)((col) & 0xff)) / 255.,
3433 (
float)((col) >> 8 & 0xff) / 255.,
3434 (
float)((col) >> 16 & 0xff) / 255.,
3435 (
float)((col) >> 24 & 0xff) / 255.);
3436 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
3452 int left, right, bottom, top;
3459 glGetIntegerv(GL_VIEWPORT, tmp);
3461 right = tmp[0] + tmp[2] - 1;
3463 top = tmp[1] + tmp[3] - 1;
3465 G_debug(3,
"GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
3466 left, right, top, bottom);
3468 return ((
double)(right - left) / (top - bottom));