http://www.tienza.es/crux/src/www.jwz.org/xscreensaver/xscreensaver-5.05.tar.gz
[xscreensaver] / hacks / glx / boxed.c
index 2bff1ec01219afb893d79f38cccdfb0ba3129a74..42f68c1c1970ffc4d86f1785063465f2c421dd94 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"
@@ -53,7 +57,9 @@ static const char sccsid[] = "@(#)boxed.c     0.9 01/09/26 xlockmore";
 # define DEF_SPEED      "0.5"
 # define DEF_BALLS     "25"
 # define DEF_BALLSIZE   "2.0"
-# define DEF_EXPLOSION "25.0f"
+# define DEF_EXPLOSION "15.0"
+# define DEF_DECAY     "0.07"
+# define DEF_MOMENTUM  "0.6"
 
 #undef countof 
 #define countof(x) (int)(sizeof((x))/sizeof((*x)))
@@ -64,6 +70,8 @@ static GLfloat speed;  /* jwz -- overall speed factor applied to all motion */
 static int cfg_balls;
 static GLfloat cfg_ballsize;
 static GLfloat cfg_explosion;
+static GLfloat cfg_decay;
+static GLfloat cfg_momentum;
 
 
 static XrmOptionDescRec opts[] = {
@@ -71,13 +79,17 @@ static XrmOptionDescRec opts[] = {
     {"-balls", ".boxed.balls", XrmoptionSepArg, 0},
     {"-ballsize", ".boxed.ballsize", XrmoptionSepArg, 0},
     {"-explosion", ".boxed.explosion", XrmoptionSepArg, 0},
+    {"-decay", ".boxed.decay", XrmoptionSepArg, 0},
+    {"-momentum", ".boxed.momentum", XrmoptionSepArg, 0},
 };
 
 static argtype vars[] = {
     {&speed, "speed", "Speed", DEF_SPEED, t_Float},
     {&cfg_balls, "balls", "Balls", DEF_BALLS, t_Int},
     {&cfg_ballsize, "ballsize", "Ball Size", DEF_BALLSIZE, t_Float},
-    {&cfg_explosion, "explosion", "Exlosion", 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};
@@ -140,6 +152,7 @@ typedef struct {
    vectorf     loc;
    vectorf     dir;
    BOOL         far;
+   BOOL         gone;
 } tri;
 
 typedef struct {
@@ -147,6 +160,8 @@ typedef struct {
    int                 lifetime;
    float       scalefac;
    float       explosion;
+   float       decay;
+   float       momentum;
    vectorf     color;
    tri         *tris;
    GLint       *indices;
@@ -158,6 +173,8 @@ typedef struct {
    int numballs;
    float ballsize;
    float explosion;
+   float decay;
+   float momentum;
    BOOL textures;
    BOOL transparent;
    float camspeed;
@@ -253,6 +270,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;
+}
+
 
 
 /*
@@ -393,7 +416,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]);
+               }
            }
         }
         
@@ -464,13 +490,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;
    
@@ -482,6 +510,7 @@ static void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, i
    
    for (i=0; i<(tman->num_tri); i++) {
       tman->tris[i].far = FALSE;
+      tman->tris[i].gone = FALSE;
       pos = i * 3;
       /* kopieer elke poly apart naar een tri structure */
       copyvector(&tman->vertices[pos+0],&spherev[spherei[pos+0]]);
@@ -529,6 +558,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);
    }
 }
 
@@ -543,6 +578,8 @@ static void updatetris(triman *t)
    GLfloat xd,zd;
    
    for (b=0;b<t->num_tri;b++) {
+      /* the exploded triangles disappear over time */
+      if (rnd() < t->decay) { t->tris[b].gone = TRUE; }
       /* apply gravity */
       t->tris[b].dir.y -= (0.1f * speed);
       /* apply movement */
@@ -632,10 +669,15 @@ static void setdefaultconfig(boxed_config *config)
   cfg_balls = MAX(3,MIN(40,cfg_balls));
   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;
 }
@@ -815,6 +857,7 @@ static void drawtriman(triman *t, int wire)
    glMaterialfv(GL_FRONT, GL_EMISSION,col);
    
    for (i=0; i<t->num_tri; i++) {
+      if (t->tris[i].gone == TRUE) { continue; }
       pos = i*3;
       glPushMatrix();
       glTranslatef(t->tris[i].loc.x,t->tris[i].loc.y,t->tris[i].loc.z);
@@ -1068,6 +1111,10 @@ pinit(ModeInfo * mi)
    
    /* 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;
    
@@ -1081,6 +1128,8 @@ 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;