home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 418_02 / rasmol2 / pixutils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-02  |  38.0 KB  |  1,493 lines

  1. /* pixutils.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, February 1994
  4.  * Version 2.3
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <windows.h>
  10. #include <malloc.h>
  11. #endif
  12. #ifdef sun386
  13. #include <stdlib.h>
  14. #endif
  15.  
  16. #include <stdio.h>
  17. #include <math.h>
  18.  
  19. #define PIXUTILS
  20. #include "pixutils.h"
  21. #include "graphics.h"
  22. #include "transfor.h"
  23. #include "render.h"
  24.  
  25. /* Sutherland-Cohen Line Clipping Macros */
  26. #define BitAbove    0x01
  27. #define BitBelow    0x02
  28. #define BitRight    0x04
  29. #define BitLeft     0x08
  30. #define BitFront    0x10
  31.  
  32. #define Reject(x,y)   ((x)&(y))
  33. #define Accept(x,y)   (!((x)|(y)))
  34.  
  35.  
  36. #define ZValid(z)     ((!UseSlabPlane) || ((z)<SlabValue))
  37. #define XValid(x)     (((x)>=0)&&((x)<XRange))
  38. #define YValid(y)     (((y)>=0)&&((y)<YRange))
  39. #define RootSix       2.44948974278
  40.  
  41. #define SETPIXEL(dptr,fptr,d,c)    if( (d) > *(dptr) )              \
  42.                                    {   *(dptr) = (d);               \
  43.                                        *(fptr) = (c);               \
  44.                                    }
  45.  
  46.  
  47. typedef struct {
  48.                 int x, y, z;
  49.                 int inten;
  50.                } Vertex;
  51.  
  52. typedef struct {
  53.                 short dx,dy,dz;
  54.                 short inten;
  55.         Long offset;
  56.            } ArcEntry;
  57.  
  58.  
  59. /* Note: DrawCylinderCaps currently employs an
  60.  *       extremely crude hack to avoid stripes
  61.  *       appearing along cylinders.
  62.  */
  63. #define ARCSIZE  2048
  64.  
  65. static ArcEntry __far *ArcAcPtr;
  66. static ArcEntry __far *ArcDnPtr;
  67. #ifdef IBMPC
  68. static ArcEntry __far *ArcAc;
  69. static ArcEntry __far *ArcDn;
  70. #else
  71. static ArcEntry ArcAc[ARCSIZE];
  72. static ArcEntry ArcDn[ARCSIZE];
  73. #endif
  74.  
  75.  
  76. static int ClipStatus;
  77.  
  78.  
  79. static int OutCode(x,y,z)
  80.     register int x,y,z;
  81. {
  82.     register int result;
  83.  
  84.     result=0;
  85.     if( y<0 )
  86.     {   result |= BitAbove;
  87.     } else if( y>=YRange )
  88.         result |= BitBelow;
  89.  
  90.     if( x<0 )
  91.     {   result |= BitLeft;
  92.     } else if( x>=XRange )
  93.         result |= BitRight;
  94.  
  95.     if( !ZValid(z) )
  96.         result |= BitFront;
  97.     return result;
  98. }
  99.  
  100.  
  101. #ifndef PIXUTILS  /* Unused Function */
  102. void PlotPoint(x,y,z,col)
  103.     int x,y,z,col;
  104. {
  105.     register Pixel __huge *fptr;
  106.     register short __huge *dptr;
  107.     register Long offset;
  108.  
  109.     /* SETPIXEL(dptr,fptr,z,Lut[col+ColourMask]); */
  110.  
  111.     offset = (Long)y*XRange+x;
  112.     dptr = DBuffer+offset;
  113.     if( z > *dptr )
  114.     {   fptr = FBuffer+offset;
  115.         *fptr = Lut[col+ColourMask];
  116.         *dptr = z;
  117.     }
  118. }
  119. #endif
  120.  
  121. #ifndef PIXUTILS  /* Unused Function */
  122. void ClipPoint(x,y,z,col)
  123.     int x,y,z,col;
  124. {
  125.     register Pixel __huge *fptr;
  126.     register short __huge *dptr;
  127.     register Long offset;
  128.  
  129.     if( XValid(x) && YValid(y) && ZValid(z) )
  130.     {   /* PlotPoint(x,y,z,col); */
  131.         offset = (Long)y*XRange+x;
  132.         dptr = DBuffer+offset;
  133.         if( z > *dptr )
  134.         {   fptr = FBuffer+offset;
  135.             *fptr = Lut[col+ColourMask];
  136.             *dptr = z;
  137.         }
  138.     }
  139. }
  140. #endif
  141.  
  142. #ifndef PIXUTILS  /* Unused Function */
  143. void PlotDeepPoint(x,y,z,col)
  144.     int x,y,z,col;
  145. {
  146.     register Long offset;
  147.     register Pixel __huge *fptr;
  148.     register short __huge *dptr;
  149.     register int inten;
  150.  
  151.     offset = (Long)y*XRange+x;
  152.     dptr = DBuffer+offset;
  153.  
  154.     if( z > *dptr )
  155.     {  fptr = FBuffer+offset;
  156.        inten = (int)((Long)(ColourDepth*z)/ImageSize);
  157.        *fptr = Lut[col+inten];
  158.        *dptr = z;
  159.     }
  160. }
  161. #endif
  162.  
  163. #ifndef PIXUTILS  /* Unused Function */
  164. void ClipDeepPoint(x,y,z,col)
  165.     int x,y,z,col;
  166. {
  167.     register Long offset;
  168.     register Pixel __huge *fptr;
  169.     register short __huge *dptr;
  170.     register int inten;
  171.  
  172.     if( XValid(x) && YValid(y) && ZValid(z) )
  173.     {   /* PlotDeepPoint(x,y,z,col); */
  174.         offset = (Long)y*XRange+x;
  175.         dptr = DBuffer+offset;
  176.  
  177.         if( z > *dptr )
  178.         {  fptr = FBuffer+offset;
  179.            inten = (int)((Long)(ColourDepth*z)/ImageSize);
  180.            *fptr = Lut[col+inten];
  181.            *dptr = z;
  182.         }
  183.     }
  184. }
  185. #endif
  186.  
  187.  
  188. /* Macros for Bresenhams Line Drawing Algorithm */
  189. #define CommonStep(s)  z1 += zrate; SETPIXEL(dptr,fptr,z1,c);     \
  190.                        if( (zerr+=dz)>0 ) { zerr-=(s); z1+=iz; }
  191.  
  192. #define XStep  { if((err+=dy)>0) { fptr+=ystep; dptr+=ystep; err-=dx; } \
  193.                  fptr+=ix; dptr+=ix; x1+=ix; CommonStep(dx); }
  194.  
  195. #define YStep  { if((err+=dx)>0) { fptr+=ix; dptr+=ix; err-=dy; } \
  196.                  fptr+=ystep; dptr+=ystep; y1+=iy; CommonStep(dy); }
  197.                      
  198.  
  199. void DrawTwinLine(x1,y1,z1,x2,y2,z2,col1,col2)
  200.     int x1,y1,z1,x2,y2,z2,col1,col2;
  201. {
  202.     register Long offset;
  203.     register Pixel __huge *fptr;
  204.     register short __huge *dptr;
  205.     register int zrate, zerr;
  206.     register int ystep,err;
  207.     register int ix,iy,iz;
  208.     register int dx,dy,dz;
  209.     register int mid;
  210.     register Pixel c;
  211.  
  212.     c = Lut[col1+ColourMask];
  213.  
  214.     offset = (Long)y1*XRange + x1;
  215.     fptr = FBuffer+offset;
  216.     dptr = DBuffer+offset;
  217.  
  218.     SETPIXEL(dptr,fptr,z1,c);
  219.  
  220.     dx = x2-x1;  dy = y2-y1; dz = z2-z1;
  221.     if( !dx && !dy ) return;
  222.  
  223.     ystep = XRange;
  224.     ix = iy = iz = 1;
  225.     if( dy<0 ) { dy = -dy; iy = -1; ystep = -ystep; }
  226.     if( dx<0 ) { dx = -dx; ix = -1; }
  227.     if( dz<0 ) { dz = -dz; iz = -1; }
  228.  
  229.     if( dx>dy )
  230.     {   zrate = dz/dx;  
  231.         dz -= dx*zrate;
  232.         err = zerr = -(dx>>1);
  233.  
  234.         if( col1 != col2 )
  235.         {   mid = (x1+x2)>>1;
  236.             while( x1!=mid ) XStep;
  237.             c = Lut[col2+ColourMask];
  238.         }
  239.         while( x1!=x2 ) XStep;
  240.     } else
  241.     {   zrate = dz/dy;
  242.         dz -= dy*zrate;
  243.         err = zerr = -(dy>>1);
  244.  
  245.         if( col1 != col2 )
  246.         {   mid = (y1+y2)>>1;
  247.             while( y1!=mid ) YStep;
  248.             c = Lut[col2+ColourMask];
  249.         }
  250.         while( y1!=y2 ) YStep;
  251.     }
  252. }
  253.  
  254.  
  255. static void ClipLine(x1,y1,z1,x2,y2,z2,col)
  256.     int x1,y1,z1,x2,y2,z2,col;
  257. {
  258.     register int code1,code2;
  259.     register int delta,rest;
  260.     register int temp;
  261.  
  262.     while( True )
  263.     {   code1 = OutCode(x1,y1,z2);
  264.         code2 = OutCode(x2,y2,z2);
  265.         if( Reject(code1,code2) ) return;
  266.         if( Accept(code1,code2) ) break;
  267.  
  268.         if( !code1 )
  269.         {   temp=x1; x1=x2; x2=temp;
  270.             temp=y1; y1=y2; y2=temp;
  271.             temp=z1; z1=z2; z2=temp;
  272.             code1 = code2;
  273.         }
  274.  
  275.         if( code1 & BitAbove )
  276.         {   delta = y2-y1;
  277.             x1 += (y1*(x1-x2))/delta;  
  278.             z1 += (y1*(z1-z2))/delta;
  279.             y1 = 0;
  280.         } else if( code1 & BitLeft )
  281.         {   delta = x2-x1;
  282.             y1 += (x1*(y1-y2))/delta;
  283.             z1 += (x1*(z1-z2))/delta;
  284.             x1 = 0;
  285.         } else if( code1 & BitRight )
  286.         {   delta = x2-x1;
  287.             temp=XRange-1; rest=temp-x1;
  288.             y1 += (rest*(y2-y1))/delta;
  289.             z1 += (rest*(z2-z1))/delta;
  290.             x1 = temp;
  291.         } else if( code1 & BitBelow )
  292.         {   delta = y2-y1;
  293.             temp=YRange-1; rest=temp-y1;
  294.             y1 += (rest*(x2-x1))/delta;
  295.             z1 += (rest*(z2-z1))/delta;
  296.             y1 = temp;
  297.         } else /* SLAB */
  298.         {   delta = z2-z1;
  299.             rest = SlabValue-z1;
  300.             x1+=(rest*(x2-x1))/delta;
  301.             y1+=(rest*(y2-y1))/delta;
  302.             z1 = SlabValue;
  303.         }
  304.     }
  305.     DrawTwinLine(x1,y1,z1,x2,y2,z2,col,col);
  306. }
  307.  
  308.  
  309. void ClipTwinLine(x1,y1,z1,x2,y2,z2,col1,col2)
  310.     int x1,y1,z1,x2,y2,z2,col1,col2;
  311. {
  312.     register int xmid,ymid,zmid;
  313.     register int code1,code2;
  314.  
  315.  
  316.     if( col1!=col2 )
  317.     {   code1 = OutCode(x1,y1,z1);
  318.         code2 = OutCode(x2,y2,z2);
  319.         if( !Reject(code1,code2) )
  320.         {   if( !Accept(code1,code2) )
  321.             {  xmid = (x1+x2)/2;
  322.                ymid = (y1+y2)/2;
  323.                zmid = (z1+z2)/2;
  324.                ClipLine(x1,y1,z1,xmid,ymid,zmid,col1);
  325.                ClipLine(xmid,ymid,zmid,x2,y2,z2,col2);
  326.             } else
  327.                DrawTwinLine(x1,y1,z1,x2,y2,z2,col1,col2);
  328.         }
  329.     } else
  330.         ClipLine(x1,y1,z1,x2,y2,z2,col1);
  331. }
  332.  
  333.  
  334.  
  335. /* Macros for 3D Bresenhams Vector Algorithm */
  336. #define CommonVectStep(s)  z1 += zrate;   c1 += crate;                    \
  337.                            SETPIXEL(dptr,fptr,z1,Lut[col+c1]);            \
  338.                            if( (zerr+=dz)>0 ) { zerr -= (s); z1 += iz; }  \
  339.                            if( (cerr+=dc)>0 ) { cerr -= (s); c1 += ic; }
  340.  
  341. #define XVectStep  { if((err+=dy)>0) { fptr+=ystep; dptr+=ystep; err-=dx; } \
  342.                      fptr+=ix; dptr+=ix; x1+=ix; CommonVectStep(dx); }
  343.  
  344. #define YVectStep  { if((err+=dx)>0) { fptr+=ix; dptr+=ix; err-=dy; } \
  345.                      fptr+=ystep; dptr+=ystep; y1+=iy; CommonVectStep(dy); }
  346.  
  347.  
  348. void DrawTwinVector(x1,y1,z1,x2,y2,z2,col1,col2)
  349.     int x1,y1,z1,x2,y2,z2,col1,col2;
  350. {
  351.     register Long offset;
  352.     register Pixel __huge *fptr;
  353.     register short __huge *dptr;
  354.     register int ix,iy,iz,ic;
  355.     register int dx,dy,dz,dc;
  356.     register int crate, cerr;
  357.     register int zrate, zerr;
  358.     register int ystep,err;
  359.     register int col, mid;
  360.     register int c1, c2;
  361.  
  362.     c1 = (ColourDepth*z1)/ImageSize;
  363.     c2 = (ColourDepth*z2)/ImageSize;
  364.  
  365.     offset = (Long)y1*XRange + x1;
  366.     fptr = FBuffer+offset;
  367.     dptr = DBuffer+offset;
  368.  
  369.     SETPIXEL(dptr,fptr,z1,Lut[col1+c1]);
  370.  
  371.     dx = x2 - x1;  dy = y2 - y1;
  372.     dz = z2 - z1;  dc = c2 - c1;
  373.     if( !dx && !dy ) return;
  374.  
  375.     ystep = XRange;
  376.     ix = iy = iz = ic = 1;
  377.     if( dy<0 ) { dy = -dy; iy = -1; ystep = -ystep; }
  378.     if( dx<0 ) { dx = -dx; ix = -1; }
  379.     if( dz<0 ) { dz = -dz; iz = -1; }
  380.     if( dc<0 ) { dc = -dc; ic = -1; }
  381.  
  382.     if( dx>dy )
  383.     {   zrate = dz/dx;  dz -= dx*zrate;
  384.         crate = dc/dx;  dc -= dx*crate;
  385.         err = zerr = cerr = -(dx>>1);
  386.         col = col1;
  387.  
  388.         if( col1 != col2 )
  389.         {   mid = (x1+x2)>>1;
  390.             while( x1!=mid ) XVectStep;
  391.             col = col2;
  392.         }
  393.         while( x1!=x2 ) XVectStep;
  394.     } else
  395.     {   zrate = dz/dy;  dz -= dy*zrate;
  396.         crate = dc/dy;  dc -= dy*crate;
  397.         err = zerr = cerr = -(dy>>1);
  398.         col = col1;
  399.  
  400.         if( col1 != col2 )
  401.         {   mid = (y1+y2)>>1;
  402.             while( y1!=mid ) YVectStep;
  403.             col=col2;
  404.         }
  405.         while( y1!=y2 ) YVectStep;
  406.     }
  407. }
  408.  
  409. static void ClipVector(x1,y1,z1,x2,y2,z2,col)
  410.     int x1,y1,z1,x2,y2,z2,col;
  411. {
  412.     register int code1,code2;
  413.     register int delta,rest;
  414.     register int temp;
  415.  
  416.     while( True )
  417.     {   code1 = OutCode(x1,y1,z2);
  418.         code2 = OutCode(x2,y2,z2);
  419.         if( Reject(code1,code2) ) return;
  420.         if( Accept(code1,code2) ) break;
  421.  
  422.         if( !code1 )
  423.         {   temp=x1; x1=x2; x2=temp;
  424.             temp=y1; y1=y2; y2=temp;
  425.             temp=z1; z1=z2; z2=temp;
  426.             code1 = code2;
  427.         }
  428.  
  429.         if( code1 & BitAbove )
  430.         {   delta = y2-y1;
  431.             x1 += (y1*(x1-x2))/delta;  
  432.             z1 += (y1*(z1-z2))/delta;
  433.             y1 = 0;
  434.         } else if( code1 & BitLeft )
  435.         {   delta = x2-x1;
  436.             y1 += (x1*(y1-y2))/delta;
  437.             z1 += (x1*(z1-z2))/delta;
  438.             x1 = 0;
  439.         } else if( code1 & BitRight )
  440.         {   delta = x2-x1;
  441.             temp=XRange-1; rest=temp-x1;
  442.             y1 += (rest*(y2-y1))/delta;
  443.             z1 += (rest*(z2-z1))/delta;
  444.             x1 = temp;
  445.         } else if( code1 & BitBelow )
  446.         {   delta = y2-y1;
  447.             temp=YRange-1; rest=temp-y1;
  448.             y1 += (rest*(x2-x1))/delta;
  449.             z1 += (rest*(z2-z1))/delta;
  450.             y1 = temp;
  451.         } else /* SLAB */
  452.         {   delta = z2-z1;
  453.             rest = SlabValue-z1;
  454.             x1+=(rest*(x2-x1))/delta;
  455.             y1+=(rest*(y2-y1))/delta;
  456.             z1 = SlabValue;
  457.         }
  458.     }
  459.     DrawTwinVector(x1,y1,z1,x2,y2,z2,col,col);
  460. }
  461.  
  462.  
  463. void ClipTwinVector(x1,y1,z1,x2,y2,z2,col1,col2)
  464.     int x1,y1,z1,x2,y2,z2,col1,col2;
  465. {
  466.     register int xmid,ymid,zmid;
  467.     register int code1,code2;
  468.  
  469.     if( col1!=col2 )
  470.     {   code1 = OutCode(x1,y1,z1);
  471.         code2 = OutCode(x2,y2,z2);
  472.         if( !Reject(code1,code2) )
  473.         {   if( !Accept(code1,code2) )
  474.             {  xmid = (x1+x2)/2;
  475.                ymid = (y1+y2)/2;
  476.                zmid = (z1+z2)/2;
  477.                ClipVector(x1,y1,z1,xmid,ymid,zmid,col1);
  478.                ClipVector(xmid,ymid,zmid,x2,y2,z2,col2);
  479.             } else
  480.                DrawTwinVector(x1,y1,z1,x2,y2,z2,col1,col2);
  481.         }
  482.     } else
  483.         ClipVector(x1,y1,z1,x2,y2,z2,col1);
  484. }
  485.  
  486.  
  487. void ClipDashVector(x1,y1,z1,x2,y2,z2,col1,col2)
  488.     int x1,y1,z1,x2,y2,z2,col1,col2;
  489. {
  490.     register Long offset;
  491.     register Pixel __huge *fptr;
  492.     register short __huge *dptr;
  493.     register int ix,iy,iz,ic;
  494.     register int dx,dy,dz,dc;
  495.     register int crate, cerr;
  496.     register int zrate, zerr;
  497.     register int ystep,err;
  498.     register int col, mid;
  499.     register int c1, c2;
  500.  
  501.  
  502.     if( (x1==x2) && (y1==y2) ) return;
  503.     if( Reject(OutCode(x1,y1,z1),OutCode(x2,y2,z2)) )
  504.         return;
  505.  
  506.     c1 = (ColourDepth*z1)/ImageSize;
  507.     c2 = (ColourDepth*z2)/ImageSize;
  508.  
  509.     dz = (z2 - z1)<<1;  
  510.     dc = (c2 - c1)<<1;
  511.     dx = x2 - x1;  
  512.     dy = y2 - y1;
  513.  
  514.     offset = (Long)y1*XRange + x1;
  515.     fptr = FBuffer+offset;
  516.     dptr = DBuffer+offset;
  517.  
  518.  
  519.     ystep = XRange;
  520.     ix = iy = iz = ic = 1;
  521.     if( dy<0 ) { dy = -dy; iy = -1; ystep = -ystep; }
  522.     if( dx<0 ) { dx = -dx; ix = -1; }
  523.     if( dz<0 ) { dz = -dz; iz = -1; }
  524.     if( dc<0 ) { dc = -dc; ic = -1; }
  525.  
  526.  
  527.     if( dx>dy )
  528.     {   if( x2<x1 )
  529.         {   mid = col1;
  530.             col1 = col2;
  531.             col2 = mid;
  532.         }
  533.         zrate = dz/dx;  dz -= dx*zrate;
  534.         crate = dc/dx;  dc -= dx*crate;
  535.         err = zerr = cerr = -(dx>>1);
  536.         mid = (x1+x2)/2;
  537.  
  538.         while( x1!=x2 )
  539.         {   if( XValid(x1) && YValid(y1) && ZValid(z1) )
  540.             {   col = (x1<mid)? col1 : col2;
  541.                 SETPIXEL(dptr,fptr,z1,Lut[col+c1]);
  542.             }
  543.  
  544.             if( (x1+ix)==x2 ) 
  545.                 break;
  546.  
  547.             if( (err+=dy+dy)>0 )
  548.                 if( (err-=dx)>0 )
  549.                 {   err-=dx;
  550.                     fptr+=ystep+ystep;
  551.                     dptr+=ystep+ystep;
  552.                     y1+=iy+iy;
  553.                 } else
  554.                 {   fptr+=ystep;
  555.                     dptr+=ystep;
  556.                     y1+=iy;
  557.                 }
  558.  
  559.             if( (zerr+=dz)>0 )
  560.                 if( (zerr-=dx)>0 )
  561.                 {   zerr -= dx;
  562.                     z1 += iz+iz;
  563.                 } else z1 += iz;
  564.  
  565.             if( (cerr+=dc)>0 )
  566.                 if( (cerr-=dx)>0 )
  567.                 {   cerr -= dx;
  568.                     c1 += ic+ic;
  569.                 } else c1 += ic;
  570.  
  571.             fptr+=ix+ix; dptr+=ix+ix; x1+=ix+ix;
  572.             z1 += zrate;   c1 += crate;
  573.         }
  574.     } else
  575.     {   if( y1>y2 )
  576.         {   mid = col1;
  577.             col1 = col2;
  578.             col2 = mid;
  579.         }
  580.  
  581.         zrate = dz/dy;  dz -= dy*zrate;
  582.         crate = dc/dy;  dc -= dy*crate;
  583.         err = zerr = cerr = -(dy>>1);
  584.         mid = (y1+y2)/2;
  585.  
  586.         
  587.         while( y1!=y2 )
  588.         {   if( XValid(x1) && YValid(y1) && ZValid(z1) )
  589.             {   col = (y1<mid)? col1 : col2;
  590.                 SETPIXEL(dptr,fptr,z1,Lut[col+c1]);
  591.             }
  592.  
  593.             if( (y1+iy)==y2 ) 
  594.                 break;
  595.  
  596.             if( (err+=dx+dx)>0 )
  597.                 if( (err-=dy)>0 )
  598.                 {   err-=dy;
  599.                     fptr+=ix+ix;
  600.                     dptr+=ix+ix;
  601.                     x1+=ix+ix;
  602.                 } else
  603.                 {   fptr+=ix;
  604.                     dptr+=ix;
  605.                     x1+=ix;
  606.                 }
  607.  
  608.             if( (zerr+=dz)>0 )
  609.                 if( (zerr-=dy)>0 )
  610.                 {   zerr -= dy;
  611.                     z1 += iz+iz;
  612.                 } else z1 += iz;
  613.  
  614.             if( (cerr+=dc)>0 )
  615.                 if( (cerr-=dy)>0 )
  616.                 {   cerr -= dy;
  617.                     c1 += ic+ic;
  618.                 } else c1 += ic;
  619.  
  620.             fptr+=ystep+ystep; dptr+=ystep+ystep; y1+=iy+iy;
  621.             z1 += zrate;   c1 += crate;
  622.         }
  623.     }
  624. }
  625.  
  626.  
  627. /* SplineCount is either 1, 2, 3, 4, 5 or 9! */
  628.  
  629. void StrandRibbon( src, dst, col )
  630.     Knot *src, *dst;  int col;
  631. {
  632.     register int hsx, hsy, hsz;
  633.     register int hdx, hdy, hdz;
  634.     register int qsx, qsy, qsz;
  635.     register int qdx, qdy, qdz;
  636.  
  637.     if( SplineCount != 4 )
  638.     {   if( SplineCount != 2 )
  639.         {   ClipVector( src->px, src->py, src->pz,
  640.                         dst->px, dst->py, dst->pz, col );
  641.             if( SplineCount==1 ) return;
  642.         }
  643.  
  644.         ClipVector( src->px+src->wx, src->py+src->wy, src->pz+src->wz,
  645.                     dst->px+dst->wx, dst->py+dst->wy, dst->pz+dst->wz, col );
  646.         ClipVector( src->px-src->wx, src->py-src->wy, src->pz-src->wz,
  647.                     dst->px-dst->wx, dst->py-dst->wy, dst->pz-dst->wz, col );
  648.         if( SplineCount<=3 ) return;
  649.  
  650.         hsx = src->wx/2;  hsy = src->wy/2;  hsz = src->wz/2;
  651.         hdx = dst->wx/2;  hdy = dst->wy/2;  hdz = dst->wz/2;
  652.  
  653.         ClipVector( src->px+hsx, src->py+hsy, src->pz+hsz,
  654.                     dst->px+hdx, dst->py+hdy, dst->pz+hdz, col );
  655.         ClipVector( src->px-hsx, src->py-hsy, src->pz-hsz,
  656.                     dst->px-hdx, dst->py-hdy, dst->pz-hdz, col );
  657.         if( SplineCount==5 ) return;
  658.     } else /* SplineCount == 4 */
  659.     {   hsx = src->wx/2;  hsy = src->wy/2;  hsz = src->wz/2;
  660.         hdx = dst->wx/2;  hdy = dst->wy/2;  hdz = dst->wz/2;
  661.     }
  662.  
  663.     qsx = hsx/2;  qsy = hsy/2;  qsz = hsz/2;
  664.     qdx = hdx/2;  qdy = hdy/2;  qdz = hdz/2;
  665.  
  666.     ClipVector( src->px+hsx+qsx, src->py+hsy+qsy, src->pz+hsz+qsz,
  667.                 dst->px+hdx+qdx, dst->py+hdy+qdy, dst->pz+hdz+qdz, col );
  668.     ClipVector( src->px+hsx-qsx, src->py+hsy-qsy, src->pz+hsz-qsz,
  669.                 dst->px+hdx-qdx, dst->py+hdy-qdy, dst->pz+hdz-qdz, col );
  670.     ClipVector( src->px-hsx+qsx, src->py-hsy+qsy, src->pz-hsz+qsz,
  671.                 dst->px-hdx+qdx, dst->py-hdy+qdy, dst->pz-hdz+qdz, col );
  672.     ClipVector( src->px-hsx-qsx, src->py-hsy-qsy, src->pz-hsz-qsz,
  673.                 dst->px-hdx-qdx, dst->py-hdy-qdy, dst->pz-hdz-qdz, col );
  674. }
  675.  
  676.  
  677. #ifndef PIXUTILS  /* Unused Function */
  678. static void OutLinePolygon( v1, v2, v3 )
  679.     Vertex *v1, *v2, *v3;
  680. {
  681.     ClipLine( v1->x, v1->y, v1->z, v2->x, v2->y, v2->z, v1->inten );
  682.     ClipLine( v2->x, v2->y, v2->z, v3->x, v3->y, v3->z, v2->inten );
  683.     ClipLine( v3->x, v3->y, v3->z, v1->x, v1->y, v1->z, v3->inten );
  684. }
  685. #endif
  686.  
  687.  
  688. static void RenderPolygon( v1, v2, v3 )
  689.     Vertex *v1, *v2, *v3;
  690. {
  691.     register Pixel __huge *fptr;
  692.     register short __huge *dptr;
  693.     register Long offset;
  694.  
  695.     register int startx, stopx;
  696.     register int startz, stopz;
  697.     register Real ratio;
  698.  
  699.     register Vertex *vtmp;
  700.     register int xmin, xmax;
  701.     register int ymin, ymax;
  702.     register int x,y,z;
  703.  
  704.     /* Sort increasing y! */
  705.     if( v1->y > v2->y )
  706.     {   vtmp = v2; 
  707.         v2 = v1; 
  708.         v1 = vtmp;
  709.     }
  710.  
  711.     if( v2->y > v3->y )
  712.     {   if( v1->y > v3->y )
  713.         {   vtmp = v3; 
  714.             v3 = v2;
  715.             v2 = v1; 
  716.             v1 = vtmp;
  717.         } else
  718.         {   vtmp = v3; 
  719.             v3 = v2; 
  720.             v2 = vtmp;
  721.         }
  722.     }
  723.  
  724.     /* Perform Polygon Y Culling! */
  725.     if( (v3->y < 0) || (v1->y >= YRange) )
  726.         return;
  727.  
  728.     xmin = MinFun(v1->x,v2->x);
  729.     xmax = MaxFun(v1->x,v2->x);
  730.     if( v3->x < xmin ) 
  731.     {   xmin = v3->x;
  732.     } else if( v3->x > xmax )
  733.         xmax = v3->x;
  734.  
  735.     if( (xmax < 0) || (xmin >= XRange) )
  736.         return;
  737.  
  738.     if( UseSlabPlane )  /* Perform Polygon Z Culling! */
  739.     {   if( (v1->z>=SlabValue) && (v2->z>=SlabValue) && (v3->z>=SlabValue) )
  740.             return;
  741.     }
  742.  
  743.  
  744.     if( v1->y == v3->y )
  745.         return;
  746.  
  747.     ymax = MinFun(v3->y,YRange-1);
  748.     ymin = MaxFun(v1->y,0);
  749.  
  750.     y = ymin;
  751.     offset = (Long)y*XRange;
  752.     while( y <= ymax )
  753.     {   if( y < v2->y )
  754.         {   ratio = (Real)(y - v1->y)/(v2->y - v1->y);
  755.             startx = (int)(ratio*(v2->x - v1->x)) + v1->x;
  756.             startz = (int)(ratio*(v2->z - v1->z)) + v1->z;
  757.         } else if( y > v2->y )
  758.         {   ratio = (Real)(y - v2->y)/(v3->y - v2->y);
  759.             startx = (int)(ratio*(v3->x - v2->x)) + v2->x;
  760.             startz = (int)(ratio*(v3->z - v2->z)) + v2->z;
  761.         } else /* y == v2->y */
  762.         {   startx = v2->x;
  763.             startz = v2->z;
  764.         }
  765.  
  766.         ratio = (float)(y - v1->y)/(v3->y - v1->y);
  767.         stopx = (int)(ratio*(v3->x - v1->x)) + v1->x;
  768.         stopz = (int)(ratio*(v3->z - v1->z)) + v1->z;
  769.  
  770.         if( startx < stopx )
  771.         {   xmin = startx;
  772.             xmax = stopx;
  773.         } else
  774.         {   xmax = startx;
  775.             xmin = stopx;
  776.         }
  777.  
  778.         if( xmax>=XRange )
  779.             xmax = XRange-1;
  780.         if( xmin<0 ) 
  781.             xmin = 0;
  782.  
  783.         z = (startz + stopz)/2;
  784.         fptr = FBuffer+offset+xmin;
  785.         dptr = DBuffer+offset+xmin;
  786.  
  787.         for( x=xmin; x<=xmax; x++ )
  788.             if( z > *dptr )
  789.             {   *fptr++ = Lut[v1->inten];
  790.                 *dptr++ = z;
  791.             } else 
  792.             {   fptr++;
  793.                 dptr++;
  794.             }
  795.         offset += XRange;
  796.         y++;
  797.     }
  798. }
  799.  
  800.  
  801. void SolidRibbon( src, dst, col )
  802.     Knot *src, *dst;  int col;
  803. {
  804.     auto Vertex v1, v2, v3;
  805.  
  806.     v1.x = src->px+src->wx;  
  807.     v1.y = src->py+src->wy;  
  808.     v1.z = src->pz+src->wz;
  809.     v1.inten = src->inten+col;
  810.  
  811.     v2.x = dst->px+dst->wx;  
  812.     v2.y = dst->py+dst->wy;  
  813.     v2.z = dst->pz+dst->wz;
  814.     v2.inten = dst->inten+col;
  815.  
  816.     v3.x = dst->px-dst->wx;
  817.     v3.y = dst->py-dst->wy;  
  818.     v3.z = dst->pz-dst->wz;
  819.     v3.inten = dst->inten+col;
  820.  
  821.     /* OutLinePolygon(&v1,&v2,&v3); */
  822.     RenderPolygon( &v1, &v2, &v3 );
  823.  
  824.     v2.x = src->px-src->wx;  
  825.     v2.y = src->py-src->wy;  
  826.     v2.z = src->pz-src->wz;
  827.     v2.inten = src->inten+col;
  828.  
  829.     /* OutLinePolygon(&v1,&v2,&v3); */
  830.     RenderPolygon( &v1, &v2, &v3 );
  831. }
  832.  
  833.  
  834.  
  835. static int TestSphere( x, y, z, rad )
  836.     register int x, y, z, rad;
  837. {
  838.     register int temp;
  839.  
  840.     ClipStatus = 0;
  841.  
  842.     if( UseSlabPlane )
  843.     {   if( z-rad>=SlabValue )
  844.             return( False );
  845.  
  846.         if( z+rad>=SlabValue )
  847.         {   if( SlabMode )
  848.             {   ClipStatus |= BitFront;
  849.             } else return( False );
  850.         } else if( SlabMode==SlabSection )
  851.             return( False );
  852.     }
  853.  
  854.     temp = y-rad;
  855.     if( temp>=YRange ) return( False );
  856.     if( temp<0 ) ClipStatus |= BitAbove;
  857.  
  858.     temp = y+rad;
  859.     if( temp<0 ) return( False );
  860.     if( temp>=YRange ) ClipStatus |= BitBelow;
  861.  
  862.     temp = x+rad;
  863.     if( temp<0 ) return( False );
  864.     if( temp>=XRange ) ClipStatus |= BitRight;
  865.  
  866.     temp = x-rad;
  867.     if( temp>=XRange ) return( False );
  868.     if( temp<0 ) ClipStatus |= BitLeft;
  869.  
  870.     return True;
  871. }
  872.  
  873.  
  874. #ifdef INVERT
  875. #define CalcInten(dz)    inten = (dz)+(dz)+dx+dy
  876. #else
  877. #define CalcInten(dz)    inten = (dz)+(dz)+dx-dy
  878. #endif
  879.  
  880. #define UpdateAcross(dz)    \
  881.         depth = (dz)+z;                    \
  882.         if( depth > *dptr )                \
  883.         {   *dptr = depth;                 \
  884.             fptr = fold+dx;                \
  885.             CalcInten((dz));               \
  886.             if( inten>0 )                  \
  887.             {      inten = (int)((inten*ColConst[rad])>>ColBits); \
  888.                    *fptr = Lut[col+inten]; \
  889.             } else *fptr = Lut[col];       \
  890.         }                                  \
  891.         dptr++;  dx++;
  892.  
  893.  
  894. #define UpdateLine  \
  895.         dx = -wide;                   \
  896.         dptr = dold-wide;             \
  897.         tptr = LookUp[wide]+wide;     \
  898.         while( dx<0 ) { UpdateAcross(*tptr); tptr--; }       \
  899.         do { UpdateAcross(*tptr); tptr++; } while(dx<=wide); \
  900.         dold += XRange;  fold += XRange;                     \
  901.         dy++;
  902.  
  903.  
  904. void DrawSphere(x,y,z,rad,col)
  905.     int x,y,z,rad,col;
  906. {
  907.     register Pixel __huge *fptr, __huge *fold;
  908.     register short __huge *dptr, __huge *dold;
  909.     register char __far *tptr;
  910.  
  911.     register Long offset;
  912.     register int depth,wide,inten;
  913.     register int dx,dy;
  914.  
  915.     offset = (Long)(y-rad)*XRange + x;
  916.     fold=FBuffer+offset;  
  917.     dold=DBuffer+offset;
  918.  
  919.     dy = -rad;
  920.     while( dy<0 ) 
  921.     {   wide = LookUp[rad][-dy]; 
  922.         UpdateLine; 
  923.     }
  924.  
  925.     do { 
  926.         wide = LookUp[rad][dy];  
  927.         UpdateLine; 
  928.     } while( dy<=rad );
  929. }
  930.  
  931.  
  932. void ClipSphere(x,y,z,rad,col)
  933.     int x,y,z,rad,col;
  934. {
  935.     register Pixel __huge *fptr, __huge *fold;
  936.     register short __huge *dptr, __huge *dold;
  937.  
  938.     register int lastx,lasty,dx,dy,dz;
  939.     register int depth,wide,inten,side;
  940.     register int crad,cwide,temp;
  941.     register Long offset;
  942.  
  943.  
  944.     /* Visibility Tests */
  945.     if( !TestSphere(x,y,z,rad) )
  946.         return;
  947.  
  948.     if( !ClipStatus )
  949.     {   DrawSphere(x,y,z,rad,col);
  950.         return;
  951.     }
  952.  
  953.     if( ClipStatus&BitAbove )
  954.     {   dy = -y;
  955.         fold = FBuffer + x;
  956.         dold = DBuffer + x;
  957.     } else
  958.     {   dy = -rad;
  959.         offset = (Long)(y+dy)*XRange+x;
  960.         fold = FBuffer + offset;
  961.         dold = DBuffer + offset;
  962.     }
  963.  
  964.     if( ClipStatus&BitBelow )
  965.     {   lasty = (YRange-1)-y;
  966.     } else lasty = rad;
  967.  
  968.  
  969.     side = (XRange-1)-x;
  970.     /* No Slab Plane Clipping */
  971.     if( !(ClipStatus&BitFront) )
  972.     {   while( dy<=lasty )
  973.         {   wide = LookUp[rad][AbsFun(dy)];
  974.             lastx = MinFun(wide,side);
  975.             dx = - MinFun(wide,x);
  976.             dptr = dold + dx;
  977.  
  978.             while( dx<=lastx )
  979.             {   dz = LookUp[wide][AbsFun(dx)];
  980.                 UpdateAcross(dz);
  981.             }
  982.             dold += XRange;
  983.             fold += XRange;
  984.             dy++;
  985.         }
  986.         return;
  987.     }
  988.  
  989.  
  990.     dz = SlabValue-z;
  991.     crad = LookUp[rad][AbsFun(dz)];
  992.  
  993.    
  994.     if( (z>SlabValue) || (SlabMode==SlabSection) )
  995.     {   if( crad<lasty ) lasty = crad;
  996.         if( -crad>dy ) 
  997.         {   dy = -crad;
  998.             offset = (Long)(y+dy)*XRange+x;
  999.             fold = FBuffer + offset;
  1000.             dold = DBuffer + offset;
  1001.         }
  1002.     }
  1003.  
  1004.     while( dy<=lasty )
  1005.     {   temp = AbsFun(dy);
  1006.         wide = LookUp[rad][temp];
  1007.         lastx = MinFun(wide,side);
  1008.         dx = - MinFun(x,wide);
  1009.         dptr = dold + dx;
  1010.  
  1011.         if( temp<=crad )
  1012.         {   cwide = LookUp[crad][temp];
  1013.             while( dx<=lastx )
  1014.             {   temp = AbsFun(dx);
  1015.                 if( temp<=cwide )
  1016.                 {    /* Slab Plane Clipping Modes */
  1017.                     switch( SlabMode )
  1018.                     {   case( SlabFinal ):
  1019.                                 fold[dx] = Lut[col+SlabInten];
  1020.                                 *dptr = SliceValue;
  1021.                                 break;
  1022.  
  1023.                         case( SlabHollow ):
  1024.                                 dz = LookUp[wide][temp];
  1025.                                 depth = z - dz;
  1026.                                 if( depth>*dptr )
  1027.                                 {   *dptr = depth;
  1028. #ifdef INVERT
  1029.                                     inten = dz+dz-dx-dy;
  1030. #else
  1031.                                     inten = dz+dz-dx+dy;
  1032. #endif
  1033.                                     if( inten>0 )
  1034.                                     {   inten=(int)( (inten*ColConst[rad])
  1035.                                                      >>(ColBits+1));
  1036.                                         fold[dx] = Lut[col+inten];
  1037.                                     } else fold[dx] = Lut[col];
  1038.                                 }
  1039.                                 break;
  1040.  
  1041.                         case( SlabSection ):
  1042.                         case( SlabClose ):
  1043.                                 dz = SlabValue-z;
  1044.                                 depth = dx*dx+dy*dy+dz*dz+SliceValue;
  1045.                                 if( (*dptr<SliceValue) || (depth<*dptr) )
  1046.                                 {   fold[dx] = Lut[col+SlabInten];
  1047.                                     *dptr = depth;
  1048.                                 }
  1049.                                 break;
  1050.                     }
  1051.                     dptr++;  dx++;
  1052.                 } else if( (z<SlabValue) && (SlabMode!=SlabSection) )
  1053.                 {    dz = LookUp[wide][temp];
  1054.                      UpdateAcross(dz);
  1055.                 } else
  1056.                 {   dptr++;  dx++;
  1057.                 }
  1058.             }
  1059.         } else /* Slabless ScanLine */
  1060.             while( dx<=lastx )
  1061.             {   dz = LookUp[wide][AbsFun(dx)];
  1062.                 UpdateAcross(dz);
  1063.             }
  1064.  
  1065.         dold += XRange;
  1066.         fold += XRange;
  1067.         dy++;
  1068.     }
  1069. }
  1070.  
  1071.  
  1072. #if defined(__STDC__) || defined(IBMPC)
  1073. /* Function Prototypes */
  1074. static void DrawArcDn( short __huge*, Pixel __huge*, int, int );
  1075. static void DrawArcAc( short __huge*, Pixel __huge*, int, int );
  1076. #endif
  1077.  
  1078.  
  1079. static void DrawArcAc(dbase,fbase,z,c)
  1080.     register short __huge *dbase;
  1081.     register Pixel __huge *fbase;
  1082.     register int z,c;
  1083. {
  1084.     register ArcEntry __far *ptr;
  1085.     register short __huge *dptr;
  1086.     register short depth;
  1087.  
  1088.     for( ptr=ArcAc; ptr<ArcAcPtr; ptr++ )
  1089.     {   dptr = dbase+ptr->offset;  depth = ptr->dz+z;
  1090.         SETPIXEL(dptr,fbase+ptr->offset,depth,Lut[ptr->inten+c]);
  1091.     }
  1092. }
  1093.  
  1094. static void DrawArcDn(dbase,fbase,z,c)
  1095.     register short __huge *dbase;
  1096.     register Pixel __huge *fbase;
  1097.     register int z,c;
  1098. {
  1099.     register ArcEntry __far *ptr;
  1100.     register short __huge *dptr;
  1101.     register short depth;
  1102.  
  1103.     for( ptr=ArcDn; ptr<ArcDnPtr; ptr++ )
  1104.     {   dptr = dbase+ptr->offset;  depth = ptr->dz+z;
  1105.         SETPIXEL(dptr,fbase+ptr->offset,depth,Lut[ptr->inten+c]);
  1106.     }
  1107. }
  1108.  
  1109.  
  1110. static void DrawCylinderCaps( x1,y1,z1,c1,x2,y2,z2,c2,rad )
  1111.     int x1,y1,z1,c1, x2,y2,z2,c2, rad;
  1112. {
  1113.     register short __huge *dold, __huge *dptr;
  1114.     register Pixel __huge *fold;
  1115.  
  1116.     register Long offset,temp,end;
  1117.     register int inten,zrate,absx;
  1118.     register int wide,depth;
  1119.     register int ix,iy,ax,ay;
  1120.     register int lx,ly,lz;
  1121.     register int dx,dy,dz;
  1122.  
  1123.     lx = x2-x1;
  1124.     ly = y2-y1;
  1125.     lz = z2-z1;
  1126.  
  1127.     if( ly>0 ) { ay = ly; iy = 1; }
  1128.     else { ay = -ly; iy = -1; }
  1129.     if( lx>0 ) { ax = lx; ix = 1; }
  1130.     else { ax = -lx; ix = -1; }
  1131.     zrate = lz/MaxFun(ax,ay);
  1132.  
  1133.  
  1134.     end = (Long)ly*XRange+lx;
  1135.     temp = (Long)y1*XRange+x1;
  1136.     fold = FBuffer+temp;
  1137.     dold = DBuffer+temp;
  1138.  
  1139.     ArcAcPtr = ArcAc;
  1140.     ArcDnPtr = ArcDn;
  1141.  
  1142.     temp = (Long)-(rad*XRange);
  1143.     for( dy= -rad; dy<=rad; dy++ )
  1144.     {   wide = LookUp[rad][AbsFun(dy)];
  1145.  
  1146.         for( dx= -wide; dx<=wide; dx++ )
  1147.         {   absx = AbsFun(dx);
  1148.             dz = LookUp[wide][absx];
  1149.             CalcInten(dz);
  1150.             if( inten>0 )
  1151.             {   inten = (int)((inten*ColConst[rad])>>ColBits);
  1152.             } else inten = 0;
  1153.             offset = temp+dx;
  1154.  
  1155.             if( XValid(x1+dx) && YValid(y1+dy) )
  1156.             {   dptr = dold+offset; depth = z1+dz;
  1157.                 SETPIXEL(dptr,fold+offset,depth,Lut[c1+inten]);
  1158.             }
  1159.  
  1160.             if( XValid(x2+dx) && YValid(y2+dy) )
  1161.             {   dptr = dold+(offset+end); depth = z2+dz;
  1162.                 SETPIXEL(dptr,fold+(offset+end),depth,Lut[c2+inten]);
  1163.             }
  1164.  
  1165. /*
  1166.             k1 = AbsFun(dx+ix); 
  1167.             k2 = AbsFun(dx-ix);
  1168.  
  1169.             if( ((k1>wide)||(dz>=LookUp[wide][k1]-zrate)) &&
  1170.                 ((k2>wide)||(dz>LookUp[wide][k2]+zrate)) )
  1171.  */
  1172.             {   ArcAcPtr->offset = offset; ArcAcPtr->inten = inten;
  1173.                 ArcAcPtr->dx=dx; ArcAcPtr->dy=dy; ArcAcPtr->dz=dz;
  1174.                 ArcAcPtr++;
  1175.             }
  1176.  
  1177. /*
  1178.             k1 = AbsFun(dy+iy);
  1179.             k2 = AbsFun(dy-iy);
  1180.  
  1181.             high = LookUp[rad][absx];
  1182.             if( ((k1>high)||(dz>=LookUp[LookUp[rad][k1]][absx]-zrate)) &&
  1183.                 ((k2>high)||(dz>LookUp[LookUp[rad][k2]][absx]+zrate)) )
  1184.  */
  1185.             {   ArcDnPtr->offset = offset; ArcDnPtr->inten = inten;
  1186.                 ArcDnPtr->dx=dx; ArcDnPtr->dy=dy; ArcDnPtr->dz=dz;
  1187.                 ArcDnPtr++;
  1188.             }
  1189.         }
  1190.         temp += XRange;
  1191.     }
  1192. }
  1193.  
  1194.  
  1195. void DrawCylinder( x1,y1,z1,c1,x2,y2,z2,c2,rad )
  1196.     int x1,y1,z1,c1, x2,y2,z2,c2, rad;
  1197. {
  1198.     register short __huge *dbase;
  1199.     register Pixel __huge *fbase;
  1200.  
  1201.     register int zrate,zerr,ystep,err;
  1202.     register int ix,iy,ax,ay;
  1203.     register int lx,ly,lz;
  1204.     register int mid,tmp;
  1205.     register Long temp;
  1206.  
  1207.  
  1208.     /* Trivial Case */
  1209.     if( (x1==x2) && (y1==y2) )
  1210.     {   if( z1>z2 )
  1211.         {      DrawSphere(x1,y1,z1,rad,c1);
  1212.         } else DrawSphere(x2,y2,z2,rad,c2);
  1213.         return;
  1214.     }
  1215.  
  1216.     if( z1<z2 )
  1217.     {   tmp=x1; x1=x2; x2=tmp;
  1218.         tmp=y1; y1=y2; y2=tmp;
  1219.         tmp=z1; z1=z2; z2=tmp;
  1220.         tmp=c1; c1=c2; c2=tmp;
  1221.     }
  1222.  
  1223.     DrawCylinderCaps(x1,y1,z1,c1,x2,y2,z2,c2,rad);
  1224.  
  1225.     lx = x2-x1;
  1226.     ly = y2-y1;
  1227.     lz = z2-z1;
  1228.  
  1229.     if( ly>0 ) { ystep = XRange; ay = ly; iy = 1; }
  1230.     else {   ystep = -XRange; ay = -ly; iy = -1; }
  1231.     if( lx>0 ) { ax = lx; ix = 1; }
  1232.     else { ax = -lx; ix = -1; }
  1233.     zrate = lz/MaxFun(ax,ay);
  1234.  
  1235.     temp = (Long)y1*XRange+x1;
  1236.     fbase = FBuffer+temp;
  1237.     dbase = DBuffer+temp;
  1238.  
  1239.     if( ax>ay )
  1240.     {   lz -= ax*zrate;
  1241.         zerr = err = -(ax>>1);
  1242.  
  1243.         if( c1 != c2 )
  1244.         {   mid = (x1+x2)>>1;
  1245.             while( x1!=mid )
  1246.             {   z1 += zrate;  if( (zerr-=lz)>0 ) { zerr-=ax; z1--; }
  1247.                 fbase+=ix; dbase+=ix; x1+=ix;
  1248.                 if( (err+=ay)>0 )
  1249.                 {   fbase+=ystep; dbase+=ystep; err-=ax;
  1250.                        DrawArcDn(dbase,fbase,z1,c1);
  1251.                 } else DrawArcAc(dbase,fbase,z1,c1);
  1252.             }
  1253.         }
  1254.  
  1255.         while( x1!=x2 )
  1256.         {   z1 += zrate;  if( (zerr-=lz)>0 ) { zerr-=ax; z1--; }
  1257.             fbase+=ix; dbase+=ix; x1+=ix;
  1258.             if( (err+=ay)>0 )
  1259.             {   fbase+=ystep; dbase+=ystep; err-=ax;
  1260.                    DrawArcDn(dbase,fbase,z1,c2);
  1261.             } else DrawArcAc(dbase,fbase,z1,c2);
  1262.         }
  1263.     } else /*ay>=ax*/
  1264.     {   lz -= ay*zrate;
  1265.         zerr = err = -(ay>>1);
  1266.  
  1267.         if( c1 != c2 )
  1268.         {   mid = (y1+y2)>>1;
  1269.             while( y1!=mid )
  1270.             {   z1 += zrate;  if( (zerr-=lz)>0 ) { zerr-=ay; z1--; }
  1271.                 fbase+=ystep; dbase+=ystep; y1+=iy;
  1272.                 if( (err+=ax)>0 )
  1273.                 {   fbase+=ix; dbase+=ix; err-=ay; 
  1274.                        DrawArcAc(dbase,fbase,z1,c1);
  1275.                 } else DrawArcDn(dbase,fbase,z1,c1);
  1276.             }
  1277.         }
  1278.  
  1279.         while( y1!=y2 )
  1280.         {   z1 += zrate;  if( (zerr-=lz)>0 ) { zerr-=ay; z1--; }
  1281.             fbase+=ystep; dbase+=ystep; y1+=iy;
  1282.             if( (err+=ax)>0 )
  1283.             {   fbase+=ix; dbase+=ix; err-=ay; 
  1284.                    DrawArcAc(dbase,fbase,z1,c2);
  1285.             } else DrawArcDn(dbase,fbase,z1,c2);
  1286.         }
  1287.     }
  1288. }
  1289.  
  1290.  
  1291. static int TestCylinder( x1,y1,z1,x2,y2,z2,rad )
  1292.     int x1,y1,z1,x2,y2,z2,rad;
  1293. {
  1294.     register int tmp1, tmp2;
  1295.  
  1296.     if( UseSlabPlane )
  1297.         if( (z1+rad>SlabValue) || (z2+rad>SlabValue) )
  1298.             return(False);
  1299.  
  1300.     ClipStatus = False;
  1301.  
  1302.     tmp1 = x1+rad;  tmp2 = x2+rad;
  1303.     if( (tmp1<0) && (tmp2<0) )
  1304.         return( False );
  1305.     if( (tmp1>=XRange) || (tmp2>=XRange) )
  1306.         ClipStatus = True;
  1307.  
  1308.     tmp1 = x1-rad;  tmp2 = x2-rad;
  1309.     if( (tmp1>=XRange) && (tmp2>=XRange) )
  1310.         return( False );
  1311.     if( (tmp1<0) || (tmp2<0) )
  1312.         ClipStatus = True;
  1313.  
  1314.     tmp1 = y1+rad;  tmp2 = y2+rad;
  1315.     if( (tmp1<0) && (tmp2<0) )
  1316.         return( False );
  1317.     if( (tmp1>=YRange) || (tmp2>=YRange) )
  1318.         ClipStatus = True;
  1319.  
  1320.     tmp1 = y1-rad;  tmp2 = y2-rad;
  1321.     if( (tmp1>=YRange) && (tmp2>=YRange) )
  1322.         return( False );
  1323.     if( (tmp1<0) || (tmp2<0) )
  1324.         ClipStatus = True;
  1325.  
  1326.     return( True );
  1327. }
  1328.  
  1329. #if defined(__STDC__) || defined(IBMPC)
  1330. /* Function Prototypes */
  1331. static void ClipArcDn( short __huge*, Pixel __huge*, int, int, int, int );
  1332. static void ClipArcAc( short __huge*, Pixel __huge*, int, int, int, int );
  1333. #endif
  1334.  
  1335.  
  1336. static void ClipArcAc(dbase,fbase,x,y,z,c)
  1337.     register short __huge *dbase;
  1338.     register Pixel __huge *fbase;
  1339.     register int x,y,z,c;
  1340. {
  1341.     register ArcEntry __far *ptr;
  1342.     register short __huge *dptr;
  1343.     register short depth;
  1344.     register int temp;
  1345.  
  1346.     ptr = ArcAc;
  1347.     while( (temp=y+ptr->dy) < 0 )
  1348.         if( ++ptr == ArcAcPtr )
  1349.             return;
  1350.  
  1351.     while( (temp<YRange) && (ptr<ArcAcPtr) )
  1352.     {   temp = x+ptr->dx;
  1353.         if( XValid(temp) )
  1354.         {   dptr = dbase+ptr->offset;  depth = ptr->dz+z;
  1355.             SETPIXEL(dptr,fbase+ptr->offset,depth,Lut[ptr->inten+c]);
  1356.         }
  1357.         ptr++;
  1358.         temp = y+ptr->dy;
  1359.     }
  1360. }
  1361.  
  1362. static void ClipArcDn(dbase,fbase,x,y,z,c)
  1363.     register short __huge *dbase;
  1364.     register Pixel __huge *fbase;
  1365.     register int x,y,z,c;
  1366. {
  1367.     register ArcEntry __far *ptr;
  1368.     register short __huge *dptr;
  1369.     register short depth;
  1370.     register int temp;
  1371.  
  1372.     ptr = ArcDn;
  1373.     while( (temp=y+ptr->dy) < 0 )
  1374.         if( ++ptr == ArcDnPtr )
  1375.             return;
  1376.  
  1377.     while( (temp<YRange) && (ptr<ArcDnPtr) )
  1378.     {   temp = x+ptr->dx;
  1379.         if( XValid(temp) )
  1380.         {   dptr = dbase+ptr->offset;  depth = ptr->dz+z;
  1381.             SETPIXEL(dptr,fbase+ptr->offset,depth,Lut[ptr->inten+c]);
  1382.         }
  1383.         ptr++;
  1384.         temp = y+ptr->dy;
  1385.     }
  1386. }
  1387.  
  1388.  
  1389. void ClipCylinder( x1,y1,z1,c1,x2,y2,z2,c2,rad )
  1390.     int x1,y1,z1,c1, x2,y2,z2,c2, rad;
  1391. {
  1392.     register short __huge *dbase;
  1393.     register Pixel __huge *fbase;
  1394.  
  1395.     register int zrate,zerr,ystep,err;
  1396.     register int ix,iy,ax,ay;
  1397.     register int lx,ly,lz;
  1398.     register int mid,tmp;
  1399.     register Long temp;
  1400.  
  1401.     /* Visibility Tests */
  1402.     if( !TestCylinder(x1,y1,z1,x2,y2,z2,rad) )
  1403.         return;
  1404.  
  1405.     if( !ClipStatus )
  1406.     {   DrawCylinder(x1,y1,z1,c1,x2,y2,z2,c2,rad);
  1407.         return;
  1408.     }
  1409.  
  1410.     /* Trivial Case */
  1411.     if( (x1==x2) && (y1==y2) )
  1412.     {   if( z1>z2 )
  1413.         {      ClipSphere(x1,y1,z1,rad,c1);
  1414.         } else ClipSphere(x2,y2,z2,rad,c2);
  1415.         return;
  1416.     }
  1417.  
  1418.     if( z1<z2 )
  1419.     {   tmp=x1; x1=x2; x2=tmp;
  1420.         tmp=y1; y1=y2; y2=tmp;
  1421.         tmp=z1; z1=z2; z2=tmp;
  1422.         tmp=c1; c1=c2; c2=tmp;
  1423.     }
  1424.  
  1425.     DrawCylinderCaps(x1,y1,z1,c1,x2,y2,z2,c2,rad);
  1426.  
  1427.     lx = x2-x1;
  1428.     ly = y2-y1;
  1429.     lz = z2-z1;
  1430.  
  1431.     if( ly>0 ) { ystep = XRange; ay = ly; iy = 1; }
  1432.     else {   ystep = -XRange; ay = -ly; iy = -1; }
  1433.     if( lx>0 ) { ax = lx; ix = 1; }
  1434.     else { ax = -lx; ix = -1; }
  1435.     zrate = lz/MaxFun(ax,ay);
  1436.  
  1437.     temp = (Long)y1*XRange+x1;
  1438.     fbase = FBuffer+temp;
  1439.     dbase = DBuffer+temp;
  1440.  
  1441.     if( ax>ay )
  1442.     {   if( x2<x1 )
  1443.         {   tmp = c1;
  1444.             c1 = c2;
  1445.             c2 = tmp;
  1446.         }
  1447.         lz -= ax*zrate;
  1448.         zerr = err = -(ax>>1);
  1449.         mid = (x1+x2)/2;
  1450.  
  1451.         while( x1!=x2 )
  1452.         {   z1 += zrate;  if( (zerr-=lz)>0 ) { zerr-=ax; z1--; }
  1453.             fbase+=ix; dbase+=ix; x1+=ix;
  1454.             if( (err+=ay)>0 )
  1455.             {   fbase += ystep;  err -= ax;
  1456.                 dbase += ystep;  y1 += iy;
  1457.                    ClipArcDn(dbase,fbase,x1,y1,z1,(x1<mid?c1:c2));
  1458.             } else ClipArcAc(dbase,fbase,x1,y1,z1,(x1<mid?c1:c2));
  1459.         }
  1460.     } else /*ay>=ax*/
  1461.     {   if( y2<y1 )
  1462.         {   tmp = c1;
  1463.             c1 = c2;
  1464.             c2 = tmp;
  1465.         }
  1466.         lz -= ay*zrate;
  1467.         zerr = err = -(ay>>1);
  1468.         mid = (y1+y2)/2;
  1469.  
  1470.         while( y1!=y2 )
  1471.         {   z1 += zrate;  if( (zerr-=lz)>0 ) { zerr-=ay; z1--; }
  1472.             fbase+=ystep; dbase+=ystep; y1+=iy;
  1473.             if( (err+=ax)>0 )
  1474.             {   fbase += ix;  err -= ay;
  1475.                 dbase += ix;  x1 += ix; 
  1476.                    ClipArcAc(dbase,fbase,x1,y1,z1,(y1<mid?c1:c2));
  1477.             } else ClipArcDn(dbase,fbase,x1,y1,z1,(y1<mid?c1:c2));
  1478.         }
  1479.     }
  1480. }
  1481.  
  1482.  
  1483. void InitialisePixUtils()
  1484. {
  1485. #ifdef IBMPC
  1486.     ArcAc = (ArcEntry __far*)_fmalloc(ARCSIZE*sizeof(ArcEntry));
  1487.     ArcDn = (ArcEntry __far*)_fmalloc(ARCSIZE*sizeof(ArcEntry));
  1488. #endif
  1489.     SplineCount = 5;
  1490. }
  1491.  
  1492.  
  1493.