ftp://ftp.jp.xemacs.org/pub/NetBSD/packages/distfiles/xscreensaver-4.15.tar.gz
[xscreensaver] / hacks / glx / mirrorblob.c
index 679b72664d259dd83c5a72193f85f32fc70ce63e..2ff5666a9ac1a8c4d33be1f298ece30146639c25 100644 (file)
@@ -1,5 +1,3 @@
-/* -*- Mode: C; tab-width: 4 -*- */
-
 /* mirrorblob  Copyright (c) 2003 Jon Dowdall <jon.dowdall@bigpond.com> */
 /*
  * Permission to use, copy, modify, and distribute this software and its
  * trade secrets or any patents by this file or any part thereof.  In no
  * event will the author be liable for any lost revenue or profits or
  * other special, indirect and consequential damages.
-
+ *
  * Revision History:
- * 23-Sep-2003:  jon.dowdall@bigpond.com  Created module "mirrorblob"
+ * 23-Sep-2003:  jon.dowdall@bigpond.com  Created module "blob"
  * 19-Oct-2003:  jon.dowdall@bigpond.com  Added texturing
+ * 21-Oct-2003:                           Renamed to mirrorblob
+ * 10-Feb-2004:  jon.dowdall@bigpond.com  Added motion blur
  *
+ * The mirrorblob screensaver draws a pulsing blob on the screen.  Options
+ * include adding a background (via screen_to_ximage), texturing the blob,
+ * making the blob semi-transparent and varying the resolution of the blob
+ * tessellation.
  *
- * The mirrorblob screensaver draws a pulsing blob on the screen.
- * Options include adding a background (via screen_to_ximage),
- * texturing the blob, making the blob semi-transparent and varying the
- * resolution of the blob tessellation.
- *
- * The mirrorblob was inspired by a lavalamp is in no way a simulation.
- * The code is just an attempt to generate some eye-candy.
+ * The blob was inspired by a lavalamp is in no way a simulation.  The code is
+ * just an attempt to generate some eye-candy.
  *
  * Much of xscreensaver code framework is taken from the pulsar module by David
  * Konerding and the glslideshow by Mike Oliphant and Jamie Zawinski.
  *
  */
 
-#include <math.h> 
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/time.h>
 
 /*-
  * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
 #include <X11/Intrinsic.h>
 
 #ifdef STANDALONE
-# define PROGCLASS                                             "MirrorBlob"
-# define HACK_INIT                                             init_mirrorblob
-# define HACK_DRAW                                             draw_mirrorblob
-# define HACK_RESHAPE                                  reshape_mirrorblob
-# define screensaver_opts                              xlockmore_opts
-
-# define DEF_DELAY                      "10000"
-# define DEF_FPS                    "False"
-# define DEF_WIRE           "False"
-# define DEF_BLEND          "False"
-# define DEF_FOG                    "False"
-# define DEF_ANTIALIAS        "False"
-# define DEF_WALLS            "True"
-# define DEF_TEXTURE          "True"
-# define DEF_COLOUR           "False"
-# define DEF_OFFSET_TEXTURE   "False"
-# define DEF_PAINT_BACKGROUND "True"
-# define DEF_X_RES            "60"
-# define DEF_Y_RES            "32"
-# define DEF_FIELD_POINTS     "5"
-# define DEF_INCREMENTAL      "0"
-# define DEF_FADE_SPEED       "1"
-# define DEF_HOLD_FRAMES      "10240"
-
-#define        DEFAULTS                "*delay:                        " DEF_DELAY                             "\n" \
-                                               "*showFPS:                      " DEF_FPS                               "\n" \
-                                               "*wire:                         " DEF_WIRE                              "\n" \
-                                               "*blend:                        " DEF_BLEND                             "\n" \
-                                               "*fog:                          " DEF_FOG                               "\n" \
-                                               "*antialias:            " DEF_ANTIALIAS                 "\n" \
-                                               "*walls:                        " DEF_WALLS                             "\n" \
-                                               "*texture:                      " DEF_TEXTURE                   "\n" \
-                                               "*colour:                       " DEF_COLOUR                    "\n" \
-                                               "*offset_texture:       " DEF_OFFSET_TEXTURE    "\n" \
-                                               "*bgimage:                      " DEF_PAINT_BACKGROUND  "\n" \
-                                               "*x_resolution:         " DEF_X_RES                             "\n" \
-                                               "*y_resolution:         " DEF_Y_RES                             "\n" \
-                                               "*field_points:         " DEF_FIELD_POINTS              "\n" \
-                                               "*incremental:          " DEF_INCREMENTAL               "\n" \
-                                               "*fade_speed:           " DEF_FADE_SPEED                "\n" \
-                                               "*hold_frames:          " DEF_HOLD_FRAMES               "\n" \
-
-# include "xlockmore.h"                                /* from the xscreensaver distribution */
+# define PROGCLASS         "Screensaver"
+# define HACK_INIT         init_screensaver
+# define HACK_DRAW         draw_screensaver
+# define HACK_RESHAPE      reshape_screensaver
+# define screensaver_opts  xlockmore_opts
+
+#define DEF_DELAY            "10000"
+#define DEF_FPS              "False"
+#define DEF_WIRE             "False"
+#define DEF_BLEND            "False"
+#define DEF_FOG              "False"
+#define DEF_ANTIALIAS        "False"
+#define DEF_WALLS            "True"
+#define DEF_COLOUR           "False"
+#define DEF_TEXTURE          "True"
+#define DEF_OFFSET_TEXTURE   "False"
+#define DEF_PAINT_BACKGROUND "True"
+#define DEF_X_RES            "60"
+#define DEF_Y_RES            "32"
+#define DEF_FIELD_POINTS     "5"
+#define DEF_MOTION_BLUR      "0"
+#define DEF_INCREMENTAL      "0"
+#define DEF_HOLD_TIME        "30"
+#define DEF_FADE_TIME        "5"
+
+#define DEFAULTS \
+    "*delay:             " DEF_DELAY                "\n" \
+    "*showFPS:           " DEF_FPS                  "\n" \
+    "*wire:              " DEF_WIRE                 "\n" \
+    "*blend:             " DEF_BLEND                "\n" \
+    "*fog:               " DEF_FOG                  "\n" \
+    "*antialias:         " DEF_ANTIALIAS            "\n" \
+    "*walls:             " DEF_WALLS                "\n" \
+    "*colour :           " DEF_COLOUR               "\n" \
+    "*texture:           " DEF_TEXTURE              "\n" \
+    "*offset_texture:    " DEF_OFFSET_TEXTURE       "\n" \
+    "*paint_background:  " DEF_PAINT_BACKGROUND     "\n" \
+    "*x_resolution:      " DEF_X_RES                "\n" \
+    "*y_resolution:      " DEF_Y_RES                "\n" \
+    "*field_points:      " DEF_FIELD_POINTS         "\n" \
+    "*motion_blur:       " DEF_MOTION_BLUR          "\n" \
+    "*incremental:       " DEF_INCREMENTAL          "\n" \
+    "*hold_time:         " DEF_HOLD_TIME            "\n" \
+    "*fade_time:         " DEF_FADE_TIME            "\n"
+
+# include "xlockmore.h"    /* from the xscreensaver distribution */
 #else /* !STANDALONE */
-# include "xlock.h"                                    /* from the xlockmore distribution */
+# include "xlock.h"        /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef USE_GL /* whole file */
 #include "grab-ximage.h"
 
 #undef countof
-#define countof(x) (sizeof((x))/sizeof((*x)))
-
-#define WIDTH 1024
-#define HEIGHT 768
+#define countof(x) (sizeof((x)) / sizeof((*x)))
 
 #define PI  3.1415926535897
 
@@ -131,93 +131,95 @@ static int offset_texture;
 static int x_resolution;
 static int y_resolution;
 static int field_points;
+static int motion_blur;
 static int incremental;
-static int fade_speed;
-static int hold_frames;
+static int fade_time;
+static int hold_time;
 
 static XrmOptionDescRec opts[] = {
-  {"-wire",   ".mirrorblob.wire",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+wire",   ".mirrorblob.wire",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-blend",   ".mirrorblob.blend",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+blend",   ".mirrorblob.blend",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-fog",   ".mirrorblob.fog",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+fog",   ".mirrorblob.fog",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-antialias",   ".mirrorblob.antialias",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+antialias",   ".mirrorblob.antialias",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-walls",   ".mirrorblob.walls",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+walls",   ".mirrorblob.walls",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-texture",   ".mirrorblob.texture",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+texture",   ".mirrorblob.texture",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-colour",   ".mirrorblob.colour",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+colour",   ".mirrorblob.colour",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-offset_texture", ".mirrorblob.offset_texture",   XrmoptionNoArg, (caddr_t) "true" },
-  {"+offset_texture", ".mirrorblob.offset_texture",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-bgimage", ".mirrorblob.bgimage", XrmoptionNoArg, (caddr_t) "true" },
-  {"+bgimage", ".mirrorblob.bgimage", XrmoptionNoArg, (caddr_t) "false" },
-  {"-x_res",   ".mirrorblob.x_res",   XrmoptionSepArg, (caddr_t) NULL },
-  {"-y_res",   ".mirrorblob.y_res",   XrmoptionSepArg, (caddr_t) NULL },
-  {"-field_points", ".mirrorblob.field_points",   XrmoptionSepArg, (caddr_t) NULL },
-  {"-incremental", ".mirrorblob.incremental",   XrmoptionSepArg, (caddr_t) NULL },
-  {"-fade_speed", ".mirrorblob.fade_speed",   XrmoptionSepArg, (caddr_t) NULL },
-  {"-hold_frames", ".mirrorblob.hold_frames",   XrmoptionSepArg, (caddr_t) NULL },
+    {"-wire",             ".blob.wire",             XrmoptionNoArg, "true" },
+    {"+wire",             ".blob.wire",             XrmoptionNoArg, "false" },
+    {"-blend",            ".blob.blend",            XrmoptionNoArg, "true" },
+    {"+blend",            ".blob.blend",            XrmoptionNoArg, "false" },
+    {"-fog",              ".blob.fog",              XrmoptionNoArg, "true" },
+    {"+fog",              ".blob.fog",              XrmoptionNoArg, "false" },
+    {"-antialias",        ".blob.antialias",        XrmoptionNoArg, "true" },
+    {"+antialias",        ".blob.antialias",        XrmoptionNoArg, "false" },
+    {"-walls",            ".blob.walls",            XrmoptionNoArg, "true" },
+    {"+walls",            ".blob.walls",            XrmoptionNoArg, "false" },
+    {"-texture",          ".blob.texture",          XrmoptionNoArg, "true" },
+    {"+texture",          ".blob.texture",          XrmoptionNoArg, "false" },
+    {"-colour",           ".blob.colour",           XrmoptionNoArg, "true" },
+    {"+colour",           ".blob.colour",           XrmoptionNoArg, "false" },
+    {"-offset_texture",   ".blob.offset_texture",   XrmoptionNoArg, "true" },
+    {"+offset_texture",   ".blob.offset_texture",   XrmoptionNoArg, "false" },
+    {"-paint_background", ".blob.paint_background", XrmoptionNoArg, "true" },
+    {"+paint_background", ".blob.paint_background", XrmoptionNoArg, "false" },
+    {"-x_res",            ".blob.x_res",            XrmoptionSepArg, NULL },
+    {"-y_res",            ".blob.y_res",            XrmoptionSepArg, NULL },
+    {"-field_points",     ".blob.field_points",     XrmoptionSepArg, NULL },
+    {"-motion_blur",      ".blob.motion_blur",      XrmoptionSepArg, NULL },
+    {"-incremental",      ".blob.incremental",      XrmoptionSepArg, NULL },
+    {"-fade_time",        ".blob.fade_time",        XrmoptionSepArg, NULL },
+    {"-hold_time",        ".blob.hold_time",        XrmoptionSepArg, NULL },
 };
 
-
 static argtype vars[] = {
-  {(caddr_t *) &do_wire,      "wire",      "Wire",      DEF_WIRE,      t_Bool},
-  {(caddr_t *) &do_blend,     "blend",     "Blend",     DEF_BLEND,     t_Bool},
-  {(caddr_t *) &do_fog,       "fog",       "Fog",       DEF_FOG,       t_Bool},
-  {(caddr_t *) &do_antialias, "antialias", "Antialias", DEF_ANTIALIAS, t_Bool},
-  {(caddr_t *) &do_walls,     "walls",     "Walls",     DEF_WALLS,     t_Bool},
-  {(caddr_t *) &do_texture,   "texture",   "texture",   DEF_TEXTURE,   t_Bool},
-  {(caddr_t *) &do_colour,    "colour",    "colour",    DEF_COLOUR,    t_Bool},
-  {(caddr_t *) &offset_texture, "offset_texture","offset_texture", DEF_OFFSET_TEXTURE, t_Bool},
-  {(caddr_t *) &do_paint_background,"bgimage","bgimage", DEF_PAINT_BACKGROUND, t_Bool},
-  {(caddr_t *) &x_resolution, "x_res", "X_res", DEF_X_RES, t_Int},
-  {(caddr_t *) &y_resolution, "y_res", "Y_res", DEF_Y_RES, t_Int},
-  {(caddr_t *) &field_points, "field_points", "Field_points", DEF_FIELD_POINTS, t_Int},
-  {(caddr_t *) &incremental, "incremental", "Incremental", DEF_INCREMENTAL, t_Int},
-  {(caddr_t *) &fade_speed, "fade_speed", "fade_speed", DEF_FADE_SPEED, t_Int},
-  {(caddr_t *) &hold_frames, "hold_frames", "hold_frames", DEF_HOLD_FRAMES, t_Int},
+    {&do_wire,      "wire",         "Wire",      DEF_WIRE,      t_Bool},
+    {&do_blend,     "blend",        "Blend",     DEF_BLEND,     t_Bool},
+    {&do_fog,       "fog",          "Fog",       DEF_FOG,       t_Bool},
+    {&do_antialias, "antialias",    "Antialias", DEF_ANTIALIAS, t_Bool},
+    {&do_walls,     "walls",        "Walls",     DEF_WALLS,     t_Bool},
+    {&do_texture,   "texture",      "Texture",   DEF_TEXTURE,   t_Bool},
+    {&do_colour,    "colour",       "Colour",    DEF_COLOUR,   t_Bool},
+    {&offset_texture, "offset_texture","Offset_Texture", DEF_OFFSET_TEXTURE, t_Bool},
+    {&do_paint_background,"paint_background","Paint_Background", DEF_PAINT_BACKGROUND, t_Bool},
+    {&x_resolution, "x_res",        "X_Res",        DEF_X_RES,        t_Int},
+    {&y_resolution, "y_res",        "Y_Res",        DEF_Y_RES,        t_Int},
+    {&field_points, "field_points", "Field_Points", DEF_FIELD_POINTS, t_Int},
+    {&motion_blur,  "motion_blur",  "Motion_Blur",  DEF_MOTION_BLUR,  t_Int},
+    {&incremental,  "incremental",  "Incremental",  DEF_INCREMENTAL,  t_Int},
+    {&fade_time,    "fade_time",    "Fade_Time",    DEF_FADE_TIME,    t_Int},
+    {&hold_time,    "hold_time",    "Hold_Time",    DEF_HOLD_TIME,    t_Int},
 };
 
 
 static OptionStruct desc[] =
 {
-       {"-/+ wire", "whether to do use wireframe instead of filled (faster)"},
-       {"-/+ blend", "whether to do enable blending (slower)"},
-       {"-/+ fog", "whether to do enable fog (slower)"},
-       {"-/+ antialias", "whether to do enable antialiased lines (slower)"},
-       {"-/+ walls", "whether to add walls to the blob space (slower)"},
-       {"-/+ texture", "whether to add a texture to the blob (slower)"},
-       {"-/+ colour", "whether to colour the blob"},
-       {"-/+ offset_texture", "whether to offset texture co-ordinates"},
-       {"-/+ bgimage", "whether to display a background texture (slower)"},
-       {"-x_res", "Blob resolution in x direction"},
-       {"-y_res", "Blob resolution in y direction"},
-       {"-field_points", "Number of field points used to disturb blob"},
-       {"-incremental", "Field summation method"},
-       {"-fade_speed", "speed of transistion"},
-       {"-hold_frames", "Number of frames before next image"},
+    {"-/+ wire", "whether to do use wireframe instead of filled (faster)"},
+    {"-/+ blend", "whether to do enable blending (slower)"},
+    {"-/+ fog", "whether to do enable fog (slower)"},
+    {"-/+ antialias", "whether to do enable antialiased lines (slower)"},
+    {"-/+ walls", "whether to add walls to the blob space (slower)"},
+    {"-/+ texture", "whether to add a texture to the blob (slower)"},
+    {"-/+ colour", "whether to colour the blob"},
+    {"-/+ offset_texture", "whether to offset texture co-ordinates"},
+    {"-/+ paint_background", "whether to display a background texture (slower)"},
+    {"-x_res", "Blob resolution in x direction"},
+    {"-y_res", "Blob resolution in y direction"},
+    {"-field_points", "Number of field points used to disturb blob"},
+    {"-motion_blur", "Fade blob images (higher number = faster fade)"},
+    {"-incremental", "Field summation method"},
+    {"-fade_time", "Number of frames to transistion to next image"},
+    {"-hold_time", "Number of frames before next image"},
 };
 
 ModeSpecOpt screensaver_opts = {countof(opts), opts, countof(vars), vars, desc};
 
 #ifdef USE_MODULES
 ModStruct   screensaver_description =
-{"screensaver", "init_mirrorblob", "draw_mirrorblob", "release_mirrorblob",
- "draw_mirrorblob", "init_mirrorblob", NULL, &screensaver_opts,
+{"screensaver", "init_screensaver", "draw_screensaver", "release_screensaver",
+ "draw_screensaver", "init_screensaver", NULL, &screensaver_opts,
  1000, 1, 2, 1, 4, 1.0, "",
  "OpenGL screensaver", 0, NULL};
 #endif
 
-
 /* structure for holding the screensaver data */
 typedef struct {
-  int screen_width, screen_height;
-  GLXContext *glx_context;
-  Window window;
-  XColor fg, bg;
+    int screen_width, screen_height;
+    GLXContext *glx_context;
+    Window window;
+    XColor fg, bg;
 } screensaverstruct;
 
 static screensaverstruct *Screensaver = NULL;
@@ -228,36 +230,36 @@ static screensaverstruct *Screensaver = NULL;
 
 typedef struct
 {
-  GLdouble x, y;
+    GLdouble x, y;
 } Vector2D;
 
 typedef struct
 {
-  GLdouble x, y, z;
+    GLdouble x, y, z;
 } Vector3D;
 
 typedef struct
 {
-  GLubyte red, green, blue, alpha;
+    GLubyte red, green, blue, alpha;
 } Colour;
 
 /* Data used for sphere tessellation */
 typedef struct
 {
-  double cosyd, sinyd;
+    double cosyd, sinyd;
 
-  /* Number of x points at each row of the blob */
-  int num_x_points;  
+    /* Number of x points at each row of the blob */
+    int num_x_points;
 } Row_Data;
 
 /* Structure to hold sphere distortion data */
 typedef struct
 {
-  double cx, cy, cpower;
-  double mx, my, mpower;
-  double ax, ay, apower;
-  double vx, vy, vpower;
-  Vector3D pos;
+    double cx, cy, cpower;
+    double mx, my, mpower;
+    double ax, ay, apower;
+    double vx, vy, vpower;
+    Vector3D pos;
 } Field_Data;
 
 /*****************************************************************************
@@ -285,7 +287,7 @@ static double *field = 0, *wall_field = 0;
 
 Field_Data *field_data;
 
-/* Use 2 textures to allow a gradualr fade between images */
+/* Use 2 textures to allow a gradual fade between images */
 #define NUM_TEXTURES 2
 static int current_texture;
 
@@ -293,23 +295,50 @@ static int current_texture;
 GLfloat tex_width[NUM_TEXTURES], tex_height[NUM_TEXTURES];
 GLuint textures[NUM_TEXTURES];
 
-static int holding = 1;
-static int transitioning = 0;
+typedef enum
+{
+  HOLDING,
+  TRANSITIONING
+} Frame_State;
+
+static Frame_State state = HOLDING;
+static double state_start_time = 0;
+
 static int colour_cycle = 0;
 
+/******************************************************************************
+ *
+ * Returns the current time in seconds as a double.  Shamelessly borrowed from
+ * glslideshow.
+ *
+ */
+static double
+double_time (void)
+{
+  struct timeval now;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+# else
+  gettimeofday(&now);
+# endif
+
+  return (now.tv_sec + ((double) now.tv_usec * 0.000001));
+}
+
 /******************************************************************************
  *
  * Change to the projection matrix and set our viewing volume.
- * 
+ *
  */
 static void
-resetProjection(int width, int height)
+reset_projection(int width, int height)
 {
-  glMatrixMode( GL_PROJECTION );
-  glLoadIdentity( );
-  gluPerspective( 60.0, 1.0, 1.0, 1024.0 );
-  glMatrixMode(GL_MODELVIEW);
-  glLoadIdentity();
+    glMatrixMode (GL_PROJECTION);
+    glLoadIdentity ();
+    gluPerspective (60.0, 1.0, 1.0, 1024.0 );
+    glMatrixMode (GL_MODELVIEW);
+    glLoadIdentity ();
 }
 
 /****************************************************************************
@@ -319,30 +348,30 @@ resetProjection(int width, int height)
 void
 grab_texture(ModeInfo *mi, int texture_index)
 {
-  XImage *ximage;
+    XImage *ximage;
 
-  ximage = screen_to_ximage (mi->xgwa.screen, mi->window, 0);
+    ximage = screen_to_ximage (mi->xgwa.screen, mi->window, 0);
 
-  glBindTexture (GL_TEXTURE_2D, textures[texture_index]);
-  glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+    glBindTexture (GL_TEXTURE_2D, textures[texture_index]);
+    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
 
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ximage->width, ximage->height,
-               0, GL_RGBA, GL_UNSIGNED_BYTE, ximage->data);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ximage->width, ximage->height,
+                 0, GL_RGBA, GL_UNSIGNED_BYTE, ximage->data);
 
-  tex_width[texture_index] = mi->xgwa.width  / (GLfloat)ximage->width;
-  tex_height[texture_index] = mi->xgwa.height  / (GLfloat)ximage->height;
+    tex_width[texture_index] = (mi->xgwa.width - 1) / (GLfloat)ximage->width;
+    tex_height[texture_index] = (mi->xgwa.height - 1)  / (GLfloat)ximage->height;
 
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
-  free(ximage->data);
-  ximage->data = 0;
-  XDestroyImage (ximage);
+    free(ximage->data);
+    ximage->data = 0;
+    XDestroyImage (ximage);
 }
 
 /******************************************************************************
@@ -350,116 +379,117 @@ grab_texture(ModeInfo *mi, int texture_index)
  * Initialise the data used to calculate the blob shape.
  */
 static void
-initializeGL(ModeInfo *mi, GLsizei width, GLsizei height) 
+initialize_gl(ModeInfo *mi, GLsizei width, GLsizei height)
 {
-  GLfloat fogColor[4] = { 0.1, 0.1, 0.1, 0.1 };
-  /* Lighting values */
-  GLfloat lightPos0[] = {50.0f, 10.0f, 20.0f, 1.0f };
-  GLfloat whiteLight0[] = { 0.1f, 0.1f, 0.1f, 1.0f };
-  GLfloat sourceLight0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
-  GLfloat specularLight0[] = { 0.7f, 0.6f, 0.3f, 1.0f };
-
-  GLfloat lightPos1[] = {0.0f, -50.0f, 50.0f, 1.0f };
-  GLfloat whiteLight1[] = { 0.1f, 0.1f, 0.1f, 1.0f };
-  GLfloat sourceLight1[] = { 1.0f, 0.3f, 0.3f, 1.0f };
-  GLfloat specularLight1[] = { 0.7f, 0.6f, 0.3f, 1.0f };
-
-  GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
-
-  /* Setup our viewport. */
-  glViewport( 0, 0, width, height ); 
-
-  glEnable(GL_DEPTH_TEST);
-
-  if (do_antialias)
-  {
-       do_blend = 1;
-       glEnable(GL_LINE_SMOOTH);
-  }
-
-  /* The blend function is used for trasitioning between two images even when
-   * blend is not selected.
-   */
-  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-  if (do_wire)
-  {
-       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-  }
-  else
-  {
-       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-  }
-
-  if (do_fog)
-  {
-       glEnable(GL_FOG);
-       glFogi(GL_FOG_MODE, GL_LINEAR);
-       glFogfv(GL_FOG_COLOR, fogColor);
-       glFogf(GL_FOG_DENSITY, 0.35);
-       glFogf(GL_FOG_START, 2.0);
-       glFogf(GL_FOG_END, 10.0);
-  }
-
-  /* Our shading model--Gouraud (smooth). */
-  glShadeModel (GL_SMOOTH);
-
-  /* Culling. */
-  glCullFace (GL_BACK);
-  glEnable (GL_CULL_FACE);
-  glEnable (GL_DEPTH_TEST);
-  glFrontFace (GL_CCW);
-
-
-  /* Set the clear color. */
-  glClearColor( 0, 0, 0, 0 );
-
-  glViewport( 0, 0, width, height );
-
-  glLightfv (GL_LIGHT0, GL_AMBIENT, whiteLight0);
-  glLightfv (GL_LIGHT0, GL_DIFFUSE, sourceLight0);
-  glLightfv (GL_LIGHT0, GL_SPECULAR, specularLight0);
-  glLightfv (GL_LIGHT0, GL_POSITION, lightPos0);
-  glEnable (GL_LIGHT0);
-  glLightfv (GL_LIGHT1, GL_AMBIENT, whiteLight1);
-  glLightfv (GL_LIGHT1, GL_DIFFUSE, sourceLight1);
-  glLightfv (GL_LIGHT1, GL_SPECULAR, specularLight1);
-  glLightfv (GL_LIGHT1, GL_POSITION, lightPos1);
-  glEnable (GL_LIGHT1);
-  glEnable (GL_LIGHTING);
-
-  /* Enable color tracking */
-  glEnable (GL_COLOR_MATERIAL);
-
-  /* Set Material properties to follow glColor values */
-  glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
-
-  /* Set all materials to have specular reflectivity */
-  glMaterialfv (GL_FRONT, GL_SPECULAR, specref);
-  glMateriali (GL_FRONT, GL_SHININESS, 64);
-
-  glEnable (GL_NORMALIZE);
-
-  /* Enable Arrays */
-  if (do_texture)
-  {
-    glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+    GLfloat fogColor[4] = { 0.1, 0.1, 0.1, 0.1 };
+    /* Lighting values */
+    GLfloat lightPos0[] = {500.0f, 100.0f, 200.0f, 1.0f };
+    GLfloat whiteLight0[] = { 0.1f, 0.1f, 0.1f, 1.0f };
+    GLfloat sourceLight0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+    GLfloat specularLight0[] = { 0.7f, 0.6f, 0.3f, 1.0f };
 
-    glEnable (GL_TEXTURE_2D);
-    current_texture = 0;
-    glGenTextures (NUM_TEXTURES, textures);
-    grab_texture (mi, current_texture);
-    grab_texture (mi, 1 - current_texture);
-
-    glEnableClientState (GL_TEXTURE_COORD_ARRAY);
-  }
-
-  if (do_colour)
-  {
-    glEnableClientState (GL_COLOR_ARRAY);
-  }
-  glEnableClientState (GL_NORMAL_ARRAY);
-  glEnableClientState (GL_VERTEX_ARRAY);
+    GLfloat lightPos1[] = {0.0f, -500.0f, 500.0f, 1.0f };
+    GLfloat whiteLight1[] = { 0.1f, 0.1f, 0.1f, 1.0f };
+    GLfloat sourceLight1[] = { 1.0f, 0.3f, 0.3f, 1.0f };
+    GLfloat specularLight1[] = { 0.7f, 0.6f, 0.3f, 1.0f };
+
+    GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+    /* Setup our viewport. */
+    glViewport (0, 0, width, height ); 
+
+    glEnable(GL_DEPTH_TEST);
+
+    if (do_antialias)
+    {
+        do_blend = 1;
+        glEnable(GL_LINE_SMOOTH);
+    }
+
+    /* The blend function is used for trasitioning between two images even when
+     * blend is not selected.
+     */
+    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    if (do_wire)
+    {
+        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+    }
+    else
+    {
+        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    }
+
+    if (do_fog)
+    {
+        glEnable(GL_FOG);
+        glFogi(GL_FOG_MODE, GL_LINEAR);
+        glFogfv(GL_FOG_COLOR, fogColor);
+        glFogf(GL_FOG_DENSITY, 0.35);
+        glFogf(GL_FOG_START, 2.0);
+        glFogf(GL_FOG_END, 10.0);
+    }
+
+    /* Our shading model--Gouraud (smooth). */
+    glShadeModel (GL_SMOOTH);
+
+    /* Culling. */
+    glCullFace (GL_BACK);
+    glEnable (GL_CULL_FACE);
+    glEnable (GL_DEPTH_TEST);
+    glFrontFace (GL_CCW);
+
+    /* Set the clear color. */
+    glClearColor( 0, 0, 0, 0 );
+
+    glViewport( 0, 0, width, height );
+
+    glLightfv (GL_LIGHT0, GL_AMBIENT, whiteLight0);
+    glLightfv (GL_LIGHT0, GL_DIFFUSE, sourceLight0);
+    glLightfv (GL_LIGHT0, GL_SPECULAR, specularLight0);
+    glLightfv (GL_LIGHT0, GL_POSITION, lightPos0);
+    glEnable (GL_LIGHT0);
+    glLightfv (GL_LIGHT1, GL_AMBIENT, whiteLight1);
+    glLightfv (GL_LIGHT1, GL_DIFFUSE, sourceLight1);
+    glLightfv (GL_LIGHT1, GL_SPECULAR, specularLight1);
+    glLightfv (GL_LIGHT1, GL_POSITION, lightPos1);
+    glEnable (GL_LIGHT1);
+    glEnable (GL_LIGHTING);
+
+    /* Enable color tracking */
+    glEnable (GL_COLOR_MATERIAL);
+
+    /* Set Material properties to follow glColor values */
+    glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
+
+    /* Set all materials to have specular reflectivity */
+    glMaterialfv (GL_FRONT, GL_SPECULAR, specref);
+    glMateriali (GL_FRONT, GL_SHININESS, 64);
+
+    glEnable (GL_NORMALIZE);
+
+    /* Enable Arrays */
+    if (do_texture)
+    {
+        glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+
+        glEnable (GL_TEXTURE_2D);
+        current_texture = 0;
+        glGenTextures (NUM_TEXTURES, textures);
+        grab_texture (mi, current_texture);
+
+        glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+    }
+
+    if (do_colour)
+    {
+        glEnableClientState (GL_COLOR_ARRAY);
+    }
+    glEnableClientState (GL_NORMAL_ARRAY);
+    glEnableClientState (GL_VERTEX_ARRAY);
+
+    /* Clear the buffer since this is not done during a draw with motion blur */
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
 /******************************************************************************
@@ -472,33 +502,33 @@ calculate_normal (Vector3D point1,
                   Vector3D point3,
                   Vector3D *normal)
 {
-  Vector3D vector1, vector2;
-  double magnitude;
-
-  vector1.x = point2.x - point1.x;
-  vector1.y = point2.y - point1.y;
-  vector1.z = point2.z - point1.z;
-
-  vector2.x = point3.x - point2.x;
-  vector2.y = point3.y - point2.y;
-  vector2.z = point3.z - point2.z;
-
-  (*normal).x = vector1.y * vector2.z - vector1.z * vector2.y;
-  (*normal).y = vector1.z * vector2.x - vector1.x * vector2.z;
-  (*normal).z = vector1.x * vector2.y - vector1.y * vector2.x;
-
-  /* Adjust the normal to unit magnitude */
-  magnitude = sqrt ((*normal).x * (*normal).x
-    + (*normal).y * (*normal).y
-    + (*normal).z * (*normal).z);
-
-  /* Watch out for divide by zero/underflow */
-  if (magnitude > 1e-300)
-  {
-    (*normal).x /= magnitude;
-    (*normal).y /= magnitude;
-    (*normal).z /= magnitude;
-  }
+    Vector3D vector1, vector2;
+    double magnitude;
+
+    vector1.x = point2.x - point1.x;
+    vector1.y = point2.y - point1.y;
+    vector1.z = point2.z - point1.z;
+
+    vector2.x = point3.x - point2.x;
+    vector2.y = point3.y - point2.y;
+    vector2.z = point3.z - point2.z;
+
+    (*normal).x = vector1.y * vector2.z - vector1.z * vector2.y;
+    (*normal).y = vector1.z * vector2.x - vector1.x * vector2.z;
+    (*normal).z = vector1.x * vector2.y - vector1.y * vector2.x;
+
+    /* Adjust the normal to unit magnitude */
+    magnitude = sqrt ((*normal).x * (*normal).x
+                      + (*normal).y * (*normal).y
+                      + (*normal).z * (*normal).z);
+
+    /* Watch out for divide by zero/underflow */
+    if (magnitude > 1e-300)
+    {
+        (*normal).x /= magnitude;
+        (*normal).y /= magnitude;
+        (*normal).z /= magnitude;
+    }
 }
 
 /******************************************************************************
@@ -513,154 +543,150 @@ initialise_blob(int width,
                 int height,
                 int field_array_size)
 {
-  /* Loop variables */
-  int x, y, i;
-  double xd;
-
-  colour_cycle = 0;
-
-  row_data = (Row_Data *) malloc (y_resolution * sizeof (Row_Data));
-  if (!row_data)
-  {
-    fprintf(stderr, "Couldn't allocate row data buffer\n");
-    return -1;
-  }
-
-  field_data = (Field_Data *) malloc (field_points * sizeof (Field_Data));
-  if (!field_data)
-  {
-    fprintf(stderr, "Couldn't allocate row data buffer\n");
-    return -1;
-  }
-
-  field = (double *)malloc(field_array_size * sizeof(double));
-  if (!field)
-  {
-    fprintf(stderr, "Couldn't allocate field buffer\n");
-    return -1;
-  }
-
-  wall_field = (double *)malloc(field_array_size * sizeof(double));
-  if (!wall_field)
-  {
-    fprintf(stderr, "Couldn't allocate wall_field buffer\n");
-    return -1;
-  }
-
-  dots = (Vector3D *)malloc(x_resolution * y_resolution * sizeof(Vector3D));
-  if (!dots)
-  {
-    fprintf(stderr, "Couldn't allocate points buffer\n");
-    return -1;
-  }
-  glVertexPointer (3, GL_DOUBLE, 0, (GLvoid *) dots);
-
-  normals = (Vector3D *)malloc(x_resolution * y_resolution * sizeof(Vector3D));
-  if (!normals)
-  {
-    fprintf(stderr, "Couldn't allocate normals buffer\n");
-    return -1;
-  }
-  glNormalPointer (GL_DOUBLE, 0, (GLvoid *) normals);
-
-  if (do_colour)
-  {
-    colours = (Colour *)malloc(x_resolution * y_resolution * sizeof(Colour));
-    if (!colours)
+    /* Loop variables */
+    int x, y, i;
+    double xd;
+
+    colour_cycle = 0;
+
+    row_data = (Row_Data *) malloc (y_resolution * sizeof (Row_Data));
+    if (!row_data)
+    {
+        fprintf(stderr, "Couldn't allocate row data buffer\n");
+        return -1;
+    }
+
+    field_data = (Field_Data *) malloc (field_points * sizeof (Field_Data));
+    if (!field_data)
+    {
+        fprintf(stderr, "Couldn't allocate field data buffer\n");
+        return -1;
+    }
+
+    field = (double *)malloc(field_array_size * sizeof(double));
+    if (!field)
+    {
+        fprintf(stderr, "Couldn't allocate field buffer\n");
+        return -1;
+    }
+
+    wall_field = (double *)malloc(field_array_size * sizeof(double));
+    if (!wall_field)
+    {
+        fprintf(stderr, "Couldn't allocate wall field buffer\n");
+        return -1;
+    }
+
+    dots = (Vector3D *)malloc(x_resolution * y_resolution * sizeof(Vector3D));
+    if (!dots)
     {
-      fprintf(stderr, "Couldn't allocate colours buffer\n");
-      return -1;
+        fprintf(stderr, "Couldn't allocate points buffer\n");
+        return -1;
     }
-    glColorPointer (4, GL_UNSIGNED_BYTE, 0, (GLvoid *) colours);
-  }
-  
-  if (do_texture)
-  {
-    tex_coords = (Vector2D *)malloc(x_resolution * y_resolution
-                                    * sizeof(Vector2D));
-    if (!tex_coords)
+    glVertexPointer (3, GL_DOUBLE, 0, (GLvoid *) dots);
+
+    normals = (Vector3D *)malloc(x_resolution * y_resolution * sizeof(Vector3D));
+    if (!normals)
     {
-      fprintf(stderr, "Couldn't allocate tex_coords buffer\n");
-      return -1;
+        fprintf(stderr, "Couldn't allocate normals buffer\n");
+        return -1;
     }
-    glTexCoordPointer (2, GL_DOUBLE, 0, (GLvoid *) tex_coords);
-  }
-
-  if (! do_texture)
-    do_paint_background = False;
-
-
-  num_points = 0;
-  /* Generate constant row data and count of total number of points */
-  for (y = 0; y < y_resolution; y++)
-  {
-    row_data[y].cosyd = cos(PI * (double)(y * (y_resolution + 1))
-                   / (double)(y_resolution * y_resolution));
-    row_data[y].sinyd = sin(PI * (double)(y * (y_resolution + 1))
-                   / (double)(y_resolution * y_resolution));
-    row_data[y].num_x_points = (int)(x_resolution * row_data[y].sinyd + 1.0);
-    num_points += row_data[y].num_x_points;
-  }
-
-  /* Initialise field data */
-  for (i = 0; i < field_points; i++)
-  {
-    field_data[i].ax = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-    field_data[i].ay = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-    field_data[i].apower = (((double)random() / (double)RAND_MAX) - 0.5);
-
-    field_data[i].pos.x = 1.5 * sin(PI * field_data[i].ay)
-      * cos(PI *  field_data[i].ax);
-    field_data[i].pos.y = 1.5 * cos(PI * field_data[i].ay);
-    field_data[i].pos.z = 1.5 * sin(PI * field_data[i].ay)
-      * sin(PI *  field_data[i].ax);
-
-    field_data[i].cx = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-    field_data[i].cy = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
-    field_data[i].cpower = (((double)random() / (double)RAND_MAX) - 0.5);
-
-    field_data[i].vx = 0.0;
-    field_data[i].vy = 0.0;
-    field_data[i].vpower = 0.0;
-
-    field_data[i].mx = 0.003 * ((double)random() / (double)RAND_MAX);
-    field_data[i].my = 0.003 * ((double)random() / (double)RAND_MAX);
-    field_data[i].mpower = 0.003 * ((double)random() / (double)RAND_MAX);
-  }
-
-  /* Initialise lookup table of field strength */
-  for (i = 0; i < field_array_size; i++)
-  {
-    xd = 2.0 * (((double)i / (double)field_array_size));
-
-    xd = 3.0 * xd * xd * xd * xd - 0.25 * xd * xd; 
-    field[i] = 0.4 / (field_points * (xd + 0.1));
-
-    xd = 10.0 * (((double)i / (double)field_array_size));
-    wall_field[i] = 0.4 / (xd * xd * xd * xd + 1.0);
-  }
-
-  for (y = 0; y < y_resolution; y++)
-  {
-    for (x = 0; x < row_data[y].num_x_points; x++)
+    glNormalPointer (GL_DOUBLE, 0, (GLvoid *) normals);
+
+    if (do_colour)
     {
-      i = x + y * x_resolution;
-      xd = 2.0 * (((double)x / (double)row_data[y].num_x_points) - 0.5);
-
-      dots[i].x = row_data[y].sinyd * cos(PI * xd);
-      dots[i].y = row_data[y].cosyd;
-      dots[i].z = row_data[y].sinyd * sin(PI * xd);
-      normals[i].x = row_data[y].sinyd * cos(PI * xd);
-      normals[i].y = row_data[y].cosyd;
-      normals[i].z = row_data[y].sinyd * sin(PI * xd);
-      if (do_texture)
-      {
-        tex_coords[i].x = 2.0 - 2.0 * x / (float) row_data[y].num_x_points;
-        tex_coords[i].y = 1.0 - y / (float) y_resolution;
-      }
+        colours = (Colour *)malloc(x_resolution * y_resolution * sizeof(Colour));
+        if (!colours)
+        {
+            fprintf(stderr, "Couldn't allocate colours buffer\n");
+            return -1;
+        }
+        glColorPointer (4, GL_UNSIGNED_BYTE, 0, (GLvoid *) colours);
     }
-  }
-  return 0;
+
+    if (do_texture)
+    {
+        tex_coords = (Vector2D *)malloc(x_resolution * y_resolution
+                                        * sizeof(Vector2D));
+        if (!tex_coords)
+        {
+            fprintf(stderr, "Couldn't allocate tex_coords buffer\n");
+            return -1;
+        }
+        glTexCoordPointer (2, GL_DOUBLE, 0, (GLvoid *) tex_coords);
+    }
+
+    num_points = 0;
+    /* Generate constant row data and count of total number of points */
+    for (y = 0; y < y_resolution; y++)
+    {
+        row_data[y].cosyd = cos(PI * (double)(y * (y_resolution + 1))
+                                / (double)(y_resolution * y_resolution));
+        row_data[y].sinyd = sin(PI * (double)(y * (y_resolution + 1))
+                                / (double)(y_resolution * y_resolution));
+        row_data[y].num_x_points = (int)(x_resolution * row_data[y].sinyd + 1.0);
+        num_points += row_data[y].num_x_points;
+    }
+
+    /* Initialise field data */
+    for (i = 0; i < field_points; i++)
+    {
+        field_data[i].ax = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+        field_data[i].ay = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+        field_data[i].apower = (((double)random() / (double)RAND_MAX) - 0.5);
+
+        field_data[i].pos.x = 1.5 * sin(PI * field_data[i].ay)
+            * cos(PI *  field_data[i].ax);
+        field_data[i].pos.y = 1.5 * cos(PI * field_data[i].ay);
+        field_data[i].pos.z = 1.5 * sin(PI * field_data[i].ay)
+            * sin(PI *  field_data[i].ax);
+
+        field_data[i].cx = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+        field_data[i].cy = 2.0 * (((double)random() / (double)RAND_MAX) - 0.5);
+        field_data[i].cpower = (((double)random() / (double)RAND_MAX) - 0.5);
+
+        field_data[i].vx = 0.0;
+        field_data[i].vy = 0.0;
+        field_data[i].vpower = 0.0;
+
+        field_data[i].mx = 0.003 * ((double)random() / (double)RAND_MAX);
+        field_data[i].my = 0.003 * ((double)random() / (double)RAND_MAX);
+        field_data[i].mpower = 0.003 * ((double)random() / (double)RAND_MAX);
+    }
+
+    /* Initialise lookup table of field strength */
+    for (i = 0; i < field_array_size; i++)
+    {
+        xd = 2.0 * (((double)i / (double)field_array_size));
+
+        xd = 3.0 * xd * xd * xd * xd;
+        field[i] = 0.4 / (field_points * (xd + 0.1));
+
+        xd = 10.0 * (((double)i / (double)field_array_size));
+        wall_field[i] = 0.4 / (xd * xd * xd * xd + 1.0);
+    }
+
+    for (y = 0; y < y_resolution; y++)
+    {
+        for (x = 0; x < row_data[y].num_x_points; x++)
+        {
+            i = x + y * x_resolution;
+            xd = 2.0 * (((double)x / (double)row_data[y].num_x_points) - 0.5);
+
+            dots[i].x = row_data[y].sinyd * cos(PI * xd);
+            dots[i].y = row_data[y].cosyd;
+            dots[i].z = row_data[y].sinyd * sin(PI * xd);
+            normals[i].x = row_data[y].sinyd * cos(PI * xd);
+            normals[i].y = row_data[y].cosyd;
+            normals[i].z = row_data[y].sinyd * sin(PI * xd);
+            if (do_texture)
+            {
+                tex_coords[i].x = 2.0 - 2.0 * x / (float) row_data[y].num_x_points;
+                tex_coords[i].y = 1.0 - y / (float) y_resolution;
+            }
+        }
+    }
+    return 0;
 }
 
 
@@ -672,261 +698,316 @@ static void
 calc_blob(int width,
           int height,
           int field_array_size,
-          float limit)
+          float limit,
+          double fade)
 {
-  static double freak = 0.0;
+    static double freak = 0.0;
 
-  static double v_freak = 0.0007;
+    static double v_freak = 0.0007;
 
-  /* Loop variables */
-  int x, y, i, index;
-  /* position of a point */
-  double xd, yd, zd, offset_x, offset_y, offset_z;
-  double strength, radius;
-  double xdist, ydist, zdist;
-  int dist;
+    /* Loop variables */
+    int x, y, i, index, index1, index2, index3;
+    /* position of a point */
+    double xd, yd, zd, offset_x, offset_y, offset_z;
+    double strength, radius;
+    double xdist, ydist, zdist;
+    int dist;
 
-  /* Color components */
+    /* Color components */
 
-  colour_cycle++;
+    colour_cycle++;
 
-  blob_force.x = 0.0;
-  blob_force.y = 0.0;
-  blob_force.z = 0.0;
-  for (y = 0; y < y_resolution; y++)
-  {
-    for (x = 0; x < row_data[y].num_x_points; x++)
+    /* Update position and strength of points used to distort the blob */
+    for (i = 0; i < field_points; i++)
     {
-      index = x + y * x_resolution;
-      xd = 2.0 * PI * (((double)x / (double)row_data[y].num_x_points) - 0.5);
-
-      radius = 1.0 + 0.0 * sin (xd * 10);
-
-      zd = radius * row_data[y].sinyd * sin(xd);
-      xd = radius * row_data[y].sinyd * cos(xd);
-      yd = radius * row_data[y].cosyd;
-
-      offset_x = 0.0;
-      offset_y = 0.0;
-      offset_z = 0.0;
-      strength = 0.0;
-      for ( i = 0; i < field_points; i++)
-      {
-        xdist = field_data[i].pos.x - xd;
-        ydist = field_data[i].pos.y - yd;
-        zdist = field_data[i].pos.z - zd;
-        dist = field_array_size * (xdist * xdist + ydist * ydist
-                                   + zdist * zdist) * 0.1;
-
-        strength += PI * field_data[i].apower;
-
-        if (dist < field_array_size)
+        field_data[i].vx += field_data[i].mx*(field_data[i].cx - field_data[i].ax);
+        field_data[i].vy += field_data[i].my*(field_data[i].cy - field_data[i].ay);
+        field_data[i].vpower += field_data[i].mpower
+            * (field_data[i].cpower - field_data[i].apower);
+
+        field_data[i].ax += 0.1 * field_data[i].vx;
+        field_data[i].ay += 0.1 * field_data[i].vy;
+        field_data[i].apower += 0.1 * field_data[i].vpower;
+
+        field_data[i].pos.x = 1.0 * sin(PI * field_data[i].ay)
+            * cos(PI * field_data[i].ax);
+        field_data[i].pos.y = 1.0 * cos(PI * field_data[i].ay);
+        field_data[i].pos.z = 1.0 * sin(PI * field_data[i].ay)
+            * sin(PI * field_data[i].ax);
+    }
+
+    blob_force.x = 0.0;
+    blob_force.y = 0.0;
+    blob_force.z = 0.0;
+    for (y = 0; y < y_resolution; y++)
+    {
+        for (x = 0; x < row_data[y].num_x_points; x++)
         {
-          offset_x += xd * field_data[i].apower * field[dist];
-          offset_y += yd * field_data[i].apower * field[dist];
-          offset_z += zd * field_data[i].apower * field[dist];
+            index = x + y * x_resolution;
+            xd = 2.0 * PI * (((double)x / (double)row_data[y].num_x_points) - 0.5);
 
-          blob_force.x += 2.0 * xd * field_data[i].apower * field[dist];
-          blob_force.y += 2.0 * yd * field_data[i].apower * field[dist];
-          blob_force.z += 2.0 * zd * field_data[i].apower * field[dist];
+            radius = 1.0 + 0.0 * sin (xd * 10);
 
-          strength *= 2.0 * field[dist];
-        }
+            zd = radius * row_data[y].sinyd * sin(xd);
+            xd = radius * row_data[y].sinyd * cos(xd);
+            yd = radius * row_data[y].cosyd;
 
-        if (incremental)
-        {
-          xd += offset_x * freak * freak;
-          yd += offset_y * freak * freak;
-          zd += offset_z * freak * freak;
-        }
-        if (incremental == 1)
-        {
-          offset_x = 0.0;
-          offset_y = 0.0;
-          offset_z = 0.0;
-        }
-      }
-
-      if (incremental < 3)
-      {
-        xd += offset_x;
-        yd += offset_y;
-        zd += offset_z;
-      }
-      xd += blob_center.x;
-      yd += blob_center.y;
-      zd += blob_center.z;
-
-      if (do_colour)
-      {
-        colours[index].red = 128 + (int)(sin(strength + colour_cycle * 0.01 + 2.0 * PI * x / row_data[y].num_x_points) * 127.0);
-        colours[index].green = 128 + (int)(cos(strength + colour_cycle * 0.025) * 127.0);
-        colours[index].blue = 128 + (int)(sin(strength + colour_cycle * 0.03 + 2.0 * PI * y / y_resolution) * 127.0);
-        colours[index].alpha = 128 + (int)(cos(strength + colour_cycle * 0.015) * 63.0);
-      }
-
-      /* Add walls */
-      if (do_walls)
-      {
-        if (zd < -limit) zd = -limit;
-        if (zd > limit) zd = limit;
-
-        dist = field_array_size * (zd + limit) * (zd + limit) * 0.5;
-        if (dist < field_array_size)
-        {
-          xd += (xd - blob_center.x) * wall_field[dist];
-          yd += (yd - blob_center.y) * wall_field[dist];
-          blob_force.z += (zd + limit);
-        }
-        else
-        {
-          dist = field_array_size * (zd - limit) * (zd - limit) * 0.5;
-          if (dist < field_array_size)
-          {
-            xd += (xd - blob_center.x) * wall_field[dist];
-            yd += (yd - blob_center.y) * wall_field[dist];
-            blob_force.z -= (zd - limit);
-          }
-
-          if (yd < -limit) yd = -limit;
-          if (yd > limit) yd = limit;
-          
-          dist = field_array_size * (yd + limit) * (yd + limit) * 0.5;
-          if (dist < field_array_size)
-          {
-            xd += (xd - blob_center.x) * wall_field[dist];
-            zd += (zd - blob_center.z) * wall_field[dist];
-            blob_force.y += (yd + limit);
-          }
-          else
-          {
-            dist = field_array_size * (yd - limit) * (yd - limit) * 0.5;
-            if (dist < field_array_size)
+            normals[index].x = xd;
+            normals[index].y = yd;
+            normals[index].z = zd;
+
+            offset_x = 0.0;
+            offset_y = 0.0;
+            offset_z = 0.0;
+            strength = 0.0;
+            for ( i = 0; i < field_points; i++)
             {
-              xd += (xd - blob_center.x) * wall_field[dist];
-              zd += (zd - blob_center.z) * wall_field[dist];
-              blob_force.y -= (yd - limit);
+                xdist = field_data[i].pos.x - xd;
+                ydist = field_data[i].pos.y - yd;
+                zdist = field_data[i].pos.z - zd;
+                dist = field_array_size * (xdist * xdist + ydist * ydist
+                                           + zdist * zdist) * 0.1;
+
+                strength += PI * field_data[i].apower;
+
+                if (dist < field_array_size)
+                {
+                    offset_x += xd * field_data[i].apower * field[dist];
+                    offset_y += yd * field_data[i].apower * field[dist];
+                    offset_z += zd * field_data[i].apower * field[dist];
+
+                    blob_force.x += 1.0 * xd * field_data[i].apower * field[dist];
+                    blob_force.y += 1.0 * yd * field_data[i].apower * field[dist];
+                    blob_force.z += 1.0 * zd * field_data[i].apower * field[dist];
+
+                    strength *= 2.0 * field[dist];
+                }
+
+                if (incremental)
+                {
+                    xd += offset_x * freak * freak;
+                    yd += offset_y * freak * freak;
+                    zd += offset_z * freak * freak;
+                }
+                if (incremental == 1)
+                {
+                    offset_x = 0.0;
+                    offset_y = 0.0;
+                    offset_z = 0.0;
+                }
             }
-          }
-          
-          if (xd < -limit) xd = -limit;
-          if (xd > limit) xd = limit;
-
-          dist = field_array_size * (xd + limit) * (xd + limit) * 0.5;
-          if (dist < field_array_size)
-          {
-            yd += (yd - blob_center.y) * wall_field[dist];
-            zd += (zd - blob_center.z) * wall_field[dist];
-            blob_force.x += (xd + limit);
-          }
-          else
-          {
-            dist = field_array_size * (xd - limit) * (xd - limit) * 0.5;
-            if (dist < field_array_size)
+
+            if (incremental < 3)
             {
-              yd += (yd - blob_center.y) * wall_field[dist];
-              zd += (zd - blob_center.z) * wall_field[dist];
-              blob_force.x -= (xd - limit);
+                xd += offset_x;
+                yd += offset_y;
+                zd += offset_z;
             }
-          }
-          
-          if (yd < -limit) yd = -limit;
-          if (yd > limit) yd = limit;
+            xd += blob_center.x;
+            yd += blob_center.y;
+            zd += blob_center.z;
+
+            if (do_colour)
+            {
+                colours[index].red = 128 + (int)(sin(strength + colour_cycle * 0.01 + 2.0 * PI * x / row_data[y].num_x_points) * 127.0);
+                colours[index].green = 128 + (int)(cos(strength + colour_cycle * 0.025) * 127.0);
+                colours[index].blue = 128 + (int)(sin(strength + colour_cycle * 0.03 + 2.0 * PI * y / y_resolution) * 127.0);
+                colours[index].alpha = (int)(255.0 * fade);
+            }
+
+            /* Add walls */
+            if (do_walls)
+            {
+                if (zd < -limit) zd = -limit;
+                if (zd > limit) zd = limit;
+
+                dist = field_array_size * (zd + limit) * (zd + limit) * 0.5;
+                if (dist < field_array_size)
+                {
+                    xd += (xd - blob_center.x) * wall_field[dist];
+                    yd += (yd - blob_center.y) * wall_field[dist];
+                    blob_force.z += (zd + limit);
+                }
+                else
+                {
+                    dist = field_array_size * (zd - limit) * (zd - limit) * 0.5;
+                    if (dist < field_array_size)
+                    {
+                        xd += (xd - blob_center.x) * wall_field[dist];
+                        yd += (yd - blob_center.y) * wall_field[dist];
+                        blob_force.z -= (zd - limit);
+                    }
+
+                    if (yd < -limit) yd = -limit;
+                    if (yd > limit) yd = limit;
+
+                    dist = field_array_size * (yd + limit) * (yd + limit) * 0.5;
+                    if (dist < field_array_size)
+                    {
+                        xd += (xd - blob_center.x) * wall_field[dist];
+                        zd += (zd - blob_center.z) * wall_field[dist];
+                        blob_force.y += (yd + limit);
+                    }
+                    else
+                    {
+                        dist = field_array_size * (yd - limit) * (yd - limit) * 0.5;
+                        if (dist < field_array_size)
+                        {
+                            xd += (xd - blob_center.x) * wall_field[dist];
+                            zd += (zd - blob_center.z) * wall_field[dist];
+                            blob_force.y -= (yd - limit);
+                        }
+                    }
+
+                    if (xd < -limit) xd = -limit;
+                    if (xd > limit) xd = limit;
+
+                    dist = field_array_size * (xd + limit) * (xd + limit) * 0.5;
+                    if (dist < field_array_size)
+                    {
+                        yd += (yd - blob_center.y) * wall_field[dist];
+                        zd += (zd - blob_center.z) * wall_field[dist];
+                        blob_force.x += (xd + limit);
+                    }
+                    else
+                    {
+                        dist = field_array_size * (xd - limit) * (xd - limit) * 0.5;
+                        if (dist < field_array_size)
+                        {
+                            yd += (yd - blob_center.y) * wall_field[dist];
+                            zd += (zd - blob_center.z) * wall_field[dist];
+                            blob_force.x -= (xd - limit);
+                        }
+                    }
+
+                    if (yd < -limit) yd = -limit;
+                    if (yd > limit) yd = limit;
+                }
+            }
+
+            dots[index].x = xd;
+            dots[index].y = yd;
+            dots[index].z = zd;
         }
-      }
-        
-      dots[index].x = xd;
-      dots[index].y = yd;
-      dots[index].z = zd;
     }
-  }
-
-  /* Calculate the normals for each vertex and the texture mapping if required.
-   * Although the code actually calculates the normal for one of the triangles
-   * attached to a vertex rather than the vertex itself the results are not too
-   * bad for with a reasonable number of verticies.
-   */
-  for (y = 1; y < y_resolution - 1; y++)
-  {
-    int index1, index2, index3;
-    if (row_data[y - 1].num_x_points)
-    {
 
-      for (x = 0; x < row_data[y].num_x_points; x++)
-      {
-        if (x == row_data[y].num_x_points - 1)
+    /* Calculate the normals for each vertex and the texture mapping if required.
+     * Although the code actually calculates the normal for one of the triangles
+     * attached to a vertex rather than the vertex itself the results are not too
+     * bad for with a reasonable number of verticies.
+     */
+
+    /* The first point is treated as a special case since the loop expects to use
+     * points in the previous row to form the triangle.
+     */
+    index1 = 0;
+    index2 = y * x_resolution;
+    index3 = 1 + y * x_resolution;
+    calculate_normal (dots[index1], dots[index2], dots[index3], &normals[index1]);
+    if (do_texture)
+    {
+        if (offset_texture)
         {
-          index1 = y * x_resolution;
+            tex_coords[index1].x = dots[index1].x * 0.125 + 0.5
+                * (1.0 + 0.25 * asin(normals[index1].x) / (0.5 * PI));
+            tex_coords[index1].y = dots[index1].y * 0.125 + 0.5
+                * (1.0 + 0.25 * asin(normals[index1].y) / (0.5 * PI));
         }
         else
         {
-          index1 = x + 1 + y * x_resolution;
+            tex_coords[index1].x = 0.5 * (1.0 + (asin(normals[index1].x)
+                                                 / (0.5 * PI)));
+            tex_coords[index1].y = 0.5 * (1.0 + (asin(normals[index1].y)
+                                                 / (0.5 * PI)));
+        }
+        tex_coords[index1].x *= tex_width[current_texture];
+        tex_coords[index1].y *= tex_height[current_texture];
+    }
+
+    for (y = 1; y < y_resolution - 1; y++)
+    {
+        if (row_data[y - 1].num_x_points)
+        {
+            for (x = 0; x < row_data[y].num_x_points; x++)
+            {
+                if (x == row_data[y].num_x_points - 1)
+                {
+                    index1 = y * x_resolution;
+                }
+                else
+                {
+                    index1 = x + 1 + y * x_resolution;
+                }
+                index2 = x + y * x_resolution;
+                index3 = ((x + 0.5) * row_data[y - 1].num_x_points
+                          / row_data[y].num_x_points) + (y - 1) * x_resolution;
+                calculate_normal (dots[index1], dots[index2], dots[index3],
+                                  &normals[index1]);
+                if (do_texture)
+                {
+                    if (offset_texture)
+                    {
+                        tex_coords[index1].x = dots[index1].x * 0.125 + 0.5
+                            * (1.0 + 0.25 * asin(normals[index1].x) / (0.5 * PI));
+                        tex_coords[index1].y = dots[index1].y * 0.125 + 0.5
+                            * (1.0 + 0.25 * asin(normals[index1].y) / (0.5 * PI));
+                    }
+                    else
+                    {
+                        tex_coords[index1].x = 0.5 * (1.0 + (asin(normals[index1].x)
+                                                             / (0.5 * PI)));
+                        tex_coords[index1].y = 0.5 * (1.0 + (asin(normals[index1].y)
+                                                             / (0.5 * PI)));
+                    }
+                    tex_coords[index1].x *= tex_width[current_texture];
+                    tex_coords[index1].y *= tex_height[current_texture];
+                }
+            }
         }
-        index2 = x + y * x_resolution;
-        index3 = ((x + 0.5) * row_data[y - 1].num_x_points
-                  / row_data[y].num_x_points) + (y - 1) * x_resolution;
-        calculate_normal (dots[index1], dots[index2], dots[index3],
-                          &normals[index1]);
-        if (do_texture)
+    }
+    index1 = (y_resolution - 1) * x_resolution;
+    index2 = (y_resolution - 2) * x_resolution;
+    index3 = 1 + (y_resolution - 2) * x_resolution;
+    calculate_normal (dots[index1], dots[index2], dots[index3], &normals[index1]);
+    if (do_texture)
+    {
+        if (offset_texture)
         {
-          if (offset_texture)
-          {
             tex_coords[index1].x = dots[index1].x * 0.125 + 0.5
-              * (1.0 + 0.25 * asin(normals[index1].x) / (0.5 * PI));
+                * (1.0 + 0.25 * asin(normals[index1].x) / (0.5 * PI));
             tex_coords[index1].y = dots[index1].y * 0.125 + 0.5
-              * (1.0 + 0.25 * asin(normals[index1].y) / (0.5 * PI));
-          }
-          else
-          {
+                * (1.0 + 0.25 * asin(normals[index1].y) / (0.5 * PI));
+        }
+        else
+        {
             tex_coords[index1].x = 0.5 * (1.0 + (asin(normals[index1].x)
                                                  / (0.5 * PI)));
             tex_coords[index1].y = 0.5 * (1.0 + (asin(normals[index1].y)
                                                  / (0.5 * PI)));
-          }
-          tex_coords[index1].x *= tex_width[current_texture];
-          tex_coords[index1].y *= tex_height[current_texture];
         }
-      }
+        tex_coords[index1].x *= tex_width[current_texture];
+        tex_coords[index1].y *= tex_height[current_texture];
     }
-  }
-
-  freak += v_freak;
-  v_freak += -freak / 2000000.0;
-
-  /* Update position and strength of points used to distort the blob */
-  for (i = 0; i < field_points; i++)
-  {
-    field_data[i].vx += field_data[i].mx*(field_data[i].cx - field_data[i].ax);
-    field_data[i].vy += field_data[i].my*(field_data[i].cy - field_data[i].ay);
-    field_data[i].vpower += field_data[i].mpower
-      * (field_data[i].cpower - field_data[i].apower);
-
-    field_data[i].ax += 0.1 * field_data[i].vx;
-    field_data[i].ay += 0.1 * field_data[i].vy;
-    field_data[i].apower += 0.1 * field_data[i].vpower;
-
-    field_data[i].pos.x = 1.5 * sin(PI * field_data[i].ay)
-      * cos(PI * field_data[i].ax);
-    field_data[i].pos.y = 1.5 * cos(PI * field_data[i].ay);
-    field_data[i].pos.z = 1.5 * sin(PI * field_data[i].ay)
-      * sin(PI * field_data[i].ax);
-  }
-        
-  /* Update the center of the whole blob */
-  blob_velocity.x += (blob_anchor.x - blob_center.x) / 80.0
-    + 0.01 * blob_force.x / num_points;
-  blob_velocity.y += (blob_anchor.y - blob_center.y) / 80.0
-    + 0.01 * blob_force.y / num_points;
-  blob_velocity.z += (blob_anchor.z - blob_center.z) / 80.0
-    + 0.01 * blob_force.z / num_points;
-
-  blob_center.x += blob_velocity.x * 0.5;
-  blob_center.y += blob_velocity.y * 0.5;
-  blob_center.z += blob_velocity.z * 0.5;
-
-  blob_velocity.x *= 0.99;
-  blob_velocity.y *= 0.99;
-  blob_velocity.z *= 0.99;
+
+
+    freak += v_freak;
+    v_freak += -freak / 2000000.0;
+
+    /* Update the center of the whole blob */
+    blob_velocity.x += (blob_anchor.x - blob_center.x) / 80.0
+        + 0.01 * blob_force.x / num_points;
+    blob_velocity.y += (blob_anchor.y - blob_center.y) / 80.0
+        + 0.01 * blob_force.y / num_points;
+    blob_velocity.z += (blob_anchor.z - blob_center.z) / 80.0
+        + 0.01 * blob_force.z / num_points;
+
+    blob_center.x += blob_velocity.x * 0.5;
+    blob_center.y += blob_velocity.y * 0.5;
+    blob_center.z += blob_velocity.z * 0.5;
+
+    blob_velocity.x *= 0.99;
+    blob_velocity.y *= 0.99;
+    blob_velocity.z *= 0.99;
 }
 
 /******************************************************************************
@@ -939,78 +1020,78 @@ calc_blob(int width,
  * with the more interesting bits of the code.
  */
 static void
-draw_blob (void) 
+draw_blob (void)
 {
-  int x, y, x2, x3;
-  int index1, index2, index3;
-  int lower, upper;
+    int x, y, x2, x3;
+    int index1, index2, index3;
+    int lower, upper;
 
-  glMatrixMode (GL_MODELVIEW);
-  glLoadIdentity ();
+    glMatrixMode (GL_MODELVIEW);
+    glLoadIdentity ();
 
-  /* Move down the z-axis. */
-  glTranslatef( 0.0, 0.0, -5.0 );
+    /* Move down the z-axis. */
+    glTranslatef (0.0, 0.0, -5.0 );
 
-  for (y = 1; y < y_resolution; y++)
-  {
-    if (row_data[y - 1].num_x_points)
+    for (y = 1; y < y_resolution; y++)
     {
-      for (x = 0; x < row_data[y].num_x_points; x++)
-      {
-        glBegin (GL_TRIANGLES);
-        if (x == row_data[y].num_x_points - 1)
+        if (row_data[y - 1].num_x_points)
         {
-          index1 = y * x_resolution;
-        }
-        else
-        {
-          index1 = x + 1 + y * x_resolution;
-        }
-        index2 = x + y * x_resolution;
-        index3 = ((x + 0.5) * row_data[y - 1].num_x_points
-                  / row_data[y].num_x_points) + (y - 1) * x_resolution;
-        glArrayElement(index1);
-        glArrayElement(index2);
-        glArrayElement(index3);
-        glEnd();
-
-        lower = floorf((x - 0.5) * row_data[y - 1].num_x_points
-                       / (float)row_data[y].num_x_points);
-        upper = floorf((x + 0.5) * row_data[y - 1].num_x_points
-                       / (float)row_data[y].num_x_points);
-
-        if (upper > lower)
-        {
-          glBegin (GL_TRIANGLE_FAN);
-          index1 = x + y * x_resolution;
-          
-          for (x2 = lower; x2 <= upper; x2++)
-          {
-            x3 = x2;
-            while (x3 < 0) x3 += row_data[y - 1].num_x_points;
-            while (x3 >= row_data[y - 1].num_x_points)
-              x3 -= row_data[y - 1].num_x_points;
-            index2 = x3 + (y - 1) * x_resolution;
-
-            if (x2 < upper)
+            for (x = 0; x < row_data[y].num_x_points; x++)
             {
-              x3 = x2 + 1;
-              while (x3 < 0) x3 += row_data[y - 1].num_x_points;
-              while (x3 >= row_data[y - 1].num_x_points)
-                x3 -= row_data[y - 1].num_x_points;
-              index3 = x3 + (y - 1) * x_resolution;
-              if (x2 == lower)
-              {
+                glBegin (GL_TRIANGLES);
+                if (x == row_data[y].num_x_points - 1)
+                {
+                    index1 = y * x_resolution;
+                }
+                else
+                {
+                    index1 = x + 1 + y * x_resolution;
+                }
+                index2 = x + y * x_resolution;
+                index3 = ((x + 0.5) * row_data[y - 1].num_x_points
+                          / row_data[y].num_x_points) + (y - 1) * x_resolution;
                 glArrayElement(index1);
-              }
+                glArrayElement(index2);
+                glArrayElement(index3);
+                glEnd();
+
+                lower = floorf((x - 0.5) * row_data[y - 1].num_x_points
+                               / (float)row_data[y].num_x_points);
+                upper = floorf((x + 0.5) * row_data[y - 1].num_x_points
+                               / (float)row_data[y].num_x_points);
+
+                if (upper > lower)
+                {
+                    glBegin (GL_TRIANGLE_FAN);
+                    index1 = x + y * x_resolution;
+
+                    for (x2 = lower; x2 <= upper; x2++)
+                    {
+                        x3 = x2;
+                        while (x3 < 0) x3 += row_data[y - 1].num_x_points;
+                        while (x3 >= row_data[y - 1].num_x_points)
+                            x3 -= row_data[y - 1].num_x_points;
+                        index2 = x3 + (y - 1) * x_resolution;
+
+                        if (x2 < upper)
+                        {
+                            x3 = x2 + 1;
+                            while (x3 < 0) x3 += row_data[y - 1].num_x_points;
+                            while (x3 >= row_data[y - 1].num_x_points)
+                                x3 -= row_data[y - 1].num_x_points;
+                            index3 = x3 + (y - 1) * x_resolution;
+                            if (x2 == lower)
+                            {
+                                glArrayElement(index1);
+                            }
+                        }
+                        glArrayElement(index2);
+                    }
+                    glEnd ();
+                }
             }
-            glArrayElement(index2);
-          }
-          glEnd ();
         }
-      }
     }
-  }
 }
 
 /******************************************************************************
@@ -1020,37 +1101,37 @@ draw_blob (void)
 static void
 draw_background (ModeInfo *mi)
 {
-  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
-  glEnable (GL_TEXTURE_2D);    
-  glDisable(GL_LIGHTING);
+    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+    glEnable (GL_TEXTURE_2D);
+    glDisable(GL_LIGHTING);
 
-  /* Reset the projection matrix to make it easier to get the size of the quad
-   * correct
-   */
-  glMatrixMode(GL_PROJECTION);
-  glPushMatrix();
-  glLoadIdentity();
+    /* Reset the projection matrix to make it easier to get the size of the quad
+     * correct
+     */
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
 
-  glOrtho(0.0, MI_WIDTH(mi), MI_HEIGHT(mi), 0.0, -1000.0, 1000.0);
+    glOrtho(0.0, MI_WIDTH(mi), MI_HEIGHT(mi), 0.0, -1000.0, 1000.0);
 
-  glBegin (GL_QUADS);
-    
-  glTexCoord2f (0.0, tex_height[current_texture]);
-  glVertex2i (0, 0);
-    
-  glTexCoord2f (0.0, 0.0);
-  glVertex2i (0, MI_HEIGHT(mi));
+    glBegin (GL_QUADS);
     
-  glTexCoord2f (tex_width[current_texture], 0.0);
-  glVertex2i (MI_WIDTH(mi), MI_HEIGHT(mi));
+    glTexCoord2f (0.0, tex_height[current_texture]);
+    glVertex2i (0, 0);
     
-  glTexCoord2f (tex_width[current_texture], tex_height[current_texture]);
-  glVertex2i (MI_WIDTH(mi), 0);
-  glEnd();
+    glTexCoord2f (0.0, 0.0);
+    glVertex2i (0, MI_HEIGHT(mi));
 
-  glPopMatrix ();
-  glMatrixMode (GL_MODELVIEW);
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    glTexCoord2f (tex_width[current_texture], 0.0);
+    glVertex2i (MI_WIDTH(mi), MI_HEIGHT(mi));
+
+    glTexCoord2f (tex_width[current_texture], tex_height[current_texture]);
+    glVertex2i (MI_WIDTH(mi), 0);
+    glEnd();
+
+    glPopMatrix ();
+    glMatrixMode (GL_MODELVIEW);
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 }
 
 /******************************************************************************
@@ -1058,193 +1139,247 @@ draw_background (ModeInfo *mi)
  * Update the scene.
  */
 static GLvoid
-drawScene(ModeInfo * mi) 
+draw_scene(ModeInfo * mi)
 {
-  check_gl_error ("drawScene");
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    double fade = 0.0;
+    double current_time;
+    check_gl_error ("draw_scene");
 
-  glDisable (GL_BLEND);
+    glColor4d(1.0, 1.0, 1.0, 1.0);
 
-  /* Ensure the background is drawn with the correct texture */
-  if (do_texture)
-  {
-    glBindTexture (GL_TEXTURE_2D, textures[current_texture]);
-  }
+    current_time = double_time();
+    switch (state)
+    {
+    case TRANSITIONING:
+        fade = (current_time - state_start_time) / fade_time;
+        break;
 
-  glColor4ub(255, 255, 255, 255);
-  if (do_paint_background && !do_wire)
-  {
-    draw_background (mi);
+    case HOLDING:
+        fade = 0.0;
+        break;
+    }
 
-    /* When transitioning between two images paint the new image over the old
-     * image with a varying alpha value to get a smooth fade.
+
+    /* Set the correct texture, when transitioning this ensures that the first draw
+     * is the original texture (which has the new texture drawn over it with decreasing
+     * transparency)
      */
-    if (transitioning)
+    if (do_texture)
     {
-      glDisable (GL_DEPTH_TEST);
-      glEnable (GL_BLEND);
-      glBindTexture (GL_TEXTURE_2D, textures[1 - current_texture]);
-      glColor4ub (255, 255, 255, transitioning);
-
-      draw_background (mi);
-
       glBindTexture (GL_TEXTURE_2D, textures[current_texture]);
-      glEnable (GL_DEPTH_TEST);
     }
-    /* Clear the depth buffer bit so the backgound is behind the blob */
-    glClear(GL_DEPTH_BUFFER_BIT);
-  }
-  else
-  {
-    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  }
 
-  calc_blob(MI_WIDTH(mi), MI_HEIGHT(mi), 1024, 2.5);
+    if (do_paint_background && !do_wire)
+    {
+        glClear(GL_DEPTH_BUFFER_BIT);
+        if (motion_blur)
+        {
+            glEnable (GL_BLEND);
+            glColor4ub (255, 255, 255, motion_blur);
+        }
+        draw_background (mi);
 
-  glEnable(GL_LIGHTING);
-  glEnable(GL_LIGHT0);
-  glEnable(GL_LIGHT1);
+        /* When transitioning between two images paint the new image over the old
+         * image with a varying alpha value to get a smooth fade.
+         */
+        if (state == TRANSITIONING)
+        {
+            glDisable (GL_DEPTH_TEST);
+            glEnable (GL_BLEND);
+            /* Select the texture to transition to */
+            glBindTexture (GL_TEXTURE_2D, textures[1 - current_texture]);
+            glColor4d (1.0, 1.0, 1.0, fade);
+
+            draw_background (mi);
 
-  if (do_blend)
-  {
-    glEnable (GL_BLEND);
-    if (transitioning)
+            /* Select the original texture to draw the blob */
+            glBindTexture (GL_TEXTURE_2D, textures[current_texture]);
+            glEnable (GL_DEPTH_TEST);
+        }
+        /* Clear the depth buffer bit so the backgound is behind the blob */
+        glClear(GL_DEPTH_BUFFER_BIT);
+    }
+    else if (motion_blur)
     {
-      glColor4ub (255, 255, 255, 128 - transitioning / 2);
+        glDisable (GL_DEPTH_TEST);
+        glEnable (GL_BLEND);
+        glColor4ub (0, 0, 0, motion_blur);
+        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+        glRectd (-10.0, -10.0, 10.0, 10.0);
+        if (do_wire)
+        {
+            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+        }
+        glEnable (GL_DEPTH_TEST);
+        glClear (GL_DEPTH_BUFFER_BIT);
     }
     else
     {
-      glColor4ub (255, 255, 255, 128);
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     }
-  }
-  else
-  {
-    glDisable (GL_BLEND);
-    glColor4ub (255, 255, 255, 255);
-  }
-  draw_blob();
-
-  /* While transitioning draw the blob twice with a modified alpha channel.
-   * The trasitioning state machine is very crude, it simply counts frames
-   * rather than elapsed time but it works.
-   */
-  if (do_texture)
-  {
-    if (transitioning)
+
+    if (do_blend)
     {
-      glClear(GL_DEPTH_BUFFER_BIT);
-      glEnable (GL_BLEND);
-      glBindTexture (GL_TEXTURE_2D, textures[1 - current_texture]);
-      if (do_blend)
-      {
-        glColor4ub (255, 255, 255, transitioning / 2);
-      }
-      else
-      {
-        glColor4ub (255, 255, 255, transitioning);
-      }
-      draw_blob ();
-      transitioning += fade_speed;
-      if (transitioning > 255)
-      {
-        transitioning = 0;
-        current_texture = 1 - current_texture;
-        holding = 1;
-      }
+        fade = fade * 0.5;
     }
-    if (holding)
+
+    calc_blob(MI_WIDTH(mi), MI_HEIGHT(mi), 1024, 2.5, fade);
+
+    glEnable(GL_LIGHTING);
+    glEnable(GL_LIGHT0);
+    glEnable(GL_LIGHT1);
+
+    if (do_blend)
+    {
+        glEnable (GL_BLEND);
+        if (do_colour)
+        {
+            glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+        }
+        else
+        {
+            glColor4d (1.0, 1.0, 1.0, 0.5 - fade);
+        }
+    }
+    else
     {
-      holding++;
-      if (holding > hold_frames)
-      {
-        grab_texture (mi, 1 - current_texture);
-        transitioning = 1;
-        holding = 0;
-      }
+        glDisable (GL_BLEND);
+        glColor4d (1.0, 1.0, 1.0, 1.0);
     }
-  }
-  
-  /* increment frame-counter */
-/*  frame++; */
+    draw_blob();
 
-/*  check_gl_error ("drawScene"); */
-}
+    if (do_blend && do_colour)
+    {
+        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    }
+
+    /* While transitioning draw a second blob twice with a modified alpha channel.
+     * The trasitioning state machine is very crude, it simply counts frames
+     * rather than elapsed time but it works.
+     */
+    if (do_texture && (hold_time > 0))
+    {
+        switch (state)
+        {
+        case TRANSITIONING:
+            glClear(GL_DEPTH_BUFFER_BIT);
+            glEnable (GL_BLEND);
+            /* Select the texture to transition to */
+            glBindTexture (GL_TEXTURE_2D, textures[1 - current_texture]);
+            glColor4d (1.0, 1.0, 1.0, fade);
+            draw_blob ();
+
+            if ((current_time - state_start_time) > fade_time)
+            {
+                state = HOLDING;
+                state_start_time = current_time;
+                current_texture = 1 - current_texture;
+            }
+            break;
 
+        case HOLDING:
+            if ((current_time - state_start_time) > hold_time)
+            {
+                grab_texture (mi, 1 - current_texture);
+                state = TRANSITIONING;
+                /* Get the time again rather than using the current time so
+                 * that the time taken by the grab_texture function is not part
+                 * of the fade time
+                 */
+                state_start_time = double_time();
+            }
+            break;
+        }
+    }
+}
 
+/******************************************************************************
+ *
+ * XScreensaver screen update entry
+ */
 void
-draw_mirrorblob(ModeInfo * mi)
+draw_screensaver(ModeInfo * mi)
 {
-  screensaverstruct *gp = &Screensaver[MI_SCREEN(mi)];
-  Display    *display = MI_DISPLAY(mi);
-  Window      window = MI_WINDOW(mi);
+    screensaverstruct *gp = &Screensaver[MI_SCREEN(mi)];
+    Display    *display = MI_DISPLAY(mi);
+    Window      window = MI_WINDOW(mi);
 
-  if (!gp->glx_context)
-       return;
+    if (!gp->glx_context)
+        return;
 
-  glXMakeCurrent(display, window, *(gp->glx_context));
-  drawScene(mi);
-  if (mi->fps_p) do_fps (mi);
-  glXSwapBuffers(display, window);
+    glXMakeCurrent(display, window, *(gp->glx_context));
+    draw_scene(mi);
+    if (mi->fps_p) do_fps (mi);
+    glXSwapBuffers(display, window);
 }
 
-/* Standard reshape function */
+/******************************************************************************
+ *
+ * XScreensaver screen resize entry
+ */
 void
-reshape_mirrorblob(ModeInfo *mi, int width, int height)
+reshape_screensaver(ModeInfo *mi, int width, int height)
 {
-  glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) );
-  resetProjection(width, height);
+    glViewport( 0, 0, MI_WIDTH(mi), MI_HEIGHT(mi) );
+    reset_projection(width, height);
 }
 
+/******************************************************************************
+ *
+ * XScreensaver initialise entry
+ */
 void
-init_mirrorblob(ModeInfo * mi)
+init_screensaver(ModeInfo * mi)
 {
-  int screen = MI_SCREEN(mi);
-
-  screensaverstruct *gp;
-
-  if (Screensaver == NULL) {
-       if ((Screensaver = (screensaverstruct *)
-         calloc(MI_NUM_SCREENS(mi), sizeof (screensaverstruct))) == NULL)
-         return;
-  }
-  gp = &Screensaver[screen];
-
-  gp->window = MI_WINDOW(mi);
-  if ((gp->glx_context = init_GL(mi)) != NULL) {
-       reshape_mirrorblob(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-       initializeGL(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-  } else {
-       MI_CLEARWINDOW(mi);
-  }
-  /* Set the environment variable used by NVIDIA cards to control updating
-   * during the blankning interval */ 
-  setenv ("__GL_SYNC_TO_VBLANK", "1", 1);
-  setenv ("__GL_FSAA_MODE", "1", 1);
-
-  initialise_blob(MI_WIDTH(mi), MI_HEIGHT(mi), 1024);
-}
+    int screen = MI_SCREEN(mi);
 
+    screensaverstruct *gp;
+
+    if (Screensaver == NULL)
+    {
+        if ((Screensaver = (screensaverstruct *)
+             calloc(MI_NUM_SCREENS(mi), sizeof (screensaverstruct))) == NULL)
+        {
+            return;
+        }
+    }
+    gp = &Screensaver[screen];
 
-/* all sorts of nice cleanup code should go here! */
-void release_mirrorblob(ModeInfo * mi)
+    gp->window = MI_WINDOW(mi);
+    if ((gp->glx_context = init_GL(mi)) != NULL)
+    {
+        reshape_screensaver(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+        initialize_gl(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+    }
+    else
+    {
+        MI_CLEARWINDOW(mi);
+    }
+
+    initialise_blob(MI_WIDTH(mi), MI_HEIGHT(mi), 1024);
+    state_start_time = double_time();
+}
+
+/******************************************************************************
+ *
+ * XScreensaver cleanup entry
+ */
+void
+release_screensaver(ModeInfo * mi)
 {
-  int screen;
-
-  if (row_data) free(row_data);
-  if (field_data) free(field_data);
-  if (colours) free(colours);
-  if (tex_coords) free(tex_coords);
-  if (dots) free(dots);
-  if (wall_field) free(wall_field);
-  if (field) free(field);
-
-  if (Screensaver != NULL) {
-       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-/*       screensaverstruct *gp = &Screensaver[screen];*/
-       }
-       (void) free((void *) Screensaver);
-       Screensaver = NULL;
-  }
-  FreeAllGL(mi);
+    if (row_data) free(row_data);
+    if (field_data) free(field_data);
+    if (colours) free(colours);
+    if (tex_coords) free(tex_coords);
+    if (dots) free(dots);
+    if (wall_field) free(wall_field);
+    if (field) free(field);
+
+    if (Screensaver != NULL)
+    {
+        (void) free((void *) Screensaver);
+        Screensaver = NULL;
+    }
+    FreeAllGL(mi);
 }
 #endif