http://www.jwz.org/xscreensaver/xscreensaver-5.13.tar.gz
[xscreensaver] / hacks / glx / boxed.c
index ef7e051f792cf7224281aa4ffa6fb6dba14f3e07..f1a409a1f775dfb4c66a4766ecec57105994bf0f 100644 (file)
@@ -26,6 +26,10 @@ static const char sccsid[] = "@(#)boxed.c    0.9 01/09/26 xlockmore";
  *
  * 2005: opts work. added options -balls, -ballsize, -explosion
  *
+ * 2006: opts work. added option -decay
+ *
+ * 2008: opts work. added option -momentum
+ *
  */
 
 #include "boxed.h"
@@ -54,7 +58,8 @@ static const char sccsid[] = "@(#)boxed.c     0.9 01/09/26 xlockmore";
 # define DEF_BALLS     "25"
 # define DEF_BALLSIZE   "2.0"
 # define DEF_EXPLOSION "15.0"
-# define DEF_DECAY     "0.1"
+# define DEF_DECAY     "0.07"
+# define DEF_MOMENTUM  "0.6"
 
 #undef countof 
 #define countof(x) (int)(sizeof((x))/sizeof((*x)))
@@ -66,6 +71,7 @@ static int cfg_balls;
 static GLfloat cfg_ballsize;
 static GLfloat cfg_explosion;
 static GLfloat cfg_decay;
+static GLfloat cfg_momentum;
 
 
 static XrmOptionDescRec opts[] = {
@@ -74,6 +80,7 @@ static XrmOptionDescRec opts[] = {
     {"-ballsize", ".boxed.ballsize", XrmoptionSepArg, 0},
     {"-explosion", ".boxed.explosion", XrmoptionSepArg, 0},
     {"-decay", ".boxed.decay", XrmoptionSepArg, 0},
+    {"-momentum", ".boxed.momentum", XrmoptionSepArg, 0},
 };
 
 static argtype vars[] = {
@@ -82,6 +89,7 @@ static argtype vars[] = {
     {&cfg_ballsize, "ballsize", "Ball Size", DEF_BALLSIZE, t_Float},
     {&cfg_explosion, "explosion", "Explosion", DEF_EXPLOSION, t_Float},
     {&cfg_decay, "decay", "Explosion Decay", DEF_DECAY, t_Float},
+    {&cfg_momentum, "momentum", "Explosion Momentum", DEF_MOMENTUM, t_Float},
 };
 
 ENTRYPOINT ModeSpecOpt boxed_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -153,6 +161,7 @@ typedef struct {
    float       scalefac;
    float       explosion;
    float       decay;
+   float       momentum;
    vectorf     color;
    tri         *tris;
    GLint       *indices;
@@ -165,6 +174,7 @@ typedef struct {
    float ballsize;
    float explosion;
    float decay;
+   float momentum;
    BOOL textures;
    BOOL transparent;
    float camspeed;
@@ -183,6 +193,7 @@ typedef struct {
    GLXContext     *glx_context;
    GLuint         listobjects;
    GLuint         gllists[3];
+   int            list_polys[3];
    Window         window;
    BOOL           stop;
    char           *tex1;
@@ -260,6 +271,12 @@ squaremagnitude(vectorf * v)
    return v->x * v->x + v->y * v->y + v->z * v->z;
 }
 
+static inline GLfloat
+squaremagnitudehorz(vectorf * v)
+{
+   return v->x * v->x + v->z * v->z;
+}
+
 
 
 /*
@@ -400,7 +417,10 @@ static void updateballs(ballman *bman)
               scalevector(&bman->balls[b].dir,&bman->balls[b].dir,0.80f);
               if (squaremagnitude(&bman->balls[b].dir) < 0.08f) {
                  createball(&bman->balls[b]);
-              }
+               }
+              if (squaremagnitudehorz(&bman->balls[b].dir) < 0.005f) {
+                 createball(&bman->balls[b]);
+               }
            }
         }
         
@@ -471,13 +491,15 @@ static void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, i
 {
    int pos;
    float explosion;
+   float momentum;
    float scale;
    register int i;
-   vectorf avgdir,dvect;
+   vectorf avgdir,dvect,mvect;
 
    tman->scalefac = b->radius;
    copyvector(&tman->color,&b->color);
    explosion = 1.0f + tman->explosion * 2.0 * rnd();
+   momentum = tman->momentum;
 
    tman->num_tri = ind_num/3;
    
@@ -537,6 +559,12 @@ static void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, i
       dvect.y = (0.15f - 0.3f*rnd());
       dvect.z = (0.1f - 0.2f*rnd());
       addvectors(&tman->tris[i].dir,&tman->tris[i].dir,&dvect);
+
+      /* add ball's momentum to each piece of the exploded ball */
+      mvect.x = b->dir.x * momentum;
+      mvect.y = 0;
+      mvect.z = b->dir.z * momentum;
+      addvectors(&tman->tris[i].dir,&tman->tris[i].dir,&mvect);
    }
 }
 
@@ -643,12 +671,14 @@ static void setdefaultconfig(boxed_config *config)
   cfg_ballsize = MAX(1.0f,MIN(5.0f,cfg_ballsize));
   cfg_explosion = MAX(0.0f,MIN(50.0f,cfg_explosion));
   cfg_decay = MAX(0.0f,MIN(1.0f,cfg_decay));
+  cfg_momentum = MAX(0.0f,MIN(1.0f,cfg_momentum));
 
   config->numballs = cfg_balls;
   config->textures = TRUE;
   config->transparent = FALSE;
   config->explosion = cfg_explosion;
   config->decay = cfg_decay;
+  config->momentum = cfg_momentum;
   config->ballsize = cfg_ballsize;
   config->camspeed = 35.0f;
 }
@@ -657,12 +687,13 @@ static void setdefaultconfig(boxed_config *config)
 /*
  * draw bottom
  */ 
-static void drawfilledbox(boxedstruct *boxed, int wire)
+static int drawfilledbox(boxedstruct *boxed, int wire)
 {   
    /* draws texture filled box, 
       top is drawn using the entire texture, 
       the sides are drawn using the edge of the texture
     */
+  int polys = 0;
    
    /* front */
    glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
@@ -674,6 +705,7 @@ static void drawfilledbox(boxedstruct *boxed, int wire)
    glVertex3f(1.0,-1.0,1.0);
    glTexCoord2f(0,1);
    glVertex3f(-1.0,-1.0,1.0);
+   polys++;
    /* rear */
    glTexCoord2f(0,1);
    glVertex3f(1.0,1.0,-1.0);
@@ -683,6 +715,7 @@ static void drawfilledbox(boxedstruct *boxed, int wire)
    glVertex3f(-1.0,-1.0,-1.0);
    glTexCoord2f(0,1);
    glVertex3f(1.0,-1.0,-1.0);
+   polys++;
    /* left */
    glTexCoord2f(1,1);
    glVertex3f(-1.0,1.0,1.0);
@@ -692,6 +725,7 @@ static void drawfilledbox(boxedstruct *boxed, int wire)
    glVertex3f(-1.0,-1.0,-1.0);
    glTexCoord2f(0,1);
    glVertex3f(-1.0,1.0,-1.0);
+   polys++;
    /* right */
    glTexCoord2f(0,1);
    glVertex3f(1.0,1.0,1.0);
@@ -701,6 +735,7 @@ static void drawfilledbox(boxedstruct *boxed, int wire)
    glVertex3f(1.0,-1.0,-1.0);
    glTexCoord2f(0,1);
    glVertex3f(1.0,-1.0,1.0);
+   polys++;
    /* top */
    glTexCoord2f(0.0,0.0);
    glVertex3f(-1.0,1.0,1.0);
@@ -710,6 +745,7 @@ static void drawfilledbox(boxedstruct *boxed, int wire)
    glVertex3f(1.0,1.0,-1.0);
    glTexCoord2f(1.0,0.0);
    glVertex3f(1.0,1.0,1.0);
+   polys++;
    /* bottom */
    glTexCoord2f(0,0);
    glVertex3f(-1.0,-1.0,1.0);
@@ -719,42 +755,47 @@ static void drawfilledbox(boxedstruct *boxed, int wire)
    glVertex3f(1.0,-1.0,-1.0);
    glTexCoord2f(1,0);
    glVertex3f(1.0,-1.0,1.0);
+   polys++;
    glEnd();
+
+   return polys;
 }
 
 
 /*
  * Draw a box made of lines
  */ 
-static void drawbox(boxedstruct *boxed)
+static int drawbox(boxedstruct *boxed)
 {
+   int polys = 0;
    /* top */
    glBegin(GL_LINE_STRIP);
    glVertex3f(-1.0,1.0,1.0);
-   glVertex3f(-1.0,1.0,-1.0);
-   glVertex3f(1.0,1.0,-1.0);
-   glVertex3f(1.0,1.0,1.0);
-   glVertex3f(-1.0,1.0,1.0);
+   glVertex3f(-1.0,1.0,-1.0); polys++;
+   glVertex3f(1.0,1.0,-1.0); polys++;
+   glVertex3f(1.0,1.0,1.0); polys++;
+   glVertex3f(-1.0,1.0,1.0); polys++;
    glEnd();
    /* bottom */
    glBegin(GL_LINE_STRIP);
    glVertex3f(-1.0,-1.0,1.0);
-   glVertex3f(1.0,-1.0,1.0);
-   glVertex3f(1.0,-1.0,-1.0);
-   glVertex3f(-1.0,-1.0,-1.0);
-   glVertex3f(-1.0,-1.0,1.0);
+   glVertex3f(1.0,-1.0,1.0); polys++;
+   glVertex3f(1.0,-1.0,-1.0); polys++;
+   glVertex3f(-1.0,-1.0,-1.0); polys++;
+   glVertex3f(-1.0,-1.0,1.0); polys++;
    glEnd();
    /* connect top & bottom */
    glBegin(GL_LINES);
    glVertex3f(-1.0,1.0,1.0);
-   glVertex3f(-1.0,-1.0,1.0);
+   glVertex3f(-1.0,-1.0,1.0); polys++;
    glVertex3f(1.0,1.0,1.0);
-   glVertex3f(1.0,-1.0,1.0);
+   glVertex3f(1.0,-1.0,1.0); polys++;
    glVertex3f(1.0,1.0,-1.0);
-   glVertex3f(1.0,-1.0,-1.0);
+   glVertex3f(1.0,-1.0,-1.0); polys++;
    glVertex3f(-1.0,1.0,-1.0);
-   glVertex3f(-1.0,-1.0,-1.0);
+   glVertex3f(-1.0,-1.0,-1.0); polys++;
    glEnd();
+   return polys;
 }
 
 
@@ -762,8 +803,9 @@ static void drawbox(boxedstruct *boxed)
 /* 
  * Draw ball
  */
-static void drawball(boxedstruct *gp, ball *b, int wire)
+static int drawball(boxedstruct *gp, ball *b, int wire)
 {
+   int polys = 0;
    int i,pos,cnt;
    GLint *spherei = gp->spherei;
    vectorf *spherev = gp->spherev;
@@ -792,26 +834,31 @@ static void drawball(boxedstruct *gp, ball *b, int wire)
         glNormal3f(spherev[spherei[pos+0]].x,spherev[spherei[pos+0]].y,spherev[spherei[pos+0]].z);
         glVertex3f(spherev[spherei[pos+0]].x,spherev[spherei[pos+0]].y,spherev[spherei[pos+0]].z);
         glNormal3f(spherev[spherei[pos+1]].x,spherev[spherei[pos+1]].y,spherev[spherei[pos+1]].z);
+         gp->list_polys[GLL_BALL]++;
         glVertex3f(spherev[spherei[pos+1]].x,spherev[spherei[pos+1]].y,spherev[spherei[pos+1]].z);
         glNormal3f(spherev[spherei[pos+2]].x,spherev[spherei[pos+2]].y,spherev[spherei[pos+2]].z);
         glVertex3f(spherev[spherei[pos+2]].x,spherev[spherei[pos+2]].y,spherev[spherei[pos+2]].z);
+         gp->list_polys[GLL_BALL]++;
         glEnd();
       }
       glEndList();
       gp->gllists[GLL_BALL] = 1;
    } else {
       glCallList(gp->listobjects + GLL_BALL);
+      polys += gp->list_polys[GLL_BALL];
    }
    
    glPopMatrix();
+   return polys;
 }
 
     
 /* 
  * Draw all triangles in triman
  */
-static void drawtriman(triman *t, int wire) 
+static int drawtriman(triman *t, int wire) 
 {
+   int polys = 0;
    int i,pos;
    vectorf *spherev = t->vertices;
    GLfloat col[3];
@@ -837,66 +884,71 @@ static void drawtriman(triman *t, int wire)
       glVertex3f(spherev[pos+0].x,spherev[pos+0].y,spherev[pos+0].z);
       glVertex3f(spherev[pos+1].x,spherev[pos+1].y,spherev[pos+1].z);
       glVertex3f(spherev[pos+2].x,spherev[pos+2].y,spherev[pos+2].z);
+      polys++;
       glEnd();
       glPopMatrix();
    }   
    glPopMatrix();   
+   return polys;
 }
       
 /* 
  * draw floor pattern
  */   
-static void drawpattern(boxedstruct *gp)
+static int drawpattern(boxedstruct *gp)
 {
+   int polys = 0;
    if (!gp->gllists[GLL_PATTERN]) {
       glNewList(gp->listobjects + GLL_PATTERN, GL_COMPILE);
      
       glBegin(GL_LINE_STRIP);
       glVertex3f(-25.0f, 0.0f, 35.0f);
-      glVertex3f(-15.0f, 0.0f, 35.0f);
-      glVertex3f(-5.0f, 0.0f, 25.0f);
-      glVertex3f(5.0f, 0.0f, 25.0f);
-      glVertex3f(15.0f, 0.0f, 35.0f);
-      glVertex3f(25.0f, 0.0f, 35.0f);
-      glVertex3f(35.0f, 0.0f, 25.0f);
-      glVertex3f(35.0f, 0.0f, 15.0f);
-      glVertex3f(25.0f, 0.0f, 5.0f);
-      glVertex3f(25.0f, 0.0f, -5.0f);
-      glVertex3f(35.0f, 0.0f, -15.0f);
-      glVertex3f(35.0f, 0.0f, -25.0f);
-      glVertex3f(25.0f, 0.0f, -35.0f);
-      glVertex3f(15.0f, 0.0f,-35.0f);
-      glVertex3f(5.0f, 0.0f, -25.0f);
-      glVertex3f(-5.0f, 0.0f, -25.0f);
-      glVertex3f(-15.0f, 0.0f,-35.0f);
-      glVertex3f(-25.0f, 0.0f,-35.0f);
-      glVertex3f(-35.0f, 0.0f, -25.0f);
-      glVertex3f(-35.0f, 0.0f, -15.0f);
-      glVertex3f(-25.0f, 0.0f, -5.0f);
-      glVertex3f(-25.0f, 0.0f, 5.0f);
-      glVertex3f(-35.0f, 0.0f, 15.0f);
-      glVertex3f(-35.0f, 0.0f, 25.0f);
-      glVertex3f(-25.0f, 0.0f, 35.0f);
+      glVertex3f(-15.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-5.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(5.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(15.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(25.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(35.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(35.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(25.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(25.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(35.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(35.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(25.0f, 0.0f, -35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(15.0f, 0.0f,-35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(5.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-5.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-15.0f, 0.0f,-35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-25.0f, 0.0f,-35.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-35.0f, 0.0f, -25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-35.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-25.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-25.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-35.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-35.0f, 0.0f, 25.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-25.0f, 0.0f, 35.0f); gp->list_polys[GLL_PATTERN]++;
       glEnd();
       
       glBegin(GL_LINE_STRIP);
       glVertex3f(-5.0f, 0.0f, 15.0f);
-      glVertex3f(5.0f, 0.0f, 15.0f);
-      glVertex3f(15.0f, 0.0f, 5.0f);
-      glVertex3f(15.0f, 0.0f, -5.0f);
-      glVertex3f(5.0f, 0.0f, -15.0f);
-      glVertex3f(-5.0f, 0.0f, -15.0f);
-      glVertex3f(-15.0f, 0.0f, -5.0f);
-      glVertex3f(-15.0f, 0.0f, 5.0f);
-      glVertex3f(-5.0f, 0.0f, 15.0f);
+      glVertex3f(5.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(15.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(15.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(5.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-5.0f, 0.0f, -15.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-15.0f, 0.0f, -5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-15.0f, 0.0f, 5.0f); gp->list_polys[GLL_PATTERN]++;
+      glVertex3f(-5.0f, 0.0f, 15.0f); gp->list_polys[GLL_PATTERN]++;
       glEnd();
 
       glEndList();
       gp->gllists[GLL_PATTERN] = 1;
    } else {
       glCallList(gp->listobjects + GLL_PATTERN);
-   }   
+      polys += gp->list_polys[GLL_PATTERN];
+   }
 
+   return polys;
 }
       
       
@@ -925,6 +977,8 @@ static void draw(ModeInfo * mi)
    GLfloat l1_diffuse[] =    {0.5, 0.5, 0.5, 1.0};
    GLfloat l1_position[] =  {0.0, 1.0, 0.0, 0.0}; /* w = 0 -> directional light */
    
+   mi->polygon_count = 0;
+
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    
@@ -980,7 +1034,7 @@ static void draw(ModeInfo * mi)
    glColor3f(1.0,1.0,1.0);
    glScalef(20.0,0.25,20.0);
    glTranslatef(0.0,2.0,0.0);
-   drawfilledbox(gp, wire);
+   mi->polygon_count += drawfilledbox(gp, wire);
    glPopMatrix();
    glDisable(GL_TEXTURE_2D);
 
@@ -988,28 +1042,28 @@ static void draw(ModeInfo * mi)
    glColor3f(0.2,0.5,0.2);
    glScalef(20.0,20.0,0.25);
    glTranslatef(0.0,1.0,81.0);
-   drawbox(gp);
+   mi->polygon_count += drawbox(gp);
    glPopMatrix();
 
    glPushMatrix();
    glColor3f(0.2,0.5,0.2);
    glScalef(20.0,20.0,0.25);
    glTranslatef(0.0,1.0,-81.0);
-   drawbox(gp);
+   mi->polygon_count += drawbox(gp);
    glPopMatrix();
 
    glPushMatrix();
    glColor3f(0.2,0.5,0.2);
    glScalef(.25,20.0,20.0);
    glTranslatef(-81.0,1.0,0.0);
-   drawbox(gp);
+   mi->polygon_count += drawbox(gp);
    glPopMatrix();
 
    glPushMatrix();
    glColor3f(0.2,0.5,0.2);
    glScalef(.25,20.0,20.0);
    glTranslatef(81.0,1.0,0.0);
-   drawbox(gp);
+   mi->polygon_count += drawbox(gp);
    glPopMatrix();
 
    if (!wire) {
@@ -1035,10 +1089,10 @@ static void draw(ModeInfo * mi)
            updatetris(&gp->tman[i]);
         }
         glDisable(GL_CULL_FACE);
-        drawtriman(&gp->tman[i], wire);
+        mi->polygon_count += drawtriman(&gp->tman[i], wire);
         if (!wire) glEnable(GL_CULL_FACE);
       } else {
-        drawball(gp, &gp->bman.balls[i], wire);
+         mi->polygon_count += drawball(gp, &gp->bman.balls[i], wire);
       }
    }
       
@@ -1077,11 +1131,14 @@ pinit(ModeInfo * mi)
 
    glShadeModel(GL_SMOOTH);
    glClearDepth(1.0);
-   glClearColor(0.0,0.05,0.1,0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    /* Load configuration */
    setdefaultconfig(&gp->config);
+
+   /* give the decay parameter a better curve */
+   if (gp->config.decay <= 0.8182) { gp->config.decay = gp->config.decay / 3; }
+   else                            { gp->config.decay = (gp->config.decay - 0.75) * 4; }
    
    bman = &gp->bman;
    
@@ -1096,6 +1153,7 @@ pinit(ModeInfo * mi)
    for(i=0;i<bman->num_balls;i++) {
       gp->tman[i].explosion = (float) (((int)gp->config.explosion) / 15.0f );
       gp->tman[i].decay = gp->config.decay;
+      gp->tman[i].momentum = gp->config.momentum;
       gp->tman[i].vertices = NULL;
       gp->tman[i].normals = NULL;
       gp->tman[i].tris = NULL;