diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/boxed.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/glx/boxed.c')
-rw-r--r-- | hacks/glx/boxed.c | 1370 |
1 files changed, 1370 insertions, 0 deletions
diff --git a/hacks/glx/boxed.c b/hacks/glx/boxed.c new file mode 100644 index 0000000..136d468 --- /dev/null +++ b/hacks/glx/boxed.c @@ -0,0 +1,1370 @@ +/* boxed --- 3D bouncing balls that explode */ + +#if 0 +static const char sccsid[] = "@(#)boxed.c 0.9 01/09/26 xlockmore"; +#endif + +/*- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * + * Revision History: + * + * 2001: Written by Sander van Grieken <mailsander@gmx.net> + * as an OpenGL screensaver for the xscreensaver package. + * Lots of hardcoded values still in place. Also, there are some + * copy/paste leftovers from the gears hack. opts don't work. + * + * 2005: opts work. added options -balls, -ballsize, -explosion + * + * 2006: opts work. added option -decay + * + * 2008: opts work. added option -momentum + * + */ + +#include "boxed.h" + +/* +**---------------------------------------------------------------------------- +** Defines +**---------------------------------------------------------------------------- +*/ + +#ifdef STANDALONE +# define DEFAULTS "*delay: 15000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" + +# define release_boxed 0 +# define boxed_handle_event xlockmore_no_events +# include "xlockmore.h" /* from the xscreensaver distribution */ +#else /* !STANDALONE */ +# include "xlock.h" /* from the xlockmore distribution */ +#endif /* !STANDALONE */ + +#ifdef USE_GL + +# define DEF_SPEED "0.5" +# define DEF_BALLS "20" +# define DEF_BALLSIZE "3.0" +# 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))) +#undef rnd +#define rnd() (frand(1.0)) + +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[] = { + {"-speed", ".boxed.speed", XrmoptionSepArg, 0}, + {"-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", "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}; + +#ifdef USE_MODULES + +ModStruct boxed_description = { + "boxed", "init_boxed", "draw_boxed", NULL, + "draw_boxed", "init_boxed", "free_boxed", &boxed_opts, + 1000, 1, 2, 1, 4, 1.0, "", + "Shows GL's boxed balls", 0, NULL}; + +#endif + +#define BOOL int +#define TRUE 1 +#define FALSE 0 + +/* camera */ +#define CAM_HEIGHT 80.0f +#define CAMDISTANCE_MIN 35.0 +#define CAMDISTANCE_MAX 150.0 +#define CAMDISTANCE_SPEED 1.5 +#define LOOKAT_R 30.0 + +/* rendering the sphere */ +#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) + +/* +**----------------------------------------------------------------------------- +** Typedefs +**----------------------------------------------------------------------------- +*/ + +typedef struct { + GLfloat x; + GLfloat y; + GLfloat z; +} vectorf; + +typedef struct { + vectorf loc; + vectorf dir; + vectorf color; + float radius; + BOOL bounced; + int offside; + BOOL justcreated; +} ball; + +typedef struct { + int num_balls; + float ballsize; + float explosion; + ball *balls; +} ballman; + +typedef struct { + vectorf loc; + vectorf dir; + BOOL far; + int gone; +} tri; + +typedef struct { + int num_tri; + int lifetime; + float scalefac; + float explosion; + float decay; + float momentum; + vectorf color; + tri *tris; + GLint *indices; + vectorf *normals; + vectorf *vertices; +} triman; + +typedef struct { + int numballs; + float ballsize; + float explosion; + float decay; + float momentum; + BOOL textures; + BOOL transparent; + float camspeed; +} boxed_config; + + +typedef struct { + float cam_x_speed, cam_z_speed, cam_y_speed; + boxed_config config; + float tic; + float camtic; + vectorf spherev[SPHERE_VERTICES]; + GLint spherei[SPHERE_INDICES]; + ballman bman; + triman *tman; + GLXContext *glx_context; + GLuint listobjects; + GLuint gllists[3]; + int list_polys[3]; + Window window; + BOOL stop; + char *tex1; +} boxedstruct; + +#define GLL_PATTERN 0 +#define GLL_BALL 1 +#define GLL_BOX 2 + +/* +**---------------------------------------------------------------------------- +** Local Variables +**---------------------------------------------------------------------------- +*/ + +static boxedstruct *boxed = NULL; + + +/* +**---------------------------------------------------------------------------- +** Functions +**---------------------------------------------------------------------------- +*/ + +/* + * Add 2 vectors + */ +static inline void addvectors(vectorf *dest, vectorf *s1, vectorf *s2) +{ + dest->x = s1->x + s2->x; + dest->y = s1->y + s2->y; + dest->z = s1->z + s2->z; +} + +/* + * Sub 2 vectors + */ +static inline void subvectors(vectorf *dest, vectorf* s1, vectorf *s2) +{ + dest->x = s1->x - s2->x; + dest->y = s1->y - s2->y; + dest->z = s1->z - s2->z; +} + +/* + * Multiply vector with scalar (scale vector) + */ +static inline void scalevector(vectorf *dest, vectorf *source, GLfloat sc) +{ + dest->x = source->x * sc; + dest->y = source->y * sc; + dest->z = source->z * sc; +} + +/* + * Copy vector + */ +static inline void copyvector(vectorf *dest, vectorf* source) +{ + dest->x = source->x; + dest->y = source->y; + dest->z = source->z; +} + + +static inline GLfloat +dotproduct(vectorf * v1, vectorf * v2) +{ + return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z; +} + +static inline GLfloat +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; +} + + + +/* + * Generate the Sphere data + * + * Input: + */ + +static void generatesphere(boxedstruct *gp) +{ + float dj = M_PI/(MESH_SIZE+1.0f); + float di = M_PI/MESH_SIZE; + int v; /* vertex offset */ + int ind; /* indices offset */ + int i,j,si; + GLfloat r_y_plane, h_y_plane; + vectorf *spherev; + GLint *spherei; + + /* + * generate the sphere data + * vertices 0 and 1 are the north and south poles + */ + + spherei = gp->spherei; + spherev = gp->spherev; + + spherev[0].x = 0.0f; spherev[0].y =1.0f; spherev[0].z = 0.0f; + spherev[1].x = 0.0f; spherev[1].y =-1.0f; spherev[1].z = 0.0f; + + for (j=0; j<MESH_SIZE; j++) { + r_y_plane = (float)sin((j+1) * dj); + h_y_plane = (float)cos((j+1) * dj); + for (i=0; i<MESH_SIZE*2; i++) { + si = 2+i+j*MESH_SIZE*2; + spherev[si].y = h_y_plane; + spherev[si].x = (float) sin(i * di) * r_y_plane; + spherev[si].z = (float) cos(i * di) * r_y_plane; + } + } + + /* generate indices */ + for (i=0; i<MESH_SIZE*2; i++) { + spherei[3*i] = 0; + spherei[3*i+1] = i+2; + spherei[3*i+2] = i+3; + if (i==MESH_SIZE*2-1) + spherei[3*i+2] = 2; + } + + /* the middle strips */ + for (j=0; j<MESH_SIZE-1; j++) { + v = 2+j*MESH_SIZE*2; + ind = 3*MESH_SIZE*2 + j*6*MESH_SIZE*2; + for (i=0; i<MESH_SIZE*2; i++) { + spherei[6*i+ind] = v+i; + spherei[6*i+2+ind] = v+i+1; + spherei[6*i+1+ind] = v+i+MESH_SIZE*2; + + spherei[6*i+ind+3] = v+i+MESH_SIZE*2; + spherei[6*i+2+ind+3] = v+i+1; + spherei[6*i+1+ind+3] = v+i+MESH_SIZE*2+1; + if (i==MESH_SIZE*2-1) { + spherei[6*i+2+ind] = v+i+1-2*MESH_SIZE; + spherei[6*i+2+ind+3] = v+i+1-2*MESH_SIZE; + spherei[6*i+1+ind+3] = v+i+MESH_SIZE*2+1-2*MESH_SIZE; + } + } + } + + v = SPHERE_VERTICES-MESH_SIZE*2; + ind = SPHERE_INDICES-3*MESH_SIZE*2; + for (i=0; i<MESH_SIZE*2; i++) { + spherei[3*i+ind] = 1; + spherei[3*i+1+ind] = v+i+1; + spherei[3*i+2+ind] = v+i; + if (i==MESH_SIZE*2-1) + spherei[3*i+1+ind] = v; + } +} + + + + +/* + * create fresh ball + */ + +static 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()) * speed; + newball->dir.y = 0.0; + newball->dir.z = (0.5-rnd()) * speed; + newball->offside = 0; + newball->bounced = FALSE; + newball->radius = cfg_ballsize; + while (r+g+b < 1.8f ) { + newball->color.x = r=rnd(); + newball->color.y = g=rnd(); + newball->color.z = b=rnd(); + } + newball->justcreated = TRUE; +} + +/* Update position of each ball */ + +static 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.30f * speed; + + /* apply gravity */ + bman->balls[b].dir.y -= gravity; + /* apply movement */ + addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir); + /* boundary check */ + if (bman->balls[b].loc.y < bman->balls[b].radius) { /* ball onder bodem? (bodem @ y=0) */ + if ((bman->balls[b].loc.x < -95.0) || + (bman->balls[b].loc.x > 95.0) || + (bman->balls[b].loc.z < -95.0) || + (bman->balls[b].loc.z > 95.0)) { + if (bman->balls[b].loc.y < -2000.0) + createball(&bman->balls[b]); + } else { + bman->balls[b].loc.y = bman->balls[b].radius + (bman->balls[b].radius - bman->balls[b].loc.y); + bman->balls[b].dir.y = -bman->balls[b].dir.y; + if (bman->balls[b].offside) { + bman->balls[b].bounced = TRUE; /* temporary disable painting ball */ + 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]); + } + } + } + + } + if (!bman->balls[b].offside) { + if (bman->balls[b].loc.x - bman->balls[b].radius < -20.0f) { /* x ondergrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.x = -bman->balls[b].dir.x; + bman->balls[b].loc.x = -20.0f + bman->balls[b].radius; + } + } + if (bman->balls[b].loc.x + bman->balls[b].radius > 20.0f) { /* x bovengrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.x = -bman->balls[b].dir.x; + bman->balls[b].loc.x = 20.0f - bman->balls[b].radius; + } + } + if (bman->balls[b].loc.z - bman->balls[b].radius < -20.0f) { /* z ondergrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.z = -bman->balls[b].dir.z; + bman->balls[b].loc.z = -20.0f + bman->balls[b].radius; + } + } + if (bman->balls[b].loc.z + bman->balls[b].radius > 20.0f) { /* z bovengrens */ + if (bman->balls[b].loc.y > 41+bman->balls[b].radius) bman->balls[b].offside=1; + else { + bman->balls[b].dir.z = -bman->balls[b].dir.z; + bman->balls[b].loc.z = 20.0f - bman->balls[b].radius; + } + } + } /* end if !offside */ + + /* check voor stuiteren */ + for (j=b+1;j<bman->num_balls;j++) { + squaredist = (bman->balls[b].radius * bman->balls[b].radius) + (bman->balls[j].radius * bman->balls[j].radius); + subvectors(&dvect,&bman->balls[b].loc,&bman->balls[j].loc); + if ( squaremagnitude(&dvect) < squaredist ) { /* balls b and j touch */ + subvectors(&richting,&bman->balls[j].loc,&bman->balls[b].loc); + subvectors(&relspeed,&bman->balls[b].dir,&bman->balls[j].dir); + /* calc mutual influence direction and magnitude */ + scalevector(&influence,&richting,(dotproduct(&richting,&relspeed)/squaremagnitude(&richting))); + + subvectors(&bman->balls[b].dir,&bman->balls[b].dir,&influence); + addvectors(&bman->balls[j].dir,&bman->balls[j].dir,&influence); + addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir); + addvectors(&bman->balls[j].loc,&bman->balls[j].loc,&bman->balls[j].dir); + + subvectors(&dvect,&bman->balls[b].loc,&bman->balls[j].loc); + while (squaremagnitude(&dvect) < squaredist) { + addvectors(&bman->balls[b].loc,&bman->balls[b].loc,&bman->balls[b].dir); + addvectors(&bman->balls[j].loc,&bman->balls[j].loc,&bman->balls[j].dir); + subvectors(&dvect,&bman->balls[b].loc,&bman->balls[j].loc); + } + } + } /* end for j */ + } /* end for b */ +} + + +/* +* explode ball into triangles +*/ + +static void createtrisfromball(triman* tman, vectorf *spherev, GLint *spherei, int ind_num, ball *b) +{ + int pos; + float explosion; + float momentum; + float scale; + register int i; + 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; + + /* reserveer geheugen voor de poly's in een bal */ + + tman->tris = (tri *)malloc(tman->num_tri * sizeof(tri)); + tman->vertices = (vectorf *)malloc(ind_num * sizeof(vectorf)); + tman->normals = (vectorf *)malloc(ind_num/3 * sizeof(vectorf)); + + for (i=0; i<(tman->num_tri); i++) { + tman->tris[i].far = FALSE; + tman->tris[i].gone = 0; + pos = i * 3; + /* kopieer elke poly apart naar een tri structure */ + copyvector(&tman->vertices[pos+0],&spherev[spherei[pos+0]]); + copyvector(&tman->vertices[pos+1],&spherev[spherei[pos+1]]); + copyvector(&tman->vertices[pos+2],&spherev[spherei[pos+2]]); + /* Calculate average direction of shrapnel */ + addvectors(&avgdir,&tman->vertices[pos+0],&tman->vertices[pos+1]); + addvectors(&avgdir,&avgdir,&tman->vertices[pos+2]); + scalevector(&avgdir,&avgdir,0.33333); + + /* should normalize first, NYI */ + copyvector(&tman->normals[i],&avgdir); + + /* copy de lokatie */ + addvectors(&tman->tris[i].loc,&b->loc,&avgdir); + /* en translate alle triangles terug naar hun eigen oorsprong */ + tman->vertices[pos+0].x -= avgdir.x; + tman->vertices[pos+0].y -= avgdir.y; + tman->vertices[pos+0].z -= avgdir.z; + tman->vertices[pos+1].x -= avgdir.x; + tman->vertices[pos+1].y -= avgdir.y; + tman->vertices[pos+1].z -= avgdir.z; + tman->vertices[pos+2].x -= avgdir.x; + tman->vertices[pos+2].y -= avgdir.y; + tman->vertices[pos+2].z -= avgdir.z; + /* alwaar opschaling plaatsvindt */ + scale = b->radius * 2; + scalevector(&tman->vertices[pos+0],&tman->vertices[pos+0],scale); + scalevector(&tman->vertices[pos+1],&tman->vertices[pos+1],scale); + scalevector(&tman->vertices[pos+2],&tman->vertices[pos+2],scale); + + tman->vertices[pos+0].x += avgdir.x; + tman->vertices[pos+0].y += avgdir.y; + tman->vertices[pos+0].z += avgdir.z; + tman->vertices[pos+1].x += avgdir.x; + tman->vertices[pos+1].y += avgdir.y; + tman->vertices[pos+1].z += avgdir.z; + tman->vertices[pos+2].x += avgdir.x; + tman->vertices[pos+2].y += avgdir.y; + tman->vertices[pos+2].z += avgdir.z; + + /* 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()); + 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); + } +} + + +/* +* update position of each tri +*/ + +static void updatetris(triman *t) +{ + int b; + GLfloat xd,zd; + + for (b=0;b<t->num_tri;b++) { + /* the exploded triangles disappear over time */ + if (rnd() < t->decay) { + if (t->tris[b].gone == 0) + t->tris[b].gone = 1; + } + /* apply gravity */ + 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 */ + if (t->tris[b].far) continue; + if (t->tris[b].loc.y < 0) { /* onder bodem ? */ + if ((t->tris[b].loc.x > -95.0f) & + (t->tris[b].loc.x < 95.0f) & + (t->tris[b].loc.z > -95.0f) & + (t->tris[b].loc.z < 95.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.80f); /* dampening */ + } + else { + t->tris[b].far = TRUE; + continue; + } + } + + 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)) { + xd = t->tris[b].loc.x + 21.0f; + } + if ((t->tris[b].loc.x < 21.0f) & + (t->tris[b].loc.x > 0)) { + xd = 21.0f - t->tris[b].loc.x; + } + if ((t->tris[b].loc.z > -21.0f) & + (t->tris[b].loc.z < 0)) { + zd = t->tris[b].loc.z + 21.0f; + } + if ((t->tris[b].loc.z < 21.0f) & + (t->tris[b].loc.z > 0)) { + 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 */ +} + + +/* + * free memory allocated by a tri manager + */ +static void freetris(triman *t) +{ + if (!t) return; + if (t->tris) free(t->tris); + if (t->vertices) free(t->vertices); + if (t->normals) free(t->normals); + t->tris = NULL; + t->vertices = NULL; + t->normals = NULL; + t->num_tri = 0; + t->lifetime = 0; +} + + +/* + *load defaults in config structure + */ +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.02f,MIN(0.90f,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; +} + + +/* + * draw bottom + */ +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); + glTexCoord2f(0,1); + glVertex3f(-1.0,1.0,1.0); + glTexCoord2f(1,1); + glVertex3f(1.0,1.0,1.0); + glTexCoord2f(1,1); + 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); + glTexCoord2f(1,1); + glVertex3f(-1.0,1.0,-1.0); + glTexCoord2f(1,1); + 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); + glTexCoord2f(1,1); + glVertex3f(-1.0,-1.0,1.0); + glTexCoord2f(0,1); + 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); + glTexCoord2f(1,1); + glVertex3f(1.0,1.0,-1.0); + glTexCoord2f(1,1); + 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); + glTexCoord2f(0.0,1.0); + glVertex3f(-1.0,1.0,-1.0); + glTexCoord2f(1.0,1.0); + 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); + glTexCoord2f(0,1); + glVertex3f(-1.0,-1.0,-1.0); + glTexCoord2f(1,1); + 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 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); 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); 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); polys++; + 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); polys++; + glVertex3f(-1.0,1.0,-1.0); + glVertex3f(-1.0,-1.0,-1.0); polys++; + glEnd(); + return polys; +} + + + +/* + * Draw ball + */ +static int drawball(boxedstruct *gp, ball *b, int wire) +{ + int polys = 0; + int i,pos,cnt; + GLint *spherei = gp->spherei; + vectorf *spherev = gp->spherev; + GLfloat col[3]; + + glPushMatrix(); + + glTranslatef(b->loc.x,b->loc.y,b->loc.z); + glScalef(b->radius,b->radius,b->radius); + glColor3f(b->color.x,b->color.y,b->color.z); + col[0] = b->color.x; + col[1] = b->color.y; + col[2] = b->color.z; + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + col[0] *= 0.5; + col[1] *= 0.5; + col[2] *= 0.5; + glMaterialfv(GL_FRONT, GL_EMISSION,col); + + if (!gp->gllists[GLL_BALL]) { + glNewList(gp->listobjects + GLL_BALL,GL_COMPILE); + glBegin(wire ? GL_LINES : GL_TRIANGLES); + cnt = SPHERE_INDICES/3; + for (i=0; i<cnt; i++) { + pos = i * 3; + 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); + if (wire) + 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 a single triangle + */ +static void drawtri(triman *t, int wire, int i) +{ + const vectorf *spherev = t->vertices + i*3; + const vectorf *loc = &t->tris[i].loc; + + glNormal3f(t->normals[i].x,t->normals[i].y,t->normals[i].z); + glVertex3f(spherev[0].x+loc->x,spherev[0].y+loc->y,spherev[0].z+loc->z); + glVertex3f(spherev[1].x+loc->x,spherev[1].y+loc->y,spherev[1].z+loc->z); + if (wire) + glVertex3f(spherev[1].x+loc->x,spherev[1].y+loc->y,spherev[1].z+loc->z); + glVertex3f(spherev[2].x+loc->x,spherev[2].y+loc->y,spherev[2].z+loc->z); + if (wire) { + glVertex3f(spherev[2].x+loc->x,spherev[2].y+loc->y,spherev[2].z+loc->z); + glVertex3f(spherev[0].x+loc->x,spherev[0].y+loc->y,spherev[0].z+loc->z); + } +} + + +/* + * Draw all triangles in triman + */ +static int drawtriman(triman *t, int wire) +{ + int polys = 0; + int i; + GLfloat col[3]; + + glPushMatrix(); + glColor3f(t->color.x,t->color.y,t->color.z); + col[0] = t->color.x; + col[1] = t->color.y; + col[2] = t->color.z; + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + col[0] *= 0.3; + col[1] *= 0.3; + col[2] *= 0.3; + glMaterialfv(GL_FRONT, GL_EMISSION,col); + glBegin(wire ? GL_LINES : GL_TRIANGLES); + + for (i=0; i<t->num_tri; i++) { + if (t->tris[i].gone > 3) { continue; } + if (t->tris[i].gone > 0) { + glColor3f(t->color.x,t->color.y,t->color.z); + col[0] = 1.0f; + col[1] = 1.0f; + col[2] = 1.0f; + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + col[0] *= 0.8; + col[1] *= 0.8; + col[2] *= 0.8; + glMaterialfv(GL_FRONT, GL_EMISSION,col); + + drawtri(t, wire, i); + polys++; + + glColor3f(t->color.x,t->color.y,t->color.z); + col[0] = t->color.x; + col[1] = t->color.y; + col[2] = t->color.z; + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + col[0] *= 0.3; + col[1] *= 0.3; + col[2] *= 0.3; + glMaterialfv(GL_FRONT, GL_EMISSION,col); + + t->tris[i].gone++; + continue; + } + + drawtri(t, wire, i); + polys++; + } + glEnd(); + glPopMatrix(); + return polys; +} + +/* + * draw floor pattern + */ +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); 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); 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; +} + + +/* + * main rendering loop + */ +static void draw(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME (mi); + vectorf v1,v2; + GLfloat r; + int dx, dz; + int i; + + GLfloat dgray[4] = {0.3f, 0.3f, 0.3f, 1.0f}; + GLfloat black[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + GLfloat lblue[4] = {0.4f,0.6f,1.0f }; + + GLfloat l0_ambient[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat l0_specular[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat l0_diffuse[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat l0_position[] = {0.0, 0.0, 0.0, 1.0}; /* w != 0 -> positional light */ + GLfloat l1_ambient[] = {0.0, 0.0, 0.0, 1.0}; + GLfloat l1_specular[] = {1.0, 1.0, 1.0, 1.0}; + 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(); + +# ifdef HAVE_MOBILE /* Keep it the same relative size when rotated. */ + { + GLfloat h = MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi); + int o = (int) current_device_rotation(); + if (o != 0 && o != 180 && o != -180) + glScalef (1/h, 1/h, 1/h); + glRotatef(o, 0, 0, 1); + } +# endif + + gp->tic += 0.01f; + gp->camtic += 0.01f + 0.01f * sin(gp->tic * speed); + + /* rotate camera around (0,0,0), looking at (0,0,0), up is (0,1,0) */ + r = CAMDISTANCE_MIN + (CAMDISTANCE_MAX - CAMDISTANCE_MIN) + (CAMDISTANCE_MAX - CAMDISTANCE_MIN)*cos((gp->camtic/CAMDISTANCE_SPEED) * speed); + v1.x = r * sin((gp->camtic/gp->cam_x_speed) * speed); + v1.z = r * cos((gp->camtic/gp->cam_x_speed) * speed); + v1.y = CAM_HEIGHT * sin((gp->camtic/gp->cam_y_speed) * speed) + 1.02 * CAM_HEIGHT; + + v2.x = LOOKAT_R * sin((gp->camtic/(gp->cam_x_speed * 5.0f)) * speed); + v2.z = LOOKAT_R * cos((gp->camtic/(gp->cam_x_speed * 5.0f)) * speed); + v2.y = (CAM_HEIGHT * sin((gp->camtic/gp->cam_y_speed) * speed) + 1.02 * CAM_HEIGHT)/10.0; + + gluLookAt(v1.x,v1.y,v1.z,v2.x,v2.y,v2.x,0.0,1.0,0.0); + + if (!wire) { + glLightfv(GL_LIGHT0, GL_AMBIENT, l0_ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, l0_diffuse); + glLightfv(GL_LIGHT0, GL_SPECULAR, l0_specular); + glLightfv(GL_LIGHT0, GL_POSITION, l0_position); + glLightfv(GL_LIGHT1, GL_AMBIENT, l1_ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, l1_diffuse); + glLightfv(GL_LIGHT1, GL_SPECULAR, l1_specular); + glLightfv(GL_LIGHT1, GL_POSITION, l1_position); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + glFrontFace(GL_CW); + + glMaterialfv(GL_FRONT, GL_SPECULAR, black); + glMaterialfv(GL_FRONT, GL_EMISSION, lblue); + glMaterialfv(GL_FRONT,GL_AMBIENT,black); + glMaterialf(GL_FRONT, GL_SHININESS, 5.0); + } + + + /* draw ground grid */ + /* glDisable(GL_DEPTH_TEST); */ + glDisable(GL_LIGHTING); + + glColor3f(0.1,0.1,0.6); + for (dx= -2; dx<3; dx++) { + for (dz= -2; dz<3; dz++) { + glPushMatrix(); + glTranslatef(dx*30.0f, 0.0f, dz*30.0f); + drawpattern(gp); + glPopMatrix(); + } + } + + /* Set drawing mode for the boxes */ + glEnable(GL_DEPTH_TEST); + if (!wire) glEnable(GL_TEXTURE_2D); + glPushMatrix(); + glColor3f(1.0,1.0,1.0); + glScalef(20.0,0.25,20.0); + glTranslatef(0.0,2.0,0.0); + mi->polygon_count += drawfilledbox(gp, wire); + glPopMatrix(); + glDisable(GL_TEXTURE_2D); + + glPushMatrix(); + glColor3f(0.2,0.5,0.2); + glScalef(20.0,20.0,0.25); + glTranslatef(0.0,1.0,81.0); + 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); + 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); + 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); + mi->polygon_count += drawbox(gp); + glPopMatrix(); + + if (!wire) { + glEnable(GL_LIGHTING); + + glMaterialfv(GL_FRONT, GL_DIFFUSE, dgray); + glMaterialfv(GL_FRONT, GL_EMISSION, black); /* turn it off before painting the balls */ + } + + /* move the balls and shrapnel */ + updateballs(&gp->bman); + + glFrontFace(GL_CCW); + for (i=0;i<gp->bman.num_balls;i++) { + if (gp->bman.balls[i].justcreated) { + gp->bman.balls[i].justcreated = FALSE; + freetris(&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); + mi->polygon_count += drawtriman(&gp->tman[i], wire); + if (!wire) glEnable(GL_CULL_FACE); + } else { + mi->polygon_count += drawball(gp, &gp->bman.balls[i], wire); + } + } + + glFlush(); +} + + + +/* + * new window size or exposure + */ +ENTRYPOINT void reshape_boxed(ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + int y = 0; + + if (width > height * 5) { /* tiny window: show middle */ + height = width * 9/16; + y = -height/2; + h = height / (GLfloat) width; + } + + glViewport(0, y, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(50.0,1/h,2.0,1000.0); + glMatrixMode (GL_MODELVIEW); + + glLineWidth(1); + glPointSize(1); +} + + +static void +pinit(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME (mi); + ballman *bman; + int i,texpixels; + char *texpixeldata; + char *texpixeltarget; + + glShadeModel(GL_SMOOTH); + glClearDepth(1.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; + + bman->balls = (ball *)malloc(gp->config.numballs * sizeof(ball)); + bman->num_balls = gp->config.numballs; + bman->ballsize = gp->config.ballsize; + bman->explosion = gp->config.explosion; + + gp->tman = (triman *)malloc(bman->num_balls * sizeof(triman)); + memset(gp->tman,0,bman->num_balls * sizeof(triman)); + + 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; + createball(&bman->balls[i]); + bman->balls[i].loc.y *= rnd(); + } + + generatesphere(gp); + + if (!wire) { + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + } + + /* define cam path */ + gp->cam_x_speed = 1.0f/((float)gp->config.camspeed/50.0 + rnd()*((float)gp->config.camspeed/50.0)); + gp->cam_z_speed = 1.0f/((float)gp->config.camspeed/50.0 + rnd()*((float)gp->config.camspeed/50.0)); + gp->cam_y_speed = 1.0f/((float)gp->config.camspeed/250.0 + rnd()*((float)gp->config.camspeed/250.0)); + if (rnd() < 0.5f) gp->cam_x_speed = -gp->cam_x_speed; + if (rnd() < 0.5f) gp->cam_z_speed = -gp->cam_z_speed; + + /* define initial cam position */ + gp->tic = gp->camtic = rnd() * 100.0f; + + /* define tex1 (bottom plate) */ + gp->tex1 = (char *)malloc(3*width*height*sizeof(GLuint)); + texpixels = 256*256; /*width*height;*/ + texpixeldata = header_data; + texpixeltarget = gp->tex1; + for (i=0; i < texpixels; i++) { + HEADER_PIXEL(texpixeldata,texpixeltarget); + texpixeltarget += 3; + } + + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + clear_gl_error(); +#if 0 + i = gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 256, 256, + GL_RGB, GL_UNSIGNED_BYTE, gp->tex1); + if (i) + { + const char *s = (char *) gluErrorString (i); + fprintf (stderr, "%s: error mipmapping texture: %s\n", + progname, (s ? s : "(unknown)")); + exit (1); + } + check_gl_error("mipmapping"); +#else + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, + GL_RGB, GL_UNSIGNED_BYTE, + gp->tex1); + check_gl_error("texture"); +#endif + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + +} + + + +ENTRYPOINT void +init_boxed(ModeInfo * mi) +{ + int screen = MI_SCREEN(mi); + + /* Colormap cmap; */ + /* Boolean rgba, doublebuffer, cmap_installed; */ + boxedstruct *gp; + + MI_INIT(mi, boxed); + gp = &boxed[screen]; + gp->window = MI_WINDOW(mi); + + if ((gp->glx_context = init_GL(mi)) != NULL) { + reshape_boxed(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + glDrawBuffer(GL_BACK); + if (!glIsList(gp->listobjects)) { + gp->listobjects = glGenLists(3); + gp->gllists[0] = 0; + gp->gllists[1] = 0; + gp->gllists[2] = 0; + } + pinit(mi); + } else { + MI_CLEARWINDOW(mi); + } +} + + +ENTRYPOINT void +draw_boxed(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + Display *display = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + + if (!gp->glx_context) + return; + + glDrawBuffer(GL_BACK); + + glXMakeCurrent(display, window, *(gp->glx_context)); + draw(mi); + + if (mi->fps_p) do_fps (mi); + glFinish(); + glXSwapBuffers(display, window); +} + +ENTRYPOINT void +free_boxed(ModeInfo * mi) +{ + boxedstruct *gp = &boxed[MI_SCREEN(mi)]; + int i; + + if (gp->glx_context) { + /* Display lists MUST be freed while their glXContext is current. */ + glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context)); + + if (glIsList(gp->listobjects)) + glDeleteLists(gp->listobjects, 3); + + 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); + + + } +} + + +XSCREENSAVER_MODULE ("Boxed", boxed) + +/*********************************************************/ + +#endif |