From d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 16 Oct 2018 10:08:48 +0200 Subject: Original 5.40 --- hacks/glx/boing.c | 658 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 658 insertions(+) create mode 100644 hacks/glx/boing.c (limited to 'hacks/glx/boing.c') diff --git a/hacks/glx/boing.c b/hacks/glx/boing.c new file mode 100644 index 0000000..55a05f3 --- /dev/null +++ b/hacks/glx/boing.c @@ -0,0 +1,658 @@ +/* boing, Copyright (c) 2005-2014 Jamie Zawinski + * + * 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. + * + * A clone of the Amiga 1000 "Boing" demo. This was the first graphics demo + * for the Amiga, written by Dale Luck and RJ Mical during a break at the 1984 + * Consumer Electronics Show (or so the legend goes.) The boing ball was + * briefly the official logo of Amiga Inc., until they were bought by + * Commodore later that year. + * + * With no arguments, this program looks a lot like the original Amiga demo. + * With "-smooth -lighting", it looks... less old. + * + * The amiga version made noise when the ball hit the walls. This version + * does not, obviously. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define free_boing 0 +# define release_boing 0 +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#include "xlockmore.h" +#include "gltrackball.h" +#include + +#ifdef USE_GL /* whole file */ + + +#define DEF_SPIN "True" +#define DEF_LIGHTING "False" +#define DEF_SMOOTH "False" +#define DEF_SCANLINES "True" +#define DEF_SPEED "1.0" +#define DEF_BALL_SIZE "0.5" +#define DEF_ANGLE "15" +#define DEF_MERIDIANS "16" +#define DEF_PARALLELS "8" +#define DEF_TILES "12" +#define DEF_THICKNESS "0.05" + +#define DEF_BALL_COLOR1 "#CC1919" +#define DEF_BALL_COLOR2 "#F2F2F2" +#define DEF_GRID_COLOR "#991999" +#define DEF_SHADOW_COLOR "#303030" +#define DEF_BACKGROUND "#8C8C8C" + +typedef struct { GLfloat x, y, z; } XYZ; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + + GLfloat speed; + + GLuint ball_list; + double ball_x, ball_y, ball_z, ball_th; + double ball_dx, ball_dy, ball_dz, ball_dth; + double ball_ddx, ball_ddy, ball_ddz; + + GLfloat ball_color1[4], ball_color2[4], grid_color[4]; + GLfloat bg_color[4], shadow_color[4]; + GLfloat lightpos[4]; + +} boing_configuration; + +static boing_configuration *bps = NULL; + +static Bool spin; +static Bool lighting_p; +static Bool smooth_p; +static Bool scanlines_p; +static GLfloat speed; +static int angle; +static GLfloat ball_size; +static unsigned int meridians; +static unsigned int parallels; +static unsigned int tiles; +static GLfloat thickness; +static char *ball_color1_str, *ball_color2_str, *grid_color_str, + *shadow_str, *bg_str; + +static XrmOptionDescRec opts[] = { + { "-spin", ".spin", XrmoptionNoArg, "True" }, + { "+spin", ".spin", XrmoptionNoArg, "False" }, + { "-lighting", ".lighting", XrmoptionNoArg, "True" }, + { "+lighting", ".lighting", XrmoptionNoArg, "False" }, + { "-smooth", ".smooth", XrmoptionNoArg, "True" }, + { "+smooth", ".smooth", XrmoptionNoArg, "False" }, + { "-scanlines", ".scanlines", XrmoptionNoArg, "True" }, + { "+scanlines", ".scanlines", XrmoptionNoArg, "False" }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + { "-angle", ".angle", XrmoptionSepArg, 0 }, + { "-size", ".ballSize", XrmoptionSepArg, 0 }, + { "-meridians", ".meridians", XrmoptionSepArg, 0 }, + { "-parallels", ".parallels", XrmoptionSepArg, 0 }, + { "-tiles", ".tiles", XrmoptionSepArg, 0 }, + { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-ball-color1",".ballColor1",XrmoptionSepArg, 0 }, + { "-ball-color2",".ballColor2",XrmoptionSepArg, 0 }, + { "-grid-color", ".gridColor", XrmoptionSepArg, 0 }, + { "-shadow-color",".shadowColor",XrmoptionSepArg, 0 }, + { "-background", ".boingBackground",XrmoptionSepArg, 0 }, + { "-bg", ".boingBackground",XrmoptionSepArg, 0 }, +}; + +static argtype vars[] = { + {&spin, "spin", "Spin", DEF_SPIN, t_Bool}, + {&lighting_p,"lighting", "Lighting", DEF_LIGHTING, t_Bool}, + {&smooth_p, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&scanlines_p,"scanlines","Scanlines", DEF_SCANLINES, t_Bool}, + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&angle, "angle", "Angle", DEF_ANGLE, t_Int}, + {&ball_size, "ballSize", "BallSize", DEF_BALL_SIZE, t_Float}, + {&meridians, "meridians", "meridians", DEF_MERIDIANS, t_Int}, + {¶llels, "parallels", "parallels", DEF_PARALLELS, t_Int}, + {&tiles, "tiles", "Tiles", DEF_TILES, t_Int}, + {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float}, + {&ball_color1_str, "ballColor1", "BallColor1", DEF_BALL_COLOR1, t_String}, + {&ball_color2_str, "ballColor2", "BallColor2", DEF_BALL_COLOR2, t_String}, + {&grid_color_str, "gridColor", "GridColor", DEF_GRID_COLOR, t_String}, + {&shadow_str, "shadowColor","ShadowColor",DEF_SHADOW_COLOR,t_String}, + /* dammit, -background is too magic... */ + {&bg_str, "boingBackground", "Background", DEF_BACKGROUND, t_String}, +}; + +ENTRYPOINT ModeSpecOpt boing_opts = {countof(opts), opts, countof(vars), vars, NULL}; + +static void +parse_color (ModeInfo *mi, const char *name, const char *s, GLfloat *a) +{ + XColor c; + a[3] = 1.0; /* alpha */ + + if (! XParseColor (MI_DISPLAY(mi), MI_COLORMAP(mi), s, &c)) + { + fprintf (stderr, "%s: can't parse %s color %s", progname, name, s); + exit (1); + } + a[0] = c.red / 65536.0; + a[1] = c.green / 65536.0; + a[2] = c.blue / 65536.0; +} + + +static void +draw_grid (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + int x, y; + GLfloat t2 = (GLfloat) tiles / 2; + GLfloat s = 1.0 / (tiles + thickness); + GLfloat z = 0; + + GLfloat lw = MI_HEIGHT(mi) * 0.06 * thickness; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bp->grid_color); + glColor3fv (bp->grid_color); + + glPushMatrix(); + glScalef(s, s, s); + glTranslatef (-t2, -t2, 0); + + glLineWidth (lw); + glBegin (GL_LINES); + for (y = 0; y <= tiles; y++) + { + glVertex3f (0, y, z); + glVertex3f (tiles, y, z); + /*mi->polygon_count++;*/ + } + for (x = 0; x <= tiles; x++) + { + glVertex3f (x, tiles, z); + glVertex3f (x, 0, z); + /*mi->polygon_count++;*/ + } + + glEnd(); + glPopMatrix(); +} + + +static void +draw_box (ModeInfo *mi) +{ + /* boing_configuration *bp = &bps[MI_SCREEN(mi)]; */ + glPushMatrix(); + glTranslatef (0, 0, -0.5); +/* glFrontFace (GL_CCW);*/ + draw_grid (mi); + glPopMatrix(); + + glPushMatrix(); + glRotatef (90, 1, 0, 0); + glTranslatef (0, 0, 0.5); +/* glFrontFace (GL_CW);*/ + draw_grid (mi); + glPopMatrix(); +} + + +static void +draw_ball (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + int x, y; + int xx = meridians; + int yy = parallels; + int scale = (smooth_p ? 5 : 1); + + if (lighting_p && !wire) + glEnable (GL_LIGHTING); + + if (parallels < 3) + scale *= 2; + + xx *= scale; + yy *= scale; + + glFrontFace (GL_CW); + + glPushMatrix(); + glTranslatef (bp->ball_x, bp->ball_y, bp->ball_z); + glScalef (ball_size, ball_size, ball_size); + glRotatef (-angle, 0, 0, 1); + glRotatef (bp->ball_th, 0, 1, 0); + + for (y = 0; y < yy; y++) + { + GLfloat thy0 = y * (M_PI * 2) / (yy * 2) + M_PI_2; + GLfloat thy1 = (y+1) * (M_PI * 2) / (yy * 2) + M_PI_2; + + for (x = 0; x < xx; x++) + { + GLfloat thx0 = x * (M_PI * 2) / xx; + GLfloat thx1 = (x+1) * (M_PI * 2) / xx; + XYZ p; + Bool bgp = ((x/scale) & 1) ^ ((y/scale) & 1); + + if (wire && bgp) continue; + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, + (bgp ? bp->ball_color2 : bp->ball_color1)); + glColor3fv (bgp ? bp->ball_color2 : bp->ball_color1); + + glBegin (wire ? GL_LINE_LOOP : GL_QUADS); + + if (!smooth_p) + { + p.x = cos((thy0+thy1)/2) * cos((thx0+thx1)/2); + p.y = sin((thy0+thy1)/2); + p.z = cos((thy0+thy1)/2) * sin((thx0+thx1)/2); + glNormal3f (-p.x, -p.y, -p.z); + } + + p.x = cos(thy0) * cos(thx0) / 2; + p.y = sin(thy0) / 2; + p.z = cos(thy0) * sin(thx0) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + p.x = cos(thy1) * cos(thx0) / 2; + p.y = sin(thy1) / 2; + p.z = cos(thy1) * sin(thx0) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + p.x = cos(thy1) * cos(thx1) / 2; + p.y = sin(thy1) / 2; + p.z = cos(thy1) * sin(thx1) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + p.x = cos(thy0) * cos(thx1) / 2; + p.y = sin(thy0) / 2; + p.z = cos(thy0) * sin(thx1) / 2; + if (smooth_p) + glNormal3f (-p.x, -p.y, -p.z); + glVertex3f (p.x, p.y, p.z); + + glEnd (); + mi->polygon_count++; + } + } + + glPopMatrix(); + + if (lighting_p && !wire) + glDisable(GL_LIGHTING); +} + + +static void +draw_shadow (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + int wire = MI_IS_WIREFRAME(mi); + GLfloat xoff = 0.14; + GLfloat yoff = 0.07; + int y; + int yy = parallels; + int scale = (smooth_p ? 5 : 1); + + if (lighting_p && !wire) + glEnable (GL_BLEND); + + if (parallels < 3) + scale *= 2; + + yy *= scale; + + glPushMatrix(); + glTranslatef (bp->ball_x + xoff, bp->ball_y + yoff, -0.49); + glScalef (ball_size, ball_size, ball_size); + glRotatef (-angle, 0, 0, 1); + + glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, bp->shadow_color); + glColor4fv (bp->shadow_color); + + glFrontFace (GL_CCW); + glNormal3f (0, 0, 1); + glBegin (wire ? GL_LINE_LOOP : GL_TRIANGLE_FAN); + if (!wire) glVertex3f (0, 0, 0); + + for (y = 0; y < yy*2+1; y++) + { + GLfloat thy0 = y * (M_PI * 2) / (yy * 2) + M_PI_2; + glVertex3f (cos(thy0) / 2, sin(thy0) / 2, 0); + mi->polygon_count++; + } + + glEnd (); + + glPopMatrix(); + + if (lighting_p && !wire) + glDisable (GL_BLEND); +} + + +static void +draw_scanlines (ModeInfo *mi) +{ + /* boing_configuration *bp = &bps[MI_SCREEN(mi)]; */ + int wire = MI_IS_WIREFRAME(mi); + int w = MI_WIDTH(mi); + int h = MI_HEIGHT(mi); + + if (h <= 300) return; + + if (!wire) + { + glEnable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + } + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + { + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + { + int lh, ls; + int y; + glLoadIdentity(); + glOrtho (0, w, 0, h, -1, 1); + + if (h > 500) lh = 4, ls = 4; + else if (h > 300) lh = 2, ls = 1; + else lh = 1, ls = 1; + + if (lh == 1) + glDisable (GL_BLEND); + + glLineWidth (lh); + glColor4f (0, 0, 0, 0.3); + + glBegin(GL_LINES); + for (y = 0; y < h; y += lh + ls) + { + glVertex3f (0, y, 0); + glVertex3f (w, y, 0); + } + glEnd(); + } + glPopMatrix(); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + if (!wire) + { + glDisable (GL_BLEND); + glEnable (GL_DEPTH_TEST); + } +} + + + +static void +tick_physics (ModeInfo *mi) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat s2 = ball_size / 2; + GLfloat max = 0.5 - s2; + GLfloat min = -max; + + bp->ball_th += bp->ball_dth; + while (bp->ball_th > 360) bp->ball_th -= 360; + while (bp->ball_th < 0) bp->ball_th += 360; + + bp->ball_dx += bp->ball_ddx; + bp->ball_x += bp->ball_dx; + if (bp->ball_x < min) bp->ball_x = min, bp->ball_dx = -bp->ball_dx, + bp->ball_dth = -bp->ball_dth, + bp->ball_dx += (frand(bp->speed/2) - bp->speed); + else if (bp->ball_x > max) bp->ball_x = max, bp->ball_dx = -bp->ball_dx, + bp->ball_dth = -bp->ball_dth, + bp->ball_dx += (frand(bp->speed/2) - bp->speed); + + bp->ball_dy += bp->ball_ddy; + bp->ball_y += bp->ball_dy; + if (bp->ball_y < min) bp->ball_y = min, bp->ball_dy = -bp->ball_dy; + else if (bp->ball_y > max) bp->ball_y = max, bp->ball_dy = -bp->ball_dy; + + bp->ball_dz += bp->ball_ddz; + bp->ball_z += bp->ball_dz; + if (bp->ball_z < min) bp->ball_z = min, bp->ball_dz = -bp->ball_dz; + else if (bp->ball_z > max) bp->ball_z = max, bp->ball_dz = -bp->ball_dz; +} + + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_boing (ModeInfo *mi, int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + int y = 0; + + h *= 4.0 / 3.0; /* Back in the caveman days we couldn't even afford + square pixels! */ + + if (width > height * 5) { /* tiny window: show middle */ + height = width * 3/4; + y = -height/2; + h = height / (GLfloat) width; + } + + glViewport (0, y, (GLint) width, (GLint) height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + if (height > width) + { + GLfloat s = width / (GLfloat) height; + glScalef (s, s, s); + } + + gluPerspective (8.0, 1/h, 1.0, 10.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt (0.0, 0.0, 8.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + + glClear(GL_COLOR_BUFFER_BIT); +} + + +ENTRYPOINT Bool +boing_handle_event (ModeInfo *mi, XEvent *event) +{ + boing_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (gltrackball_event_handler (event, bp->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &bp->button_down_p)) + return True; + + return False; +} + + +ENTRYPOINT void +init_boing (ModeInfo *mi) +{ + boing_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + + MI_INIT (mi, bps); + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + if (tiles < 1) tiles = 1; + + if (smooth_p) + { + if (meridians < 1) meridians = 1; + if (parallels < 1) parallels = 1; + } + else + { + if (meridians < 3) meridians = 3; + if (parallels < 2) parallels = 2; + } + + if (meridians > 1 && meridians & 1) meridians++; /* odd numbers look bad */ + + + if (thickness <= 0) thickness = 0.001; + else if (thickness > 1) thickness = 1; + + reshape_boing (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + parse_color (mi, "ballColor1", ball_color1_str, bp->ball_color1); + parse_color (mi, "ballColor2", ball_color2_str, bp->ball_color2); + parse_color (mi, "gridColor", grid_color_str, bp->grid_color); + parse_color (mi, "shadowColor", shadow_str, bp->shadow_color); + parse_color (mi, "background", bg_str, bp->bg_color); + + bp->shadow_color[3] = 0.9; + + glClearColor (bp->bg_color[0], bp->bg_color[1], bp->bg_color[2], 1); + + if (!wire) + { + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + } + + bp->lightpos[0] = 0.5; + bp->lightpos[1] = 0.5; + bp->lightpos[2] = -1; + bp->lightpos[3] = 0; + + if (lighting_p && !wire) + { + GLfloat amb[4] = {0, 0, 0, 1}; + GLfloat dif[4] = {1, 1, 1, 1}; + GLfloat spc[4] = {1, 1, 1, 1}; + glEnable(GL_LIGHT0); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + bp->speed = speed / 800.0; + + bp->ball_dth = (spin ? -bp->speed * 7 * 360 : 0); + + bp->ball_x = 0.5 - ((ball_size/2) + frand(1-ball_size)); + bp->ball_y = 0.2; + bp->ball_dx = bp->speed * 6 + frand(bp->speed); + bp->ball_ddy = -bp->speed; + + bp->ball_dz = bp->speed * 6 + frand(bp->speed); + + bp->trackball = gltrackball_init (False); +} + + +ENTRYPOINT void +draw_boing (ModeInfo *mi) +{ + boing_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)); + + mi->polygon_count = 0; + + glShadeModel(GL_SMOOTH); + + glEnable(GL_NORMALIZE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if (! bp->button_down_p) + tick_physics (mi); + + glPushMatrix (); + + { + double rot = current_device_rotation(); + glRotatef(rot, 0, 0, 1); +/* + if ((rot > 45 && rot < 135) || + (rot < -45 && rot > -135)) + { + GLfloat s = MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi); + glScalef (1/s, s, 1); + } +*/ + } + + gltrackball_rotate (bp->trackball); + + glLightfv (GL_LIGHT0, GL_POSITION, bp->lightpos); + + glDisable (GL_CULL_FACE); + glDisable (GL_DEPTH_TEST); + + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable (GL_BLEND); + + draw_box (mi); + draw_shadow (mi); + + glEnable (GL_CULL_FACE); + glEnable (GL_DEPTH_TEST); + + draw_ball (mi); + if (scanlines_p) + draw_scanlines (mi); + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE ("Boing", boing) + +#endif /* USE_GL */ -- cgit v1.2.3-55-g7522