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/bouncingcow.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 519 insertions(+) create mode 100644 hacks/glx/bouncingcow.c (limited to 'hacks/glx/bouncingcow.c') diff --git a/hacks/glx/bouncingcow.c b/hacks/glx/bouncingcow.c new file mode 100644 index 0000000..6f9b45d --- /dev/null +++ b/hacks/glx/bouncingcow.c @@ -0,0 +1,519 @@ +/* bouncingcow, Copyright (c) 2003-2018 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. + * + * Boing, boing, boing. Cow, cow, cow. + */ + +#define DEFAULTS "*delay: 30000 \n" \ + "*count: 1 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ + +# define free_cow 0 +# define release_cow 0 +#define DEF_SPEED "1.0" +#define DEF_TEXTURE "(none)" + +#undef countof +#define countof(x) (sizeof((x))/sizeof((*x))) + +#undef BELLRAND +#define BELLRAND(n) ((frand((n)) + frand((n)) + frand((n))) / 3) +#undef RANDSIGN +#define RANDSIGN() ((random() & 1) ? 1 : -1) + +#include "xlockmore.h" +#include "rotator.h" +#include "gltrackball.h" +#include "ximage-loader.h" +#include + +#ifdef USE_GL /* whole file */ + +#include "gllist.h" + +extern struct gllist + *cow_face, *cow_hide, *cow_hoofs, *cow_horns, *cow_tail, *cow_udder; + +static struct gllist **all_objs[] = { + &cow_face, &cow_hide, &cow_hoofs, &cow_horns, &cow_tail, &cow_udder +}; + +#define FACE 0 +#define HIDE 1 +#define HOOFS 2 +#define HORNS 3 +#define TAIL 4 +#define UDDER 5 + +typedef struct { + GLfloat x, y, z; + GLfloat ix, iy, iz; + GLfloat dx, dy, dz; + GLfloat ddx, ddy, ddz; + rotator *rot; + Bool spinner_p; +} floater; + +typedef struct { + GLXContext *glx_context; + trackball_state *trackball; + Bool button_down_p; + + GLuint *dlists; + GLuint texture; + + int nfloaters; + floater *floaters; + +} cow_configuration; + +static cow_configuration *bps = NULL; + +static GLfloat speed; +static const char *do_texture; + +static XrmOptionDescRec opts[] = { + { "-speed", ".speed", XrmoptionSepArg, 0 }, + {"-texture", ".texture", XrmoptionSepArg, 0 }, + {"+texture", ".texture", XrmoptionNoArg, "(none)" }, +}; + +static argtype vars[] = { + {&speed, "speed", "Speed", DEF_SPEED, t_Float}, + {&do_texture, "texture", "Texture", DEF_TEXTURE, t_String}, +}; + +ENTRYPOINT ModeSpecOpt cow_opts = {countof(opts), opts, countof(vars), vars, NULL}; + + +#define BOTTOM 28.0 + +static void +reset_floater (ModeInfo *mi, floater *f) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + + f->y = -BOTTOM; + f->x = f->ix; + f->z = f->iz; + + /* 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 = 5.0; + f->dx = 0; + f->dz = 0; + + /* -0.18 max -0.3 top -0.4 middle -0.6 bottom */ + f->ddy = speed * (-0.6 + BELLRAND(0.45)); + f->ddx = 0; + f->ddz = 0; + + f->spinner_p = !(random() % (12 * bp->nfloaters)); + + if (! (random() % (30 * bp->nfloaters))) + { + f->dx = BELLRAND(1.8) * RANDSIGN(); + f->dz = BELLRAND(1.8) * RANDSIGN(); + } +} + + +static void +tick_floater (ModeInfo *mi, floater *f) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + + if (bp->button_down_p) return; + + f->dx += f->ddx; + f->dy += f->ddy; + f->dz += f->ddz; + + f->x += f->dx * speed; + f->y += f->dy * speed; + f->z += f->dz * speed; + + if (f->y < -BOTTOM || + f->x < -BOTTOM*8 || f->x > BOTTOM*8 || + f->z < -BOTTOM*8 || f->z > BOTTOM*8) + reset_floater (mi, f); +} + + +/* Window management, etc + */ +ENTRYPOINT void +reshape_cow (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 (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); +} + + +ENTRYPOINT Bool +cow_handle_event (ModeInfo *mi, XEvent *event) +{ + cow_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; +} + + +/* Textures + */ + +static Bool +load_texture (ModeInfo *mi, const char *filename) +{ + Display *dpy = mi->dpy; + Visual *visual = mi->xgwa.visual; + char buf[1024]; + XImage *image; + + if (MI_IS_WIREFRAME(mi)) + return False; + + if (!filename || + !*filename || + !strcasecmp (filename, "(none)")) + { + glDisable (GL_TEXTURE_2D); + return False; + } + + image = file_to_ximage (dpy, visual, filename); + if (!image) return False; + + clear_gl_error(); + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, + image->width, image->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image->data); + sprintf (buf, "texture: %.100s (%dx%d)", + filename, image->width, image->height); + check_gl_error(buf); + + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + glPixelStorei (GL_UNPACK_ROW_LENGTH, image->width); + + return True; +} + + +ENTRYPOINT void +init_cow (ModeInfo *mi) +{ + cow_configuration *bp; + int wire = MI_IS_WIREFRAME(mi); + int i; + Bool tex_p = False; + + MI_INIT (mi, bps); + + bp = &bps[MI_SCREEN(mi)]; + + bp->glx_context = init_GL(mi); + + reshape_cow (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + + glShadeModel(GL_SMOOTH); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glEnable(GL_CULL_FACE); + + if (!wire) + { + GLfloat pos[4] = {0.4, 0.2, 0.4, 0.0}; +/* GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0};*/ + GLfloat amb[4] = {0.2, 0.2, 0.2, 1.0}; + GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat spc[4] = {1.0, 1.0, 1.0, 1.0}; + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); + glLightfv(GL_LIGHT0, GL_SPECULAR, spc); + } + + bp->trackball = gltrackball_init (False); + + bp->dlists = (GLuint *) calloc (countof(all_objs)+1, sizeof(GLuint)); + for (i = 0; i < countof(all_objs); i++) + bp->dlists[i] = glGenLists (1); + + tex_p = load_texture (mi, do_texture); + if (tex_p) + glBindTexture (GL_TEXTURE_2D, bp->texture); + + for (i = 0; i < countof(all_objs); i++) + { + GLfloat black[4] = {0, 0, 0, 1}; + const struct gllist *gll = *all_objs[i]; + + glNewList (bp->dlists[i], GL_COMPILE); + + glDisable (GL_TEXTURE_2D); + + if (i == HIDE) + { + GLfloat color[4] = {0.63, 0.43, 0.36, 1.00}; + if (tex_p) + { + /* if we have a texture, make the base color be white. */ + color[0] = color[1] = color[2] = 1.0; + + glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_2D); + + /* approximately line it up with ../images/earth.png */ + glMatrixMode (GL_TEXTURE); + glLoadIdentity(); + glTranslatef (0.45, 0.58, 0); + glScalef (0.08, 0.16, 1); + glRotatef (-5, 0, 0, 1); + glMatrixMode (GL_MODELVIEW); + } + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128); + } + else if (i == TAIL) + { + GLfloat color[4] = {0.63, 0.43, 0.36, 1.00}; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128); + } + else if (i == UDDER) + { + GLfloat color[4] = {1.00, 0.53, 0.53, 1.00}; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, black); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128); + } + else if (i == HOOFS || i == HORNS) + { + GLfloat color[4] = {0.20, 0.20, 0.20, 1.00}; + GLfloat spec[4] = {0.30, 0.30, 0.30, 1.00}; + GLfloat shiny = 8.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else if (i == FACE) + { + GLfloat color[4] = {0.10, 0.10, 0.10, 1.00}; + GLfloat spec[4] = {0.10, 0.10, 0.10, 1.00}; + GLfloat shiny = 8.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + else + { + GLfloat color[4] = {1.00, 1.00, 1.00, 1.00}; + GLfloat spec[4] = {1.00, 1.00, 1.00, 1.00}; + GLfloat shiny = 128.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec); + glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, shiny); + } + + renderList (gll, wire); + + glEndList (); + } + + bp->nfloaters = MI_COUNT (mi); + bp->floaters = (floater *) calloc (bp->nfloaters, sizeof (floater)); + + for (i = 0; i < bp->nfloaters; i++) + { + floater *f = &bp->floaters[i]; + f->rot = make_rotator (10.0, 0, 0, + 4, 0.05 * speed, + True); + if (bp->nfloaters == 2) + { + f->x = (i ? 6 : -6); + } + else if (i != 0) + { + double th = (i - 1) * M_PI*2 / (bp->nfloaters-1); + double r = 10; + f->x = r * cos(th); + f->z = r * sin(th); + } + + f->ix = f->x; + f->iy = f->y; + f->iz = f->z; + reset_floater (mi, f); + } +} + + +static void +draw_floater (ModeInfo *mi, floater *f) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + GLfloat n; + double x, y, z; + + get_position (f->rot, &x, &y, &z, !bp->button_down_p); + + glPushMatrix(); + glTranslatef (f->x, f->y, f->z); + + gltrackball_rotate (bp->trackball); + + glRotatef (y * 360, 0.0, 1.0, 0.0); + if (f->spinner_p) + { + glRotatef (x * 360, 1.0, 0.0, 0.0); + glRotatef (z * 360, 0.0, 0.0, 1.0); + } + + n = 1.5; + if (bp->nfloaters > 99) n *= 0.05; + else if (bp->nfloaters > 25) n *= 0.18; + else if (bp->nfloaters > 9) n *= 0.3; + else if (bp->nfloaters > 1) n *= 0.7; + glScalef(n, n, n); + + glCallList (bp->dlists[FACE]); + mi->polygon_count += (*all_objs[FACE])->points / 3; + + glCallList (bp->dlists[HIDE]); + mi->polygon_count += (*all_objs[HIDE])->points / 3; + + glCallList (bp->dlists[HOOFS]); + mi->polygon_count += (*all_objs[HOOFS])->points / 3; + + glCallList (bp->dlists[HORNS]); + mi->polygon_count += (*all_objs[HORNS])->points / 3; + + glCallList (bp->dlists[TAIL]); + mi->polygon_count += (*all_objs[TAIL])->points / 3; + + glCallList (bp->dlists[UDDER]); + mi->polygon_count += (*all_objs[UDDER])->points / 3; + + glPopMatrix(); +} + + + +ENTRYPOINT void +draw_cow (ModeInfo *mi) +{ + cow_configuration *bp = &bps[MI_SCREEN(mi)]; + Display *dpy = MI_DISPLAY(mi); + Window window = MI_WINDOW(mi); + int i; + + 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 (); + +# 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 + + glScalef (0.5, 0.5, 0.5); + + mi->polygon_count = 0; + +# if 0 + { + floater F; + F.x = F.y = F.z = 0; + F.dx = F.dy = F.dz = 0; + F.ddx = F.ddy = F.ddz = 0; + F.rot = make_rotator (0, 0, 0, 1, 0, False); + glScalef(2,2,2); + draw_floater (mi, &F); + } +# else + for (i = 0; i < bp->nfloaters; i++) + { + /* "Don't kid yourself, Jimmy. If a cow ever got the chance, + he'd eat you and everyone you care about!" + -- Troy McClure in "Meat and You: Partners in Freedom" + */ + floater *f = &bp->floaters[i]; + draw_floater (mi, f); + tick_floater (mi, f); + } +# endif + + glPopMatrix (); + + if (mi->fps_p) do_fps (mi); + glFinish(); + + glXSwapBuffers(dpy, window); +} + +XSCREENSAVER_MODULE_2 ("BouncingCow", bouncingcow, cow) + +#endif /* USE_GL */ -- cgit v1.2.3-55-g7522