X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fcubestorm.c;fp=hacks%2Fglx%2Fcubestorm.c;h=cf973c9ae6dd69e3b548351981bc81111a48c66f;hp=4ef7fd1b4c5eb24671be4857ab044eb8377c049f;hb=c85f503f5793839a6be4c818332aca4a96927bb2;hpb=78add6e627ee5f10e1fa6f3852602ea5066eee5a diff --git a/hacks/glx/cubestorm.c b/hacks/glx/cubestorm.c index 4ef7fd1b..cf973c9a 100644 --- a/hacks/glx/cubestorm.c +++ b/hacks/glx/cubestorm.c @@ -1,4 +1,4 @@ -/* cubestorm, Copyright (c) 2003-2014 Jamie Zawinski +/* cubestorm, 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 @@ -35,7 +35,13 @@ #define DEF_SPEED "1.0" #define DEF_THICKNESS "0.06" #define DEF_COUNT "4" -#define DEF_DBUF "False" +#define DEF_LENGTH "200" + +typedef struct { + GLfloat px, py, pz; + GLfloat rx, ry, rz; + int ccolor; +} histcube; typedef struct { rotator *rot; @@ -55,6 +61,9 @@ typedef struct { subcube *subcubes; + int hist_size, hist_count; + histcube *hist; + } cube_configuration; static cube_configuration *bps = NULL; @@ -63,7 +72,7 @@ static Bool do_spin; static Bool do_wander; static GLfloat speed; static GLfloat thickness; -static Bool dbuf_p; +static int max_length; static XrmOptionDescRec opts[] = { { "-spin", ".spin", XrmoptionNoArg, "True" }, @@ -74,14 +83,15 @@ static XrmOptionDescRec opts[] = { { "-db", ".doubleBuffer", XrmoptionNoArg, "True"}, { "+db", ".doubleBuffer", XrmoptionNoArg, "False"}, { "-thickness", ".thickness", XrmoptionSepArg, 0 }, + { "-length", ".length", XrmoptionSepArg, 0 }, }; static argtype vars[] = { {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool}, {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, {&speed, "speed", "Speed", DEF_SPEED, t_Float}, - {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float}, - {&dbuf_p, "doubleBuffer", "DoubleBuffer", DEF_DBUF, t_Bool}, + {&thickness, "thickness", "Thickness", DEF_THICKNESS, t_Float}, + {&max_length, "length", "Length", DEF_LENGTH, t_Int}, }; ENTRYPOINT ModeSpecOpt cube_opts = {countof(opts), opts, countof(vars), vars, NULL}; @@ -235,10 +245,6 @@ init_cube (ModeInfo *mi) MI_INIT (mi, bps); -# ifdef HAVE_JWZGLES - dbuf_p = True; -# endif - bp = &bps[MI_SCREEN(mi)]; bp->glx_context = init_GL(mi); @@ -247,6 +253,11 @@ init_cube (ModeInfo *mi) bp->trackball = gltrackball_init (True); bp->subcubes = (subcube *) calloc (MI_COUNT(mi), sizeof(subcube)); + + bp->hist_count = 0; + bp->hist_size = 100; + bp->hist = (histcube *) malloc (bp->hist_size * sizeof(*bp->hist)); + for (i = 0; i < MI_COUNT(mi); i++) { double wander_speed, spin_speed, spin_accel; @@ -304,6 +315,70 @@ init_cube (ModeInfo *mi) } +/* Originally, this program achieved the "accumulating cubes" effect by + simply not clearing the depth or color buffers between frames. That + doesn't work on modern systems, particularly mobile: you can no longer + rely on your buffers being unmolested once you have yielded. So now we + must save and re-render every polygon. Noof has the same problem and + solves it by taking a screenshot of the frame buffer into a texture, but + cubestorm needs to restore the depth buffer as well as the color buffer. + */ +static void +push_hist (ModeInfo *mi) +{ + cube_configuration *bp = &bps[MI_SCREEN(mi)]; + double px, py, pz; + double rx = 0, ry = 0, rz = 0; + int i; + + if (bp->hist_count > max_length && + bp->hist_count > MI_COUNT(mi) && + !bp->button_down_p) + { + /* Drop history off of the end. */ + memmove (bp->hist, + bp->hist + MI_COUNT(mi), + (bp->hist_count - MI_COUNT(mi)) * sizeof(*bp->hist)); + bp->hist_count -= MI_COUNT(mi); + } + + if (bp->hist_count + MI_COUNT(mi) >= bp->hist_size) + { + bp->hist_size = bp->hist_count + MI_COUNT(mi) + 100; + bp->hist = (histcube *) + realloc (bp->hist, bp->hist_size * sizeof(*bp->hist)); + } + + get_position (bp->subcubes[0].rot, &px, &py, &pz, !bp->button_down_p); + + for (i = 0; i < MI_COUNT(mi); i++) + { + subcube *sc = &bp->subcubes[i]; + histcube *hc = &bp->hist[bp->hist_count]; + double rx2, ry2, rz2; + + get_rotation (sc->rot, &rx2, &ry2, &rz2, !bp->button_down_p); + + if (i == 0) /* N+1 cubes rotate relative to cube 0 */ + rx = rx2, ry = ry2, rz = rz2; + else + rx2 += rx, ry2 += ry, rz2 += rz; + + hc->px = px; + hc->py = py; + hc->pz = pz; + hc->rx = rx2; + hc->ry = ry2; + hc->rz = rz2; + hc->ccolor = sc->ccolor; + sc->ccolor++; + if (sc->ccolor >= bp->ncolors) + sc->ccolor = 0; + bp->hist_count++; + } +} + + ENTRYPOINT void draw_cube (ModeInfo *mi) { @@ -312,14 +387,12 @@ draw_cube (ModeInfo *mi) Window window = MI_WINDOW(mi); int wire = MI_IS_WIREFRAME(mi); int i; - double x, y, z; if (!bp->glx_context) return; - glDrawBuffer(dbuf_p ? GL_BACK : GL_FRONT); - glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glShadeModel(GL_SMOOTH); @@ -329,7 +402,7 @@ draw_cube (ModeInfo *mi) if (bp->clear_p) /* we're in "no vapor trails" mode */ { - glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); + bp->hist_count = 0; if (! (random() % (int) (25 / speed))) bp->clear_p = False; } @@ -342,47 +415,33 @@ draw_cube (ModeInfo *mi) } } - glPushMatrix (); - - glScalef(1.1, 1.1, 1.1); - + push_hist (mi); mi->polygon_count = 0; - - get_position (bp->subcubes[0].rot, &x, &y, &z, !bp->button_down_p); - glTranslatef((x - 0.5) * 15, - (y - 0.5) * 15, - (z - 0.5) * 30); - gltrackball_rotate (bp->trackball); - - glScalef (4.0, 4.0, 4.0); - - for (i = 0; i < MI_COUNT(mi); i++) + for (i = 0; i < bp->hist_count; i++) { GLfloat bcolor[4] = {0.0, 0.0, 0.0, 1.0}; GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; GLfloat bshiny = 128.0; + histcube *hc = &bp->hist[i]; + glPushMatrix(); + glScalef (1.1, 1.1, 1.1); - if (i != 0) /* N+1 cubes rotate relative to cube 0 */ - { - get_rotation (bp->subcubes[0].rot, &x, &y, &z, False); - glRotatef (x * 360, 1.0, 0.0, 0.0); - glRotatef (y * 360, 0.0, 1.0, 0.0); - glRotatef (z * 360, 0.0, 0.0, 1.0); - } + glTranslatef((hc->px - 0.5) * 15, + (hc->py - 0.5) * 15, + (hc->pz - 0.5) * 30); + gltrackball_rotate (bp->trackball); - get_rotation (bp->subcubes[i].rot, &x, &y, &z, !bp->button_down_p); - glRotatef (x * 360, 1.0, 0.0, 0.0); - glRotatef (y * 360, 0.0, 1.0, 0.0); - glRotatef (z * 360, 0.0, 0.0, 1.0); + glScalef (4.0, 4.0, 4.0); - bcolor[0] = bp->colors[bp->subcubes[i].ccolor].red / 65536.0; - bcolor[1] = bp->colors[bp->subcubes[i].ccolor].green / 65536.0; - bcolor[2] = bp->colors[bp->subcubes[i].ccolor].blue / 65536.0; - bp->subcubes[i].ccolor++; - if (bp->subcubes[i].ccolor >= bp->ncolors) - bp->subcubes[i].ccolor = 0; + glRotatef (hc->rx * 360, 1.0, 0.0, 0.0); + glRotatef (hc->ry * 360, 0.0, 1.0, 0.0); + glRotatef (hc->rz * 360, 0.0, 0.0, 1.0); + + bcolor[0] = bp->colors[hc->ccolor].red / 65536.0; + bcolor[1] = bp->colors[hc->ccolor].green / 65536.0; + bcolor[2] = bp->colors[hc->ccolor].blue / 65536.0; if (wire) glColor3f (bcolor[0], bcolor[1], bcolor[2]); @@ -399,13 +458,10 @@ draw_cube (ModeInfo *mi) glPopMatrix(); } - glPopMatrix (); - if (mi->fps_p) do_fps (mi); glFinish(); - if (dbuf_p) - glXSwapBuffers(dpy, window); + glXSwapBuffers(dpy, window); } XSCREENSAVER_MODULE_2 ("CubeStorm", cubestorm, cube)