summaryrefslogtreecommitdiffstats
path: root/hacks/glx/peepers.c
diff options
context:
space:
mode:
authorSimon Rettberg2024-09-06 14:42:37 +0200
committerSimon Rettberg2024-09-06 14:42:37 +0200
commitbadef32037f52f79abc1f1440b786cd71afdf270 (patch)
tree412b792d4cab4a7a110db82fcf74fe8a1ac55ec1 /hacks/glx/peepers.c
parentDelete pre-6.00 files (diff)
downloadxscreensaver-master.tar.gz
xscreensaver-master.tar.xz
xscreensaver-master.zip
Diffstat (limited to 'hacks/glx/peepers.c')
-rw-r--r--hacks/glx/peepers.c1471
1 files changed, 0 insertions, 1471 deletions
diff --git a/hacks/glx/peepers.c b/hacks/glx/peepers.c
deleted file mode 100644
index 1554616..0000000
--- a/hacks/glx/peepers.c
+++ /dev/null
@@ -1,1471 +0,0 @@
-/* peepers, Copyright (c) 2018-2019 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.
- *
- * Created: 14 Feb 2018, jwz.
- *
- * Floating eyeballs!
- *
- * Inspired by @PaintYourDragon's Adafruit Snake Eyes Raspberry Pi Bonnet
- * https://learn.adafruit.com/animated-snake-eyes-bonnet-for-raspberry-pi/
- * which is excellent.
- */
-
-#define DEFAULTS "*delay: 30000 \n" \
- "*count: 0 \n" \
- "*showFPS: False \n" \
- "*wireframe: False \n" \
-
-# define release_peepers 0
-
-#define DEF_SPEED "1.0"
-#define DEF_MODE "random"
-
-#undef BELLRAND
-#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3)
-#undef RANDSIGN
-#define RANDSIGN() ((random() & 1) ? 1 : -1)
-
-#include "xlockmore.h"
-#include "normals.h"
-#include "rotator.h"
-#include "gltrackball.h"
-#include "ximage-loader.h"
-#include <ctype.h>
-
-#ifndef HAVE_JWXYZ
-# include <X11/Xatom.h>
-#endif
-
-#include "images/gen/sclera_png.h"
-#include "images/gen/iris_png.h"
-
-#ifdef USE_GL /* whole file */
-
-typedef struct { double a, o; } LL; /* latitude + longitude */
-
-typedef struct {
- int idx;
- GLfloat x, y, z;
- GLfloat dx, dy, dz;
- GLfloat ddx, ddy, ddz;
- rotator *rot;
- struct { GLfloat from, to, current, tick; } dilation;
- enum { ROTATE, SPIN, TRACK } focus;
- XYZ track;
- GLfloat tilt, roll;
- GLfloat scale;
- GLfloat color[4];
- int jaundice;
-} floater;
-
-typedef enum { RETINA, IRIS, SCLERA, LENS, TICK } component;
-
-typedef struct {
- GLXContext *glx_context;
- trackball_state *trackball;
-
- Bool button_down_p;
- XYZ mouse, last_mouse, fake_mouse;
- time_t last_mouse_time;
- int mouse_dx, mouse_dy;
-
- GLuint retina_list, sclera_list, lens_list, iris_list;
- GLuint sclera_texture, iris_texture;
- int eye_polys;
-
- int nfloaters;
- floater *floaters;
- enum { BOUNCE, SCROLL_LEFT, SCROLL_RIGHT, XEYES, BEHOLDER } mode;
-
-} peepers_configuration;
-
-static peepers_configuration *bps = NULL;
-
-static GLfloat speed;
-const char *mode_opt;
-
-static XrmOptionDescRec opts[] = {
- { "-speed", ".speed", XrmoptionSepArg, 0 },
- { "-mode", ".mode", XrmoptionSepArg, 0 },
-};
-
-static argtype vars[] = {
- {&speed, "speed", "Speed", DEF_SPEED, t_Float},
- {&mode_opt, "mode", "Mode", DEF_MODE, t_String},
-};
-
-ENTRYPOINT ModeSpecOpt peepers_opts = {countof(opts), opts, countof(vars), vars, NULL};
-
-
-/* Bottom edge of screen is -0.5; left and right scale by aspect. */
-#define BOTTOM (-1.6)
-#define LEFT (BOTTOM * MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi))
-
-static void
-reset_floater (ModeInfo *mi, floater *f)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- GLfloat r = ((bp->mode == BOUNCE ? LEFT : BOTTOM) *
- (bp->nfloaters < 10 ? 0.3: 0.6));
- GLfloat x, y;
-
- if (bp->nfloaters <= 2)
- {
- x = frand(LEFT) * RANDSIGN() * 0.3;
- y = 0;
- }
- else
- {
- /* Position them off screen in a circle */
- GLfloat th = f->idx * (M_PI + (M_PI/6)) * 2 / bp->nfloaters;
- x = r * cos (th);
- y = r * sin (th) * 1.5; /* Oval */
- }
-
- switch (bp->mode) {
- case BOUNCE:
- f->x = x;
- f->y = BOTTOM;
- f->z = y;
-
- /* Yes, I know I'm varying the force of gravity instead of varying the
- launch velocity. That's intentional: empirical studies indicate
- that it's way, way funnier that way. */
-
- f->dy = 0.1;
- f->dx = 0;
- f->dz = 0;
-
- {
- GLfloat min = -0.004;
- GLfloat max = -0.0019;
- f->ddy = min + frand (max - min);
- f->ddx = 0;
- f->ddz = 0;
- }
-
- if (! (random() % (10 * bp->nfloaters)))
- {
- f->dx = BELLRAND(0.03) * RANDSIGN();
- f->dz = BELLRAND(0.03) * RANDSIGN();
- }
- break;
-
- case SCROLL_LEFT:
- case SCROLL_RIGHT:
-
- f->x = (bp->mode == SCROLL_LEFT ? -LEFT : LEFT);
- f->y = x;
- f->z = y;
-
- f->dx = (1.0 + frand(2.0)) * 0.020 * (bp->mode == SCROLL_LEFT ? -1 : 1);
- f->dy = (1.0 + frand(2.0)) * 0.002 * RANDSIGN();
- f->dz = (1.0 + frand(2.0)) * 0.002 * RANDSIGN();
- f->ddy = 0;
- f->ddz = 0;
- break;
-
- case XEYES: /* This happens in layout_grid() */
- break;
- case BEHOLDER: /* This happens in layout_geodesic() */
- break;
-
- default:
- abort();
- }
-
- f->focus = ((random() % 8) ? ROTATE :
- (random() % 4) ? TRACK : SPIN);
- f->track.x = 8 - frand(16);
- f->track.y = 8 - frand(16);
- f->track.z = 8 + frand(16);
-
- f->tilt = 45 - BELLRAND(90);
- f->roll = frand(180);
- f->dilation.to = f->dilation.from = f->dilation.current = frand(1.0);
- f->dilation.tick = 1;
-
- f->scale = 0.8 + BELLRAND(0.2);
-
- if (bp->nfloaters == 1) f->scale *= 0.5;
- else if (bp->nfloaters <= 3) f->scale *= 0.4;
- else if (bp->nfloaters <= 9) f->scale *= 0.3;
- else if (bp->nfloaters <= 15) f->scale *= 0.2;
- else if (bp->nfloaters <= 25) f->scale *= 0.15;
- else if (bp->nfloaters <= 90) f->scale *= 0.12;
- else f->scale *= 0.07;
-
- if (MI_WIDTH(mi) < MI_HEIGHT(mi))
- {
- f->scale /= MI_HEIGHT(mi) / (GLfloat) MI_WIDTH(mi) * 1.2;
- }
-
- {
- static const struct { GLfloat pct; unsigned long c; } c[] = {
- /* All of the articles that I found with percentages in them only
- added up to around 70%, so who knows what that means. */
-# if 0
- { 55, 0x985A07 }, /* brown -- supposedly real global percentage */
-# else
- { 20, 0x985A07 }, /* brown -- but that's a lot of brown... */
-# endif
- { 8, 0xD5AD68 }, /* hazel */
- { 8, 0x777F92 }, /* blue */
- { 2, 0x6B7249 }, /* green */
- { 1, 0x7F7775 }, /* gray */
- { 0.5, 0x9E8042 }, /* amber */
- { 0.1, 0xFFAA88 }, /* red */
- };
- GLfloat p = 0, t = 0;
- GLfloat s = 1 - frand(0.3);
- int i;
- for (i = 0; i < countof(c); i++)
- p += c[i].pct;
- p = frand(p);
-
- for (i = 0; i < countof(c) - 1; i++)
- {
- t += c[i].pct;
- if (t > p) break;
- }
-
- if (c[i].c == 0xFFAA88) f->jaundice = 2;
- else if (!(random() % 20)) f->jaundice = 1;
-
- f->color[0] = ((c[i].c >> 16) & 0xFF) / 255.0 * s;
- f->color[1] = ((c[i].c >> 8) & 0xFF) / 255.0 * s;
- f->color[2] = ((c[i].c >> 0) & 0xFF) / 255.0 * s;
- f->color[3] = 1;
- }
-}
-
-
-/* Place a grid of eyeballs on the screen, maximizing use of space.
- */
-static void
-layout_grid (ModeInfo *mi)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
-
- /* Distribute the eyes into a rectangular grid that fills the window.
- There may be some empty cells. N items in a W x H rectangle:
- N = W * H
- N = W * W * R
- N/R = W*W
- W = sqrt(N/R)
- */
- GLfloat aspect = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi);
- int nlines = sqrt (bp->nfloaters / aspect) + 0.5;
- int *cols = (int *) calloc (nlines, sizeof(*cols));
- int i, x, y, max = 0;
- GLfloat scale, spacing;
-
- for (i = 0; i < bp->nfloaters; i++)
- {
- cols[i % nlines]++;
- if (cols[i % nlines] > max) max = cols[i % nlines];
- }
-
- /* That gave us, e.g. 7777666. Redistribute to 6767767. */
- for (i = 0; i < nlines / 2; i += 2)
- {
- int j = nlines-i-1;
- int swap = cols[i];
- cols[i] = cols[j];
- cols[j] = swap;
- }
-
- scale = 1.0 / nlines; /* Scale for height */
- if (scale * max > aspect) /* Shrink if overshot width */
- scale *= aspect / (scale * max);
-
- scale *= 0.9; /* Add padding */
- spacing = scale * 2.2;
-
- if (bp->nfloaters == 1) spacing = 0;
-
- i = 0;
- for (y = 0; y < nlines; y++)
- for (x = 0; x < cols[y]; x++)
- {
- floater *f = &bp->floaters[i];
- f->scale = scale;
- f->x = spacing * (x - cols[y] / 2.0) + spacing/2;
- f->y = spacing * (y - nlines / 2.0) + spacing/2;
- f->z = 0;
- i++;
- }
- free (cols);
-}
-
-
-/* Computes the midpoint of a line between two polar coords.
- */
-static void
-midpoint2 (LL v1, LL v2, LL *vm_ret,
- XYZ *p1_ret, XYZ *p2_ret, XYZ *pm_ret)
-{
- XYZ p1, p2, pm;
- LL vm;
- GLfloat hyp;
-
- p1.x = cos (v1.a) * cos (v1.o);
- p1.y = cos (v1.a) * sin (v1.o);
- p1.z = sin (v1.a);
-
- p2.x = cos (v2.a) * cos (v2.o);
- p2.y = cos (v2.a) * sin (v2.o);
- p2.z = sin (v2.a);
-
- pm.x = (p1.x + p2.x) / 2;
- pm.y = (p1.y + p2.y) / 2;
- pm.z = (p1.z + p2.z) / 2;
-
- vm.o = atan2 (pm.y, pm.x);
- hyp = sqrt (pm.x * pm.x + pm.y * pm.y);
- vm.a = atan2 (pm.z, hyp);
-
- *p1_ret = p1;
- *p2_ret = p2;
- *pm_ret = pm;
- *vm_ret = vm;
-}
-
-
-/* Computes the midpoint of a triangle specified in polar coords.
- */
-static void
-midpoint3 (LL v1, LL v2, LL v3, LL *vm_ret,
- XYZ *p1_ret, XYZ *p2_ret, XYZ *p3_ret, XYZ *pm_ret)
-{
- XYZ p1, p2, p3, pm;
- LL vm;
- GLfloat hyp;
-
- p1.x = cos (v1.a) * cos (v1.o);
- p1.y = cos (v1.a) * sin (v1.o);
- p1.z = sin (v1.a);
-
- p2.x = cos (v2.a) * cos (v2.o);
- p2.y = cos (v2.a) * sin (v2.o);
- p2.z = sin (v2.a);
-
- p3.x = cos (v3.a) * cos (v3.o);
- p3.y = cos (v3.a) * sin (v3.o);
- p3.z = sin (v3.a);
-
- pm.x = (p1.x + p2.x + p3.x) / 3;
- pm.y = (p1.y + p2.y + p3.y) / 3;
- pm.z = (p1.z + p2.z + p3.z) / 3;
-
- vm.o = atan2 (pm.y, pm.x);
- hyp = sqrt (pm.x * pm.x + pm.y * pm.y);
- vm.a = atan2 (pm.z, hyp);
-
- *p1_ret = p1;
- *p2_ret = p2;
- *p3_ret = p3;
- *pm_ret = pm;
- *vm_ret = vm;
-}
-
-
-/* Place the eyeballs on a sphere (geodesic)
- */
-static void
-layout_geodesic_triangle (ModeInfo *mi, LL v1, LL v2, LL v3, int depth,
- int *i)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
-
- if (depth <= 0)
- {
- floater *f = &bp->floaters[*i];
- GLfloat s2 = 0.7;
- LL vc;
- XYZ p1, p2, p3, pc;
- if (*i >= bp->nfloaters) abort();
-
- midpoint3 (v1, v2, v3, &vc, &p1, &p2, &p3, &pc);
-
- switch (bp->nfloaters) { /* This is lame. */
- case 20: f->scale = 0.26; break;
- case 80: f->scale = 0.13; break;
- case 320: f->scale = 0.065; break;
- case 1280: f->scale = 0.0325; break;
- default: abort();
- }
-
- f->z = s2 * cos (vc.a) * cos (vc.o);
- f->x = s2 * cos (vc.a) * sin (vc.o);
- f->y = s2 * sin (vc.a);
- (*i)++;
- }
- else
- {
- LL v12, v23, v13;
- XYZ p1, p2, p3, p12, p23, p13;
-
- midpoint2 (v1, v2, &v12, &p1, &p2, &p12);
- midpoint2 (v2, v3, &v23, &p2, &p3, &p23);
- midpoint2 (v1, v3, &v13, &p1, &p3, &p13);
- depth--;
-
- layout_geodesic_triangle (mi, v1, v12, v13, depth, i);
- layout_geodesic_triangle (mi, v12, v2, v23, depth, i);
- layout_geodesic_triangle (mi, v13, v23, v3, depth, i);
- layout_geodesic_triangle (mi, v12, v23, v13, depth, i);
- }
-}
-
-
-/* Creates triangles of a geodesic to the given depth (frequency).
- */
-static void
-layout_geodesic (ModeInfo *mi)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- int depth;
- GLfloat th0 = atan (0.5); /* lat division: 26.57 deg */
- GLfloat s = M_PI / 5; /* lon division: 72 deg */
- int i;
- int ii = 0;
-
- switch (bp->nfloaters) { /* This is lame. */
- case 20: depth = 0; break;
- case 80: depth = 1; break;
- case 320: depth = 2; break;
- case 1280: depth = 3; break;
- default: abort();
- }
-
- for (i = 0; i < 10; i++)
- {
- GLfloat th1 = s * i;
- GLfloat th2 = s * (i+1);
- GLfloat th3 = s * (i+2);
- LL v1, v2, v3, vc;
- v1.a = th0; v1.o = th1;
- v2.a = th0; v2.o = th3;
- v3.a = -th0; v3.o = th2;
- vc.a = M_PI/2; vc.o = th2;
-
- if (i & 1) /* north */
- {
- layout_geodesic_triangle (mi, v1, v2, vc, depth, &ii);
- layout_geodesic_triangle (mi, v2, v1, v3, depth, &ii);
- }
- else /* south */
- {
- v1.a = -v1.a;
- v2.a = -v2.a;
- v3.a = -v3.a;
- vc.a = -vc.a;
- layout_geodesic_triangle (mi, v2, v1, vc, depth, &ii);
- layout_geodesic_triangle (mi, v1, v2, v3, depth, &ii);
- }
- }
-
- bp->floaters[0].dx = BELLRAND(0.01) * RANDSIGN();
-}
-
-
-/* Advance the animation by one step.
- */
-static void
-tick_floater (ModeInfo *mi, floater *f)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
-
- /* if (bp->button_down_p) return;*/
-
- f->dx += f->ddx * speed * 0.5;
- f->dy += f->ddy * speed * 0.5;
- f->dz += f->ddz * speed * 0.5;
-
- if (bp->mode != BEHOLDER)
- {
- f->x += f->dx * speed * 0.5;
- f->y += f->dy * speed * 0.5;
- f->z += f->dz * speed * 0.5;
- }
-
- f->dilation.tick += 0.1 * speed;
- if (f->dilation.tick > 1) f->dilation.tick = 1;
- if (f->dilation.tick < 0) f->dilation.tick = 0;
-
- f->dilation.current = (f->dilation.from +
- ((f->dilation.to - f->dilation.from) *
- f->dilation.tick));
-
- if (f->dilation.tick == 1 && !(random() % 20))
- {
- f->dilation.from = f->dilation.to;
- f->dilation.to = frand(1.0);
- f->dilation.tick = 0;
- }
-
- switch (bp->mode) {
- case BOUNCE:
- if (f->y < BOTTOM ||
- f->x < LEFT || f->x > -LEFT)
- reset_floater (mi, f);
- break;
- case SCROLL_LEFT:
- if (f->x < LEFT)
- reset_floater (mi, f);
- break;
- case SCROLL_RIGHT:
- if (f->x > -LEFT)
- reset_floater (mi, f);
- break;
- case XEYES:
- break;
- case BEHOLDER:
- {
- GLfloat x = f->x;
- GLfloat y = f->z;
- GLfloat th = atan2 (y, x);
- GLfloat r = sqrt(x*x + y*y);
- th += bp->floaters[0].dx;
- f->x = r*cos(th);
- f->z = r*sin(th);
-
- if (! (random() % 100))
- bp->floaters[0].dx += frand(0.0001) * RANDSIGN();
- }
- break;
- default:
- abort();
- }
-}
-
-
-/* Make sure none of the eyeballs overlap.
- */
-static void
-de_collide (ModeInfo *mi)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- int i, j;
- for (i = 0; i < bp->nfloaters; i++)
- {
- floater *f0 = &bp->floaters[i];
- for (j = i+1; j < bp->nfloaters; j++)
- {
- floater *f1 = &bp->floaters[j];
- GLfloat X = f1->x - f0->x;
- GLfloat Y = f1->y - f0->y;
- GLfloat Z = f1->z - f0->z;
- GLfloat min = (f0->scale + f1->scale);
- GLfloat d2 = X*X + Y*Y + Z*Z;
- if (d2 < min*min)
- {
- GLfloat d = sqrt (d2);
- GLfloat dd = 0.5 * (min - d) / 2;
- GLfloat dx = X * dd;
- GLfloat dy = Y * dd;
- GLfloat dz = Z * dd;
- f0->x -= dx; f0->y -= dy; f0->z -= dz;
- f1->x += dx; f1->y += dy; f1->z += dz;
- }
- }
- }
-}
-
-
-/* Window management, etc
- */
-ENTRYPOINT void
-reshape_peepers (ModeInfo *mi, int width, int height)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- GLfloat h = (GLfloat) height / (GLfloat) width;
- int y = 0;
-
- glViewport (0, y, (GLint) width, (GLint) height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective (30.0, 1/h, 1.0, 100);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- gluLookAt( 0.0, 0.0, 30.0,
- 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0);
-
- glClear(GL_COLOR_BUFFER_BIT);
-
- if (bp->mode == XEYES)
- layout_grid (mi);
-}
-
-
-/* Find the mouse pointer on the screen and note its position in the scene.
- */
-static void
-track_mouse (ModeInfo *mi)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- Window r, c;
- int x, y, rx, ry;
- unsigned int m;
- int w = MI_WIDTH(mi);
- int h = MI_HEIGHT(mi);
- int rot = (int) current_device_rotation();
- int swap;
- GLfloat ys = 2.0;
- GLfloat xs = ys * w / h;
- time_t now = time ((time_t *) 0);
-
- XQueryPointer (MI_DISPLAY (mi), MI_WINDOW (mi),
- &r, &c, &rx, &ry, &x, &y, &m);
-
- if (x != bp->last_mouse.x && y != bp->last_mouse.y)
- {
- bp->last_mouse_time = now;
- bp->fake_mouse.x = x;
- bp->fake_mouse.y = y;
- bp->mouse_dx = 0;
- bp->mouse_dy = 0;
- bp->last_mouse.x = x;
- bp->last_mouse.y = y;
- }
- else if (now > bp->last_mouse_time + 10)
- {
- /* Mouse isn't moving. Bored now. */
- if (! (random() % 20)) bp->mouse_dx += (random() % 2) * RANDSIGN();
- if (! (random() % 20)) bp->mouse_dy += (random() % 2) * RANDSIGN();
- bp->fake_mouse.x += bp->mouse_dx;
- bp->fake_mouse.y += bp->mouse_dy;
- x = bp->fake_mouse.x;
- y = bp->fake_mouse.y;
- }
-
- while (rot <= -180) rot += 360;
- while (rot > 180) rot -= 360;
-
- if (rot > 135 || rot < -135) /* 180 */
- {
- x = w - x;
- y = h - y;
- }
- else if (rot > 45) /* 90 */
- {
- swap = x; x = y; y = swap;
- swap = w; w = h; h = swap;
- xs = ys;
- ys = xs * w / h;
- x = w - x;
- }
- else if (rot < -45) /* 270 */
- {
- swap = x; x = y; y = swap;
- swap = w; w = h; h = swap;
- xs = ys;
- ys = xs * w / h;
- y = h - y;
- }
-
- /* Put the mouse directly on the glass. */
- x = x - w / 2;
- y = h / 2 - y;
- bp->mouse.x = xs * x / w;
- bp->mouse.y = ys * y / h;
- bp->mouse.z = 0;
-
-# if 0
- glPushMatrix();
- glTranslatef (bp->mouse.x, bp->mouse.y, bp->mouse.z);
- if (!MI_IS_WIREFRAME(mi)) glDisable(GL_LIGHTING);
- glColor3f(1,1,1);
- glBegin(GL_LINES);
- glVertex3f(-1,0,0); glVertex3f(1,0,0);
- glVertex3f(0,-1,0); glVertex3f(0,1,0);
- glVertex3f(0,0,-1); glVertex3f(0,0,1);
- glEnd();
- glPopMatrix();
- if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
-# endif
-
- /* Move it farther into the scene: on the glass is too far away.
- But keep it farther away the farther outside the window the
- mouse is, so the eyes don''t turn 90 degrees sideways.
- */
- bp->mouse.x *= 0.8;
- bp->mouse.y *= 0.8;
- bp->mouse.z += 0.7;
-
- bp->mouse.z = MAX (0.7,
- sqrt (bp->mouse.x * bp->mouse.x +
- bp->mouse.y * bp->mouse.y));
-
- if (bp->mode == BEHOLDER)
- bp->mouse.z += 0.25;
-
-
-# if 0
- glPushMatrix();
- glTranslatef (bp->mouse.x, bp->mouse.y, bp->mouse.z);
- if (!MI_IS_WIREFRAME(mi)) glDisable(GL_LIGHTING);
- glColor3f(1,0,1);
- glBegin(GL_LINES);
- glVertex3f(-1,0,0); glVertex3f(1,0,0);
- glVertex3f(0,-1,0); glVertex3f(0,1,0);
- glVertex3f(0,0,-1); glVertex3f(0,0,1);
- glEnd();
- glPopMatrix();
- if (!MI_IS_WIREFRAME(mi)) glEnable(GL_LIGHTING);
-# endif
-}
-
-
-ENTRYPOINT Bool
-peepers_handle_event (ModeInfo *mi, XEvent *event)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
-
- if (gltrackball_event_handler (event, bp->trackball,
- MI_WIDTH (mi), MI_HEIGHT (mi),
- &bp->button_down_p))
- {
- if (bp->button_down_p) /* Aim each eyeball at the mouse. */
- {
- int i;
- track_mouse (mi);
- for (i = 0; i < bp->nfloaters; i++)
- {
- floater *f = &bp->floaters[i];
- f->track = bp->mouse;
- f->focus = TRACK;
- }
- }
-
- return True;
- }
-
- return False;
-}
-
-
-/* Generate the polygons for the display lists.
- This routine generates the various styles of sphere-oid we use.
- */
-static int
-draw_ball (ModeInfo *mi, component which)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
- int polys = 0;
-
- GLfloat iris_ratio = 0.42; /* Size of the iris. */
- /* The lens bulges out, but the iris bulges in, sorta. */
- GLfloat lens_bulge = (which == IRIS ? -0.50 : 0.32);
-
- GLfloat xstep = 32; /* Facets on the sphere */
- GLfloat ystep = 32;
- XYZ *stacks, *normals;
- GLfloat x, y, z;
- int i, j;
- int xstart, xstop;
-
- if (bp->nfloaters > 16 || wire)
- xstep = ystep = 16;
-
- if (bp->nfloaters > 96 && which == LENS)
- return 0;
-
- switch (which) {
- case LENS: xstart = 0; xstop = xstep; break;
- case SCLERA: xstart = 0; xstop = xstep * (1 - iris_ratio/2); break;
- case IRIS: xstart = xstep * (1 - iris_ratio/2 * 1.2); xstop = xstep; break;
- case RETINA: xstart = xstep * (1 - iris_ratio/2 * 1.2); xstop = 0; break;
- default: abort(); break;
- }
-
- stacks = (XYZ *) calloc (sizeof(*stacks), xstep + 1);
- normals = (XYZ *) calloc (sizeof(*stacks), xstep + 1);
-
- if (which == RETINA)
- {
- GLfloat c1[4] = { 0, 0, 0, 1 };
- GLfloat c2[4] = { 0.15, 0, 0, 1 };
- GLfloat th = M_PI * (1.0 - iris_ratio/2);
- GLfloat z1 = cos(th);
- GLfloat z2 = 0.9;
- GLfloat r1 = sin(th);
- GLfloat r2 = r1 * 0.3;
-
- if (!wire)
- {
- glColor4fv (c1);
- glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c1);
- glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, c1);
- }
-
- /* Draw a black cone to occlude the interior of the eye. */
-
- glBegin (wire ? GL_LINES : GL_QUAD_STRIP);
- for (i = 0; i <= xstep; i++)
- {
- GLfloat th2 = i * M_PI * 2 / xstep;
- GLfloat x = cos(th2);
- GLfloat y = sin(th2);
- glNormal3f (0, 0, 1);
- glVertex3f (z1, r1 * x, r1 * y);
- glNormal3f (0, 0, 1);
- glVertex3f (z2, r2 * x, r2 * y);
- polys++;
- }
- glEnd();
-
- if (!wire)
- {
- glColor4fv (c2);
- glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c2);
- glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, c2);
- }
-
- /* Draw a small red circle at the base of the cone. */
-
- glBegin (wire ? GL_LINES : GL_TRIANGLE_FAN);
- glVertex3f (z2, 0, 0);
- glNormal3f (0, 0, 1);
- for (i = xstep; i >= 0; i--)
- {
- GLfloat th2 = i * M_PI * 2 / xstep;
- GLfloat x = cos(th2);
- GLfloat y = sin(th2);
- glVertex3f (z2, r2 * x, r2 * y);
- polys++;
- }
- glEnd();
- goto DONE;
- }
-
- for (i = xstart; i <= xstop; i++)
- {
- GLfloat th = i * M_PI / xstep;
- GLfloat x = cos(th);
- GLfloat y = sin(th);
-
- /* Bulge the lens, or dimple the iris. */
- if (th > M_PI * (1.0 - iris_ratio/2) &&
- th < M_PI * (1.0 + iris_ratio/2))
- {
- GLfloat r = (1 - th / M_PI) / iris_ratio * 2;
- r = cos (M_PI * r / 2);
- r *= lens_bulge;
- r = r * r * (lens_bulge < 0 ? -1 : 1);
- x *= 1+r;
- y *= 1+r;
- }
-
- stacks[i].x = x;
- stacks[i].y = y;
- stacks[i].z = 0;
- }
-
- /* Fill normals with the normal at the center of each face. */
- for (i = xstart; i < xstop; i++)
- {
- GLfloat dx = stacks[i+1].x - stacks[i].x;
- GLfloat dy = stacks[i+1].y - stacks[i].y;
- y = dy/dx;
- z = sqrt (1 + y*y);
- normals[i].x = -y/z;
- normals[i].y = 1/z;
- normals[i].z = 0;
-
- if (lens_bulge < 0 && i > xstep * (1 - iris_ratio/2) + 1)
- {
- normals[i].x *= -1;
- normals[i].y *= -1;
- }
- }
-
- if (!wire)
- glBegin (GL_QUADS);
-
- for (i = xstart; i < xstop; i++)
- {
- GLfloat x0 = stacks[i].x;
- GLfloat x1 = stacks[i+1].x;
- GLfloat r0 = stacks[i].y;
- GLfloat r1 = stacks[i+1].y;
-
- for (j = 0; j < ystep*2; j++)
- {
- GLfloat tha = j * M_PI / ystep;
- GLfloat thb = (j+1) * M_PI / ystep;
- GLfloat xa = cos (tha);
- GLfloat ya = sin (tha);
- GLfloat xb = cos (thb);
- GLfloat yb = sin (thb);
-
- /* Each vertex normal is average of adjacent face normals. */
-
- XYZ p1, p2, p3, p4;
- XYZ n1, n2, n3, n4;
- p1.x = x0; p1.y = r0 * ya; p1.z = r0 * xa;
- p2.x = x1; p2.y = r1 * ya; p2.z = r1 * xa;
- p3.x = x1; p3.y = r1 * yb; p3.z = r1 * xb;
- p4.x = x0; p4.y = r0 * yb; p4.z = r0 * xb;
-
- if (i == 0)
- {
- n1.x = 1; n1.y = 0; n1.z = 0;
- n4.x = 1; n4.y = 0; n4.z = 0;
- }
- else
- {
- x = (normals[i-1].x + normals[i].x) / 2;
- y = (normals[i-1].y + normals[i].y) / 2;
- n1.x = x; n1.z = y * xa; n1.y = y * ya;
- n4.x = x; n4.z = y * xb; n4.y = y * yb;
- }
-
- if (i == xstep-1)
- {
- n2.x = -1; n2.y = 0; n2.z = 0;
- n3.x = -1; n3.y = 0; n3.z = 0;
- }
- else
- {
- x = (normals[i+1].x + normals[i].x) / 2;
- y = (normals[i+1].y + normals[i].y) / 2;
- n2.x = x; n2.z = y * xa; n2.y = y * ya;
- n3.x = x; n3.z = y * xb; n3.y = y * yb;
- }
-
-#if 0
- /* Render normals as lines for debugging */
- glBegin(GL_LINES);
- glVertex3f(p1.x, p1.y, p1.z);
- glVertex3f(p1.x + n1.x * 0.3, p1.y + n1.y * 0.3, p1.z + n1.z * 0.3);
- glEnd();
-
- glBegin(GL_LINES);
- glVertex3f(p2.x, p2.y, p2.z);
- glVertex3f(p2.x + n2.x * 0.3, p2.y + n2.y * 0.3, p2.z + n2.z * 0.3);
- glEnd();
-
- glBegin(GL_LINES);
- glVertex3f(p3.x, p3.y, p3.z);
- glVertex3f(p3.x + n3.x * 0.3, p3.y + n3.y * 0.3, p3.z + n3.z * 0.3);
- glEnd();
-
- glBegin(GL_LINES);
- glVertex3f(p4.x, p4.y, p4.z);
- glVertex3f(p4.x + n4.x * 0.3, p4.y + n4.y * 0.3, p4.z + n4.z * 0.3);
- glEnd();
-#endif
-
- if (wire)
- glBegin (GL_LINE_LOOP);
-
- glTexCoord2f ((j+1) / (GLfloat) ystep / 2,
- (i - xstart) / (GLfloat) (xstop - xstart));
-
- glNormal3f (n4.x, n4.y, n4.z);
- glVertex3f (p4.x, p4.y, p4.z);
-
- glTexCoord2f ((j+1) / (GLfloat) ystep / 2,
- ((i+1) - xstart) / (GLfloat) (xstop - xstart));
-
- glNormal3f (n3.x, n3.y, n3.z);
- glVertex3f (p3.x, p3.y, p3.z);
-
- glTexCoord2f (j / (GLfloat) ystep / 2,
- ((i+1) - xstart) / (GLfloat) (xstop - xstart));
-
- glNormal3f (n2.x, n2.y, n2.z);
- glVertex3f (p2.x, p2.y, p2.z);
-
- glTexCoord2f (j / (GLfloat) ystep / 2,
- (i - xstart) / (GLfloat) (xstop - xstart));
-
- glNormal3f (n1.x, n1.y, n1.z);
- glVertex3f (p1.x, p1.y, p1.z);
-
- polys++;
-
- if (wire)
- glEnd();
- }
- }
-
- if (!wire)
- glEnd();
-
- DONE:
- free (stacks);
- free (normals);
-
- return polys;
-}
-
-
-ENTRYPOINT void
-init_peepers (ModeInfo *mi)
-{
- peepers_configuration *bp;
- int wire = MI_IS_WIREFRAME(mi);
- int i;
-
- MI_INIT (mi, bps);
-
- bp = &bps[MI_SCREEN(mi)];
-
- bp->glx_context = init_GL(mi);
-
- reshape_peepers (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
-
- glShadeModel(GL_SMOOTH);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_NORMALIZE);
-
- if (!wire)
- {
- XImage *xi;
- GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0};
- GLfloat amb[4] = {0.1, 0.1, 0.1, 1.0};
-
- glLightfv(GL_LIGHT0, GL_POSITION, pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
-
- glEnable (GL_LIGHTING);
- glEnable (GL_LIGHT0);
- glEnable (GL_DEPTH_TEST);
- glEnable (GL_CULL_FACE);
- glEnable (GL_BLEND);
-
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glLightfv(GL_LIGHT0, GL_POSITION, pos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
-
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
-
- xi = image_data_to_ximage (mi->dpy, mi->xgwa.visual,
- sclera_png, sizeof(sclera_png));
- glGenTextures (1, &bp->sclera_texture);
- glBindTexture (GL_TEXTURE_2D, bp->sclera_texture);
-
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
- xi->width, xi->height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, xi->data);
- check_gl_error("texture");
- XDestroyImage (xi);
-
- xi = image_data_to_ximage (mi->dpy, mi->xgwa.visual,
- iris_png, sizeof(iris_png));
-
- glGenTextures (1, &bp->iris_texture);
- glBindTexture (GL_TEXTURE_2D, bp->iris_texture);
-
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
- xi->width, xi->height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, xi->data);
- check_gl_error("texture");
- XDestroyImage (xi);
-
-
- }
-
- bp->lens_list = glGenLists (1);
- glNewList (bp->lens_list, GL_COMPILE);
- bp->eye_polys += draw_ball (mi, LENS);
- glEndList ();
-
- bp->sclera_list = glGenLists (1);
- glNewList (bp->sclera_list, GL_COMPILE);
- bp->eye_polys += draw_ball (mi, SCLERA);
- glEndList ();
-
- bp->iris_list = glGenLists (1);
- glNewList (bp->iris_list, GL_COMPILE);
- bp->eye_polys += draw_ball (mi, IRIS);
- glEndList ();
-
- bp->retina_list = glGenLists (1);
- glNewList (bp->retina_list, GL_COMPILE);
- bp->eye_polys += draw_ball (mi, RETINA);
- glEndList ();
-
- bp->trackball = gltrackball_init (False);
-
- if (!mode_opt || !*mode_opt || !strcasecmp (mode_opt, "random"))
- bp->mode = ((random() & 1) ? BOUNCE :
- ((random() & 1) ? SCROLL_LEFT : SCROLL_RIGHT));
- else if (!strcasecmp (mode_opt, "bounce"))
- bp->mode = BOUNCE;
- else if (!strcasecmp (mode_opt, "scroll"))
- bp->mode = (random() & 1) ? SCROLL_LEFT : SCROLL_RIGHT;
- else if (!strcasecmp (mode_opt, "xeyes"))
- bp->mode = XEYES;
- else if (!strcasecmp (mode_opt, "beholder") ||
- !strcasecmp (mode_opt, "ball"))
- bp->mode = BEHOLDER;
- else
- {
- fprintf (stderr,
- "%s: mode must be bounce, scroll, random, xeyes or beholder,"
- " not \"%s\"\n",
- progname, mode_opt);
- exit (1);
- }
-
- bp->nfloaters = MI_COUNT (mi);
-
- if (bp->nfloaters <= 0)
- {
- if (bp->mode == XEYES)
- bp->nfloaters = 2 + (random() % 30);
- else if (bp->mode == BEHOLDER)
- bp->nfloaters = 20 * pow (4, (random() % 4));
- else
- bp->nfloaters = 2 + (random() % 6);
- }
-
- if (bp->mode == BEHOLDER)
- {
- if (bp->nfloaters <= 20) bp->nfloaters = 20; /* This is lame */
- else if (bp->nfloaters <= 80) bp->nfloaters = 80;
- else if (bp->nfloaters <= 320) bp->nfloaters = 320;
- else bp->nfloaters = 1280;
- }
-
- bp->floaters = (floater *) calloc (bp->nfloaters, sizeof (floater));
-
- for (i = 0; i < bp->nfloaters; i++)
- {
- floater *f = &bp->floaters[i];
- f->idx = i;
- f->rot = make_rotator (10.0, 0, 0,
- 4, 0.05 * speed,
- True);
- if (bp->nfloaters == 2)
- {
- f->x = 10 * (i ? 1 : -1);
- }
- else if (i != 0)
- {
- double th = (i - 1) * M_PI*2 / (bp->nfloaters-1);
- double r = LEFT * 0.3;
- f->x = r * cos(th);
- f->z = r * sin(th);
- }
-
- if (bp->mode == SCROLL_LEFT || bp->mode == SCROLL_RIGHT)
- {
- f->y = f->x;
- f->x = 0;
- }
-
- reset_floater (mi, f);
- }
-
- if (bp->mode == XEYES)
- layout_grid (mi);
- else if (bp->mode == BEHOLDER)
- layout_geodesic (mi);
-
-# ifndef HAVE_JWXYZ /* Real X11 */
-# if 0 /* I wonder if this works? */
- if (bp->mode == XEYES && MI_WIN_IS_INWINDOW (mi))
- {
- uint32_t ca = 0;
- glClearColor (0, 0, 0, 0);
- XChangeProperty (MI_DISPLAY(mi), MI_WINDOW(mi),
- XInternAtom (MI_DISPLAY(mi),
- "_NET_WM_WINDOW_OPACITY", 0),
- XA_CARDINAL, 32, PropModeReplace,
- (uint8_t *) &ca, 1);
- }
-# endif
-# endif
-}
-
-
-static void
-draw_floater (ModeInfo *mi, floater *f, component which)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- int wire = MI_IS_WIREFRAME(mi);
- double x, y, z;
-
- GLfloat spc[4] = { 1.0, 1.0, 1.0, 1.0 };
- GLfloat c2[4] = { 1.0, 1.0, 1.0, 1.0 };
- GLfloat c2b[4] = { 1.0, 0.6, 0.6, 1.0 };
- GLfloat c2c[4] = { 1.0, 1.0, 0.65, 1.0 };
- GLfloat c3[4] = { 0.6, 0.6, 0.6, 0.25 };
-
- get_position (f->rot, &x, &y, &z,
- which == LENS && !bp->button_down_p);
-
- if (bp->nfloaters == 2 &&
- f != &bp->floaters[0] &&
- (bp->mode == BOUNCE || bp->mode == XEYES))
- {
- /* When there are exactly two eyes, track them together. */
- floater *f0 = &bp->floaters[0];
- double x0, y0, z0;
- get_position (f0->rot, &x0, &y0, &z0, 0);
- x = x0;
- y = 1-y0; /* This is rotation: what the eye is looking at */
- z = z0;
- if (bp->mode != XEYES)
- {
- f->x = f0->x + f0->scale * 3;
- f->y = f0->y;
- f->z = f0->z;
- }
- f->dilation = f0->dilation;
- f->focus = f0->focus;
- f->track = f0->track;
- f->tilt = f0->tilt;
- f->scale = f0->scale;
- f->jaundice = f0->jaundice;
- if (f->focus == ROTATE)
- f->focus = f0->focus = TRACK;
- memcpy (f->color, f0->color, sizeof(f0->color));
- }
-
- glPushMatrix();
- glTranslatef (f->x, f->y, f->z);
-
- /* gltrackball_rotate (bp->trackball); */
-
- switch (f->focus) {
- case ROTATE:
- glRotatef (y * 180, 0, 1, 0);
- glRotatef (f->tilt, 0, 0, 1);
- break;
- case SPIN:
- glRotatef (y * 360 + 90, 0, 1, 0);
- glRotatef (x * 360, 1.0, 0.0, 0.0);
- glRotatef (z * 360, 0.0, 0.0, 1.0);
- break;
- case TRACK:
- {
- GLfloat X, Y, Z;
- X = f->track.x - f->x;
- Y = f->track.z - f->z;
- Z = f->track.y - f->y;
- if (X != 0 || Y != 0)
- {
- GLfloat facing = atan2 (X, Y) * (180 / M_PI);
- GLfloat pitch = atan2 (Z, sqrt(X*X + Y*Y)) * (180 / M_PI);
- glRotatef (90, 0, 1, 0);
- glRotatef (facing, 0, 1, 0);
- glRotatef (-pitch, 0, 0, 1);
- }
- }
-
- break;
- default:
- abort();
- }
-
- glRotatef (f->roll, 1, 0, 0);
- glScalef (f->scale, f->scale, f->scale);
-
- if (! wire)
- glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- switch (which) {
- case RETINA:
- if (!wire)
- {
- glScalef (0.96, 0.96, 0.96);
- glCallList (bp->retina_list);
- }
- break;
-
- case IRIS:
- glColor4fv (f->color);
- if (! wire)
- {
- glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spc);
- glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 10);
-
- glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, f->color);
- glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 20);
-
- glEnable (GL_TEXTURE_2D);
- glBindTexture (GL_TEXTURE_2D, bp->iris_texture);
- glMatrixMode (GL_TEXTURE);
- glLoadIdentity();
- glScalef (1, 1.25 + f->dilation.current * 0.3, 1);
- glMatrixMode (GL_MODELVIEW);
- }
- glScalef (0.96, 0.96, 0.96);
- glCallList (bp->iris_list);
-
- if (! wire)
- {
- glMatrixMode (GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode (GL_MODELVIEW);
- }
- break;
-
- case SCLERA:
- if (! wire)
- {
- GLfloat *c = (f->jaundice == 2 ? c2b : f->jaundice == 1 ? c2c : c2);
- glColor4fv (c);
- glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c);
- glBindTexture (GL_TEXTURE_2D, bp->sclera_texture);
-
- glScalef (0.98, 0.98, 0.98);
- glCallList (bp->sclera_list);
- }
- break;
-
- case LENS:
- glColor4fv (c3);
- if (! wire)
- {
- glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, c3);
- glDisable (GL_TEXTURE_2D);
- }
- glCallList (bp->lens_list);
- break;
-
- default:
- abort();
- break;
- }
-
- glPopMatrix();
-}
-
-
-ENTRYPOINT void
-draw_peepers (ModeInfo *mi)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- Display *dpy = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
-
- if (!bp->glx_context)
- return;
-
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix ();
-
- glRotatef (current_device_rotation(), 0, 0, 1);
-
-
- /* Scale so that screen is 1 high and w/h wide. */
- glScalef (8, 8, 8);
-
- mi->polygon_count = 0;
-
- if (bp->mode == XEYES || bp->mode == BEHOLDER)
- {
- int i;
- track_mouse (mi);
- for (i = 0; i < bp->nfloaters; i++)
- {
- floater *f = &bp->floaters[i];
- f->track = bp->mouse;
- f->focus = TRACK;
- }
- }
-
-# if 0
- {
- /* Draw just one */
- component j;
- floater F;
- reset_floater(mi, &F);
- F.x = F.y = F.z = 0;
- F.dx = F.dy = F.dz = 0;
- F.ddx = F.ddy = F.ddz = 0;
- F.scale = 1;
- F.focus = TRACK;
- F.dilation.current = 0;
- F.track.x = F.track.y = F.track.z = 0;
- F.rot = make_rotator (0, 0, 0, 1, 0, False);
- glRotatef(180,0,1,0);
- glRotatef(15,1,0,0);
- for (j = RETINA; j <= LENS; j++)
- draw_floater (mi, &F, j);
- mi->polygon_count += bp->eye_polys;
- }
-# else
- {
- component j;
- int i;
- for (j = RETINA; j <= TICK; j++)
- for (i = 0; i < bp->nfloaters; i++)
- {
- floater *f = &bp->floaters[i];
- if (j == TICK)
- tick_floater (mi, f);
- else
- draw_floater (mi, f, j);
- }
-
- if (bp->mode != BEHOLDER)
- de_collide (mi);
-
- mi->polygon_count += bp->eye_polys * bp->nfloaters;
- }
-# endif
-
- glPopMatrix ();
-
- if (mi->fps_p) do_fps (mi);
- glFinish();
-
- glXSwapBuffers(dpy, window);
-}
-
-
-ENTRYPOINT void
-free_peepers (ModeInfo *mi)
-{
- peepers_configuration *bp = &bps[MI_SCREEN(mi)];
- int i;
- if (!bp->glx_context) return;
- glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
- for (i = 0; i < bp->nfloaters; i++)
- free_rotator (bp->floaters[i].rot);
- if (bp->floaters) free (bp->floaters);
- if (glIsList(bp->lens_list)) glDeleteLists(bp->lens_list, 1);
- if (glIsList(bp->sclera_list)) glDeleteLists(bp->sclera_list, 1);
- if (glIsList(bp->iris_list)) glDeleteLists(bp->iris_list, 1);
- if (glIsList(bp->retina_list)) glDeleteLists(bp->retina_list, 1);
- if (bp->sclera_texture) glDeleteTextures (1, &bp->sclera_texture);
- if (bp->iris_texture) glDeleteTextures (1, &bp->iris_texture);
-}
-
-XSCREENSAVER_MODULE ("Peepers", peepers)
-
-#endif /* USE_GL */