http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.tar.gz
[xscreensaver] / hacks / glx / lament.c
index 3f5080c04d0b0b0650b988c7df94d29c732c7850..4c80da596e0e83d02be624c0632730f8f0a9a97c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1998 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1998-2004 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 
      *  Needs music.  ("Hellraiser Themes" by Coil: TORSO CD161; also
         duplicated on the "Unnatural History 2" compilation, WORLN M04699.)
-
-     *  I'm not totally happy with the spinning motion; I like the
-        acceleration and deceleration, but it often feels like it's going too
-        fast, or not naturally enough, or something.
-
-     *  However, the motion is better than that used by gears, superquadrics,
-        etc.; so maybe I should make them all share the same motion code.
  */
 
-#include <X11/Intrinsic.h>
-
-#define PROGCLASS      "Lament"
-#define HACK_INIT      init_lament
-#define HACK_DRAW      draw_lament
-#define HACK_RESHAPE   reshape_lament
-#define lament_opts    xlockmore_opts
-#define DEFAULTS       "*delay:        10000   \n"     \
+#define DEFAULTS       "*delay:        20000   \n"     \
                        "*showFPS:      False   \n"     \
-                       "*wireframe:    False   \n"     \
-                       "*texture:      True    \n"
+                       "*wireframe:    False   \n"
+# define refresh_lament 0
+# define release_lament 0
 #include "xlockmore.h"
 
 #ifdef USE_GL /* whole file */
 #define DEF_TEXTURE "True"
 
 static int do_texture;
+
 static XrmOptionDescRec opts[] = {
-  {"-texture", ".lament.texture", XrmoptionNoArg, (caddr_t) "true" },
-  {"+texture", ".lament.texture", XrmoptionNoArg, (caddr_t) "false" },
+  {"-texture", ".lament.texture", XrmoptionNoArg, "true" },
+  {"+texture", ".lament.texture", XrmoptionNoArg, "false" },
 };
 
 static argtype vars[] = {
-  {(caddr_t *) &do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
+  {&do_texture, "texture", "Texture", DEF_TEXTURE, t_Bool},
 };
 
-ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
+ENTRYPOINT ModeSpecOpt lament_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
+#include "normals.h"
 #include "xpm-ximage.h"
+#include "rotator.h"
+#include "gltrackball.h"
 #include "../images/lament.xpm"
 
 #define RAND(n) ((long) ((random() & 0x7fffffff) % ((long) (n))))
@@ -140,20 +131,26 @@ typedef enum {
 
 } lament_type;
 
-static GLfloat exterior_color[] = { 0.33, 0.22, 0.03, 1.00,  /* ambient    */
-                                    0.78, 0.57, 0.11, 1.00,  /* specular   */
-                                    0.99, 0.91, 0.81, 1.00,  /* diffuse    */
-                                   27.80                     /* shininess  */
-                                  };
-static GLfloat interior_color[] = { 0.20, 0.20, 0.15, 1.00,  /* ambient    */
-                                    0.40, 0.40, 0.32, 1.00,  /* specular   */
-                                    0.99, 0.99, 0.81, 1.00,  /* diffuse    */
-                                   50.80                     /* shininess  */
-                                  };
+static const GLfloat exterior_color[] =
+ { 0.33, 0.22, 0.03, 1.00,  /* ambient    */
+   0.78, 0.57, 0.11, 1.00,  /* specular   */
+   0.99, 0.91, 0.81, 1.00,  /* diffuse    */
+   27.80                   /* shininess  */
+ };
+static const GLfloat interior_color[] =
+ { 0.20, 0.20, 0.15, 1.00,  /* ambient    */
+   0.40, 0.40, 0.32, 1.00,  /* specular   */
+   0.99, 0.99, 0.81, 1.00,  /* diffuse    */
+   50.80                    /* shininess  */
+ };
 
 
 typedef struct {
   GLXContext *glx_context;
+  rotator *rot;
+  double rotx, roty, rotz;
+  trackball_state *trackball;
+  Bool button_down_p;
 
   GLuint box;                     /* display list IDs */
   GLuint star1, star2;
@@ -161,10 +158,6 @@ typedef struct {
   GLuint lid_0, lid_1, lid_2, lid_3, lid_4;
   GLuint taser_base, taser_lifter, taser_slider;
 
-  GLfloat rotx, roty, rotz;       /* current object rotation */
-  GLfloat dx, dy, dz;             /* current rotational velocity */
-  GLfloat ddx, ddy, ddz;          /* current rotational acceleration */
-  GLfloat d_max;                  /* max velocity */
   XImage *texture;                /* image bits */
   GLuint texids[6];               /* texture map IDs */
   lament_type type;               /* which mode of the object is current */
@@ -172,6 +165,9 @@ typedef struct {
   int anim_pause;                 /* countdown before animating again */
   GLfloat anim_r, anim_y, anim_z;  /* relative position during anims */
 
+  int state, nstates;
+  lament_type *states;
+
 } lament_configuration;
 
 static lament_configuration *lcs = NULL;
@@ -193,99 +189,12 @@ parse_image_data(ModeInfo *mi)
                               lament_faces);
 }
 
-\f
-/* Computing normal vectors (thanks to Nat Friedman <ndf@mit.edu>)
- */
-
-typedef struct vector {
-  GLfloat x, y, z;
-} vector;
-
-typedef struct plane {
-  vector p1, p2, p3;
-} plane;
-
-static void
-vector_set(vector *v, GLfloat x, GLfloat y, GLfloat z)
-{
-  v->x = x;
-  v->y = y;
-  v->z = z;
-}
-
-static void
-vector_cross(vector v1, vector v2, vector *v3)
-{
-  v3->x = (v1.y * v2.z) - (v1.z * v2.y);
-  v3->y = (v1.z * v2.x) - (v1.x * v2.z);
-  v3->z = (v1.x * v2.y) - (v1.y * v2.x);
-}
-
-static void
-vector_subtract(vector v1, vector v2, vector *res)
-{
-  res->x = v1.x - v2.x;
-  res->y = v1.y - v2.y;
-  res->z = v1.z - v2.z;
-}
-
-static void
-plane_normal(plane p, vector *n)
-{
-  vector v1, v2;
-  vector_subtract(p.p1, p.p2, &v1);
-  vector_subtract(p.p1, p.p3, &v2);
-  vector_cross(v2, v1, n);
-}
-
-static void
-do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
-         GLfloat x2, GLfloat y2, GLfloat z2,
-         GLfloat x3, GLfloat y3, GLfloat z3)
-{
-  plane plane;
-  vector n;
-  vector_set(&plane.p1, x1, y1, z1);
-  vector_set(&plane.p2, x2, y2, z2);
-  vector_set(&plane.p3, x3, y3, z3);
-  plane_normal(plane, &n);
-  n.x = -n.x; n.y = -n.y; n.z = -n.z;
-
-  glNormal3f(n.x, n.y, n.z);
-
-#ifdef DEBUG
-  /* Draw a line in the direction of this face's normal. */
-  {
-    GLfloat ax = n.x > 0 ? n.x : -n.x;
-    GLfloat ay = n.y > 0 ? n.y : -n.y;
-    GLfloat az = n.z > 0 ? n.z : -n.z;
-    GLfloat mx = (x1 + x2 + x3) / 3;
-    GLfloat my = (y1 + y2 + y3) / 3;
-    GLfloat mz = (z1 + z2 + z3) / 3;
-    GLfloat xx, yy, zz;
-
-    GLfloat max = ax > ay ? ax : ay;
-    if (az > max) max = az;
-    max *= 2;
-    xx = n.x / max;
-    yy = n.y / max;
-    zz = n.z / max;
-
-    glBegin(GL_LINE_LOOP);
-    glVertex3f(mx, my, mz);
-    glVertex3f(mx+xx, my+yy, mz+zz);
-    glEnd();
-  }
-#endif /* DEBUG */
-}
-
-
 \f
 /* Shorthand utilities for making faces, with proper normals.
  */
 
 static void
-set_colors (GLfloat *color)
+set_colors (const GLfloat *color)
 {
   glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
   glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
@@ -294,7 +203,7 @@ set_colors (GLfloat *color)
 }
 
 static void
-face3(GLint texture, GLfloat *color, Bool wire,
+face3(GLint texture, const GLfloat *color, Bool wire,
       GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
       GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
       GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3)
@@ -313,7 +222,7 @@ face3(GLint texture, GLfloat *color, Bool wire,
 }
 
 static void
-face4(GLint texture, GLfloat *color, Bool wire,
+face4(GLint texture, const GLfloat *color, Bool wire,
       GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
       GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
       GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
@@ -333,7 +242,7 @@ face4(GLint texture, GLfloat *color, Bool wire,
 }
 
 static void
-face5(GLint texture, GLfloat *color, Bool wire,
+face5(GLint texture, const GLfloat *color, Bool wire,
       GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
       GLfloat s2, GLfloat t2, GLfloat x2, GLfloat y2, GLfloat z2,
       GLfloat s3, GLfloat t3, GLfloat x3, GLfloat y3, GLfloat z3,
@@ -1403,6 +1312,49 @@ taser(ModeInfo *mi, Bool wire)
 /* Rendering and animating object models
  */
 
+ENTRYPOINT Bool
+lament_handle_event (ModeInfo *mi, XEvent *event)
+{
+  lament_configuration *lc = &lcs[MI_SCREEN(mi)];
+
+  if (event->xany.type == ButtonPress &&
+      event->xbutton.button == Button1)
+    {
+      lc->button_down_p = True;
+      gltrackball_start (lc->trackball,
+                         event->xbutton.x, event->xbutton.y,
+                         MI_WIDTH (mi), MI_HEIGHT (mi));
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease &&
+           event->xbutton.button == Button1)
+    {
+      lc->button_down_p = False;
+      return True;
+    }
+  else if (event->xany.type == ButtonPress &&
+           (event->xbutton.button == Button4 ||
+            event->xbutton.button == Button5 ||
+            event->xbutton.button == Button6 ||
+            event->xbutton.button == Button7))
+    {
+      gltrackball_mousewheel (lc->trackball, event->xbutton.button, 5,
+                              !!event->xbutton.state);
+      return True;
+    }
+  else if (event->xany.type == MotionNotify &&
+           lc->button_down_p)
+    {
+      gltrackball_track (lc->trackball,
+                         event->xmotion.x, event->xmotion.y,
+                         MI_WIDTH (mi), MI_HEIGHT (mi));
+      return True;
+    }
+
+  return False;
+}
+
+
 static void
 draw(ModeInfo *mi)
 {
@@ -1415,24 +1367,14 @@ draw(ModeInfo *mi)
     glClear(GL_COLOR_BUFFER_BIT);
 
   glPushMatrix();
-  {
-    GLfloat x = lc->rotx;
-    GLfloat y = lc->roty;
-    GLfloat z = lc->rotz;
 
-#if 0
- x=0.75; y=0; z=0; 
-#endif
+  gltrackball_rotate (lc->trackball);
 
-    if (x < 0) x = 1 - (x + 1);
-    if (y < 0) y = 1 - (y + 1);
-    if (z < 0) z = 1 - (z + 1);
+  /* Make into the screen be +Y right be +X, and up be +Z. */
+  glRotatef(-90.0, 1.0, 0.0, 0.0);
 
-    /* Make into the screen be +Y right be +X, and up be +Z. */
-    glRotatef(-90.0, 1.0, 0.0, 0.0);
-
-    /* Scale it up. */
-    glScalef(4.0, 4.0, 4.0);
+  /* Scale it up. */
+  glScalef(4.0, 4.0, 4.0);
 
 #ifdef DEBUG
     glPushMatrix();
@@ -1458,9 +1400,12 @@ draw(ModeInfo *mi)
     glPushMatrix();
     {
       /* Apply rotation to the object. */
-      glRotatef(x * 360, 1.0, 0.0, 0.0);
-      glRotatef(y * 360, 0.0, 1.0, 0.0);
-      glRotatef(z * 360, 0.0, 0.0, 1.0);
+      if (lc->type != LAMENT_LID_ZOOM)
+        get_rotation (lc->rot, &lc->rotx, &lc->roty, &lc->rotz,
+                      !lc->button_down_p);
+      glRotatef (lc->rotx * 360, 1.0, 0.0, 0.0);
+      glRotatef (lc->roty * 360, 0.0, 1.0, 0.0);
+      glRotatef (lc->rotz * 360, 0.0, 0.0, 1.0);
 
       switch (lc->type)
        {
@@ -1570,11 +1515,29 @@ draw(ModeInfo *mi)
     }
     glPopMatrix();
 
-  }
   glPopMatrix();
 }
 
 
+/* Rather than just picking states randomly, pick an ordering randomly, do it,
+   and then re-randomize.  That way one can be assured of seeing all states in
+   a short time period, though not always in the same order (it's frustrating
+   to see it pick the same state 5x in a row.)
+ */
+static void
+shuffle_states (lament_configuration *lc)
+{
+  int i;
+  for (i = 0; i < lc->nstates; i++)
+    {
+      int a = random() % lc->nstates;
+      lament_type swap = lc->states[a];
+      lc->states[a] = lc->states[i];
+      lc->states[i] = swap;
+    }
+}
+
+
 static void
 animate(ModeInfo *mi)
 {
@@ -1587,38 +1550,13 @@ animate(ModeInfo *mi)
     {
     case LAMENT_BOX:
       {
-       /* Rather than just picking states randomly, pick an ordering randomly,
-          do it, and then re-randomize.  That way one can be assured of seeing
-          all states in a short time period, though not always in the same
-          order (it's frustrating to see it pick the same state 5x in a row.)
-        */
-       static lament_type states[] = {
-         LAMENT_STAR_OUT, LAMENT_STAR_OUT,
-         LAMENT_TETRA_UNE, LAMENT_TETRA_USW,
-         LAMENT_TETRA_DWN, LAMENT_TETRA_DSE,
-         LAMENT_LID_OPEN, LAMENT_LID_OPEN, LAMENT_LID_OPEN,
-         LAMENT_TASER_OUT, LAMENT_TASER_OUT,
-         LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
-         LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX, LAMENT_BOX,
-       };
-       static int state = countof(states);
-
-       if (state < countof(states))
-         {
-           lc->type = states[state++];
-         }
-       else
-         {
-           int i;
-           state = 0;
-           for (i = 0; i < countof(states); i++)
-             {
-               int a = random() % countof(states);
-               lament_type swap = states[a];
-               states[a] = states[i];
-               states[i] = swap;
-             }
-         }
+        lc->state++;
+        if (lc->state >= lc->nstates)
+          {
+            shuffle_states (lc);
+            lc->state = 0;
+          }
+        lc->type = lc->states[lc->state];
 
        if (lc->type == LAMENT_BOX)
          lc->anim_pause = pause3;
@@ -1764,9 +1702,6 @@ animate(ModeInfo *mi)
        {
          lc->anim_r = 0.0;
          lc->anim_z = 0.0;
-         lc->rotx = frand(1.0) * RANDSIGN();
-         lc->roty = frand(1.0) * RANDSIGN();
-         lc->rotz = frand(1.0) * RANDSIGN();
          lc->type = LAMENT_BOX;
        }
       break;
@@ -1820,78 +1755,11 @@ animate(ModeInfo *mi)
 }
 
 
-static void
-rotate(GLfloat *pos, GLfloat *v, GLfloat *dv, GLfloat max_v)
-{
-  double ppos = *pos;
-
-  /* tick position */
-  if (ppos < 0)
-    ppos = -(ppos + *v);
-  else
-    ppos += *v;
-
-  if (ppos > 1.0)
-    ppos -= 1.0;
-  else if (ppos < 0)
-    ppos += 1.0;
-
-  if (ppos < 0) abort();
-  if (ppos > 1.0) abort();
-  *pos = (*pos > 0 ? ppos : -ppos);
-
-  /* accelerate */
-  *v += *dv;
-
-  /* clamp velocity */
-  if (*v > max_v || *v < -max_v)
-    {
-      *dv = -*dv;
-    }
-  /* If it stops, start it going in the other direction. */
-  else if (*v < 0)
-    {
-      if (random() % 4)
-       {
-         *v = 0;
-
-         /* keep going in the same direction */
-         if (random() % 2)
-           *dv = 0;
-         else if (*dv < 0)
-           *dv = -*dv;
-       }
-      else
-       {
-         /* reverse gears */
-         *v = -*v;
-         *dv = -*dv;
-         *pos = -*pos;
-       }
-    }
-
-  /* Alter direction of rotational acceleration randomly. */
-  if (! (random() % 120))
-    *dv = -*dv;
-
-  /* Change acceleration very occasionally. */
-  if (! (random() % 200))
-    {
-      if (*dv == 0)
-       *dv = 0.00001;
-      else if (random() & 1)
-       *dv *= 1.2;
-      else
-       *dv *= 0.8;
-    }
-}
-
-
 \f
 /* Window management, etc
  */
 
-void
+ENTRYPOINT void
 reshape_lament(ModeInfo *mi, int width, int height)
 {
   int target_size = 180;
@@ -1918,7 +1786,7 @@ reshape_lament(ModeInfo *mi, int width, int height)
      Note that the image-map bits we have are 128x128.  Therefore, if the
      image is magnified a lot, it looks pretty blocky.  So it's better to
      have a 128x128 animation on a 1280x1024 screen that looks good, than
-     a 1024x1024 animation that looks really pixellated.
+     a 1024x1024 animation that looks really pixelated.
    */
   if (win_size > target_size * 1.5)
     {
@@ -1945,13 +1813,13 @@ gl_init(ModeInfo *mi)
 
   if (!wire)
     {
-      static GLfloat pos0[]  = { -4.0,  2.0, 5.0, 1.0 };
-      static GLfloat pos1[]  = {  6.0, -1.0, 3.0, 1.0 };
+      static const GLfloat pos0[]  = { -4.0,  2.0, 5.0, 1.0 };
+      static const GLfloat pos1[]  = {  6.0, -1.0, 3.0, 1.0 };
 
-      static GLfloat amb0[]  = { 0.7, 0.7, 0.7, 1.0 };
-/*    static GLfloat amb1[]  = { 0.7, 0.0, 0.0, 1.0 }; */
-      static GLfloat dif0[]  = { 1.0, 1.0, 1.0, 1.0 };
-      static GLfloat dif1[]  = { 0.3, 0.1, 0.1, 1.0 };
+      static const GLfloat amb0[]  = { 0.7, 0.7, 0.7, 1.0 };
+/*    static const GLfloat amb1[]  = { 0.7, 0.0, 0.0, 1.0 }; */
+      static const GLfloat dif0[]  = { 1.0, 1.0, 1.0, 1.0 };
+      static const GLfloat dif1[]  = { 0.3, 0.1, 0.1, 1.0 };
 
       glLightfv(GL_LIGHT0, GL_POSITION, pos0);
       glLightfv(GL_LIGHT1, GL_POSITION, pos1);
@@ -1993,7 +1861,9 @@ gl_init(ModeInfo *mi)
           clear_gl_error();
          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                       lc->texture->width, height, 0,
-                      GL_RGBA, GL_UNSIGNED_BYTE,
+                      GL_RGBA,
+                       /* GL_UNSIGNED_BYTE, */
+                       GL_UNSIGNED_INT_8_8_8_8_REV,
                       (lc->texture->data +
                        (lc->texture->bytes_per_line * height * i)));
           check_gl_error("texture");
@@ -2082,7 +1952,7 @@ handle_signals (void)
 # endif /* HAVE_MESA_GL */
 
 
-void
+ENTRYPOINT void
 init_lament(ModeInfo *mi)
 {
   lament_configuration *lc;
@@ -2099,20 +1969,11 @@ init_lament(ModeInfo *mi)
 
   lc = &lcs[MI_SCREEN(mi)];
 
-  lc->rotx = frand(1.0) * RANDSIGN();
-  lc->roty = frand(1.0) * RANDSIGN();
-  lc->rotz = frand(1.0) * RANDSIGN();
-
-  /* bell curve from 0-1.5 degrees, avg 0.75 */
-  lc->dx = (frand(1) + frand(1) + frand(1)) / (360*2);
-  lc->dy = (frand(1) + frand(1) + frand(1)) / (360*2);
-  lc->dz = (frand(1) + frand(1) + frand(1)) / (360*2);
-
-  lc->d_max = lc->dx * 2;
-
-  lc->ddx = 0.00006 + frand(0.00003);
-  lc->ddy = 0.00006 + frand(0.00003);
-  lc->ddz = 0.00006 + frand(0.00003);
+  {
+    double rot_speed = 0.5;
+    lc->rot = make_rotator (rot_speed, rot_speed, rot_speed, 1, 0, True);
+    lc->trackball = gltrackball_init ();
+  }
 
   lc->type = LAMENT_BOX;
   lc->anim_pause = 300 + (random() % 100);
@@ -2123,13 +1984,38 @@ init_lament(ModeInfo *mi)
       gl_init(mi);
     }
 
+  lc->states = (lament_type *) calloc (50, sizeof (*lc->states));
+  lc->nstates = 0;
+  lc->states[lc->nstates++] = LAMENT_STAR_OUT;
+  lc->states[lc->nstates++] = LAMENT_STAR_OUT;
+  lc->states[lc->nstates++] = LAMENT_TETRA_UNE;
+  lc->states[lc->nstates++] = LAMENT_TETRA_USW;
+  lc->states[lc->nstates++] = LAMENT_TETRA_DWN;
+  lc->states[lc->nstates++] = LAMENT_TETRA_DSE;
+  lc->states[lc->nstates++] = LAMENT_LID_OPEN;
+  lc->states[lc->nstates++] = LAMENT_LID_OPEN;
+  lc->states[lc->nstates++] = LAMENT_LID_OPEN;
+  lc->states[lc->nstates++] = LAMENT_TASER_OUT;
+  lc->states[lc->nstates++] = LAMENT_TASER_OUT;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  lc->states[lc->nstates++] = LAMENT_BOX;
+  shuffle_states (lc);
+
 # ifdef HAVE_MESA_GL
   handle_signals ();
 # endif /* HAVE_MESA_GL */
 }
 
 
-void
+ENTRYPOINT void
 draw_lament(ModeInfo *mi)
 {
   lament_configuration *lc = &lcs[MI_SCREEN(mi)];
@@ -2148,17 +2034,12 @@ draw_lament(ModeInfo *mi)
   glFinish();
   glXSwapBuffers(dpy, window);
 
-  if (lc->type != LAMENT_LID_ZOOM)
-    {
-      rotate(&lc->rotx, &lc->dx, &lc->ddx, lc->d_max);
-      rotate(&lc->roty, &lc->dy, &lc->ddy, lc->d_max);
-      rotate(&lc->rotz, &lc->dz, &lc->ddz, lc->d_max);
-    }
-
   if (lc->anim_pause)
     lc->anim_pause--;
   else
     animate(mi);
 }
 
+XSCREENSAVER_MODULE ("Lament", lament)
+
 #endif /* USE_GL */