1 /* NIGHTFALL OpenGL Interface                                              */
2 /* Copyright (C) 2001 Rainer Wichmann & Markus Kuster                      */
3 /*                                                                         */
4 /*  This program is free software; you can redistribute it                 */
5 /*  and/or modify                                                          */
6 /*  it under the terms of the GNU General Public License as                */
7 /*  published by                                                           */
8 /*  the Free Software Foundation; either version 2 of the License, or      */
9 /*  (at your option) any later version.                                    */
10 /*
11                                                                 */
12 /*  This program is distributed in the hope that it will be useful,        */
13 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
14 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
15 /*  GNU General Public License for more details.                           */
16 /*                                                                         */
17 /*  You should have received a copy of the GNU General Public License      */
18 /*  along with this program; if not, write to the Free Software            */
19 /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
20 
21 /* ANSI C forbids an empty source file, so put this outside                */
22 /* do nothing here if we don't have OpenGL                                 */
23 
24 #include <math.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/types.h>
29 #include "Light.h"
30 
31 #ifdef  _WITH_OPENGL
32 #include <setjmp.h>
33 #include "LightGLPrefs.h"
34 
35 /* Display lists                                                           */
36 GLint PrimaryList, SecondaryList, DiskList, PlotList[2];
37 
38 TextureType Texture[3];
39 
40 /* Parameters for coordinate systems                                       */
41 CoordType CoordSys[2];
42 
43 /* structure keeping all eight spot lights                                 */
44 LightType Lights[MAX_LIGHT_NUM];
45 GLfloat lightpos[4];
46 
47 /* Color is RGBA where A is the alpha channel                              */
48 /* color and emission properties of the stars                              */
49 /* primary                                                                 */
50 GLfloat primary_colour[]          = {0.92, 0.057, 0.0, 1.0 };
51 GLfloat primary_mat_specular[]    = { 0.0, 0.0  , 0.0, 1.0 };
52 GLfloat primary_mat_diffuse[]     = { 1.0, 0.60 , 0.0, 1.0 };
53 GLfloat primary_mat_shininess[]   = { 0.0 };
54 /* secondary                                                               */
55 GLfloat secondary_colour[]        = {0.066, 0.6666, 1.0, 1.0 };
56 GLfloat secondary_mat_specular[]  = { 0.0 , 0.0   , 0.0, 1.0 };
57 GLfloat secondary_mat_diffuse[]   = { 1.0 , 0.40  , 0.0, 1.0 };
58 GLfloat secondary_mat_shininess[] = { 0.0 };
59 
60 #ifdef HAVE_DISK
61 /* color and emission properties of the disk                               */
62 GLfloat disk_colour[]             = { 0.6, 0.047, 0.0, 1.0};
63 GLfloat disk_mat_specular[]       = { 0.0,   0.0, 0.0, 1.0};
64 GLfloat disk_mat_diffuse[]        = { 1.0,  0.40, 0.0, 1.0};
65 GLfloat disk_mat_shininess[]      = { 0.0 };
66 #endif
67 
68 /* spot definition for the primary                                         */
69 GLfloat primary_spot1_direction[] = {0.0, 0.0, -1.0};
70 GLfloat primary_spot2_direction[] = {0.0, 0.0, -1.0};
71 
72 /* spot definition for the secondary                                       */
73 GLfloat secondary_spot1_direction[] = {0.0, 0.0, -1.0};
74 GLfloat secondary_spot2_direction[] = {0.0, 0.0, -1.0};
75 
76 /* the background color                                                    */
77 GLfloat bgd_colour[]              = {0.0,0.0,0.0,1.0};
78 
79 /* OpenGL window opened                                                    */
80 int GLWindowOpened = OFF;                 /* OpenGL window opened          */
81 int GLWindowHidden = OFF;                 /* OpenGL window opened          */
82 int phaseind=0;
83 
84 GtkWidget  *glArea = NULL;
85 GtkWidget  *glPlot = NULL;
86 GtkWidget  *glVelo = NULL;
87 GtkWidget  *glWindow = NULL;              /* Scene and plot window         */
88 static char movfile[256];                 /* file name of the movie files  */
89 
90 GLvoid *GLDrawFont = GLUT_BITMAP_TIMES_ROMAN_10;
91 
92 GLuint screen;
93 
94 /****************************************************************************
95  @package   nightfall
96  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
97  @version   1.0
98  @short     The main drawing code
99  @param     (GtkWidget)  *widget  discarded
100  @return    (void)
101  @heading   Open GL Animation
102 ****************************************************************************/
GLDisplayAll(void)103 void GLDisplayAll( void )
104 {
105   /*
106   DispInfo *DispInfoPtr;
107   DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
108   */
109   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
110     {
111       /* clear colour buffer                                               */
112       glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
113 
114       /* define 3d window viewport                                         */
115       glViewport(VP_3D_X0, VP_3D_Y0, VP_3D_WIDTH, VP_3D_HEIGHT);
116 
117       /* render 3D view                                                    */
118       GLDisplay3d(glArea);
119 
120       /* define light curve viewport                                       */
121       glViewport(VP_LC_X0, VP_LC_Y0, VP_LC_WIDTH, VP_LC_HEIGHT);
122 
123       /* render light curve                                                */
124       GLDisplayPlot(glArea,LIGHTCURVE);
125 
126       /* define radial velocity viewport                                   */
127       glViewport(VP_RV_X0, VP_RV_Y0, VP_RV_WIDTH, VP_RV_HEIGHT);
128 
129       /* render radial velocity plot                                       */
130       GLDisplayPlot(glArea,RADVELOCITY);
131 
132       if (Flags.texture == ON && Flags.textype != IMAGE)
133 	{
134 	  /* define wedge primary viewport                                 */
135 	  glViewport(VP_WP_X0, VP_WP_Y0, VP_WP_WIDTH, VP_WP_HEIGHT);
136 	  GLDisplayWedge( Primary );
137 	  /* define wedge secondary viewport                               */
138 	  glViewport(VP_WS_X0, VP_WS_Y0, VP_WS_WIDTH, VP_WS_HEIGHT);
139 	  GLDisplayWedge( Secondary );
140 #ifdef HAVE_DISK
141 	  if (Flags.disk == ON) {
142 	    /* define wedge disk viewport                                  */
143 	    glViewport(VP_WD_X0, VP_WD_Y0, VP_WD_WIDTH, VP_WD_HEIGHT);
144 	    GLDisplayWedge( Disk );
145 	  }
146 #endif
147 	}
148 
149       /* finally swap display buffers, we are in DoubleBuffering mode      */
150       gtk_gl_area_swap_buffers(GTK_GL_AREA(glArea));
151     }
152 }
153 
154 /****************************************************************************
155  @package   nightfall
156  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
157  @version   1.0
158  @short     Update all display lists
159  @param     (void)  *widget  discarded
160  @return    (void)
161  @heading   Open GL Animation
162 ****************************************************************************/
GLUpdateAll(void)163 void GLUpdateAll( void )
164 {
165   /* OpenGL functions can be called only if make_current returns true      */
166   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
167     {
168       /* Update display lists for 3D main window                           */
169       GLUpdate3d(glArea);
170       /* Update top plot window                                            */
171       GLUpdatePlot(5,LIGHTCURVE);
172       /* Update bottom plot window                                         */
173       GLUpdatePlot(6,RADVELOCITY);
174     }
175 }
176 
177 /****************************************************************************
178  @package   nightfall
179  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
180  @version   1.0
181  @short     Update the primary/secondary geometry
182  @param     (GtkWidget) *widget discarded
183  @return    (void)
184  @heading   Open GL Animation
185 ****************************************************************************/
GLUpdate3d(GtkWidget * widget)186 void GLUpdate3d( GtkWidget *widget )
187 {
188   /* OpenGL functions can be called only if make_current returns true      */
189   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
190     {
191       if ( PrimaryList ) {
192 	/* delete the old display list to save memory                      */
193 	glDeleteLists(PrimaryList,1);
194       }
195       /* Create the primary list                                           */
196       PrimaryList=glGenLists(1);
197 
198       glNewList(PrimaryList, GL_COMPILE);
199       if (Flags.points == TRUE) {
200 	GLMakeVolumeEclipsed(Primary);
201       } else {
202 	GLMakeVolumeEclipsed(Primary);
203       }
204       glEndList();
205 
206       if ( SecondaryList ) {
207 	/* delete the old display list to save memory                      */
208 	glDeleteLists(SecondaryList,1);
209       }
210 
211       /* Create the secondary list                                         */
212       SecondaryList=glGenLists(2);
213 
214       glNewList(SecondaryList, GL_COMPILE);
215       if (Flags.points == TRUE) {
216 	GLMakeVolumeEclipsed(Secondary);
217       } else {
218 	GLMakeVolumeEclipsed(Secondary);
219       }
220       glEndList();
221 
222 #ifdef HAVE_DISK
223       /* Create the disk display list                                      */
224       if ( Flags.disk == ON ) {
225 	if ( DiskList ) {
226 	  /* delete the old display list to save memory                    */
227 	  glDeleteLists(DiskList,1);
228 	}
229 	DiskList=glGenLists(3);
230 
231 	glNewList(DiskList, GL_COMPILE);
232 	if (Flags.points == TRUE) {
233 	  GLMakeVolumeEclipsed(Disk);
234 	} else {
235 	  GLMakeVolumeEclipsed(Disk);
236 	}
237 	glEndList();
238       }
239 #endif
240     }
241   return;
242 }
243 
244 /****************************************************************************
245  @package   nightfall
246  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
247  @version   1.0
248  @short     Update a plot viewport
249  @param     (int)  viewport number of viewport
250  @param     (int)  type     type of plot (light curve / rad. vel.)
251  @return    (void)
252  @heading   Open GL Animation
253 ****************************************************************************/
GLUpdatePlot(int viewport,int type)254 void GLUpdatePlot( int viewport, int type )
255 {
256   /* OpenGL functions can be called only if make_current returns true      */
257   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
258     {
259       if ( PlotList[type] ) {
260 	/* delete the old display list to save memory                      */
261 	glDeleteLists(PlotList[type],1);
262       }
263       PlotList[type]=glGenLists(viewport);
264       glNewList(PlotList[type], GL_COMPILE);
265 
266       switch (type)
267 	{
268 	case LIGHTCURVE:
269 	  GLMakeLCPlot();
270 	  break;
271 	case RADVELOCITY:
272 	  GLMakeRVPlot();
273 	  break;
274 	default:
275 	  break;
276 	}
277       glEndList();
278     }
279 }
280 
281 /****************************************************************************
282  @package   nightfall
283  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
284  @version   1.0
285  @short     Select font
286  @param     (int)    style font name
287  @param     (int)    size  font size
288  @return    (void)
289  @heading   Open GL Animation
290 ****************************************************************************/
GLSetFont(int style,int size)291 void GLSetFont(int style, int size)
292 {
293   switch (style) {
294 
295   case HELVETICA:
296     if (size == 12)
297       GLDrawFont = GLUT_BITMAP_HELVETICA_12;
298     else if (size == 18)
299       GLDrawFont = GLUT_BITMAP_HELVETICA_18;
300     break;
301 
302   case TIMESROMAN:
303     GLDrawFont = GLUT_BITMAP_TIMES_ROMAN_10;
304     if (size == 24)
305       GLDrawFont = GLUT_BITMAP_TIMES_ROMAN_24;
306     break;
307 
308   default:
309     GLDrawFont = GLUT_BITMAP_HELVETICA_10;
310     break;
311   }
312 }
313 
314 /****************************************************************************
315  @package   nightfall
316  @author    Rainer Wichmann (rwichman@hs.uni-hamburg.de)
317  @version   1.0
318  @short     Display given string at position x,y
319  @param     (GLint) x      x coordinate
320  @param     (GLint) y      y coordinate
321  @param     (GLint) z      z coordinate
322  @param     (char)  format string to draw
323  @return    (void)
324  @heading   Open GL Animation
325 ****************************************************************************/
GLDrawStrRightAdj(GLfloat x,GLfloat y,GLfloat z,char * format,...)326 void GLDrawStrRightAdj(GLfloat x, GLfloat y, GLfloat z, char* format, ...)
327 {
328   int string_width;
329   float string_off;
330 
331   va_list args;
332   char buffer[256], *s;
333 
334   va_start(args, format);
335   vsnprintf(buffer, 256, format, args);
336   va_end(args);
337 
338   string_width = 0;
339   for (s = buffer; *s; s++)
340     string_width += glutBitmapWidth(GLDrawFont, *s);
341 
342   string_off  = string_width/2.;
343   string_off  = (2.0 * string_off)/VP_LC_WIDTH;
344 
345   glRasterPos3f(x-string_off, y, z);
346   /* fprintf(stderr, "FIXME %f %f %f\n", x-string_off, y, z); */
347   for (s = buffer; *s; s++) {
348     glutBitmapCharacter(GLDrawFont, *s);
349   }
350 }
351 
352 /****************************************************************************
353  @package   nightfall
354  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
355  @version   1.0
356  @short     Display given string at position x,y
357  @param     (GLint) x      x coordinate
358  @param     (GLint) y      y coordinate
359  @param     (GLint) z      z coordinate
360  @param     (char)  format string to draw
361  @return    (void)
362  @heading   Open GL Animation
363 ****************************************************************************/
GLDrawStr(GLfloat x,GLfloat y,GLfloat z,char * format,...)364 void GLDrawStr(GLfloat x, GLfloat y, GLfloat z, char* format, ...)
365 {
366   /* int string_width; */
367   /* float string_off; */
368 
369   va_list args;
370   char buffer[256], *s;
371 
372   va_start(args, format);
373   vsnprintf(buffer, 256, format, args);
374   va_end(args);
375 
376   /* Unused code for making Position relative to middle of string */
377   /*
378   string_width = 0;
379   for (s = buffer; *s; s++)
380     string_width += glutBitmapWidth(GLDrawFont, *s);
381 
382   string_off = string_width/2.;
383    */
384 
385   glRasterPos3f(x, y, z);
386   for (s = buffer; *s; s++) {
387     glutBitmapCharacter(GLDrawFont, *s);
388   }
389 }
390 
391 /****************************************************************************
392  @package   nightfall
393  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
394  @version   1.0
395  @short     Draw labels for 3D plot
396  @param     (GLfloat) length  length of the axes
397  @return    (void)
398  @heading   Open GL Animation
399 ****************************************************************************/
GLDrawLabels(GtkWidget * widget)400 void GLDrawLabels(GtkWidget *widget)
401 {
402   double RLag1;
403   /* float  com; */                   /* center of mass                    */
404 
405   /* the x coordinate of the center of mass                                */
406   /*
407   com = (((float)(Binary[Primary].Mq))/( 1.0 + (float)(Binary[Primary].Mq)));
408   */
409   /* x-coordinate of lagrange point one                                    */
410   RLag1 = Binary[Primary].RLag1;
411 
412   if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
413     {
414       /* disable lighting, we don't want ligthing with                     */
415       /* markers                                                           */
416       glDisable(GL_LIGHTING);
417 
418       /* draw axes with thick lines                                        */
419       glLineWidth(2);
420       /* select font                                                       */
421       GLSetFont(HELVETICA, 12);
422 
423       glColor3f(0.0, 0.0, 1.0);
424       GLDrawStr(RLag1,0.0,0.6,"L1");
425 
426       glColor3f(1.0, 1.0, 1.0);
427       GLDrawStr(0.0,0.0,0.7,"Primary");
428 
429       glColor3f(1.0, 1.0, 1.0);
430       GLDrawStr(0.9,0.0,0.7,"Secondary");
431 
432       /* translate to display coordinates with com
433 	 at (0,0,0) */
434       glBegin(GL_LINES);
435 
436       /* blue; lagrange point one                                          */
437       glColor3f(0.0, 0.0, 1.0);
438       glVertex3f(RLag1, 0.0, 0.4);
439       glVertex3f(RLag1, 0.0, 0.5);
440 
441       /* white; primary                                                    */
442       glColor3f(1.0, 1.0, 1.0);
443       glVertex3f(0.0, 0.0, 0.5);
444       glVertex3f(0.0, 0.0, 0.6);
445 
446       /* white; secondary                                                  */
447       glColor3f(1.0, 1.0, 1.0);
448       glVertex3f(1.0, 0.0, 0.5);
449       glVertex3f(1.0, 0.0, 0.6);
450 
451       glEnd();
452 
453       /* switch on lighing                                                 */
454       glEnable(GL_LIGHTING);
455       /* set line width back to one                                        */
456       glLineWidth(1);
457     }
458 }
459 
460 /****************************************************************************
461  @package   nightfall
462  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
463  @version   1.0
464  @short     Resize the GL window and update the viewport
465  @param     (GtkWidget)          discarded
466             (GdkEventConfigure)  event pointer to the event structure
467  @return    (gint)      status   the exit status
468  @heading   Open GL Animation
469 ****************************************************************************/
GLReshape(GtkWidget * widget,GdkEventConfigure * event)470 gint GLReshape( GtkWidget *widget, GdkEventConfigure *event )
471 {
472   /* GLfloat h; */
473 
474   /*
475   DispInfo *DispInfoPtr;
476   DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
477   */
478 
479   /* OpenGL functions can be called only if make_current returns true      */
480   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
481     {
482       /* get the dimension of the GTK window                               */
483       /*
484       h= (GLfloat) glArea->allocation.height / (GLfloat) glArea->allocation.width;
485       */
486 
487       /* set the glViewport to the full size of                            */
488       /* all Viewports                                                     */
489       glViewport(0,0, GLAREA_WIDTH, GLAREA_HEIGHT);
490       return(TRUE);
491     } else {
492       return(FALSE);
493     }
494 }
495 
496 /****************************************************************************
497  @package   nightfall
498  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
499  @version   1.0
500  @short     Motion event handling
501  @param     (GtkWidget)   *widget pointer to the GL area widget
502             (GdkEventKey) *event  the motion event
503  @return    (void)
504  @heading   Open GL Animation
505 ****************************************************************************/
GLMotionNotify(GtkWidget * widget,GdkEventMotion * event)506 gint GLMotionNotify(GtkWidget *widget, GdkEventMotion *event)
507 {
508   int x, y;
509   /* uint BUTTON12_MASK = (1 << 8) + (1 << 9); */
510 
511   float spin_quat[4];
512   GdkRectangle area;
513   GdkModifierType state;
514   DispInfo *DispInfoPtr;
515 
516   DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
517 
518   if (event->is_hint) {
519     gdk_window_get_pointer(event->window, &x, &y, &state);
520   } else {
521     x = event->x;
522     y = event->y;
523     state = event->state;
524   }
525 
526   area.x = 0;
527   area.y = 0;
528   area.width  = glArea->allocation.width;
529   area.height = glArea->allocation.height;
530 
531 
532 
533   if (state & GDK_BUTTON1_MASK) {
534     /* drag in progress, simulate trackball                                */
535     trackball(spin_quat,
536 	      (2.0*DispInfoPtr->mousex -              area.width) / area.width,
537 	      (            area.height - 2.0*DispInfoPtr->mousey) / area.height,
538 	      (                  2.0*x -              area.width) / area.width,
539 	      (            area.height -                   2.0*y) / area.height);
540     add_quats(spin_quat, DispInfoPtr->quat, DispInfoPtr->quat);
541     /* orientation has changed, redraw all                                 */
542     gtk_widget_draw(glArea, &area);
543   }
544 
545   if (state & GDK_BUTTON2_MASK) {
546     /* zooming drag                                                        */
547     DispInfoPtr->zoom += ((y - DispInfoPtr->mousey) / area.height) * 1.0;
548     if (DispInfoPtr->zoom < 0.1) DispInfoPtr->zoom = 0.1;
549     if (DispInfoPtr->zoom > 20)  DispInfoPtr->zoom = 20;
550     /* zoom has changed, redraw mesh                                       */
551     gtk_widget_draw(glArea, &area);
552   }
553 
554   if (state & GDK_BUTTON3_MASK) {
555     /* left/right drag                                                     */
556       DispInfoPtr->xpos += ((x - DispInfoPtr->mousex) / area.height) * 1.0;
557       if (DispInfoPtr->xpos < -3.0) DispInfoPtr->xpos = -3.0;
558       if (DispInfoPtr->xpos >  3.0) DispInfoPtr->xpos =  3.0;
559       gtk_widget_draw(glArea, &area);
560   }
561 
562   DispInfoPtr->mousex = x;
563   DispInfoPtr->mousey = y;
564 
565   return(TRUE);
566 }
567 
568 /****************************************************************************
569  @package   nightfall
570  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
571  @version   1.0
572  @short     Mouse event handling
573  @param     (GtkWidget)   *widget pointer to the GL area widget
574             (GdkEventKey) *event  the mouse event
575  @return    (void)
576  @heading   Open GL Animation
577 ****************************************************************************/
GLButtonPress(GtkWidget * widget,GdkEventButton * event)578 gint GLButtonPress(GtkWidget *widget, GdkEventButton *event)
579 {
580   DispInfo *DispInfoPtr;
581 
582   DispInfoPtr= (DispInfo*)gtk_object_get_data(GTK_OBJECT(widget), "DispInfo");
583 
584   if (event->button == 1) {
585     /* beginning of drag, reset mouse position                             */
586     DispInfoPtr->mousex = event->x;
587     DispInfoPtr->mousey = event->y;
588 
589     return(TRUE);
590   }
591 
592   return(FALSE);
593 }
594 
595 /****************************************************************************
596  @package   nightfall
597  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
598  @version   1.0
599  @short     Grab GL viewport and write as JPEG coded image file
600  @param     (char) *filename  the name of the image file
601             (int)  x0         x0 position rel. to glViewport
602             (int)  x0         x0 position rel. to glViewport
603             (int)  width      width of the area to grab
604                       	      0 < width <= GLAREA_WIDTH
605             (int)  height     height of the area to grab
606                       	      0 < height <= GLAREA_HEIGHT
607 	    (int)  quality    the compression factor
608 	                      (0 < quality < 100)
609  @return    (int)  TRUE if successful else FALSE
610  @heading   Read a GL viewport, compress the image and save it as a
611             jpeg-file. This code is based on the example code
612             'example.c' included in the jpeg-library libjpeg-6.2.0.
613 ****************************************************************************/
GLGrabScreen(char * filename,int x0,int y0,int width,int height,int quality)614 int GLGrabScreen(char *filename, int x0, int y0,
615 		 int width, int height, int quality)
616 {
617   JSAMPLE *imgbuff;             /* array of R,G,B - order data for image   */
618   int imgwidth, imgheight;      /* width and height of the area to grab    */
619   int success;                  /* return status                           */
620   char ErrMsg[256];             /* error message                           */
621 
622 #ifdef USING_GTK2
623 #if GTK_CHECK_VERSION(2, 24, 0)
624   imgwidth  = gdk_window_get_width(glWindow->window);
625   imgheight = gdk_window_get_height(glWindow->window);
626 #else
627   gdk_drawable_get_size(glWindow->window, &imgwidth, &imgheight);
628 #endif
629 #else
630   gdk_window_get_size(glWindow->window, &imgwidth, &imgheight);
631 #endif
632 
633   imgwidth  = width;
634   imgheight = height;
635 
636   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
637     {
638       /* allocate an image storage buffer                                  */
639       imgbuff=(unsigned char *)malloc(imgheight*imgwidth*3);
640       if (!imgbuff) {
641 	sprintf(ErrMsg,_("Can't allocate memory for the image buffer\n"));
642 	WARNING (ErrMsg);
643 	return(FALSE);
644       }
645 
646       /* grab image from the viewport                                      */
647       glReadPixels(x0,y0,imgwidth,imgheight,GL_RGB,GL_UNSIGNED_BYTE,
648 		   imgbuff);
649 
650       /* write image to jpeg file                                          */
651       success=WriteJPEGFile(imgbuff, filename, imgwidth, imgheight,
652 			    3, quality);
653 
654       if (!success) {
655 	sprintf(ErrMsg,_("Failed to write mage file !\n"));
656 	WARNING (ErrMsg);
657 	return(FALSE);
658       }
659       /* free memory of the image buffer                                   */
660       if (imgbuff) {
661 	free(imgbuff);
662       }
663     }
664   return(TRUE);
665 }
666 
667 /****************************************************************************
668  @package   nightfall
669  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
670  @version   1.0
671  @short     Init lighting model
672  @param     (GtkWidget) *widget   pointer to the GL area widget
673  @return    (void)
674  @heading   Open GL Animation
675 ****************************************************************************/
GLInitLighting(GtkWidget * widget)676 void GLInitLighting( GtkWidget *widget )
677 {
678   GLdouble a=2.90;
679   GLfloat qa=1.0/a/a;
680 
681   /* the x coordinate of the center of mass                                */
682   /*
683   GLfloat com = (((GLfloat)(Binary[Primary].Mq))/( 1.0 + (GLfloat)(Binary[Primary].Mq)));
684   */
685   /* set position of lights                                                */
686   Lights[SCENE_LIGHT-GL_LIGHT0].Pos[0] = 1.0;
687   Lights[SCENE_LIGHT-GL_LIGHT0].Pos[1] = 0.0;
688   Lights[SCENE_LIGHT-GL_LIGHT0].Pos[2] = 0.0;
689   Lights[SCENE_LIGHT-GL_LIGHT0].Pos[3] = 1.0;
690 
691   Lights[DISK_SPOT-GL_LIGHT0].Pos[0]   = 1.0;
692   Lights[DISK_SPOT-GL_LIGHT0].Pos[1]   = 0.0;
693   Lights[DISK_SPOT-GL_LIGHT0].Pos[2]   = 0.0;
694   Lights[DISK_SPOT-GL_LIGHT0].Pos[3]   = 1.0;
695 
696   Lights[PRIMARY_ONE-GL_LIGHT0].Pos[0] = 0.0;
697   Lights[PRIMARY_ONE-GL_LIGHT0].Pos[1] = 0.0;
698   Lights[PRIMARY_ONE-GL_LIGHT0].Pos[2] = 0.0;
699   Lights[PRIMARY_ONE-GL_LIGHT0].Pos[3] = 1.0;
700 
701   Lights[PRIMARY_TWO-GL_LIGHT0].Pos[0] = 0.0;
702   Lights[PRIMARY_TWO-GL_LIGHT0].Pos[1] = 0.0;
703   Lights[PRIMARY_TWO-GL_LIGHT0].Pos[2] = 0.0;
704   Lights[PRIMARY_TWO-GL_LIGHT0].Pos[3] = 1.0;
705 
706   glLightfv(SCENE_LIGHT, GL_DIFFUSE, primary_colour);
707   glLightfv(SCENE_LIGHT, GL_SPECULAR, primary_colour);
708   glLightf(SCENE_LIGHT, GL_CONSTANT_ATTENUATION, 0.0);
709   glLightf(SCENE_LIGHT, GL_LINEAR_ATTENUATION, 0.0);
710   glLightf(SCENE_LIGHT, GL_QUADRATIC_ATTENUATION, qa*0.95);
711 
712   glLightfv(DISK_SPOT, GL_DIFFUSE, primary_colour);
713   glLightfv(DISK_SPOT, GL_SPECULAR, primary_colour);
714   glLightf(DISK_SPOT, GL_CONSTANT_ATTENUATION, 0.0);
715   glLightf(DISK_SPOT, GL_LINEAR_ATTENUATION, 0.0);
716   glLightf(DISK_SPOT, GL_QUADRATIC_ATTENUATION, qa*0.95);
717 
718   glLightfv(PRIMARY_ONE, GL_DIFFUSE, primary_colour);
719   glLightfv(PRIMARY_ONE, GL_SPECULAR, primary_colour);
720   glLightf(PRIMARY_ONE, GL_CONSTANT_ATTENUATION, 0.0);
721   glLightf(PRIMARY_ONE, GL_LINEAR_ATTENUATION, 0.0);
722   glLightf(PRIMARY_ONE, GL_QUADRATIC_ATTENUATION, qa);
723 
724   glEnable(GL_LIGHTING);
725   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
726 }
727 
728 /****************************************************************************
729  @package   nightfall
730  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
731  @version   0.1
732  @short     Visualize spots
733  @param     (int)       Comp      The stellar component
734  @return    (void)
735  @heading   Open GL Animation
736 ****************************************************************************/
GLMakeSpots(int Comp,float xpos)737 void GLMakeSpots( int Comp, float xpos )
738 {
739   int    nspot;                              /* index of current spot      */
740   int    N_Spot = 0;                         /* # of spots on star         */
741   /*long   i; */                             /* loop counter               */
742   /*double LatS;  */                         /* spot latitude              */
743   /*double LongS;*/                          /* spot longitude             */
744   /*double RadSpot;*/                        /* spot radius                */
745 
746   if (Comp == Primary) {
747     xpos   = 0.0;
748     N_Spot = Flags.Spots1;
749   }
750   else if (Comp == Secondary) {
751     xpos   = 1.0;
752     N_Spot = Flags.Spots2;
753   }
754 
755   /* show only the first two spots per component in GL animation, which are*/
756   /* the spots defined in the GUI                                          */
757   if (N_Spot > 1) {
758     N_Spot = 1;
759   }
760 
761   lightpos[0]=xpos;
762   lightpos[1]=0.0;
763   lightpos[2]=0.0;
764   lightpos[3]=1.0;
765 
766   /* set spot position                                                     */
767   if (Comp == Primary) {
768     glLightfv(PRIMARY_ONE, GL_POSITION, lightpos);
769     glLightfv(PRIMARY_TWO, GL_POSITION, lightpos);
770   } else {
771     glLightfv(SECONDARY_ONE, GL_POSITION, lightpos);
772     glLightfv(SECONDARY_TWO, GL_POSITION, lightpos);
773   }
774 
775   /* ----------------- loop over spots ----------------------------------  */
776 
777   for (nspot = 0; nspot < N_Spot; ++nspot) {
778     /* latitude of the spot in radians                                     */
779     /*LatS     = DTOR * Spot[Comp][nspot].latitude;
780       LongS    = DTOR * Spot[Comp][nspot].longitude;*/
781 
782     /* Must be != NULL, else spot is incorrectly placed
783      */
784     /*LatS     = ( fabs(LatS) >= DBL_EPSILON) ? LatS : DBL_EPSILON;
785       LongS    = ( fabs(LongS) >= DBL_EPSILON) ? LongS : DBL_EPSILON;*/
786 
787     /* -------------  spot size      ------------------------------------- */
788     /* RadSpot  = DTOR * Spot[Comp][nspot].radius;*/
789 
790 
791     /* set spot direction                                                  */
792     /*    glLightfv(DISK_SPOT, GL_SPOT_DIRECTION, primary_spot1_direction);
793 	  glLightfv(PRIMARY_ONE, GL_SPOT_DIRECTION, primary_spot2_direction);*/
794 
795   }
796 }
797 
798 /****************************************************************************
799  @package   nightfall
800  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
801  @version   1.0
802  @short     Init geometry display
803  @param     (GtkWidget) *widget   discarded
804  @return    (gint)      status    the exit status
805  @heading   Open GL Animation
806 ****************************************************************************/
GLInit3d(GtkWidget * widget)807 gint GLInit3d(GtkWidget *widget )
808 {
809   /* OpenGL functions can be called only if make_current                   */
810   /* returns true                                                          */
811   if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
812     {
813       /* set background color to black                                     */
814       glClearColor (bgd_colour[0], bgd_colour[1], bgd_colour[2], bgd_colour[3]);
815 
816       /* glEnable(GL_DITHER); */
817       /* use smooth Gouraud shading                                        */
818       glShadeModel (GL_SMOOTH);
819 
820       glEnable(GL_CULL_FACE);
821       glFrontFace(GL_CCW);
822 
823       /*glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
824 	glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);*/
825 
826       /* enable hidden line removal                                        */
827       glEnable(GL_DEPTH_TEST);
828       glDepthFunc(GL_LESS);
829 
830       /* activate depth mask                                               */
831       glDepthMask(GL_TRUE);
832 
833       /* clear colour buffer and depth buffer                              */
834       glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
835       /* set draw color to white                                           */
836       glColor3f (1.0, 1.0, 1.0);
837 
838       /* define lights                                                     */
839       GLInitLighting(glArea);
840 
841       /* Initialize texturing                                              */
842       GLInitTextureParams(Primary);
843       if (GLInitTexture(Primary, Flags.textype)) {
844 	Texture[Primary].IsOn   = ON;
845       }  else {
846 	Texture[Primary].IsOn   = OFF;
847       }
848 
849       GLInitTextureParams(Secondary);
850       if (GLInitTexture(Secondary, Flags.textype)) {
851 	Texture[Secondary].IsOn = ON;
852       } else {
853 	Texture[Secondary].IsOn = OFF;
854       }
855 
856 #ifdef HAVE_DISK
857       /* texture for disk has to be initialzed in any case                 */
858       GLInitTextureParams(Disk);
859       if (GLInitTexture(Disk, Flags.textype)) { // CORRECT?
860 	Texture[Disk].IsOn = ON;
861       } else {
862 	Texture[Disk].IsOn = OFF;
863       }
864 #endif
865 
866       /* switch on the lights                                              */
867       /*glEnable(SCENE_LIGHT);*/
868       /*glEnable(DISK_SPOT);*/
869       /*glEnable(PRIMARY_ONE);*/
870 
871       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
872 
873       GLUpdateAll();
874       return(TRUE);
875     } else {
876       return(FALSE);
877     }
878 }
879 
880 /****************************************************************************
881  @package   nightfall
882  @author    Rainer Wichmann (rwichman@lsw.uni-heidelberg.de)
883  @version   1.0
884  @short     Callback function for GLWindow delete
885  @param     (GtkWidget) *widget     Discarded
886  @param     (gpointer)  *data       Discarded
887  @return    (void)
888  @heading   Open GL Animation
889 ****************************************************************************/
GLDelete(GtkWidget * widget,gpointer * data)890 void GLDelete (GtkWidget *widget, gpointer *data)
891 {
892   if (GLPrefWinOpened == TRUE) {
893     if (glPrefsWindow != NULL)
894       gtk_widget_destroy (glPrefsWindow);
895     glPrefsWindow = NULL;
896     GLPrefWinOpened = OFF;
897   }
898 
899   gtk_widget_hide (glWindow);
900   GLWindowHidden = ON;
901   /*
902   if (glArea != NULL)
903     gtk_widget_destroy (glArea);
904   glArea = NULL;
905   if (glWindow != NULL)
906     gtk_widget_destroy (glWindow);
907   glWindow = NULL;
908   GLWindowOpened = OFF;
909   */
910   return;
911 }
912 
913 /****************************************************************************
914  @package   nightfall
915  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
916  @version   1.0
917  @short     Init texture parameters
918  @param     (int)       Comp      The stellar component
919  @return    (int)       status    The exit status
920  @heading   Open GL Animation
921 ****************************************************************************/
GLInitTextureParams(int Comp)922 int GLInitTextureParams(int Comp)
923 {
924   TextureType *TexPtr=NULL;               /* Pointer to texture            */
925   char  texture_file[MAX_CFG_INLINE+1] = "\0";        /* Texture image file            */
926   FILE        *txtFile;
927   int          len;
928 
929   TexPtr=&Texture[Comp];
930 
931   strncpy(texture_file, data_pix_fls(), sizeof(texture_file)-1);
932   texture_file[sizeof(texture_file)-1] = '\0';
933   len = strlen(texture_file);
934 
935   /* set default values (filenames should be stored in preferences TBD MK) */
936   if ( Comp == Primary) {
937     strncat(texture_file, "/starp_256.jpg", sizeof(texture_file) - len -1);
938   } else if ( Comp == Secondary ) {
939     strncat(texture_file, "/stars_256.jpg", sizeof(texture_file) - len -1);
940   }
941 #ifdef HAVE_DISK
942   else {
943     strncat(texture_file, "/disk_256.jpg", sizeof(texture_file) - len -1);
944   }
945 #endif
946   /* not found in default directory -> try local directory                  */
947   if ((txtFile = fopen (texture_file, "r")) == NULL) {
948     texture_file[0]='.';
949     texture_file[1]='\0';
950 
951     strcat(texture_file, "/pixmaps");
952 
953     if ( Comp == Primary) {
954       strcat(texture_file, "/starp_256.jpg");
955     } else if ( Comp == Secondary ) {
956       strcat(texture_file, "/stars_256.jpg");
957     }
958 #ifdef HAVE_DISK
959     else {
960       strcat(texture_file, "/disk_256.jpg");
961     }
962 #endif
963   } else {
964     fclose(txtFile);
965   }
966   strncpy(TexPtr->TextFile, texture_file,
967 	  strlen(texture_file) + 1);
968   TexPtr->TextFile[MAX_CFG_INLINE] = '\0';
969 
970   /* Set Texture type to default = IMAGE                                   */
971   TexPtr->Type = IMAGE;
972 
973   return(TRUE);
974 }
975 
maxtemp(SurfaceElement * surface,double num)976 double maxtemp(SurfaceElement *surface, double num) {
977   double maxvalue=0;
978   SurfaceElement *ptr;
979   double i;
980 
981   ptr=surface;
982   for (i=0;i<num;i++) {
983     if (ptr->temp > maxvalue) maxvalue = ptr->temp;
984     ptr++;
985   }
986   return(maxvalue);
987 }
988 
mintemp(SurfaceElement * surface,double num)989 double mintemp(SurfaceElement *surface, double num) {
990   double minvalue = 3.0e+38;
991   SurfaceElement *ptr;
992   double i;
993 
994   ptr=surface;
995   for (i=0;i<num;i++) {
996     if (ptr->temp < minvalue) minvalue = ptr->temp;
997     ptr++;
998   }
999   return(minvalue);
1000 }
1001 
maxgrav(SurfaceElement * surface,double num)1002 double maxgrav(SurfaceElement *surface, double num) {
1003   double maxvalue=0;
1004   SurfaceElement *ptr;
1005   double i;
1006 
1007   ptr=surface;
1008   for (i=0;i<num;i++) {
1009     if (ptr->grav > maxvalue) maxvalue = ptr->grav;
1010     ptr++;
1011   }
1012   return(maxvalue);
1013 }
1014 
mingrav(SurfaceElement * surface,double num)1015 double mingrav(SurfaceElement *surface, double num) {
1016   double minvalue =  3.0e+38;
1017   SurfaceElement *ptr;
1018   double i;
1019 
1020   ptr=surface;
1021   for (i=0;i<num;i++) {
1022     if (ptr->grav < minvalue) minvalue = ptr->grav;
1023     ptr++;
1024   }
1025   return(minvalue);
1026 }
1027 
maxflux(SurfaceElement * surface,double num,int Comp)1028 double maxflux(SurfaceElement *surface, double num, int Comp) {
1029   double maxvalue=0;
1030   SurfaceElement *ptr;
1031   double i, flux;
1032 
1033   ptr=surface;
1034   for (i=0;i<num;i++) {
1035     flux = (ptr->f_[0]/ ptr->area)
1036       /* * ptr->visibility */
1037       /* * (1.0 - Limb[Comp][0][0] * (1.0 - ptr->CosGamma)) */
1038       ;
1039     if (flux > maxvalue)
1040       maxvalue = flux;
1041     ptr++;
1042   }
1043   return(maxvalue);
1044 }
minflux(SurfaceElement * surface,double num,int Comp)1045 double minflux(SurfaceElement *surface, double num, int Comp) {
1046   double minvalue = 3.0e38;
1047   SurfaceElement *ptr;
1048   double i, flux;
1049 
1050   ptr=surface;
1051   for (i=0;i<num;i++) {
1052     flux = (ptr->f_[0]/ ptr->area)
1053       /* * ptr->visibility */
1054       * fabs(1.0 - Limb[Comp][0][0] /* * (1.0 - ptr->CosGamma) */);
1055     if (flux < minvalue) {
1056       minvalue = flux;
1057     }
1058     ptr++;
1059   }
1060   minvalue = minvalue * 0.9;
1061   return(minvalue);
1062 }
1063 
maxvel(SurfaceElement * surface,double num)1064 double maxvel(SurfaceElement *surface, double num) {
1065   double maxvalue=0;
1066   SurfaceElement *ptr;
1067   double i;
1068 
1069   ptr=surface;
1070   for (i=0;i<num;i++) {
1071     if (ptr->CosGamma > 0) {
1072       if (ptr->Velocity > maxvalue)
1073 	maxvalue = ptr->Velocity;
1074     }
1075     ptr++;
1076   }
1077   return(maxvalue);
1078 }
minvel(SurfaceElement * surface,double num)1079 double minvel(SurfaceElement *surface, double num) {
1080   double minvalue = 3.0e38;
1081   SurfaceElement *ptr;
1082   double i;
1083 
1084   ptr=surface;
1085   for (i=0;i<num;i++) {
1086     if (ptr->CosGamma > 0) {
1087       if (ptr->Velocity < minvalue)
1088 	minvalue = ptr->Velocity;
1089     }
1090     ptr++;
1091   }
1092   return(minvalue);
1093 }
1094 
1095 /****************************************************************************
1096  @package   nightfall
1097  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
1098  @version   0.5
1099  @short     Generate a texture image from binary data, e.g. temperature
1100             distribution
1101  @param     (SurfaceElement *) SurfPtr The data of the stellar component
1102  @param     (GLubyte *) textimage Pointer to the texture image
1103  @param     (int)       datatype  The type of the texture (LINEAR, COLORMODEL,
1104                                   ...)
1105  @heading   Open GL Animation
1106 ****************************************************************************/
GLDatatoTexture(SurfaceElement * SurfPtr,GLubyte * textimage,double num,int datatype,int Comp)1107 void GLDatatoTexture(SurfaceElement *SurfPtr, GLubyte *textimage,
1108 		     double num, int datatype, int Comp)
1109 {
1110   GLubyte        *imgptr=NULL;
1111   int            intensity;
1112   SurfaceElement *ptr;
1113   double         i, minval=3.0e+38,maxval=0x0, tscale, flux;
1114 
1115 #if 0
1116   double         bscale;
1117   double         x=0,y=0,z=0;
1118   double         R=0,G=0,B=0;
1119   struct GLColorSystem NTSC = {0.64, 0.33, 0.29, 0.60, 0.15, 0.06, CWP};
1120   struct GLColorSystem *cs;
1121 #endif
1122   char * name;
1123 
1124   if (Comp == Primary)
1125     name = _("Primary");
1126   else if (Comp == Secondary)
1127     name = _("Secondary");
1128   else
1129     name = _("Disk");
1130 
1131   /* pointer to the texture image memory                                   */
1132   imgptr = textimage;
1133 
1134   switch (datatype) {
1135   case TEMP:
1136 
1137     minval = mintemp(SurfPtr, num);
1138     maxval = maxtemp(SurfPtr, num);
1139 
1140     /* linear scaling factor                                                 */
1141     tscale = 256 / (maxval-minval);
1142 
1143     if (Flags.debug[VERBOSE] == ON) {
1144       printf(_("%s: Minimum temperature %8.1f Kelvin\n"), name, minval);
1145       printf(_("%s: Maximum temperature %8.1f Kelvin\n"), name, maxval);
1146     }
1147 
1148     /* init linear grey-scale LUT                                            */
1149     ptr    = SurfPtr;
1150     for (i=0; i < num; i++) {
1151       intensity = (ptr->temp-minval)*tscale;
1152       /* assign R-value                                                     */
1153       *imgptr = (GLubyte) (intensity);
1154       imgptr++;
1155       /* assign G-value                                                     */
1156       *imgptr = (GLubyte) (intensity);
1157       imgptr++;
1158       /* assign B-value                                                     */
1159       *imgptr = (GLubyte) (intensity);
1160       imgptr++;
1161       ptr++;
1162     }
1163     break;
1164   case GRAV:
1165 
1166     minval = mingrav(SurfPtr, num);
1167     maxval = maxgrav(SurfPtr, num);
1168 
1169     /* linear scaling factor                                                 */
1170     tscale = 256 / (maxval-minval);
1171 
1172     if (Flags.debug[VERBOSE] == ON) {
1173       printf(_("%s: Minimum surface gravitation %8.4g\n"), name, minval);
1174       printf(_("%s: Maximum surface gravitation %8.4g\n"), name, maxval);
1175     }
1176 
1177     /* init linear grey-scale LUT                                            */
1178     ptr    = SurfPtr;
1179     for (i=0; i < num; i++) {
1180       intensity = (ptr->grav-minval)*tscale;
1181       /* assign R-value                                                     */
1182       *imgptr = (GLubyte) (intensity);
1183       imgptr++;
1184       /* assign G-value                                                     */
1185       *imgptr = (GLubyte) (intensity);
1186       imgptr++;
1187       /* assign B-value                                                     */
1188       *imgptr = (GLubyte) (intensity);
1189       imgptr++;
1190       ptr++;
1191     }
1192     break;
1193   case FLUX:
1194 
1195     maxval = log(maxflux(SurfPtr, num, Comp));
1196     minval = log(minflux(SurfPtr, num, Comp));
1197 
1198     /* linear scaling factor                                                 */
1199     tscale = 256 / (maxval-minval);
1200 
1201     if (Flags.debug[VERBOSE] == ON) {
1202       printf(_("%s: Minimum flux %8.4g\n"), name, minval);
1203       printf(_("%s: Maximum flux %8.4g\n"), name, maxval);
1204     }
1205 
1206     /* init linear grey-scale LUT                                            */
1207     ptr    = SurfPtr;
1208     for (i=0; i < num; i++) {
1209 
1210       if (ptr->CosGamma > 0) {
1211 	flux = (ptr->f_[0]/ ptr->area) * ptr->visibility *
1212 	  (1.0 - Limb[Comp][0][0]*(1.0 - ptr->CosGamma));
1213 	flux = (flux < minval) ? minval : flux;
1214       } else {
1215 	flux = minval;
1216       }
1217 
1218       flux = log(flux);
1219       intensity = (flux-minval)*tscale;
1220       if      (intensity > 255) intensity = 255;
1221       else if (intensity <   0) intensity =   0;
1222 
1223       /* assign R-value                                                     */
1224       *imgptr = (GLubyte) intensity;
1225       imgptr++;
1226       /* assign G-value                                                     */
1227       *imgptr = (GLubyte) intensity;
1228       imgptr++;
1229       /* assign B-value                                                     */
1230       *imgptr = (GLubyte) intensity;
1231       imgptr++;
1232       ptr++;
1233     }
1234     break;
1235   case VELOCITY:
1236 
1237     minval = minvel(SurfPtr, num);
1238     maxval = maxvel(SurfPtr, num);
1239 
1240     /* linear scaling factor                                                 */
1241     tscale = 255 / (maxval-minval);
1242 
1243     if (Flags.debug[VERBOSE] == ON) {
1244       printf(_("%s: Minimum velocity %8.4g\n"), name, minval);
1245       printf(_("%s: Maximum velocity %8.4g\n"), name, maxval);
1246     }
1247 
1248     /* init linear grey-scale LUT                                            */
1249     ptr    = SurfPtr;
1250     for (i=0; i < num; i++) {
1251       if (ptr->CosGamma > 0) {
1252 	flux = ptr->Velocity;
1253       } else {
1254 	flux = minval;
1255       }
1256       intensity = (flux-minval)*tscale;
1257       /* assign R-value                                                     */
1258       *imgptr = (GLubyte) (intensity);
1259       imgptr++;
1260       /* assign G-value                                                     */
1261       *imgptr = (GLubyte) (intensity);
1262       imgptr++;
1263       /* assign B-value                                                     */
1264       *imgptr = (GLubyte) (intensity);
1265       imgptr++;
1266       ptr++;
1267     }
1268     break;
1269 #if 0
1270   case BBCOLOR:
1271     ptr    = SurfPtr;
1272     cs     = &NTSC;
1273     for (i=0; i < num; i++) {
1274       GLBBtoxyz(ptr->temp,&x,&y,&z);
1275       //if (i == 0) printf("Temp %f: x %f y %f z %f  \n",ptr->temp,x,y,z);
1276       GLxyztoRGB(cs,x,y,z,&R,&G,&B);
1277       //if (i == 0) printf("         R %f G %f B %f  \n",R,G,B);
1278 
1279       /* scale R,G,B to byte size                                           */
1280 
1281       R = R * 255;
1282       B = B * 255;
1283       G = G * 255;
1284 
1285       /* scale brightness to maximum   R.W. 23.12.2002                      */
1286 
1287       bscale = (B > R) ? B : R;
1288       bscale = (G > bscale) ? G : bscale;
1289 
1290       R = (255 / bscale) * R;
1291       B = (255 / bscale) * B;
1292       G = (255 / bscale) * G;
1293 
1294       /* assign R-value                                                     */
1295       *imgptr = (GLubyte) R;
1296       imgptr++;
1297       /* assign G-value                                                     */
1298       *imgptr = (GLubyte) G;
1299       imgptr++;
1300       /* assign B-value                                                     */
1301       *imgptr = (GLubyte) B;
1302 
1303       imgptr++;
1304       ptr++;
1305     }
1306 
1307     break;
1308 #endif
1309   default:
1310     break;
1311   }
1312 
1313   /* save to global variables                                              */
1314   texture_minval[Comp] = minval;
1315   texture_maxval[Comp] = maxval;
1316 
1317   return;
1318 }
1319 
1320 /****************************************************************************
1321  @package   nightfall
1322  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
1323  @version   1.1
1324  @short     Init texture images for the stars and the disk
1325  @param     (int)       Comp      The stellar component
1326  @param     (int)       type      The type of the texture (IMAGE, TEMP, ...)
1327  @return    (gint)      status    The exit status
1328  @heading   Open GL Animation
1329 ****************************************************************************/
GLInitTexture(int Comp,int type)1330 int GLInitTexture(int Comp, int type)
1331 {
1332   GLubyte         *textimage=NULL;
1333   TextureType     *TexPtr=NULL;
1334   SurfaceElement  *SurfPtr;        /* pointer to surface elements          */
1335   BinaryComponent *BinPtr;         /* pointer to binary                    */
1336 
1337   double          numpoints;
1338   long            n_phi;           /* # of steps in phi                    */
1339   long            n_eta;           /* # of steps in eta                    */
1340   char            ErrMsg[4096];    /* error message                        */
1341 
1342   /* pointer to the texture image of the component                         */
1343   TexPtr  = &Texture[Comp];
1344   /* pointer to first surface element                                      */
1345   SurfPtr = Surface[Comp];
1346   /* pointer to the binary parameters                                      */
1347   BinPtr  = &Binary[Comp];
1348 
1349   n_eta   = StepsPerPi;
1350   n_phi   = BinPtr->N_PhiStep[0];
1351 
1352   /* be sure that texture does not already exist                           */
1353   /* sould be done more carefully !!! TBD MK                               */
1354   glDeleteTextures( 1, &TexPtr->TexName);
1355 
1356   /* create a new texture for this component                               */
1357   glGenTextures( 1, &TexPtr->TexName);
1358 
1359   switch (type) {
1360   case IMAGE:
1361     /* use a jpeg coded image file as texture                              */
1362     /* read the texture image from file                                    */
1363     textimage = ReadJPEGFile(TexPtr->TextFile, &TexPtr->Width, &TexPtr->Height,
1364 			     &TexPtr->Components);
1365 
1366     /* on error switch off texture for this component and return to caller */
1367     if(!textimage) {
1368       sprintf(ErrMsg,_("Could not read texture file %s "), TexPtr->TextFile);
1369       WARNING (ErrMsg);
1370       sprintf(ErrMsg,_("Texturing not enabled for component %d\n"),Comp);
1371       WARNING (ErrMsg);
1372       TexPtr->Type = NONE;
1373       return(FALSE);
1374     }
1375     else {
1376       if (Flags.debug[VERBOSE] == ON) {
1377 	printf(_("Reading Texture: %s: %d x %d  %d component \n"),
1378 	       TexPtr->TextFile,TexPtr->Width,
1379 	       TexPtr->Height,TexPtr->Components);
1380       }
1381       TexPtr->Type = IMAGE;
1382     }
1383     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1384     break;
1385 
1386   case TEMP:
1387   case GRAV:
1388   case FLUX:
1389   case VELOCITY:
1390     /* build a texture image from physical data                           */
1391     /* allocate memory for texture image                                  */
1392     if (Comp < Disk)
1393       numpoints = n_eta * n_phi;
1394     else
1395       numpoints = BinPtr->NumElem;
1396 
1397     textimage = (GLubyte *) malloc(numpoints * TEXTURE_COMPONENTS);
1398 
1399     if (!textimage) {
1400       sprintf(ErrMsg,_("Can't allocate memory for texture image buffer !\n"));
1401       WARNING (ErrMsg);
1402       return(FALSE);
1403     }
1404 
1405     GLDatatoTexture(SurfPtr, textimage, numpoints, type, Comp);
1406     /*
1407     TexPtr->Width      = n_eta;
1408     TexPtr->Height     = n_phi;
1409     */
1410     /* exchange width and height R.W. 23.12.2002  */
1411     TexPtr->Width      = n_phi;
1412     if (Comp < Disk)
1413       TexPtr->Height     = n_eta;
1414     else
1415       TexPtr->Height     = numpoints / n_phi;
1416     TexPtr->Components = TEXTURE_COMPONENTS;
1417     break;
1418 
1419   default:
1420     /* we failed to initialize texturing -> turn off texture              */
1421     TexPtr->Type = NONE;
1422     return(FALSE);
1423     break;
1424   }
1425 
1426   glBindTexture(GL_TEXTURE_2D, TexPtr->TexName);
1427 
1428   /* repetitively wrap texture on object                                 */
1429   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1430   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1431 
1432   /* modulate colour of component with texture colour                    */
1433   if (Flags.textype != BBCOLOR)
1434     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1435 
1436   /* replace colour of component with texture colour                     */
1437   else
1438     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
1439 
1440   /* apply a linear approximation for texturing                          */
1441   /* GL_LINEAR is bad, produces a stripe                                 */
1442   //    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1443   //    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1444   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1445   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1446 
1447   /* build texture map                                                   */
1448   gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, TexPtr->Width,
1449 		    TexPtr->Height, GL_RGB, GL_UNSIGNED_BYTE,
1450 		    textimage);
1451   free(textimage);
1452 
1453   return(TRUE);
1454 }
1455 
1456 /****************************************************************************
1457  @package   nightfall
1458  @author    Markus Kuster (kuster@astro.uni-tuebingen.de)
1459  @version   1.0
1460  @short     Real-time animation of the binary system
1461  @param     (int)  j  The phase index
1462  @return    (void)
1463  @heading   Open GL Animation
1464 ****************************************************************************/
AnimateGL(int j)1465 void AnimateGL(int j)
1466 {
1467   char        top_title[MAX_CFG_INLINE+1];    /* window title string       */
1468   GtkWidget   *GLvbox,*GLhbox,*GLLightvbox;
1469   GtkWidget   *GLmenu_bar;
1470   GtkWidget   *GL3dFrame;
1471   DispInfo    *DispInfoPtr;
1472   static int  noentry = 0;
1473   static int  glut_initialized = 0;
1474 
1475   int attrlist[] = {
1476     GDK_GL_RGBA,
1477     GDK_GL_DEPTH_SIZE, 1,
1478     GDK_GL_RED_SIZE,   1,
1479     GDK_GL_GREEN_SIZE, 1,
1480     GDK_GL_BLUE_SIZE,  1,
1481     GDK_GL_DOUBLEBUFFER,
1482     GDK_GL_NONE
1483   };
1484 
1485   int     argc = 1;
1486   char  * argv[] = { "nightfall", NULL };
1487 
1488   if (noentry == 1)
1489     return;
1490 
1491   if (!glut_initialized)
1492     {
1493       glutInit(&argc, argv);
1494       glut_initialized = 1;
1495     }
1496 
1497   phaseind = j;
1498 
1499   if (GLWindowHidden == ON) {
1500     gtk_widget_show (glWindow);
1501     GLWindowHidden = OFF;
1502   }
1503 
1504   if (GLWindowOpened == OFF) {
1505     /* >>>>>>>>>>>  Initialize Window  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
1506     if (Flags.debug[VERBOSE] == ON) {
1507       { printf("\n");   printf(_("\n Initializing GLX Animation\n\n") );}
1508     }
1509 
1510     /* create new toplevel window                                          */
1511     glWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
1512 
1513     /* set window title                                                    */
1514     sprintf(top_title, "%10s %5s", PACKAGE, VERSION);
1515     gtk_window_set_title(GTK_WINDOW(glWindow), top_title);
1516 
1517     /* set window size                                                     */
1518     gtk_widget_set_usize (glWindow, GLWIN_WIDTH, GLWIN_HEIGHT);
1519     gtk_widget_realize(glWindow);
1520     gtk_quit_add_destroy(1, GTK_OBJECT(glWindow));
1521 
1522     /* ----------- connect the exit handler ------------------------------ */
1523 
1524     gtk_signal_connect (GTK_OBJECT (glWindow), "delete_event",
1525 			GTK_SIGNAL_FUNC (GLDelete), NULL);
1526 
1527     gtk_widget_show(GTK_WIDGET(glWindow));
1528 
1529     /* new vertical box for menu and GLArea                                */
1530     GLvbox = gtk_vbox_new (FALSE, 0);
1531     gtk_container_add (GTK_CONTAINER (glWindow), GLvbox);
1532     gtk_widget_show(GLvbox);
1533 
1534     /* >>>>>>>>>>>  the menu bar  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
1535     GLmenu_bar = gtk_menu_bar_new();
1536     GLMakeMenu(GLmenu_bar);
1537     gtk_box_pack_start (GTK_BOX (GLvbox), GLmenu_bar, FALSE, FALSE, 0);
1538 
1539     /* new horizontal box for scene and plot area                          */
1540     GLhbox = gtk_hbox_new (FALSE, 0);
1541     gtk_container_add (GTK_CONTAINER (GLvbox), GLhbox);
1542     gtk_widget_show(GLhbox);
1543 
1544     /* ---------------- 3D System Window --------------------------------- */
1545     /* frame for 3d scene                                                  */
1546     GL3dFrame = gtk_frame_new (_("Binary System") );
1547     gtk_container_add (GTK_CONTAINER (GLhbox), GL3dFrame);
1548     gtk_container_set_border_width(GTK_CONTAINER(GL3dFrame), 2);
1549     gtk_widget_show (GL3dFrame);
1550 
1551     /* create new OpenGL scene area                                        */
1552 
1553     if (gdk_gl_query() == FALSE)
1554       {
1555 	char command[256];
1556 
1557 	noentry = 1;
1558 	if (0 == system("which xmessage > /dev/null"))
1559 	  {
1560 	    int retval;
1561 
1562 	    sprintf(command,
1563 		    _("xmessage  \"ERROR: OpenGL not supported\" "));
1564 	    retval = system(command);
1565 	    if (retval)
1566 	      perror("xmessage");
1567 	  }
1568 	return;
1569       }
1570 
1571     glArea = GTK_WIDGET(gtk_gl_area_new(attrlist));
1572     if (NULL == glArea)
1573       {
1574 	char command[256];
1575 
1576 	noentry = 1;
1577 	if (0 == system("which xmessage > /dev/null"))
1578 	  {
1579 	    int retval;
1580 
1581 	    sprintf(command,
1582 		    _("xmessage  \"ERROR: OpenGL not working\" "));
1583 	    retval = system(command);
1584 	    if (retval)
1585 	      perror("xmessage");
1586 	  }
1587 	GLDelete(NULL, NULL);
1588 	return;
1589       }
1590     gtk_widget_show(glArea);
1591 
1592 
1593     /* set event mask for widget                                           */
1594     gtk_widget_set_events(glArea,
1595 			  GDK_EXPOSURE_MASK|
1596 			  GDK_BUTTON_PRESS_MASK|
1597 			  GDK_BUTTON_RELEASE_MASK|
1598 			  GDK_KEY_PRESS_MASK|
1599 			  GDK_KEY_RELEASE_MASK|
1600 			  GDK_POINTER_MOTION_MASK|
1601 			  GDK_POINTER_MOTION_HINT_MASK);
1602 
1603     gtk_gl_area_size(GTK_GL_AREA(glArea), GLAREA_WIDTH, GLAREA_HEIGHT);
1604 
1605     /* do initialization when widget has been realized                     */
1606     gtk_signal_connect(GTK_OBJECT(glArea), "realize",
1607 		       GTK_SIGNAL_FUNC(GLInit3d), NULL);
1608 
1609     gtk_signal_connect(GTK_OBJECT(glArea), "button_press_event",
1610 		       GTK_SIGNAL_FUNC(GLButtonPress), NULL);
1611 
1612     /* redraw image when exposed                                           */
1613     gtk_signal_connect(GTK_OBJECT(glArea), "expose_event",
1614     		       GTK_SIGNAL_FUNC(GLDisplayAll), NULL);
1615 
1616     /* rotate and translate objects on mouse movement                      */
1617     gtk_signal_connect (GTK_OBJECT(glArea), "motion_notify_event",
1618 			GTK_SIGNAL_FUNC(GLMotionNotify), NULL);
1619 
1620     /* capture keypress events                                             */
1621     gtk_signal_connect(GTK_OBJECT(glArea), "key_press_event",
1622 		       GTK_SIGNAL_FUNC(GLKeyboard), NULL);
1623 
1624     /* when window is resized viewport needs to be resized, too            */
1625     gtk_signal_connect(GTK_OBJECT(glArea), "configure_event",
1626 		       GTK_SIGNAL_FUNC(GLReshape), NULL);
1627 
1628     /* initialize display info structure                                   */
1629     DispInfoPtr = (DispInfo*)g_malloc(sizeof(DispInfo));
1630     DispInfoPtr->mousex = 0;
1631     DispInfoPtr->mousey = 0;
1632     DispInfoPtr->xpos   = 0;
1633     DispInfoPtr->zoom   = 1.;
1634 
1635     /* init trackball                                                      */
1636     trackball(DispInfoPtr->quat , 0.0, 0.0, 0.0, 0.0);
1637 
1638     /* Add DispInfo to glArea object                                       */
1639     gtk_object_set_data(GTK_OBJECT(glArea), "DispInfo", DispInfoPtr);
1640 
1641     /* add glArea to frame
1642      */
1643     gtk_container_add (GTK_CONTAINER(GL3dFrame), glArea);
1644 
1645     /* set event mask for widget                                           */
1646     /* enable focus for glarea widget                                      */
1647     GTK_WIDGET_SET_FLAGS(glArea, GTK_CAN_FOCUS);
1648     gtk_widget_grab_focus(glArea);
1649 
1650     /* ------------------------------------------------------------------- */
1651 
1652 
1653     /* new vertical box for lightcurve and radial vel. plot                */
1654     GLLightvbox = gtk_vbox_new (FALSE, 0);
1655     gtk_container_add (GTK_CONTAINER (GLhbox), GLLightvbox);
1656     gtk_widget_show(GLLightvbox);
1657 
1658     glutInitDisplayMode(GLUT_DEPTH);
1659 
1660     /* Render all Viewports                                                */
1661     GLDisplayAll();
1662 
1663     /* Set window status to open                                           */
1664     GLWindowOpened = ON;
1665   }
1666   else
1667     {
1668     /* update all geometries                                               */
1669     GLUpdateAll();
1670     /* update texture if active and new animation run R.W. 23.12.2002      */
1671     if (j == 0 && Flags.texture == ON && Flags.textype != IMAGE)
1672       {
1673 	GLInitTexture(Primary, Flags.textype);
1674 	GLInitTexture(Secondary, Flags.textype);
1675 #ifdef HAVE_DISK
1676 	GLInitTexture(Disk, Flags.textype);
1677 #endif
1678       }
1679     else if (Flags.texture == ON &&
1680 	     (Flags.textype == FLUX || Flags.textype == VELOCITY))
1681       {
1682 	GLInitTexture(Primary, Flags.textype);
1683 	GLInitTexture(Secondary, Flags.textype);
1684 #ifdef HAVE_DISK
1685 	GLInitTexture(Disk, Flags.textype);
1686 #endif
1687       }
1688     /* Render all Viewports                                                */
1689     GLDisplayAll();
1690   }
1691 
1692   /* write animation frames                                                */
1693   if (Flags.movie == ON) {
1694     strcpy(movfile,"");
1695     sprintf(movfile,"frame%.3d.jpg",Flags.frame);
1696     /* grab 3D Viewport only and save as max. quality jpeg file            */
1697     GLGrabScreen(movfile,0,0,VP_3D_WIDTH,VP_3D_HEIGHT,100);
1698     /* increase frame number                                               */
1699     Flags.frame++;
1700   }
1701 
1702   return;
1703 }
1704 
1705 #endif /* OpenGL end */
1706 
1707 
1708 
1709