1 /*!
2 \file lib/ogsf/gs2.c
3
4 \brief OGSF library - loading and manipulating surfaces (higher level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 Plans for handling color maps:
9 NOW:
10 if able to load as unsigned char, make lookup table containing palette
11 otherwise, load directly as packed color, set lookup = NULL
12 MAYBE LATER:
13 if able to load as POSITIVE short, make lookup table containing palette
14 - may want to calculate savings first (ie, numcells > 32768)
15 (not exactly, it's Friday & time to go home - figure it later)
16 otherwise, load directly as packed color, set lookup = NULL
17 MESSY! - need to fix up!
18
19 (C) 1999-2008 by the GRASS Development Team
20
21 This program is free software under the
22 GNU General Public License (>=v2).
23 Read the file COPYING that comes with GRASS
24 for details.
25
26 \author Bill Brown USACERL (1993)
27 \author Pierre de Mouveaux <p_de_mouveaux hotmail.com> (updated October 1999)
28 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
29 */
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34
35 #include <grass/config.h>
36
37 #if defined(OPENGL_X11) || defined(OPENGL_WINDOWS)
38 #include <GL/gl.h>
39 #include <GL/glu.h>
40 #elif defined(OPENGL_AQUA)
41 #include <OpenGL/gl.h>
42 #include <OpenGL/glu.h>
43 #endif
44
45 #include <grass/gis.h>
46 #include <grass/raster.h>
47 #include <grass/ogsf.h>
48 #include <grass/glocale.h>
49
50 #include "gsget.h"
51 #include "rowcol.h"
52 #include "rgbpack.h"
53
54 /* Hack to make NVIZ2.2 query functions.("What's Here" and "Look at")
55 * to work.
56 * Uses gs_los_intersect1() instead of gs_los_intersect().
57 * Pierre de Mouveaux - 31 oct. 1999. p_de_mouveaux@hotmail.com.
58 */
59 #define NVIZ_HACK 1
60
61 int gsd_getViewport(GLint *, GLint *);
62
63 /* array of surface ids */
64 static int Surf_ID[MAX_SURFS];
65 static int Next_surf = 0;
66 static int SDref_surf = 0;
67
68 /* attributes array */
69 static float Default_const[MAX_ATTS];
70 static float Default_nulls[MAX_ATTS];
71
72 /* largest dimension */
73 static float Longdim;
74
75 /* N, S, W, E */
76 static float Region[4];
77 static geoview Gv;
78 static geodisplay Gd;
79 static struct Cell_head wind;
80 static int Buffermode;
81 static int Numlights = 0;
82 static int Resetlight = 1;
83 static int Modelshowing = 0;
84
void_func(void)85 void void_func(void)
86 {
87 return;
88 }
89
90 /*!
91 \brief Initialize OGSF library
92
93 Get region settings - wind
94
95 Set Region (NSWE array) and compute scale
96 */
GS_libinit(void)97 void GS_libinit(void)
98 {
99 static int first = 1;
100
101 G_get_set_window(&wind);
102
103 Region[0] = wind.north;
104 Region[1] = wind.south;
105 Region[2] = wind.west;
106 Region[3] = wind.east;
107
108 /* scale largest dimension to GS_UNIT_SIZE */
109 if ((wind.east - wind.west) > (wind.north - wind.south)) {
110 Longdim = (wind.east - wind.west);
111 }
112 else {
113 Longdim = (wind.north - wind.south);
114 }
115
116 Gv.scale = GS_UNIT_SIZE / Longdim;
117
118 G_debug(1, "GS_libinit(): n=%f s=%f w=%f e=%f scale=%f first=%d",
119 Region[0], Region[1], Region[2], Region[3], Gv.scale, first);
120
121 Cxl_func = void_func;
122
123
124 if (first) {
125 gs_init();
126 }
127
128 first = 0;
129
130 return;
131 }
132
133 /*!
134 \brief Get largest dimension
135
136 \param[out] dim dimension
137
138 \return 1
139 */
GS_get_longdim(float * dim)140 int GS_get_longdim(float *dim)
141 {
142 *dim = Longdim;
143
144 G_debug(3, "GS_get_longdim(): dim=%g", *dim);
145
146 return (1);
147 }
148
149 /*!
150 \brief Get 2D region extent
151
152 \param[out] n,s,w,e extent values
153
154 \return 1
155 */
GS_get_region(float * n,float * s,float * w,float * e)156 int GS_get_region(float *n, float *s, float *w, float *e)
157 {
158 *n = Region[0];
159 *s = Region[1];
160 *w = Region[2];
161 *e = Region[3];
162
163 return (1);
164 }
165
166 /*!
167 \brief Set default attributes for map objects
168
169 \param defs attributes array (dim MAX_ATTS)
170 \param null_defs null attributes array (dim MAX_ATTS)
171 */
GS_set_att_defaults(float * defs,float * null_defs)172 void GS_set_att_defaults(float *defs, float *null_defs)
173 {
174 int i;
175
176 G_debug(3, "GS_set_att_defaults");
177
178 for (i = 0; i < MAX_ATTS; i++) {
179 Default_const[i] = defs[i];
180 Default_nulls[i] = null_defs[i];
181 }
182
183 return;
184 }
185
186 /*!
187 Check if surface exists
188
189 \param id surface id
190
191 \return 0 not found
192 \return 1 found
193 */
GS_surf_exists(int id)194 int GS_surf_exists(int id)
195 {
196 int i, found = 0;
197
198 G_debug(3, "GS_surf_exists(): id=%d", id);
199
200
201 if (NULL == gs_get_surf(id)) {
202 return (0);
203 }
204
205 for (i = 0; i < Next_surf && !found; i++) {
206 if (Surf_ID[i] == id) {
207 found = 1;
208 }
209 }
210
211 return (found);
212 }
213
214 /*!
215 \brief Add new surface
216
217 Note that origin has 1/2 cell added to represent center of cells
218 because library assumes that east - west = (cols - 1) * ew_res,
219 since left and right columns are on the edges.
220
221 \return surface id
222 \return -1 on error (MAX_SURFS exceded)
223 */
GS_new_surface(void)224 int GS_new_surface(void)
225 {
226 geosurf *ns;
227
228 G_debug(3, "GS_new_surface():");
229
230 if (Next_surf < MAX_SURFS) {
231 ns = gs_get_new_surface();
232 gs_init_surf(ns, wind.west + wind.ew_res / 2.,
233 wind.south + wind.ns_res / 2., wind.rows, wind.cols,
234 wind.ew_res, wind.ns_res);
235 gs_set_defaults(ns, Default_const, Default_nulls);
236
237 /* make default shine current */
238 gs_set_att_src(ns, ATT_SHINE, CONST_ATT);
239
240 Surf_ID[Next_surf] = ns->gsurf_id;
241 ++Next_surf;
242
243 G_debug(3, " id=%d", ns->gsurf_id);
244
245 return (ns->gsurf_id);
246 }
247
248
249
250 return (-1);
251 }
GS_set_light_reset(int i)252 void GS_set_light_reset(int i)
253 {
254 Resetlight = i;
255 if (i)
256 Numlights = 0;
257 }
GS_get_light_reset(void)258 int GS_get_light_reset(void)
259 {
260 return Resetlight;
261 }
262 /*!
263 \brief Add new model light
264
265 \return light model id
266 \return -1 on error (MAX_LIGHTS exceded)
267 */
GS_new_light(void)268 int GS_new_light(void)
269 {
270 int i;
271
272 if (GS_get_light_reset()) {
273
274 GS_set_light_reset(0);
275
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; /* infinite */
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;
285 }
286
287 gsd_init_lightmodel();
288 }
289
290 if (Numlights < MAX_LIGHTS) {
291 gsd_deflight(Numlights + 1, &(Gv.lights[Numlights]));
292 gsd_switchlight(Numlights + 1, 1);
293
294 return ++Numlights;
295 }
296
297 return -1;
298 }
299
300 /*!
301 \brief Set light position
302
303 \bug I think lights array doesnt match sgi_light array
304
305 \param num light id (starts with 1)
306 \param xpos,ypos,zpos coordinates (model)
307 \param local local coordinate (for viewport)
308 */
GS_setlight_position(int num,float xpos,float ypos,float zpos,int local)309 void GS_setlight_position(int num, float xpos, float ypos, float zpos,
310 int local)
311 {
312 if (num) {
313 num -= 1;
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;
319
320 gsd_deflight(num + 1, &(Gv.lights[num]));
321 }
322 }
323
324 return;
325 }
326
327
328 /*!
329 \brief Get light position
330
331 \param num light id (starts at 1)
332 \param[out] xpos,ypos,zpos coordinates
333 \param[out] local ?
334 */
GS_getlight_position(int num,float * xpos,float * ypos,float * zpos,int * local)335 void GS_getlight_position(int num, float *xpos, float *ypos, float *zpos,
336 int *local)
337 {
338 if (num) {
339 num -= 1;
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];
345
346 }
347 }
348
349 return;
350 }
351
352 /*!
353 \brief Set light color
354
355 \param num light id (starts at 1)
356 \param red,green,blue color values (from 0.0 to 1.0)
357 */
GS_setlight_color(int num,float red,float green,float blue)358 void GS_setlight_color(int num, float red, float green, float blue)
359 {
360 if (num) {
361 num -= 1;
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;
366
367 gsd_deflight(num + 1, &(Gv.lights[num]));
368 }
369 }
370
371 return;
372 }
373
374 /*!
375 \brief Get light color
376
377 \param num light id (starts at 1)
378 \param[out] red,green,blue color values
379 */
GS_getlight_color(int num,float * red,float * green,float * blue)380 void GS_getlight_color(int num, float *red, float *green, float *blue)
381 {
382 if (num) {
383 num -= 1;
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];
388 }
389 }
390
391 return;
392 }
393
394 /*!
395 \brief Set light ambient
396
397 Red, green, blue from 0.0 to 1.0
398
399 \param num light id (starts at 1)
400 \param red,green,blue color values
401 */
GS_setlight_ambient(int num,float red,float green,float blue)402 void GS_setlight_ambient(int num, float red, float green, float blue)
403 {
404 if (num) {
405 num -= 1;
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;
410
411 gsd_deflight(num + 1, &(Gv.lights[num]));
412 }
413 }
414
415 return;
416 }
417
418 /*!
419 \brief Get light ambient
420
421 \param num light id (starts at 1)
422 \param[out] red,green,blue color values
423 */
GS_getlight_ambient(int num,float * red,float * green,float * blue)424 void GS_getlight_ambient(int num, float *red, float *green, float *blue)
425 {
426 if (num) {
427 num -= 1;
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];
432 }
433 }
434
435 return;
436 }
437
438
439 /*!
440 \brief Switch off all lights
441 */
GS_lights_off(void)442 void GS_lights_off(void)
443 {
444 int i;
445
446 for (i = 0; i < Numlights; i++) {
447 gsd_switchlight(i + 1, 0);
448 }
449
450 return;
451 }
452
453 /*!
454 \brief Switch on all lights
455 */
GS_lights_on(void)456 void GS_lights_on(void)
457 {
458 int i;
459
460 for (i = 0; i < Numlights; i++) {
461 gsd_switchlight(i + 1, 1);
462 }
463
464 return;
465 }
466
467 /*!
468 \brief Switch on/off light
469
470 \param num light id (starts at 1)
471 \param on non-zero for 'on' otherwise 'off'
472 */
GS_switchlight(int num,int on)473 void GS_switchlight(int num, int on)
474 {
475 if (num) {
476 num -= 1;
477
478 if (num < Numlights) {
479 gsd_switchlight(num + 1, on);
480 }
481 }
482
483 return;
484 }
485
486 /*!
487 \brief Check if transparency is set
488
489 \return 0 transparency not set
490 \return 1 transparency is set
491 */
GS_transp_is_set(void)492 int GS_transp_is_set(void)
493 {
494 return (gs_att_is_set(NULL, ATT_TRANSP) || (FC_GREY == gsd_getfc()));
495 }
496
497 /*!
498 \brief Retrieves coordinates for lighting model position, at center of view
499
500 \param pos[out] coordinates
501 */
GS_get_modelposition1(float pos[])502 void GS_get_modelposition1(float pos[])
503 {
504 /* TODO: Still needs work to handle other cases */
505 /* this is a quick hack to get lighting adjustments debugged */
506 /*
507 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], center);
508 GS_v3mult(center, 1000);
509 GS_v3add(center, Gv.from_to[FROM]);
510 */
511
512 gs_get_datacenter(pos);
513 gs_get_data_avg_zmax(&(pos[Z]));
514
515 G_debug(1, "GS_get_modelposition1(): model position: %f %f %f",
516 pos[X], pos[Y], pos[Z]);
517
518 return;
519 }
520
521 /*!
522 \brief Retrieves coordinates for lighting model position, at center of view
523
524 Position at nearclip * 2: tried nearclip + siz, but since need to
525 know position to calculate size, have two dependent variables
526 (nearclip * 2) from eye.
527
528 \param siz[out] size
529 \param pos[out] coordinates (X, Y, Z)
530 */
GS_get_modelposition(float * siz,float * pos)531 void GS_get_modelposition(float *siz, float *pos)
532 {
533 float dist, near_h, dir[3];
534
535 dist = 2. * Gd.nearclip;
536
537 near_h = 2.0 * tan(4.0 * atan(1.) * Gv.fov / 3600.) * dist;
538 *siz = near_h / 8.0;
539
540 /* prevent clipping - would only happen if fov > ~127 degrees, at
541 fov = 2.0 * atan(2.0) */
542
543 if (*siz > Gd.nearclip) {
544 *siz = Gd.nearclip;
545 }
546
547 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
548
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;
552
553 return;
554 }
555
556
557 /*!
558 \brief Set decoration, north arrow ??
559
560 \todo scale used to calculate len of arrow still needs work
561 needs go function that returns center / eye distance
562 gsd_get_los function is not working correctly ??
563
564 \param pt point value in true world coordinates (?)
565 \param id surface id
566 \param[out] pos2 output coordinates
567 */
GS_set_Narrow(int * pt,int id,float * pos2)568 void GS_set_Narrow(int *pt, int id, float *pos2)
569 {
570 geosurf *gs;
571 float x, y, z;
572 GLdouble modelMatrix[16], projMatrix[16];
573 GLint viewport[4];
574
575 if (GS_get_selected_point_on_surface(pt[X], pt[Y], &id, &x, &y, &z)) {
576 gs = gs_get_surf(id);
577 if (gs) {
578 z = gs->zmax;
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;
582
583 return;
584 }
585 }
586 else {
587 gs = gs_get_surf(id);
588
589 /* Need to get model matrix, etc
590 * to run gluUnProject
591 */
592 gsd_pushmatrix();
593 gsd_do_scale(1);
594 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
595 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
596 glGetIntegerv(GL_VIEWPORT, viewport);
597
598 if (gs) {
599 GLdouble out_near[3], out_far[3];
600 GLdouble factor;
601 GLdouble out[3];
602
603 z = (float)gs->zmax + gs->z_trans;
604
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]);
611
612 glPopMatrix();
613
614 factor = (out_near[Z] - z) / (out_near[Z] - out_far[Z]);
615
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);
618 out[Z] = z;
619
620 pos2[X] = (float)out[X];
621 pos2[Y] = (float)out[Y];
622 pos2[Z] = (float)out[Z];
623
624 return;
625
626 }
627 }
628 return;
629 }
630
631 /*!
632 \brief Draw place marker
633
634 Used to display query point for raster queries.
635
636 \param id surface id
637 \param pt point, X, Y value in true world coordinates
638 */
GS_draw_X(int id,float * pt)639 void GS_draw_X(int id, float *pt)
640 {
641 geosurf *gs;
642 Point3 pos;
643 float siz;
644 gvstyle style;
645
646 if ((gs = gs_get_surf(id))) {
647 GS_get_longdim(&siz);
648 style.size = siz / 200.;
649 pos[X] = pt[X] - gs->ox;
650 pos[Y] = pt[Y] - gs->oy;
651 _viewcell_tri_interp(gs, pos);
652
653 gsd_pushmatrix();
654
655 gsd_do_scale(1);
656 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
657 gsd_linewidth(1);
658
659 if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
660 pos[Z] = gs->att[ATT_TOPO].constant;
661 gs = NULL; /* tells gpd_obj to use given Z val */
662 }
663 style.color = Gd.bgcol;
664 style.symbol = ST_GYRO;
665 gpd_obj(gs, &style, pos);
666 gsd_flush();
667
668 gsd_popmatrix();
669 }
670
671 return;
672 }
673
674 /*!
675 \brief Draw line on surface
676
677 \param id surface id
678 \param x1,y1,x2,y2 line nodes
679 */
GS_draw_line_onsurf(int id,float x1,float y1,float x2,float y2)680 void GS_draw_line_onsurf(int id, float x1, float y1, float x2, float y2)
681 {
682 float p1[2], p2[2];
683 geosurf *gs;
684
685 if ((gs = gs_get_surf(id))) {
686 p1[X] = x1 - gs->ox;
687 p1[Y] = y1 - gs->oy;
688 p2[X] = x2 - gs->ox;
689 p2[Y] = y2 - gs->oy;
690
691 gsd_pushmatrix();
692
693 gsd_do_scale(1);
694 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
695 gsd_linewidth(1);
696
697 gsd_color_func(GS_default_draw_color());
698 gsd_line_onsurf(gs, p1, p2);
699
700 gsd_popmatrix();
701 gsd_flush();
702 }
703
704 return;
705 }
706
707 /*!
708 \brief Draw multiline on surface
709
710 Like above but limits points in line to n or points found in segment,
711 whichever is smaller.
712
713 \param id surface id
714 \param x1,y1,x2,y2 line nodes
715
716 \return number of points used
717 */
GS_draw_nline_onsurf(int id,float x1,float y1,float x2,float y2,float * lasp,int n)718 int GS_draw_nline_onsurf(int id, float x1, float y1, float x2, float y2,
719 float *lasp, int n)
720 {
721 float p1[2], p2[2];
722 geosurf *gs;
723 int ret = 0;
724
725 if ((gs = gs_get_surf(id))) {
726 p1[X] = x1 - gs->ox;
727 p1[Y] = y1 - gs->oy;
728 p2[X] = x2 - gs->ox;
729 p2[Y] = y2 - gs->oy;
730
731 gsd_pushmatrix();
732
733 gsd_do_scale(1);
734 gsd_translate(gs->x_trans, gs->y_trans, gs->z_trans);
735 gsd_linewidth(1);
736 gsd_color_func(GS_default_draw_color());
737 ret = gsd_nline_onsurf(gs, p1, p2, lasp, n);
738 gsd_surf2real(gs, lasp);
739
740 gsd_popmatrix();
741 gsd_flush();
742 }
743
744 return (ret);
745 }
746
747 /*!
748 \brief Draw flow-line on surace
749
750 This is slow - should be moved to gs_ but GS_ good for testing
751 and useful for app programmer
752
753 \param id surface id
754 \param x,y coordinates of flow-line
755 */
GS_draw_flowline_at_xy(int id,float x,float y)756 void GS_draw_flowline_at_xy(int id, float x, float y)
757 {
758 geosurf *gs;
759 float nv[3], pdir[2], mult;
760 float p1[2], p2[2], next[2];
761 int i = 0;
762
763 if ((gs = gs_get_surf(id))) {
764 p1[X] = x;
765 p1[Y] = y;
766 /* multiply by 1.5 resolutions to ensure a crossing ? */
767 mult = .1 * (VXRES(gs) > VYRES(gs) ? VXRES(gs) : VYRES(gs));
768
769 GS_coordpair_repeats(p1, p1, 50);
770
771 while (1 == GS_get_norm_at_xy(id, p1[X], p1[Y], nv)) {
772 if (nv[Z] == 1.0) {
773 if (pdir[X] == 0.0 && pdir[Y] == 0.0) {
774 break;
775 }
776
777 p2[X] = p1[X] + (pdir[X] * mult);
778 p2[Y] = p1[Y] + (pdir[Y] * mult);
779 }
780 else {
781 /* use previous direction */
782 GS_v2norm(nv);
783 p2[X] = p1[X] + (nv[X] * mult);
784 p2[Y] = p1[Y] + (nv[Y] * mult);
785 pdir[X] = nv[X];
786 pdir[Y] = nv[Y];
787 }
788
789 if (i > 2000) {
790 break;
791 }
792
793 if (GS_coordpair_repeats(p1, p2, 0)) {
794 break;
795 }
796
797 /* Think about this: */
798 /* degenerate line means edge or level edge ? */
799 /* next is filled with last point drawn */
800 if (2 > GS_draw_nline_onsurf(id, p1[X], p1[Y],
801 p2[X], p2[Y], next, 3)) {
802 break;
803 }
804
805 p1[X] = next[X];
806 p1[Y] = next[Y];
807 }
808
809 G_debug(3, "GS_draw_flowline_at_xy(): dir: %f %f", nv[X], nv[Y]);
810 }
811
812 return;
813 }
814
815 /*!
816 \brief Draw fringe around data (surface) at selected corners
817
818 \param id surface id
819 \param clr color
820 \param elev elevation value
821 \param where nw/ne/sw/se edges - 0 (turn off) 1 (turn on)
822 */
GS_draw_fringe(int id,unsigned long clr,float elev,int * where)823 void GS_draw_fringe(int id, unsigned long clr, float elev, int *where)
824 {
825 geosurf *gs;
826
827 G_debug(3, "GS_draw_fringe(): id: %d clr: %ld elev %f edges: %d %d %d %d",
828 id, clr, elev, where[0], where[1], where[2], where[3]);
829 if ((gs = gs_get_surf(id)))
830 gsd_display_fringe(gs, clr, elev, where);
831
832 }
833
834
835 /*!
836 \brief Draw legend
837
838 \todo add legend from list option
839 make font loading more flexible
840
841 \param name legend name
842 \param fontbase font-base
843 \param size ?
844 \param flags legend flags
845 \param range values range
846 \param pt ?
847 */
GS_draw_legend(const char * name,GLuint fontbase,int size,int * flags,float * range,int * pt)848 int GS_draw_legend(const char *name, GLuint fontbase, int size, int *flags,
849 float *range, int *pt)
850 {
851 int list_no;
852
853 list_no = gsd_put_legend(name, fontbase, size, flags, range, pt);
854
855 return (list_no);
856 }
857
858 /*!
859 \brief Draw pre-defined list
860
861 Uses glFlush() to ensure all drawing is complete
862 before returning
863
864 \param list_id list id
865 */
GS_draw_list(GLuint list_id)866 void GS_draw_list(GLuint list_id)
867 {
868 gsd_calllist(list_id);
869 glFlush();
870 return;
871 }
872
873 /*!
874 \brief Draw all glLists
875
876 Uses glFlush() to ensure all drawing is complete
877 before returning
878 */
GS_draw_all_list(void)879 void GS_draw_all_list(void)
880 {
881 gsd_calllists(0); /* not sure if 0 is right - MN */
882 glFlush();
883 return;
884 }
885
886 /*!
887 \brief Delete pre-defined list
888
889 \param list_id list id
890 */
GS_delete_list(GLuint list_id)891 void GS_delete_list(GLuint list_id)
892 {
893 gsd_deletelist(list_id, 1);
894
895 return;
896 }
897
898 /*!
899 \brief Draw lighting model
900 */
GS_draw_lighting_model1(void)901 void GS_draw_lighting_model1(void)
902 {
903 static float center[3];
904 float tcenter[3];
905
906 if (!Modelshowing) {
907 GS_get_modelposition1(center);
908 }
909
910 GS_v3eq(tcenter, center);
911
912 gsd_zwritemask(0x0);
913 gsd_backface(1);
914
915 gsd_colormode(CM_AD);
916 gsd_shademodel(DM_GOURAUD);
917 gsd_pushmatrix();
918 gsd_do_scale(1);
919
920 if (Gv.vert_exag) {
921 tcenter[Z] *= Gv.vert_exag;
922 gsd_scale(1.0, 1.0, 1. / Gv.vert_exag);
923 }
924
925 gsd_drawsphere(tcenter, 0xDDDDDD, (float)(Longdim / 10.));
926 gsd_popmatrix();
927 Modelshowing = 1;
928
929 gsd_backface(0);
930 gsd_zwritemask(0xffffffff);
931
932 return;
933 }
934
935 /*!
936 \brief Draw lighting model
937
938 Just turn off any cutting planes and draw it just outside near
939 clipping plane, since lighting is infinite now
940 */
GS_draw_lighting_model(void)941 void GS_draw_lighting_model(void)
942 {
943 static float center[3], size;
944 float tcenter[3], tsize;
945 int i, wason[MAX_CPLANES];
946
947 gsd_get_cplanes_state(wason);
948
949 for (i = 0; i < MAX_CPLANES; i++) {
950 if (wason[i]) {
951 gsd_cplane_off(i);
952 }
953 }
954
955
956 if (!Modelshowing) {
957 GS_get_modelposition(&size, center);
958 }
959
960 GS_v3eq(tcenter, center);
961 tsize = size;
962
963 gsd_zwritemask(0x0);
964 gsd_backface(1);
965
966 gsd_colormode(CM_DIFFUSE);
967 gsd_shademodel(DM_GOURAUD);
968 gsd_pushmatrix();
969 gsd_drawsphere(tcenter, 0xDDDDDD, tsize);
970 gsd_popmatrix();
971 Modelshowing = 1;
972
973 gsd_backface(0);
974 gsd_zwritemask(0xffffffff);
975
976 for (i = 0; i < MAX_CPLANES; i++) {
977 if (wason[i]) {
978 gsd_cplane_on(i);
979 }
980 }
981
982 gsd_flush();
983
984 return;
985 }
986
987 /*!
988 \brief Update current mask
989
990 May be called to update total mask for a surface at convenient times
991 instead of waiting until ready to redraw surface
992
993 \param id surface id
994
995 \return ?
996 */
GS_update_curmask(int id)997 int GS_update_curmask(int id)
998 {
999 geosurf *gs;
1000
1001 gs = gs_get_surf(id);
1002 return (gs_update_curmask(gs));
1003 }
1004
1005 /*!
1006 \brief Check if point is masked ?
1007
1008 \param id surface id
1009 \param pt point
1010
1011 \return 1 masked
1012 \return 0 not masked
1013 \return -1 on error, invalid surface id
1014 */
GS_is_masked(int id,float * pt)1015 int GS_is_masked(int id, float *pt)
1016 {
1017 geosurf *gs;
1018 Point3 tmp;
1019
1020 if ((gs = gs_get_surf(id))) {
1021 tmp[X] = pt[X] - gs->ox;
1022 tmp[Y] = pt[Y] - gs->oy;
1023
1024 return (gs_point_is_masked(gs, tmp));
1025 }
1026
1027 return (-1);
1028 }
1029
1030 /*!
1031 \brief Unset Scaled Difference surface
1032 */
GS_unset_SDsurf(void)1033 void GS_unset_SDsurf(void)
1034 {
1035 gsdiff_set_SDref(NULL);
1036 SDref_surf = 0;
1037
1038 return;
1039 }
1040
1041 /*!
1042 \brief Set surface as Scaled Difference surface
1043
1044 \param id surface id
1045
1046 \return 1 on success
1047 \return 0 on error, invalid surface id
1048 */
GS_set_SDsurf(int id)1049 int GS_set_SDsurf(int id)
1050 {
1051 geosurf *gs;
1052
1053 if ((gs = gs_get_surf(id))) {
1054 gsdiff_set_SDref(gs);
1055 SDref_surf = id;
1056
1057 return (1);
1058 }
1059
1060 return (0);
1061 }
1062
1063 /*!
1064 \brief Set ?
1065
1066 \param scale scale value
1067
1068 \return 1
1069 */
GS_set_SDscale(float scale)1070 int GS_set_SDscale(float scale)
1071 {
1072 gsdiff_set_SDscale(scale);
1073
1074 return (1);
1075 }
1076
1077 /*!
1078 \brief Get ?
1079
1080 \param[out] id ?
1081
1082 \return 1 on success
1083 \return 0 on error
1084 */
GS_get_SDsurf(int * id)1085 int GS_get_SDsurf(int *id)
1086 {
1087 geosurf *gs;
1088
1089 if ((gs = gsdiff_get_SDref())) {
1090 *id = SDref_surf;
1091
1092 return (1);
1093 }
1094
1095 return (0);
1096 }
1097
1098 /*!
1099 \brief Get ?
1100
1101 \param[out] scale value
1102
1103 \return 1
1104 */
GS_get_SDscale(float * scale)1105 int GS_get_SDscale(float *scale)
1106 {
1107 *scale = gsdiff_get_SDscale();
1108
1109 return (1);
1110 }
1111
1112 /*!
1113 \brief Update normals
1114
1115 \param id surface id
1116
1117 \return ?
1118 */
GS_update_normals(int id)1119 int GS_update_normals(int id)
1120 {
1121 geosurf *gs;
1122
1123 gs = gs_get_surf(id);
1124
1125 return (gs_calc_normals(gs));
1126 }
1127
1128 /*!
1129 \brief Get attributes
1130
1131 \param id surface id
1132 \param att
1133 \param[out] set
1134 \param[out] constant
1135 \param[out] mapname
1136
1137 \return 1 on success
1138 \return -1 on error (invalid surface id)
1139 */
GS_get_att(int id,int att,int * set,float * constant,char * mapname)1140 int GS_get_att(int id, int att, int *set, float *constant, char *mapname)
1141 {
1142 int src;
1143 geosurf *gs;
1144
1145 gs = gs_get_surf(id);
1146 if (gs) {
1147 if (-1 != (src = gs_get_att_src(gs, att))) {
1148 *set = src;
1149
1150 if (src == CONST_ATT) {
1151 *constant = gs->att[att].constant;
1152 }
1153 else if (src == MAP_ATT) {
1154 strcpy(mapname, gsds_get_name(gs->att[att].hdata));
1155 }
1156
1157 return (1);
1158 }
1159
1160 return (-1);
1161 }
1162
1163 return (-1);
1164 }
1165
1166 /*!
1167 \brief Get surface category on given position
1168
1169 Prints "no data" or a description (i.e., "coniferous forest") to
1170 <i>catstr</i>. Usually call after GS_get_selected_point_on_surface().
1171 Define <i>att</i> as MAP_ATT
1172
1173 \todo Allocate catstr using G_store()
1174
1175 \param id surface id
1176 \param att attribute id (MAP_ATT)
1177 \param catstr cat string (must be allocated, dim?)
1178 \param x,y real coordinates
1179
1180 \return -1 if no category info or point outside of window
1181 \return 1 on success
1182 */
GS_get_cat_at_xy(int id,int att,char * catstr,float x,float y)1183 int GS_get_cat_at_xy(int id, int att, char *catstr, float x, float y)
1184 {
1185 int offset, drow, dcol, vrow, vcol;
1186 float ftmp, pt[3];
1187 typbuff *buff;
1188 geosurf *gs;
1189
1190 *catstr = '\0';
1191 gs = gs_get_surf(id);
1192
1193 if (NULL == gs) {
1194 return -1;
1195 }
1196
1197 pt[X] = x;
1198 pt[Y] = y;
1199
1200 gsd_real2surf(gs, pt);
1201 if (gs_point_is_masked(gs, pt)) {
1202 return -1;
1203 }
1204
1205 if (!in_vregion(gs, pt)) {
1206 return -1;
1207 }
1208
1209 if (MAP_ATT != gs_get_att_src(gs, att)) {
1210 sprintf(catstr, _("no category info"));
1211 return -1;
1212 }
1213
1214 buff = gs_get_att_typbuff(gs, att, 0);
1215
1216 vrow = Y2VROW(gs, pt[Y]);
1217 vcol = X2VCOL(gs, pt[X]);
1218 drow = VROW2DROW(gs, vrow);
1219 dcol = VCOL2DCOL(gs, vcol);
1220
1221 offset = DRC2OFF(gs, drow, dcol);
1222
1223 if (GET_MAPATT(buff, offset, ftmp)) {
1224 return
1225 (Gs_get_cat_label(gsds_get_name(gs->att[att].hdata),
1226 drow, dcol, catstr));
1227 }
1228
1229 sprintf(catstr, _("no data"));
1230
1231 return 1;
1232 }
1233
1234 /*!
1235 \brief Get surface normal at x,y (real coordinates)
1236
1237 Usually call after GS_get_selected_point_on_surface()
1238
1239 \param id surface id
1240 \param x,y real coordinates
1241 \param[out] nv surface normal
1242
1243 \return -1 if point outside of window or masked
1244 \return 1 on success
1245 */
GS_get_norm_at_xy(int id,float x,float y,float * nv)1246 int GS_get_norm_at_xy(int id, float x, float y, float *nv)
1247 {
1248 int offset, drow, dcol, vrow, vcol;
1249 float pt[3];
1250 geosurf *gs;
1251
1252 gs = gs_get_surf(id);
1253
1254 if (NULL == gs) {
1255 return (-1);
1256 }
1257
1258 if (gs->norm_needupdate) {
1259 gs_calc_normals(gs);
1260 }
1261
1262 pt[X] = x;
1263 pt[Y] = y;
1264
1265 gsd_real2surf(gs, pt);
1266 if (gs_point_is_masked(gs, pt)) {
1267 return (-1);
1268 }
1269
1270 if (!in_vregion(gs, pt)) {
1271 return (-1);
1272 }
1273
1274 vrow = Y2VROW(gs, pt[Y]);
1275 vcol = X2VCOL(gs, pt[X]);
1276 drow = VROW2DROW(gs, vrow);
1277 dcol = VCOL2DCOL(gs, vcol);
1278
1279 offset = DRC2OFF(gs, drow, dcol);
1280
1281 if (gs->norms) {
1282 FNORM(gs->norms[offset], nv);
1283 }
1284 else {
1285 /* otherwise must be a constant */
1286 nv[0] = 0.0;
1287 nv[1] = 0.0;
1288 nv[2] = 1.0;
1289 }
1290
1291 return (1);
1292 }
1293
1294 /*!
1295 \brief Get RGB color at given point
1296
1297 Colors are translated to rgb and returned as Rxxx Gxxx Bxxx Usually
1298 call after GS_get_selected_point_on_surface().
1299
1300 Prints NULL or the value (i.e., "921.5") to valstr
1301
1302 \param id surface id
1303 \param att attribute id
1304 \param[out] valstr value string (allocated, dim?)
1305 \param x,y real coordinates
1306
1307 \return -1 if point outside of window or masked
1308 \return 1 on success
1309 */
GS_get_val_at_xy(int id,int att,char * valstr,float x,float y)1310 int GS_get_val_at_xy(int id, int att, char *valstr, float x, float y)
1311 {
1312 int offset, drow, dcol, vrow, vcol;
1313 float ftmp, pt[3];
1314 typbuff *buff;
1315 geosurf *gs;
1316
1317 *valstr = '\0';
1318 gs = gs_get_surf(id);
1319
1320 if (NULL == gs) {
1321 return -1;
1322 }
1323
1324 pt[X] = x;
1325 pt[Y] = y;
1326
1327 gsd_real2surf(gs, pt);
1328
1329 if (gs_point_is_masked(gs, pt)) {
1330 return -1;
1331 }
1332
1333 if (!in_vregion(gs, pt)) {
1334 return (-1);
1335 }
1336
1337 if (CONST_ATT == gs_get_att_src(gs, att)) {
1338 if (att == ATT_COLOR) {
1339 int r, g, b, i;
1340
1341 i = gs->att[att].constant;
1342 sprintf(valstr, "R%d G%d B%d",
1343 INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
1344 }
1345 else {
1346 sprintf(valstr, "%f", gs->att[att].constant);
1347 }
1348
1349 return 1;
1350 }
1351 else if (MAP_ATT != gs_get_att_src(gs, att)) {
1352 return -1;
1353 }
1354
1355 buff = gs_get_att_typbuff(gs, att, 0);
1356
1357 vrow = Y2VROW(gs, pt[Y]);
1358 vcol = X2VCOL(gs, pt[X]);
1359 drow = VROW2DROW(gs, vrow);
1360 dcol = VCOL2DCOL(gs, vcol);
1361
1362 offset = DRC2OFF(gs, drow, dcol);
1363
1364 if (GET_MAPATT(buff, offset, ftmp)) {
1365 if (att == ATT_COLOR) {
1366 int r, g, b, i;
1367
1368 i = gs_mapcolor(gs_get_att_typbuff(gs, ATT_COLOR, 0),
1369 &(gs->att[ATT_COLOR]), offset);
1370 sprintf(valstr, "R%d G%d B%d",
1371 INT_TO_RED(i, r), INT_TO_GRN(i, g), INT_TO_BLU(i, b));
1372 }
1373 else {
1374 sprintf(valstr, "%f", ftmp);
1375 }
1376
1377 return (1);
1378 }
1379
1380 sprintf(valstr, "NULL");
1381
1382 return (1);
1383 }
1384
1385 /*!
1386 \brief Unset attribute
1387
1388 \param id surface id
1389 \param att attribute id
1390
1391 \return ?
1392 */
GS_unset_att(int id,int att)1393 int GS_unset_att(int id, int att)
1394 {
1395 geosurf *gs;
1396
1397 gs = gs_get_surf(id);
1398 gs->mask_needupdate = 1;
1399
1400 return (gs_set_att_src(gs, att, NOTSET_ATT));
1401 }
1402
1403 /*!
1404 \brief Set attribute constant
1405
1406 \param id surface id
1407 \param att attribute id
1408 \param constant value
1409
1410 \return ?
1411 */
GS_set_att_const(int id,int att,float constant)1412 int GS_set_att_const(int id, int att, float constant)
1413 {
1414 geosurf *gs;
1415 int ret;
1416
1417 gs = gs_get_surf(id);
1418 ret = (gs_set_att_const(gs, att, constant));
1419
1420 Gs_update_attrange(gs, att);
1421
1422 return (ret);
1423 }
1424
1425 /*!
1426 \brief Set mask mode
1427
1428 Mask attribute special: constant is set to indicate invert or no
1429
1430 \param id surface id
1431 \param mode id
1432
1433 \return mode id
1434 \return -1 on error (invalid surface id)
1435 */
GS_set_maskmode(int id,int mode)1436 int GS_set_maskmode(int id, int mode)
1437 {
1438 geosurf *gs;
1439
1440 gs = gs_get_surf(id);
1441
1442 if (gs) {
1443 gs->att[ATT_MASK].constant = mode;
1444 gs->mask_needupdate = 1;
1445
1446 return (mode);
1447 }
1448
1449 return (-1);
1450 }
1451
1452 /*!
1453 \brief Get mask mode
1454
1455 \param id surface id
1456 \param[out] mode id
1457
1458 \return 1 on success
1459 \return -1 on error (invalid surface id)
1460 */
GS_get_maskmode(int id,int * mode)1461 int GS_get_maskmode(int id, int *mode)
1462 {
1463 geosurf *gs;
1464
1465 gs = gs_get_surf(id);
1466
1467 if (gs) {
1468 *mode = gs->att[ATT_MASK].constant;
1469
1470 return (1);
1471 }
1472
1473 return (-1);
1474 }
1475
1476 /*!
1477 \brief Set client data
1478
1479 \param id surface id
1480 \param clientd pointer to client data struct
1481
1482 \return 1 on success
1483 \return -1 on error (invalid surface id)
1484 */
GS_Set_ClientData(int id,void * clientd)1485 int GS_Set_ClientData(int id, void *clientd)
1486 {
1487 geosurf *gs;
1488
1489 gs = gs_get_surf(id);
1490 if (gs) {
1491 gs->clientdata = clientd;
1492
1493 return (1);
1494 }
1495
1496 return (-1);
1497 }
1498
1499 /*!
1500 \brief Get client data
1501
1502 \param id surface id
1503
1504 \return pointer to client data
1505 \return NULL on error
1506 */
GS_Get_ClientData(int id)1507 void *GS_Get_ClientData(int id)
1508 {
1509 geosurf *gs;
1510
1511 gs = gs_get_surf(id);
1512 if (gs) {
1513 return (gs->clientdata);
1514 }
1515
1516 return (NULL);
1517 }
1518
1519 /*!
1520 \brief Get number of surfaces
1521
1522 \return number of surfaces
1523 */
GS_num_surfs(void)1524 int GS_num_surfs(void)
1525 {
1526 return (gs_num_surfaces());
1527 }
1528
1529 /*!
1530 \brief Get surface list
1531
1532 Must be freed when not neeed!
1533
1534 \param[out] numsurf number of available surfaces
1535
1536 \return pointer to surface array
1537 \return NULL on error
1538 */
GS_get_surf_list(int * numsurfs)1539 int *GS_get_surf_list(int *numsurfs)
1540 {
1541 int i, *ret;
1542
1543 *numsurfs = Next_surf;
1544
1545 if (Next_surf) {
1546 ret = (int *)G_malloc(Next_surf * sizeof(int));
1547
1548 for (i = 0; i < Next_surf; i++) {
1549 ret[i] = Surf_ID[i];
1550 }
1551
1552 return (ret);
1553 }
1554
1555 return (NULL);
1556 }
1557
1558 /*!
1559 \brief Delete surface
1560
1561 \param id surface id
1562
1563 \return 1 on success
1564 \return -1 on error
1565 */
GS_delete_surface(int id)1566 int GS_delete_surface(int id)
1567 {
1568 int i, j, found;
1569
1570 found = FALSE;
1571
1572 G_debug(1, "GS_delete_surface(): id=%d", id);
1573
1574 if (GS_surf_exists(id)) {
1575 gs_delete_surf(id);
1576 for (i = 0; i < Next_surf && !found; i++) {
1577 if (Surf_ID[i] == id) {
1578 found = TRUE;
1579
1580 for (j = i; j < Next_surf; j++) {
1581 Surf_ID[j] = Surf_ID[j + 1];
1582 }
1583 }
1584 }
1585
1586 gv_update_drapesurfs();
1587
1588 if (found) {
1589 --Next_surf;
1590 return 1;
1591 }
1592 }
1593
1594 return -1;
1595 }
1596
1597
1598 /*!
1599 \brief Load raster map as attribute
1600
1601 \param id surface id
1602 \param filename filename
1603 \param att attribute descriptor
1604
1605 \return -1 on error (invalid surface id)
1606 \return ?
1607 */
GS_load_att_map(int id,const char * filename,int att)1608 int GS_load_att_map(int id, const char *filename, int att)
1609 {
1610 geosurf *gs;
1611 unsigned int changed;
1612 unsigned int atty;
1613 const char *mapset;
1614 struct Cell_head rast_head;
1615 int reuse, begin, hdata, ret, neg, has_null;
1616 typbuff *tbuff;
1617
1618 G_debug(3, "GS_load_att_map(): map=%s", filename);
1619
1620 reuse = ret = neg = has_null = 0;
1621 gs = gs_get_surf(id);
1622
1623 if (NULL == gs) {
1624 return -1;
1625 }
1626
1627 gs->mask_needupdate = (ATT_MASK == att || ATT_TOPO == att ||
1628 (gs->nz_topo && ATT_TOPO == att) ||
1629 (gs->nz_color && ATT_COLOR == att));
1630
1631 gs_set_att_src(gs, att, MAP_ATT);
1632
1633 /* Check against maps already loaded in memory */
1634 /* if to be color attribute:
1635 - if packed color for another surface, OK to reuse
1636 - if unchanged, ok to reuse IF it's of type char (will have lookup)
1637 */
1638 begin = hdata = 1;
1639
1640 /* Get MAPSET to ensure names are fully qualified */
1641 mapset = G_find_raster2(filename, "");
1642 if (mapset == NULL) {
1643 /* Check for valid filename */
1644 G_warning("Raster map <%s> not found", filename);
1645 return -1;
1646 }
1647
1648 /* Check to see if map is in Region */
1649 Rast_get_cellhd(filename, mapset, &rast_head);
1650 if (rast_head.north <= wind.south ||
1651 rast_head.south >= wind.north ||
1652 rast_head.east <= wind.west || rast_head.west >= wind.east) {
1653
1654 G_warning(_("Raster map <%s> is outside of current region. Load failed."),
1655 G_fully_qualified_name(filename, mapset));
1656 }
1657
1658 while (!reuse && (0 < hdata)) {
1659 changed = CF_COLOR_PACKED;
1660 atty = ATTY_FLOAT | ATTY_CHAR | ATTY_INT | ATTY_SHORT | ATTY_MASK;
1661
1662 if (0 < (hdata = gsds_findh(filename, &changed, &atty, begin))) {
1663
1664 G_debug(3, "GS_load_att_map(): %s already has data handle %d.CF=%x",
1665 filename, hdata, changed);
1666
1667 /* handle found */
1668 if (ATT_COLOR == att) {
1669 if ((changed == CF_COLOR_PACKED) ||
1670 (!changed && atty == ATTY_CHAR)) {
1671 reuse = 1;
1672 }
1673 }
1674 else if (atty == ATTY_MASK && att != ATT_MASK) {
1675 reuse = 0;
1676 /* should also free mask data & share new - but need backward
1677 reference? */
1678 }
1679 else if (!changed) {
1680 reuse = 1;
1681 }
1682 }
1683
1684 begin = 0;
1685 }
1686
1687 if (reuse) {
1688 gs->att[att].hdata = hdata;
1689 gs_set_att_type(gs, att, atty); /* ?? */
1690
1691 /* free lookup & set to NULL! */
1692 if (atty == ATTY_INT) {
1693 if (gs->att[att].lookup) {
1694 free(gs->att[att].lookup);
1695 gs->att[att].lookup = NULL;
1696 }
1697 }
1698 /* TODO: FIX THIS stuff with lookup sharing! */
1699
1700 G_debug(3, "GS_load_att_map(): %s is being reused. hdata=%d",
1701 filename, hdata);
1702 }
1703 else {
1704 G_debug(3, "GS_load_att_map(): %s not loaded in correct form - loading now",
1705 filename);
1706
1707 /* not loaded - need to get new dataset handle */
1708 gs->att[att].hdata = gsds_newh(filename);
1709
1710 tbuff = gs_get_att_typbuff(gs, att, 1);
1711
1712 /* TODO: Provide mechanism for loading certain attributes at
1713 specified sizes, allow scaling or capping, or scale non-zero */
1714 if (ATT_MASK == att) {
1715 atty = ATTY_MASK;
1716 }
1717 else {
1718 atty = Gs_numtype(filename, &neg);
1719 }
1720
1721 #ifdef MAYBE_LATER
1722 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1723 atty = (neg ? ATTY_INT : ATTY_SHORT);
1724 }
1725 #endif
1726
1727 if (att == ATT_COLOR && atty == ATTY_SHORT) {
1728 atty = ATTY_INT;
1729 }
1730
1731 if (0 == gs_malloc_att_buff(gs, att, ATTY_NULL)) {
1732 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1733 }
1734
1735 switch (atty) {
1736 case ATTY_MASK:
1737 if (0 == gs_malloc_att_buff(gs, att, ATTY_MASK)) {
1738 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1739 }
1740
1741 ret = Gs_loadmap_as_bitmap(&wind, filename, tbuff->bm);
1742
1743 break;
1744 case ATTY_CHAR:
1745 if (0 == gs_malloc_att_buff(gs, att, ATTY_CHAR)) {
1746 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1747 }
1748
1749 ret = Gs_loadmap_as_char(&wind, filename, tbuff->cb,
1750 tbuff->nm, &has_null);
1751
1752 break;
1753 case ATTY_SHORT:
1754 if (0 == gs_malloc_att_buff(gs, att, ATTY_SHORT)) {
1755 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1756 }
1757
1758 ret = Gs_loadmap_as_short(&wind, filename, tbuff->sb,
1759 tbuff->nm, &has_null);
1760 break;
1761 case ATTY_FLOAT:
1762 if (0 == gs_malloc_att_buff(gs, att, ATTY_FLOAT)) {
1763 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1764 }
1765
1766 ret = Gs_loadmap_as_float(&wind, filename, tbuff->fb,
1767 tbuff->nm, &has_null);
1768
1769 break;
1770 case ATTY_INT:
1771 default:
1772 if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
1773 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1774 }
1775
1776 ret = Gs_loadmap_as_int(&wind, filename, tbuff->ib,
1777 tbuff->nm, &has_null);
1778 break;
1779
1780 } /* Done with switch */
1781
1782 if (ret == -1) {
1783 gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
1784 return -1;
1785 }
1786
1787 G_debug(4, " has_null=%d", has_null);
1788
1789 if (!has_null) {
1790 gsds_free_data_buff(gs->att[att].hdata, ATTY_NULL);
1791 }
1792 else {
1793 gs_update_curmask(gs);
1794 }
1795
1796 } /* end if not reuse */
1797
1798 if (ATT_COLOR == att) {
1799 #ifdef MAYBE_LATER
1800 if (ATTY_INT == atty) {
1801 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
1802 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
1803 gs->att[att].lookup = NULL;
1804 }
1805 else {
1806 gs_malloc_lookup(gs, att);
1807 Gs_build_lookup(filename, gs->att[att].lookup);
1808 }
1809 #else
1810
1811 if (ATTY_CHAR == atty) {
1812 if (!gs->att[att].lookup) {
1813 /* might already exist if reusing */
1814 gs_malloc_lookup(gs, att);
1815 Gs_build_256lookup(filename, gs->att[att].lookup);
1816 }
1817 }
1818 else if (ATTY_FLOAT == atty) {
1819 if (!reuse) {
1820 if (0 == gs_malloc_att_buff(gs, att, ATTY_INT)) {
1821 G_fatal_error(_("GS_load_att_map(): Out of memory. Unable to load map"));
1822 }
1823
1824 Gs_pack_colors_float(filename, tbuff->fb, tbuff->ib,
1825 gs->rows, gs->cols);
1826 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
1827 gsds_free_data_buff(gs->att[att].hdata, ATTY_FLOAT);
1828 gs->att[att].lookup = NULL;
1829 }
1830 }
1831 else {
1832 if (!reuse) {
1833 Gs_pack_colors(filename, tbuff->ib, gs->rows, gs->cols);
1834 gsds_set_changed(gs->att[att].hdata, CF_COLOR_PACKED);
1835 gs->att[att].lookup = NULL;
1836 }
1837 }
1838 #endif
1839 }
1840
1841 if (ATT_TOPO == att) {
1842 gs_init_normbuff(gs);
1843 /* S_DIFF: should also check here to see if this surface is a
1844 reference surface for scaled differences, if so update references
1845 to it */
1846 }
1847
1848 if (ret < 0) {
1849 G_warning(_("Loading failed"));
1850 }
1851
1852 if (-1 == Gs_update_attrange(gs, att)) {
1853 G_warning(_("Error finding range"));
1854 }
1855
1856 return ret;
1857 }
1858
1859 /*!
1860 \brief Draw surface
1861
1862 \param id surface id
1863 */
GS_draw_surf(int id)1864 void GS_draw_surf(int id)
1865 {
1866 geosurf *gs;
1867
1868 G_debug(3, "GS_draw_surf(): id=%d", id);
1869
1870 gs = gs_get_surf(id);
1871 if (gs) {
1872 gsd_shademodel(gs->draw_mode & DM_GOURAUD);
1873
1874 if (gs->draw_mode & DM_POLY) {
1875 gsd_surf(gs);
1876 }
1877
1878 if (gs->draw_mode & DM_WIRE) {
1879 gsd_wire_surf(gs);
1880 }
1881
1882 /* TODO: write wire/poly draw routines */
1883 if (gs->draw_mode & DM_WIRE_POLY) {
1884 gsd_surf(gs);
1885 gsd_wire_surf(gs);
1886 }
1887 }
1888
1889 return;
1890 }
1891
1892 /*!
1893 \brief Draw surface wire
1894
1895 Overrides draw_mode for fast display
1896
1897 \param id surface id
1898 */
GS_draw_wire(int id)1899 void GS_draw_wire(int id)
1900 {
1901 geosurf *gs;
1902
1903 G_debug(3, "GS_draw_wire(): id=%d", id);
1904
1905 gs = gs_get_surf(id);
1906
1907 if (gs) {
1908 gsd_wire_surf(gs);
1909 }
1910
1911 return;
1912 }
1913
1914 /*!
1915 \brief Draw all wires
1916
1917 Overrides draw_mode for fast display
1918 */
GS_alldraw_wire(void)1919 void GS_alldraw_wire(void)
1920 {
1921 geosurf *gs;
1922 int i;
1923
1924 for (i = 0; i < Next_surf; i++) {
1925 if ((gs = gs_get_surf(Surf_ID[i]))) {
1926 gsd_wire_surf(gs);
1927 }
1928 }
1929
1930 return;
1931 }
1932
1933 /*!
1934 \brief Draw all surfaces
1935 */
GS_alldraw_surf(void)1936 void GS_alldraw_surf(void)
1937 {
1938 int i;
1939
1940 for (i = 0; i < Next_surf; i++) {
1941 GS_draw_surf(Surf_ID[i]);
1942 }
1943
1944 return;
1945 }
1946
1947 /*!
1948 \brief Set Z exag for surface
1949
1950 \param id surface id
1951 \param exag z-exag value
1952 */
GS_set_exag(int id,float exag)1953 void GS_set_exag(int id, float exag)
1954 {
1955 geosurf *gs;
1956
1957 G_debug(3, "GS_set_exag");
1958
1959 gs = gs_get_surf(id);
1960
1961 if (gs) {
1962 if (gs->z_exag != exag) {
1963 gs->norm_needupdate = 1;
1964 }
1965
1966 gs->z_exag = exag;
1967 }
1968
1969 return;
1970 }
1971
1972 /*!
1973 \brief Set global z-exag value
1974
1975 \param exag exag value to be set up
1976 */
GS_set_global_exag(float exag)1977 void GS_set_global_exag(float exag)
1978 {
1979
1980 G_debug(3, "GS_set_global_exag");
1981
1982 Gv.vert_exag = exag;
1983 /* GL_NORMALIZE */
1984 /* Only need to update norms gs_norms.c
1985 * if exag is used in norm equation which
1986 * it is not! If GL_NORMALIZE is disabled
1987 * will need to include.
1988 gs_setall_norm_needupdate();
1989 */
1990
1991 return;
1992 }
1993
1994 /*!
1995 \brief Get global z-exag value
1996
1997 \return value
1998 */
GS_global_exag(void)1999 float GS_global_exag(void)
2000 {
2001 G_debug(3, "GS_global_exag(): %g", Gv.vert_exag);
2002
2003 return (Gv.vert_exag);
2004 }
2005
2006 /*!
2007 \brief Set wire color
2008
2009 \todo error-handling
2010
2011 \param id surface id
2012 \param colr color value
2013 */
GS_set_wire_color(int id,int colr)2014 void GS_set_wire_color(int id, int colr)
2015 {
2016 geosurf *gs;
2017
2018 G_debug(3, "GS_set_wire_color");
2019
2020 gs = gs_get_surf(id);
2021
2022 if (gs) {
2023 gs->wire_color = colr;
2024 }
2025
2026 return;
2027 }
2028
2029 /*!
2030 \brief Get wire color
2031
2032 \param id surface id
2033 \param[out] colr color value
2034
2035 \return 1 on success
2036 \return -1 on error
2037 */
GS_get_wire_color(int id,int * colr)2038 int GS_get_wire_color(int id, int *colr)
2039 {
2040 geosurf *gs;
2041
2042 gs = gs_get_surf(id);
2043
2044 if (gs) {
2045 *colr = gs->wire_color;
2046
2047 return (1);
2048 }
2049
2050 return (-1);
2051 }
2052
2053 /*!
2054 \brief Set all draw-modes
2055
2056 \param mode mode id
2057
2058 \return 0 on success
2059 \return -1 on error
2060 */
GS_setall_drawmode(int mode)2061 int GS_setall_drawmode(int mode)
2062 {
2063 int i;
2064
2065 for (i = 0; i < Next_surf; i++) {
2066 if (0 != GS_set_drawmode(Surf_ID[i], mode)) {
2067 return (-1);
2068 }
2069 }
2070
2071 return (0);
2072 }
2073
2074 /*!
2075 \brief Set draw mode
2076
2077 \param id surface id
2078 \param mode mode type(s)
2079
2080 \return 0 on success
2081 \return -1 on error (invalid surface id)
2082 */
GS_set_drawmode(int id,int mode)2083 int GS_set_drawmode(int id, int mode)
2084 {
2085 geosurf *gs;
2086
2087 G_debug(3, "GS_set_drawmode(): id=%d mode=%d", id, mode);
2088
2089 gs = gs_get_surf(id);
2090
2091 if (gs) {
2092 gs->draw_mode = mode;
2093
2094 return (0);
2095 }
2096
2097 return (-1);
2098 }
2099
2100 /*!
2101 \brief Get draw mode
2102
2103 \param id surface id
2104 \param[out] mode mode id
2105
2106 \return 1 on success
2107 \return -1 on error (invalid surface id)
2108 */
GS_get_drawmode(int id,int * mode)2109 int GS_get_drawmode(int id, int *mode)
2110 {
2111 geosurf *gs;
2112
2113 gs = gs_get_surf(id);
2114
2115 if (gs) {
2116 *mode = gs->draw_mode;
2117
2118 return (1);
2119 }
2120
2121 return (-1);
2122 }
2123
2124 /*!
2125 \brief Set no-zero ?
2126
2127 \param id surface id
2128 \param att attribute id
2129 \param mode mode id
2130 */
GS_set_nozero(int id,int att,int mode)2131 void GS_set_nozero(int id, int att, int mode)
2132 {
2133 geosurf *gs;
2134
2135 G_debug(3, "GS_set_nozero");
2136
2137 gs = gs_get_surf(id);
2138
2139 if (gs) {
2140 if (att == ATT_TOPO) {
2141 gs->nz_topo = mode;
2142 gs->mask_needupdate = 1;
2143 }
2144
2145 if (att == ATT_COLOR) {
2146 gs->nz_color = mode;
2147 gs->mask_needupdate = 1;
2148 }
2149 }
2150
2151 return;
2152 }
2153
2154 /*!
2155 \brief Get no-zero ?
2156
2157 \param id surface id
2158 \param att attribute id
2159 \param[out] mode mode id
2160
2161 \return -1 on error (invalid surface id)
2162 \return 1 on success
2163 */
GS_get_nozero(int id,int att,int * mode)2164 int GS_get_nozero(int id, int att, int *mode)
2165 {
2166 geosurf *gs;
2167
2168 G_debug(3, "GS_set_nozero");
2169
2170 gs = gs_get_surf(id);
2171
2172 if (gs) {
2173 if (att == ATT_TOPO) {
2174 *mode = gs->nz_topo;
2175 }
2176 else if (att == ATT_COLOR) {
2177 *mode = gs->nz_color;
2178 }
2179 else {
2180 return (-1);
2181 }
2182
2183 return (1);
2184 }
2185
2186 return (-1);
2187 }
2188
2189 /*!
2190 \brief Set all draw resolutions
2191
2192 \param xres,yres x/y resolution value
2193 \param xwire,ywire x/y wire value
2194
2195 \return 0 on success
2196 \return -1 on error
2197 */
GS_setall_drawres(int xres,int yres,int xwire,int ywire)2198 int GS_setall_drawres(int xres, int yres, int xwire, int ywire)
2199 {
2200 int i;
2201
2202 for (i = 0; i < Next_surf; i++) {
2203 if (0 != GS_set_drawres(Surf_ID[i], xres, yres, xwire, ywire)) {
2204 return (-1);
2205 }
2206 }
2207
2208 return (0);
2209 }
2210
2211 /*!
2212 \brief Set draw resolution for surface
2213
2214 \param id surface id
2215 \param xres,yres x/y resolution value
2216 \param xwire,ywire x/y wire value
2217
2218 \return -1 on error
2219 \return 0 on success
2220 */
GS_set_drawres(int id,int xres,int yres,int xwire,int ywire)2221 int GS_set_drawres(int id, int xres, int yres, int xwire, int ywire)
2222 {
2223 geosurf *gs;
2224
2225 G_debug(3, "GS_set_drawres() id=%d xyres=%d/%d xywire=%d/%d",
2226 id, xres, yres, xwire, ywire);
2227
2228 if (xres < 1 || yres < 1 || xwire < 1 || ywire < 1) {
2229 return (-1);
2230 }
2231
2232 gs = gs_get_surf(id);
2233
2234 if (gs) {
2235 if (gs->x_mod != xres || gs->y_mod != yres) {
2236 gs->norm_needupdate = 1;
2237 }
2238
2239 gs->x_mod = xres;
2240 gs->y_mod = yres;
2241 gs->x_modw = xwire;
2242 gs->y_modw = ywire;
2243 }
2244
2245 return (0);
2246 }
2247
2248 /*!
2249 \brief Get draw resolution of surface
2250
2251 \param id surface id
2252 \param[out] xres,yres x/y resolution value
2253 \param[out] xwire,ywire x/y wire value
2254 */
GS_get_drawres(int id,int * xres,int * yres,int * xwire,int * ywire)2255 void GS_get_drawres(int id, int *xres, int *yres, int *xwire, int *ywire)
2256 {
2257 geosurf *gs;
2258
2259 G_debug(3, "GS_get_drawres");
2260
2261 gs = gs_get_surf(id);
2262
2263 if (gs) {
2264 *xres = gs->x_mod;
2265 *yres = gs->y_mod;
2266 *xwire = gs->x_modw;
2267 *ywire = gs->y_modw;
2268 }
2269
2270 return;
2271 }
2272
2273 /*!
2274 \brief Get dimension of surface
2275
2276 \param id surface id
2277 \param[out] rows,cols number of rows/cols
2278 */
GS_get_dims(int id,int * rows,int * cols)2279 void GS_get_dims(int id, int *rows, int *cols)
2280 {
2281 geosurf *gs;
2282
2283 gs = gs_get_surf(id);
2284
2285 if (gs) {
2286 *rows = gs->rows;
2287 *cols = gs->cols;
2288 }
2289
2290 return;
2291 }
2292
2293 /*!
2294 \brief Get exag-value guess
2295
2296 Use no_zero range because if zero IS data, then range won't be that
2297 much off (it's just a GUESS, after all), but if zero is NO data, could
2298 drastically affect guess
2299
2300 \param id surface id
2301 \param[out] exag exag value
2302
2303 \return 1 on success
2304 \return -1 on error
2305 */
GS_get_exag_guess(int id,float * exag)2306 int GS_get_exag_guess(int id, float *exag)
2307 {
2308 geosurf *gs;
2309 float guess;
2310
2311 gs = gs_get_surf(id);
2312 guess = 1.0;
2313
2314 /* if gs is type const return guess = 1.0 */
2315 if (CONST_ATT == gs_get_att_src(gs, ATT_TOPO)) {
2316 *exag = guess;
2317 return (1);
2318 }
2319
2320 if (gs) {
2321 if (gs->zrange_nz == 0.0) {
2322 *exag = 0.0;
2323
2324 return (1);
2325 }
2326
2327 G_debug(3, "GS_get_exag_guess(): %f %f", gs->zrange_nz, Longdim);
2328
2329 while (gs->zrange_nz * guess / Longdim >= .25) {
2330 guess *= .1;
2331
2332 G_debug(3, "GS_get_exag_guess(): %f", guess);
2333 }
2334
2335 while (gs->zrange_nz * guess / Longdim < .025) {
2336 guess *= 10.;
2337
2338 G_debug(3, "GS_get_exag_guess(): %f", guess);
2339 }
2340
2341 *exag = guess;
2342
2343 return (1);
2344 }
2345
2346 return (-1);
2347 }
2348
2349 /*!
2350 \brief Get Z extents for all loaded surfaces
2351
2352 Treating zeros as "no data"
2353
2354 \param[out] min min value
2355 \param[out] max max value
2356 */
GS_get_zrange_nz(float * min,float * max)2357 void GS_get_zrange_nz(float *min, float *max)
2358 {
2359 int i, first = 1;
2360 geosurf *gs;
2361
2362 for (i = 0; i < Next_surf; i++) {
2363 if ((gs = gs_get_surf(Surf_ID[i]))) {
2364 if (first) {
2365 first = 0;
2366 *min = gs->zmin_nz;
2367 *max = gs->zmax_nz;
2368 }
2369
2370 if (gs->zmin_nz < *min) {
2371 *min = gs->zmin_nz;
2372 }
2373
2374 if (gs->zmax_nz > *max) {
2375 *max = gs->zmax_nz;
2376 }
2377 }
2378 }
2379
2380 G_debug(3, "GS_get_zrange_nz(): min=%g max=%g", *min, *max);
2381
2382 return;
2383 }
2384
2385 /*!
2386 \brief Set translation (surface position)
2387
2388 \param id surface id
2389 \param xtrans,ytrans,ztrans translation values
2390 */
GS_set_trans(int id,float xtrans,float ytrans,float ztrans)2391 void GS_set_trans(int id, float xtrans, float ytrans, float ztrans)
2392 {
2393 geosurf *gs;
2394
2395 gs = gs_get_surf(id);
2396
2397 if (gs) {
2398 gs->x_trans = xtrans;
2399 gs->y_trans = ytrans;
2400 gs->z_trans = ztrans;
2401 }
2402
2403 G_debug(3, "GS_set_trans(): id=%d, x=%f, y=%f, z=%f",
2404 id, xtrans, ytrans, ztrans);
2405
2406 return;
2407 }
2408
2409 /*!
2410 \brief Get translation values (surface position)
2411
2412 \param id surface id
2413 \param[out] xtrans,ytrans,ztrans trans values
2414 */
GS_get_trans(int id,float * xtrans,float * ytrans,float * ztrans)2415 void GS_get_trans(int id, float *xtrans, float *ytrans, float *ztrans)
2416 {
2417 geosurf *gs;
2418
2419 gs = gs_get_surf(id);
2420
2421 if (gs) {
2422 *xtrans = gs->x_trans;
2423 *ytrans = gs->y_trans;
2424 *ztrans = gs->z_trans;
2425 }
2426
2427 G_debug(3, "GS_get_trans: id=%d, x=%f, y=%f, z=%f",
2428 id, *xtrans, *ytrans, *ztrans);
2429
2430 return;
2431 }
2432
2433
2434 /*!
2435 \brief Get default draw color
2436
2437 \return color value
2438 */
GS_default_draw_color(void)2439 unsigned int GS_default_draw_color(void)
2440 {
2441
2442 G_debug(3, "GS_default_draw_color");
2443
2444 return ((unsigned int)Gd.bgcol);
2445 }
2446
2447 /*!
2448 \brief Get background color
2449
2450 \return color value
2451 */
GS_background_color(void)2452 unsigned int GS_background_color(void)
2453 {
2454 return ((unsigned int)Gd.bgcol);
2455 }
2456
2457 /*!
2458 \brief Sets which buffer to draw to
2459
2460 \param where GSD_BOTH, GSD_FRONT, GSD_BACK
2461 */
GS_set_draw(int where)2462 void GS_set_draw(int where)
2463 {
2464 Buffermode = where;
2465
2466 switch (where) {
2467 case GSD_BOTH:
2468 gsd_bothbuffers();
2469
2470 break;
2471 case GSD_FRONT:
2472 gsd_frontbuffer();
2473
2474 break;
2475 case GSD_BACK:
2476 default:
2477 gsd_backbuffer();
2478
2479 break;
2480 }
2481
2482 return;
2483 }
2484
2485 /*
2486 \brief Ready to draw
2487 */
GS_ready_draw(void)2488 void GS_ready_draw(void)
2489 {
2490
2491 G_debug(3, "GS_ready_draw");
2492
2493 gsd_set_view(&Gv, &Gd);
2494
2495 return;
2496 }
2497
2498 /*!
2499 \brief Draw done, swap buffers
2500 */
GS_done_draw(void)2501 void GS_done_draw(void)
2502 {
2503
2504 G_debug(3, "GS_done_draw");
2505
2506 if (GSD_BACK == Buffermode) {
2507 gsd_swapbuffers();
2508 }
2509
2510 gsd_flush();
2511
2512 return;
2513 }
2514
2515 /*!
2516 \brief Set focus
2517
2518 \param realto real coordinates to
2519 */
GS_set_focus(float * realto)2520 void GS_set_focus(float *realto)
2521 {
2522
2523 G_debug(3, "GS_set_focus(): %f,%f,%f", realto[0], realto[1], realto[2]);
2524
2525 Gv.infocus = 1;
2526 GS_v3eq(Gv.real_to, realto);
2527
2528 gsd_set_view(&Gv, &Gd);
2529
2530 return;
2531 }
2532
2533 /*!
2534 \brief Set real focus
2535
2536 \param realto real coordinates to
2537 */
GS_set_focus_real(float * realto)2538 void GS_set_focus_real(float *realto)
2539 {
2540
2541 G_get_set_window(&wind);
2542 realto[X] = realto[X] - wind.west - (wind.ew_res / 2.);
2543 realto[Y] = realto[Y] - wind.south - (wind.ns_res / 2.);
2544
2545 Gv.infocus = 1;
2546 GS_v3eq(Gv.real_to, realto);
2547
2548 gsd_set_view(&Gv, &Gd);
2549
2550 return;
2551 }
2552
2553
2554 /*!
2555 \brief Get focus
2556
2557 OK to call with NULL argument if just want to check state
2558
2559 \param realto real coordinates to
2560
2561 \return ?
2562 */
GS_get_focus(float * realto)2563 int GS_get_focus(float *realto)
2564 {
2565
2566 G_debug(3, "GS_get_focus");
2567
2568 if (Gv.infocus) {
2569 if (realto) {
2570 GS_v3eq(realto, Gv.real_to);
2571 }
2572 }
2573
2574 return (Gv.infocus);
2575 }
2576
2577 /*!
2578 \brief Set focus to map center
2579
2580 \param id surface id
2581 */
GS_set_focus_center_map(int id)2582 void GS_set_focus_center_map(int id)
2583 {
2584 float center[3];
2585 geosurf *gs;
2586
2587 G_debug(3, "GS_set_focus_center_map");
2588
2589 gs = gs_get_surf(id);
2590
2591 if (gs) {
2592 center[X] = (gs->xmax - gs->xmin) / 2.;
2593 center[Y] = (gs->ymax - gs->ymin) / 2.;
2594 center[Z] = (gs->zmax_nz + gs->zmin_nz) / 2.;
2595
2596 /* not yet working
2597 buff = gs_get_att_typbuff(gs, ATT_TOPO, 0);
2598 offset = gs->rows*gs->cols/2 + gs->cols/2;
2599 if (buff)
2600 {
2601 if (GET_MAPATT(buff, offset, tmp))
2602 {
2603 center[Z] = tmp;
2604 }
2605 }
2606 */
2607
2608 GS_set_focus(center);
2609 }
2610 }
2611
2612 /*!
2613 \brief Move viewpoint
2614
2615 \param pt 'from' model coordinates
2616 */
GS_moveto(float * pt)2617 void GS_moveto(float *pt)
2618 {
2619 float ft[3];
2620
2621 G_debug(3, "GS_moveto(): %f,%f,%f", pt[0], pt[1], pt[2]);
2622
2623 if (Gv.infocus) {
2624 GS_v3eq(Gv.from_to[FROM], pt);
2625 /*
2626 GS_v3eq(Gv.from_to[TO], Gv.real_to);
2627 */
2628 GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
2629 /* update inclination, look_dir if we're keeping these */
2630 }
2631 else {
2632 GS_v3eq(ft, Gv.from_to[TO]);
2633 GS_v3sub(ft, Gv.from_to[FROM]);
2634 GS_v3eq(Gv.from_to[FROM], pt);
2635 GS_v3eq(Gv.from_to[TO], pt);
2636 GS_v3add(Gv.from_to[TO], ft);
2637 }
2638
2639 return;
2640 }
2641
2642 /*!
2643 \brief Move position to (real)
2644
2645 \param pt point real coordinates
2646 */
GS_moveto_real(float * pt)2647 void GS_moveto_real(float *pt)
2648 {
2649 gsd_real2model(pt);
2650 GS_moveto(pt);
2651
2652 return;
2653 }
2654
2655 /*!
2656 \brief Get z-extent for a single surface
2657
2658 \param id surface id
2659 \param[out] min min z-value
2660 \param[out] max max z-value
2661 \param[out] mid middle z-value
2662
2663 \return -1 on error (invalid surface id)
2664 \return ?
2665 */
GS_get_zextents(int id,float * min,float * max,float * mid)2666 int GS_get_zextents(int id, float *min, float *max, float *mid)
2667 {
2668 geosurf *gs;
2669
2670 if (NULL == (gs = gs_get_surf(id))) {
2671 return (-1);
2672 }
2673
2674 G_debug(3, "GS_get_zextents(): id=%d", id);
2675
2676 return (gs_get_zextents(gs, min, max, mid));
2677 }
2678
2679 /*!
2680 \brief Get z-extent for all loaded surfaces
2681
2682 \param[out] min min z-value
2683 \param[out] max max z-value
2684 \param doexag use z-exaggeration
2685
2686 \return 1 on success
2687 \return -1 on error
2688 */
GS_get_zrange(float * min,float * max,int doexag)2689 int GS_get_zrange(float *min, float *max, int doexag)
2690 {
2691 int ret_surf, ret_vol;
2692 float surf_min, surf_max;
2693 float vol_min, vol_max;
2694
2695 ret_surf = gs_get_zrange(&surf_min, &surf_max);
2696 ret_vol = gvl_get_zrange(&vol_min, &vol_max);
2697
2698 if (ret_surf > 0 && ret_vol > 0) {
2699 *min = (surf_min < vol_min) ? surf_min : vol_min;
2700 *max = (surf_max < vol_max) ? surf_max : vol_max;
2701 }
2702 else if (ret_surf > 0) {
2703 *min = surf_min;
2704 *max = surf_max;
2705 }
2706 else if (ret_vol > 0) {
2707 *min = vol_min;
2708 *max = vol_max;
2709 }
2710
2711 if (doexag) {
2712 *min *= Gv.vert_exag;
2713 *max *= Gv.vert_exag;
2714 }
2715
2716 G_debug(3, "GS_get_zrange(): min=%g max=%g", *min, *max);
2717 return ((ret_surf > 0 || ret_vol > 0) ? (1) : (-1));
2718 }
2719
2720 /*!
2721 \brief Get viewpoint 'from' position
2722
2723 \param[out] fr from model coordinates
2724 */
GS_get_from(float * fr)2725 void GS_get_from(float *fr)
2726 {
2727 GS_v3eq(fr, Gv.from_to[FROM]);
2728
2729 G_debug(3, "GS_get_from(): %f,%f,%f", fr[0], fr[1], fr[2]);
2730
2731 return;
2732 }
2733
2734 /*!
2735 \brief Get viewpoint 'from' real coordinates
2736
2737 \param[out] fr 'from' real coordinates
2738 */
GS_get_from_real(float * fr)2739 void GS_get_from_real(float *fr)
2740 {
2741 GS_v3eq(fr, Gv.from_to[FROM]);
2742 gsd_model2real(fr);
2743
2744 return;
2745 }
2746
2747 /*!
2748 \brief Get 'to' real coordinates
2749
2750 \param[out] to 'to' real coordinates
2751 */
GS_get_to_real(float * to)2752 void GS_get_to_real(float *to)
2753 {
2754 float realto[3];
2755
2756 G_get_set_window(&wind);
2757 GS_get_focus(realto);
2758 to[X] = realto[X] + wind.west + (wind.ew_res / 2.);
2759 to[Y] = realto[Y] + wind.south + (wind.ns_res / 2.);
2760 to[Z] = realto[Z];
2761
2762 return;
2763 }
2764
2765
2766 /*!
2767 \brief Get zoom setup
2768
2769 \param[out] a,b,c,d current viewport settings
2770 \param[out] maxx,maxy max viewport size
2771 */
GS_zoom_setup(int * a,int * b,int * c,int * d,int * maxx,int * maxy)2772 void GS_zoom_setup(int *a, int *b, int *c, int *d, int *maxx, int *maxy)
2773 {
2774 GLint tmp[4];
2775 GLint num[2];
2776
2777 gsd_getViewport(tmp, num);
2778 *a = tmp[0];
2779 *b = tmp[1];
2780 *c = tmp[2];
2781 *d = tmp[3];
2782 *maxx = num[0];
2783 *maxy = num[1];
2784
2785 return;
2786 }
2787
2788 /*!
2789 \brief Get 'to' model coordinates
2790
2791 \todo need set_to? - just use viewdir?
2792
2793 \param[out] to 'to' model coordinates
2794 */
GS_get_to(float * to)2795 void GS_get_to(float *to)
2796 {
2797 G_debug(3, "GS_get_to");
2798
2799 GS_v3eq(to, Gv.from_to[TO]);
2800
2801 return;
2802 }
2803
2804 /*!
2805 \brief Get viewdir
2806
2807 \param[out] dir viewdir value
2808 */
GS_get_viewdir(float * dir)2809 void GS_get_viewdir(float *dir)
2810 {
2811 GS_v3dir(Gv.from_to[FROM], Gv.from_to[TO], dir);
2812
2813 return;
2814 }
2815
2816 /*!
2817 \brief Set viewdir
2818
2819 Automatically turns off focus
2820
2821 \param dir viewdir value
2822 */
GS_set_viewdir(float * dir)2823 void GS_set_viewdir(float *dir)
2824 {
2825 float tmp[3];
2826
2827 GS_v3eq(tmp, dir);
2828 GS_v3norm(tmp);
2829 GS_v3eq(Gv.from_to[TO], Gv.from_to[FROM]);
2830 GS_v3add(Gv.from_to[TO], tmp);
2831
2832 GS_set_nofocus();
2833 gsd_set_view(&Gv, &Gd);
2834
2835 return;
2836 }
2837
2838 /*!
2839 \brief Set field of view
2840
2841 \param fov fov value
2842 */
GS_set_fov(int fov)2843 void GS_set_fov(int fov)
2844 {
2845 Gv.fov = fov;
2846
2847 return;
2848 }
2849
2850 /*!
2851 \brief Get fied of view
2852
2853 \return field of view, in 10ths of degrees
2854 */
GS_get_fov(void)2855 int GS_get_fov(void)
2856 {
2857 return (Gv.fov);
2858 }
2859
2860 /*!
2861 \brief Get twist value
2862
2863 10ths of degrees off twelve o'clock
2864 */
GS_get_twist(void)2865 int GS_get_twist(void)
2866 {
2867 return (Gv.twist);
2868 }
2869
2870 /*!
2871 \brief Set viewpoint twist value
2872
2873 10ths of degrees off twelve o'clock
2874
2875 \param t tenths of degrees clockwise from 12:00.
2876 */
GS_set_twist(int t)2877 void GS_set_twist(int t)
2878 {
2879 Gv.twist = t;
2880
2881 return;
2882 }
2883
2884 /*!
2885 \brief Set rotation params
2886 */
GS_set_rotation(double angle,double x,double y,double z)2887 void GS_set_rotation(double angle, double x, double y, double z)
2888 {
2889 Gv.rotate.rot_angle = angle;
2890 Gv.rotate.rot_axes[0] = x;
2891 Gv.rotate.rot_axes[1] = y;
2892 Gv.rotate.rot_axes[2] = z;
2893 Gv.rotate.do_rot = 1;
2894
2895 return;
2896 }
2897
2898 /*!
2899 \brief Stop scene rotation
2900 */
GS_unset_rotation(void)2901 void GS_unset_rotation(void)
2902 {
2903 Gv.rotate.do_rot = 0;
2904 }
2905
2906 /*!
2907 \brief Reset scene rotation
2908 */
GS_init_rotation(void)2909 void GS_init_rotation(void)
2910 {
2911 int i;
2912
2913 for (i = 0; i < 16; i++) {
2914 if (i == 0 || i == 5 || i == 10 || i == 15)
2915 Gv.rotate.rotMatrix[i] = 1.0;
2916 else
2917 Gv.rotate.rotMatrix[i] = 0.0;
2918 }
2919 Gv.rotate.rot_angle = 0.0;
2920 Gv.rotate.rot_axes[0] = 0.0;
2921 Gv.rotate.rot_axes[1] = 0.0;
2922 Gv.rotate.rot_axes[2] = 0.0;
2923 Gv.rotate.do_rot = 0;
2924
2925 }
2926 /*!
2927 * \brief Get rotation matrix
2928 */
GS_get_rotation_matrix(double * matrix)2929 void GS_get_rotation_matrix(double *matrix)
2930 {
2931 int i;
2932
2933 for (i = 0; i < 16; i++) {
2934 matrix[i] = Gv.rotate.rotMatrix[i];
2935 }
2936 }
2937
2938 /*!
2939 * \brief Set rotation matrix
2940 */
GS_set_rotation_matrix(double * matrix)2941 void GS_set_rotation_matrix(double *matrix)
2942 {
2943 int i;
2944
2945 for (i = 0; i < 16; i++) {
2946 Gv.rotate.rotMatrix[i] = matrix[i];
2947 }
2948 }
2949
2950 /*!
2951 \brief Unset focus
2952 */
GS_set_nofocus(void)2953 void GS_set_nofocus(void)
2954 {
2955 G_debug(3, "GS_set_nofocus");
2956
2957 Gv.infocus = 0;
2958
2959 return;
2960 }
2961
2962 /*!
2963 \brief Set focus
2964
2965 Make sure that the center of view is set
2966 */
GS_set_infocus(void)2967 void GS_set_infocus(void)
2968 {
2969 G_debug(3, "GS_set_infocus");
2970
2971 Gv.infocus = 1;
2972
2973 return;
2974 }
2975
2976 /*!
2977 \brief Set viewport
2978
2979 \param left,right,bottom,top viewport extent values
2980 */
GS_set_viewport(int left,int right,int bottom,int top)2981 void GS_set_viewport(int left, int right, int bottom, int top)
2982 {
2983 G_debug(3, "GS_set_viewport(): left=%d, right=%d, "
2984 "bottom=%d, top=%d", left, right, bottom, top);
2985
2986 gsd_viewport(left, right, bottom, top);
2987
2988 return;
2989 }
2990
2991 /*!
2992 \brief Send screen coords sx and sy, lib traces through surfaces; sets
2993 new center to point of nearest intersection.
2994
2995 If no intersection, uses line of sight with length of current view
2996 ray (eye to center) to set new center.
2997
2998 Reset center of view to screen coordinates sx, sy.
2999
3000 \param sx,sy screen coordinates
3001
3002 \return 1 on success
3003 \return 0 on error (invalid surface id)
3004 */
GS_look_here(int sx,int sy)3005 int GS_look_here(int sx, int sy)
3006 {
3007 float x, y, z, len, los[2][3];
3008 Point3 realto, dir;
3009 int id;
3010 geosurf *gs;
3011
3012 if (GS_get_selected_point_on_surface(sx, sy, &id, &x, &y, &z)) {
3013 gs = gs_get_surf(id);
3014 if (gs) {
3015 realto[X] = x - gs->ox + gs->x_trans;
3016 realto[Y] = y - gs->oy + gs->y_trans;
3017 realto[Z] = z + gs->z_trans;
3018 GS_set_focus(realto);
3019
3020 return (1);
3021 }
3022 }
3023 else {
3024 if (gsd_get_los(los, (short)sx, (short)sy)) {
3025 len = GS_distance(Gv.from_to[FROM], Gv.real_to);
3026 GS_v3dir(los[FROM], los[TO], dir);
3027 GS_v3mult(dir, len);
3028 realto[X] = Gv.from_to[FROM][X] + dir[X];
3029 realto[Y] = Gv.from_to[FROM][Y] + dir[Y];
3030 realto[Z] = Gv.from_to[FROM][Z] + dir[Z];
3031 GS_set_focus(realto);
3032
3033 return (1);
3034 }
3035 }
3036
3037 return (0);
3038 }
3039
3040 /*!
3041 \brief Get selected point of surface
3042
3043 Given screen coordinates sx and sy, find closest intersection of
3044 view ray with surfaces and return coordinates of intersection in x, y,
3045 z, and identifier of surface in id.
3046
3047 \param sx,sy screen coordinates
3048 \param[out] id surface id
3049 \param[out] x,y,z point on surface (model coordinates?)
3050
3051 \returns 0 if no intersections found
3052 \return number of intersections
3053 */
GS_get_selected_point_on_surface(int sx,int sy,int * id,float * x,float * y,float * z)3054 int GS_get_selected_point_on_surface(int sx, int sy, int *id, float *x,
3055 float *y, float *z)
3056 {
3057 float los[2][3], find_dist[MAX_SURFS], closest;
3058 Point3 point, tmp, finds[MAX_SURFS];
3059 int surfs[MAX_SURFS], i, iclose, numhits = 0;
3060 geosurf *gs;
3061
3062 /* returns surface-world coords */
3063 gsd_get_los(los, (short)sx, (short)sy);
3064
3065 if (!gs_setlos_enterdata(los)) {
3066 G_debug(3, "gs_setlos_enterdata(los): returns false");
3067 return (0);
3068 }
3069
3070 for (i = 0; i < Next_surf; i++) {
3071 G_debug(3, "id=%d", i);
3072
3073 gs = gs_get_surf(Surf_ID[i]);
3074
3075 /* los_intersect expects surf-world coords (xy transl, no scaling) */
3076
3077 #if NVIZ_HACK
3078 if (gs_los_intersect1(Surf_ID[i], los, point)) {
3079 #else
3080 if (gs_los_intersect(Surf_ID[i], los, point)) {
3081 #endif
3082 if (!gs_point_is_masked(gs, point)) {
3083 GS_v3eq(tmp, point);
3084 tmp[X] += gs->x_trans;
3085 tmp[Y] += gs->y_trans;
3086 tmp[Z] += gs->z_trans;
3087 find_dist[numhits] = GS_distance(los[FROM], tmp);
3088 gsd_surf2real(gs, point);
3089 GS_v3eq(finds[numhits], point);
3090 surfs[numhits] = Surf_ID[i];
3091 numhits++;
3092 }
3093 }
3094 }
3095
3096 for (i = iclose = 0; i < numhits; i++) {
3097 closest = find_dist[iclose];
3098
3099 if (find_dist[i] < closest) {
3100 iclose = i;
3101 }
3102 }
3103
3104 if (numhits) {
3105 *x = finds[iclose][X];
3106 *y = finds[iclose][Y];
3107 *z = finds[iclose][Z];
3108 *id = surfs[iclose];
3109 }
3110
3111 G_debug(3, "NumHits %d, next %d", numhits, Next_surf);
3112
3113 return (numhits);
3114 }
3115
3116 /*!
3117 \brief Set cplace rotation
3118
3119 \param num cplace id
3120 \param dx,dy,dz rotation values
3121 */
3122 void GS_set_cplane_rot(int num, float dx, float dy, float dz)
3123 {
3124 gsd_cplane_setrot(num, dx, dy, dz);
3125
3126 return;
3127 }
3128
3129 /*!
3130 \brief Set cplace trans
3131
3132 \param num cplace id
3133 \param dx,dy,dz rotation values
3134 */
3135 void GS_set_cplane_trans(int num, float dx, float dy, float dz)
3136 {
3137 gsd_cplane_settrans(num, dx, dy, dz);
3138
3139 return;
3140 }
3141
3142
3143 /*!
3144 \brief Draw cplace
3145
3146 \param num cplace id
3147 */
3148 void GS_draw_cplane(int num)
3149 {
3150 geosurf *gsurfs[MAX_SURFS];
3151 int nsurfs;
3152
3153 nsurfs = gs_num_surfaces();
3154 if (2 == nsurfs) {
3155 /* testing */
3156 gs_getall_surfaces(gsurfs);
3157 gsd_draw_cplane_fence(gsurfs[0], gsurfs[1], num);
3158 }
3159 else {
3160 gsd_draw_cplane(num);
3161 }
3162
3163 return;
3164 }
3165
3166 /*!
3167 \brief Draw cplace fence ?
3168
3169 \param hs1,hs2
3170 \param num cplane id
3171
3172 \return 0 on error
3173 \return 1 on success
3174 */
3175 int GS_draw_cplane_fence(int hs1, int hs2, int num)
3176 {
3177 geosurf *gs1, *gs2;
3178
3179 if (NULL == (gs1 = gs_get_surf(hs1))) {
3180 return (0);
3181 }
3182
3183 if (NULL == (gs2 = gs_get_surf(hs2))) {
3184 return (0);
3185 }
3186
3187 gsd_draw_cplane_fence(gs1, gs2, num);
3188
3189 return (1);
3190 }
3191
3192 /*!
3193 \brief Draw all cplace fences ?
3194 */
3195 void GS_alldraw_cplane_fences(void)
3196 {
3197 int onstate[MAX_CPLANES], i;
3198
3199 gsd_get_cplanes_state(onstate);
3200
3201 for (i = 0; i < MAX_CPLANES; i++) {
3202 if (onstate[i]) {
3203 GS_draw_cplane_fence(Surf_ID[0], Surf_ID[1], i);
3204 }
3205 }
3206
3207 return;
3208 }
3209
3210 /*!
3211 \brief Set cplace
3212
3213 \param num cplane id
3214 */
3215 void GS_set_cplane(int num)
3216 {
3217 gsd_cplane_on(num);
3218
3219 return;
3220 }
3221
3222 /*!
3223 \brief Unset clip place (turn off)
3224
3225 \param num cplane id
3226 */
3227 void GS_unset_cplane(int num)
3228 {
3229 gsd_cplane_off(num);
3230
3231 return;
3232 }
3233
3234 /*!
3235 \brief Get axis scale
3236
3237 \param sx,sy,sz x/y/z scale values
3238 \param doexag use vertical exaggeration
3239 */
3240 void GS_get_scale(float *sx, float *sy, float *sz, int doexag)
3241 {
3242 float zexag;
3243
3244 zexag = doexag ? Gv.vert_exag : 1.;
3245 *sx = *sy = Gv.scale;
3246 *sz = Gv.scale * zexag;
3247
3248 return;
3249 }
3250
3251 /*!
3252 \brief Set fence color
3253
3254 \param mode mode id
3255 */
3256 void GS_set_fencecolor(int mode)
3257 {
3258 gsd_setfc(mode);
3259
3260 return;
3261 }
3262
3263 /*!
3264 \brief Get fence color
3265
3266 \return color value
3267 */
3268 int GS_get_fencecolor(void)
3269 {
3270 return gsd_getfc();
3271 }
3272
3273 /*!
3274 \brief Measure distance "as the ball rolls" between two points on
3275 surface
3276
3277 \param hs surface id
3278 \param x1,y1,x2,y2 two points on surface
3279 \param[out] dist measured distance
3280 \param use_exag use exag. surface
3281
3282 \return 0 on error or if one or more points is not in region
3283 \return distance following terrain
3284 */
3285 int GS_get_distance_alongsurf(int hs, float x1, float y1, float x2, float y2,
3286 float *dist, int use_exag)
3287 {
3288 geosurf *gs;
3289 float p1[2], p2[2];
3290
3291 gs = gs_get_surf(hs);
3292 if (gs == NULL) {
3293 return 0;
3294 }
3295
3296 p1[X] = x1;
3297 p1[Y] = y1;
3298 p2[X] = x2;
3299 p2[Y] = y2;
3300 gsd_real2surf(gs, p1);
3301 gsd_real2surf(gs, p2);
3302
3303 G_debug(3, "GS_get_distance_alongsurf(): hs=%d p1=%f,%f p2=%f,%f",
3304 hs, x1, y1, x2, y2);
3305 return gs_distance_onsurf(gs, p1, p2, dist, use_exag);
3306 }
3307
3308 /*!
3309 \brief Save 3d view
3310
3311 \param vname view file name
3312 \param surfid surface id
3313
3314 \return ?
3315 */
3316 int GS_save_3dview(const char *vname, int surfid)
3317 {
3318 return (Gs_save_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
3319 }
3320
3321 /*!
3322 \brief Load 3d view
3323
3324 \param vname view file name
3325 \param surfid surface id
3326
3327 \return ?
3328 */
3329 int GS_load_3dview(const char *vname, int surfid)
3330 {
3331
3332 return (Gs_load_3dview(vname, &Gv, &Gd, &wind, gs_get_surf(surfid)));
3333
3334 /* what to do about lights - I guess, delete all &
3335 create any that exist in 3dview file */
3336 }
3337
3338 /************************************************************************
3339 * Following routines use Graphics Library
3340 ************************************************************************/
3341
3342 /*!
3343 \brief Init viewpoint
3344
3345 \todo allow setting center?
3346 */
3347 void GS_init_view(void)
3348 {
3349 static int first = 1;
3350
3351 G_debug(3, "GS_init_view");
3352
3353 if (first) {
3354 first = 0;
3355 glMatrixMode(GL_MODELVIEW);
3356
3357 /* OGLXXX doublebuffer: use GLX_DOUBLEBUFFER in attriblist */
3358 /* glxChooseVisual(*dpy, screen, *attriblist); */
3359 /* OGLXXX
3360 * ZMIN not needed -- always 0.
3361 * ZMAX not needed -- always 1.
3362 * getgdesc other posiblilties:
3363 * glxGetConfig();
3364 * glxGetCurrentContext();
3365 * glxGetCurrentDrawable();
3366 * GLint gdtmp;
3367 * getgdesc other posiblilties:
3368 * glxGetConfig();
3369 * glxGetCurrentContext();
3370 * glxGetCurrentDrawable();
3371 * GLint gdtmp;
3372 * glDepthRange params must be scaled to [0, 1]
3373 */
3374 glDepthRange(0.0, 1.0);
3375 glEnable(GL_DEPTH_TEST);
3376 glDepthFunc(GL_LEQUAL);
3377 /* } */
3378
3379 /* replace these with something meaningful */
3380 Gv.fov = 450;
3381 Gv.twist = 0;
3382
3383 GS_init_rotation();
3384
3385 Gv.from_to[FROM][X] = Gv.from_to[FROM][Y] =
3386 Gv.from_to[FROM][Z] = GS_UNIT_SIZE / 2.;
3387
3388 Gv.from_to[TO][X] = GS_UNIT_SIZE / 2.;
3389 Gv.from_to[TO][Y] = GS_UNIT_SIZE / 2.;
3390 Gv.from_to[TO][Z] = 0.;
3391 Gv.from_to[TO][W] = Gv.from_to[FROM][W] = 1.;
3392
3393 Gv.real_to[W] = 1.;
3394 Gv.vert_exag = 1.;
3395
3396 GS_v3eq(Gv.real_to, Gv.from_to[TO]);
3397 GS_v3normalize(Gv.from_to[FROM], Gv.from_to[TO]);
3398
3399 /*
3400 Gd.nearclip = 50;
3401 Gd.farclip = 10000.;
3402 */
3403 Gd.nearclip = 10.;
3404 Gd.farclip = 10000.;
3405 Gd.aspect = (float)GS_get_aspect();
3406
3407 GS_set_focus(Gv.real_to);
3408 }
3409
3410 return;
3411 }
3412
3413 /*!
3414 \brief Clear view
3415
3416 \param col color value
3417 */
3418 void GS_clear(int col)
3419 {
3420 G_debug(3, "GS_clear");
3421
3422 col = col | 0xFF000000;
3423
3424 /* OGLXXX
3425 * change glClearDepth parameter to be in [0, 1]
3426 * ZMAX not needed -- always 1.
3427 * getgdesc other posiblilties:
3428 * glxGetConfig();
3429 * glxGetCurrentContext();
3430 * glxGetCurrentDrawable();
3431 * GLint gdtmp;
3432 */
3433 glClearDepth(1.0);
3434 glClearColor(((float)((col) & 0xff)) / 255.,
3435 (float)((col) >> 8 & 0xff) / 255.,
3436 (float)((col) >> 16 & 0xff) / 255.,
3437 (float)((col) >> 24 & 0xff) / 255.);
3438 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
3439
3440 Gd.bgcol = col;
3441 Modelshowing = 0;
3442 gsd_flush();
3443
3444 return;
3445 }
3446
3447 /*!
3448 \brief Get aspect value
3449
3450 \return aspect value
3451 */
3452 double GS_get_aspect(void)
3453 {
3454 int left, right, bottom, top;
3455 GLint tmp[4];
3456
3457 /* OGLXXX
3458 * get GL_VIEWPORT:
3459 * You can probably do better than this.
3460 */
3461 glGetIntegerv(GL_VIEWPORT, tmp);
3462 left = tmp[0];
3463 right = tmp[0] + tmp[2] - 1;
3464 bottom = tmp[1];
3465 top = tmp[1] + tmp[3] - 1;
3466
3467 G_debug(3, "GS_get_aspect(): left=%d, right=%d, top=%d, bottom=%d",
3468 left, right, top, bottom);
3469
3470 return ((double)(right - left) / (top - bottom));
3471 }
3472
3473 /*!
3474 \brief Check for transparency
3475
3476 Disabled.
3477
3478 \return 1
3479 */
3480 int GS_has_transparency(void)
3481 {
3482 /* OGLXXX
3483 * getgdesc other posiblilties:
3484 * glxGetConfig();
3485 * glxGetCurrentContext();
3486 * glxGetCurrentDrawable();
3487 * GLint gdtmp;
3488 * blending is ALWAYS supported.
3489 * This function returns whether it is enabled.
3490 * return((glGetIntegerv(GL_BLEND, &gdtmp), gdtmp));
3491 */
3492
3493 return (1);
3494 }
3495