home *** CD-ROM | disk | FTP | other *** search
- /*
- * ico.c: hterm 'ico' screen saver
- *
- * Original: X11R3
- * Revised by HIRANO Satoshi
- *
- * Edition History:
- * 1.1 89/09/18 Halca.Hirano ported from X11R3 ico
- * ---- V2.4.0 distribution ----
- * 1.2 89/10/04 Halca.Hirano fix PC98XA color bug (old black! -> new white)
- *
- * IMPORTANT NOTE:
- * Don't use register variable since MSC5.1 optimizer becomes crazy.
- * Also don't use too complex expression.
- *
- * $Header: ico.cv 1.9 90/07/03 20:08:04 hirano Exp $
- *
- */
-
- #include "option.h"
- #ifdef ICO_SAVER
-
- #include <stdio.h>
- #include "config.h"
- #include "hterm.h"
- #include "default.h"
- #include "global.h"
- #include "graph.h"
- #ifdef __TURBOC__
- #include <mem.h>
- #else
- #include <memory.h>
- #endif
-
- typedef double Transform3D[4][4];
-
- #define WIN_SIZE_W 500
- #define WIN_SIZE_H 500
- #define ICO_SIZE 100
- #define DELTA_X 13
- #define DELTA_Y 9
- #define SPEED 1
- #define ITER 500
-
- #define MAXVERTS 15 /* icosahedron is 12. original is 120 */
- /* great rhombicosidodecahedron has 120 vertices */
- #define MAXNV MAXVERTS
- #define MAXFACES 20 /* icosahedron is 20. original is 30 */
- /* (hexakis icosahedron has 120 faces) */
- #define MAXEDGES 30 /* icosahedron is 30. original is 180 */
- /* great rhombicosidodecahedron has 180 edges */
-
- typedef struct {
- double x, y, z;
- } Point3D;
-
- typedef struct {
- int x, y;
- } Point;
-
- typedef struct {
- int x1, y1, x2, y2;
- } Segment;
-
- /* structure of the include files which define the polyhedra */
- typedef struct {
- 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;
-
- Polyinfo polys[] = {
-
- /*
- * plane
- */
- {
- 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 */
-
- /*
- * pyramid
- */
-
- {
- 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 },
- #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 */
-
- /*
- * cube
- */
- {
- 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 */
-
- /*
- * octahedron
- */
- {
- 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 */
-
- /*
- * icosahedron
- */
- {
- 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
- }
- },
-
- /*
- * make your own special shape.
- * CAUTION MAXVERTS,...
- */
- };
-
- static int polysize = sizeof(polys)/sizeof(polys[0]);
- static int initialized = 0;
-
- icoSaver()
- {
- int winW, winH;
- Polyinfo *poly; /* the poly to draw */
- int icoX, icoY;
- int icoDeltaX, icoDeltaY;
- int icoW, icoH;
- int i, j, speed;
-
- winW = WIN_SIZE_W;
- winH = WIN_SIZE_H;
-
- plot_space(0,0,winW,winH);
- plot_erase();
- plot_colormod(WHITE);
- #ifdef ICO_DEBUG
- textCRTOnOff(YES);
- #endif /* ICO_DEBUG */
-
- /* Get the initial position, size, and speed of the bounding-box: */
-
- icoW = icoH = ICO_SIZE;
- icoX = ((long)(winW - icoW) * (timerValue & 0xFF)) >> 8;
- icoY = ((long)(winH - icoH) * (timerValue & 0xFF)) >> 8;
- icoDeltaX = DELTA_X;
- icoDeltaY = DELTA_Y;
-
- /*
- * Bounce the box
- */
- j = 0;
- for (;;) {
- int prevX;
- int prevY;
-
- poly = polys+j;
- if (++j >= polysize)
- j = 0;
- initialized = 0;
- for (i = 0; i < ITER; i++) {
- if (checkEvent()) {
- plot_erase();
- return;
- }
- prevX = icoX;
- prevY = icoY;
-
- icoX += icoDeltaX;
- if (icoX < 0 || icoX + icoW > winW) {
- icoX -= (icoDeltaX << 1);
- icoDeltaX = - icoDeltaX;
- }
- icoY += icoDeltaY;
- if (icoY < 0 || icoY + icoH > winH) {
- icoY -= (icoDeltaY << 1);
- icoDeltaY = - icoDeltaY;
- }
- drawPoly(poly, icoX, icoY, icoW, icoH, prevX, prevY);
- for (speed = 0; speed < SPEED; speed++)
- nullFunction();
- }
- }
- }
-
- /******************************************************************************
- * Description
- * Undraw previous polyhedron (by erasing its bounding box).
- * Rotate and draw the new polyhedron.
- *
- * Input
- * poly the polyhedron to draw
- * icoX, icoY position of upper left of bounding-box
- * icoW, icoH size of bounding-box
- * prevX, prevY position of previous bounding-box
- *****************************************************************************/
-
- drawPoly(poly, icoX, icoY, icoW, icoH, prevX, prevY)
- Polyinfo *poly;
- int icoX, icoY, icoW, icoH;
- int prevX, prevY;
- {
- Point3D *v = poly->v;
- int *f = poly->f;
- int NV = poly->numverts;
- int NF = poly->numfaces;
-
- static Transform3D xform;
- static Point3D xv[2][MAXNV];
- static char drawn[MAXNV][MAXNV];
- static int buffer;
- int p0;
- int p1;
- Point *pv2;
- Segment *pe;
- Point3D *pxv;
- static double wo2, ho2;
- static Point v2[MAXNV];
- static Segment edges[MAXEDGES];
- int i;
- int j,k, n;
- int *pf;
- int pcount;
- double pxvz;
-
- /* Set up points, transforms, etc.: */
-
- if (!initialized) {
- Transform3D r1;
- Transform3D r2;
-
- FormatRotateMat('x', 5 * 3.1416 / 180.0, r1);
- FormatRotateMat('y', 5 * 3.1416 / 180.0, r2);
- FormatRotateMat('z', 3 * 3.1416 / 180.0, r2);
- ConcatMat(r1, r2, xform);
- memcpy((char *) xv[0], (char *) v, NV * sizeof(Point3D));
- #ifdef ICO_DEBUG
- dmat4("xform", xform);
- dmat3("xv[0]", xv[0]);
- dmat3("v", v);
- #endif /* ICO_DEBUG */
- buffer = 0;
-
- wo2 = icoW / 2.0;
- ho2 = icoH / 2.0;
-
- initialized = 1;
- }
-
-
- /* Switch double-buffer and rotate vertices: */
-
- buffer = !buffer;
- PartialNonHomTransform(NV, xform, xv[!buffer], xv[buffer]);
- #ifdef ICO_DEBUG
- dmat3("xv[buffer]", xv[buffer]);
- #endif /* ICO_DEBUG */
-
- /* Convert 3D coordinates to 2D window coordinates: */
-
- pxv = xv[buffer];
- pv2 = v2;
- for (i = NV - 1; i >= 0; --i) {
- pv2->x = (int) ((pxv->x + 1.0) * wo2) + icoX;
- pv2->y = (int) ((pxv->y + 1.0) * ho2) + icoY;
- ++pxv;
- ++pv2;
- }
-
-
- /* Accumulate edges to be drawn, eliminating duplicates for speed: */
-
- pxv = xv[buffer];
- pv2 = v2;
- pf = f;
- pe = edges;
- memset(drawn, 0, sizeof(drawn));
-
-
- 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;
-
- for (j=0; j<pcount; j++) {
- if (j<pcount-1) k=j+1;
- else k=0;
- p0 = pf[j];
- p1 = pf[k];
- if (!drawn[p0][p1]) {
- drawn[p0][p1] = 1;
- 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 */
-
- plot_colormod(0);
- plot_boxfill(prevX, prevY, icoW + 1+prevX, icoH + 1+prevY);
- plot_colormod(7);
- for (n = 0; n < pe - edges; n++)
- plot_line(edges[n].x1, edges[n].y1, edges[n].x2, edges[n].y2);
- }
-
-
- /******************************************************************************
- * Description
- * Concatenate two 4-by-4 transformation matrices.
- *
- * Input
- * l multiplicand (left operand)
- * r multiplier (right operand)
- *
- * Output
- * *m Result matrix
- *****************************************************************************/
-
- ConcatMat(l, r, m)
- Transform3D l;
- Transform3D r;
- Transform3D m;
- {
- int i, 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
- *****************************************************************************/
-
- FormatRotateMat(axis, angle, m)
- char axis;
- double angle;
- Transform3D m;
- {
- double s, c;
- double sin(), cos();
-
- 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
- * Format a 4x4 identity matrix.
- *
- * Output
- * *m Formatted identity matrix
- *****************************************************************************/
-
- IdentMat(m)
- Transform3D m;
- {
- int i;
- int j;
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++)
- m[i][j] = 0.0;
- m[i][i] = 1.0;
- }
- }
-
-
-
- /******************************************************************************
- * 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
- *****************************************************************************/
-
- PartialNonHomTransform(n, m, in, out)
- int n;
- Transform3D m;
- Point3D *in;
- Point3D *out;
- {
- int i;
-
- for (i = 0; i < n; i++, 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];
- }
- }
-
- #ifdef ICO_DEBUG
- dmat3(name, m)
- char *name;
- Point3D *m;
- {
- int i;
- char buf[80];
-
- for (i = 0; i < 4; i++) {
- sprintf(buf, "%s[%d]: %f %f %f\n\r", name, i, m[i].x, m[i].y, m[i].z);
- conPrint(buf);
- }
- }
-
- dmat4(name, m)
- char *name;
- Transform3D m;
- {
- int i;
- char buf[80];
-
- for (i = 0; i < 4; i++) {
- sprintf(buf, "%s: %f %f %f %f\n\r", name, m[i][0],m[i][1],m[i][2],m[i][3]);
- conPrint(buf);
- }
- }
- #endif /* ICO_DEBUG */
- #endif /* ICO_SAVER */
-