X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fpolyhedra-gl.c;h=a46453348f6ba7b861ee65f26f7a4a0e1cfdb149;hp=e85559dbe6b8ecf0613aa03345073954a0e16cfb;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hpb=9c9d475ff889ed8be02e8ce8c17da28b93278fca diff --git a/hacks/glx/polyhedra-gl.c b/hacks/glx/polyhedra-gl.c index e85559db..a4645334 100644 --- a/hacks/glx/polyhedra-gl.c +++ b/hacks/glx/polyhedra-gl.c @@ -1,4 +1,4 @@ -/* polyhedra, Copyright (c) 2004 Jamie Zawinski +/* polyhedra, Copyright (c) 2004-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 @@ -13,59 +13,62 @@ * * This file contains the OpenGL side; computation of the polyhedra themselves * is in "polyhedra.c". - * - * KNOWN BUG: - * - * The normals are wrong (inverted) on some faces of some of the duals - * (e.g., "Rhombicosacron".) I can't figure out how to tell when the - * normal should be pointing the other way. */ -#include - -extern XtAppContext app; - -#define PROGCLASS "Polyhedra" -#define HACK_INIT init_polyhedra -#define HACK_DRAW draw_polyhedra -#define HACK_RESHAPE reshape_polyhedra -#define HACK_HANDLE_EVENT polyhedra_handle_event -#define EVENT_MASK PointerMotionMask -#define sws_opts xlockmore_opts - -#define DEF_SPIN "True" -#define DEF_WANDER "True" -#define DEF_SPEED "1.0" -#define DEF_TITLES "True" -#define DEF_DURATION "12" -#define DEF_WHICH "-1" - #define DEFAULTS "*delay: 30000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ - "*speed: " DEF_SPEED "\n" \ - "*spin: " DEF_SPIN "\n" \ - "*wander: " DEF_WANDER "\n" \ - "*duration: " DEF_DURATION "\n" \ - "*which: " DEF_WHICH "\n" \ - "*titleFont: -*-times-bold-r-normal-*-180-*\n" \ - "*titleFont2: -*-times-bold-r-normal-*-120-*\n" \ - "*titleFont3: -*-times-bold-r-normal-*-80-*\n" \ + "*titleFont: -*-helvetica-medium-r-normal-*-*-140-*-*-*-*-*-*\n" \ + "*titleFont2: -*-helvetica-medium-r-normal-*-*-100-*-*-*-*-*-*\n" \ + "*titleFont3: -*-helvetica-medium-r-normal-*-*-80-*-*-*-*-*-*\n" \ + "*suppressRotationAnimation: True\n" \ +# define refresh_polyhedra 0 +# define release_polyhedra 0 #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) #include "xlockmore.h" + +#ifdef HAVE_JWXYZ +# include "jwxyz.h" +#else +# include +# include +# include +#endif + +#ifdef HAVE_JWZGLES +# include "jwzgles.h" +#endif /* HAVE_JWZGLES */ + +#define DEF_SPIN "True" +#define DEF_WANDER "True" +#define DEF_SPEED "1.0" +#define DEF_TITLES "True" +#define DEF_DURATION "12" +#define DEF_WHICH "random" + +#include "texfont.h" +#include "normals.h" #include "polyhedra.h" #include "colors.h" #include "rotator.h" #include "gltrackball.h" -#include +#include "teapot.h" -#ifdef USE_GL /* whole file */ +#ifndef HAVE_JWXYZ +# define XK_MISCELLANY +# include +#endif + +#ifndef HAVE_JWZGLES +# define HAVE_TESS +#endif -#include + +#ifdef USE_GL /* whole file */ typedef struct { GLXContext *glx_context; @@ -79,7 +82,6 @@ typedef struct { int which; int change_to; GLuint object_list; - GLuint title_list; int mode; /* 0 = normal, 1 = out, 2 = in */ int mode_tick; @@ -87,8 +89,10 @@ typedef struct { int ncolors; XColor *colors; - XFontStruct *xfont1, *xfont2, *xfont3; - GLuint font1_dlist, font2_dlist, font3_dlist; + texture_font_data *font1_data, *font2_data, *font3_data; + + time_t last_change_time; + int change_tick; } polyhedra_configuration; @@ -123,111 +127,43 @@ static argtype vars[] = { {&do_which_str,"which", "Which", DEF_WHICH, t_String}, }; -ModeSpecOpt sws_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt polyhedra_opts = {countof(opts), opts, countof(vars), vars, NULL}; -typedef struct { - double x,y,z; -} XYZ; - -static void -normalize (XYZ *p) -{ - double length; - length = sqrt (p->x * p->x + - p->y * p->y + - p->z * p->z); - if (length != 0) - { - p->x /= length; - p->y /= length; - p->z /= length; - } - else - { - p->x = 0; - p->y = 0; - p->z = 0; - } -} - -/* Calculate the unit normal at p given two other points p1,p2 on the - surface. The normal points in the direction of p1 crossproduct p2 +/* Calculate the normals at each vertex of a face, and use the sum to + decide which normal to assign to the entire face. This also solves + problems caused by nonconvex faces, in most (but not all) cases. */ -static XYZ -calc_normal (XYZ p, XYZ p1, XYZ p2) -{ - XYZ n, pa, pb; - pa.x = p1.x - p.x; - pa.y = p1.y - p.y; - pa.z = p1.z - p.z; - pb.x = p2.x - p.x; - pb.y = p2.y - p.y; - pb.z = p2.z - p.z; - n.x = pa.y * pb.z - pa.z * pb.y; - n.y = pa.z * pb.x - pa.x * pb.z; - n.z = pa.x * pb.y - pa.y * pb.x; - normalize (&n); - return (n); -} - - static void -do_normal(GLfloat x1, GLfloat y1, GLfloat z1, - GLfloat x2, GLfloat y2, GLfloat z2, - GLfloat x3, GLfloat y3, GLfloat z3) +kludge_normal (int n, const int *indices, const point *points) { - XYZ p1, p2, p3, p; - p1.x = x1; p1.y = y1; p1.z = z1; - p2.x = x2; p2.y = y2; p2.z = z2; - p3.x = x3; p3.y = y3; p3.z = z3; + XYZ normal = { 0, 0, 0 }; + XYZ p = { 0, 0, 0 }; + int i; - p = calc_normal (p1, p2, p3); + for (i = 0; i < n; ++i) { + int i1 = indices[i]; + int i2 = indices[(i + 1) % n]; + int i3 = indices[(i + 2) % n]; + XYZ p1, p2, p3; - glNormal3f (p.x, p.y, p.z); + p1.x = points[i1].x; p1.y = points[i1].y; p1.z = points[i1].z; + p2.x = points[i2].x; p2.y = points[i2].y; p2.z = points[i2].z; + p3.x = points[i3].x; p3.y = points[i3].y; p3.z = points[i3].z; -#ifdef DEBUG - /* Draw a line in the direction of this face's normal. */ - { - glPushMatrix(); - glTranslatef ((x1 + x2 + x3) / 3, - (y1 + y2 + y3) / 3, - (z1 + z2 + z3) / 3); - glScalef (0.5, 0.5, 0.5); - glBegin(GL_LINE_LOOP); - glVertex3f(0, 0, 0); - glVertex3f(p.x, p.y, p.z); - glEnd(); - glPopMatrix(); + p = calc_normal (p1, p2, p3); + normal.x += p.x; + normal.y += p.y; + normal.z += p.z; } -#endif /* DEBUG */ -} -static void -load_font (ModeInfo *mi, char *res, XFontStruct **fontP, GLuint *dlistP) -{ - const char *font = get_string_resource (res, "Font"); - XFontStruct *f; - Font id; - int first, last; - - if (!font) font = "-*-times-bold-r-normal-*-180-*"; - - f = XLoadQueryFont(mi->dpy, font); - if (!f) f = XLoadQueryFont(mi->dpy, "fixed"); - - id = f->fid; - first = f->min_char_or_byte2; - last = f->max_char_or_byte2; - - clear_gl_error (); - *dlistP = glGenLists ((GLuint) last+1); - check_gl_error ("glGenLists"); - glXUseXFont(id, first, last-first+1, *dlistP + first); - check_gl_error ("glXUseXFont"); - - *fontP = f; + /*normalize(&normal);*/ + if (normal.x == 0 && normal.y == 0 && normal.z == 0) { + glNormal3f (p.x, p.y, p.z); + } else { + glNormal3f (normal.x, normal.y, normal.z); + } } @@ -235,116 +171,24 @@ static void load_fonts (ModeInfo *mi) { polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; - load_font (mi, "titleFont", &bp->xfont1, &bp->font1_dlist); - load_font (mi, "titleFont2", &bp->xfont2, &bp->font2_dlist); - load_font (mi, "titleFont3", &bp->xfont3, &bp->font3_dlist); + bp->font1_data = load_texture_font (mi->dpy, "titleFont"); + bp->font2_data = load_texture_font (mi->dpy, "titleFont2"); + bp->font3_data = load_texture_font (mi->dpy, "titleFont3"); } -static int -string_width (XFontStruct *f, const char *c) -{ - int w = 0; - while (*c) - { - int cc = *((unsigned char *) c); - w += (f->per_char - ? f->per_char[cc-f->min_char_or_byte2].rbearing - : f->min_bounds.rbearing); - c++; - } - return w; -} - -static void -print_title_string (ModeInfo *mi, const char *string, - GLfloat x, GLfloat y, - XFontStruct *font, int font_dlist) -{ - GLfloat line_height = font->ascent + font->descent; - GLfloat sub_shift = (line_height * 0.3); - int cw = string_width (font, "m"); - int tabs = cw * 7; - - y -= line_height; - - glPushAttrib (GL_TRANSFORM_BIT | /* for matrix contents */ - GL_ENABLE_BIT); /* for various glDisable calls */ - glDisable (GL_LIGHTING); - glDisable (GL_DEPTH_TEST); - { - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - { - glLoadIdentity(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - { - int i; - int x2 = x; - Bool sub_p = False; - glLoadIdentity(); - - gluOrtho2D (0, mi->xgwa.width, 0, mi->xgwa.height); - - glColor3f (0.8, 0.8, 0); - - glRasterPos2f (x, y); - for (i = 0; i < strlen(string); i++) - { - char c = string[i]; - if (c == '\n') - { - glRasterPos2f (x, (y -= line_height)); - x2 = x; - } - else if (c == '\t') - { - x2 -= x; - x2 = ((x2 + tabs) / tabs) * tabs; /* tab to tab stop */ - x2 += x; - glRasterPos2f (x2, y); - } - else if (c == '[' && (isdigit (string[i+1]))) - { - sub_p = True; - glRasterPos2f (x2, (y -= sub_shift)); - } - else if (c == ']' && sub_p) - { - sub_p = False; - glRasterPos2f (x2, (y += sub_shift)); - } - else - { - glCallList (font_dlist + (int)(c)); - x2 += (font->per_char - ? font->per_char[c - font->min_char_or_byte2].width - : font->min_bounds.width); - } - } - } - glPopMatrix(); - } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - } - glPopAttrib(); - - glMatrixMode(GL_MODELVIEW); -} - static void startup_blurb (ModeInfo *mi) { polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; const char *s = "Computing polyhedra..."; - print_title_string (mi, s, - mi->xgwa.width - (string_width (bp->xfont1, s) + 40), - 10 + bp->xfont1->ascent + bp->xfont1->descent, - bp->xfont1, bp->font1_dlist); + texture_font_data *f = bp->font1_data; + + glColor3f (0.8, 0.8, 0); + print_texture_label (mi->dpy, f, + mi->xgwa.width, mi->xgwa.height, + 0, s); glFinish(); glXSwapBuffers(MI_DISPLAY(mi), MI_WINDOW(mi)); } @@ -353,9 +197,7 @@ startup_blurb (ModeInfo *mi) /* Window management, etc */ -static void new_label (ModeInfo *mi); - -void +ENTRYPOINT void reshape_polyhedra (ModeInfo *mi, int width, int height) { GLfloat h = (GLfloat) height / (GLfloat) width; @@ -373,32 +215,18 @@ reshape_polyhedra (ModeInfo *mi, int width, int height) 0.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); - - /* need to re-render the text when the window size changes */ - new_label (mi); } -Bool +ENTRYPOINT Bool polyhedra_handle_event (ModeInfo *mi, XEvent *event) { polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; - if (event->xany.type == ButtonPress && - event->xbutton.button & Button1) - { - bp->button_down_p = True; - gltrackball_start (bp->trackball, - event->xbutton.x, event->xbutton.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); - return True; - } - else if (event->xany.type == ButtonRelease && - event->xbutton.button & Button1) - { - bp->button_down_p = False; - return True; - } + if (gltrackball_event_handler (event, bp->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &bp->button_down_p)) + return True; else if (event->xany.type == KeyPress) { KeySym keysym; @@ -408,21 +236,23 @@ polyhedra_handle_event (ModeInfo *mi, XEvent *event) bp->change_to = -1; if (c == ' ' || c == '\t' || c == '\r' || c == '\n') bp->change_to = random() % bp->npolyhedra; - else if (c == '>' || c == '.' || c == '+' || c == '=') + else if (c == '>' || c == '.' || c == '+' || c == '=' || + keysym == XK_Right || keysym == XK_Up || keysym == XK_Next) bp->change_to = (bp->which + 1) % bp->npolyhedra; else if (c == '<' || c == ',' || c == '-' || c == '_' || - c == '\010' || c == '\177') + c == '\010' || c == '\177' || + keysym == XK_Left || keysym == XK_Down || keysym == XK_Prior) bp->change_to = (bp->which + bp->npolyhedra - 1) % bp->npolyhedra; + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) + goto DEF; if (bp->change_to != -1) return True; } - else if (event->xany.type == MotionNotify && - bp->button_down_p) + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) { - gltrackball_track (bp->trackball, - event->xmotion.x, event->xmotion.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); + DEF: + bp->change_to = random() % bp->npolyhedra; return True; } @@ -431,54 +261,62 @@ polyhedra_handle_event (ModeInfo *mi, XEvent *event) static void -new_label (ModeInfo *mi) +draw_label (ModeInfo *mi) { polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; polyhedron *p = bp->which >= 0 ? bp->polyhedra[bp->which] : 0; + char label[1024]; + char name2[255]; + GLfloat color[4] = { 0.8, 0.8, 0.8, 1 }; + texture_font_data *f; + + if (!p || !do_titles) return; + + strcpy (name2, p->name); + if (*p->class) + sprintf (name2 + strlen(name2), " (%s)", p->class); + + sprintf (label, + "Polyhedron %d: \t%s\n\n" + "Wythoff Symbol:\t%s\n" + "Vertex Configuration:\t%s\n" + "Symmetry Group:\t%s\n" + /* "Dual of: \t%s\n" */ + "\n" + "Faces:\t %d\n" + "Edges:\t %d\n" + "Vertices:\t %d\n" + "Density:\t %d\n" + "Euler:\t%s%d\n", + bp->which, name2, p->wythoff, p->config, p->group, + /* p->dual, */ + p->logical_faces, p->nedges, p->logical_vertices, + p->density, (p->chi < 0 ? "" : " "), p->chi); + + if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375) + f = bp->font1_data; + else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260) + f = bp->font2_data; /* small font */ + else + f = bp->font3_data; /* tiny font */ - glNewList (bp->title_list, GL_COMPILE); - if (p && do_titles) - { - char label[1024]; - char name2[255]; - strcpy (name2, p->name); - if (*p->class) - sprintf (name2 + strlen(name2), " (%s)", p->class); - - sprintf (label, - "Polyhedron %d: \t%s\n\n" - "Wythoff Symbol:\t%s\n" - "Vertex Configuration:\t%s\n" - "Symmetry Group:\t%s\n" - /* "Dual of: \t%s\n" */ - "\n" - "Faces:\t %d\n" - "Edges:\t %d\n" - "Vertices:\t %d\n" - "Density:\t %d\n" - "Euler:\t%s%d\n", - bp->which, name2, p->wythoff, p->config, p->group, - /* p->dual, */ - p->logical_faces, p->nedges, p->logical_vertices, - p->density, (p->chi < 0 ? "" : " "), p->chi); + glColor4fv (color); + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); + print_texture_label (mi->dpy, f, + mi->xgwa.width, mi->xgwa.height, + 1, label); +} - { - XFontStruct *f; - GLuint fl; - if (MI_WIDTH(mi) >= 500 && MI_HEIGHT(mi) >= 375) - f = bp->xfont1, fl = bp->font1_dlist; /* big font */ - else if (MI_WIDTH(mi) >= 350 && MI_HEIGHT(mi) >= 260) - f = bp->xfont2, fl = bp->font2_dlist; /* small font */ - else - f = bp->xfont3, fl = bp->font3_dlist; /* tiny font */ - print_title_string (mi, label, - 10, mi->xgwa.height - 10, - f, fl); - } - } - glEndList (); +#ifdef HAVE_TESS +static void +tess_error (GLenum errorCode) +{ + fprintf (stderr, "%s: tesselation error: %s\n", + progname, gluErrorString(errorCode)); + abort(); } +#endif /* HAVE_TESS */ static void @@ -487,9 +325,19 @@ new_polyhedron (ModeInfo *mi) polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; polyhedron *p; int wire = MI_IS_WIREFRAME(mi); - static GLfloat bcolor[4] = {0.0, 0.0, 0.0, 1.0}; int i; + /* Use the GLU polygon tesselator so that nonconvex faces are displayed + correctly (e.g., for the "pentagrammic concave deltohedron"). + */ +# ifdef HAVE_TESS + GLUtesselator *tobj = gluNewTess(); + gluTessCallback (tobj, GLU_TESS_BEGIN, (void (*) (void)) &glBegin); + gluTessCallback (tobj, GLU_TESS_END, (void (*) (void)) &glEnd); + gluTessCallback (tobj, GLU_TESS_VERTEX, (void (*) (void)) &glVertex3dv); + gluTessCallback (tobj, GLU_TESS_ERROR, (void (*) (void)) &tess_error); +# endif /* HAVE_TESS */ + mi->polygon_count = 0; bp->ncolors = 128; @@ -507,68 +355,114 @@ new_polyhedron (ModeInfo *mi) bp->change_to = -1; p = bp->polyhedra[bp->which]; - new_label (mi); + if (wire) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glNewList (bp->object_list, GL_COMPILE); - for (i = 0; i < p->nfaces; i++) + if (bp->which == bp->npolyhedra-1) { - int j; - face *f = &p->faces[i]; - - if (f->color > 64 || f->color < 0) abort(); + GLfloat bcolor[4]; + bcolor[0] = bp->colors[0].red / 65536.0; + bcolor[1] = bp->colors[0].green / 65536.0; + bcolor[2] = bp->colors[0].blue / 65536.0; + bcolor[3] = 1.0; if (wire) glColor3f (0, 1, 0); else + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bcolor); + + glScalef (0.8, 0.8, 0.8); + p->nfaces = unit_teapot (6, wire); + p->nedges = p->nfaces * 3 / 2; + p->npoints = p->nfaces * 3; + p->logical_faces = p->nfaces; + p->logical_vertices = p->npoints; + } + else + { + glFrontFace (GL_CCW); + for (i = 0; i < p->nfaces; i++) { - bcolor[0] = bp->colors[f->color].red / 65536.0; - bcolor[1] = bp->colors[f->color].green / 65536.0; - bcolor[2] = bp->colors[f->color].blue / 65536.0; - glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bcolor); - } + int j; + face *f = &p->faces[i]; - do_normal (p->points[f->points[0]].x, - p->points[f->points[0]].y, - p->points[f->points[0]].z, - p->points[f->points[1]].x, - p->points[f->points[1]].y, - p->points[f->points[1]].z, - p->points[f->points[2]].x, - p->points[f->points[2]].y, - p->points[f->points[2]].z); - - glBegin (wire ? GL_LINE_LOOP : - f->npoints == 3 ? GL_TRIANGLES : - f->npoints == 4 ? GL_QUADS : - GL_POLYGON); - for (j = 0; j < f->npoints; j++) - { - point *pp = &p->points[f->points[j]]; - glVertex3f (pp->x, pp->y, pp->z); + if (f->color > 64 || f->color < 0) abort(); + if (wire) + glColor3f (0, 1, 0); + else + { + GLfloat bcolor[4]; + bcolor[0] = bp->colors[f->color].red / 65536.0; + bcolor[1] = bp->colors[f->color].green / 65536.0; + bcolor[2] = bp->colors[f->color].blue / 65536.0; + bcolor[3] = 1.0; + glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, bcolor); + } + + kludge_normal (f->npoints, f->points, p->points); + +# ifdef HAVE_TESS + gluTessBeginPolygon (tobj, 0); + gluTessBeginContour (tobj); + for (j = 0; j < f->npoints; j++) + { + point *pp = &p->points[f->points[j]]; + gluTessVertex (tobj, &pp->x, &pp->x); + } + gluTessEndContour (tobj); + gluTessEndPolygon (tobj); +# else /* !HAVE_TESS */ + glBegin (wire ? GL_LINE_LOOP : + f->npoints == 3 ? GL_TRIANGLES : + f->npoints == 4 ? GL_QUADS : + GL_POLYGON); + for (j = 0; j < f->npoints; j++) + { + point *pp = &p->points[f->points[j]]; + glVertex3f (pp->x, pp->y, pp->z); + } + glEnd(); +# endif /* !HAVE_TESS */ } - glEnd(); } glEndList (); mi->polygon_count += p->nfaces; +# ifdef HAVE_TESS + gluDeleteTess (tobj); +# endif } -void +static void +construct_teapot (ModeInfo *mi) +{ + polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; + int n = bp->npolyhedra-1; + polyhedron *p = (polyhedron *) calloc (1, sizeof(*p)); + p->number = n; + p->wythoff = strdup("X00398|1984"); + p->name = strdup("Teapot"); + p->dual = strdup(""); + p->config = strdup("Melitta"); + p->group = strdup("Teapotahedral (Newell[1975])"); + p->class = strdup("Utah Teapotahedron"); + bp->polyhedra[n] = p; +} + + +ENTRYPOINT void init_polyhedra (ModeInfo *mi) { polyhedra_configuration *bp; int wire = MI_IS_WIREFRAME(mi); - if (!bps) { - bps = (polyhedra_configuration *) - calloc (MI_NUM_SCREENS(mi), sizeof (polyhedra_configuration)); - if (!bps) { - fprintf(stderr, "%s: out of memory\n", progname); - exit(1); - } +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + MI_IS_WIREFRAME(mi) = 0; + wire = 0; +# endif - bp = &bps[MI_SCREEN(mi)]; - } + MI_INIT (mi, bps, NULL); bp = &bps[MI_SCREEN(mi)]; @@ -578,8 +472,6 @@ init_polyhedra (ModeInfo *mi) load_fonts (mi); startup_blurb (mi); - reshape_polyhedra (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - if (!wire) { GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; @@ -592,6 +484,11 @@ init_polyhedra (ModeInfo *mi) glEnable(GL_DEPTH_TEST); /* glEnable(GL_CULL_FACE); */ + /* We need two-sided lighting for polyhedra where both sides of + a face are simultaneously visible (e.g., the "X-hemi-Y-hedrons".) + */ + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glLightfv(GL_LIGHT0, GL_POSITION, pos); glLightfv(GL_LIGHT0, GL_AMBIENT, amb); glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); @@ -609,21 +506,30 @@ init_polyhedra (ModeInfo *mi) spin_accel, do_wander ? wander_speed : 0, True); - bp->trackball = gltrackball_init (); + bp->trackball = gltrackball_init (True); } bp->npolyhedra = construct_polyhedra (&bp->polyhedra); + construct_teapot (mi); bp->object_list = glGenLists (1); - bp->title_list = glGenLists (1); bp->change_to = -1; { int x; char c; do_which = -1; - if (1 == sscanf (do_which_str, " %d %c", &x, &c)) - do_which = x; + if (!strcasecmp (do_which_str, "random")) + ; + else if (1 == sscanf (do_which_str, " %d %c", &x, &c)) + { + if (x >= 0 && x < bp->npolyhedra) + do_which = x; + else + fprintf (stderr, + "%s: polyhedron %d does not exist: there are only %d.\n", + progname, x, bp->npolyhedra-1); + } else if (*do_which_str) { char *s; @@ -632,6 +538,7 @@ init_polyhedra (ModeInfo *mi) for (x = 0; x < bp->npolyhedra; x++) if (!strcasecmp (do_which_str, bp->polyhedra[x]->name) || + !strcasecmp (do_which_str, bp->polyhedra[x]->class) || !strcasecmp (do_which_str, bp->polyhedra[x]->wythoff) || !strcasecmp (do_which_str, bp->polyhedra[x]->config)) { @@ -648,42 +555,43 @@ init_polyhedra (ModeInfo *mi) } new_polyhedron (mi); + reshape_polyhedra (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ + } -void +ENTRYPOINT void draw_polyhedra (ModeInfo *mi) { polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; Display *dpy = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); - static time_t last_time = 0; - - static GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; - static GLfloat bshiny = 128.0; + static const GLfloat bspec[4] = {1.0, 1.0, 1.0, 1.0}; + GLfloat bshiny = 128.0; if (!bp->glx_context) return; + glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(bp->glx_context)); + if (bp->mode == 0 && do_which >= 0 && bp->change_to < 0) ; else if (bp->mode == 0) { - static int tick = 0; - if (bp->change_to >= 0) - tick = 999, last_time = 1; - if (tick++ > 10) + bp->change_tick = 999, bp->last_change_time = 1; + if (bp->change_tick++ > 10) { time_t now = time((time_t *) 0); - if (last_time == 0) last_time = now; - tick = 0; - if (!bp->button_down_p && now - last_time >= duration) + if (bp->last_change_time == 0) bp->last_change_time = now; + bp->change_tick = 0; + if (!bp->button_down_p && now - bp->last_change_time >= duration) { bp->mode = 1; /* go out */ - bp->mode_tick = 20 * speed; - last_time = now; + bp->mode_tick = 20 / speed; + bp->last_change_time = now; } } } @@ -692,7 +600,7 @@ draw_polyhedra (ModeInfo *mi) if (--bp->mode_tick <= 0) { new_polyhedron (mi); - bp->mode_tick = 20 * speed; + bp->mode_tick = 20 / speed; bp->mode = 2; /* go in */ } } @@ -711,6 +619,15 @@ draw_polyhedra (ModeInfo *mi) 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); + } +# endif + glScalef(1.1, 1.1, 1.1); { @@ -736,15 +653,15 @@ draw_polyhedra (ModeInfo *mi) if (bp->mode != 0) { GLfloat s = (bp->mode == 1 - ? bp->mode_tick / (20 * speed) - : ((20 * speed) - bp->mode_tick + 1) / (20 * speed)); + ? bp->mode_tick / (20 / speed) + : ((20 / speed) - bp->mode_tick + 1) / (20 / speed)); glScalef (s, s, s); } glScalef (2, 2, 2); glCallList (bp->object_list); if (bp->mode == 0 && !bp->button_down_p) - glCallList (bp->title_list); + draw_label (mi); /* print_texture_font can't go inside a display list */ glPopMatrix (); @@ -754,4 +671,6 @@ draw_polyhedra (ModeInfo *mi) glXSwapBuffers(dpy, window); } +XSCREENSAVER_MODULE ("Polyhedra", polyhedra) + #endif /* USE_GL */