ftp://ftp.jp.xemacs.org/pub/NetBSD/packages/distfiles/xscreensaver-4.15.tar.gz
[xscreensaver] / hacks / glx / blinkbox.c
index bbd1e599f0326a1bc1239a123fa8df4d36111518..c057943f5344066893eb6704aad6e98e83b211eb 100644 (file)
@@ -5,7 +5,7 @@
  * the above copyright notice appear in all copies and that both that
  * copyright notice and this permission notice appear in supporting
  * documentation.  No representations are made about the suitability of this
- * software for any purpose.  It is provided "as is" without express or 
+ * software for any purpose.  It is provided "as is" without express or
  * implied warranty.
  */
 
@@ -18,10 +18,22 @@ extern XtAppContext app;
 #define HACK_DRAW        draw_ball
 #define HACK_RESHAPE  reshape_ball
 #define sws_opts         xlockmore_opts
-
 #define MAX_COUNT 20
+#define ALPHA_AMT 0.05
+
+/* this should be between 1 and 4 */
+#define DEF_WH      "1"
+#define DEF_DISSOLVE "False"
+#define DEF_FADE    "True"
 
-#define DEFAULTS       "*delay:        30000       \n" \
+#define DEFAULTS       "*delay:          30000         \n" \
+                               "*wireframe:  False      \n" \
+                       "*boxsize:  " DEF_WH      "\n" \
+                    "*dissolve:  " DEF_DISSOLVE "\n" \
+                    "*fade:     " DEF_FADE    "\n" \
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
 
 #include "xlockmore.h"
 #include "sphere.h"
@@ -42,6 +54,8 @@ typedef struct{
   int counter;
   GLfloat color[3];
   GLfloat rot[4];
+  int des_count;
+  int alpha_count;
 }Side;
 
 struct Bounding_box {
@@ -56,28 +70,51 @@ struct Ball {
   int d;
 } ball = {0,0,0,1};
 
+struct {
+  GLfloat wh; /*width Height*/
+  GLfloat d; /*depth*/
+} bscale = {1, 0.25};
+
 static GLuint ballList;
 static GLuint boxList;
 Tdpos mo = { 1.0, 1.0, 1.0};  /*motion*/
 Tdpos moh= {-1.0,-1.5,-1.5}; /*hold motion value*/
 
-GLfloat bscale[3] = {1,1,0.25};
-GLfloat bpos[3];
+Tdpos bpos= {1.0, 1.0, 1.0};
 
 /*sides*/
-static Side lside = {0, {0, 0, 0,}, MAX_COUNT,  {1.0, 0.0, 0.0},{90,0,1,0}};/*Red*/
-static Side rside = {0, {0, 0, 0,}, MAX_COUNT,  {0.0, 1.0, 0.0},{90,0,1,0}};/*Green*/
-static Side tside = {0, {0, 0, 0,}, MAX_COUNT,  {0.0, 0.0, 1.0},{90,1,0,0}};/*Blue*/
-static Side bside = {0, {0, 0, 0,}, MAX_COUNT,  {1.0, 0.5, 0.0},{90,1,0,0}};/*Orange*/
-static Side fside = {0, {0, 0, 0,}, MAX_COUNT,  {1.0, 1.0, 0.0},{90,0,0,1}};/*Yellow*/
-static Side aside = {0, {0, 0, 0,}, MAX_COUNT,  {0.5, 0.0, 1.0},{90,0,0,1}};/*Purple*/
+static Side lside = {0, {0, 0, 0,}, MAX_COUNT,  {1.0, 0.0, 0.0},{90,0,1,0},1,1};/*Red*/
+static Side rside = {0, {0, 0, 0,}, MAX_COUNT,  {0.0, 1.0, 0.0},{90,0,1,0},1,1};/*Green*/
+static Side tside = {0, {0, 0, 0,}, MAX_COUNT,  {0.0, 0.0, 1.0},{90,1,0,0},1,1};/*Blue*/
+static Side bside = {0, {0, 0, 0,}, MAX_COUNT,  {1.0, 0.5, 0.0},{90,1,0,0},1,1};/*Orange*/
+static Side fside = {0, {0, 0, 0,}, MAX_COUNT,  {1.0, 1.0, 0.0},{90,0,0,1},1,1};/*Yellow*/
+static Side aside = {0, {0, 0, 0,}, MAX_COUNT,  {0.5, 0.0, 1.0},{90,0,0,1},1,1};/*Purple*/
 Side *sp;
 
 /* lights */
 static float LightDiffuse[]=   { 1.0f, 1.0f, 1.0f, 1.0f };
 static float LightPosition[]=  { 20.0f, 100.0f, 20.0f, 1.0f };
 
-ModeSpecOpt sws_opts = {0,NULL,0,NULL,NULL};
+static Bool do_dissolve;
+static Bool do_fade;
+static GLfloat des_amt   = 1;
+
+static XrmOptionDescRec opts[] = {
+  { "-boxsize", ".boxsize", XrmoptionSepArg, 0 },
+  { "-dissolve", ".dissolve", XrmoptionNoArg, "True" },
+  { "+dissolve", ".dissolve", XrmoptionNoArg, "False" },
+  { "-fade",    ".fade",    XrmoptionNoArg, "True" },
+  { "+fade",    ".fade",    XrmoptionNoArg, "False" }
+
+};
+
+static argtype vars[] = {
+  {(caddr_t *) &bscale.wh,  "boxsize",  "Boxsize",  DEF_WH,      t_Float},
+  {(caddr_t *) &do_dissolve, "dissolve",  "Dissolve",  DEF_DISSOLVE, t_Bool},
+  {(caddr_t *) &do_fade,    "fade",     "Fade",     DEF_FADE,    t_Bool},
+};
+
+ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
 void
 swap(GLfloat *a, GLfloat *b)
@@ -87,7 +124,7 @@ swap(GLfloat *a, GLfloat *b)
   *b = t;
 }
 
-float 
+float
 get_rand(void)
 {
   GLfloat j = 1+(random() % 2);
@@ -106,7 +143,7 @@ swap_mov(GLfloat *a, GLfloat *b)
     *a = j;
 }
 
-void 
+void
 cp_b_pos(Tdpos *s_pos){
   s_pos->x = ball.x;
   s_pos->y = ball.y;
@@ -116,15 +153,19 @@ cp_b_pos(Tdpos *s_pos){
 void
 hit_side(void)
 {
-  if ((ball.x - ball.d) <= bbox.bottom.x){ 
+  if ((ball.x - ball.d) <= bbox.bottom.x){
     lside.hit = 1;
-    lside.counter = MAX_COUNT;
+    lside.counter   = MAX_COUNT;
+    lside.des_count = 1;
+    lside.alpha_count = 0;
     cp_b_pos(&lside.pos);
     swap_mov(&mo.x,&moh.x);
   }else
-  if ((ball.x + ball.d) >= bbox.top.x){ 
+  if ((ball.x + ball.d) >= bbox.top.x){
     rside.hit = 1;
     rside.counter = MAX_COUNT;
+    rside.des_count = 1;
+    rside.alpha_count = 0;
     cp_b_pos(&rside.pos);
     swap_mov(&mo.x,&moh.x);
   }
@@ -135,13 +176,17 @@ hit_top_bottom(void)
 {
   if ((ball.y - ball.d) <= bbox.bottom.y){
     bside.hit = 1;
-    bside.counter = MAX_COUNT;    
+    bside.counter = MAX_COUNT;
+    bside.des_count = 1;
+    bside.alpha_count = 0;
     cp_b_pos(&bside.pos);
     swap_mov(&mo.y,&moh.y);
   }else
   if ((ball.y + ball.d) >= bbox.top.y){
     tside.hit = 1;
     tside.counter = MAX_COUNT;
+    tside.des_count = 1;
+    tside.alpha_count = 0;
     cp_b_pos(&tside.pos);
     swap_mov(&mo.y,&moh.y);
   }
@@ -149,16 +194,20 @@ hit_top_bottom(void)
 
 void
 hit_front_back(void)
-{    
+{
   if ((ball.z - ball.d) <= bbox.bottom.z){
     aside.hit = 1;
     aside.counter = MAX_COUNT;
+    aside.des_count = 1;
+    aside.alpha_count = 0;
     cp_b_pos(&aside.pos);
     swap_mov(&mo.z,&moh.z);
   }else
   if((ball.z + ball.d) >= bbox.top.z){
     fside.hit = 1;
     fside.counter = MAX_COUNT;
+    fside.des_count = 1;
+    fside.alpha_count = 0;
     cp_b_pos(&fside.pos);
     swap_mov(&mo.z,&moh.z);
   }
@@ -183,11 +232,11 @@ reshape_ball (ModeInfo *mi, int width, int height)
 }
 
 void
-unit_cube(void)
+unit_cube(int wire)
 {
-  glBegin(GL_QUADS);           
+  glBegin((wire)?GL_LINE_LOOP:GL_QUADS);
   glNormal3f( 0.0f, -1.0f, 0.0f);
-  glVertex3f(-1.0f, -1.0f, -1.0f);     
+  glVertex3f(-1.0f, -1.0f, -1.0f);
   glVertex3f( 1.0f, -1.0f, -1.0f);
   glVertex3f( 1.0f, -1.0f,  1.0f);
   glVertex3f(-1.0f, -1.0f,  1.0f);
@@ -200,7 +249,7 @@ unit_cube(void)
   glVertex3f(-1.0f, -1.0f, -1.0f);
   glVertex3f(-1.0f,  1.0f, -1.0f);
   glVertex3f( 1.0f,  1.0f, -1.0f);
-  glVertex3f( 1.0f, -1.0f, -1.0f);     
+  glVertex3f( 1.0f, -1.0f, -1.0f);
   glNormal3f( 1.0f,  0.0f,  0.0f);
   glVertex3f( 1.0f, -1.0f, -1.0f);
   glVertex3f( 1.0f,  1.0f, -1.0f);
@@ -216,50 +265,75 @@ unit_cube(void)
   glVertex3f(-1.0f,  1.0f,  1.0f);
   glVertex3f( 1.0f,  1.0f,  1.0f);
   glVertex3f( 1.0f,  1.0f, -1.0f);
-  glEnd();                                             
+  glEnd();
 }
 
-void 
+void
 init_ball (ModeInfo *mi)
-{ 
+{
   #define SPHERE_SLICES 32  /* how densely to render spheres */
   #define SPHERE_STACKS 16
+  int wire = MI_IS_WIREFRAME(mi);
+
   sp = malloc(sizeof(*sp));
   if(sp == NULL){
     fprintf(stderr,"Could not allocate memory\n");
     exit(1);
   }
+  if( (bscale.wh < 1) ||
+      (bscale.wh > 4) ) {
+    fprintf(stderr,"Boxsize out of range. Using default\n");
+    bscale.wh = 1;
+  }
+  if (do_dissolve){
+    des_amt = bscale.wh / MAX_COUNT;
+  }
   init_GL(mi);
   reshape_ball(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
   ballList = glGenLists(1);
   glNewList(ballList, GL_COMPILE);
-  unit_sphere (SPHERE_STACKS, SPHERE_SLICES, False);
+  unit_sphere (SPHERE_STACKS, SPHERE_SLICES, wire);
   glEndList ();
 
   boxList = glGenLists(1);
   glNewList(boxList, GL_COMPILE);
-  unit_cube();
+  unit_cube(wire);
   glEndList();
 
+  if (wire) return;
+
   glEnable(GL_COLOR_MATERIAL);
-  glShadeModel(GL_SMOOTH);                             
+  glShadeModel(GL_SMOOTH);
   glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
-  glClearDepth(1.0f);                          
-  glEnable(GL_DEPTH_TEST);             
+  glClearDepth(1.0f);
+  glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   glEnable(GL_LIGHTING);
   glClearDepth(1);
   glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
   glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
   glEnable(GL_LIGHT1);
+  if (do_fade){
+    glEnable(GL_BLEND);
+    glDisable(GL_DEPTH_TEST);
+  }
+}
+
+void
+CheckBoxPos(GLfloat bot_x, GLfloat top_x, GLfloat bot_y, GLfloat top_y)
+{
+  /*Make sure it's inside of the bounding box*/
+  bpos.x = ((bpos.x - bscale.wh) < bot_x) ? bot_x + bscale.wh : bpos.x;
+  bpos.x = ((bpos.x + bscale.wh) > top_x) ? top_x - bscale.wh : bpos.x;
+  bpos.y = ((bpos.y - bscale.wh) < bot_y) ? bot_y + bscale.wh : bpos.y;
+  bpos.y = ((bpos.y + bscale.wh) > top_y) ? top_y - bscale.wh : bpos.y;
 }
 
 void
 draw_ball (ModeInfo *mi)
-{  
+{
    Display *dpy = MI_DISPLAY(mi);
    Window window = MI_WINDOW(mi);
-   /*int dem = 1;*/
    int i = 0;
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -271,6 +345,7 @@ draw_ball (ModeInfo *mi)
    glRotated(0.25,0,1,0);
    glRotated(0.25,1,0,0);
 
+
    glColor3f(1,1,1);
    glPushMatrix();
    glTranslatef(ball.x += mo.x,
@@ -284,60 +359,83 @@ draw_ball (ModeInfo *mi)
     switch(i){
       case 0:{
                sp = &lside;
-               bpos[0] = lside.pos.z*-1;
-               bpos[1] = lside.pos.y;
-               bpos[2] = bbox.bottom.x - bscale[3];
+               bpos.x = lside.pos.z*-1;
+               bpos.y = lside.pos.y;
+               bpos.z = bbox.bottom.x - bscale.d;
+               if (sp->hit)
+                CheckBoxPos(bbox.bottom.z,bbox.top.z,bbox.bottom.y,bbox.top.y);
                break;
              }
       case 1:{
                sp = &rside;
-               bpos[0] = rside.pos.z*-1;
-               bpos[1] = rside.pos.y;
-               bpos[2] = bbox.top.x + bscale[3];
+               bpos.x = rside.pos.z*-1;
+               bpos.y = rside.pos.y;
+               bpos.z = bbox.top.x + bscale.d;
+               if (sp->hit)
+                CheckBoxPos(bbox.bottom.z,bbox.top.z,bbox.bottom.y,bbox.top.y);
                break;
              }
       case 2:{
                sp = &tside;
-               bpos[0] = tside.pos.x;
-               bpos[1] = tside.pos.z;
-               bpos[2] = bbox.bottom.y - bscale[3];
+               bpos.x = tside.pos.x;
+               bpos.y = tside.pos.z;
+               bpos.z = bbox.bottom.y - bscale.d;
+               if (sp->hit)
+                CheckBoxPos(bbox.bottom.x,bbox.top.x,bbox.bottom.z,bbox.top.z);
                break;
              }
       case 3:{
                sp = &bside;
-               bpos[0] = bside.pos.x;
-               bpos[1] = bside.pos.z;
-               bpos[2] = bbox.top.y + bscale[3];
+               bpos.x = bside.pos.x;
+               bpos.y = bside.pos.z;
+               bpos.z = bbox.top.y + bscale.d;
+               if (sp->hit)
+                CheckBoxPos(bbox.bottom.x,bbox.top.x,bbox.bottom.z,bbox.top.z);
                break;
              }
       case 4:{
                sp = &fside;
-               bpos[0] = fside.pos.y;
-               bpos[1] = fside.pos.x*-1;
-               bpos[2] = bbox.top.z + bscale[3];
+               bpos.x = fside.pos.y;
+               bpos.y = fside.pos.x*-1;
+               bpos.z = bbox.top.z + bscale.d;
+               if (sp->hit)
+                CheckBoxPos(bbox.bottom.y,bbox.top.y,bbox.bottom.x,bbox.top.x);
                break;
              }
       case 5:{
                sp = &aside;
-               bpos[0] = aside.pos.y;
-               bpos[1] = aside.pos.x*-1;
-               bpos[2] = bbox.bottom.z + bscale[3];
+               bpos.x = aside.pos.y;
+               bpos.y = aside.pos.x*-1;
+               bpos.z = bbox.bottom.z + bscale.d;
+               if (sp->hit)
+                CheckBoxPos(bbox.bottom.y,bbox.top.y,bbox.bottom.x,bbox.top.x);
                break;
              }
     }
     if(sp->hit){
-     glColor3fv(sp->color);
-     glPushMatrix();
-     glRotatef(sp->rot[0],sp->rot[1],sp->rot[2],sp->rot[3]);
-     glTranslatef(bpos[0],bpos[1],bpos[2]);
-     /*dem = (MAX_COUNT-(sp->counter+1));*/
-     /*glScalef(bscale[0]/dem,bscale[1]/dem,bscale[2]);*/
-     glScalef(bscale[0],bscale[1],bscale[2]);
-     glCallList(boxList);
-     glPopMatrix();
-     sp->counter--;
-     if(!sp->counter)
-       sp->hit = 0;
+      if(do_fade){
+        glColor4f(sp->color[0],sp->color[1],sp->color[2],1-(ALPHA_AMT * sp->alpha_count));
+      }else{
+        glColor3fv(sp->color);
+      }
+      glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+      glPushMatrix();
+      glRotatef(sp->rot[0],sp->rot[1],sp->rot[2],sp->rot[3]);
+      glTranslatef(bpos.x,bpos.y,bpos.z);
+      if (do_dissolve) {
+         glScalef(bscale.wh-(des_amt*sp->des_count),bscale.wh-(des_amt*sp->des_count),bscale.d);
+      }else{
+        glScalef(bscale.wh,bscale.wh,bscale.d);
+      }
+      glCallList(boxList);
+      glPopMatrix();
+      sp->counter--;
+      sp->des_count++;
+      sp->alpha_count++;
+      if(!sp->counter)
+      {
+        sp->hit = 0;
+      }
     }
     i++;
   }