summaryrefslogtreecommitdiffstats
path: root/hacks/glx/polyhedra-gl.c
diff options
context:
space:
mode:
Diffstat (limited to 'hacks/glx/polyhedra-gl.c')
-rw-r--r--hacks/glx/polyhedra-gl.c686
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 */