http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / glx / providence.c
index bd307b99a1cb37a8fb6aab9f82851ac3ae230469..3ecf88c4e3f0a7119e935d3389a173ff266ff89d 100644 (file)
  * Copyright 2004 Blair Tennessy
  */
 
-#include <X11/Intrinsic.h>
-
 #ifdef STANDALONE
-#define PROGCLASS          "Providence"
-#define HACK_INIT          init_providence
-#define HACK_DRAW          draw_providence
-#define HACK_RESHAPE       reshape_providence
-#define HACK_HANDLE_EVENT   providence_handle_event
-#define EVENT_MASK         PointerMotionMask
-#define providence_opts            xlockmore_opts
 #define DEFAULTS           "*delay:   20000   \n" \
                            "*showFPS: False   \n" \
                            "*wireframe: False \n"
 
+# define refresh_providence 0
 #include "xlockmore.h"
 #else
 #include "xlock.h"
 #endif
 
-#include <GL/glu.h>
 #include "gltrackball.h"
 
 #define DEF_SOLIDPROVIDENCE  "False"
@@ -54,7 +45,7 @@ static OptionStruct desc[] = {
   {"-/+eye", "turn on/off eye of providence"}
 };
 
-ModeSpecOpt providence_opts = {
+ENTRYPOINT ModeSpecOpt providence_opts = {
   sizeof opts / sizeof opts[0], opts, 
   sizeof vars / sizeof vars[0], vars, desc
 };
@@ -77,73 +68,91 @@ ModStruct   providence_description = {
 #define Pi M_PI
 #endif
 
-int mono = 0, wire = 0;
-double camera_velocity = 0.0;
-double camera_z = -8.0;
-int camera_mode = 0;
+/* brick texture */
+#define checkImageWidth 64
+#define checkImageHeight 64
+
+#define EYE_PARTICLE_COUNT 2000
+
+#define LOOKUPSIZE 3600
+#define EYELENGTH 300
+
+#define EPSILON 0.0001
+#define PARTICLE_COUNT 2000
+#define FPS 50
+
 
 typedef struct {
   GLint       WindH, WindW;
   GLXContext *glx_context;
   trackball_state *trackball;
   Bool        button_down_p;
+  GLfloat position0[4];
+  GLubyte checkImage[checkImageWidth][checkImageHeight][3];
+  GLuint bricktexture;
+
+  int mono, wire;
+  double camera_velocity;
+  double camera_z;
+
+  int pyramidlist;
+  double currenttime;
+  double theta;
+  double theta_scale;
+
+  double particles[PARTICLE_COUNT][5];
+  int eyeparticles[EYE_PARTICLE_COUNT][2];
+  double lookup[LOOKUPSIZE][EYELENGTH][2];
+  double lookup2[LOOKUPSIZE][EYELENGTH][2];
+
 } providencestruct;
 
 /* lighting variables */
-GLfloat front_shininess[] = {60.0};
-GLfloat front_specular[] = {0.2, 0.2, 0.2, 1.0};
-GLfloat ambient[] = {0.8, 0.8, 0.8, 1.0};
-GLfloat ambient2[] = {0.25, 0.25, 0.25, 1.0};
-GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
-GLfloat position0[] = {1.0, 5.0, 1.0, 1.0};
-GLfloat position1[] = {-1.0, -5.0, 1.0, 1.0};
-GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
-GLfloat lmodel_twoside[] = {GL_TRUE};
+/*static const GLfloat front_shininess[] = {60.0};*/
+/*static const GLfloat front_specular[] = {0.2, 0.2, 0.2, 1.0};*/
+/*static const GLfloat ambient[] = {0.8, 0.8, 0.8, 1.0};*/
+static const GLfloat ambient2[] = {0.25, 0.25, 0.25, 1.0};
+static const GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0};
+static const GLfloat lmodel_ambient[] = {0.5, 0.5, 0.5, 1.0};
+static const GLfloat lmodel_twoside[] = {GL_TRUE};
 
 /* gray-gray */
 
-GLfloat MaterialGlory[] = {0.04, 0.30, 0.22, 0.7};
-GLfloat MaterialGloryB[] = {0.07, 0.50, 0.36, 0.6};
-
-GLfloat MaterialGloryF[] = {0.07, 0.50, 0.36, 1.0};
-/* GLfloat MaterialGloryF[] = {0.06, 0.38, 0.27, 1.0}; */
-GLfloat MaterialGloryE[] = {0.06, 0.38, 0.27, 0.3};
-GLfloat MaterialGloryM[] = {0.5, 0.5, 0.5, 0.5};
-GLfloat MaterialGloryMB[] = {0.36, 0.36, 0.36, 0.4};
-GLfloat MaterialGreenback[4] = {0.04, 0.30, 0.22, 1.0};
-GLfloat MaterialBlack[4] = {0.0, 0.0, 0.0, 1.0};
+static const GLfloat MaterialGlory[] = {0.04, 0.30, 0.22, 0.7};
+static const GLfloat MaterialGloryB[] = {0.07, 0.50, 0.36, 0.6};
 
-GLfloat MaterialGray5[] = {0.5, 0.5, 0.5, 1.0};
-GLfloat MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};
+static const GLfloat MaterialGloryF[] = {0.07, 0.50, 0.36, 1.0};
+/* static const GLfloat MaterialGloryF[] = {0.06, 0.38, 0.27, 1.0}; */
+/*static const GLfloat MaterialGloryE[] = {0.06, 0.38, 0.27, 0.3};*/
+static const GLfloat MaterialGloryM[] = {0.5, 0.5, 0.5, 0.5};
+static const GLfloat MaterialGloryMB[] = {0.36, 0.36, 0.36, 0.4};
+/*static const GLfloat MaterialGreenback[4] = {0.04, 0.30, 0.22, 1.0};*/
+/*static const GLfloat MaterialBlack[4] = {0.0, 0.0, 0.0, 1.0};*/
 
-double currenttime;
+static const GLfloat MaterialGray5[] = {0.5, 0.5, 0.5, 1.0};
+/*static const GLfloat MaterialGray6[] = {0.6, 0.6, 0.6, 1.0};*/
 
 static providencestruct *providence = (providencestruct *) NULL;
 
 #define NUM_SCENES      2
 
-/* brick texture */
-#define checkImageWidth 64
-#define checkImageHeight 64
-GLubyte checkImage[checkImageWidth][checkImageHeight][3];
-GLuint bricktexture;
-
 /* build brick texture */
-void make_brick(void) {
+static void make_brick(providencestruct *mp) 
+{
   int i, j, c;
 
   for (i = 0; i < checkImageWidth; i++) {
     for (j = 0; j < checkImageHeight; j++) {
       c = i % 16 == 15 ? 255 : (j + 48*(i / 16))%64 == 0 ? 255 : 
        102 + random() % 102;
-      checkImage[i][j][0] = (GLubyte) c;
-      checkImage[i][j][1] = (GLubyte) c;
-      checkImage[i][j][2] = (GLubyte) c;
+      mp->checkImage[i][j][0] = (GLubyte) c;
+      mp->checkImage[i][j][1] = (GLubyte) c;
+      mp->checkImage[i][j][2] = (GLubyte) c;
     }
   }
 
-  glGenTextures(1, &bricktexture);
-  glBindTexture(GL_TEXTURE_2D, bricktexture);
+  glGenTextures(1, &mp->bricktexture);
+  glBindTexture(GL_TEXTURE_2D, mp->bricktexture);
 
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
@@ -151,25 +160,14 @@ void make_brick(void) {
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
   glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, 
               checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 
-              &checkImage[0][0]);
+              &mp->checkImage[0][0]);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
-/* int min */
-int mini(int a, int b) { return a < b ? a : b; }
-
-/* eye particles */
-#define EYE_PARTICLE_COUNT 2000
-int eyeparticles[EYE_PARTICLE_COUNT][2];
-
-/* lookup table for the eye */
-#define LOOKUPSIZE 3600
-#define EYELENGTH 300
-double lookup[LOOKUPSIZE][EYELENGTH][2];
-double lookup2[LOOKUPSIZE][EYELENGTH][2];
 
 /* build eye lookup table */
-void build_eye(void) {
+static void build_eye(providencestruct *mp) 
+{
   int i, j;
   double x;
   double inc = 0.1 / EYELENGTH;
@@ -183,8 +181,8 @@ void build_eye(void) {
     x = 0.07;
 
     for(j = 0; j < EYELENGTH; ++j) {
-      lookup[i][j][0] = x*sr;
-      lookup[i][j][1] = x*cr;
+      mp->lookup[i][j][0] = x*sr;
+      mp->lookup[i][j][1] = x*cr;
       x += inc;
     }
   }
@@ -195,33 +193,31 @@ void build_eye(void) {
     
     for(j = 0; j < EYELENGTH; ++j) {
       if(i % 2) {
-       lookup2[i][j][0] = sin(y)/6.0 + i/36000.0 - 0.05;
-       lookup2[i][j][1] = i%4 ? y/12.0 - 0.05 : 1.2*Pi-y/12.0 + 0.05;
+       mp->lookup2[i][j][0] = sin(y)/6.0 + i/36000.0 - 0.05;
+       mp->lookup2[i][j][1] = i%4 ? y/12.0 - 0.05 : 1.2*Pi-y/12.0 + 0.05;
       }
       else {
-       lookup2[i][j][0] = i/36000.0 - 0.05;
-       lookup2[i][j][1] = y/9.0 - 0.05;
+       mp->lookup2[i][j][0] = i/36000.0 - 0.05;
+       mp->lookup2[i][j][1] = y/9.0 - 0.05;
       }
       y += inc2;
     }
   }
 }
 
-int pyramidlist;
-#define EPSILON 0.0001
 
-double min(double a, double b) {
+static double min(double a, double b) 
+{
   return a < b ? a : b;
 }
 
-double max(double a, double b) {
+static double max(double a, double b) 
+{
   return a > b ? a : b;
 }
 
-#define PARTICLE_COUNT 2000
-double particles[PARTICLE_COUNT][5];
-
-void init_particle(double particle[5]) {
+static void init_particle(providencestruct *mp, double particle[5]) 
+{
   /* position along glory */
   double p = (random() % 485410) / 100000.0;
 
@@ -243,60 +239,61 @@ void init_particle(double particle[5]) {
     particle[1] = d*sin(atan(2.0)) - 0.75;
   }
 
-  particle[3] = currenttime;
+  particle[3] = mp->currenttime;
   particle[4] = 1.25 + (random()%10)/10.0;
 }
 
 /* init glory particles */
-void init_particles(void) {
+static void init_particles(providencestruct *mp) 
+{
   int i;
   for(i = 0; i < PARTICLE_COUNT; ++i) {
-    init_particle(particles[i]);
+    init_particle(mp, mp->particles[i]);
 
     /* set initial time */
-    particles[i][3] = currenttime - (random()%1250)/1000.0;
+    mp->particles[i][3] = mp->currenttime - (random()%1250)/1000.0;
   }
 
   /* init eye particles */
   for(i = 0; i < EYE_PARTICLE_COUNT; ++i) {
-    eyeparticles[i][0] = random()%LOOKUPSIZE;
-    eyeparticles[i][1] = random()%EYELENGTH;
+    mp->eyeparticles[i][0] = random()%LOOKUPSIZE;
+    mp->eyeparticles[i][1] = random()%EYELENGTH;
   }
 }
 
-#define FPS 50
-double theta = 0.0;
 
 /* ugg, should be a priority queue if next event times known */
-void update_particles(void) {
+static void update_particles(providencestruct *mp) 
+{
   int i;
 
   for(i = 0; i < PARTICLE_COUNT; ++i) {
     /* check for time elapse */
-    if(currenttime > particles[i][3] + particles[i][4])
-      init_particle(particles[i]);
+    if(mp->currenttime > mp->particles[i][3] + mp->particles[i][4])
+      init_particle(mp, mp->particles[i]);
   }
 
   /* now update eye particles */
   for(i = 0; i < EYE_PARTICLE_COUNT; ++i) {
 /*     int x = eyeparticles[i][1] + random()%16; */
-    int x = eyeparticles[i][1] + random()%(cos(theta) < 0.0 ? 8 : 16);
+    int x = mp->eyeparticles[i][1] + random()%(cos(mp->theta) < 0.0 ? 8 : 16);
 
     /* reset if dead */
-    if(x > EYELENGTH || random()%(cos(theta) < 0.0 ? 40 : 10) == 0) {
+    if(x > EYELENGTH || random()%(cos(mp->theta) < 0.0 ? 40 : 10) == 0) {
 
 /*     if(x > EYELENGTH || (x > EYELENGTH/(2/3.0) && random()%7 == 0)) { */
-      eyeparticles[i][0] = random()%LOOKUPSIZE;
-      eyeparticles[i][1] = random()%40;
+      mp->eyeparticles[i][0] = random()%LOOKUPSIZE;
+      mp->eyeparticles[i][1] = random()%40;
     }
     else {
-      eyeparticles[i][1] = x;
+      mp->eyeparticles[i][1] = x;
     }    
   }
 }
 
 /* draw the pyramid */
-void draw_seal(void) {
+static void draw_seal(providencestruct *mp) 
+{
   int i;
   double base = sqrt(2.0);
   double top = 1.0 / sqrt(2.0);
@@ -305,20 +302,20 @@ void draw_seal(void) {
   glPushMatrix();
 
   /* set options for mono, wireframe */
-  if(wire) {
+  if(mp->wire) {
     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
     glDisable(GL_LIGHTING);
     glDisable(GL_TEXTURE_2D);
   }
   else {
     glEnable(GL_TEXTURE_2D);
-    glBindTexture(GL_TEXTURE_2D, bricktexture);
+    glBindTexture(GL_TEXTURE_2D, mp->bricktexture);
 
     glEnable(GL_LIGHTING);
 
-    glColor4fv(mono ? MaterialGray5 : MaterialGloryF);
+    glColor4fv(mp->mono ? MaterialGray5 : MaterialGloryF);
     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-                mono ? MaterialGray5 : MaterialGloryF);
+                mp->mono ? MaterialGray5 : MaterialGloryF);
   }
 
   glRotatef(45.0, 0.0, 1.0, 0.0);
@@ -371,10 +368,11 @@ void draw_seal(void) {
 }
 
 /* draw glory */
-void draw_glory(void) {
+static void draw_glory(providencestruct *mp) 
+{
   int i;
 
-  if(wire) {
+  if(mp->wire) {
     glBegin(GL_TRIANGLES);
     glVertex3f(-0.75, -0.75, 0.0);
     glVertex3f(0.75, -0.75, 0.0);
@@ -393,39 +391,39 @@ void draw_glory(void) {
   glEnable(GL_BLEND);
 
   /* glory colour lines */
-  glColor4fv(mono ? MaterialGloryM : MaterialGlory);
+  glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryM : MaterialGlory);
+              mp->mono ? MaterialGloryM : MaterialGlory);
 
   glBegin(GL_LINES);
   for(i = 0; i < PARTICLE_COUNT/2; ++i) {
-    double t = currenttime - particles[i][3];
-    double th = atan(particles[i][1] / particles[i][0]);
-    if(particles[i][0] < 0.0)
+    double t = mp->currenttime - mp->particles[i][3];
+    double th = atan(mp->particles[i][1] / mp->particles[i][0]);
+    if(mp->particles[i][0] < 0.0)
       th += Pi;
 
-    glVertex3f(particles[i][0], particles[i][1], particles[i][2]);
-    glVertex3f(particles[i][0] + 0.2*cos(th)*t,
-              particles[i][1] + 0.2*sin(th)*t,
-              particles[i][2]);
+    glVertex3f(mp->particles[i][0], mp->particles[i][1], mp->particles[i][2]);
+    glVertex3f(mp->particles[i][0] + 0.2*cos(th)*t,
+              mp->particles[i][1] + 0.2*sin(th)*t,
+              mp->particles[i][2]);
   }
   glEnd();
   
   /* gloryb colour lines */
-  glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
+  glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryMB : MaterialGloryB);
+              mp->mono ? MaterialGloryMB : MaterialGloryB);
   glBegin(GL_LINES);
   for(; i < PARTICLE_COUNT; ++i) {
-    double t = currenttime - particles[i][3];
-    double th = atan(particles[i][1] / particles[i][0]);
-    if(particles[i][0] < 0.0)
+    double t = mp->currenttime - mp->particles[i][3];
+    double th = atan(mp->particles[i][1] / mp->particles[i][0]);
+    if(mp->particles[i][0] < 0.0)
       th += Pi;
 
-    glVertex3f(particles[i][0], particles[i][1], particles[i][2]);
-    glVertex3f(particles[i][0] + 0.2*cos(th)*t,
-              particles[i][1] + 0.2*sin(th)*t,
-              particles[i][2]);
+    glVertex3f(mp->particles[i][0], mp->particles[i][1], mp->particles[i][2]);
+    glVertex3f(mp->particles[i][0] + 0.2*cos(th)*t,
+              mp->particles[i][1] + 0.2*sin(th)*t,
+              mp->particles[i][2]);
   }
   glEnd();
 
@@ -434,11 +432,12 @@ void draw_glory(void) {
 }
 
 /* draw eye of providence */
-void draw_eye(void) {
+static void draw_eye(providencestruct *mp) 
+{
   int i;
 
   /* draw wireeye */
-  if(wire) {
+  if(mp->wire) {
     glBegin(GL_TRIANGLES);
     glVertex3f(-0.25, -0.25, 0.0);
     glVertex3f(0.25, -0.25, 0.0);
@@ -453,29 +452,29 @@ void draw_eye(void) {
   glEnable(GL_BLEND);
 
   /* eye */
-  glColor4fv(mono ? MaterialGloryM : MaterialGlory);
+  glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryM : MaterialGlory);
+              mp->mono ? MaterialGloryM : MaterialGlory);
 
   /* draw eye particles on z = 0 plane */
   glBegin(GL_POINTS);
   for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) {
-    glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0], 
-              lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
+    glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], 
+              mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1],
               0.0);
   }
   glEnd();
 
   /* eye */
-  glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
+  glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryMB : MaterialGloryB);
+              mp->mono ? MaterialGloryMB : MaterialGloryB);
 
   /* draw eye particles on z = 0 plane */
   glBegin(GL_POINTS);
   for(; i < EYE_PARTICLE_COUNT; ++i) {
-    glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0], 
-              lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
+    glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], 
+              mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1],
               0.0);
   }
   glEnd();
@@ -486,28 +485,28 @@ void draw_eye(void) {
   glScalef(3.3, 2.2, 3.3);
 
   /* eye */
-  glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
+  glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryMB : MaterialGloryB);
+              mp->mono ? MaterialGloryMB : MaterialGloryB);
 
   /* draw eye particles on z = 0 plane */
   glBegin(GL_POINTS);
   for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) {
-    glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0], 
-              lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
+    glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], 
+              mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1],
               0.0);
   }
   glEnd();
 
-  glColor4fv(mono ? MaterialGloryM : MaterialGlory);
+  glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryM : MaterialGlory);
+              mp->mono ? MaterialGloryM : MaterialGlory);
 
   /* draw eye particles on z = 0 plane */
   glBegin(GL_POINTS);
   for(; i < EYE_PARTICLE_COUNT; ++i) {
-    glVertex3f(lookup[eyeparticles[i][0]][eyeparticles[i][1]][0], 
-              lookup[eyeparticles[i][0]][eyeparticles[i][1]][1],
+    glVertex3f(mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], 
+              mp->lookup[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1],
               0.0);
   }
   glEnd();
@@ -519,11 +518,12 @@ void draw_eye(void) {
 }
 
 /* draw eye of providence */
-void draw_eye2(void) {
+static void draw_eye2(providencestruct *mp) 
+{
   int i;
 
   /* draw wireeye */
-  if(wire) {
+  if(mp->wire) {
     glBegin(GL_TRIANGLES);
     glVertex3f(0.0, 0.25, 0.0);
     glVertex3f(0.25, -0.25, 0.0);
@@ -538,29 +538,29 @@ void draw_eye2(void) {
   glEnable(GL_BLEND);
 
   /* eye */
-  glColor4fv(mono ? MaterialGloryM : MaterialGlory);
+  glColor4fv(mp->mono ? MaterialGloryM : MaterialGlory);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryM : MaterialGlory);
+              mp->mono ? MaterialGloryM : MaterialGlory);
 
   /* draw eye particles on z = 0 plane */
   glBegin(GL_POINTS);
   for(i = 0; i < EYE_PARTICLE_COUNT/2; ++i) {
-    glVertex3f(lookup2[eyeparticles[i][0]][eyeparticles[i][1]][0], 
-              lookup2[eyeparticles[i][0]][eyeparticles[i][1]][1],
+    glVertex3f(mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], 
+              mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1],
               0.0);
   }
   glEnd();
 
   /* eye */
-  glColor4fv(mono ? MaterialGloryMB : MaterialGloryB);
+  glColor4fv(mp->mono ? MaterialGloryMB : MaterialGloryB);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, 
-              mono ? MaterialGloryMB : MaterialGloryB);
+              mp->mono ? MaterialGloryMB : MaterialGloryB);
 
   /* draw eye particles on z = 0 plane */
   glBegin(GL_POINTS);
   for(; i < EYE_PARTICLE_COUNT; ++i) {
-    glVertex3f(lookup2[eyeparticles[i][0]][eyeparticles[i][1]][0], 
-              lookup2[eyeparticles[i][0]][eyeparticles[i][1]][1],
+    glVertex3f(mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][0], 
+              mp->lookup2[mp->eyeparticles[i][0]][mp->eyeparticles[i][1]][1],
               0.0);
   }
   glEnd();
@@ -570,33 +570,36 @@ void draw_eye2(void) {
 }
 
 /* draw the scene */
-void draw_providence_strip(ModeInfo *mi) {
+static void draw_providence_strip(ModeInfo *mi) 
+{
+  providencestruct *mp = &providence[MI_SCREEN(mi)];
   glTranslatef(0.0, 1.414, 0.0);
 
-  position0[0] = 1.6*sin(theta);
-  position0[1] = 1.2;
-  position0[2] = 1.6*cos(theta);
-  position0[3] = 0.0;
-  glLightfv(GL_LIGHT0, GL_POSITION, position0);
+  mp->position0[0] = 1.6*sin(mp->theta);
+  mp->position0[1] = 1.2;
+  mp->position0[2] = 1.6*cos(mp->theta);
+  mp->position0[3] = 0.0;
+  glLightfv(GL_LIGHT0, GL_POSITION, mp->position0);
   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient2);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
 
   /* draw pyramid, glory */
   glDisable(GL_BLEND);
-  glCallList(pyramidlist);
-  draw_glory();
+  glCallList(mp->pyramidlist);
+  draw_glory(mp);
   if(eye) {
-    if(cos(theta) < 0.0)
-      draw_eye2();
+    if(cos(mp->theta) < 0.0)
+      draw_eye2(mp);
     else
-      draw_eye();
+      draw_eye(mp);
   }
 
   return;
 }
 
-void reshape_providence(ModeInfo * mi, int width, int height) {
+ENTRYPOINT void reshape_providence(ModeInfo * mi, int width, int height) 
+{
   double h = (GLfloat) height / (GLfloat) width;  
   providencestruct *mp = &providence[MI_SCREEN(mi)];
 
@@ -611,24 +614,25 @@ void reshape_providence(ModeInfo * mi, int width, int height) {
   glPointSize(2.0);
 }
 
-static void pinit(void) {
+static void pinit(providencestruct *mp) 
+{
   glClearDepth(1.0);
   glClearColor(0.0, 0.0, 0.0, 1.0);
   
   /* setup twoside lighting */
   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient2);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
-  glLightfv(GL_LIGHT0, GL_POSITION, position0);
+  glLightfv(GL_LIGHT0, GL_POSITION, mp->position0);
 
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
   glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
 
-  currenttime = 0.0;
-  init_particles();
-  make_brick();
-  build_eye();
+  mp->currenttime = 0.0;
+  init_particles(mp);
+  make_brick(mp);
+  build_eye(mp);
 
   glEnable(GL_NORMALIZE);
   glFrontFace(GL_CCW);
@@ -642,14 +646,15 @@ static void pinit(void) {
   glDepthFunc(GL_LEQUAL);
 
   /* build pyramid list */
-  pyramidlist = glGenLists(1);
-  glNewList(pyramidlist, GL_COMPILE);
-  draw_seal();
+  mp->pyramidlist = glGenLists(1);
+  glNewList(mp->pyramidlist, GL_COMPILE);
+  draw_seal(mp);
   glEndList();
 }
 
 /* cleanup routine */
-void release_providence(ModeInfo * mi) {
+ENTRYPOINT void release_providence(ModeInfo * mi) 
+{
 
   if(providence) {
     free((void *) providence);
@@ -660,7 +665,8 @@ void release_providence(ModeInfo * mi) {
 }
 
 /* event handling */
-Bool providence_handle_event(ModeInfo *mi, XEvent *event) {
+ENTRYPOINT Bool providence_handle_event(ModeInfo *mi, XEvent *event) 
+{
   providencestruct *mp = &providence[MI_SCREEN(mi)];
 
   switch(event->xany.type) {
@@ -676,11 +682,11 @@ Bool providence_handle_event(ModeInfo *mi, XEvent *event) {
       break;
       
     case Button4:
-      camera_velocity += 1.0;
+      mp->camera_velocity += 1.0;
       break;
 
     case Button5:
-      camera_velocity -= 1.0;
+      mp->camera_velocity -= 1.0;
       break;
     }
 
@@ -710,7 +716,8 @@ Bool providence_handle_event(ModeInfo *mi, XEvent *event) {
   return True;
 }
 
-void init_providence(ModeInfo *mi) {
+ENTRYPOINT void init_providence(ModeInfo *mi) 
+{
   providencestruct *mp;
   
   if(!providence) {
@@ -721,19 +728,30 @@ void init_providence(ModeInfo *mi) {
   mp = &providence[MI_SCREEN(mi)];
   mp->trackball = gltrackball_init ();
 
-  mono = MI_IS_MONO(mi);
-  wire = MI_IS_WIREFRAME(mi);
+  mp->position0[0] = 1;
+  mp->position0[1] = 5;
+  mp->position0[2] = 1;
+  mp->position0[3] = 1;
+
+  mp->camera_velocity = -8.0;
+
+  mp->mono = MI_IS_MONO(mi);
+  mp->wire = MI_IS_WIREFRAME(mi);
+
+  /* make multiple screens rotate at slightly different rates. */
+  mp->theta_scale = 0.7 + frand(0.6);
 
   if((mp->glx_context = init_GL(mi)) != NULL) {
     reshape_providence(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
     glDrawBuffer(GL_BACK);
-    pinit();
+    pinit(mp);
   }
   else
     MI_CLEARWINDOW(mi);
 }
 
-void draw_providence(ModeInfo * mi) {
+ENTRYPOINT void draw_providence(ModeInfo * mi) 
+{
   providencestruct *mp;
   
   Display    *display = MI_DISPLAY(mi);
@@ -755,16 +773,16 @@ void draw_providence(ModeInfo * mi) {
   glPushMatrix();
 
   /* modify camera */
-  if(fabs(camera_velocity) > EPSILON) {
-    camera_z = max(min(camera_z + 0.1*camera_velocity, -4.0), -12.0);
-    camera_velocity = 0.95*camera_velocity;
+  if(fabs(mp->camera_velocity) > EPSILON) {
+    mp->camera_z = max(min(mp->camera_z + 0.1*mp->camera_velocity, -4.0), -12.0);
+    mp->camera_velocity = 0.95*mp->camera_velocity;
   }
   
   /* rotate providence */
-  glTranslatef(0.0, 0.0, camera_z + sin(theta/4.0));
-  glRotatef(10.0+20.0*sin(theta/2.0), 1.0, 0.0, 0.0);
+  glTranslatef(0.0, 0.0, mp->camera_z + sin(mp->theta/4.0));
+  glRotatef(10.0+20.0*sin(mp->theta/2.0), 1.0, 0.0, 0.0);
   gltrackball_rotate(mp->trackball);
-  glRotatef(theta * 180.0 / Pi, 0.0, -1.0, 0.0);
+  glRotatef(mp->theta * 180.0 / Pi, 0.0, -1.0, 0.0);
 
   /* draw providence */
   draw_providence_strip(mi);
@@ -776,12 +794,14 @@ void draw_providence(ModeInfo * mi) {
   glXSwapBuffers(display, window);
 
   /* update */
-  currenttime += 1.0 / FPS;
-  theta = currenttime / 2.0;
-  update_particles();
+  mp->currenttime += 1.0 / FPS;
+  mp->theta = mp->currenttime / 2.0 * mp->theta_scale;
+  update_particles(mp);
 }
 
-void change_providence(ModeInfo * mi) {
+#ifndef STANDALONE
+ENTRYPOINT void change_providence(ModeInfo * mi) 
+{
   providencestruct *mp = &providence[MI_SCREEN(mi)];
   
   if (!mp->glx_context)
@@ -790,3 +810,6 @@ void change_providence(ModeInfo * mi) {
   glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(mp->glx_context));
   pinit();
 }
+#endif /* !STANDALONE */
+
+XSCREENSAVER_MODULE ("Providence", providence)