home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / voglw.zip / polygons.c < prev    next >
C/C++ Source or Header  |  1997-02-13  |  22KB  |  1,272 lines

  1. /*
  2.  * tmesh, and quadstrips added by
  3.  * marsh@ppdrs1.nrl.navy.mil (Spencer J. Marsh)
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "vogl.h"
  8.  
  9. static    int    sync;
  10.  
  11. extern    double    cos();
  12. extern    double    sin();
  13.  
  14. #define MAX(x, y)    ((x) > (y) ? (x) : (y))
  15. #define MIN(x, y)    ((x) < (y) ? (x) : (y))
  16. #define ABS(x)        ((x) < 0 ? -(x) : (x))
  17.  
  18. static float    F[6][4], S[6][4], I[4], p[MAXVERTS][4];
  19. static int    nout, first[6], numv;
  20. static long    polymodeflag = PYM_FILL;
  21. static int    ip1[MAXVERTS], ip2[MAXVERTS];
  22.  
  23. /*
  24.  *  Orientation of backfacing polygons(in screen coords)
  25.  */
  26. static    int    clockwise = 1;
  27.  
  28. static void    polyoutline(), polyclip(), shclip(), shclose();
  29. static int    checkbacki(), intersect(), visible();
  30.  
  31. /*
  32.  * concave
  33.  *
  34.  *    signal wether or not polygons are concave (not a lot of use at the moment).
  35.  */
  36. void
  37. concave(yesno)
  38.     Boolean    yesno;
  39. {
  40.     vdevice.concave = yesno;
  41. }
  42.  
  43. /*
  44.  * backface
  45.  *
  46.  *    Turns on culling of backfacing polygons. A polygon is
  47.  * backfacing if it's orientation in *screen* coords is clockwise.
  48.  */
  49. void
  50. backface(onoff)
  51.     int    onoff;
  52. {
  53.     vdevice.attr->a.backface = onoff;
  54.     clockwise = 1;
  55. }
  56.  
  57. /*
  58.  * frontface
  59.  *
  60.  *    Turns on culling of frontfacing polygons. A polygon is
  61.  * frontfacing if it's orientation in *screen* coords is anti-clockwise.
  62.  */
  63. void
  64. frontface(onoff)
  65.     int    onoff;
  66. {
  67.     vdevice.attr->a.backface = onoff;
  68.     clockwise = 0;
  69. }
  70.  
  71. /*
  72.  * polymode
  73.  *
  74.  *    Sets the polygon filling mode - only filled or outlined supported
  75.  */
  76. void
  77. polymode(mode)
  78.     long    mode;
  79. {
  80.     Token   *tok;
  81.  
  82.     if (!vdevice.initialised)
  83.         verror("polymode: vogl not initialised");
  84.  
  85.     if (vdevice.inobject) {
  86.         tok = newtokens(2);
  87.         tok[0].i = POLYMODE;
  88.         tok[1].i = (int)mode;
  89.         return;
  90.     }
  91. /*
  92.  * On older SGI Machines this call used to work... On the newer
  93.  * boxes it doesn't do anything. If you want the old stuff then
  94.  * #define OLD_SGI_BOXES somewhere.
  95.  */
  96. #define OLD_SGI_BOXES 1
  97. #ifdef OLD_SGI_BOXES
  98.     polymodeflag = mode;
  99. #endif
  100. }
  101.  
  102. /*
  103.  * dopoly
  104.  *
  105.  *    do a transformed polygon with n edges using fill
  106.  */
  107. static void
  108. dopoly(n)
  109.     int    n;
  110. {
  111.     int    i, sync;
  112.     char    buf[100];
  113.  
  114.     if (n > MAXVERTS) {
  115.         sprintf(buf, "dopoly: can't fill a polygon with more than %d vertices", MAXVERTS);
  116.         verror(buf);
  117.     }
  118.  
  119.     if (sync = vdevice.sync)
  120.         vdevice.sync = 0;
  121.  
  122.     if (!vdevice.clipoff) {
  123.         polyclip(n);
  124.     } else {
  125.         nout = n;
  126.         for (i = 0; i < n; i++) {
  127.             ip1[i] = WtoVx(p[i]);
  128.             ip2[i] = WtoVy(p[i]);
  129.         }
  130.     }
  131.  
  132.  
  133.     if (vdevice.attr->a.backface && checkbacki()) {
  134.         vdevice.fill = 0;
  135.         return;
  136.     }
  137.  
  138.     if (vdevice.fill) {
  139.         if (nout > 2) {
  140.             (*vdevice.dev.Vfill)(nout, ip1, ip2);
  141.         }
  142.     } else {
  143.         vdevice.cpVx = ip1[0];
  144.         vdevice.cpVy = ip2[0];
  145.         vdevice.cpVvalid = 0;
  146.         polyoutline(nout, ip1, ip2);
  147.     }
  148.  
  149.     if (sync) {
  150.         vdevice.sync = 1;
  151.         (*vdevice.dev.Vsync)();
  152.     }
  153.  
  154.     vdevice.fill = 0;
  155. }
  156.  
  157. /*
  158.  * polyoutline
  159.  *
  160.  *    draws a polygon outline from already transformed points.
  161.  */
  162. static void
  163. polyoutline(n, ipx, ipy)
  164.     int    n;
  165.     int    ipx[], ipy[];
  166. {
  167.     int    i;
  168.  
  169.     if (n > 2) {
  170.         for (i = 1; i < n; i++) {
  171.             (*vdevice.dev.Vdraw)(ipx[i], ipy[i]);
  172.  
  173.             vdevice.cpVx = ipx[i];
  174.             vdevice.cpVy = ipy[i];
  175.         }
  176.         (*vdevice.dev.Vdraw)(ipx[0], ipy[0]);
  177.  
  178.         vdevice.cpVx = ipx[0];
  179.         vdevice.cpVy = ipy[0];
  180.     }
  181. }
  182.  
  183. /*
  184.  * polyobj
  185.  *
  186.  *    construct a polygon from a object token list.
  187.  */
  188. void
  189. polyobj(n, dp, fill)
  190.     int    n;
  191.     Token    dp[];
  192.     int    fill;
  193. {
  194.     int    i, j;
  195.     float    vect[4], result[4];
  196.     
  197.     for (i = 0, j = 0; i < n; i++, j += 3) {
  198.         vect[V_X] = dp[j + V_X].f;
  199.         vect[V_Y] = dp[j + V_Y].f;
  200.         vect[V_Z] = dp[j + V_Z].f;
  201.         vect[V_W] = 1;
  202.         multvector(result, vect, vdevice.transmat->m);
  203.         p[i][V_X] = result[V_X];
  204.         p[i][V_Y] = result[V_Y];
  205.         p[i][V_Z] = result[V_Z];
  206.         p[i][V_W] = result[V_W];
  207.     }
  208.  
  209.     if (fill)
  210.         vdevice.fill = polymodeflag;
  211.     else
  212.         vdevice.fill = 0;
  213.  
  214.     dopoly(n);
  215.  
  216.     vdevice.cpW[V_X] = dp[V_X].f;
  217.     vdevice.cpW[V_Y] = dp[V_Y].f;
  218.     vdevice.cpW[V_Z] = dp[V_Z].f;
  219. }
  220.  
  221. /*
  222.  * poly2
  223.  *
  224.  *    construct a polygon from an (x, y) array of points provided by the user.
  225.  */
  226. void
  227. poly2(nv, dp)
  228.     long    nv;
  229.     float    dp[][2];
  230. {
  231.     int    i;
  232.     float    np[MAXVERTS][3];
  233.  
  234.     if (!vdevice.initialised)
  235.         verror("poly2: vogl not initialised");
  236.  
  237.     vdevice.fill = 0;
  238.  
  239.     for (i = 0; i < (int)nv; i++) {
  240.         np[i][V_X] = dp[i][V_X];
  241.         np[i][V_Y] = dp[i][V_Y];
  242.         np[i][V_Z] = 0.0;
  243.     }
  244.  
  245.     poly(nv, np);
  246. }
  247.  
  248. /*
  249.  * poly2i
  250.  *
  251.  *    construct a polygon from an (x, y) array of points provided by the user.
  252.  * Icoord version.
  253.  */
  254. void
  255. poly2i(nv, dp)
  256.     long    nv;
  257.     Icoord    dp[][2];
  258. {
  259.     int    i;
  260.     float    np[MAXVERTS][3];
  261.  
  262.     if (!vdevice.initialised)
  263.         verror("poly2i: vogl not initialised");
  264.  
  265.     vdevice.fill = 0;
  266.  
  267.     for (i = 0; i < (int)nv; i++) {
  268.         np[i][V_X] = dp[i][V_X];
  269.         np[i][V_Y] = dp[i][V_Y];
  270.         np[i][V_Z] = 0.0;
  271.     }
  272.  
  273.     poly(nv, np);
  274. }
  275.  
  276. /*
  277.  * poly2s
  278.  *
  279.  *    construct a polygon from an (x, y) array of points provided by the user.
  280.  * Scoord version.
  281.  */
  282. void
  283. poly2s(nv, dp)
  284.     long    nv;
  285.     Scoord    dp[][2];
  286. {
  287.     int    i;
  288.     float    np[MAXVERTS][3];
  289.  
  290.     if (!vdevice.initialised)
  291.         verror("poly2s: vogl not initialised");
  292.  
  293.     vdevice.fill = 0;
  294.  
  295.     for (i = 0; i < (int)nv; i++) {
  296.         np[i][V_X] = dp[i][V_X];
  297.         np[i][V_Y] = dp[i][V_Y];
  298.         np[i][V_Z] = 0.0;
  299.     }
  300.  
  301.     poly(nv, np);
  302. }
  303.  
  304. /*
  305.  * polyi
  306.  *
  307.  *    construct a polygon from an (x, y, z) array of points provided by the user.
  308.  * Icoord version.
  309.  */
  310. void
  311. polyi(nv, dp)
  312.     long    nv;
  313.     Icoord    dp[][3];
  314. {
  315.     int    i;
  316.     float    np[MAXVERTS][3];
  317.  
  318.     if (!vdevice.initialised)
  319.         verror("polyi: vogl not initialised");
  320.  
  321.     vdevice.fill = 0;
  322.  
  323.     for (i = 0; i < (int)nv; i++) {
  324.         np[i][V_X] = dp[i][V_X];
  325.         np[i][V_Y] = dp[i][V_Y];
  326.         np[i][V_Z] = dp[i][V_Z];
  327.     }
  328.  
  329.     poly(nv, np);
  330. }
  331.  
  332. /*
  333.  * polys
  334.  *
  335.  *    construct a polygon from an (x, y, z) array of points provided by the user.
  336.  * Scoord version.
  337.  */
  338. void
  339. polys(nv, dp)
  340.     long    nv;
  341.     Scoord    dp[][3];
  342. {
  343.     int    i;
  344.     float    np[MAXVERTS][3];
  345.  
  346.     if (!vdevice.initialised)
  347.         verror("poly2s: vogl not initialised");
  348.  
  349.     vdevice.fill = 0;
  350.  
  351.     for (i = 0; i < (int)nv; i++) {
  352.         np[i][V_X] = dp[i][V_X];
  353.         np[i][V_Y] = dp[i][V_Y];
  354.         np[i][V_Z] = dp[i][V_Z];
  355.     }
  356.  
  357.     poly(nv, np);
  358. }
  359.  
  360. /*
  361.  * polf2
  362.  *
  363.  *    construct a filled polygon from an (x, y) array of points provided
  364.  * by the user.
  365.  */
  366. void
  367. polf2(nv, dp)
  368.     long    nv;
  369.     float    dp[][2];
  370. {
  371.     int    i;
  372.     float    np[MAXVERTS][3];
  373.  
  374.     if (!vdevice.initialised)
  375.         verror("polf2: vogl not initialised");
  376.  
  377.     vdevice.fill = polymodeflag;
  378.  
  379.     for (i = 0; i < (int)nv; i++) {
  380.         np[i][V_X] = dp[i][V_X];
  381.         np[i][V_Y] = dp[i][V_Y];
  382.         np[i][V_Z] = 0.0;
  383.     }
  384.  
  385.     polf(nv, np);
  386.  
  387.     vdevice.fill = 0;
  388. }
  389.  
  390. /*
  391.  * polf2i
  392.  *
  393.  *    construct a filled polygon from an (x, y) array of points provided
  394.  * by the user. Icoord version.
  395.  */
  396. void
  397. polf2i(nv, dp)
  398.     long    nv;
  399.     Icoord    dp[][2];
  400. {
  401.     int    i;
  402.     float    np[MAXVERTS][3];
  403.  
  404.     if (!vdevice.initialised)
  405.         verror("polf2i: vogl not initialised");
  406.  
  407.     vdevice.fill = polymodeflag;
  408.  
  409.     for (i = 0; i < (int)nv; i++) {
  410.         np[i][V_X] = dp[i][V_X];
  411.         np[i][V_Y] = dp[i][V_Y];
  412.         np[i][V_Z] = 0.0;
  413.     }
  414.  
  415.     polf(nv, np);
  416.  
  417.     vdevice.fill = 0;
  418. }
  419.  
  420. /*
  421.  * polf2s
  422.  *
  423.  *    construct a filled polygon from an (x, y) array of points provided
  424.  * by the user. Scoord version.
  425.  */
  426. void
  427. polf2s(nv, dp)
  428.     long    nv;
  429.     Scoord    dp[][2];
  430. {
  431.     int    i;
  432.     float    np[MAXVERTS][3];
  433.  
  434.     if (!vdevice.initialised)
  435.         verror("polf2s: vogl not initialised");
  436.  
  437.     vdevice.fill = polymodeflag;
  438.  
  439.     for (i = 0; i < (int)nv; i++) {
  440.         np[i][V_X] = dp[i][V_X];
  441.         np[i][V_Y] = dp[i][V_Y];
  442.         np[i][V_Z] = 0.0;
  443.     }
  444.  
  445.     polf(nv, np);
  446.  
  447.     vdevice.fill = 0;
  448. }
  449.  
  450. /*
  451.  * polfi
  452.  *
  453.  *    construct a filled polygon from an (x, y, z) array of points provided
  454.  * by the user. Icoord version.
  455.  */
  456. void
  457. polfi(nv, dp)
  458.     long    nv;
  459.     Icoord    dp[][3];
  460. {
  461.     int    i;
  462.     float    np[MAXVERTS][3];
  463.  
  464.     if (!vdevice.initialised)
  465.         verror("polfi: vogl not initialised");
  466.  
  467.     vdevice.fill = polymodeflag;
  468.  
  469.     for (i = 0; i < (int)nv; i++) {
  470.         np[i][V_X] = dp[i][V_X];
  471.         np[i][V_Y] = dp[i][V_Y];
  472.         np[i][V_Z] = dp[i][V_Z];
  473.     }
  474.  
  475.     polf(nv, np);
  476.  
  477.     vdevice.fill = 0;
  478. }
  479.  
  480. /*
  481.  * polfs
  482.  *
  483.  *    construct a filled polygon from an (x, y, z) array of points provided
  484.  * by the user. Scoord version.
  485.  */
  486. void
  487. polfs(nv, dp)
  488.     long    nv;
  489.     Scoord    dp[][3];
  490. {
  491.     int    i;
  492.     float    np[MAXVERTS][3];
  493.  
  494.     if (!vdevice.initialised)
  495.         verror("polfs: vogl not initialised");
  496.  
  497.     vdevice.fill = polymodeflag;
  498.  
  499.     for (i = 0; i < (int)nv; i++) {
  500.         np[i][V_X] = dp[i][V_X];
  501.         np[i][V_Y] = dp[i][V_Y];
  502.         np[i][V_Z] = dp[i][V_Z];
  503.     }
  504.  
  505.     polf(nv, np);
  506.  
  507.     vdevice.fill = 0;
  508. }
  509.  
  510. /*
  511.  * poly
  512.  *
  513.  *    construct a polygon from an array of points provided by the user.
  514.  */
  515. void
  516. poly(nv, dp)
  517.     long    nv;
  518.     float    dp[][3];
  519. {
  520.     int    i, j;
  521.     Vector    vect, result;
  522.     Token    *tok;
  523.     int    n = nv;
  524.     
  525.     if (!vdevice.initialised)
  526.         verror("poly: vogl not initialised");
  527.  
  528.     if (vdevice.inobject) {
  529.         tok = newtokens(2 + 3 * n);
  530.         tok[0].i = POLY;
  531.         tok[1].i = n;
  532.         for (i = 0, j = 2; i < n; i++, j += 3) {
  533.             tok[j + V_X].f = dp[i][V_X];
  534.             tok[j + V_Y].f = dp[i][V_Y];
  535.             tok[j + V_Z].f = dp[i][V_Z];
  536.         }
  537.         return;
  538.     }
  539.  
  540.     for (i = 0; i < n; i++) {
  541.         vect[V_X] = dp[i][V_X];
  542.         vect[V_Y] = dp[i][V_Y];
  543.         vect[V_Z] = dp[i][V_Z];
  544.         vect[V_W] = 1;
  545.         multvector(result, vect, vdevice.transmat->m);
  546.         p[i][V_X] = result[V_X];
  547.         p[i][V_Y] = result[V_Y];
  548.         p[i][V_Z] = result[V_Z];
  549.         p[i][V_W] = result[V_W];
  550.     }
  551.  
  552.     dopoly(n);
  553.  
  554.     vdevice.cpW[V_X] = dp[0][V_X];
  555.     vdevice.cpW[V_Y] = dp[0][V_Y];
  556.     vdevice.cpW[V_Z] = dp[0][V_Z];
  557. }
  558.  
  559. /*
  560.  * polf
  561.  *
  562.  *    construct a filled polygon from an array of points provided
  563.  * by the user.
  564.  */
  565. void
  566. polf(nv, dp)
  567.     long    nv;
  568.     float    dp[][3];
  569. {
  570.     int    i, j;
  571.     Vector    vect, result;
  572.     Token    *tok;
  573.     long    n = nv;
  574.     
  575.     if (!vdevice.initialised)
  576.         verror("poly: vogl not initialised");
  577.  
  578.     vdevice.fill = polymodeflag;
  579.  
  580.     if (vdevice.inobject) {
  581.         tok = newtokens(2 + 3 * n);
  582.         tok[0].i = POLYF;
  583.         tok[1].i = n;
  584.         for (i = 0, j = 2; i < n; i++, j += 3) {
  585.             tok[j + V_X].f = dp[i][V_X];
  586.             tok[j + V_Y].f = dp[i][V_Y];
  587.             tok[j + V_Z].f = dp[i][V_Z];
  588.         }
  589.         return;
  590.     }
  591.  
  592.     for (i = 0; i < n; i++) {
  593.         vect[V_X] = dp[i][V_X];
  594.         vect[V_Y] = dp[i][V_Y];
  595.         vect[V_Z] = dp[i][V_Z];
  596.         vect[V_W] = 1;
  597.         multvector(result, vect, vdevice.transmat->m);
  598.         p[i][V_X] = result[V_X];
  599.         p[i][V_Y] = result[V_Y];
  600.         p[i][V_Z] = result[V_Z];
  601.         p[i][V_W] = result[V_W];
  602.     }
  603.  
  604.     dopoly(n);
  605.  
  606.     vdevice.cpW[V_X] = dp[0][V_X];
  607.     vdevice.cpW[V_Y] = dp[0][V_Y];
  608.     vdevice.cpW[V_Z] = dp[0][V_Z];
  609.  
  610.     vdevice.fill = 0;
  611. }
  612.  
  613. /*
  614.  * pmv
  615.  *
  616.  *    set the start position of a polygon
  617.  */
  618. void
  619. pmv(x, y, z)
  620.     float    x, y, z;
  621. {
  622.     vdevice.inpolygon = 1;
  623.     vdevice.fill = polymodeflag;
  624.     numv = 0;
  625.     p[numv][V_X] = x;
  626.     p[numv][V_Y] = y;
  627.     p[numv][V_Z] = z;
  628.     p[numv][V_W] = 1.0;
  629. }
  630.  
  631. /*
  632.  * pmvi
  633.  *
  634.  *    The integer argument version of pmv.
  635.  */
  636. void
  637. pmvi(x, y, z)
  638.     Icoord    x, y, z;
  639. {
  640.     pmv((float)x, (float)y, (float)z);
  641. }
  642.  
  643. /*
  644.  * pmv2i
  645.  *
  646.  *    The integer argument version of pmv2.
  647.  */
  648. void
  649. pmv2i(x, y)
  650.     Icoord    x, y;
  651. {
  652.     pmv((float)x, (float)y, vdevice.cpW[V_Z]);
  653. }
  654.  
  655. /*
  656.  * pmvs
  657.  *
  658.  *    The integer argument version of pmv.
  659.  */
  660. void
  661. pmvs(x, y, z)
  662.     Scoord    x, y, z;
  663. {
  664.     pmv((float)x, (float)y, (float)z);
  665. }
  666.  
  667. /*
  668.  * pmv2s
  669.  *
  670.  *    The integer argument version of pmv2.
  671.  */
  672. void
  673. pmv2s(x, y)
  674.     Scoord    x, y;
  675. {
  676.     pmv((float)x, (float)y, vdevice.cpW[V_Z]);
  677. }
  678.  
  679. /*
  680.  * pmv2
  681.  *
  682.  *    set up a polygon which will be constructed by a series of
  683.  * move draws in x, y.
  684.  */
  685. void
  686. pmv2(x, y)
  687.     float    x, y;
  688. {
  689.     pmv(x, y, vdevice.cpW[V_Z]);
  690. }
  691.  
  692.  
  693. /*
  694.  * pdr
  695.  *
  696.  *    add another vertex to the polygon array
  697.  */
  698. void
  699. pdr(x, y, z)
  700.     Coord    x, y, z;
  701. {
  702.     char    buf[100];
  703.     Token    *t;
  704.  
  705.     numv++;
  706.  
  707.     if (numv >= MAXVERTS) {
  708.         sprintf(buf, "pdr: can't draw a polygon with more than %d vertices", MAXVERTS);
  709.         verror(buf);
  710.     }
  711.  
  712.     p[numv][V_X] = x;
  713.     p[numv][V_Y] = y;
  714.     p[numv][V_Z] = z;
  715.     p[numv][V_W] = 1.0;
  716. }
  717.  
  718. /*
  719.  * rpdr
  720.  *
  721.  *    relative polygon draw.
  722.  */
  723. void
  724. rpdr(dx, dy, dz)
  725.     Coord    dx, dy, dz;
  726. {
  727.     pdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  728. }
  729.  
  730. /*
  731.  * rpdr2
  732.  *
  733.  *    relative polygon draw - only (x, y).
  734.  */
  735. void
  736. rpdr2(dx, dy)
  737.     Coord    dx, dy;
  738. {
  739.     pdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  740. }
  741.  
  742. /*
  743.  * rpdri
  744.  *
  745.  *    relative polygon draw. Icoord version.
  746.  */
  747. void
  748. rpdri(dx, dy, dz)
  749.     Icoord    dx, dy, dz;
  750. {
  751.     pdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  752. }
  753.  
  754. /*
  755.  * rpdr2i
  756.  *
  757.  *    relative polygon draw - only (x, y). Icoord version.
  758.  */
  759. void
  760. rpdr2i(dx, dy)
  761.     Icoord    dx, dy;
  762. {
  763.     pdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  764. }
  765.  
  766. /*
  767.  * rpdrs
  768.  *
  769.  *    relative polygon draw. Icoord version.
  770.  */
  771. void
  772. rpdrs(dx, dy, dz)
  773.     Scoord    dx, dy, dz;
  774. {
  775.     pdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  776. }
  777.  
  778. /*
  779.  * rpdr2s
  780.  *
  781.  *    relative polygon draw - only (x, y). Scoord version.
  782.  */
  783. void
  784. rpdr2s(dx, dy)
  785.     Scoord    dx, dy;
  786. {
  787.     pdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  788. }
  789.  
  790. /*
  791.  * rpmv
  792.  *
  793.  *    relative polygon move.
  794.  */
  795. void
  796. rpmv(dx, dy, dz)
  797.     Coord    dx, dy, dz;
  798. {
  799.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  800. }
  801.  
  802. /*
  803.  * rpmv2
  804.  *
  805.  *    relative polygon move - only (x, y).
  806.  */
  807. void
  808. rpmv2(dx, dy)
  809.     Coord    dx, dy;
  810. {
  811.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  812. }
  813.  
  814. /*
  815.  * rpmvi
  816.  *
  817.  *    relative polygon move. Icoord version.
  818.  */
  819. void
  820. rpmvi(dx, dy, dz)
  821.     Icoord    dx, dy, dz;
  822. {
  823.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  824. }
  825.  
  826. /*
  827.  * rpmv2i
  828.  *
  829.  *    relative polygon move - only (x, y). Icoord version.
  830.  */
  831. void
  832. rpmv2i(dx, dy)
  833.     Icoord    dx, dy;
  834. {
  835.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  836. }
  837.  
  838. /*
  839.  * rpmvs
  840.  *
  841.  *    relative polygon move. Icoord version.
  842.  */
  843. void
  844. rpmvs(dx, dy, dz)
  845.     Scoord    dx, dy, dz;
  846. {
  847.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  848. }
  849.  
  850. /*
  851.  * rpmv2s
  852.  *
  853.  *    relative polygon move - only (x, y). Scoord version.
  854.  */
  855. void
  856. rpmv2s(dx, dy)
  857.     Scoord    dx, dy;
  858. {
  859.     pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  860. }
  861.  
  862. /*
  863.  * pdri
  864.  *
  865.  *    The integer argument version of pdr.
  866.  */
  867. void
  868. pdri(x, y, z)
  869.     Icoord    x, y, z;
  870. {
  871.     pdr((float)x, (float)y, (float)z);
  872. }
  873.  
  874. /*
  875.  * pdr2i
  876.  *
  877.  *    The integer argument version of pdr2.
  878.  */
  879. void
  880. pdr2i(x, y)
  881.     Icoord    x, y;
  882. {
  883.     pdr((float)x, (float)y, vdevice.cpW[V_Z]);
  884. }
  885.  
  886. /*
  887.  * pdrs
  888.  *
  889.  *    The short argument version of pdr.
  890.  */
  891. void
  892. pdrs(x, y)
  893.     Scoord    x, y;
  894. {
  895.     pdr((float)x, (float)y, vdevice.cpW[V_Z]);
  896. }
  897.  
  898. /*
  899.  * pdr2s
  900.  *
  901.  *    The short argument version of pdr2.
  902.  */
  903. void
  904. pdr2s(x, y)
  905.     Scoord    x, y;
  906. {
  907.     pdr((float)x, (float)y, vdevice.cpW[V_Z]);
  908. }
  909.  
  910. /*
  911.  * pdr2
  912.  *
  913.  *    add another vertex to the polygon array
  914.  */
  915. void
  916. pdr2(x, y)
  917.     float    x, y;
  918. {
  919.     pdr(x, y, vdevice.cpW[V_Z]);
  920. }
  921.  
  922. /*
  923.  * pclos
  924.  *
  925.  *    draw the polygon started by the above.
  926.  */
  927. void
  928. pclos()
  929. {
  930.     float    lstx, lsty, lstz;
  931.     Vector    result;
  932.     int    i, j;
  933.     Token    *tok;
  934.  
  935.     if (!vdevice.initialised)
  936.         verror("pclos: vogl not initialised");
  937.  
  938.     vdevice.inpolygon = 0;
  939.  
  940.     if (vdevice.inobject) {
  941.         tok = newtokens(2 + 3 * (numv + 1));
  942.         tok[0].i = POLYF;
  943.         tok[1].i = numv + 1;
  944.         for (i = 0, j = 2; i <= numv; i++, j += 3) {
  945.             tok[j + V_X].f = p[i][V_X];
  946.             tok[j + V_Y].f = p[i][V_Y];
  947.             tok[j + V_Z].f = p[i][V_Z];
  948.         }
  949.  
  950.         return;
  951.     }
  952.  
  953.     lstx = p[numv][V_X];
  954.     lsty = p[numv][V_Y];
  955.     lstz = p[numv][V_Z];
  956.  
  957.     numv++;
  958.  
  959.     for (i = 0; i < numv; i++) {
  960.         multvector(result, p[i], vdevice.transmat->m);
  961.         p[i][V_X] = result[V_X];
  962.         p[i][V_Y] = result[V_Y];
  963.         p[i][V_Z] = result[V_Z];
  964.         p[i][V_W] = result[V_W];
  965.     }
  966.  
  967.     dopoly(numv);
  968.  
  969.     vdevice.cpW[V_X] = lstx;
  970.     vdevice.cpW[V_Y] = lsty;
  971.     vdevice.cpW[V_Z] = lstz;
  972. }
  973.  
  974. /*
  975.  * checkbacki
  976.  *
  977.  *    Checks if a transformed polygon is backfacing or not.
  978.  */
  979. static    int
  980. checkbacki()
  981. {
  982.  
  983. #ifdef    PC    /*    Only has 16 bit ints */
  984. #define    BACKFACE(z)    (clockwise ? ((z) <= 0L) : ((z) > 0L))
  985.     long    z;
  986. #else
  987. #define    BACKFACE(z)    (clockwise ? ((z) <= 0) : ((z) > 0))
  988.     int    z;
  989. #endif
  990.  
  991.     int    x1, x2, y1, y2;
  992.  
  993.     x1 = ip1[1] - ip1[0];
  994.     x2 = ip1[2] - ip1[1];
  995.     y1 = ip2[1] - ip2[0];
  996.     y2 = ip2[2] - ip2[1];
  997.  
  998. #ifdef    PC
  999.     z = (long)x1 * (long)y2 - (long)y1 * (long)x2;
  1000. #else
  1001.     z = x1 * y2 - y1 * x2;
  1002. #endif
  1003.  
  1004.     return(BACKFACE(z));
  1005. }
  1006.  
  1007. /*
  1008.  * The following routines are an implementation of the Sutherland - Hodgman
  1009.  * polygon clipper, as described in "Reentrant Polygon Clipping"
  1010.  * Communications of the ACM Jan 1974, Vol 17 No. 1.
  1011.  */
  1012. static void
  1013. polyclip(n)
  1014.     register    int    n;
  1015. {
  1016.     int    i;
  1017.  
  1018.     nout = 0;
  1019.     for (i = 0; i < 6; i++)
  1020.         first[i] = 1;
  1021.  
  1022.     for (i = 0; i < n; i++) 
  1023.         shclip(p[i], 0);
  1024.  
  1025.     shclose(0);
  1026. }
  1027.  
  1028. static void
  1029. shclip(Pnt, side)
  1030.     float    Pnt[4];
  1031.     int    side;
  1032. {
  1033.     float    P[4];
  1034.  
  1035.     if (side == 6) {
  1036.         ip1[nout] = WtoVx(Pnt);
  1037.         ip2[nout++] = WtoVy(Pnt);
  1038.     } else {
  1039.         copyvector(P, Pnt);
  1040.         if (first[side]) {
  1041.             first[side] = 0;
  1042.             copyvector(F[side], P);
  1043.         } else if (intersect(side, I, P)) {
  1044.             shclip(I, side + 1);
  1045.         }
  1046.         copyvector(S[side], P);
  1047.         if (visible(side)) 
  1048.             shclip(S[side], side + 1);
  1049.     }
  1050. }
  1051.  
  1052. static void
  1053. shclose(side)
  1054.     int    side;
  1055. {
  1056.     if (side < 6) {
  1057.         if (intersect(side, I, F[side]))
  1058.             shclip(I, side + 1);
  1059.  
  1060.         shclose(side + 1);
  1061.  
  1062.         first[side] = 1;
  1063.     }
  1064. }
  1065.  
  1066. static
  1067. intersect(side, Ip, Pnt)
  1068.     int    side;
  1069.     register    Vector    Ip, Pnt;
  1070. {
  1071.     register    float    wc1, wc2, a;
  1072.  
  1073.     switch (side) {
  1074.     case 0:        /* x - left */
  1075.         wc1 = Pnt[3] + Pnt[0];
  1076.         wc2 = S[side][3] + S[side][0];
  1077.         break;
  1078.     case 1:        /* x - right */
  1079.         wc1 = Pnt[3] - Pnt[0];
  1080.         wc2 = S[side][3] - S[side][0];
  1081.         break;
  1082.     case 2:        /* y - bottom */
  1083.         wc1 = Pnt[3] + Pnt[1];
  1084.         wc2 = S[side][3] + S[side][1];
  1085.         break;
  1086.     case 3:        /* y - top */
  1087.         wc1 = Pnt[3] - Pnt[1];
  1088.         wc2 = S[side][3] - S[side][1];
  1089.         break;
  1090.     case 4:        /* z - near */
  1091.         wc1 = Pnt[3] + Pnt[2];
  1092.         wc2 = S[side][3] + S[side][2];
  1093.         break;
  1094.     case 5:        /* z - far */
  1095.         wc1 = Pnt[3] - Pnt[2];
  1096.         wc2 = S[side][3] - S[side][2];
  1097.         break;
  1098.     default:
  1099.         verror("intersect: ridiculous side value");
  1100.     }
  1101.  
  1102.     if (wc1 * wc2 < 0.0) {    /* Both are opposite in sign - crosses */
  1103.         a = wc1 / (wc1 - wc2);
  1104.         if (a < 0.0 || a > 1.0) {
  1105.             return(0);
  1106.         } else {
  1107.             Ip[0] = Pnt[0] + a * (S[side][0] - Pnt[0]);
  1108.             Ip[1] = Pnt[1] + a * (S[side][1] - Pnt[1]);
  1109.             Ip[2] = Pnt[2] + a * (S[side][2] - Pnt[2]);
  1110.             Ip[3] = Pnt[3] + a * (S[side][3] - Pnt[3]);
  1111.             return(1);
  1112.         }
  1113.     }
  1114.     return(0);
  1115. }
  1116.  
  1117. static
  1118. visible(side)
  1119.     int    side;
  1120. {
  1121.     float    wc;
  1122.  
  1123.     switch (side) {
  1124.     case 0:        /* x - left */
  1125.         wc = S[side][3] + S[side][0];
  1126.         break;
  1127.     case 1:        /* x - right */
  1128.         wc = S[side][3] - S[side][0];
  1129.         break;
  1130.     case 2:        /* y - bottom */
  1131.         wc = S[side][3] + S[side][1];
  1132.         break;
  1133.     case 3:        /* y - top */
  1134.         wc = S[side][3] - S[side][1];
  1135.         break;
  1136.     case 4:        /* z - near */
  1137.         wc = S[side][3] + S[side][2];
  1138.         break;
  1139.     case 5:        /* z - far */
  1140.         wc = S[side][3] - S[side][2];
  1141.         break;
  1142.     default:
  1143.         verror("visible: ridiculous side value");
  1144.     }
  1145.  
  1146.     return(wc >= 0.0);
  1147. }
  1148.  
  1149. /*
  1150.  * bgnpolygon
  1151.  *
  1152.  *    Set a flag so that we know what to do with v*() calls.
  1153.  */
  1154. void
  1155. bgnpolygon()
  1156. {
  1157.     if (vdevice.bgnmode != NONE)
  1158.         verror("vogl: bgnpolygon mode already belongs to some other bgn routine");
  1159.  
  1160.     vdevice.bgnmode = VPOLY;
  1161.     vdevice.fill = polymodeflag;
  1162.     vdevice.save = 1;
  1163.     vdevice.inpolygon = 1;
  1164.         if (sync = vdevice.sync)
  1165.                 vdevice.sync = 0;
  1166. }
  1167.  
  1168. /*
  1169.  * endpolygon
  1170.  *
  1171.  *    Set a flag so that we know what to do with v*() calls.
  1172.  */
  1173. void
  1174. endpolygon()
  1175. {
  1176.     pclos();
  1177.  
  1178.     vdevice.bgnmode = NONE;
  1179.     vdevice.fill = 0;
  1180.     vdevice.inpolygon = 0;
  1181.     vdevice.save = 0;
  1182. }
  1183.  
  1184. /*
  1185.  * bgntmesh
  1186.  *
  1187.  *    Set a flag so that we know what to do with v*() calls.
  1188.  */
  1189. void
  1190. bgntmesh()
  1191. {
  1192.     if (vdevice.bgnmode != NONE)
  1193.         verror("vogl: bgntmesh mode already belongs to some other bgn routine");
  1194.  
  1195.     vdevice.bgnmode = VTMESH;
  1196.     vdevice.fill = polymodeflag;
  1197.     vdevice.save = 0;
  1198.     vdevice.inpolygon = 1;
  1199.         if (sync = vdevice.sync)
  1200.                 vdevice.sync = 0;
  1201. }
  1202.  
  1203. /*
  1204.  * swaptmesh
  1205.  *
  1206.  *    cause v* calls to save in the new register 
  1207.  */
  1208. void
  1209. swaptmesh()
  1210. {
  1211.     if (vdevice.bgnmode != VTMESH)
  1212.       verror("vogl: swaptmesh called outside bgntmesh/endtmesh ");
  1213.     if( vdevice.save < 2)
  1214.       verror("vogl: swaptmesh called before first triangle was defined ");
  1215.     vdevice.save++;
  1216. }
  1217. /*
  1218.  * endtmesh
  1219.  *
  1220.  *    Set a flag so that we know what to do with v*() calls.
  1221.  */
  1222. void
  1223. endtmesh()
  1224. {
  1225.     vdevice.bgnmode = NONE;
  1226.     vdevice.fill = 0;
  1227.     vdevice.inpolygon = 0;
  1228.     vdevice.save = 0;
  1229.     if (sync) {
  1230.         vdevice.sync = 1;
  1231.         (*vdevice.dev.Vsync)();
  1232.     }
  1233. }
  1234.  
  1235. /*
  1236.  * bgnqstrip
  1237.  *
  1238.  *    Set a flag so that we know what to do with v*() calls.
  1239.  */
  1240. void
  1241. bgnqstrip()
  1242. {
  1243.     if (vdevice.bgnmode != NONE)
  1244.         verror("vogl: bgnqstrip mode already belongs to some other bgn routine");
  1245.  
  1246.     vdevice.bgnmode = VQSTRIP;
  1247.     vdevice.fill = polymodeflag;
  1248.     vdevice.save = 0;
  1249.     vdevice.inpolygon = 1;
  1250.         if (sync = vdevice.sync)
  1251.                 vdevice.sync = 0;
  1252. }
  1253.  
  1254. /*
  1255.  * endqstrip
  1256.  *
  1257.  *    Set a flag so that we know what to do with v*() calls.
  1258.  */
  1259. void
  1260. endqstrip()
  1261. {
  1262.     vdevice.bgnmode = NONE;
  1263.     vdevice.fill = 0;
  1264.     vdevice.inpolygon = 0;
  1265.     vdevice.save = 0;
  1266.     if (sync) {
  1267.         vdevice.sync = 1;
  1268.         (*vdevice.dev.Vsync)();
  1269.     }
  1270.  
  1271. }
  1272.