diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-14 16:48:57 +0000 |
commit | 352df17fc71405e7bc36559ee8a72e21d7a5694a (patch) | |
tree | 34441fb7cf5bda1b968d4993924eaef0aa42dab7 |
Initial revisionXORG-STABLE
-rw-r--r-- | allobjs.h | 5 | ||||
-rw-r--r-- | ico.c | 1320 | ||||
-rw-r--r-- | ico.man | 92 | ||||
-rw-r--r-- | objcube.h | 29 | ||||
-rw-r--r-- | objico.h | 45 | ||||
-rw-r--r-- | objocta.h | 29 | ||||
-rw-r--r-- | objplane.h | 20 | ||||
-rw-r--r-- | objpyr.h | 30 | ||||
-rw-r--r-- | polyinfo.h | 31 |
9 files changed, 1601 insertions, 0 deletions
diff --git a/allobjs.h b/allobjs.h new file mode 100644 index 0000000..fec24fb --- /dev/null +++ b/allobjs.h @@ -0,0 +1,5 @@ +#include "objcube.h" +#include "objico.h" +#include "objocta.h" +#include "objpyr.h" +#include "objplane.h" @@ -0,0 +1,1320 @@ +/* $XConsortium: ico.c,v 1.47 94/04/17 20:45:15 gildea Exp $ */ +/*********************************************************** + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ +/* $XFree86: xc/programs/ico/ico.c,v 1.9 2002/12/24 17:43:00 tsi Exp $ */ + +/****************************************************************************** + * Description + * Display a wire-frame rotating icosahedron, with hidden lines removed + * + * Arguments: + * -r display on root window instead of creating a new one + * (plus a host of others, try -help) + *****************************************************************************/ +/* Additions by jimmc@sci: + * faces and colors + * double buffering on the display + * additional polyhedra + * sleep switch + */ + +/* + * multi-thread version by Stephen Gildea, January 1992 + */ + +/* Additions by Carlos A M dos Santos, XFree86 project, September 1999: + * use of "q" to quit threads + * support for ICCCM delete window message + * better thread support - mutex and condition to control termination + */ +#include <math.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#include <X11/Xfuncs.h> +#include <X11/keysym.h> +#include <stdio.h> +#ifdef MULTIBUFFER +#include <X11/extensions/multibuf.h> +#endif /* MULTIBUFFER */ +#ifdef MULTITHREAD +#include <X11/Xthreads.h> +#endif +#include <X11/Xos.h> + +#define MIN_ICO_WIDTH 5 +#define MIN_ICO_HEIGHT 5 +#define DEFAULT_ICO_WIDTH 150 +#define DEFAULT_ICO_HEIGHT 150 +#define DEFAULT_DELTAX 13 +#define DEFAULT_DELTAY 9 + +#include "polyinfo.h" /* define format of one polyhedron */ + +/* Now include all the files which define the actual polyhedra */ +Polyinfo polygons[] = { +#include "allobjs.h" +}; +#define NumberPolygons sizeof(polygons)/sizeof(polygons[0]) + +#include <stdlib.h> +#include <time.h> /* for time_t */ +#include <sys/time.h> /* for struct timeval */ + +typedef double Transform3D[4][4]; + +typedef struct { + int prevX, prevY; + unsigned long *plane_masks; /* points into dbpair.plane_masks */ + unsigned long enplanemask; /* what we enable for drawing */ + XColor *colors; /* size = 2 ** totalplanes */ + unsigned long *pixels; /* size = 2 ** planesperbuf */ +} DBufInfo; + +/* variables that need to be per-thread */ + +struct closure { + /* these elements were originally in DBufPair, a struct type */ + int planesperbuf; + int pixelsperbuf; /* = 1<<planesperbuf */ + int totalplanes; /* = 2*planesperbuf */ + int totalpixels; /* = 1<<totalplanes */ + unsigned long *plane_masks; /* size = totalplanes */ + unsigned long pixels[1]; + int dbufnum; + DBufInfo bufs[2]; + DBufInfo *drawbuf, *dpybuf; + /* end of old DBufPair dbpair */ + /* these elements were originally global variables */ + Window win, draw_window; + int winW, winH; + Colormap cmap; + GC gcontext; +#ifdef MULTIBUFFER + Multibuffer multibuffers[2]; +#endif /* MULTIBUFFER */ + int nplanesets; + /* items needed by drawPoly */ + char drawn[MAXNV][MAXNV]; + Transform3D xform; + Point3D xv[2][MAXNV]; + int xv_buffer; + double wo2, ho2; +#ifdef MULTITHREAD + int thread_num; +#endif +}; + + +/* The display is shared and writable, but Xlib locks it as necessary */ + +Display *dpy; + +/* This atom will be used to catch the ICCCM "delete window" message. It will + * be allocated once and used in read-only mode by threads, so it can be a + * global variable */ + +Atom wm_delete_window; + +/* + * variables that are not set except maybe in initialization before + * any additional threads are created + */ + +char *Primaries[] = { + "red", "green", "blue", "yellow", "cyan", "magenta" +}; +#define NumberPrimaries 6 + +const char *help_message[] = { +"where options include:", +"-display host:dpy X server to use", +" -geometry geom geometry of window to use", +" -size WxH size of object to rotate", +" -delta +X+Y amount by which to move object", +" -r draw in the root window", +" -d number dashed line pattern for wire frames", +" -bg color background color", +" -colors color ... codes to use on sides", +" -p# use # (1 through 8) primary colors", +#ifdef MULTIBUFFER +" -dbl use double buffering (extension if present)", +#else +" -dbl use double buffering (software only)", +#endif +" -softdbl use software double buffering", +" -noedges don't draw wire frame edges", +" -faces draw faces", +" -copy use multibuffer update action Copied", +" -untouched use multibuffer update action Untouched", +" -undefined use multibuffer update action Undefined", +" -lw number line width to use", +" -i invert", +" -sleep number seconds to sleep in between draws", +" -obj objname type of polyhedral object to draw", +" -objhelp list polyhedral objects available", +#ifdef MULTITHREAD +" -threads number number of windows, each its own thread", +#endif +NULL}; + +const char *ProgramName; /* argv[0] */ + +/* + * variables set by command-line options + */ +const char *geom = NULL; /* -geometry: window geometry */ +int useRoot = 0; /* -r */ +int dash = 0; /* -d: dashed line pattern */ +char **colornames; /* -colors (points into argv) */ +#ifdef MULTIBUFFER +int update_action = MultibufferUpdateActionBackground; +#endif +int linewidth = 0; /* -lw */ +int multibufext = 0; /* -dbl: use Multi-Buffering extension */ +int dblbuf = 0; /* -dbl or -softdbl: double buffering */ +int numcolors = 0; /* -p: number of primary colors to use */ +const char *background_colorname = NULL; /* -bg */ +int doedges = 1; /* -noedges turns this off */ +int dofaces = 0; /* -faces */ +int invert = 0; /* -i */ +const char *ico_geom = NULL; /* -size: size of object in window */ +const char *delta_geom = NULL; /* -delta: amount by which to move object */ +Polyinfo *poly; /* -obj: the poly to draw */ +int dsync = 0; /* -dsync */ +int msleepcount = 0; /* -sleep value in milliseconds*/ +#ifdef MULTITHREAD +int thread_count; +#ifdef XMUTEX_INITIALIZER +xmutex_rec count_mutex = XMUTEX_INITIALIZER; +#else +xmutex_rec count_mutex; +#endif +xcondition_rec count_cond; /* Xthreads doesn't define an equivalent to + * PTHREAD_COND_INITIALIZER, so we must call + * xcondition_init later */ +#endif + +/****************************************************************************** + * Description + * Error handling + *****************************************************************************/ + +#if defined(__GNUC__) && \ + ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) +void icoFatal (const char *fmt, const char *a0) __attribute__((__noreturn__)); +#endif +void +icoFatal(fmt,a0) + const char *fmt; + const char *a0; +{ + fprintf(stderr, "%s: ", ProgramName); + fprintf(stderr, fmt, a0); + fprintf(stderr, "\n"); + exit(1); +} + + +/****************************************************************************** + * Description + * Memory allocation + *****************************************************************************/ + +static char * +xalloc(unsigned int nbytes) +{ + char *p; + + p = malloc(nbytes); + if (p) + return p; + + fprintf(stderr, "%s: no more memory\n", ProgramName); + exit(1); +} + + +/****************************************************************************** + * Description + * Sleep a certain number of milliseconds + *****************************************************************************/ + +static void +msleep(unsigned int msecs) +{ + struct timeval timeout; + + timeout.tv_sec = msecs / 1000; timeout.tv_usec = (msecs % 1000) * 1000; + select(1,NULL,NULL,NULL,&timeout); +} + + +/****************************************************************************** + * Description + * Format a 4x4 identity matrix. + * + * Output + * *m Formatted identity matrix + *****************************************************************************/ + +static void +IdentMat(Transform3D m) +{ + int i; + int j; + + for (i = 3; i >= 0; --i) { + for (j = 3; j >= 0; --j) + m[i][j] = 0.0; + m[i][i] = 1.0; + } +} + + +/****************************************************************************** + * Description + * Concatenate two 4-by-4 transformation matrices. + * + * Input + * l multiplicand (left operand) + * r multiplier (right operand) + * + * Output + * *m Result matrix + *****************************************************************************/ + +static void +ConcatMat(Transform3D l, Transform3D r, Transform3D m) +{ + int i; + int j; + + for (i = 0; i < 4; ++i) + for (j = 0; j < 4; ++j) + m[i][j] = l[i][0] * r[0][j] + + l[i][1] * r[1][j] + + l[i][2] * r[2][j] + + l[i][3] * r[3][j]; +} + + +/****************************************************************************** + * Description + * Format a matrix that will perform a rotation transformation + * about the specified axis. The rotation angle is measured + * counterclockwise about the specified axis when looking + * at the origin from the positive axis. + * + * Input + * axis Axis ('x', 'y', 'z') about which to perform rotation + * angle Angle (in radians) of rotation + * A Pointer to rotation matrix + * + * Output + * *m Formatted rotation matrix + *****************************************************************************/ + +static void +FormatRotateMat(char axis, double angle, Transform3D m) +{ + double s, c; + + IdentMat(m); + + s = sin(angle); + c = cos(angle); + + switch (axis) + { + case 'x': + m[1][1] = m[2][2] = c; + m[1][2] = s; + m[2][1] = -s; + break; + case 'y': + m[0][0] = m[2][2] = c; + m[2][0] = s; + m[0][2] = -s; + break; + case 'z': + m[0][0] = m[1][1] = c; + m[0][1] = s; + m[1][0] = -s; + break; + } +} + + +/****************************************************************************** + * Description + * Perform a partial transform on non-homogeneous points. + * Given an array of non-homogeneous (3-coordinate) input points, + * this routine multiplies them by the 3-by-3 upper left submatrix + * of a standard 4-by-4 transform matrix. The resulting non-homogeneous + * points are returned. + * + * Input + * n number of points to transform + * m 4-by-4 transform matrix + * in array of non-homogeneous input points + * + * Output + * *out array of transformed non-homogeneous output points + *****************************************************************************/ + +static void +PartialNonHomTransform(int n, Transform3D m, const Point3D *in, Point3D *out) +{ + for (; n > 0; --n, ++in, ++out) { + out->x = in->x * m[0][0] + in->y * m[1][0] + in->z * m[2][0]; + out->y = in->x * m[0][1] + in->y * m[1][1] + in->z * m[2][1]; + out->z = in->x * m[0][2] + in->y * m[1][2] + in->z * m[2][2]; + } +} + + +/* + * Unfortunately we can not use XWindowEvent and XCheckWindowEvent to get + * ClientMessage events, because there is no corresponding event mask. We must + * use XIfEvent and XCheckIfEvent and this function as a predicate. Better if + * Xlib had some kind of XWindowAnyEvent and XCheckWindowEvent. -- Casantos. + */ + +static Bool +predicate(Display *display, XEvent *event, XPointer args) +{ + Window w = (Window) args; + return event->xany.window == w; +} + +/****************************************************************************** + * Description + * Icosahedron animator. + *****************************************************************************/ + +static void +icoClearArea(struct closure *closure, int x, int y, int w, int h) +{ + if (multibufext && dblbuf) + return; + + if (dblbuf || dofaces) { + XSetForeground(dpy, + closure->gcontext, + closure->drawbuf->pixels[0]); + + /* use background as foreground color for fill */ + XFillRectangle(dpy,closure->win,closure->gcontext,x,y,w,h); + } else { + XClearArea(dpy,closure->win,x,y,w,h,0); + } +} + +/* Set up points, transforms, etc. */ + +static void +initPoly(struct closure *closure, const Polyinfo *poly, int icoW, int icoH) +{ + Point3D *vertices = poly->v; + int NV = poly->numverts; + Transform3D r1; + Transform3D r2; + + FormatRotateMat('x', 5 * 3.1416 / 180.0, r1); + FormatRotateMat('y', 5 * 3.1416 / 180.0, r2); + ConcatMat(r1, r2, closure->xform); + + memcpy((char *)closure->xv[0], (char *)vertices, NV * sizeof(Point3D)); + closure->xv_buffer = 0; + + closure->wo2 = icoW / 2.0; + closure->ho2 = icoH / 2.0; +} + +static void +setDrawBuf (struct closure *closure, int n) +{ + XGCValues xgcv; + unsigned long mask; + +#ifdef MULTIBUFFER + if (multibufext && dblbuf) { + closure->win = closure->multibuffers[n]; + n = 0; + } +#endif /* MULTIBUFFER */ + + closure->drawbuf = closure->bufs+n; + xgcv.foreground = closure->drawbuf->pixels[closure->pixelsperbuf-1]; + xgcv.background = closure->drawbuf->pixels[0]; + mask = GCForeground | GCBackground; + if (dblbuf && !multibufext) { + xgcv.plane_mask = closure->drawbuf->enplanemask; + mask |= GCPlaneMask; + } + XChangeGC(dpy, closure->gcontext, mask, &xgcv); +} + +static void +setDisplayBuf(struct closure *closure, int n, int firsttime) +{ +#ifdef MULTIBUFFER + if (multibufext && dblbuf) { + XmbufDisplayBuffers (dpy, 1, &closure->multibuffers[n], msleepcount, 0); + if (!firsttime) + return; + n = 0; + } +#endif + closure->dpybuf = closure->bufs+n; + if (closure->totalpixels > 2) + XStoreColors(dpy,closure->cmap,closure->dpybuf->colors,closure->totalpixels); +} + +static void +setBufColor(struct closure *closure, int n, XColor *color) +{ + int i,j,cx; + DBufInfo *b; + unsigned long pix; + + for (i=0; i<closure->nplanesets; i++) { + b = closure->bufs+i; + for (j=0; j<(dblbuf&&!multibufext?closure->pixelsperbuf:1); j++) { + cx = n + j*closure->pixelsperbuf; + pix = b->colors[cx].pixel; + b->colors[cx] = *color; + b->colors[cx].pixel = pix; + b->colors[cx].flags = DoRed | DoGreen | DoBlue; + } + } +} + +/****************************************************************************** + * Description + * Undraw previous polyhedron (by erasing its bounding box). + * Rotate and draw the new polyhedron. + * + * Input + * poly the polyhedron to draw + * gc X11 graphics context to be used for drawing + * icoX, icoY position of upper left of bounding-box + * icoW, icoH size of bounding-box + * prevX, prevY position of previous bounding-box + *****************************************************************************/ + +static void +drawPoly(struct closure *closure, Polyinfo *poly, GC gc, + int icoX, int icoY, int icoW, int icoH, int prevX, int prevY) +{ + int *f = poly->f; + int NV = poly->numverts; + int NF = poly->numfaces; + + int p0; + int p1; + XPoint *pv2; + XSegment *pe; + Point3D *pxv; + XPoint v2[MAXNV]; + XSegment edges[MAXEDGES]; + int i; + int j,k; + int *pf; + int facecolor; + + int pcount; + double pxvz; + XPoint ppts[MAXEDGESPERPOLY]; + + /* Switch double-buffer and rotate vertices */ + + closure->xv_buffer = !closure->xv_buffer; + PartialNonHomTransform(NV, closure->xform, + closure->xv[!closure->xv_buffer], + closure->xv[closure->xv_buffer]); + + + /* Convert 3D coordinates to 2D window coordinates: */ + + pxv = closure->xv[closure->xv_buffer]; + pv2 = v2; + for (i = NV - 1; i >= 0; --i) { + pv2->x = (int) ((pxv->x + 1.0) * closure->wo2) + icoX; + pv2->y = (int) ((pxv->y + 1.0) * closure->ho2) + icoY; + ++pxv; + ++pv2; + } + + + /* Accumulate edges to be drawn, eliminating duplicates for speed: */ + + pxv = closure->xv[closure->xv_buffer]; + pv2 = v2; + pf = f; + pe = edges; + bzero(closure->drawn, sizeof(closure->drawn)); + + if (dblbuf) + setDrawBuf(closure, closure->dbufnum); + /* switch drawing buffers if double buffered */ + /* for faces, need to clear before FillPoly */ + if (dofaces && !(multibufext && dblbuf)) { + /* multibuf uses update background */ + if (dblbuf) + icoClearArea(closure, + closure->drawbuf->prevX - linewidth/2, + closure->drawbuf->prevY - linewidth/2, + icoW + linewidth + 1, icoH + linewidth + 1); + icoClearArea(closure, + prevX - linewidth/2, prevY - linewidth/2, + icoW + linewidth + 1, icoH + linewidth + 1); + } + + if (dsync) + XSync(dpy, 0); + + for (i = NF - 1; i >= 0; --i, pf += pcount) { + + pcount = *pf++; /* number of edges for this face */ + pxvz = 0.0; + for (j=0; j<pcount; j++) { + p0 = pf[j]; + pxvz += pxv[p0].z; + } + + /* If facet faces away from viewer, don't consider it: */ + if (pxvz<0.0) + continue; + + if (dofaces) { + if (numcolors) + facecolor = i%numcolors + 1; + else + facecolor = 1; + XSetForeground(dpy, gc, + closure->drawbuf->pixels[facecolor]); + for (j=0; j<pcount; j++) { + p0 = pf[j]; + ppts[j].x = pv2[p0].x; + ppts[j].y = pv2[p0].y; + } + XFillPolygon(dpy, closure->win, gc, ppts, pcount, + Convex, CoordModeOrigin); + } + + if (doedges) { + for (j=0; j<pcount; j++) { + if (j<pcount-1) k=j+1; + else k=0; + p0 = pf[j]; + p1 = pf[k]; + if (!closure->drawn[p0][p1]) { + closure->drawn[p0][p1] = 1; + closure->drawn[p1][p0] = 1; + pe->x1 = pv2[p0].x; + pe->y1 = pv2[p0].y; + pe->x2 = pv2[p1].x; + pe->y2 = pv2[p1].y; + ++pe; + } + } + } + } + + /* Erase previous, draw current icosahedrons; sync for smoothness. */ + + if (doedges) { + if (dofaces) { + XSetForeground(dpy, gc, closure->drawbuf->pixels[0]); + /* use background as foreground color */ + } else { + if (dblbuf && !multibufext) + icoClearArea(closure, + closure->drawbuf->prevX - linewidth/2, + closure->drawbuf->prevY - linewidth/2, + icoW + linewidth + 1, + icoH + linewidth + 1); + if (!(multibufext && dblbuf)) + icoClearArea(closure, + prevX - linewidth/2, + prevY - linewidth/2, + icoW + linewidth + 1, + icoH + linewidth + 1); + if (dblbuf || dofaces) { + XSetForeground(dpy, gc, closure->drawbuf->pixels[ + closure->pixelsperbuf-1]); + } + } + XDrawSegments(dpy, closure->win, gc, edges, pe - edges); + } + + if (dsync) + XSync(dpy, 0); + + if (dblbuf) { + closure->drawbuf->prevX = icoX; + closure->drawbuf->prevY = icoY; + setDisplayBuf(closure, closure->dbufnum, 0); + } + if (dblbuf) + closure->dbufnum = 1 - closure->dbufnum; + if (!(multibufext && dblbuf) && msleepcount > 0) + msleep(msleepcount); +} + +static void +initDBufs(struct closure *closure, int fg, int bg, int planesperbuf) +{ + int i,j,jj,j0,j1,k,m,t; + DBufInfo *b, *otherb; + XColor bgcolor, fgcolor; + + closure->nplanesets = (dblbuf && !multibufext ? 2 : 1); + + closure->planesperbuf = planesperbuf; + closure->pixelsperbuf = 1<<planesperbuf; + closure->totalplanes = closure->nplanesets * planesperbuf; + closure->totalpixels = 1<<closure->totalplanes; + closure->plane_masks = (unsigned long *) + xalloc(closure->totalplanes * sizeof(unsigned long)); + closure->dbufnum = 0; + for (i=0; i < closure->nplanesets; i++) { + b = closure->bufs+i; + b->plane_masks = closure->plane_masks + (i*planesperbuf); + b->colors = (XColor *) + xalloc(closure->totalpixels * sizeof(XColor)); + b->pixels = (unsigned long *) + xalloc(closure->pixelsperbuf * sizeof(unsigned long)); + } + + if (closure->totalplanes == 1) { + closure->pixels[0] = bg; + closure->plane_masks[0] = fg ^ bg; + } else { + t = XAllocColorCells(dpy,closure->cmap,0, + closure->plane_masks,closure->totalplanes, closure->pixels,1); + /* allocate color planes */ + if (t==0) { + icoFatal("can't allocate enough color planes", NULL); + } + } + + fgcolor.pixel = fg; + bgcolor.pixel = bg; + XQueryColor(dpy,closure->cmap,&fgcolor); + XQueryColor(dpy,closure->cmap,&bgcolor); + + setBufColor(closure, 0,&bgcolor); + setBufColor(closure, 1,&fgcolor); + for (i=0; i<closure->nplanesets; i++) { + b = closure->bufs+i; + if (dblbuf) + otherb = closure->bufs+(1-i); + for (j0=0; j0<(dblbuf&&!multibufext?closure->pixelsperbuf:1); j0++) { + for (j1=0; j1<closure->pixelsperbuf; j1++) { + j = (j0<<closure->planesperbuf)|j1; + if (i==0) jj=j; + else jj= (j1<<closure->planesperbuf)|j0; + b->colors[jj].pixel = closure->pixels[0]; + for (k=0, m=j; m; k++, m=m>>1) { + if (m&1) + b->colors[jj].pixel ^= closure->plane_masks[k]; + } + b->colors[jj].flags = DoRed | DoGreen | DoBlue; + } + } + b->prevX = b->prevY = 0; + b->enplanemask = 0; + for (j=0; j<planesperbuf; j++) { + b->enplanemask |= b->plane_masks[j]; + } + for (j=0; j<closure->pixelsperbuf; j++) { + b->pixels[j] = closure->pixels[0]; + for (k=0, m=j; m; k++, m=m>>1) { + if (m&1) + b->pixels[j] ^= b->plane_masks[k]; + } + } + } + + if (!(multibufext && dblbuf)) { + setDrawBuf(closure, 0); + XSetBackground(dpy, closure->gcontext, closure->bufs[0].pixels[0]); + XSetWindowBackground(dpy, closure->draw_window, closure->bufs[0].pixels[0]); + XSetPlaneMask(dpy, closure->gcontext, AllPlanes); + icoClearArea(closure, 0, 0, closure->winW, closure->winH); /* clear entire window */ + } +} + +static void +setBufColname(struct closure *closure, int n, char *colname) +{ + int t; + XColor dcolor, color; + + t = XLookupColor(dpy,closure->cmap,colname,&dcolor,&color); + if (t==0) { /* no such color */ + icoFatal("no such color %s",colname); + } + setBufColor(closure, n,&color); +} + + +/* function to create and run an ico window */ +static void * +do_ico_window(void *ptr) +{ + int fg, bg; + XSetWindowAttributes xswa; + XWindowAttributes xwa; + XEvent xev; + int icoX, icoY; + unsigned long vmask; + XGCValues xgcv; + int initcolors = 0; + int icoDeltaX = DEFAULT_DELTAX, icoDeltaY = DEFAULT_DELTAY; + int icodeltax2, icodeltay2; + Bool blocking = False; + int winX, winY; + int icoW = 0, icoH = 0; + KeySym ksym; + Bool do_it = True; + char buf[20]; + struct closure *closure = ptr; +#ifdef MULTITHREAD + int len; +#endif + +#ifdef DEBUG + printf("thread %x starting\n", xthread_self()); +#endif + closure->cmap = XDefaultColormap(dpy,DefaultScreen(dpy)); + if (!closure->cmap) { + icoFatal("no default colormap!", NULL); + } + + fg = WhitePixel(dpy, DefaultScreen(dpy)); + bg = BlackPixel(dpy, DefaultScreen(dpy)); + if (background_colorname) { + XColor cdef, igndef; + + if (XAllocNamedColor (dpy, closure->cmap, background_colorname, + &cdef, &igndef)) + bg = cdef.pixel; + else + icoFatal("background: no such color \"%s\"",background_colorname); + } + if (numcolors && (!dofaces || numcolors == 1)) { + XColor cdef, igndef; + + if (XAllocNamedColor (dpy, closure->cmap, colornames[0], &cdef, &igndef)) + fg = cdef.pixel; + else + icoFatal("face: no such color \"%s\"", colornames[0]); + } + + if (invert) { + unsigned long tmp = fg; + fg = bg; + bg = tmp; + } + + /* Set up window parameters, create and map window if necessary */ + + if (useRoot) { + closure->draw_window = DefaultRootWindow(dpy); + winX = 0; + winY = 0; + closure->winW = DisplayWidth(dpy, DefaultScreen(dpy)); + closure->winH = DisplayHeight(dpy, DefaultScreen(dpy)); + } else { + closure->winW = closure->winH = (multibufext&&dblbuf ? 300 : 600); + winX = (DisplayWidth(dpy, DefaultScreen(dpy)) - closure->winW) >> 1; + winY = (DisplayHeight(dpy, DefaultScreen(dpy)) - closure->winH) >> 1; + if (geom) + XParseGeometry(geom, &winX, &winY, + (unsigned int *)&closure->winW, + (unsigned int *)&closure->winH); + + xswa.event_mask = ExposureMask | + StructureNotifyMask | + KeyPressMask; + xswa.background_pixel = bg; + xswa.border_pixel = fg; + + closure->draw_window = XCreateWindow(dpy, + DefaultRootWindow(dpy), + winX, winY, closure->winW, closure->winH, 0, + DefaultDepth(dpy, DefaultScreen(dpy)), + InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)), + CWEventMask | CWBackPixel | CWBorderPixel, &xswa); +#ifdef MULTITHREAD + len = sprintf(buf, "Ico: thread %d", closure->thread_num); + XChangeProperty(dpy, closure->draw_window, + XA_WM_NAME, XA_STRING, 8, + PropModeReplace, (unsigned char *)buf, len); +#else + XChangeProperty(dpy, closure->draw_window, + XA_WM_NAME, XA_STRING, 8, + PropModeReplace, (unsigned char *)"Ico", 3); +#endif + (void) XSetWMProtocols (dpy, closure->draw_window, + &wm_delete_window, 1); + XMapWindow(dpy, closure->draw_window); +#ifdef DEBUG + printf("thread %x waiting for Expose\n", xthread_self()); +#endif + for (;;) { + XNextEvent(dpy, &xev); + if (xev.type == Expose) + break; + } +#ifdef DEBUG + printf("thread %x got Expose\n", xthread_self()); +#endif + if (XGetWindowAttributes(dpy,closure->draw_window,&xwa)==0) { + icoFatal("cannot get window attributes (size)", NULL); + } + closure->winW = xwa.width; + closure->winH = xwa.height; + } + + if (ico_geom) + XParseGeometry (ico_geom, &icoX, &icoY, + (unsigned int *)&icoW, + (unsigned int *)&icoH); + if (icoW <= 0) icoW = DEFAULT_ICO_WIDTH; + if (icoH <= 0) icoH = DEFAULT_ICO_HEIGHT; + if (icoW < MIN_ICO_WIDTH) icoW = MIN_ICO_WIDTH; + if (icoH < MIN_ICO_HEIGHT) icoH = MIN_ICO_HEIGHT; + + if (delta_geom) { + unsigned int junk; + + XParseGeometry (delta_geom, &icoDeltaX, &icoDeltaY, &junk, &junk); + if (icoDeltaX == 0 && icoDeltaY == 0) { + icoDeltaX = DEFAULT_DELTAX; + icoDeltaY = DEFAULT_DELTAY; + } + } + + closure->win = None; + +#ifdef MULTIBUFFER + if (multibufext && dblbuf) { + if (XmbufCreateBuffers (dpy, closure->draw_window, 2, update_action, + MultibufferUpdateHintFrequent, + closure->multibuffers) == 2) { + XCopyArea (dpy, closure->draw_window, closure->multibuffers[1], + DefaultGC(dpy, DefaultScreen(dpy)), + 0, 0, closure->winW, closure->winH, 0, 0); + closure->win = closure->multibuffers[1]; + } else + icoFatal ("unable to obtain 2 buffers", NULL); + } +#endif /* MULTIBUFFER */ + if (closure->win == None) closure->win = closure->draw_window; + + /* Set up a graphics context */ + + vmask = (GCBackground | GCForeground | GCLineWidth); + xgcv.background = bg; + xgcv.foreground = fg; + xgcv.line_width = linewidth; + if (dash) { + xgcv.line_style = LineDoubleDash; + xgcv.dashes = dash; + vmask |= (GCLineStyle | GCDashList); + } + closure->gcontext = XCreateGC (dpy, closure->draw_window, vmask, &xgcv); + + if (dofaces && numcolors>1) { + int i,t,bits; + bits = 0; + for (t=numcolors; t; t=t>>1) bits++; + initDBufs(closure, fg,bg,bits); + /* don't set the background color */ + for (i=0; i<numcolors; i++) { + setBufColname(closure, i+1,colornames[i]); + } + initcolors = 1; + } + else if (dblbuf || dofaces) { + initDBufs(closure, fg,bg,1); + initcolors = 1; + } + if (initcolors) { + setDisplayBuf(closure, dblbuf?1:0, 1); /* insert new colors */ + } + + if (dsync) + XSync(dpy, 0); + + /* Get the initial position, size, and speed of the bounding-box */ + + srand((int) time((time_t *)0) % 231); + icoX = ((closure->winW - icoW) * (rand() & 0xFF)) >> 8; + icoY = ((closure->winH - icoH) * (rand() & 0xFF)) >> 8; + + + /* Bounce the box in the window */ + + icodeltax2 = icoDeltaX * 2; + icodeltay2 = icoDeltaY * 2; + initPoly(closure, poly, icoW, icoH); + + while (do_it) { + int prevX; + int prevY; + Bool do_event; + + /* + * This is not a good example of how to do event reading + * in multi-threaded programs. More commonly there would + * be one thread reading all events and dispatching them + * to the appropriate thread. However, the threaded version + * of ico was developed to test the MT Xlib implementation, + * so it is useful to have it behave a little oddly. + * For a discussion of how to write multi-threaded X programs, + * see Gildea, S., "Multi-Threaded Xlib", The X Resource, + * Issue 5, January 1993, pp. 159-166. + */ + if (blocking) { + XIfEvent(dpy, &xev, predicate, (XPointer) closure->win); + do_event = True; + } else + do_event = XCheckIfEvent(dpy, &xev, predicate, + (XPointer) closure->win); + if (do_event) { + switch (xev.type) { + case ConfigureNotify: +#ifdef DEBUG + printf("thread %x configure\n", xthread_self()); +#endif + if (xev.xconfigure.width != closure->winW || + xev.xconfigure.height != closure->winH) + icoX = icoY = 1; + closure->winW = xev.xconfigure.width; + closure->winH = xev.xconfigure.height; + break; + case KeyPress: +#ifdef DEBUG + printf("thread %x keypress\n", xthread_self()); +#endif + XLookupString(&xev.xkey, buf, 10, &ksym, NULL); + do_it = ((ksym != XK_Q) && ksym != XK_q); + break; + case MapNotify: + blocking = False; +#ifdef DEBUG + printf("thread %x unblocking\n", xthread_self()); +#endif + break; + case UnmapNotify: + blocking = True; +#ifdef DEBUG + printf("thread %x blocking\n", xthread_self()); +#endif + break; + case ClientMessage: +#ifdef DEBUG + printf("thread %x message\n", xthread_self()); +#endif + if (xev.xclient.data.l[0] == wm_delete_window) + do_it = False; + else + XBell (dpy, 0); + continue; + } + } + + prevX = icoX; + prevY = icoY; + + icoX += icoDeltaX; + if (icoX < 0 || icoX + icoW > closure->winW) { + icoX -= icodeltax2; + icoDeltaX = - icoDeltaX; + icodeltax2 = icoDeltaX * 2; + } + icoY += icoDeltaY; + if (icoY < 0 || icoY + icoH > closure->winH) { + icoY -= icodeltay2; + icoDeltaY = - icoDeltaY; + icodeltay2 = icoDeltaY * 2; + } + + drawPoly(closure, poly, closure->gcontext, + icoX, icoY, icoW, icoH, prevX, prevY); + } + XDestroyWindow(dpy, closure->win); +#ifdef MULTITHREAD + xmutex_lock(&count_mutex); + thread_count--; + if (thread_count == 0) { + xcondition_broadcast(&count_cond); + } + xmutex_unlock(&count_mutex); +#endif + return NULL; +} + +/****************************************************************************** + * Description + * Main routine. Process command-line arguments, then bounce a bounding + * box inside the window. Call DrawIco() to redraw the icosahedron. + *****************************************************************************/ + +static void +giveObjHelp(void) +{ + int i; + Polyinfo *poly; + + printf("%-16s%-12s #Vert. #Edges #Faces %-16s\n", + "Name", "ShortName", "Dual"); + for (i=0; i<NumberPolygons; i++) { + poly = polygons+i; + printf("%-16s%-12s%6d%8d%8d %-16s\n", + poly->longname, poly->shortname, + poly->numverts, poly->numedges, poly->numfaces, + poly->dual); + } +} + +static Polyinfo * +findpoly(const char *name) +{ + int i; + Polyinfo *poly; + + for (i=0; i<NumberPolygons; i++) { + poly = polygons+i; + if (strcmp(name,poly->longname)==0 || strcmp(name,poly->shortname)==0) + return poly; + } + icoFatal("can't find object %s", name); +} + +int main(argc, argv) + int argc; + char **argv; +{ + const char *display = NULL; +#ifdef MULTIBUFFER + int mbevbase, mberrbase; +#endif +#ifdef MULTITHREAD + int nthreads = 1; /* -threads: number of windows */ + int i; +#endif + struct closure *closure; + + ProgramName = argv[0]; + + /* Process arguments: */ + + poly = findpoly("icosahedron"); /* default */ + + for (argv++, argc--; argc > 0; argv++, argc--) { + if (!strcmp (*argv, "-display")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + display = *++argv; argc--; + } else if (!strncmp (*argv, "-g", 2)) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + geom = *++argv; argc--; + } else if (!strcmp(*argv, "-r")) + useRoot = 1; + else if (!strcmp (*argv, "-d")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + dash = atoi(*++argv); argc--; + } +#ifdef MULTITHREAD + else if (!strcmp(*argv, "-threads")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + nthreads = atoi(*++argv); argc--; + } +#endif + else if (!strcmp(*argv, "-colors")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + colornames = ++argv; argc--; numcolors = 0; + for ( ; argc > 0 && argv[0][0]!='-'; argv++, argc--, numcolors++) ; + argv--; argc++; + } + else if (!strcmp (*argv, "-copy")) { +#ifdef MULTIBUFFER + update_action = MultibufferUpdateActionCopied; +#endif + } + else if (!strcmp (*argv, "-untouched")) { +#ifdef MULTIBUFFER + update_action = MultibufferUpdateActionUntouched; +#endif + } + else if (!strcmp (*argv, "-undefined")) { +#ifdef MULTIBUFFER + update_action = MultibufferUpdateActionUndefined; +#endif + } else if (!strcmp (*argv, "-lw")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + linewidth = atoi(*++argv); argc--; + } else if (!strcmp (*argv, "-dbl")) { + dblbuf = 1; +#ifdef MULTIBUFFER + multibufext = 1; +#endif + } + else if (!strcmp(*argv, "-softdbl")) { + dblbuf = 1; + multibufext = 0; + } + else if (!strncmp(*argv, "-p", 2)) { + numcolors = atoi(argv[0]+2); + if (numcolors < 1 || numcolors > NumberPrimaries) + numcolors = NumberPrimaries; + colornames = Primaries; + dofaces = 1; + } + else if (!strcmp(*argv, "-bg")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + background_colorname = *++argv; argc--; + } else if (!strcmp(*argv, "-noedges")) + doedges = 0; + else if (!strcmp(*argv, "-faces")) + dofaces = 1; + else if (!strcmp(*argv, "-i")) + invert = 1; + else if (!strcmp(*argv, "-size")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + ico_geom = *++argv; argc--; + } else if (!strcmp(*argv, "-delta")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + delta_geom = *++argv; argc--; + } else if (!strcmp (*argv, "-sleep")) { + float f; + if (argc < 2) + icoFatal("missing argument for %s", *argv); + if (sscanf (*++argv, "%f", &f) < 1) + icoFatal("invalid argument for %s", argv[-1]); + msleepcount = (int) (f * 1000.0); + argc--; + } else if (!strcmp (*argv, "-obj")) { + if (argc < 2) + icoFatal("missing argument for %s", *argv); + poly = findpoly(*++argv); argc--; + } else if (!strcmp(*argv, "-dsync")) + dsync = 1; + else if (!strncmp(*argv, "-sync", 5)) + _Xdebug = 1; + else if (!strcmp(*argv, "-objhelp")) { + giveObjHelp(); + exit(1); + } + else { /* unknown arg */ + const char **cpp; + + fprintf (stderr, "usage: %s [options]\n\n", + ProgramName); + for (cpp = help_message; *cpp; cpp++) + fprintf (stderr, "%s\n", *cpp); + exit (1); + } + } + + if (!dofaces && !doedges) + icoFatal("nothing to draw", NULL); + +#ifdef MULTITHREAD + XInitThreads(); +#endif + if (!(dpy = XOpenDisplay(display))) + icoFatal("cannot open display \"%s\"", XDisplayName(display)); + wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False); + +#ifdef MULTIBUFFER + if (multibufext && !XmbufQueryExtension (dpy, &mbevbase, &mberrbase)) { + multibufext = 0; + } +#endif + +#ifdef MULTITHREAD +#ifndef XMUTEX_INITIALIZER + xmutex_init(&count_mutex); +#endif + xcondition_init(&count_cond); + + /* start all threads here */ + thread_count = nthreads; + for (i=1; i <= nthreads; i++) { + closure = (struct closure *) xalloc(sizeof(struct closure)); + closure->thread_num = i; + xthread_fork(do_ico_window, closure); + } + /* wait until all theads terminate */ + xmutex_lock(&count_mutex); + xcondition_wait(&count_cond, &count_mutex); + xmutex_unlock(&count_mutex); +#else + /* start the animation */ + closure = (struct closure *) xalloc(sizeof(struct closure)); + do_ico_window(closure); +#endif + XCloseDisplay(dpy); + return 0; +} @@ -0,0 +1,92 @@ +.\" $XConsortium: ico.man,v 1.14 94/04/17 20:45:16 gildea Exp $ +.\" $XFree86: xc/programs/ico/ico.man,v 1.3 2001/01/27 18:21:03 dawes Exp $ +.TH ICO 1 __xorgversion__ +.SH NAME +ico \- animate an icosahedron or other polyhedron +.SH SYNOPSIS +.B ico +[-display display] [-geometry geometry] +[-r] [-d pattern] [-i] [-dbl] [-faces] [-noedges] +[-sleep n] [-obj object] [-objhelp] [-colors color-list] +.SH DESCRIPTION +.I Ico +displays a wire-frame rotating polyhedron, with hidden lines removed, +or a solid-fill polyhedron with hidden faces removed. +There are a number of different polyhedra available; +adding a new polyhedron to the program is quite simple. +.SH OPTIONS +.TP +.B -r +Display on the root window instead of creating a new window. +.TP +.B -d pattern +Specify a bit pattern for drawing dashed lines for wire frames. +.TP +.B -i +Use inverted colors for wire frames. +.TP +.B -dbl +Use double buffering on the display. +This works for either wire frame or solid fill drawings. +For solid fill drawings, using this switch results in substantially +smoother movement. +Note that this requires twice as many bit planes as without double buffering. +Since some colors are typically allocated by other programs, +most eight-bit-plane displays will probably be limited to eight colors +when using double buffering. +.TP +.B -faces +Draw filled faces instead of wire frames. +.TP +.B -noedges +Don't draw the wire frames. +Typically used only when -faces is used. +.TP +.B -sleep \fIn\fP +Sleep n seconds between each move of the object. +.TP +.B -obj \fIobject\fP +Specify what object to draw. +If no object is specified, an icosahedron is drawn. +.TP +.B -objhelp +Print out a list of the available objects, along with information +about each object. +.TP +.B -colors \fIcolor color ...\fP +Specify what colors should be used to draw the filled faces of the object. +If less colors than faces are given, the colors are reused. +.SH PROGRAM TREMINATION +.LP +Pressing "q" will close a window. If compiled with threads support, the +program will stop only when all threads terminate. You can also close an +animation window using the ICCCM \fIdelete\fP message (deppending on your +window manager, you will have a decoration button or menu to send such +message). +.SH ADDING POLYHEDRA +.LP +If you have the source to ico, it is very easy to add more polyhedra. +Each polyhedron is defined in an include file by the name of objXXX.h, +where XXX is something related to the name of the polyhedron. +The format of the include file is defined in the file polyinfo.h. +Look at the file objcube.h to see what the exact format of an objXXX.h +file should be, then create your objXXX.h file in that format. +.LP +After making the new objXXX.h file (or copying in a new one from elsewhere), +simply do a 'make depend'. +This will recreate the file allobjs.h, which lists all of the objXXX.h +files. +Doing a 'make' after this will rebuild ico with the new object information. +.SH "SEE ALSO" +X(__miscmansuffix__) +.SH BUGS +.LP +Pyramids and tetrahedrons with filled faces do not display correctly. +.LP +A separate color cell is allocated for each name in the -colors list, even +when the same name may be specified twice. Color allocation fails in +TrueColor displays and option \fI-faces\fP does not work well. +.SH COPYRIGHT +Copyright ([\d,\s]*) X Consortium +.br +See \fIX(__miscmansuffix__)\fP for a full statement of rights and permissions. diff --git a/objcube.h b/objcube.h new file mode 100644 index 0000000..441145e --- /dev/null +++ b/objcube.h @@ -0,0 +1,29 @@ +/* objcube.h - structure values for cube */ + +{ "cube", "cube", /* long and short names */ + "octahedron", /* long name of dual */ + 8, 12, 6, /* number of vertices, edges, and faces */ + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ +#define T 0.577 + { T, T, T }, + { T, T, -T }, + { T, -T, -T }, + { T, -T, T }, + { -T, T, T }, + { -T, T, -T }, + { -T, -T, -T }, + { -T, -T, T }, +#undef T + }, + { /* faces (numfaces + indexes into vertices) */ + /* faces must be specified clockwise from the outside */ + 4, 0, 1, 2, 3, + 4, 7, 6, 5, 4, + 4, 1, 0, 4, 5, + 4, 3, 2, 6, 7, + 4, 2, 1, 5, 6, + 4, 0, 3, 7, 4, + } +}, /* leave a comma to separate from the next include file */ +/* end */ diff --git a/objico.h b/objico.h new file mode 100644 index 0000000..7ca56ae --- /dev/null +++ b/objico.h @@ -0,0 +1,45 @@ +/* objico.h - structure values for icosahedron */ + +{ "icosahedron", "ico", /* long and short names */ + "dodecahedron", /* long name of dual */ + 12, 30, 20, /* number of vertices, edges, and faces */ + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ + { 0.00000000, 0.00000000, -0.95105650}, + { 0.00000000, 0.85065080, -0.42532537}, + { 0.80901698, 0.26286556, -0.42532537}, + { 0.50000000, -0.68819095, -0.42532537}, + {-0.50000000, -0.68819095, -0.42532537}, + {-0.80901698, 0.26286556, -0.42532537}, + { 0.50000000, 0.68819095, 0.42532537}, + { 0.80901698, -0.26286556, 0.42532537}, + { 0.00000000, -0.85065080, 0.42532537}, + {-0.80901698, -0.26286556, 0.42532537}, + {-0.50000000, 0.68819095, 0.42532537}, + { 0.00000000, 0.00000000, 0.95105650} + }, + { /* faces (numfaces + indexes into vertices) */ + /* faces must be specified clockwise from the outside */ + 3, 0, 2, 1, + 3, 0, 3, 2, + 3, 0, 4, 3, + 3, 0, 5, 4, + 3, 0, 1, 5, + 3, 1, 6, 10, + 3, 1, 2, 6, + 3, 2, 7, 6, + 3, 2, 3, 7, + 3, 3, 8, 7, + 3, 3, 4, 8, + 3, 4, 9, 8, + 3, 4, 5, 9, + 3, 5, 10, 9, + 3, 5, 1, 10, + 3, 10, 6, 11, + 3, 6, 7, 11, + 3, 7, 8, 11, + 3, 8, 9, 11, + 3, 9, 10, 11 + } +}, /* leave a comma to separate from the next include file */ +/* end */ diff --git a/objocta.h b/objocta.h new file mode 100644 index 0000000..80521d3 --- /dev/null +++ b/objocta.h @@ -0,0 +1,29 @@ +/* objocta.h - structure values for octahedron */ + +{ "octahedron", "octa", /* long and short names */ + "cube", /* long name of dual */ + 6, 12, 8, /* number of vertices, edges, and faces */ + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ +#define T 1.0 + { T, 0, 0 }, + { -T, 0, 0 }, + { 0, T, 0 }, + { 0, -T, 0 }, + { 0, 0, T }, + { 0, 0, -T }, +#undef T + }, + { /* faces (numfaces + indexes into vertices) */ + /* faces must be specified clockwise from the outside */ + 3, 0, 4, 2, + 3, 0, 2, 5, + 3, 0, 5, 3, + 3, 0, 3, 4, + 3, 1, 2, 4, + 3, 1, 5, 2, + 3, 1, 3, 5, + 3, 1, 4, 3, + } +}, /* leave a comma to separate from the next include file */ +/* end */ diff --git a/objplane.h b/objplane.h new file mode 100644 index 0000000..ce5b4e0 --- /dev/null +++ b/objplane.h @@ -0,0 +1,20 @@ +/* objplane.h - structure values for plane */ + +{ "plane", "plane", /* long and short names */ + "cube", /* long name of dual */ + 4, 4, 1, /* number of vertices, edges, and faces */ + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ +#define T 1.0 + { T, 0, 0 }, + { -T, 0, 0 }, + { 0, T, 0 }, + { 0, -T, 0 }, +#undef T + }, + { /* faces (numfaces + indexes into vertices) */ + /* faces must be specified clockwise from the outside */ + 4, 0, 2, 1, 3, + } +}, /* leave a comma to separate from the next include file */ +/* end */ diff --git a/objpyr.h b/objpyr.h new file mode 100644 index 0000000..5ea163e --- /dev/null +++ b/objpyr.h @@ -0,0 +1,30 @@ +/* objpyr.h - structure values for pyramid */ + +{ "pyramid", "pyramid", /* long and short names */ + "cube", /* long name of dual */ + 5, 8, 5, /* number of vertices, edges, and faces */ + { /* vertices (x,y,z) */ + /* all points must be within radius 1 of the origin */ +#define T 1.0 + { T, 0, 0 }, + { -T, 0, 0 }, + { 0, T, 0 }, + { 0, -T, 0 }, + { 0, 0, T }, + /* { 0, 0, -T }, */ +#undef T + }, + { /* faces (numfaces + indexes into vertices) */ + /* faces must be specified clockwise from the outside */ + 3, 0, 4, 2, + /* 3, 0, 2, 5, */ + /* 3, 0, 5, 3, */ + 3, 0, 3, 4, + 3, 1, 2, 4, + /* 3, 1, 5, 2, */ + /* 3, 1, 3, 5, */ + 3, 1, 4, 3, + 4, 0, 2, 1, 3, + } +}, /* leave a comma to separate from the next include file */ +/* end */ diff --git a/polyinfo.h b/polyinfo.h new file mode 100644 index 0000000..cc79271 --- /dev/null +++ b/polyinfo.h @@ -0,0 +1,31 @@ +/* polyinfo.h + * This is the description of one polyhedron file + */ +/* $XFree86: xc/programs/ico/polyinfo.h,v 1.3 2000/02/17 14:00:32 dawes Exp $ */ + +#define MAXVERTS 120 + /* great rhombicosidodecahedron has 120 vertices */ +#define MAXNV MAXVERTS +#define MAXFACES 30 + /* (hexakis icosahedron has 120 faces) */ +#define MAXEDGES 180 + /* great rhombicosidodecahedron has 180 edges */ +#define MAXEDGESPERPOLY 20 + +typedef struct { + double x, y, z; +} Point3D; + +/* structure of the include files which define the polyhedra */ +typedef struct { + const char *longname; /* long name of object */ + const char *shortname; /* short name of object */ + const char *dual; /* long name of dual */ + int numverts; /* number of vertices */ + int numedges; /* number of edges */ + int numfaces; /* number of faces */ + Point3D v[MAXVERTS]; /* the vertices */ + int f[MAXEDGES*2+MAXFACES]; /* the faces */ +} Polyinfo; + +/* end */ |