home *** CD-ROM | disk | FTP | other *** search
/ Teach Yourself Game Programming in 21 Days / TYGAMES_R.ISO / source / day_05 / polydemo.c < prev    next >
Text File  |  1994-06-13  |  22KB  |  971 lines

  1.  
  2. // I N C L U D E S ///////////////////////////////////////////////////////////
  3.  
  4. #include <io.h>
  5. #include <conio.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <dos.h>
  9. #include <bios.h>
  10. #include <fcntl.h>
  11. #include <memory.h>
  12. #include <malloc.h>
  13. #include <math.h>
  14. #include <string.h>
  15.  
  16. #include "graph3.h"  // include our graphics stuff
  17. #include "graph4.h"
  18.  
  19. // D E F I N E S /////////////////////////////////////////////////////////////
  20.  
  21. // global clipping region default value
  22.  
  23. #define POLY_CLIP_MIN_X   (160-30)
  24. #define POLY_CLIP_MIN_Y   (100-30)
  25.  
  26. #define POLY_CLIP_MAX_X   (160+30)
  27. #define POLY_CLIP_MAX_Y   (100+30)
  28.  
  29. #define MAX_VERTICES          16   // maximum numbr of vertices in a polygon
  30.  
  31. // S T R U C T U R E S ///////////////////////////////////////////////////////
  32.  
  33. typedef struct vertex_typ
  34.         {
  35.  
  36.         float x,y;        // the vertex in 2-D
  37.  
  38.         } vertex, *vertex_ptr;
  39.  
  40. //////////////////////////////////////////////////////////////////////////////
  41.  
  42. typedef struct polygon_typ
  43.         {
  44.  
  45.         int b_color;                    // border color
  46.         int i_color;                    // interior color
  47.         int closed;                     // is the polygon closed
  48.         int filled;                     // is this polygon filled
  49.  
  50.  
  51.         int lxo,lyo;                    // local origin of polygon
  52.         int num_vertices;               // number of defined vertices
  53.         vertex vertices[MAX_VERTICES];  // the vertices of the polygon
  54.  
  55.         } polygon, *polygon_ptr;
  56.  
  57. // P R O T O T Y P E S ///////////////////////////////////////////////////////
  58.  
  59. void Bline(int xo, int yo, int x1,int y1, unsigned char color);
  60.  
  61. // G L O B A L S  ////////////////////////////////////////////////////////////
  62.  
  63.  
  64. float sin_look[361],   // look up tables for sin and cosine
  65.       cos_look[361];
  66.  
  67. // the clipping region, set it to default on start up
  68.  
  69. int poly_clip_min_x = POLY_CLIP_MIN_X,
  70.     poly_clip_min_y = POLY_CLIP_MIN_Y,
  71.  
  72.     poly_clip_max_x = POLY_CLIP_MAX_X,
  73.     poly_clip_max_y = POLY_CLIP_MAX_Y;
  74.  
  75.  
  76. // F U N C T I O N S /////////////////////////////////////////////////////////
  77.  
  78. void Create_Tables()
  79. {
  80. // this function creates the sin and cosine lookup tables
  81.  
  82. int index;
  83.  
  84. // create the tables
  85.  
  86. for (index=0; index<=360; index++)
  87.     {
  88.  
  89.     cos_look[index] = (float)cos((double)(index*3.14159/180));
  90.     sin_look[index] = (float)sin((double)(index*3.14159/180));
  91.  
  92.     } // end for
  93.  
  94. } // end Create_Tables
  95.  
  96. //////////////////////////////////////////////////////////////////////////////
  97.  
  98. void Rotate_Polygon(polygon_ptr poly, int angle)
  99. {
  100.  
  101. int index;    // loop index
  102.  
  103. float si,cs,  // values of sin and cosine
  104.       rx,ry;  // roated points
  105.  
  106. // rotate each point of the poly gon around its local origin
  107. // note that angle is an integer and ranges from -360 to +360
  108.  
  109. // compute sin and cos of angle to be rotated
  110.  
  111. if (angle>=0)
  112.    {
  113.    // extract sin and cosine from look up table
  114.  
  115.    si = sin_look[angle];
  116.    cs = cos_look[angle];
  117.  
  118.  
  119.    } // end if positive angle
  120. else
  121.    {
  122.    // angle is negative to convert to positive
  123.  
  124.    // convert negative angle to positive angle and extract values
  125.  
  126.    si = sin_look[angle+360];
  127.    cs = cos_look[angle+360];
  128.  
  129.    } // end else
  130.  
  131. // using values for sin and cosine rotate the point
  132.  
  133. for (index=0; index<poly->num_vertices; index++)
  134.     {
  135.     // compute rotated values using rotation eqns.
  136.  
  137.     rx  = poly->vertices[index].x * cs -  poly->vertices[index].y * si;
  138.     ry  = poly->vertices[index].y * cs +  poly->vertices[index].x * si;
  139.  
  140.     // store the rotated vertex back into structure
  141.  
  142.     poly->vertices[index].x = rx;
  143.     poly->vertices[index].y = ry;
  144.  
  145.     } // end for
  146.  
  147. } // end Rotate_Polygon
  148.  
  149. ///////////////////////////////////////////////////////////////////////////////
  150.  
  151. void Scale_Polygon(polygon_ptr poly, float scale)
  152. {
  153.  
  154. int index;
  155.  
  156. // scale each vertex of the polygon
  157.  
  158. for (index=0; index<poly->num_vertices; index++)
  159.     {
  160.     // multiply by the scaling factor
  161.  
  162.     poly->vertices[index].x*=scale;
  163.     poly->vertices[index].y*=scale;
  164.  
  165.     } // end for
  166.  
  167. } // end Scale_Polygon
  168.  
  169. ///////////////////////////////////////////////////////////////////////////////
  170.  
  171. void Translate_Polygon(polygon_ptr poly, int dx,int dy)
  172. {
  173.  
  174. // translate the origin of the polygon
  175.  
  176. poly->lxo+=dx;
  177. poly->lyo+=dy;
  178.  
  179. // that was easy!
  180.  
  181. } // end Translate_Polygon
  182.  
  183. ///////////////////////////////////////////////////////////////////////////////
  184.  
  185. void Draw_Polygon(polygon_ptr poly)
  186. {
  187. // this function draws a polygon on the screen without clipping
  188. // caller should make sure that vertices are within bounds of clipping
  189. // rectangle, also the polygon will always be unfilled regardless
  190. // of the fill flag
  191.  
  192. int index,xo,yo;
  193.  
  194. // extract local origin
  195.  
  196. xo = poly->lxo;
  197. yo = poly->lyo;
  198.  
  199. // draw polygon
  200.  
  201. for (index=0; index<poly->num_vertices-1; index++)
  202.     {
  203.  
  204.     Bline(xo+(int)poly->vertices[index].x,yo+(int)poly->vertices[index].y,
  205.           xo+(int)poly->vertices[index+1].x,yo+(int)poly->vertices[index+1].y,
  206.           poly->b_color);
  207.  
  208.     } // end for index
  209.  
  210.     // close polygon?
  211.  
  212.     if (!poly->closed)
  213.        return;
  214.  
  215.     Bline(xo+(int)poly->vertices[index].x,yo+(int)poly->vertices[index].y,
  216.           xo+(int)poly->vertices[0].x,yo+(int)poly->vertices[0].y,
  217.           poly->b_color);
  218.  
  219.  
  220. } // end Draw_Polygon
  221.  
  222. //////////////////////////////////////////////////////////////////////////////
  223.  
  224. int Clip_Line(int *x1,int *y1,int *x2, int *y2)
  225. {
  226. // this function clips the sent line using the globally defined clipping
  227. // region
  228.  
  229. int point_1 = 0, point_2 = 0;  // tracks if each end point is visible or invisible
  230.  
  231. int clip_always = 0;           // used for clipping override
  232.  
  233. int xi,yi;                     // point of intersection
  234.  
  235. int right_edge=0,              // which edges are the endpoints beyond
  236.     left_edge=0,
  237.     top_edge=0,
  238.     bottom_edge=0;
  239.  
  240.  
  241. int success = 0;               // was there a successfull clipping
  242.  
  243. float dx,dy;                   // used to holds slope deltas
  244.  
  245. // SECTION 1 //////////////////////////////////////////////////////////////////
  246.  
  247. // test if line is completely visible
  248.  
  249. if ( (*x1>=poly_clip_min_x) && (*x1<=poly_clip_max_x) &&
  250.      (*y1>=poly_clip_min_y) && (*y1<=poly_clip_max_y) )
  251.      point_1 = 1;
  252.  
  253.  
  254. if ( (*x2>=poly_clip_min_x) && (*x2<=poly_clip_max_x) &&
  255.      (*y2>=poly_clip_min_y) && (*y2<=poly_clip_max_y) )
  256.      point_2 = 1;
  257.  
  258. // SECTION 2 /////////////////////////////////////////////////////////////////
  259.  
  260. // test endpoints
  261.  
  262. if (point_1==1 && point_2==1)
  263.    return(1);
  264.  
  265. // SECTION 3 /////////////////////////////////////////////////////////////////
  266.  
  267. // test if line is completely invisible
  268.  
  269. if (point_1==0 && point_2==0)
  270.    {
  271.  
  272.    // must test to see if each endpoint is on the same side of one of
  273.    // the bounding planes created by each clipping region boundary
  274.  
  275.    if ( ((*x1<poly_clip_min_x) && (*x2<poly_clip_min_x)) || // to the left
  276.         ((*x1>poly_clip_max_x) && (*x2>poly_clip_max_x)) || // to the right
  277.  
  278.         ((*y1<poly_clip_min_y) && (*y2<poly_clip_min_y)) || // above
  279.         ((*y1>poly_clip_max_y) && (*y2>poly_clip_max_y)) )  // below
  280.         {
  281.  
  282.         // no need to draw line
  283.  
  284.         return(0);
  285.  
  286.         } // end if invisible
  287.  
  288.    // if we got here we have the special case where the line cuts into and
  289.    // out of the clipping region
  290.  
  291.    clip_always = 1;
  292.  
  293.    } // end if test for invisibly
  294.  
  295. // SECTION 4 /////////////////////////////////////////////////////////////////
  296.  
  297. // take care of case where either endpoint is in clipping region
  298.  
  299. if (( point_1==1) || (point_1==0 && point_2==0) )
  300.    {
  301.  
  302.    // compute deltas
  303.  
  304.    dx = *x2 - *x1;
  305.    dy = *y2 - *y1;
  306.  
  307.    // compute what boundary line need to be clipped against
  308.  
  309.    if (*x2 > poly_clip_max_x)
  310.       {
  311.       // flag right edge
  312.  
  313.       right_edge = 1;
  314.  
  315.       // compute intersection with right edge
  316.  
  317.       if (dx!=0)
  318.          yi = (int)(.5 + (dy/dx) * (poly_clip_max_x - *x1) + *y1);
  319.       else
  320.          yi = -1;  // invalidate intersection
  321.  
  322.       } // end if to right
  323.    else
  324.    if (*x2 < poly_clip_min_x)
  325.       {
  326.       // flag left edge
  327.  
  328.       left_edge = 1;
  329.  
  330.       // compute intersection with left edge
  331.  
  332.       if (dx!=0)
  333.          yi = (int)(.5 + (dy/dx) * (poly_clip_min_x - *x1) + *y1);
  334.       else
  335.          yi = -1;  // invalidate intersection
  336.  
  337.       } // end if to left
  338.  
  339.    // horizontal intersections
  340.  
  341.    if (*y2 > poly_clip_max_y)
  342.       {
  343.       // flag bottom edge
  344.  
  345.       bottom_edge = 1;
  346.  
  347.       // compute intersection with right edge
  348.  
  349.       if (dy!=0)
  350.          xi = (int)(.5 + (dx/dy) * (poly_clip_max_y - *y1) + *x1);
  351.       else
  352.          xi = -1;  // invalidate inntersection
  353.  
  354.       } // end if bottom
  355.    else
  356.    if (*y2 < poly_clip_min_y)
  357.       {
  358.       // flag top edge
  359.  
  360.       top_edge = 1;
  361.  
  362.       // compute intersection with top edge
  363.  
  364.       if (dy!=0)
  365.          xi = (int)(.5 + (dx/dy) * (poly_clip_min_y - *y1) + *x1);
  366.       else
  367.          xi = -1;  // invalidate inntersection
  368.  
  369.       } // end if top
  370.  
  371. // SECTION 5 /////////////////////////////////////////////////////////////////
  372.  
  373.    // now we know where the line passed thru
  374.    // compute which edge is the proper intersection
  375.  
  376.    if (right_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  377.       {
  378.  
  379.       *x2 = poly_clip_max_x;
  380.       *y2 = yi;
  381.  
  382.       success = 1;
  383.  
  384.       } // end if intersected right edge
  385.    else
  386.    if (left_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  387.       {
  388.  
  389.       *x2 = poly_clip_min_x;
  390.       *y2 = yi;
  391.  
  392.       success = 1;
  393.  
  394.       } // end if intersected left edge
  395.  
  396.    if (bottom_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  397.       {
  398.  
  399.       *x2 = xi;
  400.       *y2 = poly_clip_max_y;
  401.  
  402.       success = 1;
  403.  
  404.       } // end if intersected bottom edge
  405.    else
  406.    if (top_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  407.       {
  408.  
  409.       *x2 = xi;
  410.       *y2 = poly_clip_min_y;
  411.  
  412.       success = 1;
  413.  
  414.       } // end if intersected top edge
  415.  
  416.    } // end if point_1 is visible
  417.  
  418. // SECTION 6 /////////////////////////////////////////////////////////////////
  419.  
  420. // reset edge flags
  421.  
  422. right_edge = left_edge= top_edge = bottom_edge = 0;
  423.  
  424. // test second endpoint
  425.  
  426. if ( (point_2==1) || (point_1==0 && point_2==0))
  427.    {
  428.  
  429.    // compute deltas
  430.  
  431.    dx = *x1 - *x2;
  432.    dy = *y1 - *y2;
  433.  
  434.    // compute what boundary line need to be clipped against
  435.  
  436.    if (*x1 > poly_clip_max_x)
  437.       {
  438.       // flag right edge
  439.  
  440.       right_edge = 1;
  441.  
  442.       // compute intersection with right edge
  443.  
  444.       if (dx!=0)
  445.          yi = (int)(.5 + (dy/dx) * (poly_clip_max_x - *x2) + *y2);
  446.       else
  447.          yi = -1;  // invalidate inntersection
  448.  
  449.       } // end if to right
  450.    else
  451.    if (*x1 < poly_clip_min_x)
  452.       {
  453.       // flag left edge
  454.  
  455.       left_edge = 1;
  456.  
  457.       // compute intersection with left edge
  458.  
  459.       if (dx!=0)
  460.          yi = (int)(.5 + (dy/dx) * (poly_clip_min_x - *x2) + *y2);
  461.       else
  462.          yi = -1;  // invalidate intersection
  463.  
  464.       } // end if to left
  465.  
  466.    // horizontal intersections
  467.  
  468.    if (*y1 > poly_clip_max_y)
  469.       {
  470.       // flag bottom edge
  471.  
  472.       bottom_edge = 1;
  473.  
  474.       // compute intersection with right edge
  475.  
  476.       if (dy!=0)
  477.          xi = (int)(.5 + (dx/dy) * (poly_clip_max_y - *y2) + *x2);
  478.       else
  479.          xi = -1;  // invalidate inntersection
  480.  
  481.       } // end if bottom
  482.    else
  483.    if (*y1 < poly_clip_min_y)
  484.       {
  485.       // flag top edge
  486.  
  487.       top_edge = 1;
  488.  
  489.       // compute intersection with top edge
  490.  
  491.       if (dy!=0)
  492.          xi = (int)(.5 + (dx/dy) * (poly_clip_min_y - *y2) + *x2);
  493.       else
  494.          xi = -1;  // invalidate inntersection
  495.  
  496.       } // end if top
  497.  
  498.    // now we know where the line passed thru
  499.    // compute which edge is the proper intersection
  500.  
  501.    if (right_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  502.       {
  503.  
  504.       *x1 = poly_clip_max_x;
  505.       *y1 = yi;
  506.  
  507.       success = 1;
  508.  
  509.       } // end if intersected right edge
  510.    else
  511.    if (left_edge==1 && (yi>=poly_clip_min_y && yi<=poly_clip_max_y) )
  512.       {
  513.  
  514.       *x1 = poly_clip_min_x;
  515.       *y1 = yi;
  516.  
  517.       success = 1;
  518.  
  519.       } // end if intersected left edge
  520.  
  521.    if (bottom_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  522.       {
  523.  
  524.       *x1 = xi;
  525.       *y1 = poly_clip_max_y;
  526.  
  527.       success = 1;
  528.  
  529.       } // end if intersected bottom edge
  530.    else
  531.    if (top_edge==1 && (xi>=poly_clip_min_x && xi<=poly_clip_max_x) )
  532.       {
  533.  
  534.       *x1 = xi;
  535.       *y1 = poly_clip_min_y;
  536.  
  537.       success = 1;
  538.  
  539.       } // end if intersected top edge
  540.  
  541.  
  542.    } // end if point_2 is visible
  543.  
  544. // SECTION 7 /////////////////////////////////////////////////////////////////
  545.  
  546. return(success);
  547.  
  548. } // end Clip_Line
  549.  
  550. //////////////////////////////////////////////////////////////////////////////
  551.  
  552. void Draw_Polygon_Clip(polygon_ptr poly)
  553. {
  554.  
  555. // this function draws a polygon on the screen with clipping
  556. // also the polygon will always be unfilled regardless
  557. // of the fill flag in the polygon structure
  558.  
  559. int index,  // loop index
  560.     xo,yo,  // local origin
  561.     x1,y1,  // end points of current line being processed
  562.     x2,y2;
  563.  
  564. // extract local origin
  565.  
  566. xo = poly->lxo;
  567. yo = poly->lyo;
  568.  
  569. // draw polygon
  570.  
  571. for (index=0; index<poly->num_vertices-1; index++)
  572.     {
  573.  
  574.     // extract the line
  575.  
  576.     x1 = (int)poly->vertices[index].x+xo;
  577.     y1 = (int)poly->vertices[index].y+yo;
  578.  
  579.     x2 = (int)poly->vertices[index+1].x+xo;
  580.     y2 = (int)poly->vertices[index+1].y+yo;
  581.  
  582.     // clip line to viewing screen and draw unless line is totally invisible
  583.  
  584.     if (Clip_Line(&x1,&y1,&x2,&y2))
  585.        {
  586.        // line was clipped and now can be drawn
  587.        Bline(x1,y1,x2,y2,poly->b_color);
  588.  
  589.        } // end if draw line
  590.  
  591.     } // end for index
  592.  
  593.     // close polygon?
  594.  
  595.     if (!poly->closed)
  596.        return;
  597.  
  598.     // extract the line
  599.  
  600.     x1 = (int)poly->vertices[index].x+xo;
  601.     y1 = (int)poly->vertices[index].y+yo;
  602.  
  603.     x2 = (int)poly->vertices[0].x+xo;
  604.     y2 = (int)poly->vertices[0].y+yo;
  605.  
  606.     // clip line to viewing screen and draw unless line is totally invisible
  607.  
  608.     if (Clip_Line(&x1,&y1,&x2,&y2))
  609.        {
  610.  
  611.        // line was clipped and now can be drawn
  612.  
  613.        Bline(x1,y1,x2,y2,poly->b_color);
  614.  
  615.        } // end if draw line
  616.  
  617. } // end Draw_Polygon_Clip
  618.  
  619. //////////////////////////////////////////////////////////////////////////////
  620.  
  621. void Bline(int xo, int yo, int x1,int y1, unsigned char color)
  622. {
  623. // this function uses Bresenham's algorithm IBM (1965) to draw a line from
  624. // (xo,yo) - (x1,y1)
  625.  
  626. int dx,             // difference in x's
  627.     dy,             // difference in y's
  628.     x_inc,          // amount in pixel space to move during drawing
  629.     y_inc,          // amount in pixel space to move during drawing
  630.     error=0,        // the discriminant i.e. error i.e. decision variable
  631.     index;          // used for looping
  632.  
  633.  
  634.  
  635. unsigned char far *vb_start = video_buffer; // directly access the video
  636.                                             // buffer for speed
  637.  
  638.  
  639. // SECTION 1 /////////////////////////////////////////////////////////////////
  640.  
  641. // pre-compute first pixel address in video buffer
  642. // use shifts for multiplication
  643.  
  644.  
  645. vb_start = vb_start + ((unsigned int)yo<<6) +
  646.                       ((unsigned int)yo<<8) +
  647.                       (unsigned int)xo;
  648.  
  649. // compute deltas
  650.  
  651. dx = x1-xo;
  652. dy = y1-yo;
  653.  
  654. // SECTION 2 /////////////////////////////////////////////////////////////////
  655.  
  656. // test which direction the line is going in i.e. slope angle
  657.  
  658. if (dx>=0)
  659.    {
  660.    x_inc = 1;
  661.  
  662.    } // end if line is moving right
  663. else
  664.    {
  665.    x_inc = -1;
  666.    dx    = -dx;  // need absolute value
  667.  
  668.    } // end else moving left
  669.  
  670. // SECTION 3 /////////////////////////////////////////////////////////////////
  671.  
  672. // test y component of slope
  673.  
  674. if (dy>=0)
  675.    {
  676.    y_inc = 320; // 320 bytes per line
  677.  
  678.    } // end if line is moving down
  679. else
  680.    {
  681.    y_inc = -320;
  682.    dy    = -dy;  // need absolute value
  683.  
  684.    } // end else moving up
  685.  
  686. // SECTION 4 /////////////////////////////////////////////////////////////////
  687.  
  688. // now based on which delta is greater we can draw the line
  689.  
  690. if (dx>dy)
  691.    {
  692.  
  693.    // draw the line
  694.  
  695.    for (index=0; index<=dx; index++)
  696.        {
  697.        // set the pixel
  698.  
  699.        *vb_start = color;
  700.  
  701.        // adjust the discriminate
  702.  
  703.        error+=dy;
  704.  
  705.        // test if error overflowed
  706.  
  707.        if (error>dx)
  708.           {
  709.  
  710.           error-=dx;
  711.  
  712.           // move to next line
  713.  
  714.           vb_start+=y_inc;
  715.  
  716.           } // end if error overflowed
  717.  
  718.        // move to the next pixel
  719.  
  720.        vb_start+=x_inc;
  721.  
  722.        } // end for
  723.  
  724.    } // end if |slope| <= 1
  725. else
  726.    {
  727.  
  728. // SECTION 5 /////////////////////////////////////////////////////////////////
  729.  
  730.    // draw the line
  731.  
  732.    for (index=0; index<=dy; index++)
  733.        {
  734.        // set the pixel
  735.  
  736.        *vb_start = color;
  737.  
  738.        // adjust the discriminate
  739.  
  740.        error+=dx;
  741.  
  742.        // test if error overflowed
  743.  
  744.        if (error>0)
  745.           {
  746.  
  747.           error-=dy;
  748.  
  749.           // move to next line
  750.  
  751.           vb_start+=x_inc;
  752.  
  753.           } // end if error overflowed
  754.  
  755.        // move to the next pixel
  756.  
  757.        vb_start+=y_inc;
  758.  
  759.        } // end for
  760.  
  761.    } // end else |slope| > 1
  762.  
  763. } // end Bline
  764.  
  765. ///////////////////////////////////////////////////////////////////////////////
  766.  
  767. void Draw_Boundary(int color)
  768. {
  769. // draws in the clipping boundary if user is intersted in seeing it
  770.  
  771. Bline(poly_clip_min_x,poly_clip_min_y,
  772.       poly_clip_max_x,poly_clip_min_y,color);
  773.  
  774.  
  775. Bline(poly_clip_max_x,poly_clip_min_y,
  776.       poly_clip_max_x,poly_clip_max_y,color);
  777.  
  778. Bline(poly_clip_max_x,poly_clip_max_y,
  779.       poly_clip_min_x,poly_clip_max_y,color);
  780.  
  781. Bline(poly_clip_min_x,poly_clip_max_y,
  782.       poly_clip_min_x,poly_clip_min_y,color);
  783.  
  784. } // end Draw_Boundary
  785.  
  786. // M A I N ///////////////////////////////////////////////////////////////////
  787.  
  788. void main(void)
  789. {
  790.  
  791. int clip_on = 1;       // tracks if the clipping engine is on
  792.  
  793. polygon p1;            // the working polygon
  794.  
  795. int done=0;            // system exit flag
  796.  
  797. // set video mode to 320x200 256 color mode
  798.  
  799. Set_Video_Mode(VGA256);
  800.  
  801. // draw some instructions
  802.  
  803. Blit_String(0,0 ,7,"Press Q - To quit.",1);
  804. Blit_String(0,10,7,"Press T - To toggle clipping engine.",1);
  805. Blit_String(0,20,7,"Use Numeric keypad to translate.",1);
  806.  
  807. // create lookup tables for polygon engine
  808.  
  809. Create_Tables();
  810.  
  811.  
  812. // build up a little spaceship polygon
  813.  
  814. p1.vertices[0].x = 3;
  815. p1.vertices[0].y = -19;
  816.  
  817. p1.vertices[1].x = 12;
  818. p1.vertices[1].y = -1;
  819.  
  820. p1.vertices[2].x = 17;
  821. p1.vertices[2].y = 2;
  822.  
  823. p1.vertices[3].x = 17;
  824. p1.vertices[3].y = 9;
  825.  
  826. p1.vertices[4].x = 8;
  827. p1.vertices[4].y = 14;
  828.  
  829. p1.vertices[5].x = 5;
  830. p1.vertices[5].y = 8;
  831.  
  832. p1.vertices[6].x = -5;
  833. p1.vertices[6].y = 8;
  834.  
  835. p1.vertices[7].x = -8;
  836. p1.vertices[7].y = 14;
  837.  
  838. p1.vertices[8].x = -17;
  839. p1.vertices[8].y = 9;
  840.  
  841. p1.vertices[9].x = -17;
  842. p1.vertices[9].y = 2;
  843.  
  844. p1.vertices[10].x = -12;
  845. p1.vertices[10].y = -1;
  846.  
  847. p1.vertices[11].x = -3;
  848. p1.vertices[11].y = -19;
  849.  
  850. p1.vertices[12].x = -3;
  851. p1.vertices[12].y = -8;
  852.  
  853. p1.vertices[13].x = 3;
  854. p1.vertices[13].y = -8;
  855.  
  856. // set position of shaceship
  857.  
  858. p1.lxo = 160;
  859. p1.lyo = 100;
  860.  
  861. // fill in important fields
  862.  
  863. p1.num_vertices=14;
  864. p1.b_color = 1;
  865. p1.closed=1;
  866.  
  867.  
  868. // main event loop
  869.  
  870. while(!done)
  871.      {
  872.  
  873.      // erase polygon
  874.  
  875.      p1.b_color = 0;
  876.  
  877.      if (clip_on==1)
  878.         Draw_Polygon_Clip((polygon_ptr)&p1);
  879.      else
  880.         Draw_Polygon((polygon_ptr)&p1);
  881.  
  882.      // erase the origin of polygon
  883.  
  884.      Plot_Pixel_Fast(p1.lxo,p1.lyo,0);
  885.  
  886.      // what is user doing
  887.  
  888.      if (kbhit())
  889.         {
  890.         switch(getch())
  891.               {
  892.               case '8':   // move ship left
  893.                  {
  894.                  p1.lyo--;
  895.  
  896.                  } break;
  897.  
  898.               case '2':  // move ship right
  899.                  {
  900.                  p1.lyo++;
  901.  
  902.                  } break;
  903.  
  904.               case '6':   // move ship down
  905.                  {
  906.                  p1.lxo++;
  907.  
  908.                  } break;
  909.  
  910.               case '4':   // move ship up
  911.                  {
  912.                  p1.lxo--;
  913.  
  914.                  } break;
  915.  
  916.               case 't':   // toggle clipper
  917.                    {
  918.                    clip_on=-clip_on;
  919.                    } break;
  920.  
  921.               case 'q':   // it's coming now Khan!!!
  922.                  {
  923.                  done=1;
  924.                  } break;
  925.  
  926.               default:break;
  927.  
  928.               } // end switch
  929.  
  930.         } // end if kbhit
  931.  
  932.      // rotate polygon 5 degrees
  933.  
  934.      Rotate_Polygon((polygon_ptr)&p1,5);
  935.  
  936.      // draw polygon
  937.  
  938.      if (clip_on==1)
  939.         {
  940.         p1.b_color = 1;
  941.         Draw_Polygon_Clip((polygon_ptr)&p1);
  942.         Blit_String(10,100,7,"Clipping on. ",0);
  943.         }
  944.      else
  945.         {
  946.         p1.b_color = 12;
  947.         Draw_Polygon((polygon_ptr)&p1);
  948.         Blit_String(10,100,7,"Clipping off.",0);
  949.         }
  950.  
  951.      // draw a point art origin of polygon
  952.  
  953.      Plot_Pixel_Fast(p1.lxo,p1.lyo,15);
  954.  
  955.      // let user see clipping region
  956.  
  957.      Draw_Boundary(10);
  958.  
  959.      // just chill here for 1/18.2 th of a second
  960.  
  961.      Delay(1);
  962.  
  963.      } // end while
  964.  
  965. // reset the video mode back to text
  966.  
  967. Set_Video_Mode(TEXT_MODE);
  968.  
  969. } // end main
  970.  
  971.