1 /*!
2 \file lib/ogsf/gsd_prim.c
3
4 \brief OGSF library - primitive drawing functions (lower level functions)
5
6 GRASS OpenGL gsurf OGSF Library
7
8 (C) 1999-2008, 2018 by the GRASS Development Team
9
10 This program is free software under the
11 GNU General Public License (>=v2).
12 Read the file COPYING that comes with GRASS
13 for details.
14
15 \author Bill Brown USACERL (January 1993)
16 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
17 \author Support for framebuffer objects by Huidae Cho <grass4u gmail.com> (July 2018)
18 */
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <grass/config.h>
24
25 #if defined(OPENGL_X11)
26 #include <GL/gl.h>
27 #include <GL/glu.h>
28 #include <GL/glx.h>
29 #elif defined(OPENGL_AQUA)
30 #include <OpenGL/gl.h>
31 #include <OpenGL/glu.h>
32 #if defined(OPENGL_AGL)
33 #include <AGL/agl.h>
34 #endif
35 #elif defined(OPENGL_WINDOWS)
36 #include <GL/gl.h>
37 #include <GL/glu.h>
38 #include <wingdi.h>
39 #endif
40
41 #include <grass/gis.h>
42 #include <grass/ogsf.h>
43 #include <grass/glocale.h>
44
45 #define USE_GL_NORMALIZE
46
47 #define RED_MASK 0x000000FF
48 #define GRN_MASK 0x0000FF00
49 #define BLU_MASK 0x00FF0000
50 #define ALP_MASK 0xFF000000
51
52 #define INT_TO_RED(i, r) (r = (i & RED_MASK))
53 #define INT_TO_GRN(i, g) (g = (i & GRN_MASK) >> 8)
54 #define INT_TO_BLU(i, b) (b = (i & BLU_MASK) >> 16)
55 #define INT_TO_ALP(i, a) (a = (i & ALP_MASK) >> 24)
56
57 #define MAX_OBJS 64
58 /* ^ TMP - move to gstypes */
59
60 /* define border width (pixels) for viewport check */
61 #define border 15
62
63 static GLuint ObjList[MAX_OBJS];
64 static int numobjs = 0;
65
66 static int Shade;
67
68 static float ogl_light_amb[MAX_LIGHTS][4];
69 static float ogl_light_diff[MAX_LIGHTS][4];
70 static float ogl_light_spec[MAX_LIGHTS][4];
71 static float ogl_light_pos[MAX_LIGHTS][4];
72 static float ogl_mat_amb[4];
73 static float ogl_mat_diff[4];
74 static float ogl_mat_spec[4];
75 static float ogl_mat_emis[4];
76 static float ogl_mat_shin;
77
78 /*!
79 \brief Mostly for flushing drawing commands across a network
80
81 glFlush doesn't block, so if blocking is desired use glFinish.
82 */
gsd_flush(void)83 void gsd_flush(void)
84 {
85 glFlush();
86
87 return;
88 }
89
90 /*!
91 \brief Set color mode
92
93 Call glColorMaterial before enabling the GL_COLOR_MATERIAL
94
95 \param cm color mode value
96 */
gsd_colormode(int cm)97 void gsd_colormode(int cm)
98 {
99 switch (cm) {
100 case CM_COLOR:
101
102 glDisable(GL_COLOR_MATERIAL);
103 glDisable(GL_LIGHTING);
104
105 break;
106 case CM_EMISSION:
107
108 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
109 glEnable(GL_COLOR_MATERIAL);
110 glEnable(GL_LIGHTING);
111
112 break;
113 case CM_DIFFUSE:
114
115 glColorMaterial(GL_FRONT, GL_DIFFUSE);
116 glEnable(GL_COLOR_MATERIAL);
117 glEnable(GL_LIGHTING);
118
119 break;
120 case CM_AD:
121
122 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
123 glEnable(GL_COLOR_MATERIAL);
124 glEnable(GL_LIGHTING);
125
126 break;
127 case CM_NULL:
128
129 /* OGLXXX
130 * lmcolor: if LMC_NULL, use:
131 * glDisable(GL_COLOR_MATERIAL);
132 * LMC_NULL: use glDisable(GL_COLOR_MATERIAL);
133 */
134 glDisable(GL_COLOR_MATERIAL);
135 glEnable(GL_LIGHTING);
136
137 break;
138 default:
139
140 glDisable(GL_COLOR_MATERIAL);
141 break;
142 }
143
144 return;
145 }
146
147 /*!
148 \brief Print color mode to stderr
149 */
show_colormode(void)150 void show_colormode(void)
151 {
152 GLint mat;
153
154 glGetIntegerv(GL_COLOR_MATERIAL_PARAMETER, &mat);
155 G_message(_("Color Material: %d"), mat);
156
157 return;
158 }
159
160 /*!
161 \brief ADD
162
163 \param x,y
164 \param rad
165 */
gsd_circ(float x,float y,float rad)166 void gsd_circ(float x, float y, float rad)
167 {
168 GLUquadricObj *qobj = gluNewQuadric();
169
170 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
171 glPushMatrix();
172 glTranslatef(x, y, 0.);
173 gluDisk(qobj, 0., rad, 32, 1);
174 glPopMatrix();
175 gluDeleteQuadric(qobj);
176
177 return;
178 }
179
180 /*!
181 \brief ADD
182
183 \param x,y,z
184 \param rad
185 */
gsd_disc(float x,float y,float z,float rad)186 void gsd_disc(float x, float y, float z, float rad)
187 {
188 GLUquadricObj *qobj = gluNewQuadric();
189
190 gluQuadricDrawStyle(qobj, GLU_FILL);
191 glPushMatrix();
192 glTranslatef(x, y, z);
193 gluDisk(qobj, 0., rad, 32, 1);
194 glPopMatrix();
195 gluDeleteQuadric(qobj);
196
197 return;
198 }
199
200 /*!
201 \brief ADD
202
203 \param center center-point
204 \param siz size value
205 */
gsd_sphere(float * center,float siz)206 void gsd_sphere(float *center, float siz)
207 {
208 static int first = 1;
209 static GLUquadricObj *QOsphere;
210
211 if (first) {
212 QOsphere = gluNewQuadric();
213
214 if (QOsphere) {
215 gluQuadricNormals(QOsphere, GLU_SMOOTH); /* default */
216 gluQuadricTexture(QOsphere, GL_FALSE); /* default */
217 gluQuadricOrientation(QOsphere, GLU_OUTSIDE); /* default */
218 gluQuadricDrawStyle(QOsphere, GLU_FILL);
219 }
220
221 first = 0;
222 }
223
224 glPushMatrix();
225 glTranslatef(center[0], center[1], center[2]);
226 gluSphere(QOsphere, (double)siz, 24, 24);
227 glPopMatrix();
228
229 return;
230 }
231
232 /*!
233 \brief Write out z-mask
234
235 Enable or disable writing into the depth buffer
236
237 \param n Specifies whether the depth buffer is enabled for
238 writing
239 */
gsd_zwritemask(unsigned long n)240 void gsd_zwritemask(unsigned long n)
241 {
242 /* OGLXXX glDepthMask is boolean only */
243 glDepthMask((GLboolean) (n));
244
245 return;
246 }
247
248 /*!
249 \brief ADD
250
251 \param n
252 */
gsd_backface(int n)253 void gsd_backface(int n)
254 {
255 glCullFace(GL_BACK);
256 (n) ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
257
258 return;
259 }
260
261 /*!
262 \brief Set width of rasterized lines
263
264 \param n line width
265 */
gsd_linewidth(short n)266 void gsd_linewidth(short n)
267 {
268 glLineWidth((GLfloat) (n));
269
270 return;
271 }
272
273 /*!
274 \brief ADD
275 */
gsd_bgnqstrip(void)276 void gsd_bgnqstrip(void)
277 {
278 glBegin(GL_QUAD_STRIP);
279
280 return;
281 }
282
283 /*!
284 \brief ADD
285 */
gsd_endqstrip(void)286 void gsd_endqstrip(void)
287 {
288 glEnd();
289
290 return;
291 }
292
293 /*!
294 \brief ADD
295 */
gsd_bgntmesh(void)296 void gsd_bgntmesh(void)
297 {
298 glBegin(GL_TRIANGLE_STRIP);
299
300 return;
301 }
302
303 /*!
304 \brief ADD
305 */
gsd_endtmesh(void)306 void gsd_endtmesh(void)
307 {
308 glEnd();
309
310 return;
311 }
312
313 /*!
314 \brief ADD
315 */
gsd_bgntstrip(void)316 void gsd_bgntstrip(void)
317 {
318 glBegin(GL_TRIANGLE_STRIP);
319
320 return;
321 }
322
323 /*!
324 \brief ADD
325 */
gsd_endtstrip(void)326 void gsd_endtstrip(void)
327 {
328 glEnd();
329
330 return;
331 }
332
333 /*!
334 \brief ADD
335 */
gsd_bgntfan(void)336 void gsd_bgntfan(void)
337 {
338 glBegin(GL_TRIANGLE_FAN);
339
340 return;
341 }
342
343 /*!
344 \brief ADD
345 */
gsd_endtfan(void)346 void gsd_endtfan(void)
347 {
348 glEnd();
349
350 return;
351 }
352
353 /*!
354 \brief ADD
355 */
gsd_swaptmesh(void)356 void gsd_swaptmesh(void)
357 {
358 /* OGLXXX
359 * swaptmesh not supported, maybe glBegin(GL_TRIANGLE_FAN)
360 * swaptmesh()
361 */
362
363 /*DELETED*/;
364
365 return;
366 }
367
368 /*!
369 \brief Delimit the vertices of a primitive or a group of like primitives
370 */
gsd_bgnpolygon(void)371 void gsd_bgnpolygon(void)
372 {
373 /* OGLXXX
374 * special cases for polygons:
375 * independent quads: use GL_QUADS
376 * independent triangles: use GL_TRIANGLES
377 */
378 glBegin(GL_POLYGON);
379
380 return;
381 }
382
383 /*!
384 \brief Delimit the vertices of a primitive or a group of like primitives
385 */
gsd_endpolygon(void)386 void gsd_endpolygon(void)
387 {
388 glEnd();
389
390 return;
391 }
392
393 /*!
394 \brief Begin line
395 */
gsd_bgnline(void)396 void gsd_bgnline(void)
397 {
398 /* OGLXXX for multiple, independent line segments: use GL_LINES */
399 glBegin(GL_LINE_STRIP);
400 return;
401 }
402
403 /*!
404 \brief End line
405 */
gsd_endline(void)406 void gsd_endline(void)
407 {
408 glEnd();
409
410 return;
411 }
412
413 /*!
414 \brief Set shaded model
415
416 \param shade non-zero for GL_SMOOTH otherwise GL_FLAT
417 */
gsd_shademodel(int shade)418 void gsd_shademodel(int shade)
419 {
420 Shade = shade;
421
422 if (shade) {
423 glShadeModel(GL_SMOOTH);
424 }
425 else {
426 glShadeModel(GL_FLAT);
427 }
428
429 return;
430 }
431
432 /*!
433 \brief Get shaded model
434
435 \return shade
436 */
gsd_getshademodel(void)437 int gsd_getshademodel(void)
438 {
439 return (Shade);
440 }
441
442 /*!
443 \brief Draw to the front and back buffers
444 */
gsd_bothbuffers(void)445 void gsd_bothbuffers(void)
446 {
447 #if !defined(OPENGL_FBO)
448 /* OGLXXX bothbuffer: other possibilities include GL_FRONT, GL_BACK */
449 glDrawBuffer(GL_FRONT_AND_BACK);
450 #endif
451 return;
452 }
453
454 /*!
455 \brief Draw to the front buffer
456 */
gsd_frontbuffer(void)457 void gsd_frontbuffer(void)
458 {
459 #if !defined(OPENGL_FBO)
460 /* OGLXXX frontbuffer: other possibilities include GL_FRONT_AND_BACK */
461 glDrawBuffer(GL_FRONT);
462 #endif
463 return;
464 }
465
466 /*!
467 \brief Draw to the back buffer
468 */
gsd_backbuffer(void)469 void gsd_backbuffer(void)
470 {
471 #if !defined(OPENGL_FBO)
472 /* OGLXXX backbuffer: other possibilities include GL_FRONT_AND_BACK */
473 glDrawBuffer(GL_BACK);
474 #endif
475 return;
476 }
477
478 /*!
479 \brief Swap buffers
480 */
gsd_swapbuffers(void)481 void gsd_swapbuffers(void)
482 {
483 #if !defined(OPENGL_FBO)
484 /* OGLXXX swapbuffers: copy the back buffer to the front;
485 * the back buffer becomes undefined afterward */
486 #if defined(OPENGL_X11)
487 glXSwapBuffers(glXGetCurrentDisplay(), glXGetCurrentDrawable());
488 #elif defined(OPENGL_AQUA)
489 aglSwapBuffers(aglGetCurrentContext());
490 #elif defined(OPENGL_WINDOWS)
491 SwapBuffers(wglGetCurrentDC());
492 #endif
493 #endif
494 return;
495 }
496
497 /*!
498 \brief Pop the current matrix stack
499 */
gsd_popmatrix(void)500 void gsd_popmatrix(void)
501 {
502 glPopMatrix();
503
504 return;
505 }
506
507 /*!
508 \brief Push the current matrix stack
509 */
gsd_pushmatrix(void)510 void gsd_pushmatrix(void)
511 {
512 glPushMatrix();
513
514 return;
515 }
516
517 /*!
518 \brief Multiply the current matrix by a general scaling matrix
519
520 \param xs x scale value
521 \param ys y scale value
522 \param zs z scale value
523 */
gsd_scale(float xs,float ys,float zs)524 void gsd_scale(float xs, float ys, float zs)
525 {
526 glScalef(xs, ys, zs);
527
528 return;
529 }
530
531 /*!
532 \brief Multiply the current matrix by a translation matrix
533
534 \param dx x translation value
535 \param dy y translation value
536 \param dz z translation value
537 */
gsd_translate(float dx,float dy,float dz)538 void gsd_translate(float dx, float dy, float dz)
539 {
540 glTranslatef(dx, dy, dz);
541
542 return;
543 }
544
545 /*!
546 \brief Get viewport
547
548 \param[out] window
549 \param viewport
550 \param modelMatrix model matrix
551 \param projMatrix projection matrix
552 */
gsd_getwindow(int * window,int * viewport,double * modelMatrix,double * projMatrix)553 void gsd_getwindow(int *window, int *viewport, double *modelMatrix,
554 double *projMatrix)
555 {
556 gsd_pushmatrix();
557 gsd_do_scale(1);
558
559 glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
560 glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
561 glGetIntegerv(GL_VIEWPORT, viewport);
562 gsd_popmatrix();
563
564 window[0] = viewport[1] + viewport[3] + border;
565 window[1] = viewport[1] - border;
566 window[2] = viewport[0] - border;
567 window[3] = viewport[0] + viewport[2] + border;
568
569 return;
570
571 }
572
573 /*!
574 \brief ADD
575
576 \param pt
577 \param widnow
578 \param viewport
579 \param doubleMatrix
580 \param projMatrix
581
582 \return 0
583 \return 1
584 */
gsd_checkpoint(float pt[4],int window[4],int viewport[4],double modelMatrix[16],double projMatrix[16])585 int gsd_checkpoint(float pt[4],
586 int window[4],
587 int viewport[4],
588 double modelMatrix[16], double projMatrix[16])
589 {
590 GLdouble fx, fy, fz;
591
592 gluProject((GLdouble) pt[X], (GLdouble) pt[Y], (GLdouble) pt[Z],
593 modelMatrix, projMatrix, viewport, &fx, &fy, &fz);
594
595 if (fx < window[2] || fx > window[3]
596 || fy < window[1] || fy > window[0])
597 return 1;
598 else
599 return 0;
600
601 }
602
603 /*!
604 \brief ADD
605
606 \param angle
607 \param axis
608 */
gsd_rot(float angle,char axis)609 void gsd_rot(float angle, char axis)
610 {
611 GLfloat x;
612 GLfloat y;
613 GLfloat z;
614
615 switch (axis) {
616 case 'x':
617 case 'X':
618
619 x = 1.0;
620 y = 0.0;
621 z = 0.0;
622
623 break;
624 case 'y':
625 case 'Y':
626
627 x = 0.0;
628 y = 1.0;
629 z = 0.0;
630
631 break;
632 case 'z':
633 case 'Z':
634
635 x = 0.0;
636 y = 0.0;
637 z = 1.0;
638
639 break;
640 default:
641
642 G_warning(_("gsd_rot(): %c is an invalid axis "
643 "specification. Rotation ignored. "
644 "Please advise GRASS developers of this error"), axis);
645 return;
646 }
647
648 glRotatef((GLfloat) angle, x, y, z);
649
650 return;
651 }
652
653 /*!
654 \brief Set the current normal vector & specify vertex
655
656 \param norm normal vector
657 \param col color value
658 \param pt point (model coordinates)
659 */
gsd_litvert_func(float * norm,unsigned long col,float * pt)660 void gsd_litvert_func(float *norm, unsigned long col, float *pt)
661 {
662 glNormal3fv(norm);
663 gsd_color_func(col);
664 glVertex3fv(pt);
665
666 return;
667 }
668
669 /*!
670 \brief ADD
671
672 \param norm
673 \param col
674 \param pt
675 */
gsd_litvert_func2(float * norm,unsigned long col,float * pt)676 void gsd_litvert_func2(float *norm, unsigned long col, float *pt)
677 {
678 glNormal3fv(norm);
679 glVertex3fv(pt);
680
681 return;
682 }
683
684 /*!
685 \brief ADD
686
687 \param pt
688 */
gsd_vert_func(float * pt)689 void gsd_vert_func(float *pt)
690 {
691 glVertex3fv(pt);
692
693 return;
694 }
695
696 /*!
697 \brief Set current color
698
699 \param col color value
700 */
gsd_color_func(unsigned int col)701 void gsd_color_func(unsigned int col)
702 {
703 GLbyte r, g, b, a;
704
705 /* OGLXXX
706 * cpack: if argument is not a variable
707 * might need to be:
708 * glColor4b(($1)&0xff, ($1)>>8&0xff, ($1)>>16&0xff, ($1)>>24&0xff)
709 */
710 INT_TO_RED(col, r);
711 INT_TO_GRN(col, g);
712 INT_TO_BLU(col, b);
713 INT_TO_ALP(col, a);
714 glColor4ub(r, g, b, a);
715
716 return;
717 }
718
719 /*!
720 \brief Initialize model light
721 */
gsd_init_lightmodel(void)722 void gsd_init_lightmodel(void)
723 {
724
725 glEnable(GL_LIGHTING);
726
727 /* normal vector renormalization */
728 #ifdef USE_GL_NORMALIZE
729 {
730 glEnable(GL_NORMALIZE);
731 }
732 #endif
733
734 /* OGLXXX
735 * Ambient:
736 * If this is a light model lmdef, then use
737 * glLightModelf and GL_LIGHT_MODEL_AMBIENT.
738 * Include ALPHA parameter with ambient
739 */
740
741 /* Default is front face lighting, infinite viewer
742 */
743 ogl_mat_amb[0] = 0.1;
744 ogl_mat_amb[1] = 0.1;
745 ogl_mat_amb[2] = 0.1;
746 ogl_mat_amb[3] = 1.0;
747
748 ogl_mat_diff[0] = 0.8;
749 ogl_mat_diff[1] = 0.8;
750 ogl_mat_diff[2] = 0.8;
751 ogl_mat_diff[3] = 0.8;
752
753 ogl_mat_spec[0] = 0.8;
754 ogl_mat_spec[1] = 0.8;
755 ogl_mat_spec[2] = 0.8;
756 ogl_mat_spec[3] = 0.8;
757
758 ogl_mat_emis[0] = 0.0;
759 ogl_mat_emis[1] = 0.0;
760 ogl_mat_emis[2] = 0.0;
761 ogl_mat_emis[3] = 0.0;
762
763 ogl_mat_shin = 25.0;
764
765 /* OGLXXX
766 * attenuation: see glLightf man page: (ignored for infinite lights)
767 * Add GL_LINEAR_ATTENUATION.
768 sgi_lmodel[0] = GL_CONSTANT_ATTENUATION;
769 sgi_lmodel[1] = 1.0;
770 sgi_lmodel[2] = 0.0;
771 sgi_lmodel[3] = ;
772 */
773
774 /* OGLXXX
775 * lmdef other possibilities include:
776 * glLightf(light, pname, *params);
777 * glLightModelf(pname, param);
778 * Check list numbering.
779 * Translate params as needed.
780 */
781 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ogl_mat_amb);
782 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, ogl_mat_diff);
783 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ogl_mat_spec);
784 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, ogl_mat_emis);
785 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, ogl_mat_shin);
786
787 /* OGLXXX lmbind: check object numbering. */
788 /* OGLXXX
789 * lmbind: check object numbering.
790 * Use GL_FRONT in call to glMaterialf.
791 * Use GL_FRONT in call to glMaterialf.
792 if(1) {glCallList(1); glEnable(LMODEL);} else glDisable(LMODEL);
793 if(1) {glCallList(1); glEnable(GL_FRONT);} else glDisable(GL_FRONT);
794 */
795
796 return;
797 }
798
799 /*!
800 \brief Set material
801
802 \param set_shin,set_emis flags
803 \param sh,em should be 0. - 1.
804 \param emcolor packed colors to use for emission
805 */
gsd_set_material(int set_shin,int set_emis,float sh,float em,int emcolor)806 void gsd_set_material(int set_shin, int set_emis, float sh, float em,
807 int emcolor)
808 {
809 if (set_shin) {
810 ogl_mat_spec[0] = sh;
811 ogl_mat_spec[1] = sh;
812 ogl_mat_spec[2] = sh;
813 ogl_mat_spec[3] = sh;
814
815 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ogl_mat_spec);
816
817 ogl_mat_shin = 60. + (int)(sh * 68.);
818
819 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, ogl_mat_shin);
820 }
821
822 if (set_emis) {
823 ogl_mat_emis[0] = (em * (emcolor & 0x0000FF)) / 255.;
824 ogl_mat_emis[1] = (em * ((emcolor & 0x00FF00) >> 8)) / 255.;
825 ogl_mat_emis[2] = (em * ((emcolor & 0xFF0000) >> 16)) / 255.;
826
827 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, ogl_mat_emis);
828 }
829
830 return;
831 }
832
833 /*!
834 \brief Define light
835
836 \param num light id (starts with 1)
837 \param vals position(x,y,z,w), color, ambientm, emission
838 */
gsd_deflight(int num,struct lightdefs * vals)839 void gsd_deflight(int num, struct lightdefs *vals)
840 {
841 if (num > 0 && num <= MAX_LIGHTS) {
842 ogl_light_pos[num - 1][0] = vals->position[X];
843 ogl_light_pos[num - 1][1] = vals->position[Y];
844 ogl_light_pos[num - 1][2] = vals->position[Z];
845 ogl_light_pos[num - 1][3] = vals->position[W];
846
847 glLightfv(GL_LIGHT0 + num, GL_POSITION, ogl_light_pos[num - 1]);
848
849 ogl_light_diff[num - 1][0] = vals->color[0];
850 ogl_light_diff[num - 1][1] = vals->color[1];
851 ogl_light_diff[num - 1][2] = vals->color[2];
852 ogl_light_diff[num - 1][3] = .3;
853
854 glLightfv(GL_LIGHT0 + num, GL_DIFFUSE, ogl_light_diff[num - 1]);
855
856 ogl_light_amb[num - 1][0] = vals->ambient[0];
857 ogl_light_amb[num - 1][1] = vals->ambient[1];
858 ogl_light_amb[num - 1][2] = vals->ambient[2];
859 ogl_light_amb[num - 1][3] = .3;
860
861 glLightfv(GL_LIGHT0 + num, GL_AMBIENT, ogl_light_amb[num - 1]);
862
863 ogl_light_spec[num - 1][0] = vals->color[0];
864 ogl_light_spec[num - 1][1] = vals->color[1];
865 ogl_light_spec[num - 1][2] = vals->color[2];
866 ogl_light_spec[num - 1][3] = .3;
867
868 glLightfv(GL_LIGHT0 + num, GL_SPECULAR, ogl_light_spec[num - 1]);
869 }
870
871 return;
872 }
873
874 /*!
875 \brief Switch light on/off
876
877 \param num
878 \param on 1 for 'on', 0 turns them off
879 */
gsd_switchlight(int num,int on)880 void gsd_switchlight(int num, int on)
881 {
882 short defin;
883
884 defin = on ? num : 0;
885
886 if (defin) {
887 glEnable(GL_LIGHT0 + num);
888 }
889 else {
890 glDisable(GL_LIGHT0 + num);
891 }
892
893 return;
894 }
895
896 /*!
897 \brief Get image of current GL screen
898
899 \param pixbuf data buffer
900 \param[out] xsize,ysize picture dimension
901
902 \return 0 on failure
903 \return 1 on success
904 */
gsd_getimage(unsigned char ** pixbuf,unsigned int * xsize,unsigned int * ysize)905 int gsd_getimage(unsigned char **pixbuf, unsigned int *xsize,
906 unsigned int *ysize)
907 {
908 GLuint l, r, b, t;
909
910 /* OGLXXX
911 * get GL_VIEWPORT:
912 * You can probably do better than this.
913 */
914 GLint tmp[4];
915
916 glGetIntegerv(GL_VIEWPORT, tmp);
917 l = tmp[0];
918 r = tmp[0] + tmp[2] - 1;
919 b = tmp[1];
920 t = tmp[1] + tmp[3] - 1;
921
922 *xsize = r - l + 1;
923 *ysize = t - b + 1;
924
925 if (!*xsize || !*ysize)
926 return (0);
927
928 *pixbuf = (unsigned char *)G_malloc((*xsize) * (*ysize) * 4); /* G_fatal_error */
929
930 if (!*pixbuf)
931 return (0);
932
933 #if !defined(OPENGL_FBO)
934 glReadBuffer(GL_FRONT);
935 #endif
936
937 /* OGLXXX lrectread: see man page for glReadPixels */
938 glReadPixels(l, b, (r) - (l) + 1, (t) - (b) + 1, GL_RGBA,
939 GL_UNSIGNED_BYTE, *pixbuf);
940
941 return (1);
942 }
943
944 /*!
945 \brief Get viewpoint
946
947 \param tmp
948 \param num
949
950 \return 1
951 */
gsd_getViewport(GLint tmp[4],GLint num[2])952 int gsd_getViewport(GLint tmp[4], GLint num[2])
953 {
954
955 /* Save current viewport to tmp */
956 glGetIntegerv(GL_VIEWPORT, tmp);
957 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, num);
958
959 return (1);
960 }
961
962 /*!
963 \brief Write view
964
965 \param pixbuf data buffer
966 \param xsize,ysize picture dimension
967
968 \return 0 on failure
969 \return 1 on success
970 */
gsd_writeView(unsigned char ** pixbuf,unsigned int xsize,unsigned int ysize)971 int gsd_writeView(unsigned char **pixbuf, unsigned int xsize,
972 unsigned int ysize)
973 {
974
975 /* Malloc Buffer for image */
976 *pixbuf = (unsigned char *)G_malloc(xsize * ysize * 4); /* G_fatal_error */
977 if (!*pixbuf) {
978 return (0);
979 }
980
981 #if !defined(OPENGL_FBO)
982 /* Read image buffer */
983 glReadBuffer(GL_FRONT);
984 #endif
985
986 /* Read Pixels into Buffer */
987 glReadPixels(0, 0, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, *pixbuf);
988 return (1);
989 }
990
991 /*!
992 \brief Specify pixel arithmetic
993
994 \param yesno turn on/off
995 */
gsd_blend(int yesno)996 void gsd_blend(int yesno)
997 {
998 if (yesno) {
999 glEnable(GL_BLEND);
1000 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1001 }
1002 else {
1003 glDisable(GL_BLEND);
1004 glBlendFunc(GL_ONE, GL_ZERO);
1005 }
1006
1007 return;
1008 }
1009
1010 /*!
1011 \brief Define clip plane
1012
1013 \param num
1014 \param params
1015 */
gsd_def_clipplane(int num,double * params)1016 void gsd_def_clipplane(int num, double *params)
1017 {
1018 int wason = 0;
1019
1020 /* OGLXXX see man page for glClipPlane equation */
1021 if (glIsEnabled(GL_CLIP_PLANE0 + (num))) {
1022 wason = 1;
1023 }
1024
1025 glClipPlane(GL_CLIP_PLANE0 + (num), params);
1026
1027 if (wason) {
1028 glEnable(GL_CLIP_PLANE0 + (num));
1029 }
1030 else {
1031 glDisable(GL_CLIP_PLANE0 + (num));
1032 }
1033
1034 return;
1035 }
1036
1037 /*!
1038 \brief Set clip plane
1039
1040 \param num
1041 \param able
1042 */
gsd_set_clipplane(int num,int able)1043 void gsd_set_clipplane(int num, int able)
1044 {
1045 /* OGLXXX see man page for glClipPlane equation */
1046 if (able) {
1047 glEnable(GL_CLIP_PLANE0 + (num));
1048 }
1049 else {
1050 glDisable(GL_CLIP_PLANE0 + (num));
1051 }
1052
1053 return;
1054 }
1055
1056 /*!
1057 \brief Finish
1058
1059 Does nothing, only called from src.contrib/GMSL/NVIZ2.2/src/glwrappers.c
1060 */
gsd_finish(void)1061 void gsd_finish(void)
1062 {
1063 return;
1064 }
1065
1066 /*!
1067 \brief Set the viewport
1068
1069 <i>l</i>, <i>b</i> specify the lower left corner of the viewport
1070 rectangle, in pixels.
1071
1072 <i>r</i>, <i>t</i> specify the width and height of the viewport.
1073
1074 \param l left
1075 \param r right
1076 \param b bottom
1077 \param t top
1078 */
gsd_viewport(int l,int r,int b,int t)1079 void gsd_viewport(int l, int r, int b, int t)
1080 {
1081 /* Screencoord */
1082 glViewport(l, b, r, t);
1083
1084 return;
1085 }
1086
1087 /*!
1088 \brief ADD
1089
1090 First time called, gets a bunch of objects, then hands them back
1091 when needed
1092
1093 \return -1 on failure
1094 \return number of objects
1095 */
gsd_makelist(void)1096 int gsd_makelist(void)
1097 {
1098 int i;
1099
1100 if (numobjs) {
1101 if (numobjs < MAX_OBJS) {
1102 numobjs++;
1103
1104 return (numobjs);
1105 }
1106
1107 return (-1);
1108 }
1109 else {
1110 ObjList[0] = glGenLists(MAX_OBJS);
1111
1112 for (i = 1; i < MAX_OBJS; i++) {
1113 ObjList[i] = ObjList[0] + i;
1114 }
1115 numobjs = 1;
1116
1117 return (numobjs);
1118 }
1119
1120 }
1121
1122 /*!
1123 \brief ADD
1124
1125 \param listno
1126 \param do_draw
1127 */
gsd_bgnlist(int listno,int do_draw)1128 void gsd_bgnlist(int listno, int do_draw)
1129 {
1130 if (do_draw) {
1131 glNewList(ObjList[listno], GL_COMPILE_AND_EXECUTE);
1132 }
1133 else {
1134 glNewList(ObjList[listno], GL_COMPILE);
1135 }
1136
1137 return;
1138 }
1139
1140 /*!
1141 \brief End list
1142 */
gsd_endlist(void)1143 void gsd_endlist(void)
1144 {
1145 glEndList();
1146
1147 return;
1148 }
1149
1150 /*!
1151 \brief Delete list
1152
1153 \param listno
1154 \param range
1155 */
gsd_deletelist(GLuint listno,int range)1156 void gsd_deletelist(GLuint listno, int range)
1157 {
1158 unsigned int i;
1159
1160 for (i = 1; i < MAX_OBJS; i++) {
1161 if (i == listno) {
1162 glDeleteLists(ObjList[i], 1);
1163 numobjs--;
1164 if (numobjs < 1)
1165 numobjs = 1;
1166 return;
1167 }
1168 }
1169 }
1170
1171 /*!
1172 \brief ADD
1173
1174 \param listno
1175 */
gsd_calllist(int listno)1176 void gsd_calllist(int listno)
1177 {
1178 glCallList(ObjList[listno]);
1179
1180 return;
1181 }
1182
1183
1184 /*!
1185 \brief ADD
1186
1187 \param listno
1188 */
gsd_calllists(int listno)1189 void gsd_calllists(int listno)
1190 {
1191 int i;
1192
1193 gsd_pushmatrix();
1194 for (i = 1; i < MAX_OBJS; i++) {
1195 glCallList(ObjList[i]);
1196 glFlush();
1197 }
1198 gsd_popmatrix();
1199
1200 gsd_call_label();
1201
1202 return;
1203 }
1204