From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / menger.c
index 4d40a8e955037f6ea0be8c75dc886ac1439c7665..c5108a28d93c4725dc618e9127f0875d52a042fc 100644 (file)
@@ -1,4 +1,4 @@
-/* menger, Copyright (c) 2001, 2002, 2004 Jamie Zawinski <jwz@jwz.org>
+/* menger, Copyright (c) 2001-2014 Jamie Zawinski <jwz@jwz.org>
  *         Copyright (c) 2002 Aurelien Jacobs <aurel@gnuage.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  *  just draw them as spots on the surface!  It would look the same.
  */
 
-#include <X11/Intrinsic.h>
-
-extern XtAppContext app;
-
-#define PROGCLASS      "Menger"
-#define HACK_INIT      init_sponge
-#define HACK_DRAW      draw_sponge
-#define HACK_RESHAPE   reshape_sponge
-#define HACK_HANDLE_EVENT sponge_handle_event
-#define EVENT_MASK     PointerMotionMask
-#define sws_opts       xlockmore_opts
-
-#define DEF_SPIN        "True"
-#define DEF_WANDER      "True"
-#define DEF_SPEED       "150"
-#define DEF_MAX_DEPTH   "3"
-#define DEF_OPTIMIZE    "True"
-
 #define DEFAULTS       "*delay:         30000          \n" \
                        "*showFPS:       False          \n" \
                        "*wireframe:     False          \n" \
-                       "*maxDepth:    " DEF_MAX_DEPTH "\n" \
-                       "*speed:"        DEF_SPEED     "\n" \
-                       "*optimize:"     DEF_OPTIMIZE  "\n" \
-                       "*spin:        " DEF_SPIN      "\n" \
-                       "*wander:      " DEF_WANDER    "\n" \
+                       "*suppressRotationAnimation: True\n" \
 
 
+# define refresh_sponge 0
+# define release_sponge 0
 #undef countof
 #define countof(x) (sizeof((x))/sizeof((*x)))
 
@@ -89,8 +69,10 @@ extern XtAppContext app;
 
 #ifdef USE_GL /* whole file */
 
-#include <GL/glu.h>
-
+#define DEF_SPIN        "True"
+#define DEF_WANDER      "True"
+#define DEF_SPEED       "150"
+#define DEF_MAX_DEPTH   "3"
 
 typedef struct {
   GLXContext *glx_context;
@@ -111,6 +93,8 @@ typedef struct {
   int ccolor1;
   int ccolor2;
 
+  int draw_tick;
+
 } sponge_configuration;
 
 static sponge_configuration *sps = NULL;
@@ -118,34 +102,29 @@ static sponge_configuration *sps = NULL;
 static Bool do_spin;
 static Bool do_wander;
 static int speed;
-static Bool do_optimize;
 static int max_depth;
 
 static XrmOptionDescRec opts[] = {
-  { "-spin",   ".spin",   XrmoptionNoArg, "True" },
-  { "+spin",   ".spin",   XrmoptionNoArg, "False" },
-  { "-wander", ".wander", XrmoptionNoArg, "True" },
-  { "+wander", ".wander", XrmoptionNoArg, "False" },
-  { "-speed",  ".speed",  XrmoptionSepArg, 0 },
-  { "-optimize", ".optimize", XrmoptionNoArg, "True" },
-  { "+optimize", ".optimize", XrmoptionNoArg, "False" },
-  {"-depth",   ".maxDepth", XrmoptionSepArg, (caddr_t) 0 },
+  { "-wander", ".wander",   XrmoptionNoArg, "True"  },
+  { "+wander", ".wander",   XrmoptionNoArg, "False" },
+  { "-spin",   ".spin",     XrmoptionSepArg, 0 },
+  { "-speed",  ".speed",    XrmoptionSepArg, 0 },
+  { "-depth",  ".maxDepth", XrmoptionSepArg, 0 },
 };
 
 static argtype vars[] = {
   {&do_spin,     "spin",     "Spin",     DEF_SPIN,      t_Bool},
   {&do_wander,   "wander",   "Wander",   DEF_WANDER,    t_Bool},
   {&speed,       "speed",    "Speed",    DEF_SPEED,     t_Int},
-  {&do_optimize, "optimize", "Optimize", DEF_OPTIMIZE,  t_Bool},
   {&max_depth,   "maxDepth", "MaxDepth", DEF_MAX_DEPTH, t_Int},
 };
 
-ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
+ENTRYPOINT ModeSpecOpt sponge_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
 
 /* Window management, etc
  */
-void
+ENTRYPOINT void
 reshape_sponge (ModeInfo *mi, int width, int height)
 {
   GLfloat h = (GLfloat) height / (GLfloat) width;
@@ -162,6 +141,14 @@ reshape_sponge (ModeInfo *mi, int width, int height)
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
 
+# ifdef HAVE_MOBILE    /* Keep it the same relative size when rotated. */
+  {
+    int o = (int) current_device_rotation();
+    if (o != 0 && o != 180 && o != -180)
+      glScalef (1/h, 1/h, 1/h);
+  }
+# endif
+
   glClear(GL_COLOR_BUFFER_BIT);
 }
 
@@ -250,17 +237,16 @@ cube (float x0, float x1, float y0, float y1, float z0, float z1,
 }
 
 static int
-menger_recurs (int level, float x0, float x1, float y0, float y1,
-               float z0, float z1, int faces, Bool wireframe, int orig)
+menger_recurs_1 (int level, float x0, float x1, float y0, float y1,
+                 float z0, float z1, int faces, Bool wireframe, 
+                 int orig, int forig)
 {
   float xi, yi, zi;
   int f, x, y, z;
-  static int forig;
   int n = 0;
 
   if (orig)
     {
-      forig = faces;
       if (wireframe)
         n += cube (x0, x1, y0, y1, z0, z1,
                    faces & (X0 | X1 | Y0 | Y1), wireframe);
@@ -314,10 +300,11 @@ menger_recurs (int level, float x0, float x1, float y0, float y1,
                   if (forig & Z1 && z == 0 && (x == 1 || y == 1))
                     f |= Z1;
 
-                  n += menger_recurs (level-1,
-                                      x0+x*xi, x0+(x+1)*xi,
-                                      y0+y*yi, y0+(y+1)*yi,
-                                      z0+z*zi, z0+(z+1)*zi, f, wireframe, 0);
+                  n += menger_recurs_1 (level-1,
+                                        x0+x*xi, x0+(x+1)*xi,
+                                        y0+y*yi, y0+(y+1)*yi,
+                                        z0+z*zi, z0+(z+1)*zi, f, wireframe, 0,
+                                        forig);
                 }
               else if (wireframe && (x != 1 || y != 1 || z != 1))
                 n += cube (x0+x*xi, x0+(x+1)*xi,
@@ -330,6 +317,16 @@ menger_recurs (int level, float x0, float x1, float y0, float y1,
   return n;
 }
 
+static int
+menger_recurs (int level, float x0, float x1, float y0, float y1,
+               float z0, float z1, int faces, Bool wireframe, 
+               int orig)
+{
+  return menger_recurs_1 (level, x0, x1, y0, y1, z0, z1, faces, 
+                          wireframe, orig, faces);
+}
+
+
 static void
 build_sponge (sponge_configuration *sp, Bool wireframe, int level)
 {
@@ -353,32 +350,43 @@ build_sponge (sponge_configuration *sp, Bool wireframe, int level)
 }
 
 
-Bool
+ENTRYPOINT Bool
 sponge_handle_event (ModeInfo *mi, XEvent *event)
 {
   sponge_configuration *sp = &sps[MI_SCREEN(mi)];
 
-  if (event->xany.type == ButtonPress &&
-      event->xbutton.button & Button1)
+  if (gltrackball_event_handler (event, sp->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &sp->button_down_p))
+    return True;
+  else if (event->xany.type == KeyPress)
     {
-      sp->button_down_p = True;
-      gltrackball_start (sp->trackball,
-                         event->xbutton.x, event->xbutton.y,
-                         MI_WIDTH (mi), MI_HEIGHT (mi));
-      return True;
+      KeySym keysym;
+      char c = 0;
+      XLookupString (&event->xkey, &c, 1, &keysym, 0);
+      if (c == '+' || c == '=' ||
+          keysym == XK_Up || keysym == XK_Right || keysym == XK_Next)
+        {
+          sp->draw_tick = speed;
+          sp->current_depth += (sp->current_depth > 0 ? 1 : -1);
+          sp->current_depth--;
+          return True;
+        }
+      else if (c == '-' || c == '_' ||
+               keysym == XK_Down || keysym == XK_Left || keysym == XK_Prior)
+        {
+          sp->draw_tick = speed;
+          sp->current_depth -= (sp->current_depth > 0 ? 1 : -1);
+          sp->current_depth--;
+          return True;
+        }
+      else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+        goto DEF;
     }
-  else if (event->xany.type == ButtonRelease &&
-           event->xbutton.button & Button1)
+  else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
     {
-      sp->button_down_p = False;
-      return True;
-    }
-  else if (event->xany.type == MotionNotify &&
-           sp->button_down_p)
-    {
-      gltrackball_track (sp->trackball,
-                         event->xmotion.x, event->xmotion.y,
-                         MI_WIDTH (mi), MI_HEIGHT (mi));
+    DEF:
+      sp->draw_tick = speed;
       return True;
     }
 
@@ -387,22 +395,13 @@ sponge_handle_event (ModeInfo *mi, XEvent *event)
 
 
 
-void 
+ENTRYPOINT void 
 init_sponge (ModeInfo *mi)
 {
   sponge_configuration *sp;
   int wire = MI_IS_WIREFRAME(mi);
 
-  if (!sps) {
-    sps = (sponge_configuration *)
-      calloc (MI_NUM_SCREENS(mi), sizeof (sponge_configuration));
-    if (!sps) {
-      fprintf(stderr, "%s: out of memory\n", progname);
-      exit(1);
-    }
-
-    sp = &sps[MI_SCREEN(mi)];
-  }
+  MI_INIT (mi, sps, NULL);
 
   sp = &sps[MI_SCREEN(mi)];
 
@@ -412,10 +411,10 @@ init_sponge (ModeInfo *mi)
 
   if (!wire)
     {
-      static GLfloat pos0[4] = {-1.0, -1.0, 1.0, 0.1};
-      static GLfloat pos1[4] = { 1.0, -0.2, 0.2, 0.1};
-      static GLfloat dif0[4] = {1.0, 1.0, 1.0, 1.0};
-      static GLfloat dif1[4] = {1.0, 1.0, 1.0, 1.0};
+      static const GLfloat pos0[4] = {-1.0, -1.0, 1.0, 0.1};
+      static const GLfloat pos1[4] = { 1.0, -0.2, 0.2, 0.1};
+      static const GLfloat dif0[4] = {1.0, 1.0, 1.0, 1.0};
+      static const GLfloat dif1[4] = {1.0, 1.0, 1.0, 1.0};
 
       glLightfv(GL_LIGHT0, GL_POSITION, pos0);
       glLightfv(GL_LIGHT1, GL_POSITION, pos1);
@@ -441,7 +440,7 @@ init_sponge (ModeInfo *mi)
                             1.0,
                             do_wander ? wander_speed : 0,
                             True);
-    sp->trackball = gltrackball_init ();
+    sp->trackball = gltrackball_init (True);
   }
 
   sp->ncolors = 128;
@@ -456,25 +455,27 @@ init_sponge (ModeInfo *mi)
   sp->sponge_list0 = glGenLists (1);
   sp->sponge_list1 = glGenLists (1);
   sp->sponge_list2 = glGenLists (1);
+
+  sp->draw_tick = 9999999;
 }
 
 
-void
+ENTRYPOINT void
 draw_sponge (ModeInfo *mi)
 {
   sponge_configuration *sp = &sps[MI_SCREEN(mi)];
   Display *dpy = MI_DISPLAY(mi);
   Window window = MI_WINDOW(mi);
 
-  static GLfloat color0[4] = {0.0, 0.0, 0.0, 1.0};
-  static GLfloat color1[4] = {0.0, 0.0, 0.0, 1.0};
-  static GLfloat color2[4] = {0.0, 0.0, 0.0, 1.0};
-
-  static int tick = 99999;
+  GLfloat color0[4] = {0.0, 0.0, 0.0, 1.0};
+  GLfloat color1[4] = {0.0, 0.0, 0.0, 1.0};
+  GLfloat color2[4] = {0.0, 0.0, 0.0, 1.0};
 
   if (!sp->glx_context)
     return;
 
+  glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sp->glx_context));
+
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix ();
@@ -516,9 +517,9 @@ draw_sponge (ModeInfo *mi)
   if (sp->ccolor1 >= sp->ncolors) sp->ccolor1 = 0;
   if (sp->ccolor2 >= sp->ncolors) sp->ccolor2 = 0;
 
-  if (tick++ >= speed)
+  if (sp->draw_tick++ >= speed)
     {
-      tick = 0;
+      sp->draw_tick = 0;
       if (sp->current_depth >= max_depth)
         sp->current_depth = -max_depth;
       sp->current_depth++;
@@ -528,6 +529,8 @@ draw_sponge (ModeInfo *mi)
                      ? -sp->current_depth : sp->current_depth));
 
       mi->polygon_count = sp->squares_fp;  /* for FPS display */
+      mi->recursion_depth = (sp->current_depth < 0
+                             ? -sp->current_depth : sp->current_depth);
     }
 
   glScalef (2.0, 2.0, 2.0);
@@ -547,4 +550,6 @@ draw_sponge (ModeInfo *mi)
   glXSwapBuffers(dpy, window);
 }
 
+XSCREENSAVER_MODULE_2 ("Menger", menger, sponge)
+
 #endif /* USE_GL */