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

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