diff options
Diffstat (limited to 'hacks/glx/polyhedra-gl.c')
| -rw-r--r-- | hacks/glx/polyhedra-gl.c | 686 |
1 files changed, 0 insertions, 686 deletions
diff --git a/hacks/glx/polyhedra-gl.c b/hacks/glx/polyhedra-gl.c deleted file mode 100644 index d433d7a..0000000 --- a/hacks/glx/polyhedra-gl.c +++ /dev/null @@ -1,686 +0,0 @@ -/* polyhedra, Copyright (c) 2004-2014 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. - * - * Renders 160 different 3D solids, and displays some information about each. - * A new solid is chosen every few seconds. - * - * This file contains the OpenGL side; computation of the polyhedra themselves - * is in "polyhedra.c". - */ - -#define DEFAULTS "*delay: 30000 \n" \ - "*showFPS: False \n" \ - "*wireframe: False \n" \ - "*titleFont: sans-serif 14\n" \ - "*titleFont2: sans-serif 10\n" \ - "*titleFont3: sans-serif 8\n" \ - "*suppressRotationAnimation: True\n" \ - - -# define release_polyhedra 0 - -#include "xlockmore.h" -#include "texfont.h" -#include "normals.h" -#include "polyhedra.h" -#include "colors.h" -#include "rotator.h" -#include "gltrackball.h" -#include "teapot.h" - -#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" - -#ifndef HAVE_JWXYZ -# define XK_MISCELLANY -# include <X11/keysymdef.h> -#endif - -#ifndef HAVE_JWZGLES -# define HAVE_TESS -#endif - - -#ifdef USE_GL /* whole file */ - -typedef struct { - GLXContext *glx_context; - rotator *rot; - trackball_state *trackball; - Bool button_down_p; - - int npolyhedra; - polyhedron **polyhedra; - - int which; - int change_to; - GLuint object_list; - - int mode; /* 0 = normal, 1 = out, 2 = in */ - int mode_tick; - - int ncolors; - XColor *colors; - - texture_font_data *font1_data, *font2_data, *font3_data; - - time_t last_change_time; - int change_tick; - -} polyhedra_configuration; - -static polyhedra_configuration *bps = NULL; - -static Bool do_spin; -static GLfloat speed; -static Bool do_wander; -static Bool do_titles; -static int duration; -static int do_which; -static char *do_which_str; - -static XrmOptionDescRec opts[] = { - { "-spin", ".spin", XrmoptionNoArg, "True" }, - { "+spin", ".spin", XrmoptionNoArg, "False" }, - { "-speed", ".speed", XrmoptionSepArg, 0 }, - { "-wander", ".wander", XrmoptionNoArg, "True" }, - { "+wander", ".wander", XrmoptionNoArg, "False" }, - { "-titles", ".titles", XrmoptionNoArg, "True" }, - { "+titles", ".titles", XrmoptionNoArg, "False" }, - { "-duration",".duration",XrmoptionSepArg, 0 }, - { "-which", ".which", XrmoptionSepArg, 0 }, -}; - -static argtype vars[] = { - {&do_spin, "spin", "Spin", DEF_SPIN, t_Bool}, - {&do_wander, "wander", "Wander", DEF_WANDER, t_Bool}, - {&do_titles, "titles", "Titles", DEF_TITLES, t_Bool}, - {&speed, "speed", "Speed", DEF_SPEED, t_Float}, - {&duration,"duration","Duration",DEF_DURATION,t_Int}, - {&do_which_str,"which", "Which", DEF_WHICH, t_String}, -}; - -ENTRYPOINT ModeSpecOpt polyhedra_opts = {countof(opts), opts, countof(vars), vars, NULL}; - - - -/* 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 void -kludge_normal (int n, const int *indices, const point *points) -{ - XYZ normal = { 0, 0, 0 }; - XYZ p = { 0, 0, 0 }; - int i; - - 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; - - 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; - - p = calc_normal (p1, p2, p3); - normal.x += p.x; - normal.y += p.y; - normal.z += p.z; - } - - /*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); - } -} - - -static void -load_fonts (ModeInfo *mi) -{ - polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; - 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 void -startup_blurb (ModeInfo *mi) -{ - polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; - const char *s = "Computing polyhedra..."; - 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)); -} - - - -/* Window management, etc - */ -ENTRYPOINT void -reshape_polyhedra (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.0); - - 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 -polyhedra_handle_event (ModeInfo *mi, XEvent *event) -{ - polyhedra_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; - else if (event->xany.type == KeyPress) - { - KeySym keysym; - char c = 0; - XLookupString (&event->xkey, &c, 1, &keysym, 0); - - bp->change_to = -1; - if (c == ' ' || c == '\t' || c == '\r' || c == '\n') - bp->change_to = random() % bp->npolyhedra; - 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' || - 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 (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) - { - DEF: - bp->change_to = random() % bp->npolyhedra; - return True; - } - - return False; -} - - -static void -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 */ - - 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); -} - - -#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 -new_polyhedron (ModeInfo *mi) -{ - polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; - polyhedron *p; - int wire = MI_IS_WIREFRAME(mi); - 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; - bp->colors = (XColor *) calloc(bp->ncolors, sizeof(XColor)); - make_random_colormap (0, 0, 0, - bp->colors, &bp->ncolors, - True, False, 0, False); - - if (do_which >= bp->npolyhedra) - do_which = -1; - - bp->which = (bp->change_to != -1 ? bp->change_to : - do_which >= 0 ? do_which : - (random() % bp->npolyhedra)); - bp->change_to = -1; - p = bp->polyhedra[bp->which]; - - if (wire) - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - glNewList (bp->object_list, GL_COMPILE); - if (bp->which == bp->npolyhedra-1) - { - 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++) - { - int j; - face *f = &p->faces[i]; - - 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 */ - } - } - glEndList (); - - mi->polygon_count += p->nfaces; -# ifdef HAVE_TESS - gluDeleteTess (tobj); -# endif -} - - -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); - -# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ - MI_IS_WIREFRAME(mi) = 0; - wire = 0; -# endif - - MI_INIT (mi, bps); - - bp = &bps[MI_SCREEN(mi)]; - - bp->glx_context = init_GL(mi); - - bp->which = -1; - load_fonts (mi); - startup_blurb (mi); - - if (!wire) - { - GLfloat pos[4] = {1.0, 1.0, 1.0, 0.0}; - GLfloat amb[4] = {0.0, 0.0, 0.0, 1.0}; - GLfloat dif[4] = {1.0, 1.0, 1.0, 1.0}; - GLfloat spc[4] = {0.0, 1.0, 1.0, 1.0}; - - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - 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); - glLightfv(GL_LIGHT0, GL_SPECULAR, spc); - } - - { - double spin_speed = 2.0; - double wander_speed = 0.05; - double spin_accel = 0.2; - - bp->rot = make_rotator (do_spin ? spin_speed : 0, - do_spin ? spin_speed : 0, - do_spin ? spin_speed : 0, - spin_accel, - do_wander ? wander_speed : 0, - True); - bp->trackball = gltrackball_init (True); - } - - bp->npolyhedra = construct_polyhedra (&bp->polyhedra); - construct_teapot (mi); - - bp->object_list = glGenLists (1); - bp->change_to = -1; - - { - int x; - char c; - do_which = -1; - 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; - for (s = do_which_str; *s; s++) - if (*s == '-' || *s == '_') *s = ' '; - - 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)) - { - do_which = x; - break; - } - if (do_which < 0) - { - fprintf (stderr, "%s: no such polyhedron: \"%s\"\n", - progname, do_which_str); - exit (1); - } - } - } - - new_polyhedron (mi); - reshape_polyhedra (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); - clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ - -} - - -ENTRYPOINT void -draw_polyhedra (ModeInfo *mi) -{ - polyhedra_configuration *bp = &bps[MI_SCREEN(mi)]; - Display *dpy = MI_DISPLAY(mi); - Window window = MI_WINDOW(mi); - - 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) - { - if (bp->change_to >= 0) - bp->change_tick = 999, bp->last_change_time = 1; - if (bp->change_tick++ > 10) - { - time_t now = time((time_t *) 0); - 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; - bp->last_change_time = now; - } - } - } - else if (bp->mode == 1) /* out */ - { - if (--bp->mode_tick <= 0) - { - new_polyhedron (mi); - bp->mode_tick = 20 / speed; - bp->mode = 2; /* go in */ - } - } - else if (bp->mode == 2) /* in */ - { - if (--bp->mode_tick <= 0) - bp->mode = 0; /* normal */ - } - else - abort(); - - glShadeModel(GL_FLAT); - glEnable(GL_NORMALIZE); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glPushMatrix (); - - { - GLfloat s = (MI_WIDTH(mi) < MI_HEIGHT(mi) - ? (MI_WIDTH(mi) / (GLfloat) MI_HEIGHT(mi)) - : 1); - glScalef (s, s, s); - } - - glScalef(1.1, 1.1, 1.1); - - { - double x, y, z; - get_position (bp->rot, &x, &y, &z, !bp->button_down_p); - glTranslatef((x - 0.5) * 8, - (y - 0.5) * 8, - (z - 0.5) * 15); - - gltrackball_rotate (bp->trackball); - - get_rotation (bp->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 (2.0, 2.0, 2.0); - - glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, bspec); - glMateriali (GL_FRONT_AND_BACK, GL_SHININESS, bshiny); - - if (bp->mode != 0) - { - GLfloat s = (bp->mode == 1 - ? 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) - draw_label (mi); /* print_texture_font can't go inside a display list */ - - glPopMatrix (); - - if (mi->fps_p) do_fps (mi); - glFinish(); - - glXSwapBuffers(dpy, window); -} - - -ENTRYPOINT void -free_polyhedra (ModeInfo *mi) -{ - polyhedra_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->npolyhedra; i++) - free_polyhedron (bp->polyhedra[i]); - if (bp->trackball) gltrackball_free (bp->trackball); - if (bp->rot) free_rotator (bp->rot); - if (bp->colors) free (bp->colors); - if (bp->font1_data) free_texture_font (bp->font1_data); - if (bp->font2_data) free_texture_font (bp->font2_data); - if (bp->font3_data) free_texture_font (bp->font3_data); - if (glIsList(bp->object_list)) glDeleteLists(bp->object_list, 1); -} - -XSCREENSAVER_MODULE ("Polyhedra", polyhedra) - -#endif /* USE_GL */ |
