ftp://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/redhat/linux/enterprise/4/en/os...
[xscreensaver] / hacks / glx / boxed.c
index 30d5f6f872b58231e524b2cab4294e8851bc3e82..e9da0e3b03793b9ace49797d5132dd0187600985 100644 (file)
@@ -1,8 +1,7 @@
 /* thebox --- 3D bouncing balls that explode */
 
-#if !defined( lint ) && !defined( SABER )
+#if 0
 static const char sccsid[] = "@(#)boxed.c      0.9 01/09/26 xlockmore";
-
 #endif
 
 /*-
@@ -36,17 +35,18 @@ static const char sccsid[] = "@(#)boxed.c   0.9 01/09/26 xlockmore";
 */
 
 #ifdef STANDALONE
-# define PROGCLASS                                     "boxed"
-# define HACK_INIT                                     init_boxed
-# define HACK_DRAW                                     draw_boxed
-# define HACK_RESHAPE                                  reshape_boxed
-# define boxed_opts                                    xlockmore_opts
-# define DEFAULTS      "*delay:                20000   \n"                     \
-     "*showFPS:         False   \n"                    \
-
-# include "xlockmore.h"                                /* from the xscreensaver distribution */
+# define PROGCLASS     "boxed"
+# define HACK_INIT     init_boxed
+# define HACK_DRAW     draw_boxed
+# define HACK_RESHAPE  reshape_boxed
+# define boxed_opts    xlockmore_opts
+# define DEFAULTS      "*delay:   20000   \n"  \
+                       "*showFPS: False   \n"  \
+                       "*speed:   0.5     \n"  \
+
+# include "xlockmore.h"                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
-# include "xlock.h"                                    /* from the xlockmore distribution */
+# include "xlock.h"            /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
 #ifdef USE_GL
@@ -55,25 +55,20 @@ static const char sccsid[] = "@(#)boxed.c   0.9 01/09/26 xlockmore";
 #undef countof 
 #define countof(x) (int)(sizeof((x))/sizeof((*x)))
 #undef rnd
-#define rnd() ( ((float)random()) / ((float)RAND_MAX * 2.0) )
+#define rnd() (frand(1.0))
 
-/* #define DEF_PLANETARY "False"
+GLfloat speed;  /* jwz -- overall speed factor applied to all motion */
 
-static int planetary;
 
 static XrmOptionDescRec opts[] = {
-  {"-planetary", ".gears.planetary", XrmoptionNoArg, (caddr_t) "true" },
-  {"+planetary", ".gears.planetary", XrmoptionNoArg, (caddr_t) "false" },
+    {"-speed", ".boxed.speed", XrmoptionSepArg, 0},
 };
 
 static argtype vars[] = {
-  {(caddr_t *) &planetary, "planetary", "Planetary", DEF_PLANETARY, t_Bool},
+    {&speed, "speed", "Speed", "1.0", t_Float},
 };
-*/
 
-/* ModeSpecOpts boxed_opts = {countof(opts), opts, countof(vars), vars, NULL}; */
-
-ModeSpecOpt boxed_opts = {0, NULL, 0, NULL, NULL};
+ModeSpecOpt boxed_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
 #ifdef USE_MODULES
 
@@ -91,6 +86,7 @@ ModStruct   boxed_description = {
 
 /* rendering defines */
 
+
 /* box size */
 #define BOX_SIZE       20.0f
 
@@ -101,7 +97,7 @@ ModStruct   boxed_description = {
 #define CAMDISTANCE_SPEED 1.5
 
 /* rendering the sphere */
-#define MESH_SIZE      5
+#define MESH_SIZE      10
 #define SPHERE_VERTICES        (2+MESH_SIZE*MESH_SIZE*2)
 #define SPHERE_INDICES ((MESH_SIZE*4 + MESH_SIZE*4*(MESH_SIZE-1))*3)
 
@@ -176,16 +172,16 @@ typedef struct {
    ballman        bman;
    triman         *tman;
    GLXContext     *glx_context;
-   GLint          listobjects;
-   GLint          gllists[3];
+   GLuint         listobjects;
+   GLuint         gllists[3];
    Window         window;
    BOOL           stop;
    char           *tex1;
 } boxedstruct;
 
-#define GLL_PATTERN 1
-#define GLL_BALL    2
-#define GLL_BOX     3
+#define GLL_PATTERN 0
+#define GLL_BALL    1
+#define GLL_BOX     2
 
 /*
 **----------------------------------------------------------------------------
@@ -343,14 +339,15 @@ static void generatesphere(void)
  * create fresh ball 
  */
 
-void createball(ball *newball) {
+void createball(ball *newball) 
+{
    float r=0.0f,g=0.0f,b=0.0f;
    newball->loc.x = 5-10*rnd();
    newball->loc.y = 35+20*rnd();
    newball->loc.z = 5-10*rnd();
-   newball->dir.x = 0.5f-rnd();
+   newball->dir.x = (0.5f-rnd()) * speed;
    newball->dir.y = 0.0;
-   newball->dir.z = 0.5-rnd();
+   newball->dir.z = (0.5-rnd())  * speed;
    newball->offside = 0;
    newball->bounced = FALSE;
    newball->radius = BALLSIZE;
@@ -364,15 +361,18 @@ void createball(ball *newball) {
 
 /* Update position of each ball */
 
-void updateballs(ballman *bman) {
+void updateballs(ballman *bman) 
+{
    register int b,j;
    vectorf dvect,richting,relspeed,influence;
    GLfloat squaredist;
 
    for (b=0;b<bman->num_balls;b++) {
 
+     GLfloat gravity = 0.15f * speed;
+
       /* apply gravity */
-      bman->balls[b].dir.y -= 0.15f;
+      bman->balls[b].dir.y -= gravity;
       /* apply movement */
       addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir);
       /* boundary check */
@@ -458,7 +458,8 @@ void updateballs(ballman *bman) {
 * explode ball into triangles
 */
 
-void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, int ind_num, ball *b) {
+void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, int ind_num, ball *b)
+{
    int pos;
    float explosion;
    float scale;
@@ -512,9 +513,9 @@ void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, int ind_
             
       /* bereken nieuwe richting */
       scalevector(&tman->tris[i].dir,&avgdir,explosion);
-      dvect.x = 0.1f - 0.2f*rnd();
-      dvect.y = 0.15f - 0.3f*rnd();
-      dvect.z = 0.1f - 0.2f*rnd(); 
+      dvect.x = (0.1f - 0.2f*rnd());
+      dvect.y = (0.15f - 0.3f*rnd());
+      dvect.z = (0.1f - 0.2f*rnd());
       addvectors(&tman->tris[i].dir,&tman->tris[i].dir,&dvect);
    }
 }
@@ -524,12 +525,14 @@ void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, int ind_
 * update position of each tri
 */
 
-void updatetris(triman *t) {
+void updatetris(triman *t) 
+{
    int b;
-
+   GLfloat xd,zd;
+   
    for (b=0;b<t->num_tri;b++) {
       /* apply gravity */
-      t->tris[b].dir.y -= 0.1f;
+      t->tris[b].dir.y -= (0.1f * speed);
       /* apply movement */
       addvectors(&t->tris[b].loc,&t->tris[b].loc,&t->tris[b].dir);
       /* boundary check */
@@ -541,7 +544,7 @@ void updatetris(triman *t) {
             (t->tris[b].loc.z < 100.0f)) {  /* in veld  */
            t->tris[b].dir.y = -(t->tris[b].dir.y);
            t->tris[b].loc.y = -t->tris[b].loc.y;
-           scalevector(&t->tris[b].dir,&t->tris[b].dir,0.75f); /* dampening */
+           scalevector(&t->tris[b].dir,&t->tris[b].dir,0.80f); /* dampening */
         }
         else {
            t->tris[b].far = TRUE;
@@ -549,33 +552,44 @@ void updatetris(triman *t) {
         }
       }
       
-      /* this should be replaced with code that determines 
-       * the correct wall the tri bounces in to. this code sucks.
-       */
-       if ((t->tris[b].loc.x > -21.0f) &
+      if ((t->tris[b].loc.x > -21.0f) &
          (t->tris[b].loc.x < 21.0f) &
          (t->tris[b].loc.z > -21.0f) &
          (t->tris[b].loc.z < 21.0f)) { /* in box? */
+
+        xd = zd = 999.0f; /* big */
         if ((t->tris[b].loc.x > -21.0f) &
             (t->tris[b].loc.x < 0)) {
-           t->tris[b].loc.x = -21.0f;
-           t->tris[b].dir.x = -t->tris[b].dir.x;
+           xd = t->tris[b].loc.x + 21.0f;
         }
         if ((t->tris[b].loc.x < 21.0f) &
             (t->tris[b].loc.x > 0)) {
-           t->tris[b].loc.x = 21.0f;
-           t->tris[b].dir.x = -t->tris[b].dir.x;
+           xd = 21.0f - t->tris[b].loc.x;
         }
         if ((t->tris[b].loc.z > -21.0f) &
             (t->tris[b].loc.z < 0)) {
-           t->tris[b].loc.z = -21.0f;
-           t->tris[b].dir.z = -t->tris[b].dir.z;
+           zd = t->tris[b].loc.z + 21.0f;
         }
         if ((t->tris[b].loc.z < 21.0f) &
             (t->tris[b].loc.z > 0)) {
-           t->tris[b].loc.z = 21.0f;
-           t->tris[b].dir.z = -t->tris[b].dir.z;
+           zd = 21.0f - t->tris[b].loc.z;
         }
+        if (xd < zd) {
+           /* bounce x */
+           if (t->tris[b].dir.x < 0) 
+             t->tris[b].loc.x += (21.0f - t->tris[b].loc.x);
+           else
+             t->tris[b].loc.x += (-21.0f - t->tris[b].loc.x);
+           t->tris[b].dir.x = -t->tris[b].dir.x;
+        } else { 
+           /* bounce z */
+           if (t->tris[b].dir.z < 0)
+             t->tris[b].loc.z += (21.0f - t->tris[b].loc.z);
+           else
+             t->tris[b].loc.z += (-21.0f - t->tris[b].loc.z);
+           t->tris[b].dir.z = -t->tris[b].dir.z;
+        }       
+              
       }
    } /* end for b */
 } 
@@ -584,7 +598,8 @@ void updatetris(triman *t) {
 /*
  * free memory allocated by a tri manager
  */
-void freetris(triman *t) {
+void freetris(triman *t) 
+{
    if (!t) return;
    if (t->tris) free(t->tris);
    if (t->vertices) free(t->vertices);
@@ -600,7 +615,8 @@ void freetris(triman *t) {
 /*
  *load defaults in config structure
  */
-void setdefaultconfig(boxed_config *config) {
+void setdefaultconfig(boxed_config *config) 
+{
   config->numballs = NUMBALLS;
   config->textures = TRUE;
   config->transparent = FALSE;
@@ -740,7 +756,7 @@ static void drawball(boxedstruct *gp, ball *b)
    glMaterialfv(GL_FRONT, GL_EMISSION,col);
 
    if (!gp->gllists[GLL_BALL]) {
-      glNewList(gp->listobjects + GLL_BALL,GL_COMPILE_AND_EXECUTE);
+      glNewList(gp->listobjects + GLL_BALL,GL_COMPILE);
       cnt = SPHERE_INDICES/3;
       for (i=0; i<cnt; i++) {
         pos = i * 3;
@@ -804,8 +820,8 @@ static void drawtriman(triman *t)
 static void drawpattern(boxedstruct *boxed)
 {
    if (!boxed->gllists[GLL_PATTERN]) {
-      glNewList(boxed->listobjects + GLL_PATTERN,GL_COMPILE_AND_EXECUTE);
-      
+      glNewList(boxed->listobjects + GLL_PATTERN, GL_COMPILE);
+     
       glBegin(GL_LINE_STRIP);
       glVertex3f(-25.0f, 0.0f, 35.0f);
       glVertex3f(-15.0f, 0.0f, 35.0f);
@@ -845,11 +861,13 @@ static void drawpattern(boxedstruct *boxed)
       glVertex3f(-15.0f, 0.0f, 5.0f);
       glVertex3f(-5.0f, 0.0f, 15.0f);
       glEnd();
+
       glEndList();
       boxed->gllists[GLL_PATTERN] = 1;
    } else {
       glCallList(boxed->listobjects + GLL_PATTERN);
    }   
+
 }
       
       
@@ -883,10 +901,10 @@ static void draw(ModeInfo * mi)
    gp->tic += 0.01f;
 
    /* rotate camera around (0,0,0), looking at (0,0,0), up is (0,1,0) */
-   dcam = CAMDISTANCE_MIN + (CAMDISTANCE_MAX - CAMDISTANCE_MIN) + (CAMDISTANCE_MAX - CAMDISTANCE_MIN)*cos(gp->tic/CAMDISTANCE_SPEED);
-   v1.x = dcam * sin(gp->tic/gp->cam_x_speed);
-   v1.z = dcam * cos(gp->tic/gp->cam_z_speed);
-   v1.y = CAM_HEIGHT * sin(gp->tic/gp->cam_y_speed) + 1.02 * CAM_HEIGHT;
+   dcam = CAMDISTANCE_MIN + (CAMDISTANCE_MAX - CAMDISTANCE_MIN) + (CAMDISTANCE_MAX - CAMDISTANCE_MIN)*cos((gp->tic/CAMDISTANCE_SPEED) * speed);
+   v1.x = dcam * sin((gp->tic/gp->cam_x_speed) * speed);
+   v1.z = dcam * cos((gp->tic/gp->cam_z_speed) * speed);
+   v1.y = CAM_HEIGHT * sin((gp->tic/gp->cam_y_speed) * speed) + 1.02 * CAM_HEIGHT;
    gluLookAt(v1.x,v1.y,v1.z,0.0,0.0,0.0,0.0,1.0,0.0); 
 
    glLightfv(GL_LIGHT0, GL_AMBIENT, l0_ambient); 
@@ -975,11 +993,12 @@ static void draw(ModeInfo * mi)
         gp->bman.balls[i].justcreated = FALSE;
         freetris(&gp->tman[i]);
       }
-      if ((gp->bman.balls[i].bounced) & (gp->tman[i].vertices == NULL)) {
-        createtrisfromball(&gp->tman[i],gp->spherev,gp->spherei,SPHERE_INDICES,&gp->bman.balls[i]);
-      }
-      if (gp->bman.balls[i].bounced) {
-        updatetris(&gp->tman[i]);
+      if (gp->bman.balls[i].bounced) { 
+        if (gp->tman[i].vertices == NULL) {
+           createtrisfromball(&gp->tman[i],gp->spherev,gp->spherei,SPHERE_INDICES,&gp->bman.balls[i]);
+        } else {
+           updatetris(&gp->tman[i]);
+        }
         glDisable(GL_CULL_FACE);
         drawtriman(&gp->tman[i]);
         glEnable(GL_CULL_FACE);
@@ -1077,7 +1096,7 @@ pinit(ModeInfo * mi)
                          GL_RGB, GL_UNSIGNED_BYTE, gp->tex1);
    if (i)
      {
-       const char *s = gluErrorString (i);
+       const char *s = (char *) gluErrorString (i);
        fprintf (stderr, "%s: error mipmapping texture: %s\n",
                 progname, (s ? s : "(unknown)"));
        exit (1);
@@ -1148,6 +1167,8 @@ draw_boxed(ModeInfo * mi)
 void
 release_boxed(ModeInfo * mi)
 {
+   int i;
+   
    if (boxed != NULL) {
       int screen;
       
@@ -1158,23 +1179,16 @@ release_boxed(ModeInfo * mi)
            /* Display lists MUST be freed while their glXContext is current. */
            glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
            
-           /*if (glIsList(gp->gear1))
-             glDeleteLists(gp->gear1, 1);
-           if (glIsList(gp->gear2))
-             glDeleteLists(gp->gear2, 1);
-           if (glIsList(gp->gear3))
-             glDeleteLists(gp->gear3, 1);
-           if (glIsList(gp->gear_inner))
-             glDeleteLists(gp->gear_inner, 1);
-           if (glIsList(gp->gear_outer))
-             glDeleteLists(gp->gear_outer, 1);
-            */
+           if (glIsList(gp->listobjects))
+             glDeleteLists(gp->listobjects, 3);
            
-           /* TODO 
-            * free all trimans
-            * free all balls
-            * free all sphere indices & vertices
-            */
+           for (i=0;i<gp->bman.num_balls;i++) {
+              if (gp->bman.balls[i].bounced) freetris(&gp->tman[i]);
+           }
+           free (gp->bman.balls);
+           free (gp->tman);
+           free (gp->tex1);
+                
            
         }
       }