From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / hacks / glx / sballs.c
index ad77d8c4d5b118060d79227da130f90cfbaed100..bae0b78902a5d7569495c7f8e2d48417971d5fc0 100644 (file)
@@ -1,6 +1,6 @@
 /* sballs --- balls spinning like crazy in GL */
 
-#if !defined( lint ) && !defined( SABER )
+#if 0
 static const char sccsid[] = "@(#)sballs.c     5.02 2001/03/10 xlockmore";
 #endif
 
@@ -23,7 +23,7 @@ static const char sccsid[] = "@(#)sballs.c    5.02 2001/03/10 xlockmore";
  * Mustata Bogdan (LoneRunner) <lonerunner@planetquake.com>
  * and can be found at http://www.cfxweb.net/lonerunner/
  *
- * Eric Lassauge  (November-07-2000) <lassauge@mail.dotcom.fr>
+ * Eric Lassauge  (November-07-2000) <lassauge@users.sourceforge.net>
  *                                 http://lassauge.free.fr/linux.html
  *
  * REVISION HISTORY:
@@ -41,22 +41,17 @@ static const char sccsid[] = "@(#)sballs.c  5.02 2001/03/10 xlockmore";
  */
 
 #ifdef STANDALONE      /* xscreensaver mode */
-#define PROGCLASS      "Sballs"
-#define HACK_INIT      init_sballs
-#define HACK_DRAW      draw_sballs
-#define HACK_RESHAPE   reshape_sballs
-#define sballs_opts    xlockmore_opts
-#define DEFAULTS       "*delay:        10000 \n" \
+#define DEFAULTS       "*delay:        30000 \n" \
                        "*size:             0 \n" \
-                       "*cycles:          10 \n" \
-                       "*object:           0 \n" \
-                       "*trackmouse:   False \n" \
+                       "*cycles:           4 \n" \
                        "*showFPS:      False \n" \
                        "*wireframe:    False \n" \
-                       "*texture:      True  \n"
 
+# define refresh_sballs 0
+# define release_sballs 0
 #define MODE_sballs
 #include "xlockmore.h"         /* from the xscreensaver distribution */
+#include "gltrackball.h"
 #else                          /* !STANDALONE */
 #include "xlock.h"             /* from the xlockmore distribution */
 #include "visgl.h"
@@ -68,64 +63,62 @@ static const char sccsid[] = "@(#)sballs.c  5.02 2001/03/10 xlockmore";
 #define FRAME           50      /* frame count interval */
 #define MAX_OBJ                8       /* number of 3D objects */
 
-#include <GL/gl.h>
-#include <GL/glx.h>
-#include <GL/glu.h>
-
-#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( HAVE_XPM )
+#if defined( USE_XPM ) || defined( USE_XPMINC ) || defined( STANDALONE )
 /* USE_XPM & USE_XPMINC in xlock mode ; HAVE_XPM in xscreensaver mode */
-#include "xpm-ximage.h"
-#define I_HAVE_XPM
-
-#ifdef STANDALONE
-#include "../images/sball.xpm"
-#include "../images/sball-bg.xpm"
-#else /* !STANDALONE */
-#include "pixmaps/sball.xpm"
-#include "pixmaps/sball-bg.xpm"
-#endif /* !STANDALONE */
+# include "xpm-ximage.h"
+# define I_HAVE_XPM
+
+# ifdef STANDALONE
+
+#  ifdef __GNUC__
+   __extension__ /* don't warn about "string length is greater than the length
+                    ISO C89 compilers are required to support" when including
+                    the following XPM file... */
+#  endif
+#  include "../images/sball.xpm"
+#  ifdef __GNUC__
+   __extension__
+#  endif
+#  include "../images/sball-bg.xpm"
+# else /* !STANDALONE */
+#  include "pixmaps/sball.xpm"
+#  include "pixmaps/sball-bg.xpm"
+# endif /* !STANDALONE */
 #endif /* HAVE_XPM */
 
 /* Manage option vars */
 #define DEF_TEXTURE    "True"
-#define DEF_TRACKMOUSE  "False"
-#define DEF_OBJECT     "2"
-#define DEF_OBJECT_INDX        2
+#define DEF_OBJECT     "0"
 static Bool do_texture;
-static Bool do_trackmouse;
 static int  object;
 static int  spheres;
 
 static XrmOptionDescRec opts[] = {
-    {(char *) "-texture", (char *) ".sballs.texture", XrmoptionNoArg, (caddr_t) "on"},
-    {(char *) "+texture", (char *) ".sballs.texture", XrmoptionNoArg, (caddr_t) "off"},
-    {(char *) "-trackmouse", (char *) ".sballs.trackmouse", XrmoptionNoArg, (caddr_t) "on"},
-    {(char *) "+trackmouse", (char *) ".sballs.trackmouse", XrmoptionNoArg, (caddr_t) "off"},
-    {(char *) "-object", (char *) ".sballs.object", XrmoptionSepArg, (caddr_t) NULL},
+    {"-texture", ".sballs.texture", XrmoptionNoArg, "on"},
+    {"+texture", ".sballs.texture", XrmoptionNoArg, "off"},
+    {"-object", ".sballs.object", XrmoptionSepArg, 0},
 
 };
 
 static argtype vars[] = {
-    {(caddr_t *) & do_texture, (char *) "texture", (char *) "Texture", (char *) DEF_TEXTURE, t_Bool},
-    {(caddr_t *) & do_trackmouse, (char *) "trackmouse", (char *) "TrackMouse", (char *) DEF_TRACKMOUSE, t_Bool},
-    {(caddr_t *) & object, (char *) "object", (char *) "Object", (char *) DEF_OBJECT, t_Int},
+    {&do_texture,    "texture",    "Texture",    DEF_TEXTURE,    t_Bool},
+    {&object,        "object",     "Object",     DEF_OBJECT,     t_Int},
 
 };
 
 static OptionStruct desc[] = {
-    /*{(char *) "-count spheres", (char *) "set number of spheres"},*/
-    /*{(char *) "-cycles speed", (char *) "set ball speed value"},*/
-    {(char *) "-/+texture", (char *) "turn on/off texturing"},
-    {(char *) "-/+trackmouse", (char *) "turn on/off the tracking of the mouse"},
-    {(char *) "-object num", (char *) "number of the 3D object (0 means random)"},
+    /*{"-count spheres", "set number of spheres"},*/
+    /*{"-cycles speed", "set ball speed value"},*/
+    {"-/+texture", "turn on/off texturing"},
+    {"-object num", "number of the 3D object (0 means random)"},
 };
 
-ModeSpecOpt sballs_opts =
+ENTRYPOINT ModeSpecOpt sballs_opts =
  { sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc };
 
 #ifdef USE_MODULES
 ModStruct sballs_description =
-    { "sballs", "init_sballs", "draw_sballs", "release_sballs",
+    { "sballs", "init_sballs", "draw_sballs", NULL,
     "draw_sballs", "change_sballs", (char *) NULL, &sballs_opts,
     /*
     delay,count,cycles,size,ncolors,sat
@@ -158,20 +151,22 @@ typedef struct {
     GLuint faceid;             /* face texture id: GL world */
 
     vec3_t eye;
-    vec3_t rot;
     vec3_t rotm;
     int speed;
     float radius[MAX_BALLS];
 
+    trackball_state *trackball;
+    Bool button_down_p;
+
 } sballsstruct;
 
 /* array of sballsstruct indexed by screen number */
 static sballsstruct *sballs = (sballsstruct *) NULL;
 
 /* lights */
-static float LightAmbient[]=   { 1.0f, 1.0f, 1.0f, 1.0f };
-static float LightDiffuse[]=   { 1.0f, 1.0f, 1.0f, 1.0f };
-static float LightPosition[]=  { 0.0f, 0.0f, 4.0f, 1.0f };
+static const float LightAmbient[]=   { 1.0f, 1.0f, 1.0f, 1.0f };
+static const float LightDiffuse[]=   { 1.0f, 1.0f, 1.0f, 1.0f };
+static const float LightPosition[]=  { 0.0f, 0.0f, 4.0f, 1.0f };
 
 /* structure of the polyhedras */
 typedef struct {
@@ -182,7 +177,7 @@ typedef struct {
         vec3_t      v[MAX_BALLS];/* the vertices */
 } Polyinfo;
 
-static Polyinfo polygons[] =
+static const Polyinfo polygons[] =
 {
 
 /* 0: objtetra - structure values for tetrahedron */
@@ -362,54 +357,6 @@ static Polyinfo polygons[] =
  *-----------------------------------------------------------------------------
  */
 
-static void clamp(vec3_t v)
-{
-    int i;
-
-    for (i = 0; i < 3; i ++)
-        if (v[i] > 360 || v[i] < -360)
-            v[i] = 0;
-}
-
-/* track the mouse in a joystick manner : not perfect but it works */
-static void trackmouse(ModeInfo * mi)
-{
-    sballsstruct *sb = &sballs[MI_SCREEN(mi)];
-    /* we keep static values (not per screen) for the mouse stuff: in general you have only one mouse :-> */
-    static int max[2] = { 0, 0 };
-    static int min[2] = { 0x7fffffff, 0x7fffffff }, center[2];
-    Window r, c;
-    int rx, ry, cx, cy;
-    unsigned int m;
-
-    (void) XQueryPointer(MI_DISPLAY(mi), MI_WINDOW(mi),
-                        &r, &c, &rx, &ry, &cx, &cy, &m);
-
-    if (max[0] < cx)
-       max[0] = cx;
-    if (min[0] > cx)
-       min[0] = cx;
-    center[0] = (max[0] + min[0]) / 2;
-
-    if (max[1] < cy)
-       max[1] = cy;
-    if (min[1] > cy)
-       min[1] = cy;
-    center[1] = (max[1] + min[1]) / 2;
-
-    if (fabs(center[0] - (float) cx) > 0.1 * (max[0] - min[0]))
-       sb->rot[0] -= ((center[0] - (float) cx) / (max[0] - min[0]) * 180.0f) / 200.0f;
-    if (fabs(center[1] - (float) cy) > 0.1 * (max[1] - min[1]))
-        sb->rot[1] -= ((center[1] - (float) cy) / (max[1] - min[1]) * 180.0f) / 200.0f;;
-    clamp(sb->rot);
-
-    /* oops: can't get those buttons */
-    if (m & Button4Mask)
-        sb->speed++;
-    if (m & Button5Mask)
-        sb->speed--;
-
-}
 
 /* initialise textures */
 static void inittextures(ModeInfo * mi)
@@ -507,8 +454,8 @@ static void drawSphere(ModeInfo * mi,int sphere_num)
   float x = polygons[object].v[sphere_num][0];
   float y = polygons[object].v[sphere_num][1];
   float z = polygons[object].v[sphere_num][2];
-  int numMajor = 10;
-  int numMinor = 10;
+  int numMajor = 15;
+  int numMinor = 30;
   float radius = sb->radius[sphere_num];
   double majorStep = (M_PI / numMajor);
   double minorStep = (2.0 * M_PI / numMinor);
@@ -541,6 +488,8 @@ static void drawSphere(ModeInfo * mi,int sphere_num)
       glNormal3f((x * r1) / radius, (y * r1) / radius, z1 / radius);
       glTexCoord2f(j / (GLfloat) numMinor, (i + 1) / (GLfloat) numMajor);
       glVertex3f(x * r1, y * r1, z1);
+
+      mi->polygon_count++;
     }
     glEnd();
   }
@@ -559,7 +508,7 @@ static void drawSphere(ModeInfo * mi,int sphere_num)
 #ifndef STANDALONE
 static void Reshape(ModeInfo * mi)
 #else
-void reshape_sballs(ModeInfo * mi, int width, int height)
+ENTRYPOINT void reshape_sballs(ModeInfo * mi, int width, int height)
 #endif
 {
 
@@ -591,8 +540,7 @@ static void Draw(ModeInfo * mi)
     sballsstruct *sb = &sballs[MI_SCREEN(mi)];
     int sphere;
 
-    if (do_trackmouse && !MI_IS_ICONIC(mi))
-       trackmouse(mi);
+    mi->polygon_count = 0;
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -617,32 +565,41 @@ static void Draw(ModeInfo * mi)
        glColor3f(0, 0, 0);
     }
     glBegin(GL_QUAD_STRIP);
+#ifndef HAVE_MOBILE
+    /* Letterbox the background image */
     glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(8, 4.1, -4);
     glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(8, -4.1, -4);
     glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-8, 4.1, -4);
     glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-8, -4.1, -4);
+#else
+    /* Fill the iPhone screen. Letterboxing looks dumb there. */
+    glNormal3f(0, 0, 1); glTexCoord2f(0,0); glVertex3f(4, 5.2, -4);
+    glNormal3f(0, 0, 1); glTexCoord2f(0,1); glVertex3f(4, -5.2, -4);
+    glNormal3f(0, 0, 1); glTexCoord2f(1,0); glVertex3f(-4, 5.2, -4);
+    glNormal3f(0, 0, 1); glTexCoord2f(1,1); glVertex3f(-4, -5.2, -4);
+#endif
     glEnd();
+    mi->polygon_count++;
 
-    /* rotate the mouse */
-    glRotatef(sb->rot[0], 1.0f, 0.0f, 0.0f);
-    glRotatef(sb->rot[1], 0.0f, 1.0f, 0.0f);
-    glRotatef(sb->rot[2], 0.0f, 0.0f, 1.0f);
+    gltrackball_rotate (sb->trackball);
 
     /* rotate the balls */
     glRotatef(sb->rotm[0], 1.0f, 0.0f, 0.0f);
     glRotatef(sb->rotm[1], 0.0f, 1.0f, 0.0f);
     glRotatef(sb->rotm[2], 0.0f, 0.0f, 1.0f);
 
-    sb->rotm[0] += sb->speed;
-    sb->rotm[1] += -(sb->speed);
-    sb->rotm[2] += 0;
+    if (! sb->button_down_p) {
+      sb->rotm[0] += sb->speed;
+      sb->rotm[1] += -(sb->speed);
+      sb->rotm[2] += 0;
+    }
 
     /* draw the balls */
     if (do_texture)
 #ifdef HAVE_GLBINDTEXTURE
        glBindTexture(GL_TEXTURE_2D, sb->faceid);
-#endif /* HAVE_GLBINDTEXTURE */
     else
+#endif /* HAVE_GLBINDTEXTURE */
        glEnable(GL_LIGHTING);
     for (sphere=0;sphere<spheres;sphere++)
     {
@@ -676,15 +633,12 @@ static void Init(ModeInfo * mi)
     }
 
     vinit(sb->eye   ,0.0f, 0.0f, 6.0f);
-    vinit(sb->rot   ,0.0f, 0.0f, 0.0f);
     vinit(sb->rotm  ,0.0f, 0.0f, 0.0f);
     sb->speed = MI_CYCLES(mi);
 
     /* initialise object number */
-    if (object == 0)
-       object = NRAND(MAX_OBJ);
     if ((object == 0) || (object > MAX_OBJ))
-       object = DEF_OBJECT_INDX;
+      object = NRAND(MAX_OBJ-1)+1;
     object--;
 
     /* initialise sphere number */
@@ -722,8 +676,6 @@ static void Init(ModeInfo * mi)
         glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
         glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
         glEnable(GL_LIGHT1);
-
-        glClearColor(0, 0, 0, 0);
 }
 
 /*
@@ -734,23 +686,23 @@ static void Init(ModeInfo * mi)
  *-----------------------------------------------------------------------------
  */
 
+static void free_sballs(ModeInfo * mi);
+
 /*
  *-----------------------------------------------------------------------------
  *    Initialize sballs.  Called each time the window changes.
  *-----------------------------------------------------------------------------
  */
 
-void init_sballs(ModeInfo * mi)
+ENTRYPOINT void init_sballs(ModeInfo * mi)
 {
     sballsstruct *sb;
 
-    if (sballs == NULL) {
-       if ((sballs = (sballsstruct *) calloc(MI_NUM_SCREENS(mi),
-                                         sizeof(sballsstruct))) == NULL)
-           return;
-    }
+    MI_INIT(mi, sballs, free_sballs);
     sb = &sballs[MI_SCREEN(mi)];
 
+    sb->trackball = gltrackball_init (True);
+
     if ((sb->glx_context = init_GL(mi)) != NULL) {
 
 #ifndef STANDALONE
@@ -771,7 +723,7 @@ void init_sballs(ModeInfo * mi)
  *    Called by the mainline code periodically to update the display.
  *-----------------------------------------------------------------------------
  */
-void draw_sballs(ModeInfo * mi)
+ENTRYPOINT void draw_sballs(ModeInfo * mi)
 {
     Display *display = MI_DISPLAY(mi);
     Window window = MI_WINDOW(mi);
@@ -801,36 +753,45 @@ void draw_sballs(ModeInfo * mi)
 /*
  *-----------------------------------------------------------------------------
  *    The display is being taken away from us.  Free up malloc'ed
- *      memory and X resources that we've alloc'ed.  Only called
- *      once, we must zap everything for every screen.
+ *      memory and X resources that we've alloc'ed.
  *-----------------------------------------------------------------------------
  */
 
-void release_sballs(ModeInfo * mi)
+static void free_sballs(ModeInfo * mi)
 {
-    int screen;
-
-    if (sballs != NULL) {
-       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
-           sballsstruct *sb = &sballs[screen];
-           if (sb->btexture)
-           {
-               glDeleteTextures(1,&sb->backid);
-               XDestroyImage(sb->btexture);
-           }
-           if (sb->ftexture)
-           {
-               glDeleteTextures(1,&sb->faceid);
-               XDestroyImage(sb->ftexture);
-           }
+    sballsstruct *sb = &sballs[MI_SCREEN(mi)];
+    if (sb->glx_context)
+    {
+       glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sb->glx_context));
+       if (sb->btexture)
+       {
+           glDeleteTextures(1,&sb->backid);
+           XDestroyImage(sb->btexture);
+       }
+       if (sb->ftexture)
+       {
+           glDeleteTextures(1,&sb->faceid);
+           XDestroyImage(sb->ftexture);
        }
-       (void) free((void *) sballs);
-       sballs = (sballsstruct *) NULL;
     }
-    FreeAllGL(mi);
 }
 
-void change_sballs(ModeInfo * mi)
+ENTRYPOINT Bool
+sballs_handle_event (ModeInfo *mi, XEvent *event)
+{
+  sballsstruct *sb = &sballs[MI_SCREEN(mi)];
+
+  if (gltrackball_event_handler (event, sb->trackball,
+                                 MI_WIDTH (mi), MI_HEIGHT (mi),
+                                 &sb->button_down_p))
+    return True;
+
+  return False;
+}
+
+
+#ifndef STANDALONE
+ENTRYPOINT void change_sballs(ModeInfo * mi)
 {
     sballsstruct *sb;
 
@@ -842,10 +803,8 @@ void change_sballs(ModeInfo * mi)
        return;
 
     /* initialise object number */
-    if (object == 0)
-       object = NRAND(MAX_OBJ);
     if ((object == 0) || (object > MAX_OBJ))
-       object = DEF_OBJECT_INDX;
+      object = NRAND(MAX_OBJ-1)+1;
     object--;
 
     /* correct sphere number */
@@ -868,4 +827,8 @@ void change_sballs(ModeInfo * mi)
     glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(sb->glx_context));
 
 }
+#endif /* !STANDALONE */
+
+XSCREENSAVER_MODULE ("SBalls", sballs)
+
 #endif /* MODE_sballs */