home *** CD-ROM | disk | FTP | other *** search
- /* xsolar_opengl.c
- * Displays a planet with a moon, orbiting a sun.
- * Uses X and Open GL widget.
- *
- * Exit with the ESCape key or through the window manager menu.
- */
- #include <Xm/Xm.h>
- #include <Xm/Frame.h>
- #include <Xm/Form.h>
- #include <X11/StringDefs.h>
- #include <X11/keysym.h>
-
- #include <GL/GLwMDrawA.h>
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glx.h>
- #include <stdio.h>
- #include <math.h>
-
- typedef struct _spin {
- GLfloat year;
- } SPINDATA, *SPINPTR;
-
- /* function prototypes */
-
- void main(int argc, char **argv);
-
- void initCB (Widget w, XtPointer client_data, XtPointer call_data);
- void exposeCB (Widget w, XtPointer spin, XtPointer call_data);
- void resizeCB (Widget w, XtPointer spin, XtPointer call_data);
- void inputCB (Widget w, XtPointer client_data, XtPointer call_data);
-
- GLboolean drawWP (XtPointer spin);
-
- void drawscene(SPINPTR spin);
- void setbeachball(int stripes);
- void beachball(unsigned long color1, unsigned long color2);
-
- SPINPTR spin;
-
- static XtAppContext app_context;
- static XtWorkProcId workprocid = NULL;
-
- GLXContext glx_context;
- Display *global_display;
- Window global_window;
-
- /* Create application context, and a form widget to contain
- * the Open GL widget. Set up the Open GL widget callbacks
- */
- void main(int argc, char **argv)
- {
- Arg wargs[15];
- int n;
- Widget glw, toplevel, frame, form;
-
- static String fallback_resources[] = {
- "*frame*shadowType: SHADOW_IN",
- "*glwidget*width: 750",
- "*glwidget*height: 600",
- "*glwidget*rgba: TRUE",
- "*glwidget*doublebuffer: TRUE",
- "*glwidget*allocateBackground: TRUE",
- NULL
- };
-
- /* create main data structure, spin pointer */
- spin = (SPINPTR) malloc (sizeof (SPINDATA));
- spin->year = 0.0;
-
- toplevel = XtAppInitialize(
- &app_context, /* Application context */
- "XSolar", /* Application class */
- NULL, 0, /* command line option list */
- &argc, argv, /* command line args */
- fallback_resources,
- NULL, /* argument list */
- 0); /* number of arguments */
-
- n = 0;
- form = XmCreateForm(toplevel, "form", wargs, n);
- XtManageChild(form);
-
- n = 0;
- XtSetArg(wargs[n], XtNx, 30); n++;
- XtSetArg(wargs[n], XtNy, 30); n++;
- XtSetArg(wargs[n], XmNbottomAttachment, XmATTACH_FORM); n++;
- XtSetArg(wargs[n], XmNleftAttachment, XmATTACH_FORM); n++;
- XtSetArg(wargs[n], XmNrightAttachment, XmATTACH_FORM); n++;
- XtSetArg(wargs[n], XmNtopAttachment, XmATTACH_FORM); n++;
-
- XtSetArg(wargs[n], XmNleftOffset, 30); n++;
- XtSetArg(wargs[n], XmNbottomOffset, 30); n++;
- XtSetArg(wargs[n], XmNrightOffset, 30); n++;
- XtSetArg(wargs[n], XmNtopOffset, 30); n++;
- frame = XmCreateFrame (form, "frame", wargs, n);
- XtManageChild (frame);
-
- n = 0;
- glw = GLwCreateMDrawingArea(frame, "glwidget", wargs, n);
- XtManageChild (glw);
- XtAddCallback(glw, GLwNginitCallback, initCB,
- (XtPointer) NULL);
- XtAddCallback(glw, GLwNexposeCallback, exposeCB,
- (XtPointer) spin);
- XtAddCallback(glw, GLwNresizeCallback, resizeCB,
- (XtPointer) spin);
- XtAddCallback(glw, GLwNinputCallback, inputCB,
- (XtPointer) NULL);
-
- XtRealizeWidget(toplevel); /* instantiate it now */
- XtAppMainLoop(app_context); /* loop for events */
- } /* end main() */
-
- /* initCB
- * The initCB subroutine initializes graphics modes and
- * transformation matrices.
- */
-
- void initCB (Widget w, XtPointer client_data, XtPointer call_data)
- {
- Arg args[1];
- XVisualInfo *vi;
-
- XtSetArg(args[0], GLwNvisualInfo, &vi);
- XtGetValues(w, args, 1);
-
- global_display = XtDisplay(w);
- global_window = XtWindow(w);
- glx_context = glXCreateContext(global_display, vi, 0, GL_FALSE);
- } /* end initCB() */
-
- /* exposeCB() and resizeCB() are called when the window
- * is uncovered, moved, or resized.
- */
-
- void exposeCB (Widget w, XtPointer ptr, XtPointer call_data)
- {
- SPINPTR spin = (SPINPTR) ptr;
- static int first_time = 1;
- GLwDrawingAreaCallbackStruct *call_ptr =
- (GLwDrawingAreaCallbackStruct *) call_data;
-
- GLwDrawingAreaMakeCurrent(w, glx_context);
-
- if (first_time) {
- glClearColor(0.0, 0.0, 0.0, 0.0);
-
- glShadeModel(GL_FLAT);
- glEnable(GL_DEPTH_TEST);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(45.0, (GLfloat)(call_ptr->width)
- /(GLfloat)(call_ptr->height), 1.0, 25.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.0, 0.0, -12.0);
-
- workprocid = XtAppAddWorkProc
- (app_context, drawWP, spin); /* ptr is spin */
- first_time = 0;
- }
- drawscene(spin);
- }
-
- void resizeCB (Widget w, XtPointer ptr, XtPointer call_data)
- {
- SPINPTR spin = (SPINPTR) ptr;
- GLwDrawingAreaCallbackStruct *call_ptr =
- (GLwDrawingAreaCallbackStruct *) call_data;
-
- GLwDrawingAreaMakeCurrent(w, glx_context);
-
- glViewport(0, 0, (GLsizei) (call_ptr->width-1),
- (GLsizei) (call_ptr->height-1));
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(45.0, (GLfloat)(call_ptr->width)
- /(GLfloat)(call_ptr->height), 1.0, 25.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity ();
- glTranslatef(0.0, 0.0, -12.0);
-
- drawscene(spin);
- }
-
- /* inputCB() handles all types of input from the GL widget.
- * The KeyRelease handles the ESCape key, so that it exits
- * the program.
- */
- void inputCB (Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- char buffer[1];
- KeySym keysym;
- GLwDrawingAreaCallbackStruct *call_ptr =
- (GLwDrawingAreaCallbackStruct *) call_data;
- XKeyEvent *kevent = (XKeyEvent *) (call_ptr->event);
-
- GLwDrawingAreaMakeCurrent(w, glx_context);
-
- switch(call_ptr->event->type) {
- case KeyRelease:
- /* It is necessary to convert the keycode to a
- * keysym before checking if it is an escape */
- if (XLookupString(kevent,buffer,1,&keysym,NULL) == 1
- && keysym == (KeySym)XK_Escape)
- exit(0);
- break;
- default:
- break;
- }
- }
-
- /* drawWP() is called by the WorkProc. When the scene
- * is in automatic motion, the WorkProc calls this routine,
- * which adds 1 degree (10 tenths) to the cumulative amount
- * of rotation. drawscene() is called, so the image is
- * redrawn. It returns(FALSE) so the WorkProc does not
- * discontinue operation.
- */
- GLboolean drawWP (XtPointer ptr)
- {
- SPINPTR spin;
-
- spin = (SPINPTR) ptr;
- spin->year = fmodf((spin->year + 1.0), 360.0);
- drawscene (spin);
- return (FALSE);
- }
-
-
- /* drawscene calculates angles relative to the spin->year
- * and then draws sun, planet, and moon.
- */
-
- void drawscene(SPINPTR spin)
- {
- static GLfloat bluecol[] = { 0, 0, 1.0 };
- static GLfloat whitecol[] = { 1.0, 1.0, 1.0 };
- GLfloat sunangle, dayangle, monthangle;
- /* actual 1.5e8 kM * 3.0e-9 fudgefactor */
- GLfloat earthdist = 4.5, earthscale = 0.5;
- GLfloat moondist = 0.9, moonscale = 0.2;
-
- glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
-
- glPushMatrix();
- glRotatef(10.0, 1.0, 0.0, 0.0); /* tilt scene slightly */
- glPushMatrix();
- sunangle = fmodf((spin->year*365.0/25.0), 360.0);
- /* sun rotates on axis every 25 days */
- glRotatef(sunangle, 0.0, 1.0, 0.0);
- /* cpack format color1, color2 swapped by hand */
- /* was beachball(0x20C0FF, 0x200FFFF); */
- beachball(0xFFC02000, 0xFFFF0020);
- glPopMatrix();
- glPushMatrix();
- glRotatef(spin->year, 0.0, 1.0, 0.0);
- glTranslatef(earthdist, 0.0, 0.0);
- glPushMatrix();
- dayangle = fmodf((spin->year*5.0), 360.0);
- /* dayangle fudged so earth rotation shows */
- glRotatef(dayangle, 0.0, 1.0, 0.0);
- glScalef(earthscale, earthscale, earthscale);
- glColor3fv(bluecol);
- /* swapped; was beachball(0xFF0000, 0xC02000);*/
- beachball(0x0000FF00, 0x0020C000); /* earth */
- glPopMatrix();
- monthangle = fmodf((spin->year*365.0/28.0), 360.0);
- glRotatef(monthangle, 0.0, 1.0, 0.0);
- glTranslatef(moondist, 0.0, 0.0);
- glScalef(moonscale, moonscale, moonscale);
- glColor3fv(whitecol);
- /* hand swapped; was beachball(0xFFFFFF, 0xC0C0C0); */
- beachball(0xFFFFFF00, 0xC0C0C000); /* moon */
- glPopMatrix();
- glPopMatrix();
-
- glXSwapBuffers(global_display, global_window);
- } /* end drawscene() */
-
- /* BEACHBALL */
-
- /* three dimensional vector */
- typedef float vector[3];
-
- static vector front = { 0.0, 0.0, 1.0 };
- static vector back = { 0.0, 0.0, -1.0 };
- static vector top = { 0.0, 1.0, 0.0 };
- static vector bottom = { 0.0, -1.0, 0.0 };
- static vector right = { 1.0, 0.0, 0.0 };
- static vector left = { -1.0, 0.0, 0.0 };
- static vector center = { 0.0, 0.0, 0.0 };
-
- /* Number of colored stripes. Should be even to look right */
- #define BEACHBALL_STRIPES 12
-
- /* Default number of polygons making up a stripe. Should be even */
- #define BEACHBALL_POLYS 16
-
- /* array of vertices making up a stripe */
- static vector stripe_point[BEACHBALL_POLYS + 3];
-
- /* has the beachball been initialized */
- static GLboolean beachball_initialized = FALSE;
-
- /* Number of polygons making up a stripe */
- static int beachball_stripes;
-
- /* Number of vertices making up a stripe */
- static int stripe_vertices;
-
- /* Initialize beachball_point array to be a stripe
- * of unit radius.
- */
- void setbeachball(int stripes)
- {
- int i,j;
- float x,y,z; /* vertex points */
- float theta,delta_theta; /* angle from top pole to bottom pole */
- float offset; /* offset from center of stripe to vertex */
- float cross_radius; /* radius of cross section at current latitude */
- float cross_theta; /* angle occupied by a stripe */
-
- beachball_stripes = stripes;
-
- /* polys distributed by even angles from top to bottom */
- delta_theta = M_PI/((float)BEACHBALL_POLYS/2.0);
- theta = delta_theta;
-
- cross_theta = 2.0*M_PI/(float)beachball_stripes;
-
- j = 0;
-
- stripe_point[j][0] = top[0];
- stripe_point[j][1] = top[1];
- stripe_point[j][2] = top[2];
- j++;
-
- for (i = 0; i < BEACHBALL_POLYS; i += 2) {
- cross_radius = fsin(theta);
- offset = cross_radius * ftan(cross_theta/2.0);
-
- stripe_point[j][0] = - offset;
- stripe_point[j][1] = fcos(theta);
- stripe_point[j][2] = cross_radius;
- j++;
-
- stripe_point[j][0] = offset;
- stripe_point[j][1] = stripe_point[j-1][1];
- stripe_point[j][2] = stripe_point[j-1][2];
- j++;
-
- theta += delta_theta;
- }
-
- stripe_point[j][0] = bottom[0];
- stripe_point[j][1] = bottom[1];
- stripe_point[j][2] = bottom[2];
-
- stripe_vertices = j + 1;
-
- beachball_initialized = TRUE;
- }
-
- /*
- * Draws a canonical beachball. The colors are cpack values.
- */
- void beachball(unsigned long c1, unsigned long c2)
- {
- GLfloat angle, delta_angle;
- int i,j;
-
- if (! beachball_initialized)
- setbeachball(BEACHBALL_STRIPES);
-
- angle = 0.0;
- delta_angle = 360.0/(float)beachball_stripes;
-
- for (i = 0; i < beachball_stripes; i++) {
- if ( i%2 == 0)
- glColor4ubv((GLubyte *)(&c1));
- else glColor4ubv((GLubyte *)(&c2));
-
- glPushMatrix();
- glRotatef(angle, 0.0, 1.0, 0.0);
-
- angle += delta_angle;
-
- glBegin(GL_TRIANGLE_STRIP);
- for (j = 0; j < stripe_vertices; j++)
- glVertex3fv(stripe_point[j]);
- glEnd();
- glPopMatrix();
- }
- }
-
-