home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / COMM / MISC / SRC26_2.ZIP / SRC / ICO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-13  |  13.8 KB  |  597 lines

  1. /*
  2.  * ico.c: hterm 'ico' screen saver
  3.  *
  4.  * Original: X11R3
  5.  * Revised by HIRANO Satoshi
  6.  *
  7.  * Edition History:
  8.  * 1.1 89/09/18 Halca.Hirano ported from X11R3 ico
  9.  *     ---- V2.4.0 distribution ----
  10.  * 1.2 89/10/04 Halca.Hirano fix PC98XA color bug (old black! -> new white)
  11.  *
  12.  * IMPORTANT NOTE:
  13.  *    Don't use register variable since MSC5.1 optimizer becomes crazy.
  14.  *    Also don't use too complex expression.
  15.  *
  16.  * $Header: ico.cv  1.9  90/07/03 20:08:04  hirano  Exp $
  17.  *
  18.  */
  19.  
  20. #include "option.h"
  21. #ifdef ICO_SAVER
  22.  
  23. #include <stdio.h>
  24. #include "config.h"
  25. #include "hterm.h"
  26. #include "default.h"
  27. #include "global.h"
  28. #include "graph.h"
  29. #ifdef __TURBOC__
  30. #include <mem.h>
  31. #else
  32. #include <memory.h>
  33. #endif
  34.  
  35. typedef double Transform3D[4][4];
  36.  
  37. #define WIN_SIZE_W 500
  38. #define WIN_SIZE_H    500
  39. #define ICO_SIZE    100
  40. #define DELTA_X        13
  41. #define DELTA_Y        9
  42. #define SPEED        1
  43. #define ITER        500
  44.  
  45. #define MAXVERTS 15    /* icosahedron is 12. original is 120 */
  46.             /* great rhombicosidodecahedron has 120 vertices */
  47. #define MAXNV MAXVERTS
  48. #define MAXFACES 20    /* icosahedron is 20. original is 30 */
  49.             /* (hexakis icosahedron has 120 faces) */
  50. #define MAXEDGES 30    /* icosahedron is 30. original is 180 */
  51.             /* great rhombicosidodecahedron has 180 edges */
  52.  
  53. typedef struct {
  54.     double x, y, z;
  55. } Point3D;
  56.  
  57. typedef struct {   
  58.     int x, y;
  59. } Point;
  60.  
  61. typedef struct {
  62.     int x1, y1, x2, y2;
  63. } Segment;
  64.  
  65. /* structure of the include files which define the polyhedra */
  66. typedef struct {
  67.     int numverts;        /* number of vertices */
  68.     int numedges;        /* number of edges */
  69.     int numfaces;        /* number of faces */
  70.     Point3D v[MAXVERTS];    /* the vertices */
  71.     int f[MAXEDGES*2+MAXFACES];    /* the faces */
  72. } Polyinfo;
  73.  
  74. Polyinfo polys[] = {
  75.  
  76.     /*
  77.      * plane 
  78.      */
  79.     {
  80.             4, 4, 1,        /* number of vertices, edges, and faces */
  81.             {               /* vertices (x,y,z) */
  82.                         /* all points must be within radius 1 of the origin */
  83. #define T 1.0
  84.                     {  T,  0,  0 },
  85.                     { -T,  0,  0 },
  86.                     {  0,  T,  0 },
  87.                     {  0, -T,  0 },
  88. #undef T
  89.             },
  90.             {       /* faces (numfaces + indexes into vertices) */
  91.                     /*  faces must be specified clockwise from the outside */
  92.                     4,      0, 2, 1, 3,
  93.             }
  94.     },              /* leave a comma to separate from the next include file */
  95.  
  96.     /*
  97.      * pyramid 
  98.      */
  99.  
  100.     {
  101.             5, 8, 5,        /* number of vertices, edges, and faces */
  102.             {               /* vertices (x,y,z) */
  103.                             /* all points must be within radius 1 of the origin */
  104. #define T 1.0
  105.                     {  T,  0,  0 },
  106.                     { -T,  0,  0 },
  107.                     {  0,  T,  0 },
  108.                     {  0, -T,  0 },
  109.                     {  0,  0,  T },
  110. #undef T
  111.             },
  112.             {       /* faces (numfaces + indexes into vertices) */
  113.                     /*  faces must be specified clockwise from the outside */
  114.                     3,      0, 4, 2,
  115.                     /* 3,   0, 2, 5, */
  116.                     /* 3,   0, 5, 3, */
  117.                     3,      0, 3, 4,
  118.                     3,      1, 2, 4,
  119.                     /* 3,   1, 5, 2, */
  120.                     /* 3,   1, 3, 5, */
  121.                     3,      1, 4, 3,
  122.                     4,      0, 2, 1, 3,
  123.             }
  124.     },              /* leave a comma to separate from the next include file */
  125.  
  126.     /*
  127.      *  cube 
  128.      */
  129.     {
  130.         8, 12, 6,    /* number of vertices, edges, and faces */
  131.         {        /* vertices (x,y,z) */
  132.             /* all points must be within radius 1 of the origin */
  133. #define T 0.577
  134.             {  T,  T,  T },
  135.             {  T,  T, -T },
  136.             {  T, -T, -T },
  137.             {  T, -T,  T },
  138.             { -T,  T,  T },
  139.             { -T,  T, -T },
  140.             { -T, -T, -T },
  141.             { -T, -T,  T },
  142. #undef T
  143.         },
  144.         {    /* faces (numfaces + indexes into vertices) */
  145.             /*  faces must be specified clockwise from the outside */
  146.             4,    0, 1, 2, 3,
  147.             4,     7, 6, 5, 4,
  148.             4,     1, 0, 4, 5,
  149.             4,    3, 2, 6, 7,
  150.             4,    2, 1, 5, 6,
  151.             4,    0, 3, 7, 4,
  152.         }
  153.     },        /* leave a comma to separate from the next include file */
  154.  
  155.     /*
  156.      * octahedron 
  157.      */
  158.     {
  159.         6, 12, 8,    /* number of vertices, edges, and faces */
  160.         {        /* vertices (x,y,z) */
  161.                 /* all points must be within radius 1 of the origin */
  162. #define T 1.0
  163.             {  T,  0,  0 },
  164.             { -T,  0,  0 },
  165.             {  0,  T,  0 },
  166.             {  0, -T,  0 },
  167.             {  0,  0,  T },
  168.             {  0,  0, -T },
  169. #undef T
  170.         },
  171.         {    /* faces (numfaces + indexes into vertices) */
  172.             /*  faces must be specified clockwise from the outside */
  173.             3,    0, 4, 2,
  174.             3,    0, 2, 5,
  175.             3,    0, 5, 3,
  176.             3,    0, 3, 4,
  177.             3,    1, 2, 4,
  178.             3,    1, 5, 2,
  179.             3,    1, 3, 5,
  180.             3,    1, 4, 3,
  181.         }
  182.     },        /* leave a comma to separate from the next include file */
  183.  
  184.     /*
  185.      * icosahedron 
  186.      */
  187.     {
  188.         12, 30, 20,    /* number of vertices, edges, and faces */
  189.         {        /* vertices (x,y,z) */
  190.                 /* all points must be within radius 1 of the origin */
  191.             { 0.00000000,  0.00000000, -0.95105650},
  192.             { 0.00000000,  0.85065080, -0.42532537},
  193.             { 0.80901698,  0.26286556, -0.42532537},
  194.             { 0.50000000, -0.68819095, -0.42532537},
  195.             {-0.50000000, -0.68819095, -0.42532537},
  196.             {-0.80901698,  0.26286556, -0.42532537},
  197.             { 0.50000000,  0.68819095,  0.42532537},
  198.             { 0.80901698, -0.26286556,  0.42532537},
  199.             { 0.00000000, -0.85065080,  0.42532537},
  200.             {-0.80901698, -0.26286556,  0.42532537},
  201.             {-0.50000000,  0.68819095,  0.42532537},
  202.             { 0.00000000,  0.00000000,  0.95105650}
  203.         },
  204.         {    /* faces (numfaces + indexes into vertices) */
  205.             /*  faces must be specified clockwise from the outside */
  206.              3,    0,  2,  1,
  207.              3,    0,  3,  2,
  208.              3,    0,  4,  3,
  209.              3,    0,  5,  4,
  210.              3,    0,  1,  5,
  211.              3,    1,  6, 10,
  212.              3,    1,  2,  6,
  213.              3,    2,  7,  6,
  214.              3,    2,  3,  7,
  215.              3,    3,  8,  7,
  216.              3,    3,  4,  8,
  217.              3,    4,  9,  8,
  218.              3,    4,  5,  9,
  219.              3,    5, 10,  9,
  220.              3,    5,  1, 10,
  221.              3,    10,  6, 11,
  222.              3,    6,  7, 11,
  223.              3,    7,  8, 11,
  224.              3,    8,  9, 11,
  225.              3,    9, 10, 11
  226.         }
  227.     },
  228.     
  229.     /*
  230.      * make your own special shape.
  231.      * CAUTION MAXVERTS,...
  232.      */
  233. };
  234.  
  235. static int polysize = sizeof(polys)/sizeof(polys[0]);
  236. static int initialized = 0;
  237.  
  238. icoSaver()
  239. {
  240.     int winW, winH;
  241.     Polyinfo *poly;        /* the poly to draw */
  242.     int icoX, icoY;
  243.     int icoDeltaX, icoDeltaY;
  244.     int icoW, icoH;
  245.     int i, j, speed;
  246.  
  247.     winW = WIN_SIZE_W;
  248.     winH = WIN_SIZE_H;
  249.  
  250.     plot_space(0,0,winW,winH);
  251.     plot_erase();
  252.     plot_colormod(WHITE);
  253. #ifdef ICO_DEBUG
  254.     textCRTOnOff(YES);
  255. #endif /* ICO_DEBUG */
  256.  
  257.     /* Get the initial position, size, and speed of the bounding-box: */
  258.  
  259.     icoW = icoH = ICO_SIZE;
  260.     icoX = ((long)(winW - icoW) * (timerValue & 0xFF)) >> 8;
  261.     icoY = ((long)(winH - icoH) * (timerValue & 0xFF)) >> 8;
  262.     icoDeltaX = DELTA_X;
  263.     icoDeltaY = DELTA_Y;
  264.  
  265.     /*
  266.      * Bounce the box
  267.      */
  268.     j = 0;
  269.     for (;;) {
  270.         int prevX;
  271.         int prevY;
  272.  
  273.         poly = polys+j;
  274.         if (++j >= polysize) 
  275.             j = 0;
  276.         initialized = 0;
  277.         for (i = 0; i < ITER; i++) {
  278.             if (checkEvent()) {
  279.                 plot_erase();
  280.                 return;
  281.             }
  282.             prevX = icoX;
  283.             prevY = icoY;
  284.  
  285.             icoX += icoDeltaX;
  286.             if (icoX < 0 || icoX + icoW > winW) {
  287.                 icoX -= (icoDeltaX << 1);
  288.                 icoDeltaX = - icoDeltaX;
  289.             }
  290.             icoY += icoDeltaY;
  291.             if (icoY < 0 || icoY + icoH > winH) {
  292.                 icoY -= (icoDeltaY << 1);
  293.                 icoDeltaY = - icoDeltaY;
  294.             }
  295.             drawPoly(poly, icoX, icoY, icoW, icoH, prevX, prevY);
  296.             for (speed = 0; speed < SPEED; speed++)
  297.                 nullFunction();
  298.         }
  299.     }
  300. }
  301.  
  302. /******************************************************************************
  303.  * Description
  304.  *    Undraw previous polyhedron (by erasing its bounding box).
  305.  *    Rotate and draw the new polyhedron.
  306.  *
  307.  * Input
  308.  *    poly        the polyhedron to draw
  309.  *    icoX, icoY    position of upper left of bounding-box
  310.  *    icoW, icoH    size of bounding-box
  311.  *    prevX, prevY    position of previous bounding-box
  312.  *****************************************************************************/
  313.  
  314. drawPoly(poly, icoX, icoY, icoW, icoH, prevX, prevY)
  315. Polyinfo *poly;
  316. int icoX, icoY, icoW, icoH;
  317. int prevX, prevY;
  318. {
  319.     Point3D *v = poly->v;
  320.     int *f = poly->f;
  321.     int NV = poly->numverts;
  322.     int NF = poly->numfaces;
  323.  
  324.     static Transform3D xform;
  325.     static Point3D xv[2][MAXNV];
  326.     static char drawn[MAXNV][MAXNV];
  327.     static int buffer;
  328.     int p0;
  329.     int p1;
  330.     Point *pv2;
  331.     Segment *pe;
  332.     Point3D *pxv;
  333.     static double wo2, ho2;
  334.     static Point v2[MAXNV];
  335.     static Segment edges[MAXEDGES];
  336.     int i;
  337.     int j,k, n;
  338.     int *pf;
  339.     int pcount;
  340.     double pxvz;
  341.  
  342.     /* Set up points, transforms, etc.:  */
  343.  
  344.     if (!initialized) {
  345.         Transform3D r1;
  346.         Transform3D r2;
  347.  
  348.         FormatRotateMat('x', 5 * 3.1416 / 180.0, r1);
  349.         FormatRotateMat('y', 5 * 3.1416 / 180.0, r2);
  350.         FormatRotateMat('z', 3 * 3.1416 / 180.0, r2);
  351.         ConcatMat(r1, r2, xform);
  352.         memcpy((char *) xv[0], (char *) v, NV * sizeof(Point3D));
  353. #ifdef ICO_DEBUG
  354.         dmat4("xform", xform);
  355.         dmat3("xv[0]", xv[0]);
  356.         dmat3("v", v);
  357. #endif /* ICO_DEBUG */
  358.         buffer = 0;
  359.  
  360.         wo2 = icoW / 2.0;
  361.         ho2 = icoH / 2.0;
  362.  
  363.         initialized = 1;
  364.     }
  365.  
  366.  
  367.     /* Switch double-buffer and rotate vertices: */
  368.  
  369.     buffer = !buffer;
  370.     PartialNonHomTransform(NV, xform, xv[!buffer], xv[buffer]);
  371. #ifdef ICO_DEBUG
  372.     dmat3("xv[buffer]", xv[buffer]);
  373. #endif /* ICO_DEBUG */
  374.  
  375.     /* Convert 3D coordinates to 2D window coordinates: */
  376.  
  377.     pxv = xv[buffer];
  378.     pv2 = v2;
  379.     for (i = NV - 1; i >= 0; --i) {
  380.         pv2->x = (int) ((pxv->x + 1.0) * wo2) + icoX;
  381.         pv2->y = (int) ((pxv->y + 1.0) * ho2) + icoY;
  382.         ++pxv;
  383.         ++pv2;
  384.     }
  385.  
  386.  
  387.     /* Accumulate edges to be drawn, eliminating duplicates for speed: */
  388.  
  389.     pxv = xv[buffer];
  390.     pv2 = v2;
  391.     pf = f;
  392.     pe = edges;
  393.     memset(drawn, 0, sizeof(drawn));
  394.  
  395.  
  396.     for (i = NF - 1; i >= 0; --i, pf += pcount) {
  397.         pcount = *pf++;    /* number of edges for this face */
  398.         pxvz = 0.0;
  399.         for (j=0; j<pcount; j++) {
  400.             p0 = pf[j];
  401.             pxvz += pxv[p0].z;
  402.         }
  403.  
  404.         /* If facet faces away from viewer, don't consider it: */
  405.         if (pxvz<0.0)
  406.             continue;
  407.  
  408.         for (j=0; j<pcount; j++) {
  409.             if (j<pcount-1) k=j+1;
  410.             else k=0;
  411.             p0 = pf[j];
  412.             p1 = pf[k];
  413.             if (!drawn[p0][p1]) {
  414.                 drawn[p0][p1] = 1;
  415.                 drawn[p1][p0] = 1;
  416.                 pe->x1 = pv2[p0].x;
  417.                 pe->y1 = pv2[p0].y;
  418.                 pe->x2 = pv2[p1].x;
  419.                 pe->y2 = pv2[p1].y;
  420.                 ++pe;
  421.             }
  422.         }
  423.     }
  424.  
  425.     /* Erase previous, draw current icosahedrons */
  426.  
  427.     plot_colormod(0);
  428.     plot_boxfill(prevX, prevY, icoW + 1+prevX, icoH + 1+prevY);
  429.     plot_colormod(7);
  430.     for (n = 0; n < pe - edges; n++)
  431.         plot_line(edges[n].x1, edges[n].y1, edges[n].x2, edges[n].y2);
  432. }
  433.  
  434.  
  435. /******************************************************************************
  436.  * Description
  437.  *    Concatenate two 4-by-4 transformation matrices.
  438.  *
  439.  * Input
  440.  *    l        multiplicand (left operand)
  441.  *    r        multiplier (right operand)
  442.  *
  443.  * Output
  444.  *    *m        Result matrix
  445.  *****************************************************************************/
  446.  
  447. ConcatMat(l, r, m)
  448. Transform3D l;
  449. Transform3D r;
  450. Transform3D m;
  451. {
  452.     int i, j;
  453.  
  454.     for (i = 0; i < 4; ++i)
  455.         for (j = 0; j < 4; ++j)
  456.             m[i][j] = l[i][0] * r[0][j]
  457.                 + l[i][1] * r[1][j]
  458.                 + l[i][2] * r[2][j]
  459.                 + l[i][3] * r[3][j];
  460. }
  461.  
  462.  
  463.  
  464. /******************************************************************************
  465.  * Description
  466.  *    Format a matrix that will perform a rotation transformation
  467.  *    about the specified axis.  The rotation angle is measured
  468.  *    counterclockwise about the specified axis when looking
  469.  *    at the origin from the positive axis.
  470.  *
  471.  * Input
  472.  *    axis        Axis ('x', 'y', 'z') about which to perform rotation
  473.  *    angle        Angle (in radians) of rotation
  474.  *    A        Pointer to rotation matrix
  475.  *
  476.  * Output
  477.  *    *m        Formatted rotation matrix
  478.  *****************************************************************************/
  479.  
  480. FormatRotateMat(axis, angle, m)
  481. char axis;
  482. double angle;
  483. Transform3D m;
  484. {
  485.     double s, c;
  486.     double sin(), cos();
  487.  
  488.     IdentMat(m);
  489.  
  490.     s = sin(angle);
  491.     c = cos(angle);
  492.  
  493.     switch(axis) {
  494.         case 'x':
  495.             m[1][1] = m[2][2] = c;
  496.             m[1][2] = s;
  497.             m[2][1] = -s;
  498.             break;
  499.         case 'y':
  500.             m[0][0] = m[2][2] = c;
  501.             m[2][0] = s;
  502.             m[0][2] = -s;
  503.             break;
  504.         case 'z':
  505.             m[0][0] = m[1][1] = c;
  506.             m[0][1] = s;
  507.             m[1][0] = -s;
  508.             break;
  509.     }
  510. }
  511.  
  512.  
  513.  
  514. /******************************************************************************
  515.  * Description
  516.  *    Format a 4x4 identity matrix.
  517.  *
  518.  * Output
  519.  *    *m        Formatted identity matrix
  520.  *****************************************************************************/
  521.  
  522. IdentMat(m)
  523. Transform3D m;
  524. {
  525.     int i;
  526.     int j;
  527.  
  528.     for (i = 0; i < 4; i++) {
  529.         for (j = 0; j < 4; j++)
  530.             m[i][j] = 0.0;
  531.         m[i][i] = 1.0;
  532.     }
  533. }
  534.  
  535.  
  536.  
  537. /******************************************************************************
  538.  * Description
  539.  *    Perform a partial transform on non-homogeneous points.
  540.  *    Given an array of non-homogeneous (3-coordinate) input points,
  541.  *    this routine multiplies them by the 3-by-3 upper left submatrix
  542.  *    of a standard 4-by-4 transform matrix.  The resulting non-homogeneous
  543.  *    points are returned.
  544.  *
  545.  * Input
  546.  *    n        number of points to transform
  547.  *    m        4-by-4 transform matrix
  548.  *    in        array of non-homogeneous input points
  549.  *
  550.  * Output
  551.  *    *out        array of transformed non-homogeneous output points
  552.  *****************************************************************************/
  553.  
  554. PartialNonHomTransform(n, m, in, out)
  555. int n;
  556. Transform3D m;
  557. Point3D *in;
  558. Point3D *out;
  559. {
  560.     int  i;
  561.  
  562.     for (i = 0; i < n; i++, in++, out++) {
  563.         out->x = in->x * m[0][0] + in->y * m[1][0] + in->z * m[2][0];
  564.         out->y = in->x * m[0][1] + in->y * m[1][1] + in->z * m[2][1];
  565.         out->z = in->x * m[0][2] + in->y * m[1][2] + in->z * m[2][2];
  566.     }
  567. }
  568.  
  569. #ifdef ICO_DEBUG
  570. dmat3(name, m)
  571. char *name;
  572. Point3D *m;
  573. {
  574.     int  i;
  575.     char buf[80];
  576.  
  577.     for (i = 0; i < 4; i++) {    
  578.         sprintf(buf, "%s[%d]: %f %f %f\n\r", name, i, m[i].x, m[i].y, m[i].z);
  579.         conPrint(buf);
  580.     }
  581. }
  582.         
  583. dmat4(name, m)
  584. char *name;
  585. Transform3D m;
  586. {
  587.     int  i;
  588.     char buf[80];
  589.     
  590.     for (i = 0; i < 4; i++) {
  591.         sprintf(buf, "%s: %f %f %f %f\n\r", name, m[i][0],m[i][1],m[i][2],m[i][3]);
  592.         conPrint(buf);
  593.     }
  594. }
  595. #endif /* ICO_DEBUG */
  596. #endif /* ICO_SAVER */
  597.