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

  1. #include "vogl.h"
  2.  
  3. static    int    nsegs = 15;
  4. static    Matrix    e;
  5.  
  6. void     drcurve();
  7.  
  8. /*
  9.  * curvebasis
  10.  *
  11.  *      sets the basis type of curves.
  12.  *
  13.  */
  14. void
  15. curvebasis(id)
  16.     short   id;
  17. {
  18.     if(!vdevice.initialised)
  19.         verror("curvebasis: vogl not initialised");
  20.  
  21.     copymatrix(vdevice.tbasis, vdevice.bases[id]);
  22. }
  23.                            
  24. /*
  25.  * curveprecision
  26.  *
  27.  *    sets the number of line segments that make up a curve segment.
  28.  *
  29.  */
  30. void
  31. curveprecision(nsegments)
  32.     short        nsegments;
  33. {
  34.     float    n2, n3;
  35.  
  36.     if (nsegments > 0)
  37.         nsegs = nsegments;
  38.     else
  39.         verror("curveprecision: number of segments <= 0");
  40.  
  41.     /*
  42.      * Set up the difference matrix.
  43.      */
  44.     identmatrix(e);
  45.     n2 = (float)(nsegs * nsegs);
  46.     n3 = (float)(nsegs * n2);
  47.  
  48.     e[0][0] = e[2][2] = e[3][3] = 0.0;
  49.     e[1][0] = 1.0 / n3;
  50.     e[1][1] = 1.0 / n2;
  51.     e[2][0] = e[3][0] = 6.0 / n3;
  52.     e[2][1] = 2.0 / n2;
  53.     e[1][2] = 1.0 / (float)nsegs;
  54.     e[0][3] = 1.0;
  55. }
  56.  
  57. /*
  58.  * rcrv
  59.  *
  60.  *    draws a rational curve
  61.  *
  62.  */
  63. void
  64. rcrv(geom)
  65.     Coord    geom[4][4];
  66. {
  67.     Matrix    d, tmp;
  68.     float    *m, xlast, ylast, zlast;
  69.     Token    *tok;
  70.     int    i;
  71.     
  72.     if (!vdevice.initialised)
  73.         verror("rcrv: vogl not initialised");
  74.  
  75.  
  76.     mult4x4(d, vdevice.tbasis, geom);
  77.  
  78.     /*
  79.      * Find the last point on the curve....
  80.      */
  81.     xlast = d[0][0] + d[1][0] + d[2][0] + d[3][0];
  82.     ylast = d[0][1] + d[1][1] + d[2][1] + d[3][1];
  83.     zlast = d[0][2] + d[1][2] + d[2][2] + d[3][2];
  84.  
  85.     /*
  86.      * Mult. by the precision matrix....
  87.      */
  88.     mult4x4(tmp, e, d);
  89.  
  90.     if (vdevice.inobject) {
  91.         tok = newtokens(21);
  92.  
  93.         tok[0].i = RCURVE;
  94.         (++tok)->i = nsegs;
  95.         (++tok)->f = xlast;
  96.         (++tok)->f = ylast;
  97.         (++tok)->f = zlast;
  98.         m = (float *)tmp;
  99.         for (i = 0; i < 16; i++)
  100.             (++tok)->f = *m++;
  101.  
  102.         return;
  103.     }
  104.  
  105.     /*
  106.      * Multiply by the current transformation matrix.
  107.      */
  108.     mult4x4(d, tmp, vdevice.transmat->m);
  109.  
  110.     /*
  111.      * Draw the curve.....
  112.      */
  113.     drcurve(nsegs, d);
  114.     /*
  115.      * Set the current world position to the last point (This
  116.      * is the untransformed one)
  117.      */
  118.     vdevice.cpW[V_X] = xlast;
  119.     vdevice.cpW[V_Y] = ylast;
  120.     vdevice.cpW[V_Z] = zlast;
  121. }
  122.  
  123. /*
  124.  * crv
  125.  *
  126.  *    draws a curve
  127.  *
  128.  */
  129. void
  130. crv(geom)
  131.     Coord    geom[4][3];
  132. {
  133.     Matrix    tmp;
  134.     int    i, j;
  135.  
  136.     if (!vdevice.initialised)
  137.         verror("crv: vogl not initialised");
  138.  
  139.     /*
  140.      * Fill in the w column for rcurve
  141.      */
  142.     for (i = 0; i < 4; i++) {
  143.         tmp[i][3] = 1.0;
  144.         for (j = 0; j < 3; j++) 
  145.             tmp[i][j] = geom[i][j];
  146.     }
  147.  
  148.     rcrv(tmp);
  149. }
  150.  
  151. /*
  152.  *  drcurve
  153.  *
  154.  *    Iterate a forward difference matrix to draw a curve.
  155.  *    Also bypasses the normal multiplication by the current
  156.  *      transformation matrix (ie. goes straight to clip).
  157.  */
  158. void
  159. drcurve(n, r)
  160.     int    n;
  161.     Matrix    r;
  162. {
  163.     int    it, vx, vy, sync;
  164.  
  165.     if (sync = vdevice.sync)                /* We'll sync at the end */
  166.         vdevice.sync = 0;
  167.  
  168.     vdevice.cpVvalid = 0;        /* we start loop with a "move" */
  169.     if (vdevice.clipoff) {
  170.         vdevice.cpVx = WtoVx(r[0]);        
  171.         vdevice.cpVy = WtoVy(r[0]);        
  172.     }
  173.  
  174.     for (it = 0; it < n; it++) {
  175.         vdevice.cpWtrans[V_X] = r[0][V_X];
  176.         vdevice.cpWtrans[V_Y] = r[0][V_Y];
  177.         vdevice.cpWtrans[V_Z] = r[0][V_Z];
  178.         vdevice.cpWtrans[V_W] = r[0][V_W];
  179.  
  180.         /* These loops now unwound ....
  181.          * for (i = 0; i < 4; i++)
  182.          *    for (j = 0; j < 3; j++)
  183.          *        r[j][i] += r[j+1][i];
  184.          */
  185.  
  186.         r[0][0] += r[1][0];
  187.         r[1][0] += r[2][0];
  188.         r[2][0] += r[3][0];
  189.  
  190.         r[0][1] += r[1][1];
  191.         r[1][1] += r[2][1];
  192.         r[2][1] += r[3][1];
  193.  
  194.         r[0][2] += r[1][2];
  195.         r[1][2] += r[2][2];
  196.         r[2][2] += r[3][2];
  197.  
  198.         r[0][3] += r[1][3];
  199.         r[1][3] += r[2][3];
  200.         r[2][3] += r[3][3];
  201.  
  202.         if (vdevice.clipoff) {    
  203.             vx = WtoVx(r[0]);        /* just draw it */
  204.             vy = WtoVy(r[0]);
  205.          
  206.             (*vdevice.dev.Vdraw)(vx, vy);
  207.  
  208.             vdevice.cpVx = vx;
  209.             vdevice.cpVy = vy;
  210.  
  211.             vdevice.cpVvalid = 0;
  212.         } else {
  213.             if (vdevice.cpVvalid)
  214.                 quickclip(vdevice.cpWtrans, r[0]);
  215.             else
  216.                 clip(vdevice.cpWtrans, r[0]);
  217.         }
  218.     }
  219.  
  220.     vdevice.cpWtrans[V_X] = r[0][V_X];
  221.     vdevice.cpWtrans[V_Y] = r[0][V_Y];
  222.     vdevice.cpWtrans[V_Z] = r[0][V_Z];
  223.     vdevice.cpWtrans[V_W] = r[0][V_W];
  224.  
  225.     /*
  226.      * must set current world position here - clip or quickclip will have
  227.      * set valid to the approriate value.
  228.      */
  229.     if (sync) {
  230.         vdevice.sync = 1;
  231.         (*vdevice.dev.Vsync)();
  232.     }
  233. }
  234.  
  235. /*
  236.  * crvn
  237.  *
  238.  *    draws a series of curve segments.
  239.  *
  240.  */
  241. void
  242. crvn(n, geom)
  243.     long    n;
  244.     Coord    geom[][3];
  245. {
  246.     int    i;
  247.  
  248.     if (!vdevice.initialised)
  249.         verror("crvn: vogl not initialised");
  250.  
  251.     if (n < 4)
  252.         verror("crvn: not enough points in geometry matrix");
  253.  
  254.     for (i = 0; i <= n - 4; i++)
  255.         crv(&geom[i][0]);
  256. }
  257.  
  258. /*
  259.  * rcrvn
  260.  *
  261.  *    draws a series of rational curve segments.
  262.  *
  263.  */
  264. void
  265. rcrvn(n, geom)
  266.     long    n;
  267.     Coord    geom[][4];
  268. {
  269.     int    i;
  270.  
  271.     if (!vdevice.initialised)
  272.         verror("rcrvn: vogl not initialised");
  273.  
  274.     if (n < 4)
  275.         verror("rcrvn: not enough points in geometry matrix");
  276.  
  277.     for (i = 0; i <= n - 4; i++)
  278.         rcrv(&geom[i][0]);
  279. }
  280.  
  281. /*
  282.  * curveit
  283.  *
  284.  *    Iterates the top matrix on the stack as a forward difference
  285.  *    matrix, drawing as it goes along.
  286.  */
  287. void
  288. curveit(n)
  289.     short    n;
  290. {
  291.     drcurve((int)n, vdevice.transmat->m);
  292. }
  293.