/* NIGHTFALL OpenGL Interface */
/* Copyright (C) 2001 Rainer Wichmann & Markus Kuster */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify */
/* it under the terms of the GNU General Public License as */
/* published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/*
*/
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ANSI C forbids an empty source file, so put this outside */
/* do nothing here if we don't have OpenGL */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "Light.h"
#ifdef _WITH_OPENGL
#include <setjmp.h>
#include "LightGLPrefs.h"
/* Display lists */
GLint PrimaryList, SecondaryList, DiskList, PlotList[2];
TextureType Texture[3];
/* Parameters for coordinate systems */
CoordType CoordSys[2];
/* structure keeping all eight spot lights */
LightType Lights[MAX_LIGHT_NUM];
GLfloat lightpos[4];
/* Color is RGBA where A is the alpha channel */
/* color and emission properties of the stars */
/* primary */
GLfloat primary_colour[] = {0.92, 0.057, 0.0, 1.0 };
GLfloat primary_mat_specular[] = { 0.0, 0.0 , 0.0, 1.0 };
GLfloat primary_mat_diffuse[] = { 1.0, 0.60 , 0.0, 1.0 };
GLfloat primary_mat_shininess[] = { 0.0 };
/* secondary */
GLfloat secondary_colour[] = {0.066, 0.6666, 1.0, 1.0 };
GLfloat secondary_mat_specular[] = { 0.0 , 0.0 , 0.0, 1.0 };
GLfloat secondary_mat_diffuse[] = { 1.0 , 0.40 , 0.0, 1.0 };
GLfloat secondary_mat_shininess[] = { 0.0 };
#ifdef HAVE_DISK
/* color and emission properties of the disk */
GLfloat disk_colour[] = { 0.6, 0.047, 0.0, 1.0};
GLfloat disk_mat_specular[] = { 0.0, 0.0, 0.0, 1.0};
GLfloat disk_mat_diffuse[] = { 1.0, 0.40, 0.0, 1.0};
GLfloat disk_mat_shininess[] = { 0.0 };
#endif
/* spot definition for the primary */
GLfloat primary_spot1_direction[] = {0.0, 0.0, -1.0};
GLfloat primary_spot2_direction[] = {0.0, 0.0, -1.0};
/* spot definition for the secondary */
GLfloat secondary_spot1_direction[] = {0.0, 0.0, -1.0};
GLfloat secondary_spot2_direction[] = {0.0, 0.0, -1.0};
/* the background color */
GLfloat bgd_colour[] = {0.0,0.0,0.0,1.0};
/* OpenGL window opened */
int GLWindowOpened = OFF; /* OpenGL window opened */
int GLWindowHidden = OFF; /* OpenGL window opened */
int phaseind=0;
GtkWidget *glArea = NULL;
GtkWidget *glPlot = NULL;
GtkWidget *glVelo = NULL;
GtkWidget *glWindow = NULL; /* Scene and plot window */
static char movfile[256]; /* file name of the movie files */
GLvoid *GLDrawFont = GLUT_BITMAP_TIMES_ROMAN_10;
GLuint screen;
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short The main drawing code
@param (GtkWidget) *widget discarded
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLDisplayAll( void )
{
DispInfo *DispInfoPtr;
DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
/* clear colour buffer */
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* define 3d window viewport */
glViewport(VP_3D_X0, VP_3D_Y0, VP_3D_WIDTH, VP_3D_HEIGHT);
/* render 3D view */
GLDisplay3d(glArea);
/* define light curve viewport */
glViewport(VP_LC_X0, VP_LC_Y0, VP_LC_WIDTH, VP_LC_HEIGHT);
/* render light curve */
GLDisplayPlot(glArea,LIGHTCURVE);
/* define radial velocity viewport */
glViewport(VP_RV_X0, VP_RV_Y0, VP_RV_WIDTH, VP_RV_HEIGHT);
/* render radial velocity plot */
GLDisplayPlot(glArea,RADVELOCITY);
if (Flags.texture == ON && Flags.textype != IMAGE)
{
/* define wedge primary viewport */
glViewport(VP_WP_X0, VP_WP_Y0, VP_WP_WIDTH, VP_WP_HEIGHT);
GLDisplayWedge( Primary );
/* define wedge secondary viewport */
glViewport(VP_WS_X0, VP_WS_Y0, VP_WS_WIDTH, VP_WS_HEIGHT);
GLDisplayWedge( Secondary );
#ifdef HAVE_DISK
if (Flags.disk == ON) {
/* define wedge disk viewport */
glViewport(VP_WD_X0, VP_WD_Y0, VP_WD_WIDTH, VP_WD_HEIGHT);
GLDisplayWedge( Disk );
}
#endif
}
/* finally swap display buffers, we are in DoubleBuffering mode */
gtk_gl_area_swap_buffers(GTK_GL_AREA(glArea));
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Update all display lists
@param (void) *widget discarded
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLUpdateAll( void )
{
/* OpenGL functions can be called only if make_current returns true */
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
/* Update display lists for 3D main window */
GLUpdate3d(glArea);
/* Update top plot window */
GLUpdatePlot(5,LIGHTCURVE);
/* Update bottom plot window */
GLUpdatePlot(6,RADVELOCITY);
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Update the primary/secondary geometry
@param (GtkWidget) *widget discarded
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLUpdate3d( GtkWidget *widget )
{
/* OpenGL functions can be called only if make_current returns true */
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
if ( PrimaryList ) {
/* delete the old display list to save memory */
glDeleteLists(PrimaryList,1);
}
/* Create the primary list */
PrimaryList=glGenLists(1);
glNewList(PrimaryList, GL_COMPILE);
if (Flags.points == TRUE) {
GLMakeVolumeEclipsed(Primary);
} else {
GLMakeVolumeEclipsed(Primary);
}
glEndList();
if ( SecondaryList ) {
/* delete the old display list to save memory */
glDeleteLists(SecondaryList,1);
}
/* Create the secondary list */
SecondaryList=glGenLists(2);
glNewList(SecondaryList, GL_COMPILE);
if (Flags.points == TRUE) {
GLMakeVolumeEclipsed(Secondary);
} else {
GLMakeVolumeEclipsed(Secondary);
}
glEndList();
#ifdef HAVE_DISK
/* Create the disk display list */
if ( Flags.disk == ON ) {
if ( DiskList ) {
/* delete the old display list to save memory */
glDeleteLists(DiskList,1);
}
DiskList=glGenLists(3);
glNewList(DiskList, GL_COMPILE);
if (Flags.points == TRUE) {
GLMakeVolumeEclipsed(Disk);
} else {
GLMakeVolumeEclipsed(Disk);
}
glEndList();
}
#endif
}
return;
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Update a plot viewport
@param (int) viewport number of viewport
@param (int) type type of plot (light curve / rad. vel.)
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLUpdatePlot( int viewport, int type )
{
/* OpenGL functions can be called only if make_current returns true */
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
if ( PlotList[type] ) {
/* delete the old display list to save memory */
glDeleteLists(PlotList[type],1);
}
PlotList[type]=glGenLists(viewport);
glNewList(PlotList[type], GL_COMPILE);
switch (type)
{
case LIGHTCURVE:
GLMakeLCPlot();
break;
case RADVELOCITY:
GLMakeRVPlot();
break;
default:
break;
}
glEndList();
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Select font
@param (int) style font name
@param (int) size font size
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLSetFont(int style, int size)
{
switch (style) {
case HELVETICA:
if (size == 12)
GLDrawFont = GLUT_BITMAP_HELVETICA_12;
else if (size == 18)
GLDrawFont = GLUT_BITMAP_HELVETICA_18;
break;
case TIMESROMAN:
GLDrawFont = GLUT_BITMAP_TIMES_ROMAN_10;
if (size == 24)
GLDrawFont = GLUT_BITMAP_TIMES_ROMAN_24;
break;
default:
GLDrawFont = GLUT_BITMAP_HELVETICA_10;
break;
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Display given string at position x,y
@param (GLint) x x coordinate
@param (GLint) y y coordinate
@param (GLint) z z coordinate
@param (char) format string to draw
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLDrawStr(GLfloat x, GLfloat y, GLfloat z, char* format, ...)
{
int string_width;
float string_off;
va_list args;
char buffer[256], *s;
va_start(args, format);
vsnprintf(buffer, 256, format, args);
va_end(args);
string_width = 0;
for (s = buffer; *s; s++)
string_width += glutBitmapWidth(GLDrawFont, *s);
string_off = string_width/2.;
glRasterPos3f(x, y, z);
for (s = buffer; *s; s++) {
glutBitmapCharacter(GLDrawFont, *s);
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Draw labels for 3D plot
@param (GLfloat) length length of the axes
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLDrawLabels(GtkWidget *widget)
{
double RLag1;
float com; /* center of mass */
/* the x coordinate of the center of mass */
com = (((float)(Binary[Primary].Mq))/( 1.0 + (float)(Binary[Primary].Mq)));
/* x-coordinate of lagrange point one */
RLag1 = Binary[Primary].RLag1;
if (gtk_gl_area_make_current(GTK_GL_AREA(widget)))
{
/* disable lighting, we don't want ligthing with */
/* markers */
glDisable(GL_LIGHTING);
/* draw axes with thick lines */
glLineWidth(2);
/* select font */
GLSetFont(HELVETICA, 12);
glColor3f(0.0, 0.0, 1.0);
GLDrawStr(RLag1,0.0,0.6,"L1");
glColor3f(1.0, 1.0, 1.0);
GLDrawStr(0.0,0.0,0.7,"Primary");
glColor3f(1.0, 1.0, 1.0);
GLDrawStr(0.9,0.0,0.7,"Secondary");
/* translate to display coordinates with com
at (0,0,0) */
glBegin(GL_LINES);
/* blue; lagrange point one */
glColor3f(0.0, 0.0, 1.0);
glVertex3f(RLag1, 0.0, 0.4);
glVertex3f(RLag1, 0.0, 0.5);
/* white; primary */
glColor3f(1.0, 1.0, 1.0);
glVertex3f(0.0, 0.0, 0.5);
glVertex3f(0.0, 0.0, 0.6);
/* white; secondary */
glColor3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 0.0, 0.5);
glVertex3f(1.0, 0.0, 0.6);
glEnd();
/* switch on lighing */
glEnable(GL_LIGHTING);
/* set line width back to one */
glLineWidth(1);
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Resize the GL window and update the viewport
@param (GtkWidget) discarded
(GdkEventConfigure) event pointer to the event structure
@return (gint) status the exit status
@heading Open GL Animation
****************************************************************************/
gint GLReshape( GtkWidget *widget, GdkEventConfigure *event )
{
GLfloat h;
DispInfo *DispInfoPtr;
DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
/* OpenGL functions can be called only if make_current returns true */
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
/* get the dimension of the GTK window */
h= (GLfloat) glArea->allocation.height / (GLfloat) glArea->allocation.width;
/* set the glViewport to the full size of */
/* all Viewports */
glViewport(0,0, GLAREA_WIDTH, GLAREA_HEIGHT);
return(TRUE);
} else {
return(FALSE);
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Motion event handling
@param (GtkWidget) *widget pointer to the GL area widget
(GdkEventKey) *event the motion event
@return (void)
@heading Open GL Animation
****************************************************************************/
gint GLMotionNotify(GtkWidget *widget, GdkEventMotion *event)
{
int x, y;
uint BUTTON12_MASK;
float spin_quat[4];
GdkRectangle area;
GdkModifierType state;
DispInfo *DispInfoPtr;
DispInfoPtr = (DispInfo*)gtk_object_get_data(GTK_OBJECT(glArea), "DispInfo");
if (event->is_hint) {
gdk_window_get_pointer(event->window, &x, &y, &state);
} else {
x = event->x;
y = event->y;
state = event->state;
}
area.x = 0;
area.y = 0;
area.width = glArea->allocation.width;
area.height = glArea->allocation.height;
BUTTON12_MASK = (1 << 8) + (1 << 9);
if (state & GDK_BUTTON1_MASK) {
/* drag in progress, simulate trackball */
trackball(spin_quat,
(2.0*DispInfoPtr->mousex - area.width) / area.width,
( area.height - 2.0*DispInfoPtr->mousey) / area.height,
( 2.0*x - area.width) / area.width,
( area.height - 2.0*y) / area.height);
add_quats(spin_quat, DispInfoPtr->quat, DispInfoPtr->quat);
/* orientation has changed, redraw all */
gtk_widget_draw(glArea, &area);
}
if (state & GDK_BUTTON2_MASK) {
/* zooming drag */
DispInfoPtr->zoom += ((y - DispInfoPtr->mousey) / area.height) * 1.0;
if (DispInfoPtr->zoom < 0.1) DispInfoPtr->zoom = 0.1;
if (DispInfoPtr->zoom > 20) DispInfoPtr->zoom = 20;
/* zoom has changed, redraw mesh */
gtk_widget_draw(glArea, &area);
}
if (state & GDK_BUTTON3_MASK) {
/* left/right drag */
DispInfoPtr->xpos += ((x - DispInfoPtr->mousex) / area.height) * 1.0;
if (DispInfoPtr->xpos < -3.0) DispInfoPtr->xpos = -3.0;
if (DispInfoPtr->xpos > 3.0) DispInfoPtr->xpos = 3.0;
gtk_widget_draw(glArea, &area);
}
DispInfoPtr->mousex = x;
DispInfoPtr->mousey = y;
return(TRUE);
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Mouse event handling
@param (GtkWidget) *widget pointer to the GL area widget
(GdkEventKey) *event the mouse event
@return (void)
@heading Open GL Animation
****************************************************************************/
gint GLButtonPress(GtkWidget *widget, GdkEventButton *event)
{
DispInfo *DispInfoPtr;
DispInfoPtr= (DispInfo*)gtk_object_get_data(GTK_OBJECT(widget), "DispInfo");
if (event->button == 1) {
/* beginning of drag, reset mouse position */
DispInfoPtr->mousex = event->x;
DispInfoPtr->mousey = event->y;
return(TRUE);
}
return(FALSE);
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Grab GL viewport and write as JPEG coded image file
@param (char) *filename the name of the image file
(int) x0 x0 position rel. to glViewport
(int) x0 x0 position rel. to glViewport
(int) width width of the area to grab
0 < width <= GLAREA_WIDTH
(int) height height of the area to grab
0 < height <= GLAREA_HEIGHT
(int) quality the compression factor
(0 < quality < 100)
@return (int) TRUE if successful else FALSE
@heading Read a GL viewport, compress the image and save it as a
jpeg-file. This code is based on the example code
'example.c' included in the jpeg-library libjpeg-6.2.0.
****************************************************************************/
int GLGrabScreen(char *filename, int x0, int y0,
int width, int height, int quality)
{
JSAMPLE *imgbuff; /* array of R,G,B - order data for image */
int imgwidth, imgheight; /* width and height of the area to grab */
int success; /* return status */
char ErrMsg[256]; /* error message */
#ifdef USING_GTK2
gdk_drawable_get_size(glWindow->window, &imgwidth, &imgheight);
#else
gdk_window_get_size(glWindow->window, &imgwidth, &imgheight);
#endif
imgwidth = width;
imgheight = height;
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
/* allocate an image storage buffer */
imgbuff=(unsigned char *)malloc(imgheight*imgwidth*3);
if (!imgbuff) {
sprintf(ErrMsg,_("Can't allocate memory for the image buffer\n"));
WARNING (ErrMsg);
return(FALSE);
}
/* grab image from the viewport */
glReadPixels(x0,y0,imgwidth,imgheight,GL_RGB,GL_UNSIGNED_BYTE,
imgbuff);
/* write image to jpeg file */
success=WriteJPEGFile(imgbuff, filename, imgwidth, imgheight,
3, quality);
if (!success) {
sprintf(ErrMsg,_("Failed to write mage file !\n"));
WARNING (ErrMsg);
return(FALSE);
}
/* free memory of the image buffer */
if (imgbuff) {
free(imgbuff);
}
}
return(TRUE);
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Init lighting model
@param (GtkWidget) *widget pointer to the GL area widget
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLInitLighting( GtkWidget *widget )
{
GLdouble a=2.90;
GLfloat com;
GLfloat qa=1.0/a/a;
/* the x coordinate of the center of mass */
com = (((GLfloat)(Binary[Primary].Mq))/( 1.0 + (GLfloat)(Binary[Primary].Mq)));
/* set position of lights */
Lights[SCENE_LIGHT].Pos[0] = 1.0;
Lights[SCENE_LIGHT].Pos[1] = 0.0;
Lights[SCENE_LIGHT].Pos[2] = 0.0;
Lights[SCENE_LIGHT].Pos[3] = 1.0;
Lights[DISK_SPOT].Pos[0] = 1.0;
Lights[DISK_SPOT].Pos[1] = 0.0;
Lights[DISK_SPOT].Pos[2] = 0.0;
Lights[DISK_SPOT].Pos[3] = 1.0;
Lights[PRIMARY_ONE].Pos[0] = 0.0;
Lights[PRIMARY_ONE].Pos[1] = 0.0;
Lights[PRIMARY_ONE].Pos[2] = 0.0;
Lights[PRIMARY_ONE].Pos[3] = 1.0;
Lights[PRIMARY_TWO].Pos[0] = 0.0;
Lights[PRIMARY_TWO].Pos[1] = 0.0;
Lights[PRIMARY_TWO].Pos[2] = 0.0;
Lights[PRIMARY_TWO].Pos[3] = 1.0;
glLightfv(SCENE_LIGHT, GL_DIFFUSE, primary_colour);
glLightfv(SCENE_LIGHT, GL_SPECULAR, primary_colour);
glLightf(SCENE_LIGHT, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(SCENE_LIGHT, GL_LINEAR_ATTENUATION, 0.0);
glLightf(SCENE_LIGHT, GL_QUADRATIC_ATTENUATION, qa*0.95);
glLightfv(DISK_SPOT, GL_DIFFUSE, primary_colour);
glLightfv(DISK_SPOT, GL_SPECULAR, primary_colour);
glLightf(DISK_SPOT, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(DISK_SPOT, GL_LINEAR_ATTENUATION, 0.0);
glLightf(DISK_SPOT, GL_QUADRATIC_ATTENUATION, qa*0.95);
glLightfv(PRIMARY_ONE, GL_DIFFUSE, primary_colour);
glLightfv(PRIMARY_ONE, GL_SPECULAR, primary_colour);
glLightf(PRIMARY_ONE, GL_CONSTANT_ATTENUATION, 0.0);
glLightf(PRIMARY_ONE, GL_LINEAR_ATTENUATION, 0.0);
glLightf(PRIMARY_ONE, GL_QUADRATIC_ATTENUATION, qa);
glEnable(GL_LIGHTING);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 0.1
@short Visualize spots
@param (int) Comp The stellar component
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLMakeSpots( int Comp, float xpos )
{
int nspot; /* index of current spot */
int N_Spot = 0; /* # of spots on star */
/*long i; */ /* loop counter */
/*double LatS; */ /* spot latitude */
/*double LongS;*/ /* spot longitude */
/*double RadSpot;*/ /* spot radius */
if (Comp == Primary) {
xpos = 0.0;
N_Spot = Flags.Spots1;
}
else if (Comp == Secondary) {
xpos = 1.0;
N_Spot = Flags.Spots2;
}
/* show only the first two spots per component in GL animation, which are*/
/* the spots defined in the GUI */
if (N_Spot > 1) {
N_Spot = 1;
}
lightpos[0]=xpos;
lightpos[1]=0.0;
lightpos[2]=0.0;
lightpos[3]=1.0;
/* set spot position */
if (Comp == Primary) {
glLightfv(PRIMARY_ONE, GL_POSITION, lightpos);
glLightfv(PRIMARY_TWO, GL_POSITION, lightpos);
} else {
glLightfv(SECONDARY_ONE, GL_POSITION, lightpos);
glLightfv(SECONDARY_TWO, GL_POSITION, lightpos);
}
/* ----------------- loop over spots ---------------------------------- */
for (nspot = 0; nspot < N_Spot; ++nspot) {
/* latitude of the spot in radians */
/*LatS = DTOR * Spot[Comp][nspot].latitude;
LongS = DTOR * Spot[Comp][nspot].longitude;*/
/* Must be != NULL, else spot is incorrectly placed
*/
/*LatS = ( fabs(LatS) >= DBL_EPSILON) ? LatS : DBL_EPSILON;
LongS = ( fabs(LongS) >= DBL_EPSILON) ? LongS : DBL_EPSILON;*/
/* ------------- spot size ------------------------------------- */
/* RadSpot = DTOR * Spot[Comp][nspot].radius;*/
/* set spot direction */
/* glLightfv(DISK_SPOT, GL_SPOT_DIRECTION, primary_spot1_direction);
glLightfv(PRIMARY_ONE, GL_SPOT_DIRECTION, primary_spot2_direction);*/
}
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Init geometry display
@param (GtkWidget) *widget discarded
@return (gint) status the exit status
@heading Open GL Animation
****************************************************************************/
gint GLInit3d(GtkWidget *widget )
{
SurfaceElement *SurfPtr; /* pointer to surface elements */
SurfPtr=Surface[Primary];
/* OpenGL functions can be called only if make_current */
/* returns true */
if (gtk_gl_area_make_current(GTK_GL_AREA(glArea)))
{
/* set background color to black */
glClearColor (bgd_colour[0], bgd_colour[1], bgd_colour[2], bgd_colour[3]);
/* glEnable(GL_DITHER); */
/* use smooth Gouraud shading */
glShadeModel (GL_SMOOTH);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
/*glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);*/
/* enable hidden line removal */
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
/* activate depth mask */
glDepthMask(GL_TRUE);
/* clear colour buffer and depth buffer */
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* set draw color to white */
glColor3f (1.0, 1.0, 1.0);
/* define lights */
GLInitLighting(glArea);
/* Initialize texturing */
GLInitTextureParams(Primary);
if (GLInitTexture(Primary, Flags.textype)) {
Texture[Primary].IsOn = ON;
} else {
Texture[Primary].IsOn = OFF;
}
GLInitTextureParams(Secondary);
if (GLInitTexture(Secondary, Flags.textype)) {
Texture[Secondary].IsOn = ON;
} else {
Texture[Secondary].IsOn = OFF;
}
#ifdef HAVE_DISK
/* texture for disk has to be initialzed in any case */
GLInitTextureParams(Disk);
if (GLInitTexture(Disk, Flags.textype)) { // CORRECT?
Texture[Disk].IsOn = ON;
} else {
Texture[Disk].IsOn = OFF;
}
#endif
/* switch on the lights */
/*glEnable(SCENE_LIGHT);*/
/*glEnable(DISK_SPOT);*/
/*glEnable(PRIMARY_ONE);*/
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
GLUpdateAll();
return(TRUE);
} else {
return(FALSE);
}
}
/****************************************************************************
@package nightfall
@author Rainer Wichmann (rwichman@lsw.uni-heidelberg.de)
@version 1.0
@short Callback function for GLWindow delete
@param (GtkWidget) *widget Discarded
@param (gpointer) *data Discarded
@return (void)
@heading Open GL Animation
****************************************************************************/
void GLDelete (GtkWidget *widget, gpointer *data)
{
if (GLPrefWinOpened == TRUE) {
if (glPrefsWindow != NULL)
gtk_widget_destroy (glPrefsWindow);
glPrefsWindow = NULL;
GLPrefWinOpened = OFF;
}
gtk_widget_hide (glWindow);
GLWindowHidden = ON;
/*
if (glArea != NULL)
gtk_widget_destroy (glArea);
glArea = NULL;
if (glWindow != NULL)
gtk_widget_destroy (glWindow);
glWindow = NULL;
GLWindowOpened = OFF;
*/
return;
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Init texture parameters
@param (int) Comp The stellar component
@return (int) status The exit status
@heading Open GL Animation
****************************************************************************/
int GLInitTextureParams(int Comp)
{
TextureType *TexPtr=NULL; /* Pointer to texture */
char texture_file[MAX_CFG_INLINE+1] = "\0"; /* Texture image file */
FILE *txtFile;
int len;
TexPtr=&Texture[Comp];
strncpy(texture_file, data_pix_fls(), sizeof(texture_file)-1);
texture_file[sizeof(texture_file)-1] = '\0';
len = strlen(texture_file);
/* set default values (filenames should be stored in preferences TBD MK) */
if ( Comp == Primary) {
strncat(texture_file, "/starp_256.jpg", sizeof(texture_file) - len -1);
} else if ( Comp == Secondary ) {
strncat(texture_file, "/stars_256.jpg", sizeof(texture_file) - len -1);
}
#ifdef HAVE_DISK
else {
strncat(texture_file, "/disk_256.jpg", sizeof(texture_file) - len -1);
}
#endif
/* not found in default directory -> try local directory */
if ((txtFile = fopen (texture_file, "r")) == NULL) {
texture_file[0]='.';
texture_file[1]='\0';
strcat(texture_file, "/pixmaps");
if ( Comp == Primary) {
strcat(texture_file, "/starp_256.jpg");
} else if ( Comp == Secondary ) {
strcat(texture_file, "/stars_256.jpg");
}
#ifdef HAVE_DISK
else {
strcat(texture_file, "/disk_256.jpg");
}
#endif
} else {
fclose(txtFile);
}
strncpy(TexPtr->TextFile, texture_file,
strlen(texture_file) + 1);
TexPtr->TextFile[MAX_CFG_INLINE] = '\0';
/* Set Texture type to default = IMAGE */
TexPtr->Type = IMAGE;
return(TRUE);
}
double maxtemp(SurfaceElement *surface, double num) {
double maxvalue=0;
SurfaceElement *ptr;
double i;
ptr=surface;
for (i=0;i<num;i++) {
if (ptr->temp > maxvalue) maxvalue = ptr->temp;
ptr++;
}
return(maxvalue);
}
double mintemp(SurfaceElement *surface, double num) {
double minvalue = 3.0e+38;
SurfaceElement *ptr;
double i;
ptr=surface;
for (i=0;i<num;i++) {
if (ptr->temp < minvalue) minvalue = ptr->temp;
ptr++;
}
return(minvalue);
}
double maxgrav(SurfaceElement *surface, double num) {
double maxvalue=0;
SurfaceElement *ptr;
double i;
ptr=surface;
for (i=0;i<num;i++) {
if (ptr->grav > maxvalue) maxvalue = ptr->grav;
ptr++;
}
return(maxvalue);
}
double mingrav(SurfaceElement *surface, double num) {
double minvalue = 3.0e+38;
SurfaceElement *ptr;
double i;
ptr=surface;
for (i=0;i<num;i++) {
if (ptr->grav < minvalue) minvalue = ptr->grav;
ptr++;
}
return(minvalue);
}
double maxflux(SurfaceElement *surface, double num, int Comp) {
double maxvalue=0;
SurfaceElement *ptr;
double i, flux;
ptr=surface;
for (i=0;i<num;i++) {
flux = (ptr->f_[0]/ ptr->area)
/* * ptr->visibility */
/* * (1.0 - Limb[Comp][0][0] * (1.0 - ptr->CosGamma)) */
;
if (flux > maxvalue)
maxvalue = flux;
ptr++;
}
return(maxvalue);
}
double minflux(SurfaceElement *surface, double num, int Comp) {
double minvalue = 3.0e38;
SurfaceElement *ptr;
double i, flux;
ptr=surface;
for (i=0;i<num;i++) {
flux = (ptr->f_[0]/ ptr->area)
/* * ptr->visibility */
* fabs(1.0 - Limb[Comp][0][0] /* * (1.0 - ptr->CosGamma) */);
if (flux < minvalue) {
minvalue = flux;
}
ptr++;
}
minvalue = minvalue * 0.9;
return(minvalue);
}
double maxvel(SurfaceElement *surface, double num) {
double maxvalue=0;
SurfaceElement *ptr;
double i;
ptr=surface;
for (i=0;i<num;i++) {
if (ptr->CosGamma > 0) {
if (ptr->Velocity > maxvalue)
maxvalue = ptr->Velocity;
}
ptr++;
}
return(maxvalue);
}
double minvel(SurfaceElement *surface, double num) {
double minvalue = 3.0e38;
SurfaceElement *ptr;
double i;
ptr=surface;
for (i=0;i<num;i++) {
if (ptr->CosGamma > 0) {
if (ptr->Velocity < minvalue)
minvalue = ptr->Velocity;
}
ptr++;
}
return(minvalue);
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 0.5
@short Generate a texture image from binary data, e.g. temperature
distribution
@param (SurfaceElement *) SurfPtr The data of the stellar component
@param (GLubyte *) textimage Pointer to the texture image
@param (int) datatype The type of the texture (LINEAR, COLORMODEL,
...)
@heading Open GL Animation
****************************************************************************/
void GLDatatoTexture(SurfaceElement *SurfPtr, GLubyte *textimage,
double num, int datatype, int Comp)
{
GLubyte *imgptr=NULL;
int intensity;
SurfaceElement *ptr;
double i, minval=3.0e+38,maxval=0x0, tscale, flux;
#if 0
double bscale;
double x=0,y=0,z=0;
double R=0,G=0,B=0;
struct GLColorSystem NTSC = {0.64, 0.33, 0.29, 0.60, 0.15, 0.06, CWP};
struct GLColorSystem *cs;
#endif
char * name;
if (Comp == Primary)
name = _("Primary");
else if (Comp == Secondary)
name = _("Secondary");
else
name = _("Disk");
/* pointer to the texture image memory */
imgptr = textimage;
switch (datatype) {
case TEMP:
minval = mintemp(SurfPtr, num);
maxval = maxtemp(SurfPtr, num);
/* linear scaling factor */
tscale = 256 / (maxval-minval);
if (Flags.debug[VERBOSE] == ON) {
printf(_("%s: Minimum temperature %8.1f Kelvin\n"), name, minval);
printf(_("%s: Maximum temperature %8.1f Kelvin\n"), name, maxval);
}
/* init linear grey-scale LUT */
ptr = SurfPtr;
for (i=0; i < num; i++) {
intensity = (ptr->temp-minval)*tscale;
/* assign R-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
/* assign G-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
/* assign B-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
ptr++;
}
break;
case GRAV:
minval = mingrav(SurfPtr, num);
maxval = maxgrav(SurfPtr, num);
/* linear scaling factor */
tscale = 256 / (maxval-minval);
if (Flags.debug[VERBOSE] == ON) {
printf(_("%s: Minimum surface gravitation %8.4g\n"), name, minval);
printf(_("%s: Maximum surface gravitation %8.4g\n"), name, maxval);
}
/* init linear grey-scale LUT */
ptr = SurfPtr;
for (i=0; i < num; i++) {
intensity = (ptr->grav-minval)*tscale;
/* assign R-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
/* assign G-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
/* assign B-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
ptr++;
}
break;
case FLUX:
maxval = log(maxflux(SurfPtr, num, Comp));
minval = log(minflux(SurfPtr, num, Comp));
/* linear scaling factor */
tscale = 256 / (maxval-minval);
if (Flags.debug[VERBOSE] == ON) {
printf(_("%s: Minimum flux %8.4g\n"), name, minval);
printf(_("%s: Maximum flux %8.4g\n"), name, maxval);
}
/* init linear grey-scale LUT */
ptr = SurfPtr;
for (i=0; i < num; i++) {
if (ptr->CosGamma > 0) {
flux = (ptr->f_[0]/ ptr->area) * ptr->visibility *
(1.0 - Limb[Comp][0][0]*(1.0 - ptr->CosGamma));
flux = (flux < minval) ? minval : flux;
} else {
flux = minval;
}
flux = log(flux);
intensity = (flux-minval)*tscale;
if (intensity > 255) intensity = 255;
else if (intensity < 0) intensity = 0;
/* assign R-value */
*imgptr = (GLubyte) intensity;
imgptr++;
/* assign G-value */
*imgptr = (GLubyte) intensity;
imgptr++;
/* assign B-value */
*imgptr = (GLubyte) intensity;
imgptr++;
ptr++;
}
break;
case VELOCITY:
minval = minvel(SurfPtr, num);
maxval = maxvel(SurfPtr, num);
/* linear scaling factor */
tscale = 255 / (maxval-minval);
if (Flags.debug[VERBOSE] == ON) {
printf(_("%s: Minimum velocity %8.4g\n"), name, minval);
printf(_("%s: Maximum velocity %8.4g\n"), name, maxval);
}
/* init linear grey-scale LUT */
ptr = SurfPtr;
for (i=0; i < num; i++) {
if (ptr->CosGamma > 0) {
flux = ptr->Velocity;
} else {
flux = minval;
}
intensity = (flux-minval)*tscale;
/* assign R-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
/* assign G-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
/* assign B-value */
*imgptr = (GLubyte) (intensity);
imgptr++;
ptr++;
}
break;
#if 0
case BBCOLOR:
ptr = SurfPtr;
cs = &NTSC;
for (i=0; i < num; i++) {
GLBBtoxyz(ptr->temp,&x,&y,&z);
//if (i == 0) printf("Temp %f: x %f y %f z %f \n",ptr->temp,x,y,z);
GLxyztoRGB(cs,x,y,z,&R,&G,&B);
//if (i == 0) printf(" R %f G %f B %f \n",R,G,B);
/* scale R,G,B to byte size */
R = R * 255;
B = B * 255;
G = G * 255;
/* scale brightness to maximum R.W. 23.12.2002 */
bscale = (B > R) ? B : R;
bscale = (G > bscale) ? G : bscale;
R = (255 / bscale) * R;
B = (255 / bscale) * B;
G = (255 / bscale) * G;
/* assign R-value */
*imgptr = (GLubyte) R;
imgptr++;
/* assign G-value */
*imgptr = (GLubyte) G;
imgptr++;
/* assign B-value */
*imgptr = (GLubyte) B;
imgptr++;
ptr++;
}
break;
#endif
default:
break;
}
/* save to global variables */
texture_minval[Comp] = minval;
texture_maxval[Comp] = maxval;
return;
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.1
@short Init texture images for the stars and the disk
@param (int) Comp The stellar component
@param (int) type The type of the texture (IMAGE, TEMP, ...)
@return (gint) status The exit status
@heading Open GL Animation
****************************************************************************/
int GLInitTexture(int Comp, int type)
{
GLubyte *textimage=NULL;
TextureType *TexPtr=NULL;
SurfaceElement *SurfPtr; /* pointer to surface elements */
BinaryComponent *BinPtr; /* pointer to binary */
double numpoints;
long n_phi; /* # of steps in phi */
long n_eta; /* # of steps in eta */
char ErrMsg[4096]; /* error message */
/* pointer to the texture image of the component */
TexPtr = &Texture[Comp];
/* pointer to first surface element */
SurfPtr = Surface[Comp];
/* pointer to the binary parameters */
BinPtr = &Binary[Comp];
n_eta = StepsPerPi;
n_phi = BinPtr->N_PhiStep[0];
/* be sure that texture does not already exist */
/* sould be done more carefully !!! TBD MK */
glDeleteTextures( 1, &TexPtr->TexName);
/* create a new texture for this component */
glGenTextures( 1, &TexPtr->TexName);
switch (type) {
case IMAGE:
/* use a jpeg coded image file as texture */
/* read the texture image from file */
textimage = ReadJPEGFile(TexPtr->TextFile, &TexPtr->Width, &TexPtr->Height,
&TexPtr->Components);
/* on error switch off texture for this component and return to caller */
if(!textimage) {
sprintf(ErrMsg,_("Could not read texture file %s "), TexPtr->TextFile);
WARNING (ErrMsg);
sprintf(ErrMsg,_("Texturing not enabled for component %d\n"),Comp);
WARNING (ErrMsg);
TexPtr->Type = NONE;
return(FALSE);
}
else {
if (Flags.debug[VERBOSE] == ON) {
printf(_("Reading Texture: %s: %d x %d %d component \n"),
TexPtr->TextFile,TexPtr->Width,
TexPtr->Height,TexPtr->Components);
}
TexPtr->Type = IMAGE;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
break;
case TEMP:
case GRAV:
case FLUX:
case VELOCITY:
/* build a texture image from physical data */
/* allocate memory for texture image */
if (Comp < Disk)
numpoints = n_eta * n_phi;
else
numpoints = BinPtr->NumElem;
textimage = (GLubyte *) malloc(numpoints * TEXTURE_COMPONENTS);
if (!textimage) {
sprintf(ErrMsg,_("Can't allocate memory for texture image buffer !\n"));
WARNING (ErrMsg);
return(FALSE);
}
GLDatatoTexture(SurfPtr, textimage, numpoints, type, Comp);
/*
TexPtr->Width = n_eta;
TexPtr->Height = n_phi;
*/
/* exchange width and height R.W. 23.12.2002 */
TexPtr->Width = n_phi;
if (Comp < Disk)
TexPtr->Height = n_eta;
else
TexPtr->Height = numpoints / n_phi;
TexPtr->Components = TEXTURE_COMPONENTS;
break;
default:
/* we failed to initialize texturing -> turn off texture */
TexPtr->Type = NONE;
return(FALSE);
break;
}
glBindTexture(GL_TEXTURE_2D, TexPtr->TexName);
/* repetitively wrap texture on object */
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
/* modulate colour of component with texture colour */
if (Flags.textype != BBCOLOR)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
/* replace colour of component with texture colour */
else
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
/* apply a linear approximation for texturing */
/* GL_LINEAR is bad, produces a stripe */
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
/* build texture map */
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, TexPtr->Width,
TexPtr->Height, GL_RGB, GL_UNSIGNED_BYTE,
textimage);
free(textimage);
return(TRUE);
}
/****************************************************************************
@package nightfall
@author Markus Kuster (kuster@astro.uni-tuebingen.de)
@version 1.0
@short Real-time animation of the binary system
@param (int) j The phase index
@return (void)
@heading Open GL Animation
****************************************************************************/
void AnimateGL(int j)
{
char top_title[MAX_CFG_INLINE+1]; /* window title string */
GtkWidget *GLvbox,*GLhbox,*GLLightvbox;
GtkWidget *GLmenu_bar;
GtkWidget *GL3dFrame;
DispInfo *DispInfoPtr;
static int noentry = 0;
static int glut_initialized = 0;
int attrlist[] = {
GDK_GL_RGBA,
GDK_GL_DEPTH_SIZE, 1,
GDK_GL_RED_SIZE, 1,
GDK_GL_GREEN_SIZE, 1,
GDK_GL_BLUE_SIZE, 1,
GDK_GL_DOUBLEBUFFER,
GDK_GL_NONE
};
int argc = 1;
char * argv = "nightfall";
if (noentry == 1)
return;
if (!glut_initialized)
{
glutInit(&argc, &argv);
glut_initialized = 1;
}
phaseind = j;
if (GLWindowHidden == ON) {
gtk_widget_show (glWindow);
GLWindowHidden = OFF;
}
if (GLWindowOpened == OFF) {
/* >>>>>>>>>>> Initialize Window <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
if (Flags.debug[VERBOSE] == ON) {
{ printf("\n"); printf(_("\n Initializing GLX Animation\n\n") );}
}
/* create new toplevel window */
glWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL);
/* set window title */
sprintf(top_title, "%10s %5s", PACKAGE, VERSION);
gtk_window_set_title(GTK_WINDOW(glWindow), top_title);
/* set window size */
gtk_widget_set_usize (glWindow, GLWIN_WIDTH, GLWIN_HEIGHT);
gtk_widget_realize(glWindow);
gtk_quit_add_destroy(1, GTK_OBJECT(glWindow));
/* ----------- connect the exit handler ------------------------------ */
gtk_signal_connect (GTK_OBJECT (glWindow), "delete_event",
GTK_SIGNAL_FUNC (GLDelete), NULL);
gtk_widget_show(GTK_WIDGET(glWindow));
/* new vertical box for menu and GLArea */
GLvbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (glWindow), GLvbox);
gtk_widget_show(GLvbox);
/* >>>>>>>>>>> the menu bar <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */
GLmenu_bar = gtk_menu_bar_new();
GLMakeMenu(GLmenu_bar);
gtk_box_pack_start (GTK_BOX (GLvbox), GLmenu_bar, FALSE, FALSE, 0);
/* new horizontal box for scene and plot area */
GLhbox = gtk_hbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (GLvbox), GLhbox);
gtk_widget_show(GLhbox);
/* ---------------- 3D System Window --------------------------------- */
/* frame for 3d scene */
GL3dFrame = gtk_frame_new (_("Binary System") );
gtk_container_add (GTK_CONTAINER (GLhbox), GL3dFrame);
gtk_container_set_border_width(GTK_CONTAINER(GL3dFrame), 2);
gtk_widget_show (GL3dFrame);
/* create new OpenGL scene area */
glArea = gtk_gl_area_new(attrlist);
if (NULL == glArea)
{
char command[256];
noentry = 1;
if (0 == system("which xmessage > /dev/null"))
{
sprintf(command,
_("xmessage \"ERROR: OpenGL not working\" "));
system(command);
}
GLDelete(NULL, NULL);
return;
}
gtk_widget_show(glArea);
/* set event mask for widget */
gtk_widget_set_events(glArea,
GDK_EXPOSURE_MASK|
GDK_BUTTON_PRESS_MASK|
GDK_BUTTON_RELEASE_MASK|
GDK_KEY_PRESS_MASK|
GDK_KEY_RELEASE_MASK|
GDK_POINTER_MOTION_MASK|
GDK_POINTER_MOTION_HINT_MASK);
gtk_gl_area_size(GTK_GL_AREA(glArea), GLAREA_WIDTH, GLAREA_HEIGHT);
/* do initialization when widget has been realized */
gtk_signal_connect(GTK_OBJECT(glArea), "realize",
GTK_SIGNAL_FUNC(GLInit3d), NULL);
gtk_signal_connect(GTK_OBJECT(glArea), "button_press_event",
GTK_SIGNAL_FUNC(GLButtonPress), NULL);
/* redraw image when exposed */
gtk_signal_connect(GTK_OBJECT(glArea), "expose_event",
GTK_SIGNAL_FUNC(GLDisplayAll), NULL);
/* rotate and translate objects on mouse movement */
gtk_signal_connect (GTK_OBJECT(glArea), "motion_notify_event",
GTK_SIGNAL_FUNC(GLMotionNotify), NULL);
/* capture keypress events */
gtk_signal_connect(GTK_OBJECT(glArea), "key_press_event",
GTK_SIGNAL_FUNC(GLKeyboard), NULL);
/* when window is resized viewport needs to be resized, too */
gtk_signal_connect(GTK_OBJECT(glArea), "configure_event",
GTK_SIGNAL_FUNC(GLReshape), NULL);
/* initialize display info structure */
DispInfoPtr = (DispInfo*)g_malloc(sizeof(DispInfo));
DispInfoPtr->mousex = 0;
DispInfoPtr->mousey = 0;
DispInfoPtr->xpos = 0;
DispInfoPtr->zoom = 1.;
/* init trackball */
trackball(DispInfoPtr->quat , 0.0, 0.0, 0.0, 0.0);
/* Add DispInfo to glArea object */
gtk_object_set_data(GTK_OBJECT(glArea), "DispInfo", DispInfoPtr);
/* add glArea to frame
*/
gtk_container_add (GTK_CONTAINER(GL3dFrame), glArea);
/* set event mask for widget */
/* enable focus for glarea widget */
GTK_WIDGET_SET_FLAGS(glArea, GTK_CAN_FOCUS);
gtk_widget_grab_focus(glArea);
/* ------------------------------------------------------------------- */
/* new vertical box for lightcurve and radial vel. plot */
GLLightvbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (GLhbox), GLLightvbox);
gtk_widget_show(GLLightvbox);
glutInitDisplayMode(GLUT_DEPTH);
/* Render all Viewports */
GLDisplayAll();
/* Set window status to open */
GLWindowOpened = ON;
}
else
{
/* update all geometries */
GLUpdateAll();
/* update texture if active and new animation run R.W. 23.12.2002 */
if (j == 0 && Flags.texture == ON && Flags.textype != IMAGE)
{
GLInitTexture(Primary, Flags.textype);
GLInitTexture(Secondary, Flags.textype);
#ifdef HAVE_DISK
GLInitTexture(Disk, Flags.textype);
#endif
}
else if (Flags.texture == ON &&
(Flags.textype == FLUX || Flags.textype == VELOCITY))
{
GLInitTexture(Primary, Flags.textype);
GLInitTexture(Secondary, Flags.textype);
#ifdef HAVE_DISK
GLInitTexture(Disk, Flags.textype);
#endif
}
/* Render all Viewports */
GLDisplayAll();
}
/* write animation frames */
if (Flags.movie == ON) {
strcpy(movfile,"");
sprintf(movfile,"frame%.3d.jpg",Flags.frame);
/* grab 3D Viewport only and save as max. quality jpeg file */
GLGrabScreen(movfile,0,0,VP_3D_WIDTH,VP_3D_HEIGHT,100);
/* increase frame number */
Flags.frame++;
}
return;
}
#endif /* OpenGL end */
syntax highlighted by Code2HTML, v. 0.9.1