summaryrefslogtreecommitdiffstats
path: root/hacks/glx/razzledazzle.c
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/glx/razzledazzle.c
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'hacks/glx/razzledazzle.c')
-rw-r--r--hacks/glx/razzledazzle.c725
1 files changed, 725 insertions, 0 deletions
diff --git a/hacks/glx/razzledazzle.c b/hacks/glx/razzledazzle.c
new file mode 100644
index 0000000..a3c8f98
--- /dev/null
+++ b/hacks/glx/razzledazzle.c
@@ -0,0 +1,725 @@
+/* razzledazzle, Copyright (c) 2018 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * 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
+ * implied warranty.
+ */
+
+#define DEFAULTS "*delay: 30000 \n" \
+ "*showFPS: False \n" \
+ "*wireframe: False \n" \
+ "*ncolors: 2 \n" \
+ "*suppressRotationAnimation: True\n" \
+
+# define release_dazzle 0
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#include "xlockmore.h"
+#include "colors.h"
+#include "normals.h"
+#include "gllist.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+#define DEF_SPEED "1.0"
+#define DEF_DENSITY "5.0"
+#define DEF_THICKNESS "0.1"
+#define DEF_MODE "Random"
+
+#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
+#undef RANDSIGN
+#define RANDSIGN() ((random() & 1) ? 1 : -1)
+
+extern const struct gllist
+ *ships_ship1, *ships_ship2, *ships_ship3, *ships_ship4,
+ *ships_ship5, *ships_ship6, *ships_ship7, *ships_ship8;
+
+static const struct gllist * const *all_ships[] = {
+ &ships_ship1, &ships_ship2, &ships_ship3, &ships_ship4,
+ &ships_ship5, &ships_ship6, &ships_ship7, &ships_ship8,
+};
+
+
+typedef enum { LEFT, RIGHT, UP, DOWN } direction;
+
+typedef struct node node;
+
+struct node {
+ long gx, gy;
+ GLfloat x, y;
+ GLfloat dx, dy;
+ int nstripes;
+ Bool horiz_p;
+ Bool drawn_p;
+ GLfloat color1[4], color2[4];
+};
+
+typedef struct {
+ GLXContext *glx_context;
+ Bool button_down_p;
+ GLfloat xoff, yoff, dx, dy;
+ node *nodes;
+ node *dragging;
+ int drag_x, drag_y;
+ int ncolors;
+ XColor *colors;
+ GLuint *dlists;
+ enum { SHIPS, FLAT, RANDOM } mode;
+ int which_ship;
+ long frames;
+} dazzle_configuration;
+
+static dazzle_configuration *bps = NULL;
+
+static GLfloat speed, thickness, density;
+static char *mode_arg;
+
+static XrmOptionDescRec opts[] = {
+ { "-speed", ".speed", XrmoptionSepArg, 0 },
+ { "-thickness", ".thickness", XrmoptionSepArg, 0 },
+ { "-density", ".density", XrmoptionSepArg, 0 },
+ { "-mode", ".mode", XrmoptionSepArg, 0 },
+ { "-ships", ".mode", XrmoptionNoArg, "ships" },
+ { "-flat", ".mode", XrmoptionNoArg, "flat" },
+};
+
+static argtype vars[] = {
+ {&speed, "speed", "Speed", DEF_SPEED, t_Float},
+ {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float},
+ {&density, "density", "Density", DEF_DENSITY, t_Float},
+ {&mode_arg, "mode", "Mode", DEF_MODE, t_String},
+};
+
+ENTRYPOINT ModeSpecOpt dazzle_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+
+
+static void
+draw_grid (ModeInfo *mi, int gx, int gy)
+{
+ dazzle_configuration *bp = &bps[MI_SCREEN(mi)];
+ Bool wire = MI_IS_WIREFRAME(mi);
+ long x, y;
+ long wh = density * 2;
+
+ if (wire)
+ glColor3f (1, 1, 1);
+
+ if (!wire)
+ glBegin (GL_QUADS);
+
+ for (y = 0; y < wh; y++)
+ for (x = 0; x < wh; x++)
+ {
+ node *n0 = &bp->nodes[(y % wh) * wh + (x % wh)];
+ node *n1 = &bp->nodes[(y % wh) * wh + ((x+1) % wh)];
+ node *n2 = &bp->nodes[((y+1) % wh) * wh + ((x+1) % wh)];
+ node *n3 = &bp->nodes[((y+1) % wh) * wh + (x % wh)];
+ int nstripes, i;
+ Bool horiz_p, visible;
+ GLfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ GLfloat xoff = (x < wh-1 ? 0 : wh);
+ GLfloat yoff = (y < wh-1 ? 0 : wh);
+ GLfloat bx = fmod ((double) bp->xoff, 2.0);
+ GLfloat by = fmod ((double) bp->yoff, 2.0);
+
+ bx += gx*2;
+ by += gy*2;
+
+ if (wire)
+ {
+ GLfloat a;
+ glColor3f (0, 0, 1);
+ glBegin (GL_LINE_LOOP);
+ for (a = 0; a < 360; a += 10)
+ glVertex3f ((n0->x / density-1) + 0.05 * cos(a * M_PI/180) + bx,
+ (n0->y / density-1) + 0.05 * sin(a * M_PI/180) + by,
+ 0);
+ glEnd();
+ }
+
+ x0 = n0->x / density - 1 + bx;
+ y0 = n0->y / density - 1 + by;
+
+ x1 = (n1->x+xoff) / density - 1 + bx;
+ y1 = n1->y / density - 1 + by;
+ x2 = (n2->x+xoff) / density - 1 + bx;
+ y2 = (n2->y+yoff) / density - 1 + by;
+ x3 = n3->x / density - 1 + bx;
+ y3 = (n3->y+yoff) / density - 1 + by;
+
+ if (wire)
+ {
+ if (gx == 0 && gy == 0)
+ {
+ glLineWidth (4);
+ glColor3f(1, 0, 0);
+ }
+ else
+ glColor3f(0.5, 0, 0.5);
+ if (wire) glBegin (GL_LINE_LOOP);
+ glVertex3f (x0, y0, 0);
+ glVertex3f (x1, y1, 0);
+ glVertex3f (x2, y2, 0);
+ glVertex3f (x3, y3, 0);
+ mi->polygon_count++;
+ if (wire) glEnd();
+ glLineWidth (1);
+ }
+
+ /* This isn't quite right: just because all corners are off screen
+ doesn't mean the quad isn't visible. We need to intersect the
+ edges with the screen rectangle.
+ */
+ {
+ GLfloat max = 0.75;
+ visible = ((x0 >= -max && y0 >= -max && x0 <= max && y0 <= max) ||
+ (x1 >= -max && y1 >= -max && x1 <= max && y1 <= max) ||
+ (x2 >= -max && y2 >= -max && x2 <= max && y2 <= max) ||
+ (x3 >= -max && y3 >= -max && x3 <= max && y3 <= max));
+ }
+
+ if (!visible) continue;
+
+ if (visible)
+ n0->drawn_p = True;
+
+ nstripes = n0->nstripes;
+ horiz_p = n0->horiz_p;
+
+ for (i = 0; i < nstripes; i++)
+ {
+ GLfloat ss = (GLfloat) i / nstripes;
+ GLfloat ss1 = (GLfloat) (i+1) / nstripes;
+ if (i & 1)
+ glColor4fv (n0->color1);
+ else if (wire)
+ continue;
+ else
+ glColor4fv (n0->color2);
+
+ if (horiz_p)
+ {
+ x0 = n0->x + (n3->x - n0->x) * ss;
+ y0 = n0->y + ((n3->y+yoff) - n0->y) * ss;
+ x1 = (n1->x+xoff) + ((n2->x+xoff) - (n1->x+xoff)) * ss;
+ y1 = n1->y + ((n2->y+yoff) - n1->y) * ss;
+
+ x2 = (n1->x+xoff) + ((n2->x+xoff) - (n1->x+xoff)) * ss1;
+ y2 = n1->y + ((n2->y+yoff) - n1->y) * ss1;
+ x3 = n0->x + (n3->x - n0->x) * ss1;
+ y3 = n0->y + ((n3->y+yoff) - n0->y) * ss1;
+ }
+ else
+ {
+ x0 = n0->x + ((n1->x+xoff) - n0->x) * ss;
+ y0 = n0->y + (n1->y - n0->y) * ss;
+ x1 = n3->x + ((n2->x+xoff) - n3->x) * ss;
+ y1 = (n3->y+yoff) + ((n2->y+yoff) - (n3->y+yoff)) * ss;
+
+ x2 = n3->x + ((n2->x+xoff) - n3->x) * ss1;
+ y2 = (n3->y+yoff) + ((n2->y+yoff) - (n3->y+yoff)) * ss1;
+ x3 = n0->x + ((n1->x+xoff) - n0->x) * ss1;
+ y3 = n0->y + (n1->y - n0->y) * ss1;
+ }
+
+ if (wire) glBegin (GL_LINES);
+ glVertex3f (x0 / density - 1 + bx, y0 / density - 1 + by, 0);
+ glVertex3f (x1 / density - 1 + bx, y1 / density - 1 + by, 0);
+ glVertex3f (x2 / density - 1 + bx, y2 / density - 1 + by, 0);
+ glVertex3f (x3 / density - 1 + bx, y3 / density - 1 + by, 0);
+ mi->polygon_count++;
+ if (wire) glEnd();
+ }
+ }
+
+ if (!wire)
+ glEnd();
+}
+
+
+static void
+move_grid (ModeInfo *mi)
+{
+ dazzle_configuration *bp = &bps[MI_SCREEN(mi)];
+ long x, y;
+ long wh = density * 2;
+ Bool wire = MI_IS_WIREFRAME(mi);
+ GLfloat max = 1.0 / density * 3;
+
+ if (bp->button_down_p)
+ return;
+
+ bp->xoff += bp->dx;
+ bp->yoff += bp->dy;
+
+ if (! (random() % 50))
+ {
+ bp->dx += frand(0.0002) * RANDSIGN() * speed;
+ bp->dy += frand(0.0002) * RANDSIGN() * speed;
+ }
+
+ if (bp->dx > 0.003 * speed) bp->dx = 0.003 * speed;
+ if (bp->dy > 0.003 * speed) bp->dy = 0.003 * speed;
+
+ for (y = 0; y < wh; y++)
+ for (x = 0; x < wh; x++)
+ {
+ node *n = &bp->nodes[y * wh + x];
+ GLfloat x2 = n->x + n->dx;
+ GLfloat y2 = n->y + n->dy;
+
+ if (x2 < n->gx + max && x2 >= n->gx - max &&
+ y2 < n->gy + max && y2 >= n->gy - max)
+ {
+ n->x = x2;
+ n->y = y2;
+ }
+
+ if (! (random() % 50))
+ {
+ n->dx += frand(0.0005) * RANDSIGN() * speed;
+ n->dy += frand(0.0005) * RANDSIGN() * speed;
+ }
+
+ /* If this quad was not drawn, it's ok to re-randomize stripes, */
+ if (! n->drawn_p)
+ {
+ int i = random() % bp->ncolors;
+ int j = (i + bp->ncolors / 2) % bp->ncolors;
+ GLfloat cscale = 0.3;
+
+ n->color1[0] = bp->colors[i].red / 65536.0;
+ n->color1[1] = bp->colors[i].green / 65536.0;
+ n->color1[2] = bp->colors[i].blue / 65536.0;
+ n->color1[3] = 1.0;
+
+ n->color2[0] = bp->colors[j].red / 65536.0;
+ n->color2[1] = bp->colors[j].green / 65536.0;
+ n->color2[2] = bp->colors[j].blue / 65536.0;
+ n->color2[3] = 1.0;
+
+ if (! wire)
+ {
+ n->color1[0] = cscale * n->color1[0] + 1 - cscale;
+ n->color1[1] = cscale * n->color1[1] + 1 - cscale;
+ n->color1[2] = cscale * n->color1[2] + 1 - cscale;
+ n->color2[0] = cscale * n->color2[0];
+ n->color2[1] = cscale * n->color2[1];
+ n->color2[2] = cscale * n->color2[2];
+ }
+
+ n->horiz_p = random() & 1;
+ n->nstripes = 2 + (int) (BELLRAND(1.0 / thickness));
+ }
+ n->drawn_p = False;
+ }
+}
+
+
+/* Window management, etc
+ */
+ENTRYPOINT void
+reshape_dazzle (ModeInfo *mi, int width, int height)
+{
+ glViewport (0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho (0, 1, 1, 0, -1, 1);
+
+ if (width > height * 5) { /* tiny window: show middle */
+ GLfloat s = (GLfloat)height/width;
+ glOrtho (0, 1, 0.5-s, 0.5+s, -1, 1);
+ }
+
+# ifdef USE_IPHONE /* So much WTF */
+ {
+ int rot = current_device_rotation();
+
+ glTranslatef (0.5, 0.5, 0);
+
+ if (rot == 180 || rot == -180) {
+ glTranslatef (1, 1, 0);
+ } else if (rot == 90 || rot == -270) {
+ glRotatef (180, 0, 0, 1);
+ glTranslatef (0, 1, 0);
+ } else if (rot == -90 || rot == 270) {
+ glRotatef (180, 0, 0, 1);
+ glTranslatef (1, 0, 0);
+ }
+
+ glTranslatef(-0.5, -0.5, 0);
+ }
+# endif
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+static void
+dazzle_randomize (ModeInfo *mi)
+{
+ dazzle_configuration *bp = &bps[MI_SCREEN(mi)];
+ long x, y;
+ long wh = density * 2;
+
+ bp->ncolors = MI_NCOLORS(mi) - 1;
+ if (bp->ncolors < 1) bp->ncolors = 1;
+ if (bp->colors) free (bp->colors);
+ bp->colors = (XColor *) calloc (bp->ncolors, sizeof(XColor));
+ if (bp->ncolors < 3)
+ make_random_colormap (0, 0, 0, bp->colors, &bp->ncolors,
+ True, False, 0, False);
+ else
+ make_smooth_colormap (0, 0, 0,
+ bp->colors, &bp->ncolors,
+ False, False, False);
+ if (bp->ncolors < 1) abort();
+
+ bp->dragging = 0;
+ if (bp->nodes) free (bp->nodes);
+
+ bp->nodes = (node *) calloc (wh * wh, sizeof (node));
+ for (y = 0; y < wh; y++)
+ for (x = 0; x < wh; x++)
+ {
+ node *n = &bp->nodes[wh * y + x];
+ n->gx = n->x = x;
+ n->gy = n->y = y;
+ }
+
+ bp->dx = bp->dy = 0;
+ bp->xoff = bp->yoff = 0;
+ for (x = 0; x < 1000; x++)
+ move_grid (mi);
+
+ bp->dx = frand(0.0005) * RANDSIGN() * speed;
+ bp->dy = frand(0.0005) * RANDSIGN() * speed;
+
+ if (bp->mode == SHIPS || bp->mode == RANDOM)
+ {
+ bp->which_ship = random() % countof(all_ships);
+ if (bp->mode == RANDOM && !(random() % 3))
+ bp->which_ship = -1;
+ }
+
+ if (bp->which_ship != -1)
+ {
+ bp->dx /= 10;
+ bp->dy /= 10;
+ }
+}
+
+
+ENTRYPOINT Bool
+dazzle_handle_event (ModeInfo *mi, XEvent *event)
+{
+ dazzle_configuration *bp = &bps[MI_SCREEN(mi)];
+ Bool wire = MI_IS_WIREFRAME(mi);
+ GLfloat bx = fmod ((double) bp->xoff, 2.0);
+ GLfloat by = fmod ((double) bp->yoff, 2.0);
+ long wh = density * 2;
+
+ if (event->xany.type == ButtonPress)
+ {
+ GLfloat x = (GLfloat) event->xbutton.x / MI_WIDTH (mi) - 0.5;
+ GLfloat y = (GLfloat) event->xbutton.y / MI_HEIGHT (mi) - 0.5;
+ node *nn = 0;
+ int xoff = 0, yoff = 0;
+ GLfloat d2 = 999999;
+ long x0, y0, x1, y1;
+
+ if (wire) x /= 0.2, y /= 0.2;
+
+ for (y0 = -1; y0 <= 1; y0++)
+ for (x0 = -1; x0 <= 1; x0++)
+ for (y1 = 0; y1 < wh; y1++)
+ for (x1 = 0; x1 < wh; x1++)
+ {
+ node *n0 = &bp->nodes[(y1 % wh) * wh + (x1 % wh)];
+ double dist2;
+ GLfloat x2 = n0->x / density - 1 + bx + x0*2;
+ GLfloat y2 = n0->y / density - 1 + by + y0*2;
+
+ dist2 = (x - x2) * (x - x2) + (y - y2) * (y - y2);
+ if (dist2 < d2)
+ {
+ d2 = dist2;
+ nn = n0;
+ xoff = x0;
+ yoff = y0;
+ }
+ }
+
+ bp->button_down_p = True;
+ bp->dragging = nn;
+ bp->drag_x = xoff;
+ bp->drag_y = yoff;
+ return True;
+ }
+ else if (event->xany.type == ButtonRelease)
+ {
+ bp->dragging = 0;
+ bp->button_down_p = False;
+ return True;
+ }
+ else if (event->xany.type == MotionNotify && bp->dragging)
+ {
+ GLfloat x = (GLfloat) event->xmotion.x / MI_WIDTH (mi) - 0.5;
+ GLfloat y = (GLfloat) event->xmotion.y / MI_HEIGHT (mi) - 0.5;
+ if (wire) x /= 0.2, y /= 0.2;
+ x -= bx;
+ y -= by;
+ x -= bp->drag_x * 2;
+ y -= bp->drag_y * 2;
+ bp->dragging->x = x * density + density;
+ bp->dragging->y = y * density + density;
+ bp->dragging->dx = bp->dragging->dy = 0;
+ return True;
+ }
+ else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+ {
+ dazzle_randomize (mi);
+ return True;
+ }
+
+ return False;
+}
+
+
+ENTRYPOINT void
+init_dazzle (ModeInfo *mi)
+{
+ dazzle_configuration *bp;
+
+ MI_INIT (mi, bps);
+
+ bp = &bps[MI_SCREEN(mi)];
+
+ bp->glx_context = init_GL(mi);
+
+ if (!mode_arg || !*mode_arg || !strcasecmp(mode_arg, "random"))
+ bp->mode = RANDOM;
+ else if (!strcasecmp(mode_arg, "ship") || !strcasecmp(mode_arg, "ships"))
+ bp->mode = SHIPS;
+ else if (!strcasecmp(mode_arg, "flat"))
+ bp->mode = FLAT;
+ else
+ {
+ fprintf (stderr, "%s: mode must be ship, flat or random, not %s\n",
+ progname, mode_arg);
+ exit (1);
+ }
+
+ bp->which_ship = -1;
+ if (bp->mode == SHIPS || bp->mode == RANDOM)
+ {
+ int i;
+ bp->dlists = (GLuint *) calloc (countof(all_ships)+1, sizeof(GLuint));
+ for (i = 0; i < countof(all_ships); i++)
+ {
+ const struct gllist *gll = *all_ships[i];
+
+ bp->dlists[i] = glGenLists (1);
+ glNewList (bp->dlists[i], GL_COMPILE);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ if (random() & 1)
+ {
+ glScalef (-1, 1, 1);
+ glTranslatef (-1, 0, 0);
+ }
+ renderList (gll, MI_IS_WIREFRAME(mi));
+
+ glMatrixMode(GL_TEXTURE);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glEndList ();
+ }
+ }
+
+ dazzle_randomize (mi);
+ reshape_dazzle (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+}
+
+
+ENTRYPOINT void
+draw_dazzle (ModeInfo *mi)
+{
+ dazzle_configuration *bp = &bps[MI_SCREEN(mi)];
+ Bool wire = MI_IS_WIREFRAME(mi);
+ Display *dpy = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ int x, y;
+
+ if (!bp->glx_context)
+ return;
+
+ glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context));
+
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_NORMALIZE);
+ glDisable(GL_CULL_FACE);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix ();
+ mi->polygon_count = 0;
+
+ glTranslatef (0.5, 0.5, 0);
+
+ if (wire)
+ glScalef (0.2, 0.2, 1);
+
+ move_grid (mi);
+
+ for (y = -1; y <= 1; y++)
+ for (x = -1; x <= 1; x++)
+ draw_grid (mi, x, y);
+
+ if (bp->which_ship != -1)
+ {
+# ifdef USE_IPHONE
+ int rot = current_device_rotation();
+# endif
+
+ if (wire)
+ glColor3f (1, 0, 0);
+ else
+ {
+ glColor3f (0, 0, 0);
+
+ /* Draw into the depth buffer but not the frame buffer */
+ glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glClear (GL_DEPTH_BUFFER_BIT);
+ glEnable (GL_DEPTH_TEST);
+ }
+
+# ifdef USE_IPHONE
+ glRotatef (90, 0, 0, 1);
+ if (rot == 90 || rot == -270)
+ glRotatef (180, 0, 0, 1);
+# endif
+
+ glPushMatrix();
+ glRotatef (90, 1, 0, 0);
+ glScalef (0.9, 0.9, 0.9);
+ glTranslatef (-0.5, 0, -0.2);
+
+# ifdef USE_IPHONE
+ if (rot == 0 || rot == 180 || rot == -180)
+ glScalef (1, 1, (GLfloat) MI_HEIGHT(mi) / MI_WIDTH(mi));
+ else
+# endif
+ glScalef (1, 1, (GLfloat) MI_WIDTH(mi) / MI_HEIGHT(mi));
+
+ /* Wave boat horizontally and vertically */
+ glTranslatef (cos ((double) bp->frames / 80 * M_PI * speed) / 200,
+ 0,
+ cos ((double) bp->frames / 60 * M_PI * speed) / 300);
+
+ glCallList (bp->dlists[bp->which_ship]);
+ mi->polygon_count += (*all_ships[bp->which_ship])->points / 3;
+ glPopMatrix();
+
+ /* Wave horizon vertically */
+ glTranslatef (0,
+ cos ((double) bp->frames / 120 * M_PI * speed) / 200,
+ 0);
+
+ if (! wire)
+ {
+ glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ /* Black out everything that isn't a ship. */
+# if 0
+ glBegin (GL_QUADS);
+ glVertex3f (-1, -1, 0);
+ glVertex3f (-1, 1, 0);
+ glVertex3f ( 1, 1, 0);
+ glVertex3f ( 1, -1, 0);
+ glEnd();
+# else
+ {
+ GLfloat horizon = 0.15;
+
+ glColor3f (0.7, 0.7, 1.0);
+ glBegin (GL_QUADS);
+ glVertex3f (-1, -1, 0);
+ glVertex3f (-1, horizon, 0);
+ glVertex3f ( 1, horizon, 0);
+ glVertex3f ( 1, -1, 0);
+ glEnd();
+
+ glColor3f (0.0, 0.05, 0.2);
+ glBegin (GL_QUADS);
+ glVertex3f (-1, horizon, 0);
+ glVertex3f (-1, 1, 0);
+ glVertex3f ( 1, 1, 0);
+ glVertex3f ( 1, horizon, 0);
+ glEnd();
+ }
+# endif
+
+ glDisable (GL_DEPTH_TEST);
+ }
+ }
+
+ if (wire)
+ {
+ glColor3f(0,1,1);
+ glLineWidth(4);
+ glBegin(GL_LINE_LOOP);
+ glVertex3f(-0.5, -0.5, 0);
+ glVertex3f(-0.5, 0.5, 0);
+ glVertex3f( 0.5, 0.5, 0);
+ glVertex3f( 0.5, -0.5, 0);
+ glEnd();
+ glLineWidth(1);
+ }
+
+ glPopMatrix ();
+
+ bp->frames++;
+ if (mi->fps_p) do_fps (mi);
+ glFinish();
+
+ glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+free_dazzle (ModeInfo *mi)
+{
+ dazzle_configuration *bp = &bps[MI_SCREEN(mi)];
+ if (bp->nodes) free (bp->nodes);
+ if (bp->colors) free (bp->colors);
+ if (bp->dlists)
+ {
+ int i;
+ for (i = 0; i < countof(all_ships); i++)
+ glDeleteLists (bp->dlists[i], 1);
+ free (bp->dlists);
+ }
+}
+
+XSCREENSAVER_MODULE_2 ("RazzleDazzle", razzledazzle, dazzle)
+
+#endif /* USE_GL */