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