http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / glx / glplanet.c
index 39ae21bb05cb8e23f709b83e00250790afc6655a..0685386f3710d20f72520485f04cac0082178da5 100644 (file)
@@ -1,12 +1,6 @@
 /* -*- Mode: C; tab-width: 4 -*- */
-/* glplanet --- 3D rotating planet, e.g., Earth. */
-
-#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)plate.c      4.07 97/11/24 xlockmore";
-
-#endif
-
-/*-
+/* glplanet --- 3D rotating planet, e.g., Earth.
+ *
  * Permission to use, copy, modify, and distribute this software and its
  * documentation for any purpose and without fee is hereby granted,
  * provided that the above copyright notice appear in all copies and that
@@ -20,6 +14,10 @@ static const char sccsid[] = "@(#)plate.c    4.07 97/11/24 xlockmore";
  * other special, indirect and consequential damages.
  *
  * Revision History:
+ *
+ * 16-Jan-02: jwz@jwz.org   gdk_pixbuf support.
+ * 21-Mar-01: jwz@jwz.org   Broke sphere routine out into its own file.
+ *
  * 9-Oct-98:  dek@cgl.ucsf.edu  Added stars.
  *
  * 8-Oct-98:  jwz@jwz.org   Made the 512x512x1 xearth image be built in.
@@ -32,18 +30,8 @@ static const char sccsid[] = "@(#)plate.c    4.07 97/11/24 xlockmore";
  * BUGS:
  * -bounce is broken
  * 
- *   For even more spectacular results, grab the images from the "SSysten"
- *   package (http://www.msu.edu/user/kamelkev/) and do this:
- *
- *     cd ssystem-1.4/hires/
- *     foreach f ( *.jpg )
- *       djpeg $f | ppmquant 254 | ppmtoxpm > /tmp/$f:r.xpm
- *     end
- *
- *     cd /tmp
- *     foreach f ( *.xpm )
- *       glplanet -image $f
- *     end
+ *   For even more spectacular results, grab the images from the "SSystem"
+ *   package (http://www.msu.edu/user/kamelkev/) and use its JPEGs!
  */
 
 
@@ -58,8 +46,10 @@ static const char sccsid[] = "@(#)plate.c    4.07 97/11/24 xlockmore";
 # define PROGCLASS                                             "Planet"
 # define HACK_INIT                                             init_planet
 # define HACK_DRAW                                             draw_planet
+# define HACK_RESHAPE                                  reshape_planet
 # define planet_opts                                   xlockmore_opts
 #define DEFAULTS       "*delay:                        15000   \n"     \
+                                       "*showFPS:                      False   \n" \
                     "*rotate:           True    \n" \
                     "*roll:             True    \n" \
                     "*bounce:           True    \n" \
@@ -78,12 +68,7 @@ static const char sccsid[] = "@(#)plate.c    4.07 97/11/24 xlockmore";
 
 #ifdef USE_GL /* whole file */
 
-#ifdef HAVE_XPM
-# include <X11/xpm.h>
-# ifndef PIXEL_ALREADY_TYPEDEFED
-#  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
-# endif
-#endif
+#include "sphere.h"
 
 #ifdef HAVE_XMU
 # ifndef VMS
@@ -161,8 +146,8 @@ ModStruct   planet_description =
  */
 
 #define NUM_STARS 1000
-#define SLICES 15
-#define STACKS 15
+#define SLICES 32
+#define STACKS 32
 
 /* radius of the sphere- fairly arbitrary */
 #define RADIUS 4
@@ -237,8 +222,10 @@ setup_xbm_texture (char *bits, int width, int height,
                *out++ = (word & 0x0000FF);
          }
 
+  clear_gl_error();
   glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0,
                           GL_RGB, GL_UNSIGNED_BYTE, data);
+  check_gl_error("texture");
 
   /* setup parameters for texturing */
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@@ -255,86 +242,25 @@ setup_file_texture (ModeInfo *mi, char *filename)
 {
   Display *dpy = mi->dpy;
   Visual *visual = mi->xgwa.visual;
+
   Colormap cmap = mi->xgwa.colormap;
+  XImage *image = xpm_file_to_ximage (dpy, visual, cmap, filename);
 
-#ifdef HAVE_XPM
-  {
-       char **xpm_data = 0;
-       int result = XpmReadFileToData (filename, &xpm_data);
-       switch (result) {
-       case XpmSuccess:
-         {
-               XImage *image = xpm_to_ximage (dpy, visual, cmap, xpm_data);
-
-               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
-                                        image->width, image->height, 0,
-                                        GL_RGBA, GL_UNSIGNED_BYTE, image->data);
-
-               /* setup parameters for texturing */
-               glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-               glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
-
-               glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-               return;
-         }
-         break;
-
-       case XpmOpenFailed:
-         fprintf (stderr, "%s: file %s doesn't exist.\n", progname, filename);
-         exit (-1);
-         break;
-
-       case XpmFileInvalid:
-         /* Fall through and try it as an XBM. */
-         break;
-
-       case XpmNoMemory:
-         fprintf (stderr, "%s: XPM: out of memory\n", progname);
-         exit (-1);
-         break;
-
-       default:
-         fprintf (stderr, "%s: XPM: unknown error code %d\n", progname, result);
-         exit (-1);
-         break;
-       }
-  }
-#endif /* HAVE_XPM */
+  clear_gl_error();
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+               image->width, image->height, 0,
+               GL_RGBA, GL_UNSIGNED_BYTE, image->data);
+  check_gl_error("texture");
 
-#ifdef HAVE_XMU
-  {
-       planetstruct *gp = &planets[MI_SCREEN(mi)];
-       unsigned int width = 0;
-       unsigned int height = 0;
-       unsigned char *data = 0;
-       int xhot, yhot;
-       int status = XmuReadBitmapDataFromFile (filename, &width, &height, &data,
-                                                                                       &xhot, &yhot);
-       if (status != Success)
-         {
-# ifdef HAVE_XPM
-               fprintf (stderr, "%s: not an XPM file: %s\n", progname, filename);
-# endif
-               fprintf (stderr, "%s: not an XBM file: %s\n", progname, filename);
-               exit (1);
-         }
+  /* setup parameters for texturing */
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, image->width);
 
-       setup_xbm_texture ((char *) data, width, height, &gp->fg, &gp->bg);
-  }
-#else  /* !XMU */
-
-# ifdef HAVE_XPM
-  fprintf (stderr, "%s: not an XPM file: %s\n", progname, filename);
-# endif
-  fprintf (stderr, "%s: your vendor doesn't ship the standard Xmu library.\n",
-                  progname);
-  fprintf (stderr, "%s: we can't load XBM files without it.\n",progname);
-  exit (1);
-#endif /* !XMU */
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 }
 
 
@@ -372,6 +298,7 @@ setup_face(void)
 }
 
 
+#if 0
 /* Function for determining points on the surface of the sphere */
 static void inline ParametricSphere(float theta, float rho, GLfloat *vector)
 {
@@ -387,20 +314,19 @@ static void inline ParametricSphere(float theta, float rho, GLfloat *vector)
 
        return;
 }
+#endif
 
 
 /* lame way to generate some random stars */
 void generate_stars(int width, int height)
 {
-  int i;
-/*  GLfloat size_range[2], size;*/
-  GLfloat x, y;
+  int i, j;
+  int max_size = 3;
+  GLfloat inc = 0.5;
+  int steps = max_size / inc;
 
   planetstruct *gp = &planets[MI_SCREEN(mi)];
   
-/*    glGetFloatv(GL_POINT_SIZE_RANGE, size_range); */
-  
-/*    printf("size range: %f\t%f\n", size_range[0], size_range[1]); */
   gp->starlist = glGenLists(1);
   glNewList(gp->starlist, GL_COMPILE);
 
@@ -415,20 +341,27 @@ void generate_stars(int width, int height)
 
   /* disable depth testing for the stars, so they don't obscure the planet */
   glDisable(GL_DEPTH_TEST);
-  glEnable(GL_POINT_SMOOTH);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
-  glBegin(GL_POINTS);
-  for(i = 0 ; i < NUM_STARS ; i++)
-       {
-/*       size = (drand48()+size_range[0]) * size_range[1]/2.; */
-/*    glPointSize(size); */
-         x = drand48()*width;
-         y = drand48()*height;
-         glVertex2f(x,y);
-       }
-  glEnd();
+  glColor3f(1,1,1);
+
+  glEnable(GL_POINT_SMOOTH);
+
+  for (j = 1; j <= steps; j++)
+    {
+      glPointSize(inc * j);
+      glBegin(GL_POINTS);
+      for(i = 0 ; i < NUM_STARS / steps; i++)
+        {
+          glColor3f (0.6 + frand(0.3),
+                     0.6 + frand(0.3),
+                     0.6 + frand(0.3));
+          glVertex2f ((GLfloat) (random() % width),
+                      (GLfloat) (random() % height));
+        }
+      glEnd();
+    }
 
   /* return to original PROJECT and MODELVIEW */
   glMatrixMode(GL_PROJECTION);
@@ -440,20 +373,26 @@ void generate_stars(int width, int height)
 
 }
 
+/* Set up lighting */
+static void
+init_sun (ModeInfo * mi)
+{
+  GLfloat light[4];
+  light[0] = frand(2.0) - 1.0;
+  light[1] = frand(2.0) - 1.0;
+  light[2] = 1.0;
+  light[3] = 0;
+
+  glLightfv(GL_LIGHT0, GL_POSITION, light);
+}
+
+
 /* Initialization function for screen saver */
 static void
 pinit(ModeInfo * mi)
 {
   Bool wire = MI_IS_WIREFRAME(mi);
   planetstruct *gp = &planets[MI_SCREEN(mi)];
-  int i, j;
-  int stacks=STACKS, slices=SLICES;
-  float radius=RADIUS;
-
-  float drho, dtheta;
-  float rho, theta;
-  GLfloat vector[3];
-  GLfloat ds, dt, t, s;;
 
   if (wire) {
        glEnable(GL_LINE_SMOOTH);
@@ -473,72 +412,16 @@ pinit(ModeInfo * mi)
        generate_stars(MI_WIDTH(mi), MI_HEIGHT(mi));
   }
 
-
-  /*-
-   * Generate a sphere with quadrilaterals.
-   * Quad vertices are determined using a parametric sphere function.
-   * For fun, you could generate practically any parameteric surface and
-   * map an image onto it. 
-   */
-
-  drho = M_PI / stacks;
-  dtheta = 2.0 * M_PI / slices;
-  ds = 1.0 / slices;
-  dt = 1.0 / stacks;
-  
-
   gp->platelist=glGenLists(1);
   glNewList(gp->platelist, GL_COMPILE);
-
-  glColor3f(1,1,1);
-  glBegin( wire ? GL_LINE_LOOP : GL_QUADS );
-
-  t = 0.0;
-  for(i=0; i<stacks; i++) {
-       rho = i * drho;
-       s = 0.0;
-       for(j=0; j<slices; j++) {
-         theta = j * dtheta;
-
-
-         glTexCoord2f(s,t);
-         ParametricSphere(theta, rho, vector);
-         normalize(vector);
-         glNormal3fv(vector);
-         ParametricSphere(theta, rho, vector);
-         glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
-
-         glTexCoord2f(s,t+dt);
-         ParametricSphere(theta, rho+drho, vector);
-         normalize(vector);
-         glNormal3fv(vector);
-         ParametricSphere(theta, rho+drho, vector);
-         glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
-
-         glTexCoord2f(s+ds,t+dt);
-         ParametricSphere(theta + dtheta, rho+drho, vector);
-         normalize(vector);
-         glNormal3fv(vector);
-         ParametricSphere(theta + dtheta, rho+drho, vector);
-         glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
-
-         glTexCoord2f(s+ds, t);
-         ParametricSphere(theta + dtheta, rho, vector);
-         normalize(vector);
-         glNormal3fv(vector);
-         ParametricSphere(theta + dtheta, rho, vector);
-         glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
-
-         s = s + ds;
-
-       }
-       t = t + dt;
-  }
-  glEnd();
+  glPushMatrix ();
+  glScalef (RADIUS, RADIUS, RADIUS);
+  unit_sphere (STACKS, SLICES, wire);
+  glPopMatrix ();
   glEndList();
 
-
- }
+  init_sun (mi);
+}
 
 static void
 draw_sphere(ModeInfo * mi)
@@ -614,52 +497,31 @@ rotate_and_move (ModeInfo * mi)
 
   if (do_bounce)
        {
-         /* Move in the direction we had been moving in. */
-         gp->xpos += gp->dx;
-         gp->ypos += gp->dy;
-         gp->zpos += gp->dz;
-
-         /* Bounce. */
-         if (gp->xpos > gp->box_depth)
-               gp->xpos = gp->box_depth, gp->dx = -gp->dx;
-         else if (gp->xpos < 0)
-               gp->xpos = 0, gp->dx = -gp->dx;
-
-         if (gp->ypos > gp->box_width/2)
-               gp->ypos = gp->box_width/2, gp->dy = -gp->dy;
-         else if (gp->ypos < -gp->box_width/2)
-               gp->ypos = -gp->box_width/2, gp->dy = -gp->dy;
-
-         if (gp->zpos > gp->box_height/2)
-               gp->zpos = gp->box_height/2, gp->dz = -gp->dz;
-         else if (gp->zpos < -gp->box_height/2)
-               gp->zpos = -gp->box_height/2, gp->dz = -gp->dz;
+      static int frame = 0;
+#     define SINOID(SCALE,SIZE) \
+        ((((1 + sin((frame * (SCALE)) / 2 * M_PI)) / 2.0) * (SIZE)) - (SIZE)/2)
+      gp->xpos = SINOID(0.031, gp->box_width);
+      gp->ypos = SINOID(0.023, gp->box_height);
+      gp->zpos = SINOID(0.017, gp->box_depth);
+      frame++;
        }
 }
 
 
 /* Standard reshape function */
-static void
-reshape(int width, int height)
+void
+reshape_planet(ModeInfo *mi, int width, int height)
 {
-  GLfloat light[4];
   GLfloat h = (GLfloat) height / (GLfloat) width;
 
-  light[0] = -1;
-  light[1] = (int) (((random() % 3) & 0xFF) - 1);
-  light[2] = (int) (((random() % 3) & 0xFF) - 1);
-  light[3] = 0;
-
   glViewport(0, 0, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -h, h, 5.0, 100.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  glTranslatef(0.0, 0.0, -DIST);
-  glLightfv(GL_LIGHT0, GL_POSITION, light);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
+  glTranslatef(0.0, 0.0, -DIST);
 }
 
 
@@ -711,7 +573,7 @@ init_planet(ModeInfo * mi)
 
   gp->window = MI_WINDOW(mi);
   if ((gp->glx_context = init_GL(mi)) != NULL) {
-       reshape(MI_WIDTH(mi), MI_HEIGHT(mi));
+       reshape_planet(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
        pinit(mi);
   } else {
        MI_CLEARWINDOW(mi);
@@ -737,15 +599,8 @@ draw_planet(ModeInfo * mi)
   if (do_stars) {
        /* protect our modelview matrix and attributes */
        glPushMatrix();
-       glPushAttrib(GL_ALL_ATTRIB_BITS);
-       {
-         glColor3f(1,1,1);
-         /* draw the star field. */
-         glCallList(gp->starlist);
-
-       }
+    glCallList(gp->starlist);
        glPopMatrix();
-       glPopAttrib();
   }
 
   /* protect our modelview matrix and attributes */
@@ -768,6 +623,7 @@ draw_planet(ModeInfo * mi)
 
 
 
+  if (mi->fps_p) do_fps (mi);
   glFinish();
   glXSwapBuffers(display, window);