home *** CD-ROM | disk | FTP | other *** search
/ gondwana.ecr.mu.oz.au/pub/ / Graphics.tar / Graphics / VOGLE.ZIP / SRC / DRAW.C < prev    next >
C/C++ Source or Header  |  2000-02-11  |  7KB  |  413 lines

  1. #include <stdio.h>
  2.  
  3. extern double    sqrt();
  4.  
  5. #include "vogle.h"
  6.  
  7. static    int    do_dash = 1;
  8.  
  9. /* a == b or b > a */
  10. #define NEAR(a, b)    (((a) - (b)) / (a) < 0.0001)
  11. #define checkdash(l)    ((*(++l->dashp) == '\0' ? *(l->dashp = l->style) : *l->dashp) != '0')
  12.  
  13. /*
  14.  * Set the current dash length
  15.  */
  16. void
  17. setdash(d)
  18.     float    d;
  19. {    
  20.     if (d < 0.0)
  21.         d = -d;
  22.  
  23.     if (d == 0.0)
  24.         d = 0.1;
  25.  
  26.     vdevice.attr->a.dash = d;
  27. }
  28.     
  29. /*
  30.  * Set the current linestyle as a character string of 1's and 0's
  31.  */
  32. void
  33. linestyle(l)
  34.     unsigned char    *l;
  35. {
  36.     Attribute *line;
  37.     unsigned char    *c;
  38.  
  39.     line = &vdevice.attr->a;
  40.  
  41.     if (!l || !*l) {
  42.         line->style = NULL;
  43.     } else {
  44.         /*
  45.          * If it's all non-0 (or ' ') then it's a solid line 
  46.          */
  47.         for (c = l; *c != '\0'; c++) {
  48.             if (*c == '0' || *c == ' ') {
  49.                 if (line->style)
  50.                     free(line->style);    /* probably could realloc */
  51.                 line->style = (unsigned char *)vallocate(strlen(l) + 1);
  52.                 strcpy(line->style, l);
  53.                 line->dashp = line->style;
  54.                 line->adist = 0.0;
  55.                 do_dash = *line->dashp != '0';
  56.  
  57.                 return;
  58.             }
  59.         }
  60.         line->style = NULL;
  61.     }
  62.  
  63.     return;
  64. }
  65.  
  66. /*
  67.  * Draw dashed lines (Duh)
  68.  * Assumes p0 - p1 are valid (possibly clipped endpoints)
  69.  */
  70. void
  71. dashline(p0, p1)
  72.     register Vector p0, p1;
  73. {
  74.     int    vx, vy, sync;
  75.     float    dx, dy, dz, dw, dist, ldist, tdist;
  76.     Vector    pd;
  77.     Attribute *line;
  78.  
  79.  
  80.     line = &vdevice.attr->a;
  81.     if (line->dash == 0.0) {
  82.         vx = WtoVx(p1);
  83.         vy = WtoVy(p1);
  84.  
  85.         (*vdevice.dev.Vdraw)(vx, vy);
  86.         return;
  87.     }
  88.  
  89.     /*
  90.      * The distance for this line segment
  91.      */
  92.     dx = p1[V_X] - p0[V_X];
  93.     dy = p1[V_Y] - p0[V_Y];
  94.     dz = p1[V_Z] - p0[V_Z];
  95.     dw = p1[V_W] - p0[V_W];
  96.     ldist = sqrt(dx*dx + dy*dy + dz*dz + dw*dw);
  97.  
  98.     /* 
  99.      * If this distance is less than it takes to
  100.      * complete the current dash then just do it.
  101.      */
  102.     if (ldist <= (line->dash - line->adist)) {
  103.  
  104.         if (NEAR(line->dash, line->adist)) {
  105.             line->adist = 0.0;
  106.             do_dash = checkdash(line);
  107.         }
  108.  
  109.         line->adist += ldist;
  110.  
  111.         vx = WtoVx(p1);
  112.         vy = WtoVy(p1);
  113.  
  114.         if (do_dash)
  115.             (*vdevice.dev.Vdraw)(vx, vy);
  116.  
  117.         vdevice.cpVx = vx;
  118.         vdevice.cpVy = vy;
  119.  
  120.         return;
  121.  
  122.     } else {
  123.         if ((sync = vdevice.sync))                /* We'll sync at the end */
  124.             vdevice.sync = 0;
  125.  
  126.         /* 
  127.          * If this distance will take us over the end of a
  128.          * dash then break it up.
  129.          */
  130.  
  131.         /*
  132.          * Handle the initial case where we start in the middle
  133.          * of a dash.
  134.          */
  135.  
  136.         tdist = 0.0;
  137.         copyvector(pd, p0);
  138.  
  139.         if (line->adist > 0.0) {
  140.  
  141.             tdist = (line->dash - line->adist);
  142.  
  143.             if (NEAR(line->dash, line->adist)) {
  144.                 line->adist = 0.0;
  145.                 do_dash = checkdash(line);
  146.             }
  147.  
  148.             line->adist += tdist;
  149.  
  150.             dist = tdist / ldist;
  151.             pd[V_X] += dx * dist;
  152.             pd[V_Y] += dy * dist;
  153.             pd[V_Z] += dz * dist;
  154.             pd[V_W] += dw * dist;
  155.             vx = WtoVx(pd);
  156.             vy = WtoVy(pd);
  157.  
  158.  
  159.             if (do_dash)
  160.                 (*vdevice.dev.Vdraw)(vx, vy);
  161.  
  162.             vdevice.cpVx = vx;
  163.             vdevice.cpVy = vy;
  164.         }
  165.  
  166.         dx *= line->dash / ldist;
  167.         dy *= line->dash / ldist;
  168.         dz *= line->dash / ldist;
  169.         dw *= line->dash / ldist;
  170.         dist = line->dash;
  171.         
  172.         while (tdist <= ldist - dist) {
  173.  
  174.             if (NEAR(line->dash, line->adist)) {
  175.                 line->adist = 0.0;
  176.                 do_dash = checkdash(line);
  177.             }
  178.  
  179.             pd[V_X] += dx;
  180.             pd[V_Y] += dy;
  181.             pd[V_Z] += dz;
  182.             pd[V_W] += dw;
  183.  
  184.             vx = WtoVx(pd);
  185.             vy = WtoVy(pd);
  186.  
  187.             line->adist += dist;
  188.             tdist += dist;
  189.  
  190.             if (do_dash)
  191.                 (*vdevice.dev.Vdraw)(vx, vy);
  192.  
  193.             vdevice.cpVx = vx;
  194.             vdevice.cpVy = vy;
  195.         }
  196.  
  197.  
  198.         /*
  199.          * Check the last little bit....
  200.          */
  201.         if (NEAR(line->dash, line->adist)) {
  202.             line->adist = 0.0;
  203.             do_dash = checkdash(line);
  204.         }
  205.  
  206.         dx = p1[V_X] - pd[V_X];
  207.         dy = p1[V_Y] - pd[V_Y];
  208.         dz = p1[V_Z] - pd[V_Z];
  209.         dw = p1[V_W] - pd[V_W];
  210.         dist = sqrt(dx*dx + dy*dy + dz*dz + dw*dw);
  211.  
  212.         line->adist += dist;
  213.  
  214.         vx = WtoVx(p1);
  215.         vy = WtoVy(p1);
  216.  
  217.         if (do_dash)
  218.             (*vdevice.dev.Vdraw)(vx, vy);
  219.  
  220.         vdevice.cpVx = vx;
  221.         vdevice.cpVy = vy;
  222.     }
  223.  
  224.     if (sync) {
  225.         vdevice.sync = 1;
  226.         (*vdevice.dev.Vsync)();
  227.     }
  228.  
  229. }
  230.  
  231. /*
  232.  * draw
  233.  *
  234.  * draw a line form the logical graphics position to the
  235.  * the world coordinates x, y, z.
  236.  *
  237.  */
  238. void
  239. draw(x, y, z)
  240.     float        x, y, z;
  241. {
  242.     Token    *tok;
  243.     int    vx, vy;
  244.     Vector    res;
  245.  
  246.  
  247.     if (!vdevice.initialised)
  248.         verror("draw: vogle not initialised");
  249.  
  250.     if (vdevice.inpolygon) {
  251.         (*vdevice.pdraw)(x, y, z);
  252.  
  253.         vdevice.cpW[V_X] = x;
  254.         vdevice.cpW[V_Y] = y;
  255.         vdevice.cpW[V_Z] = z;
  256.  
  257.         vdevice.cpVvalid = 0;
  258.  
  259.         return;
  260.     }
  261.  
  262.     if (vdevice.inobject) {
  263.         tok = newtokens(4);
  264.  
  265.         tok[0].i = DRAW;
  266.         tok[1].f = x;
  267.         tok[2].f = y;
  268.         tok[3].f = z;
  269.  
  270.         vdevice.cpW[V_X] = x;
  271.         vdevice.cpW[V_Y] = y;
  272.         vdevice.cpW[V_Z] = z;
  273.  
  274.         vdevice.cpVvalid = 0;
  275.  
  276.         return;
  277.     }
  278.  
  279.     if (!vdevice.cpVvalid)
  280.         multvector(vdevice.cpWtrans, vdevice.cpW, vdevice.transmat->m);
  281.  
  282.     vdevice.cpW[V_X] = x;
  283.     vdevice.cpW[V_Y] = y;
  284.     vdevice.cpW[V_Z] = z;
  285.     multvector(res, vdevice.cpW, vdevice.transmat->m);
  286.  
  287.     if (vdevice.clipoff) {    
  288.         vx = WtoVx(res);        /* just draw it */
  289.         vy = WtoVy(res);
  290.      
  291.         if (vdevice.attr->a.style) {
  292.             dashline(vdevice.cpWtrans, res);
  293.             vdevice.cpVvalid = 0;
  294.             return;
  295.         }
  296.  
  297.         (*vdevice.dev.Vdraw)(vx, vy);
  298.  
  299.         vdevice.cpVx = vx;
  300.         vdevice.cpVy = vy;
  301.  
  302.         vdevice.cpVvalid = 0;
  303.     } else {
  304.         if (vdevice.cpVvalid)
  305.             quickclip(vdevice.cpWtrans, res);
  306.         else
  307.             clip(vdevice.cpWtrans, res);
  308.     }
  309.  
  310.     vdevice.cpWtrans[V_X] = res[V_X];
  311.     vdevice.cpWtrans[V_Y] = res[V_Y];
  312.     vdevice.cpWtrans[V_Z] = res[V_Z];
  313.     vdevice.cpWtrans[V_W] = res[V_W];
  314. }
  315.  
  316.  
  317. /*
  318.  * draw2
  319.  *
  320.  * draw a line from the logical graphics position  to the
  321.  * the world coordinates x, y.
  322.  *
  323.  */
  324. void
  325. draw2(x, y)
  326.     float        x, y;
  327. {
  328.     if (!vdevice.initialised)
  329.         verror("draw2: vogle not initialised");
  330.  
  331.     draw(x, y, 0.0);
  332. }
  333.  
  334. /*
  335.  * rdraw
  336.  *
  337.  * 3D relative draw from the logical graphics position by dx, dy, dz.
  338.  *
  339.  */
  340. void
  341. rdraw(dx, dy, dz)
  342.     float        dx, dy, dz;
  343. {
  344.     if (!vdevice.initialised) 
  345.         verror("rdraw: vogle not initialised");
  346.  
  347.     draw((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  348. }
  349.  
  350. /*
  351.  * rdraw2
  352.  *
  353.  * 2D relative draw from the logical graphics position by dx, dy.
  354.  *
  355.  */
  356. void
  357. rdraw2(dx, dy)
  358.     float        dx, dy;
  359. {
  360.     if (!vdevice.initialised) 
  361.         verror("rdraw2: vogle not initialised");
  362.  
  363.     draw((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), 0.0);
  364. }
  365.  
  366. /*
  367.  * sdraw2
  368.  *
  369.  * Draw directly in proportion to screen coordinates.
  370.  */
  371. void
  372. sdraw2(xs, ys)
  373.     float     xs, ys;
  374. {
  375.     int    nx, ny;
  376.  
  377.     if (!vdevice.initialised) 
  378.         verror("sdraw2: vogle not initialised");
  379.  
  380.     nx = (xs / 2 + 0.5) * vdevice.sizeX;
  381.     ny = (0.5 + ys / 2) * vdevice.sizeY;
  382.  
  383.     (*vdevice.dev.Vdraw)(nx, ny);
  384.  
  385.     vdevice.cpVx = nx;
  386.     vdevice.cpVy = ny;
  387.     vdevice.cpVvalid = 0;
  388. }
  389.  
  390. /*
  391.  * rsdraw2
  392.  *
  393.  * Relative draw as a fraction of screen size.
  394.  */
  395. void
  396. rsdraw2(dxs, dys)
  397.     float    dxs, dys;
  398. {
  399.     int    ndx, ndy;
  400.  
  401.     if (!vdevice.initialised) 
  402.         verror("rsdraw2: vogle not initialised");
  403.  
  404.     ndx = dxs * vdevice.sizeSx / 2;
  405.     ndy = dys * vdevice.sizeSy / 2;
  406.  
  407.     (*vdevice.dev.Vdraw)(vdevice.cpVx + ndx, vdevice.cpVy + ndy);
  408.  
  409.     vdevice.cpVx += ndx;
  410.     vdevice.cpVy += ndy;
  411. }
  412.  
  413.