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