home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Educational / RasMol / Source / render.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-18  |  46.3 KB  |  1,839 lines

  1. /* render.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, August 1995
  4.  * Version 2.6
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <windows.h>
  10. #include <malloc.h>
  11. #endif
  12. #ifdef APPLEMAC
  13. #include <Types.h>
  14. #include <Errors.h>
  15. #ifdef __CONDITIONALMACROS__
  16. #include <Printing.h>
  17. #else
  18. #include <PrintTraps.h>
  19. #endif
  20. #endif
  21. #ifndef sun386
  22. #include <stdlib.h>
  23. #endif
  24.  
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <stdio.h>
  28. #include <math.h>
  29.  
  30. #define RENDER
  31. #include "molecule.h"
  32. #include "graphics.h"
  33. #include "render.h"
  34. #include "repres.h"
  35. #include "abstree.h"
  36. #include "transfor.h"
  37. #include "command.h"
  38. #include "pixutils.h"
  39.  
  40. /* Avoid PowerPC Errors! */
  41. #ifdef INFINITY
  42. #undef INFINITY
  43. #endif
  44.  
  45. #define PoolSize        16
  46. #define RootSix         2.4494897427831780
  47. #define OneOverRootSix  0.4082482904638630
  48. #define TwoOverRootSix  0.8164965809277260
  49. #define ApproxZero      1.0E-3
  50. #define INFINITY       200000
  51. #define FUDGEFACTOR    1000
  52.  
  53.  
  54.  
  55. typedef struct { Real h,l; } Interval;
  56.  
  57.  
  58. static Atom __far * __far *YBucket;
  59. static Atom __far * __far *IBuffer;
  60. static int BuckY,ItemX;
  61. static int FBufX,FBufY;
  62. static int DBClear;
  63.  
  64. static Atom __far *SBuffer;
  65. static Atom __far *Exclude;
  66. static Real ShadowI, ShadowJ, ShadowK;
  67. static int  ShadowX, ShadowY, ShadowZ;
  68. static int deltax, deltay, deltaz;
  69. static int xcord, ycord, zcord;
  70. static int xflag, yflag, zflag;
  71. static int xhash, yhash, zhash;
  72. static int RayCount;
  73.  
  74. static Item __far *FreeItem;
  75. static Real VoxRatio;
  76. static int VoxelCount,InVoxCount;
  77. static int ProbeCount;
  78. static int VoxelsDone;
  79.  
  80. /* Identified Atom Info */
  81. static AtomRef PickHist[4];
  82. static Long IdentDist;
  83. static int IdentFound;
  84. static int IdentDepth;
  85. static int PickCount;
  86. static int PickMode;
  87.  
  88.  
  89. /* Macros for commonly used loops */
  90. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  91.              for(group=chain->glist;group;group=group->gnext)    \
  92.              for(aptr=group->alist;aptr;aptr=aptr->anext)
  93. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  94. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  95.              for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  96.  
  97.  
  98.  
  99.  
  100. static void FatalRenderError(ptr)
  101.     char *ptr;
  102. {
  103.     char buffer[80];
  104.  
  105.     sprintf(buffer,"Renderer Error: Unable to allocate %s!",ptr);
  106.     RasMolFatalExit(buffer);
  107. }
  108.  
  109.  
  110. int isqrt( val )
  111.     Card val;
  112. {
  113. #ifndef sun386
  114.     register int i,result;
  115.     register Card temp;
  116.     register Card rem;
  117.  
  118.     i = 16;
  119.     while( !(val&((Card)3<<30)) && i )
  120.     {   val <<= 2;
  121.         i--;
  122.     }
  123.  
  124.     if( i )
  125.     {   rem = (val>>30)-1;
  126.         val <<= 2;
  127.         result = 1;
  128.         i--;
  129.  
  130.         while( i )
  131.         {   rem = (rem<<2) | (val>>30);
  132.             result <<= 1;
  133.             val <<= 2;
  134.  
  135.             temp = result<<1;
  136.             if( rem > temp )
  137.             {   rem -= temp|1;
  138.                 result |= 1;
  139.             }
  140.             i--;
  141.         }
  142.         return( result );
  143.     } else return( 0 );
  144. #else
  145.     return( (int)sqrt((double)val) );
  146. #endif
  147. }
  148.  
  149.  
  150. /*=============================*/
  151. /*  ClearBuffers Subroutines!  */
  152. /*=============================*/
  153.  
  154. #ifdef IBMPC
  155. /* Windows NT vs Microsoft C vs Borland Turbo C */
  156. static void ClearMemory( register char __huge*, register long );
  157.  
  158. static void ClearMemory( ptr, count )
  159.     register char __huge *ptr;
  160.     register long count;
  161. {
  162. #ifndef _WIN32
  163. #ifdef __TURBOC__
  164.     register long left;
  165.     register int off;
  166.  
  167.     off = OFFSETOF(ptr);
  168.     if( off )
  169.     {   left = 65536 - off;
  170.         if( count < left )
  171.         {   _fmemset(ptr,0,(size_t)count);
  172.             return;
  173.         } else
  174.         {   _fmemset(ptr,0,(size_t)left);
  175.             count -= left;
  176.             ptr += left;
  177.         }
  178.     }
  179.  
  180.     while( count > 65535 )
  181.     {   _fmemset(ptr,0,(size_t)65535);
  182.         count -= 65536;
  183.         ptr += 65535;
  184.         *ptr++ = '\0';
  185.     }
  186.  
  187.     if( count )
  188.         _fmemset(ptr,0,(size_t)count);
  189. #else /* Microsoft C/C++ */
  190.     while( count > 65534 )
  191.     {   _fmemset(ptr,0,(size_t)65534);
  192.         count -= 65534;
  193.     ptr += 65534;
  194.     }
  195.     if( count )
  196.         _fmemset(ptr,0,(size_t)count);
  197. #endif
  198. #else  /* Windows NT  */
  199.     memset(ptr,0,(size_t)count);
  200. #endif /* Windows NT */
  201. }
  202.  
  203. void ClearBuffers()
  204. {
  205.     register char __huge *ptr;
  206.  
  207.     if( !FBClear )
  208.     {   FBClear = True;
  209.     ptr = (Pixel __huge*)GlobalLock(FBufHandle);
  210.         ClearMemory(ptr,(Long)XRange*YRange);
  211.     GlobalUnlock(FBufHandle);
  212.     }
  213.  
  214.     if( !DBClear )
  215.     {   DBClear = True;
  216.     ptr = (char __huge*)GlobalLock(DBufHandle);
  217.         ClearMemory(ptr,(Long)XRange*YRange*sizeof(short));
  218.     GlobalUnlock(DBufHandle);
  219.     }
  220. }
  221. #else
  222. #if defined(VMS) || defined(__sgi)        /* memset */
  223. void ClearBuffers()
  224. {
  225. #ifndef EIGHTBIT
  226.     register Long *ptr;
  227.     register Long *end;
  228.     register Long fill;
  229.  
  230.     if( !FBClear )
  231.     {   FBClear = True;
  232.     fill = Lut[BackCol];
  233.     ptr = (Long*)FBuffer;
  234.     end = (Long*)(FBuffer+(Long)XRange*YRange);
  235.     do { *ptr++=fill; *ptr++=fill;
  236.          *ptr++=fill; *ptr++=fill;
  237.     } while( ptr<end );
  238.     }
  239. #else
  240.     if( !FBClear )
  241.     {   FBClear = True;
  242.         memset(FBuffer,Lut[BackCol],(Long)XRange*YRange);
  243.     }
  244. #endif
  245.  
  246.     if( !DBClear )
  247.     {   DBClear = True;
  248.         memset(DBuffer,0,(Long)XRange*YRange*sizeof(short));
  249.     }
  250. }
  251.  
  252. #else /* !memset */
  253. void ClearBuffers()
  254. {
  255.     register Long *ptr;
  256.     register Long *end;
  257.     register Long fill;
  258.  
  259.     if( !FBClear )
  260.     {   FBClear = True;
  261.     fill = Lut[BackCol];
  262. #ifdef EIGHTBIT
  263.     fill |= fill<<8;
  264.     fill |= fill<<16;
  265. #endif
  266. #ifdef SIXTEENBIT
  267.     fill |= fill<<16;
  268. #endif
  269.     ptr = (Long*)FBuffer;
  270.     end = (Long*)(FBuffer+(Long)XRange*YRange);
  271.     do { *ptr++=fill; *ptr++=fill;
  272.          *ptr++=fill; *ptr++=fill;
  273.     } while( ptr<end );
  274.     }
  275.  
  276.     if( !DBClear )
  277.     {   DBClear = True;
  278.     ptr = (Long*)DBuffer;
  279.     end = (Long*)(DBuffer+(Long)XRange*YRange);
  280.     do { *ptr++=0; *ptr++=0;
  281.          *ptr++=0; *ptr++=0;
  282.     } while( ptr<end );
  283.     }
  284. }
  285. #endif /* !memset    */
  286. #endif /* UNIX & VMS */
  287.  
  288.  
  289.  
  290.  
  291. void ReAllocBuffers()
  292. {
  293.     register Atom __far * __far *iptr;
  294.     register int index,len;
  295.     register Long temp;
  296.  
  297.     temp = (Long)XRange*YRange*sizeof(short)+32;
  298. #ifdef IBMPC
  299.     if( DBufHandle ) GlobalFree(DBufHandle);
  300.     DBufHandle = GlobalAlloc(GMEM_MOVEABLE,temp);
  301.     if( !DBufHandle ) FatalRenderError("depth buffer");
  302. #else
  303.     if( DBuffer ) _ffree( DBuffer );
  304.     DBuffer = (short*)_fmalloc( temp );
  305.     if( !DBuffer ) FatalRenderError("depth buffer");
  306. #endif
  307.     DBClear=False;
  308.  
  309.     if( YBucket && (BuckY<YRange) )
  310.     {   _ffree(YBucket); 
  311.     YBucket=(void __far*)0; 
  312.     }
  313.  
  314.     if( !YBucket )
  315.     {   len = YRange*sizeof(Atom __far*);
  316.     YBucket = (Atom __far* __far*)_fmalloc( len );
  317.     if( !YBucket ) FatalRenderError("Y buckets");
  318.     BuckY = YRange;
  319.     }
  320.  
  321.     if( IBuffer && (ItemX<XRange) )
  322.     {   _ffree(IBuffer); 
  323.     IBuffer=(void __far*)0; 
  324.     }
  325.  
  326.     if( !IBuffer )
  327.     {   len = (XRange+4)*sizeof(Atom __far*);
  328.     IBuffer = (Atom __far* __far*)_fmalloc(len);
  329.     if( !IBuffer ) FatalRenderError("item buffer");
  330.     len = XRange>>2;  iptr = IBuffer;
  331.     for( index=0; index<=len; index++ )
  332.     {   *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  333.         *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  334.     }
  335.     ItemX = XRange;
  336.     }
  337. }
  338.  
  339.  
  340. void ReSizeScreen()
  341. {
  342.     register Real orig;
  343.  
  344.     if( Range != ZoomRange )
  345.     {   orig = MaxZoom;
  346.     MaxZoom = 0.236*(WorldSize+1000)/Range;
  347.     ZoomRange = Range;  MaxZoom -= 1.0;
  348.  
  349.     /* Handle Change in MaxZoom */
  350.     if( DialValue[3]>0.0 )
  351.     {   DialValue[3] *= orig/MaxZoom;
  352.         if( DialValue[3]>1.0 )
  353.         DialValue[3] = 1.0;
  354.     }
  355.     }
  356.  
  357. #ifdef IBMPC
  358.     if( !FBufHandle || (FBufX!=XRange) || (FBufY!=YRange) )
  359. #else /* UNIX */
  360.     if( !FBuffer || (FBufX!=XRange) || (FBufY!=YRange) )
  361. #endif
  362.     {   if( !CreateImage() )
  363.         FatalRenderError("frame buffer");
  364.  
  365.     BucketFlag = False;
  366.     FBufX=XRange;  FBufY=YRange;  FBClear = False;
  367.     ReAllocBuffers();
  368.     ClearBuffers();
  369.     }
  370. }
  371.  
  372.  
  373.  
  374. static void PrepareYBucket()
  375. {
  376.     register Atom __far * __far *temp;
  377.     register Chain __far *chain;
  378.     register Group __far *group;
  379.     register Atom __far *aptr;
  380.     register int scan;
  381.     register int rad;
  382.  
  383.     temp = YBucket;
  384.     for( scan=0; scan<BuckY; scan++ )
  385.     *temp++ = (void __far*)0;
  386.  
  387.     if( UseClipping )
  388.     {   ForEachAtom
  389.         if( aptr->flag&SphereFlag )
  390.         {   rad = aptr->irad;
  391.         if( (aptr->x-rad>=XRange) || 
  392.             (aptr->x+rad<0) || (aptr->y+rad<0) )
  393.             continue;
  394.         if( (scan=aptr->y-rad) > BuckY ) continue;
  395.  
  396.         if( scan>0 )
  397.         {   aptr->bucket = YBucket[scan];
  398.             YBucket[scan] = aptr;
  399.         } else
  400.         {   aptr->bucket = *YBucket;
  401.             *YBucket = aptr;
  402.         }
  403.         }
  404.     } else
  405.     ForEachAtom
  406.         if( aptr->flag&SphereFlag )
  407.         {   scan = aptr->y-aptr->irad;
  408.         aptr->bucket = YBucket[scan];
  409.         YBucket[scan] = aptr;
  410.         }
  411.     BucketFlag = True;
  412. }
  413.  
  414. #ifdef FUNCPROTO
  415. /* Function Prototypes */
  416. static void SqrInterval( Interval __far* );
  417. static void VoxelInsert( Atom __far*, int );
  418. static int AtomInter( Atom __far* );
  419. #endif
  420.  
  421.  
  422. static void SqrInterval( ival )
  423.     Interval __far *ival;
  424. {   register Real l,h;
  425.  
  426.     l = ival->l;
  427.     h = ival->h;
  428.  
  429.     if( l>=0.0 )
  430.     {   ival->l = l*l;
  431.     ival->h = h*h;
  432.     } else if( h<0.0 )
  433.     {   ival->l = h*h;
  434.     ival->h = l*l;
  435.     } else
  436.     {   ival->h = (-l>h)? l*l : h*h;
  437.     ival->l = 0.0;
  438.     }
  439. }
  440.  
  441. static void VoxelInsert( ptr, ref )
  442.     Atom __far *ptr;
  443.     int ref;
  444. {
  445.     register Item __far *datum;
  446.     register int i;
  447.  
  448.     if( !FreeItem )
  449.     {   datum = (Item __far*)_fmalloc( PoolSize*sizeof(Item) );
  450.     if( !datum ) FatalRenderError("voxel item");
  451.     for( i=1; i<PoolSize; i++ )
  452.     {   datum->list = FreeItem;
  453.         FreeItem = datum++;
  454.     }
  455.     } else
  456.     {   datum = FreeItem;
  457.     FreeItem = datum->list;
  458.     }
  459.     datum->data = ptr;
  460.     InVoxCount++;
  461.  
  462.     if( !HashTable[ref] ) VoxelCount++;
  463.     datum->list = (Item __far*)HashTable[ref];
  464.     HashTable[ref] = (void __far*)datum;
  465. }
  466.  
  467.  
  468. void ResetVoxelData()
  469. {
  470.     register Item __far *datum;
  471.     register int i;
  472.  
  473.     if( VoxelsDone )
  474.     {   for( i=0; i<VOXSIZE; i++ )
  475.         if( HashTable[i] )
  476.         {   datum = (Item __far*)HashTable[i];
  477.                 while( datum->list ) datum = datum->list;
  478.         datum->list = FreeItem;
  479.         FreeItem = (Item __far*)HashTable[i];
  480.         HashTable[i] = (void __far*)0;
  481.         }
  482.     VoxelsDone = False;
  483.     } else for( i=0; i<VOXSIZE; i++ )
  484.     HashTable[i] = (void __far*)0;
  485.     VoxelsClean = True;
  486. }
  487.  
  488.  
  489. void CreateVoxelData( flag )
  490.     int flag;
  491. {
  492.     static Interval ix, iy, iz;
  493.     register int lvx, lvy, lvz;
  494.     register int hvx, hvy, hvz;
  495.     register Long mx, my, mz;
  496.     register int px, py, pz;
  497.     register int i, rad;
  498.     register Real radius2;
  499.  
  500.     register Chain __far *chain;
  501.     register Group __far *group;
  502.     register Atom __far *aptr;
  503.  
  504.  
  505.     ResetVoxelData();
  506.     ProbeCount = InVoxCount = VoxelCount = 0;
  507.     VoxRatio = (Real)SideLen/VOXORDER;
  508.     IVoxRatio = 1.0/VoxRatio;
  509.     VoxelsDone = True;
  510.  
  511.     ForEachAtom
  512.     if( aptr->flag & flag )
  513.     {   mx = aptr->xorg+Offset;
  514.     my = aptr->yorg+Offset;
  515.     mz = aptr->zorg+Offset;
  516.     if( flag != SphereFlag )
  517.     {   if( SolventDots || !ProbeRadius )
  518.         {   rad = ElemVDWRadius(aptr->elemno);
  519.         } else rad = ProbeRadius;
  520.     } else rad = aptr->radius;  
  521.     radius2 = (Long)rad*rad;
  522.  
  523.     lvx = (int)((mx-rad)*IVoxRatio);  hvx = (int)((mx+rad)*IVoxRatio);
  524.     lvy = (int)((my-rad)*IVoxRatio);  hvy = (int)((my+rad)*IVoxRatio);
  525.     lvz = (int)((mz-rad)*IVoxRatio);  hvz = (int)((mz+rad)*IVoxRatio);
  526.  
  527.  
  528.     for( px=lvx; px<=hvx; px++ )
  529.     {   ix.l=px*VoxRatio-mx;
  530.         ix.h=ix.l+VoxRatio;  
  531.         SqrInterval(&ix);
  532.         i = VOXORDER2*px + VOXORDER*lvy;
  533.        
  534.         for( py=lvy; py<=hvy; py++ )
  535.         {   iy.l=py*VoxRatio-my;
  536.         iy.h=iy.l+VoxRatio;
  537.         SqrInterval(&iy);
  538.         
  539.         for( pz=lvz; pz<=hvz; pz++ )
  540.         {   iz.l=pz*VoxRatio-mz; 
  541.             iz.h=iz.l+VoxRatio;
  542.             SqrInterval(&iz);
  543.  
  544. #ifdef ORIG
  545.                     /* Test for surface voxels */
  546.             if( ((ix.l+iy.l+iz.l)<radius2) && 
  547.             ((ix.h+iy.h+iz.h)>radius2) )
  548.             VoxelInsert( aptr, i+pz );
  549. #else
  550.                     /* Test for contained voxels */
  551.                     if( ix.l+iy.l+iz.l < radius2 )
  552.             VoxelInsert( aptr, i+pz );
  553. #endif
  554.         } /*pz*/
  555.         i += VOXORDER;
  556.         } /*py*/
  557.     } /*px*/
  558.     }
  559. }
  560.  
  561.  
  562. void ShadowTransform()
  563. {
  564.     ShadowI = OneOverRootSix*(RotX[0]-RotY[0]+RotZ[0]+RotZ[0]);
  565.     ShadowK = OneOverRootSix*(RotX[2]-RotY[2]+RotZ[2]+RotZ[2]);
  566. #ifdef INVERT
  567.     ShadowJ = -OneOverRootSix*(RotX[1]-RotY[1]+RotZ[1]+RotZ[1]);
  568. #else
  569.     ShadowJ =  OneOverRootSix*(RotX[1]-RotY[1]+RotZ[1]+RotZ[1]);
  570. #endif
  571.  
  572.     if( ShadowI>ApproxZero )
  573.     {   deltax =  (int)(FUDGEFACTOR/ShadowI); xhash =  VOXORDER2; xflag =  1;
  574.     } else if( ShadowI<-ApproxZero )
  575.     {   deltax = -(int)(FUDGEFACTOR/ShadowI); xhash = -VOXORDER2; xflag = -1;
  576.     } else xflag = 0;
  577.  
  578.     if( ShadowJ>ApproxZero )
  579.     {   deltay =  (int)(FUDGEFACTOR/ShadowJ); yhash =  VOXORDER; yflag =  1;
  580.     } else if( ShadowJ<-ApproxZero )
  581.     {   deltay = -(int)(FUDGEFACTOR/ShadowJ); yhash = -VOXORDER; yflag = -1;
  582.     } else yflag = 0;
  583.  
  584.     if( ShadowK>ApproxZero )
  585.     {   deltaz =  (int)(FUDGEFACTOR/ShadowK); zhash = zflag =  1;
  586.     } else if( ShadowK<-ApproxZero )
  587.     {   deltaz = -(int)(FUDGEFACTOR/ShadowK); zhash = zflag = -1;
  588.     } else zflag = 0;
  589. }
  590.  
  591.  
  592. static int AtomInter( ptr )
  593.     Atom __far *ptr;
  594. {
  595.     register Long modv,radius2;
  596.     register int vx, vy, vz;
  597.     register Real tca;
  598.  
  599.     if( ptr->mbox == RayCount )
  600.     return( False );
  601.     ptr->mbox = RayCount;
  602.  
  603.     vx = (int)ptr->xorg-ShadowX;
  604.     vy = (int)ptr->yorg-ShadowY;
  605.     vz = (int)ptr->zorg-ShadowZ;
  606.  
  607.     tca = vx*ShadowI + vy*ShadowJ + vz*ShadowK;
  608.     if( tca<0.0 ) return( False );
  609.     
  610.     radius2 = ptr->radius+10;  radius2 = radius2*radius2;
  611.     modv = (Long)vx*vx + (Long)vy*vy + (Long)vz*vz - radius2;
  612.     return( modv<tca*tca );
  613. }
  614.  
  615.  
  616. static int ShadowRay()
  617. {
  618.     register Item __far * __far *ident;
  619.     register Item __far *ptr;
  620.     register Real ex, ey, ez;
  621.     register Long dx, dy, dz;
  622.     register int ref;
  623.  
  624.    
  625.     RayCount++;
  626.     if( SBuffer )
  627.     {   if( (SBuffer!=Exclude) && AtomInter(SBuffer) )
  628.         return( True );
  629.     SBuffer = (void __far*)0;
  630.     }
  631.  
  632.     ex = IVoxRatio*(ShadowX+Offset);  xcord = (int)ex;
  633.     ey = IVoxRatio*(ShadowY+Offset);  ycord = (int)ey;
  634.     ez = IVoxRatio*(ShadowZ+Offset);  zcord = (int)ez;
  635.  
  636.     ref = VOXORDER2*xcord+VOXORDER*ycord+zcord;
  637.     ident = (Item __far* __far*)(HashTable+ref);
  638.  
  639.     if( xflag==1 ) 
  640.     {   dx = (Long)(((xcord+1)-ex)*deltax);
  641.     } else if( xflag == -1 )
  642.     {   dx = (Long)((ex-xcord)*deltax); 
  643.     } else dx = INFINITY;
  644.  
  645.     if( yflag==1 ) 
  646.     {   dy = (Long)(((ycord+1)-ey)*deltay);
  647.     } else if( yflag == -1 )
  648.     {   dy = (Long)((ey-ycord)*deltay); 
  649.     } else dy = INFINITY;
  650.  
  651.     if( zflag==1 ) 
  652.     {   dz = (Long)(((zcord+1)-ez)*deltaz);
  653.     } else if( zflag == -1 )
  654.     {   dz = (Long)((ez-zcord)*deltaz); 
  655.     } else dz = INFINITY;
  656.  
  657.     
  658.     while( True )
  659.     {   for( ptr = *ident; ptr; ptr = ptr->list )
  660.         if( (ptr->data!=Exclude) && AtomInter(ptr->data) )
  661.         {   SBuffer = ptr->data;
  662.         return( True );
  663.         }
  664.  
  665.     if( (dx<=dy) && (dx<=dz) )
  666.     {   xcord += xflag;
  667.         if( (xcord<0) || (xcord>=VOXORDER) ) return( False );
  668.         ident += xhash; dx += deltax;
  669.     } else if( dy<=dz  ) /*(dy<=dx)*/
  670.     {   ycord += yflag;
  671.         if( (ycord<0) || (ycord>=VOXORDER) ) return( False );
  672.         ident += yhash; dy += deltay;
  673.     } else /* (dz<=dx) && (dz<=dy) */
  674.     {   zcord += zflag;
  675.         if( (zcord<0) || (zcord>=VOXORDER) ) return( False );
  676.         ident += zhash; dz += deltaz;
  677.     }
  678.     }
  679. }
  680.  
  681.  
  682.  
  683. #define UpdateScanAcross \
  684.     if( depth>*dptr )   \
  685.     {   *dptr = depth;  \
  686.         iptr[dx] = ptr; \
  687.     } dptr++; dx++;
  688.  
  689.  
  690. /* ScanLine for Shadows! */
  691. static void ScanLine()
  692. {
  693.     static Atom __far *list;
  694.     register Atom __far *ptr;
  695.     register Atom __far * __far *iptr;
  696.     register Atom __far * __far *prev;
  697.     register short __huge *dbase;
  698.     register short __huge *dptr;
  699.     register Pixel __huge *fptr;
  700.     register Byte __far *tptr;
  701.  
  702.     register int pos,depth,inten;
  703.     register int lastx,wide,scan;
  704.     register int dx,dy,dz;
  705.  
  706.     fptr = FBuffer;
  707.     dbase = DBuffer;
  708.     list = (void __far*)0;  
  709.  
  710.     wide = XRange>>2;  iptr = IBuffer;
  711.     for( pos=0; pos<=wide; pos++ )
  712.     {   *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  713.     *iptr++ = (void __far*)0;  *iptr++ = (void __far*)0;
  714.     }
  715.  
  716.  
  717.     for( scan=0; scan<YRange; scan++ )
  718.     {   for( ptr = YBucket[scan]; ptr; ptr = ptr->bucket )
  719.     {    ptr->next = list; list = ptr; }
  720.  
  721.     prev = &list;
  722.     for( ptr=list; ptr; ptr=ptr->next )
  723.     {   dy = scan - ptr->y;
  724.         wide = LookUp[ptr->irad][AbsFun(dy)];
  725.         lastx = (XRange-1)-ptr->x;
  726.         if( wide<lastx ) lastx=wide;
  727.         dx = - MinFun(wide,ptr->x);
  728.  
  729.         iptr = IBuffer+ptr->x;
  730.         tptr = LookUp[wide];
  731.  
  732.         dptr = dbase+ptr->x+dx;
  733.         while( dx<=lastx )
  734.         {   depth = tptr[AbsFun(dx)]+ptr->z;
  735.         UpdateScanAcross;
  736.         }
  737.  
  738.         /* Remove completed atoms */
  739.         if( dy == ptr->irad )
  740.         {   *prev = ptr->next;
  741.         } else prev = &ptr->next;
  742.     } /*ptr*/
  743.  
  744.  
  745.     /* Process visible scanline */
  746.     prev = (Atom __far* __far*)IBuffer;
  747.     SBuffer = (void __far*)0;
  748.     dptr = dbase; 
  749.  
  750.     for( pos=0; pos<XRange; pos++ )
  751.     {   if( *prev )
  752.         {   ptr = *prev;
  753.                 dz = *dptr-ptr->z;
  754. #ifdef INVERT
  755.         inten = (dz<<1)+(pos-ptr->x)+(scan-ptr->y);
  756. #else
  757.         inten = (dz<<1)+(pos-ptr->x)-(scan-ptr->y);
  758. #endif
  759.         if( inten>0 )
  760.         {   inten = (int)( (inten*ColConst[ptr->irad])>>ColBits);
  761.             dz = *dptr-ZOffset;
  762.             dx = pos-XOffset;
  763.             dy =   scan-YOffset;
  764.  
  765.             ShadowX = (int)(dx*InvX[0]+dy*InvX[1]+dz*InvX[2]);
  766.             ShadowY = (int)(dx*InvY[0]+dy*InvY[1]+dz*InvY[2]);
  767.             ShadowZ = (int)(dx*InvZ[0]+dy*InvZ[1]+dz*InvZ[2]);
  768.  
  769.             Exclude = ptr;
  770.             if( ShadowRay() )
  771.             {   *fptr = Lut[ptr->col+(inten>>2)];
  772.             } else *fptr = Lut[ptr->col+inten];
  773.         } else *fptr = Lut[ptr->col];
  774.         *prev = (void __far*)0;
  775.         }
  776.         dptr++; fptr++; prev++;
  777.     }
  778.     dbase = dptr;
  779.     } /*scan*/
  780. }
  781.  
  782.  
  783. #ifdef FUNCPROTO
  784. /* Function Prototype */
  785. static void DisplayHBonds( HBond __far *, int );
  786. #endif
  787.  
  788.  
  789. static void DisplaySpaceFill()
  790. {
  791.     register Chain __far *chain;
  792.     register Group __far *group;
  793.     register Atom __far *aptr;
  794.  
  795.     if( UseShadow )
  796.     {   if( !BucketFlag )
  797.         PrepareYBucket();
  798.     ScanLine();
  799.     } else if( UseClipping )
  800.     {   ForEachAtom
  801.         if( aptr->flag&SphereFlag )
  802.         ClipSphere(aptr->x,aptr->y,aptr->z,aptr->irad,aptr->col);
  803.     } else 
  804.     ForEachAtom
  805.         if( aptr->flag&SphereFlag )
  806.         DrawSphere(aptr->x,aptr->y,aptr->z,aptr->irad,aptr->col);
  807. }
  808.  
  809.  
  810. static void DisplayWireframe()
  811. {
  812.     register Bond __far *bptr;
  813.     register Atom __far *s;
  814.     register Atom __far *d;
  815.     register int sc,dc;
  816.  
  817.     if( UseClipping )
  818.     {   ForEachBond
  819.            if( bptr->flag & DrawBondFlag )
  820.            {   s = bptr->srcatom; d = bptr->dstatom;
  821.            if( !bptr->col ) 
  822.            {   sc = s->col;  dc = d->col;
  823.            } else sc = dc = bptr->col;
  824.  
  825.            if( bptr->flag&WireFlag )
  826.            {   ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  827.            } else if( bptr->flag&CylinderFlag )
  828.            {   if( bptr->irad>0 )
  829.                {  ClipCylinder(s->x,s->y,s->z,d->x,d->y,d->z,
  830.                                    sc,dc,bptr->irad);
  831.                } else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  832.                    sc+ColourMask,dc+ColourMask);
  833.                } else /* bptr->flag & DashFlag */
  834.                    ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  835.        }
  836.     } else
  837.     ForEachBond
  838.            if( bptr->flag & DrawBondFlag )
  839.            {   s = bptr->srcatom; d = bptr->dstatom;
  840.                if( !bptr->col )
  841.                {   sc = s->col;  dc = d->col;
  842.                } else sc = dc = bptr->col;
  843.  
  844.                if( bptr->flag&WireFlag )
  845.                {      DrawTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  846.            } else if( bptr->flag&CylinderFlag )
  847.            {   if( bptr->irad>0 )
  848.                {  DrawCylinder(s->x,s->y,s->z,d->x,d->y,d->z,
  849.                                    sc,dc,bptr->irad);
  850.                } else DrawTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  851.                    sc+ColourMask,dc+ColourMask);
  852.            } else ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  853.            }
  854. }
  855.  
  856.  
  857. /* Used by DisplayDoubleBonds! */
  858. static void DisplayCylinder(x1,y1,z1,x2,y2,z2,c1,c2,rad)
  859.     int x1,y1,z1,x2,y2,z2,c1,c2,rad;
  860. {
  861.     if( UseClipping )
  862.     {   if( rad == 0 )
  863.         {   ClipTwinLine(x1,y1,z1,x2,y2,z2,c1+ColourMask,c2+ColourMask);
  864.         } else ClipCylinder(x1,y1,z1,x2,y2,z2,c1,c2,rad);
  865.     } else
  866.     {   if( rad == 0 )
  867.         {   DrawTwinLine(x1,y1,z1,x2,y2,z2,c1+ColourMask,c2+ColourMask);
  868.         } else DrawCylinder(x1,y1,z1,x2,y2,z2,c1,c2,rad);
  869.     }
  870. }
  871.  
  872.  
  873. static void DisplayDoubleBonds()
  874. {
  875.     register Atom __far *s;
  876.     register Atom __far *d;
  877.     register Bond __far *bptr;
  878.     register int dx,dy,ix,iy;
  879.     register int ax,ay,sc,dc;
  880.     register int k,flag;
  881.  
  882.     ForEachBond
  883.         if( bptr->flag & DrawBondFlag )
  884.         {   s = bptr->srcatom; d = bptr->dstatom;
  885.             if( !bptr->col ) 
  886.             {   sc = s->col;  dc = d->col;
  887.             } else sc = dc = bptr->col;
  888.  
  889.             flag = (bptr->flag&CylinderFlag) && (bptr->irad>4);
  890.             if( !(bptr->flag & DoubBondFlag) || flag )
  891.             {   if( bptr->flag&WireFlag )
  892.                 {   ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  893.                 } else if( bptr->flag&CylinderFlag )
  894.                 {   DisplayCylinder(s->x,s->y,s->z,d->x,d->y,d->z,
  895.                                     sc,dc,bptr->irad);
  896.                 } else /* bptr->flag & DashFlag */
  897.                     ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  898.             } 
  899.  
  900.             if( (bptr->flag & (DoubBondFlag|TripBondFlag)) && !flag )
  901.             {   if( s->x > d->x )
  902.                 {   ax = s->x - d->x;  dx = 1;
  903.                 } else
  904.                 {   ax = d->x - s->x;  dx = 0;
  905.                 }
  906.  
  907.                 if( s->y > d->y )
  908.                 {   ay = s->y - d->y;  dy = 1;
  909.                 } else 
  910.                 {   ay = d->y - s->y;  dy = 0;
  911.                 }
  912.  
  913.                 /* Determine Bond Separation */
  914.                 if( (bptr->flag&CylinderFlag) && bptr->irad )
  915.                 {   if( bptr->flag & DoubBondFlag )
  916.                     {   k = (3*bptr->irad+1)>>1;
  917.                     } else k = 3*bptr->irad;
  918.                 } else k = (bptr->flag&TripBondFlag)?3:2;
  919.  
  920.                 if( ax > (ay<<1) )
  921.                 {   ix = 0;  iy = k;
  922.                 } else if( ay > (ax<<1) )
  923.                 {   iy = 0;  ix = k;
  924.                 } else /* diagonal */
  925.                 {   k = (3*k)>>2;
  926.                     if( dx == dy )
  927.                     {   ix = k;  iy = -k;
  928.                     } else
  929.                     {   ix = k;  iy = k;
  930.                     }
  931.                 }
  932.  
  933.                 if( bptr->flag&WireFlag )
  934.                 {   ClipTwinVector(s->x+ix,s->y+iy,s->z,
  935.                                    d->x+ix,d->y+iy,d->z,sc,dc);
  936.                     ClipTwinVector(s->x-ix,s->y-iy,s->z,
  937.                                    d->x-ix,d->y-iy,d->z,sc,dc);
  938.                 } else if( bptr->flag&CylinderFlag )
  939.                 {   DisplayCylinder(s->x+ix,s->y+iy,s->z,
  940.                                     d->x+ix,d->y+iy,d->z,
  941.                                     sc,dc,bptr->irad);
  942.                     DisplayCylinder(s->x-ix,s->y-iy,s->z,
  943.                                     d->x-ix,d->y-iy,d->z,
  944.                                     sc,dc,bptr->irad);
  945.                 } else /* bptr->flag & DashFlag */
  946.                 {  ClipDashVector(s->x+ix,s->y+iy,s->z,
  947.                                   d->x+ix,d->y+iy,d->z,sc,dc);
  948.                    ClipDashVector(s->x+ix,s->y+iy,s->z,
  949.                                   d->x+ix,d->y+iy,d->z,sc,dc);
  950.                 }
  951.             }
  952.         }
  953. }
  954.  
  955.  
  956. static void DisplayBackbone()
  957. {
  958.     register Chain __far *chain;
  959.     register Bond __far *bptr;
  960.     register Atom __far *s;
  961.     register Atom __far *d;
  962.     register int sc,dc;
  963.  
  964.     ForEachBack
  965.        if( bptr->flag&DrawBondFlag )
  966.        {   s = bptr->srcatom; d = bptr->dstatom;
  967.            if( !bptr->col ) 
  968.            {   sc = s->col;  dc = d->col;
  969.            } else sc = dc = bptr->col;
  970.  
  971.            if( bptr->flag&CylinderFlag )
  972.            {   if( bptr->irad>0 )
  973.                { ClipCylinder(s->x,s->y,s->z,d->x,d->y,d->z,
  974.                               sc,dc,bptr->irad);
  975.                } else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  976.                                    sc+ColourMask,dc+ColourMask);
  977.            } else if( bptr->flag & WireFlag )
  978.            {      ClipTwinVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  979.            } else ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  980.        }
  981. }
  982.  
  983.  
  984. static void DisplayHBonds( list, mode )
  985.     HBond __far *list; 
  986.     int mode;
  987. {
  988.     register HBond __far *ptr;
  989.     register Atom __far *s;
  990.     register Atom __far *d;
  991.     register int sc,dc;
  992.  
  993.     for( ptr=list; ptr; ptr=ptr->hnext )
  994.         if( ptr->flag & DrawBondFlag )
  995.     {   if( mode )
  996.         {   s = ptr->srcCA; d = ptr->dstCA;
  997.         if( !s || !d ) continue;
  998.         } else
  999.         {   d = ptr->src;
  1000.         s = ptr->dst;
  1001.         }
  1002.  
  1003.         if( !ptr->col )
  1004.         {   sc = s->col;  dc = d->col;
  1005.         } else sc = dc = ptr->col;
  1006.         if( ptr->flag & CylinderFlag )
  1007.         {   if( ptr->irad>0 )
  1008.         {   ClipCylinder(s->x,s->y,s->z,d->x,d->y,d->z,
  1009.                                  sc,dc,ptr->irad);
  1010.         } else ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  1011.                     sc+ColourMask,dc+ColourMask);
  1012.         } else ClipDashVector(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc);
  1013.     }
  1014. }
  1015.  
  1016.  
  1017.  
  1018. static void DisplayBoxes()
  1019. {
  1020.     register Real lena, lenb, lenc;
  1021.     register Real tmpx, tmpy, tmpz;
  1022.     register Real cosa, cosb, cosg;
  1023.     register Real temp, sing;
  1024.  
  1025.     register int xorg, yorg, zorg;
  1026.     register int dxx,dxy,dxz;
  1027.     register int dyx,dyy,dyz;
  1028.     register int dzx,dzy,dzz;
  1029.     register int x, y, z;
  1030.  
  1031.  
  1032.     if( DrawAxes  || DrawBoundBox )
  1033.     {   dxx = (int)(MaxX*MatX[0]);
  1034.     dxy = (int)(MaxX*MatY[0]);
  1035.     dxz = (int)(MaxX*MatZ[0]);
  1036.  
  1037.     dyx = (int)(MaxY*MatX[1]);
  1038.     dyy = (int)(MaxY*MatY[1]);
  1039.     dyz = (int)(MaxY*MatZ[1]);
  1040.  
  1041.     dzx = (int)(MaxZ*MatX[2]);
  1042.     dzy = (int)(MaxZ*MatY[2]);
  1043.     dzz = (int)(MaxZ*MatZ[2]);
  1044.  
  1045.     if( DrawAxes )
  1046.     {   /* Line (MinX,0,0) to (MaxX,0,0) */
  1047.             x = XOffset+dxx;  y = YOffset+dxy;  z = ZOffset+dxz;
  1048.             if( ZValid(z) ) DisplayString(x+2,y,z,"X",BoxCol);
  1049.         ClipTwinLine(XOffset-dxx,YOffset-dxy,ZOffset-dxz,
  1050.                          x,y,z,BoxCol,BoxCol);
  1051.  
  1052.         /* Line (0,MinY,0) to (0,MaxY,0) */
  1053.             x = XOffset+dyx;  y = YOffset+dyy;  z = ZOffset+dyz;
  1054.             if( ZValid(z) ) DisplayString(x+2,y,z,"Y",BoxCol);
  1055.         ClipTwinLine(XOffset-dyx,YOffset-dyy,ZOffset-dyz, 
  1056.              x,y,z,BoxCol,BoxCol);
  1057.  
  1058.  
  1059.         /* Line (0,0,MinZ) to (0,0,MaxZ) */
  1060.             x = XOffset-dzx;  y = YOffset-dzy;  z = ZOffset-dzz;
  1061.             if( ZValid(z) ) DisplayString(x+2,y,z,"Z",BoxCol);
  1062.         ClipTwinLine(XOffset+dzx,YOffset+dzy,ZOffset+dzz, 
  1063.              x,y,z,BoxCol,BoxCol);
  1064.  
  1065.     }
  1066.  
  1067.     if( DrawBoundBox )
  1068.     {   /* Line (MinX,MinY,MinZ) to (MaxX,MinY,MinZ) */
  1069.         x=XOffset-dyx-dzx;  y=YOffset-dyy-dzy;  z=ZOffset-dyz-dzz;
  1070.         ClipTwinLine(x-dxx,y-dxy,z-dxz,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1071.  
  1072.         /* Line (MaxX,MinY,MinZ) to (MaxX,MaxY,MinZ) */
  1073.         x=XOffset+dxx-dzx;  y=YOffset+dxy-dzy;  z=ZOffset+dxz-dzz;
  1074.         ClipTwinLine(x-dyx,y-dyy,z-dyz,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1075.  
  1076.         /* Line (MaxX,MaxY,MinZ) to (MinX,MaxY,MinZ) */
  1077.         x=XOffset+dyx-dzx;  y=YOffset+dyy-dzy;  z=ZOffset+dyz-dzz;
  1078.         ClipTwinLine(x+dxx,y+dxy,z+dxz,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1079.  
  1080.         /* Line (MinX,MaxY,MinZ) to (MinX,MinY,MinZ) */
  1081.         x=XOffset-dxx-dzx;  y=YOffset-dxy-dzy;  z=ZOffset-dxz-dzz;
  1082.         ClipTwinLine(x+dyx,y+dyy,z+dyz,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1083.  
  1084.  
  1085.         /* Line (MinX,MinY,MinZ) to (MinX,MinY,MaxZ) */
  1086.         x=XOffset-dxx-dyx;  y=YOffset-dxy-dyy;  z=ZOffset-dxz-dyz;
  1087.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1088.  
  1089.         /* Line (MaxX,MinY,MinZ) to (MaxX,MinY,MaxZ) */
  1090.         x=XOffset+dxx-dyx;  y=YOffset+dxy-dyy;  z=ZOffset+dxz-dyz;
  1091.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1092.  
  1093.         /* Line (MaxX,MaxY,MinZ) to (MaxX,MaxY,MaxZ) */
  1094.         x=XOffset+dxx+dyx;  y=YOffset+dxy+dyy;  z=ZOffset+dxz+dyz;
  1095.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1096.  
  1097.         /* Line (MinX,MaxY,MinZ) to (MinX,MaxY,MaxZ) */
  1098.         x=XOffset-dxx+dyx;  y=YOffset-dxy+dyy;  z=ZOffset-dxz+dyz;
  1099.         ClipTwinLine(x-dzx,y-dzy,z-dzz,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1100.  
  1101.  
  1102.         /* Line (MinX,MinY,MaxZ) to (MaxX,MinY,MaxZ) */
  1103.         x=XOffset-dyx+dzx;  y=YOffset-dyy+dzy;  z=ZOffset-dyz+dzz;
  1104.         ClipTwinLine(x-dxx,y-dxy,z-dxz,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1105.  
  1106.         /* Line (MaxX,MinY,MaxZ) to (MaxX,MaxY,MaxZ) */
  1107.         x=XOffset+dxx+dzx;  y=YOffset+dxy+dzy;  z=ZOffset+dxz+dzz;
  1108.         ClipTwinLine(x-dyx,y-dyy,z-dyz,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1109.  
  1110.         /* Line (MaxX,MaxY,MaxZ) to (MinX,MaxY,MaxZ) */
  1111.         x=XOffset+dyx+dzx;  y=YOffset+dyy+dzy;  z=ZOffset+dyz+dzz;
  1112.         ClipTwinLine(x+dxx,y+dxy,z+dxz,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1113.  
  1114.         /* Line (MinX,MaxY,MaxZ) to (MinX,MinY,MaxZ) */
  1115.         x=XOffset-dxx+dzx;  y=YOffset-dxy+dzy;  z=ZOffset-dxz+dzz;
  1116.         ClipTwinLine(x+dyx,y+dyy,z+dyz,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1117.     }
  1118.     }
  1119.  
  1120.     if( DrawUnitCell && *InfoSpaceGroup )
  1121.     {   /* Calculate Unit Cell! */
  1122.     lena =  250.0*InfoCellA;
  1123.     lenb =  250.0*InfoCellB;
  1124.     lenc = -250.0*InfoCellC;
  1125.  
  1126.     cosa = cos(InfoCellAlpha);
  1127.     cosb = cos(InfoCellBeta);
  1128.     cosg = cos(InfoCellGamma);  
  1129.         sing = sin(InfoCellGamma);
  1130.  
  1131.     temp = cosa*cosa + cosb*cosb + cosg*cosg - 2.0*cosa*cosb*cosg;
  1132.     tmpx = cosb; 
  1133.     tmpy = (cosa - cosb*cosg)/sing;
  1134.     tmpz = sqrt(1.0-temp)/sing;
  1135.  
  1136.     dxx = (int)(lena*MatX[0]);
  1137.     dxy = (int)(lena*MatY[0]);
  1138.     dxz = (int)(lena*MatZ[0]);
  1139.  
  1140.     dyx = (int)(lenb*(cosg*MatX[0] + sing*MatX[1]));
  1141.     dyy = (int)(lenb*(cosg*MatY[0] + sing*MatY[1]));
  1142.     dyz = (int)(lenb*(cosg*MatZ[0] + sing*MatZ[1]));
  1143.  
  1144.     dzx = (int)(lenc*(tmpx*MatX[0] + tmpy*MatX[1] + tmpz*MatX[2]));
  1145.     dzy = (int)(lenc*(tmpx*MatY[0] + tmpy*MatY[1] + tmpz*MatY[2]));
  1146.     dzz = (int)(lenc*(tmpx*MatZ[0] + tmpy*MatZ[1] + tmpz*MatZ[2]));
  1147.  
  1148.     xorg = XOffset - (int)(OrigCX*MatX[0]+OrigCY*MatX[1]+OrigCZ*MatX[2]);
  1149.     yorg = YOffset - (int)(OrigCX*MatY[0]+OrigCY*MatY[1]+OrigCZ*MatY[2]);
  1150.     zorg = ZOffset + (int)(OrigCX*MatZ[0]+OrigCY*MatZ[1]+OrigCZ*MatZ[2]);
  1151.  
  1152.  
  1153.     /* Draw Unit Cell! */
  1154.     x = xorg;
  1155.     y = yorg;
  1156.     z = zorg;
  1157.     ClipTwinLine(x,y,z,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1158.     ClipTwinLine(x,y,z,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1159.     ClipTwinLine(x,y,z,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1160.  
  1161.     x = xorg + dxx + dyx;
  1162.     y = yorg + dxy + dyy;
  1163.     z = zorg + dxz + dyz;
  1164.     ClipTwinLine(x,y,z,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1165.     ClipTwinLine(x,y,z,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1166.     ClipTwinLine(x,y,z,x+dzx,y+dzy,z+dzz,BoxCol,BoxCol);
  1167.  
  1168.     x = xorg + dxx + dzx;
  1169.     y = yorg + dxy + dzy;
  1170.     z = zorg + dxz + dyz;
  1171.     ClipTwinLine(x,y,z,x-dxx,y-dxy,z-dxz,BoxCol,BoxCol);
  1172.     ClipTwinLine(x,y,z,x+dyx,y+dyy,z+dyz,BoxCol,BoxCol);
  1173.     ClipTwinLine(x,y,z,x-dzx,y-dzy,z-dzz,BoxCol,BoxCol);
  1174.  
  1175.     x = xorg + dyx + dzx;
  1176.     y = yorg + dyy + dzy;
  1177.     z = zorg + dyz + dzz;
  1178.     ClipTwinLine(x,y,z,x+dxx,y+dxy,z+dxz,BoxCol,BoxCol);
  1179.     ClipTwinLine(x,y,z,x-dyx,y-dyy,z-dyz,BoxCol,BoxCol);
  1180.     ClipTwinLine(x,y,z,x-dzx,y-dzy,z-dzz,BoxCol,BoxCol);
  1181.     }
  1182. }
  1183.  
  1184.  
  1185. static void DisplaySelected()
  1186. {
  1187.     register Atom __far *s, __far *d;
  1188.     register Chain __far *chain;
  1189.     register Group __far *group;
  1190.     register Bond __far *bptr;
  1191.     register Atom __far *aptr;
  1192.     register int irad,sc,dc;
  1193.     register int col;
  1194.  
  1195.     irad = (int)(Scale*20);
  1196.  
  1197.     if( irad>0 )
  1198.     {   ForEachBond
  1199.     {   s = bptr->srcatom;  
  1200.         col = (s->flag&SelectFlag)? 1 : 0;
  1201.         sc = Shade2Colour(col);
  1202.  
  1203.         d = bptr->dstatom;  
  1204.         col = (d->flag&SelectFlag)? 1 : 0;
  1205.         dc = Shade2Colour(col);
  1206.         ClipCylinder(s->x,s->y,s->z,d->x,d->y,d->z,sc,dc,irad);
  1207.     }
  1208.     } else ForEachBond
  1209.     {   s = bptr->srcatom;  
  1210.         col = (s->flag&SelectFlag)? 1 : 0;
  1211.         sc = Shade2Colour(col);
  1212.  
  1213.         d = bptr->dstatom;  
  1214.         col = (d->flag&SelectFlag)? 1 : 0;
  1215.         dc = Shade2Colour(col);
  1216.         ClipTwinLine(s->x,s->y,s->z,d->x,d->y,d->z,
  1217.              sc+ColourMask,dc+ColourMask);
  1218.     }
  1219.  
  1220.  
  1221.     irad = (int)(Scale*50);
  1222.     ForEachAtom
  1223.     if( aptr->flag&NonBondFlag )
  1224.     {   col = Shade2Colour( (aptr->flag&SelectFlag)? 1 : 0 );
  1225.         ClipSphere(aptr->x,aptr->y,aptr->z,irad,col);
  1226.     }
  1227. }
  1228.  
  1229.  
  1230. static void RenderFrame()
  1231. {
  1232.     register Chain __far *chain;
  1233.  
  1234.     if( !DisplayMode )
  1235.     {   if( DrawAtoms ) 
  1236.         DisplaySpaceFill();
  1237.  
  1238.     if( !UseSlabPlane || (SlabMode != SlabSection) )
  1239.     {   if( DrawBonds ) 
  1240.             {   if( DrawDoubleBonds )
  1241.                 {   DisplayDoubleBonds();
  1242.                 } else DisplayWireframe();
  1243.             }
  1244.  
  1245.         if( DrawRibbon )
  1246.         for( chain=Database->clist; chain; chain=chain->cnext )
  1247.             if( chain->glist )
  1248.                         DisplayRibbon( chain );
  1249.  
  1250.         if( DrawDots ) DisplaySurface();
  1251.         if( DrawLabels ) DisplayLabels();
  1252.             if( MonitList ) DisplayMonitors();
  1253.         DisplayHBonds( Database->slist, SSBondMode );
  1254.         DisplayHBonds( Database->hlist, HBondMode );
  1255.         DisplayBackbone();
  1256.     }
  1257.     } else DisplaySelected();
  1258.     DisplayBoxes();
  1259. }
  1260.  
  1261.  
  1262. void DrawFrame()
  1263. {
  1264.     register int wide;
  1265.  
  1266.     if( !Database ) 
  1267.     return;
  1268.  
  1269.     ClearBuffers();
  1270.     if( !DisplayMode )
  1271.     {   if( UseShadow && DrawAtoms )
  1272.         if( !VoxelsClean )
  1273.         CreateVoxelData( SphereFlag );
  1274.     }
  1275.  
  1276.     if( UseSlabPlane )
  1277.     {   SlabValue = (int)(DialValue[7]*ImageRadius)+ZOffset;
  1278.     SlabInten = (int)(ColourMask*TwoOverRootSix);
  1279.     SliceValue = SlabValue+16;
  1280.     UseClipping = True;
  1281.     } else UseClipping = UseScreenClip;
  1282.  
  1283. #ifdef IBMPC
  1284.     /* Lock Buffers into Memory */
  1285.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  1286.     DBuffer = (short __huge*)GlobalLock(DBufHandle);
  1287. #endif
  1288.  
  1289.     /* Common View Elements */
  1290.     View.yskip = XRange;
  1291.     View.ymax = YRange;
  1292.  
  1293.     if( UseStereo )
  1294.     {   wide = XRange>>1;
  1295.  
  1296.         /* Create 'Left' View structure */
  1297.         View.fbuf = FBuffer;
  1298.         View.dbuf = DBuffer;
  1299.         View.xmax = wide;
  1300.         RenderFrame();
  1301.  
  1302.         /* Create 'Right' View structure */
  1303.         View.fbuf = FBuffer+wide;
  1304.         View.dbuf = DBuffer+wide;
  1305.         View.xmax = wide;
  1306.         RenderFrame();
  1307.  
  1308.     } else /* Mono */
  1309.     {   /* Create 'Mono' View structure */
  1310.         View.fbuf = FBuffer;
  1311.         View.dbuf = DBuffer;
  1312.         View.xmax = XRange;
  1313.         RenderFrame();
  1314.     }
  1315.  
  1316. #ifdef IBMPC
  1317.     /* Unlock Buffers */
  1318.     GlobalUnlock(FBufHandle);
  1319.     GlobalUnlock(DBufHandle);
  1320. #endif
  1321.     DBClear = False;
  1322.     FBClear = False;
  1323. }
  1324.  
  1325.  
  1326.  
  1327. #ifdef FUNCPROTO
  1328. /* Function Prototype */
  1329. static void TestAtomProximity( Atom __far *, int, int );
  1330. #endif
  1331.  
  1332.  
  1333. static void TestAtomProximity( ptr, xpos, ypos )
  1334.     Atom __far *ptr;
  1335.     int xpos, ypos;
  1336. {
  1337.     register Long dist;
  1338.     register int dx,dy;
  1339.  
  1340.     if( UseSlabPlane && (ptr->z>SlabValue) )
  1341.     return;
  1342.  
  1343.     dx = ptr->x - xpos;
  1344.     dy = ptr->y - ypos;
  1345.  
  1346.     dist = (Long)dx*dx + (Long)dy*dy;
  1347.  
  1348.     if( IdentFound )
  1349.     {   if( dist==IdentDist )
  1350.     {   if( ptr->z<IdentDepth )
  1351.         return;
  1352.     } else if( dist>IdentDist ) 
  1353.         return;
  1354.     }
  1355.  
  1356.     IdentDepth = ptr->z;
  1357.     IdentFound = True;
  1358.     IdentDist = dist;
  1359.     QAtom = ptr;
  1360. }
  1361.  
  1362. static void IdentifyAtom( xpos, ypos )
  1363.     int xpos, ypos;
  1364. {
  1365.     register int rad, wide, dpth;
  1366.     register int new, dx, dy, dz;
  1367.     register Chain __far *chain;
  1368.     register Group __far *group;
  1369.     register HBond __far *hptr;
  1370.     register Atom  __far *aptr;
  1371.     register Bond __far *bptr;
  1372.  
  1373.     /* Reset Search */
  1374.     QChain = (void __far*)0;
  1375.     QGroup = (void __far*)0;
  1376.     QAtom = (void __far*)0;
  1377.     IdentFound = False;
  1378.  
  1379.     if( !DisplayMode )
  1380.     {   if( !UseSlabPlane || (SlabMode != SlabSection) )
  1381.     {   if( DrawBonds )
  1382.         ForEachBond
  1383.             if( bptr->flag&DrawBondFlag )
  1384.             {   TestAtomProximity(bptr->srcatom,xpos,ypos);
  1385.             TestAtomProximity(bptr->dstatom,xpos,ypos);
  1386.             }
  1387.  
  1388.         ForEachBack
  1389.         if( bptr->flag&DrawBondFlag )
  1390.         {   TestAtomProximity(bptr->srcatom,xpos,ypos);
  1391.             TestAtomProximity(bptr->dstatom,xpos,ypos);
  1392.         }
  1393.  
  1394.         for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1395.         if( hptr->flag )
  1396.         {   if( HBondMode )
  1397.             {   TestAtomProximity(hptr->srcCA,xpos,ypos);
  1398.             TestAtomProximity(hptr->dstCA,xpos,ypos);
  1399.             } else
  1400.             {   TestAtomProximity(hptr->src,xpos,ypos);
  1401.             TestAtomProximity(hptr->dst,xpos,ypos);
  1402.             }
  1403.         }
  1404.  
  1405.         for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1406.         if( hptr->flag )
  1407.         {   if( HBondMode )
  1408.             {   TestAtomProximity(hptr->srcCA,xpos,ypos);
  1409.             TestAtomProximity(hptr->dstCA,xpos,ypos);
  1410.             } else
  1411.             {   TestAtomProximity(hptr->src,xpos,ypos);
  1412.             TestAtomProximity(hptr->dst,xpos,ypos);
  1413.             }
  1414.         }
  1415.     }
  1416.  
  1417.     ForEachAtom
  1418.     {   /* Identify bond! */
  1419.         if( aptr == QAtom )
  1420.         {   QChain = chain;
  1421.         QGroup = group;
  1422.         }
  1423.  
  1424.         if( aptr->flag & SphereFlag )
  1425.         {   dy = AbsFun(aptr->y-ypos);
  1426.         if( dy>aptr->irad ) continue;
  1427.         rad = LookUp[aptr->irad][dy];
  1428.         dx = AbsFun(aptr->x-xpos);
  1429.         if( dx>rad ) continue;
  1430.  
  1431.         new = False;
  1432.         dpth = aptr->z+LookUp[rad][dx];
  1433.         if( UseSlabPlane && (aptr->z+rad>=SlabValue) )
  1434.         {   dz = SlabValue-aptr->z;
  1435.             if( SlabMode && (dz >= -rad) )
  1436.             {   wide = LookUp[aptr->irad][AbsFun(dz)];
  1437.             if( (dy<=wide) && (dx<=(int)(LookUp[wide][dy])) )
  1438.             {   if( SlabMode == SlabFinal )
  1439.                 {   dpth = SliceValue;
  1440.                 new = True;
  1441.                 } else if( SlabMode == SlabHollow )
  1442.                 {   dpth = aptr->z-LookUp[rad][dx];
  1443.                 new = !IdentFound || (dpth>IdentDepth);
  1444.                 } else if( SlabMode != SlabHalf )
  1445.                 {   /* SlabClose, SlabSection */
  1446.                 dpth = dx*dx+dy*dy+dz*dz+SliceValue;
  1447.                 if( IdentFound )
  1448.                 {   new = (IdentDepth<SliceValue) 
  1449.                       || (dpth<IdentDepth);
  1450.                 } else new=True;
  1451.                 }
  1452.             } else if( (dz>0) && (SlabMode!=SlabSection) )
  1453.                 new = !IdentFound || (dpth>IdentDepth);
  1454.             }
  1455.         } else if( !UseSlabPlane || (SlabMode != SlabSection) )
  1456.             new = !IdentFound || IdentDist || (dpth>IdentDepth);
  1457.  
  1458.         if( new )
  1459.         {   IdentFound = True;
  1460.             IdentDepth = dpth;
  1461.             IdentDist = 0;
  1462.  
  1463.             QChain = chain;
  1464.             QGroup = group;
  1465.             QAtom = aptr;
  1466.         }
  1467.         } 
  1468.     }
  1469.     } else /* Display Mode */
  1470.     {   ForEachAtom
  1471.     {   TestAtomProximity(aptr,xpos,ypos);
  1472.         /* Identify bond! */
  1473.         if( aptr == QAtom )
  1474.         {   QChain = chain;
  1475.         QGroup = group;
  1476.         }
  1477.     }
  1478.     }
  1479.  
  1480.  
  1481.     if( !IdentFound || (IdentDist>=50) )
  1482.     {   /* Reset Pick Atom! */
  1483.         QChain = (void __far*)0;
  1484.     QGroup = (void __far*)0;
  1485.     QAtom = (void __far*)0;
  1486.     }
  1487. }
  1488.  
  1489.  
  1490. void SetPickMode( mode )
  1491.     int mode;
  1492. {
  1493.     PickMode = mode;
  1494.     PickCount = 0;
  1495. }
  1496.  
  1497.  
  1498. static void DescribeAtom( ptr, flag )
  1499.     AtomRef *ptr;  int flag;
  1500. {
  1501.     register char *str;
  1502.     register int i,ch;
  1503.     char buffer[40];
  1504.  
  1505.     str = Residue[ptr->grp->refno];
  1506.     for( i=0; i<3; i++ )
  1507.         if( str[i]!=' ' ) 
  1508.              WriteChar(str[i]);
  1509.  
  1510.     sprintf(buffer,"%d",ptr->grp->serno);
  1511.     WriteString(buffer);
  1512.  
  1513.     ch = ptr->chn->ident;
  1514.     if( ch != ' ' )
  1515.     {   if( isdigit(ch) )
  1516.             WriteChar(':');
  1517.         WriteChar(ch);
  1518.     }
  1519.  
  1520.     WriteChar('.');
  1521.     str = ElemDesc[ptr->atm->refno];
  1522.     for( i=0; i<3; i++ )
  1523.         if( str[i]!=' ' ) 
  1524.              WriteChar(str[i]);
  1525.  
  1526.     if( flag )
  1527.     {   sprintf(buffer," (%d)",ptr->atm->serno);
  1528.         WriteString(buffer);
  1529.     }
  1530. }
  1531.  
  1532.  
  1533. void PickAtom( shift, xpos, ypos )
  1534.     int shift, xpos, ypos;
  1535. {
  1536.     register AtomRef *ptr;
  1537.     register Label *label;
  1538.     register float temp;
  1539.     register char *str;
  1540.     register int len;
  1541.  
  1542.     char buffer[40];
  1543.     AtomRef ref;
  1544.  
  1545.  
  1546.     if( PickMode == PickNone )
  1547.         return;
  1548.  
  1549.     IdentifyAtom(xpos,ypos);
  1550.  
  1551.     if( QAtom )
  1552.     {   if( PickMode == PickIdent )
  1553.         {   if( CommandActive )
  1554.             WriteChar('\n');
  1555.             CommandActive = False;
  1556.  
  1557.             WriteString("Atom: ");
  1558.             str = ElemDesc[QAtom->refno];
  1559.             if( str[0]!=' ' )   WriteChar(str[0]);
  1560.             WriteChar(str[1]);  WriteChar(str[2]);
  1561.             if( str[3]!=' ' )   WriteChar(str[3]);
  1562.  
  1563.         sprintf(buffer," %d  ",QAtom->serno);
  1564.             WriteString(buffer);
  1565.  
  1566.             str = Residue[QGroup->refno];
  1567.             if( QAtom->flag&HeteroFlag )
  1568.             {   WriteString("Hetero: ");
  1569.             } else WriteString("Group: ");
  1570.  
  1571.             if( str[0]!=' ' )  WriteChar(str[0]);
  1572.             WriteChar(str[1]); WriteChar(str[2]);
  1573.  
  1574.             sprintf(buffer," %d",QGroup->serno);
  1575.             WriteString(buffer);
  1576.  
  1577.             if( QChain->ident!=' ' )
  1578.             {   WriteString("  Chain: ");
  1579.                 WriteChar(QChain->ident);
  1580.             }
  1581.             WriteChar('\n');
  1582.  
  1583.         } else if( PickMode == PickLabel )
  1584.         {   if( !QAtom->label )
  1585.             {   if( MainGroupCount > 1 )
  1586.                 {   strcpy(buffer,"%n%r");
  1587.                     str = buffer+4;
  1588.                     if( InfoChainCount > 1 )
  1589.                     {   if( isdigit(QChain->ident) )
  1590.                             *str++ = ':';
  1591.                         *str++ = '%';
  1592.                         *str++ = 'c';
  1593.                     }
  1594.                     strcpy(str,".%a");
  1595.  
  1596.                     len = (str-buffer) + 3;
  1597.                     label = CreateLabel(buffer,len);
  1598.                 } else label = CreateLabel("%e%i",4);
  1599.  
  1600.                 QAtom->label = label;
  1601.                 label->refcount++;
  1602.             } else
  1603.             {   DeleteLabel( (Label*)QAtom->label );
  1604.                 QAtom->label = (void*)0;
  1605.             }
  1606.  
  1607.             DrawLabels = LabelList? True : False;
  1608.             ReDrawFlag |= RFRefresh;
  1609.  
  1610.         } else if( PickMode == PickCentr )
  1611.         {   CenX = QAtom->xorg;
  1612.             CenY = QAtom->yorg;
  1613.             CenZ = QAtom->zorg;
  1614.  
  1615.             ref.chn = QChain;
  1616.             ref.grp = QGroup;
  1617.             ref.atm = QAtom;
  1618.  
  1619.             if( CommandActive )
  1620.             WriteChar('\n');
  1621.             CommandActive = False;
  1622.  
  1623.             WriteString("Rotating about ");
  1624.             DescribeAtom(&ref,True);
  1625.             WriteChar('\n');
  1626.  
  1627.         } else if( PickMode == PickMonit )
  1628.         {   /* State Machine Implementation */
  1629.  
  1630.             if( PickCount == 0 )
  1631.             {   PickHist[0].atm = QAtom;
  1632.                 PickCount = 1;
  1633.             } else if( PickCount == 1 )
  1634.             {   if( !shift )
  1635.                 {   if( PickHist[0].atm != QAtom )
  1636.                     {   AddMonitors(PickHist[0].atm,QAtom);
  1637.                         ReDrawFlag |= RFRefresh;
  1638.                     }
  1639.                     PickCount = 2;
  1640.                 } else PickHist[0].atm = QAtom;
  1641.             } else /* PickCount == 2 */
  1642.                 if( !shift )
  1643.                 {   PickHist[0].atm = QAtom;
  1644.                     PickCount = 1;
  1645.                 } else if( PickHist[0].atm != QAtom )   
  1646.                 {   AddMonitors(PickHist[0].atm,QAtom);
  1647.                     ReDrawFlag |= RFRefresh;
  1648.                 }
  1649.  
  1650.         } else /* Distance, Angle or Torsion! */
  1651.         {   if( PickCount )
  1652.             {   if( shift )
  1653.                 {   PickCount--;
  1654.                 } else if( PickCount == PickMode )
  1655.                     PickCount = 0;
  1656.             }
  1657.  
  1658.             ptr = PickHist+PickCount;
  1659.             ptr->chn = QChain;
  1660.             ptr->grp = QGroup;
  1661.             ptr->atm = QAtom;
  1662.             PickCount++;
  1663.  
  1664.             if( CommandActive )
  1665.             WriteChar('\n');
  1666.             CommandActive = False;
  1667.  
  1668.             WriteString("Atom #");
  1669.             WriteChar(PickCount+'0');
  1670.             WriteString(": ");
  1671.             DescribeAtom(ptr,True);
  1672.             WriteChar('\n');
  1673.  
  1674.             if( PickCount == PickMode )
  1675.             {   if( PickMode == PickDist )
  1676.                 {   temp = (float)CalcDistance(PickHist[0].atm,
  1677.                                                PickHist[1].atm);
  1678.  
  1679.                     WriteString("Distance ");
  1680.                     DescribeAtom(PickHist,False);
  1681.                     WriteChar('-');
  1682.                     DescribeAtom(PickHist+1,False);
  1683.                     sprintf(buffer,": %.3f\n\n",temp);
  1684.                     WriteString(buffer);
  1685.  
  1686.                 } else if( PickMode == PickAngle )
  1687.                 {   temp = (float)CalcAngle(PickHist[0].atm,
  1688.                                             PickHist[1].atm,
  1689.                                             PickHist[2].atm);
  1690.  
  1691.                     WriteString("Angle ");
  1692.                     DescribeAtom(PickHist,False);
  1693.                     WriteChar('-');
  1694.                     DescribeAtom(PickHist+1,False);
  1695.                     WriteChar('-');
  1696.                     DescribeAtom(PickHist+2,False);
  1697.                     sprintf(buffer,": %.1f\n\n",temp);
  1698.                     WriteString(buffer);
  1699.  
  1700.                 } else /* PickMode == PickTorsn */
  1701.                 {   temp = (float)CalcTorsion(PickHist[0].atm,
  1702.                                               PickHist[1].atm,
  1703.                                               PickHist[2].atm,
  1704.                                               PickHist[3].atm);
  1705.  
  1706.                     WriteString("Torsion ");
  1707.                     DescribeAtom(PickHist,False);
  1708.                     WriteChar('-');
  1709.                     DescribeAtom(PickHist+1,False);
  1710.                     WriteChar('-');
  1711.                     DescribeAtom(PickHist+2,False);
  1712.                     WriteChar('-');
  1713.                     DescribeAtom(PickHist+3,False);
  1714.                     sprintf(buffer,": %.1f\n\n",temp);
  1715.                     WriteString(buffer);
  1716.                 }
  1717.             }
  1718.         }
  1719.     }
  1720. }
  1721.  
  1722.  
  1723. void SetStereoMode( enable )
  1724.     int enable;
  1725. {
  1726.     StereoView = ViewLeft;
  1727.     UseStereo = enable;
  1728.     DetermineClipping();
  1729. }
  1730.  
  1731.  
  1732. void ResetRenderer()
  1733. {
  1734.     DrawAtoms = False;  MaxAtomRadius = 0;
  1735.     DrawBonds = False;  MaxBondRadius = 0;
  1736.     DrawRibbon = False; DrawDots = False;
  1737.  
  1738.     SlabMode = SlabClose;
  1739.     UseSlabPlane = False;
  1740.     UseLabelCol = False;
  1741.     UseShadow = False;
  1742.  
  1743.     SSBondMode = False;
  1744.     HBondMode = False;
  1745.     DisplayMode = 0;
  1746.  
  1747.     DrawDoubleBonds = False;
  1748.     DrawBoundBox = False;
  1749.     DrawUnitCell = False;
  1750.     DrawAxes = False;
  1751.  
  1752.     SetStereoMode(False);
  1753. }
  1754.  
  1755.  
  1756. static void InitialiseTables()
  1757. {
  1758.     register Byte __far *ptr;
  1759.     register unsigned int root,root2;
  1760.     register unsigned int i,rad,arg;
  1761.  
  1762.     ptr = Array;
  1763.     LookUp[0] = ptr;  *ptr++ = 0;
  1764.     LookUp[1] = ptr;  *ptr++ = 1;  *ptr++ = 0;
  1765.     
  1766.     for( rad=2; rad<MAXRAD; rad++ )
  1767.     {   LookUp[rad] = ptr;
  1768.  
  1769.         /* i == 0 */
  1770.         *ptr++ = (Byte)rad;  
  1771.  
  1772.         root = rad-1;
  1773.         root2 = root*root;
  1774.  
  1775.         arg = rad*rad;
  1776.     for( i=1; i<rad; i++ )
  1777.         {   /* arg = rad*rad - i*i */
  1778.             arg -= (i<<1)-1;
  1779.  
  1780.             /* root = isqrt(arg)   */
  1781.             while( arg < root2 )
  1782.             {   root2 -= (root<<1)-1;
  1783.                 root--;
  1784.             }
  1785.             /* Thanks to James Crook */
  1786.             *ptr++ = ((arg-root2)<i)? root : root+1;
  1787.         }
  1788.  
  1789.         /* i == rad */
  1790.         *ptr++ = 0;    
  1791.     }
  1792. }
  1793.  
  1794.  
  1795. void InitialiseRenderer()
  1796. {
  1797.     register int rad,maxval;
  1798.  
  1799.     FBuffer = (void __huge*)0;  
  1800.     DBuffer = (void __huge*)0;
  1801.     IBuffer = (void __far*)0;   
  1802.     YBucket = (void __far*)0;
  1803.  
  1804. #if defined(IBMPC) || defined(APPLEMAC)
  1805.     FBufHandle = NULL;
  1806.     DBufHandle = NULL;
  1807. #endif
  1808.  
  1809. #if defined(IBMPC) || defined(APPLEMAC)
  1810.     /* Allocate tables on FAR heaps */ 
  1811.     Array = (Byte __far*)_fmalloc(MAXTABLE*sizeof(Byte));
  1812.     LookUp = (Byte __far* __far*)_fmalloc(MAXRAD*sizeof(Byte __far*));
  1813.     HashTable = (void __far* __far*)_fmalloc(VOXSIZE*sizeof(void __far*));
  1814.     ColConst = (Card __far*)_fmalloc(MAXRAD*sizeof(Card));
  1815.     
  1816.     if( !Array || !LookUp || !HashTable || !ColConst )
  1817.     FatalRenderError("tables");
  1818. #endif
  1819.  
  1820.     InitialiseTables();
  1821.  
  1822.     /* Initialise ColConst! */
  1823.     for( rad=0; rad<MAXRAD; rad++ )
  1824.     {   maxval = (int)(RootSix*rad)+4;
  1825.     ColConst[rad] = ((Card)ColourDepth<<ColBits)/maxval;
  1826.     }
  1827.  
  1828.     FreeItem = (Item __far*)0;
  1829.     PickMode = PickIdent;
  1830.  
  1831.     VoxelsClean = False;
  1832.     VoxelsDone = False;
  1833.     BucketFlag = False;
  1834.     RayCount = 0;
  1835.  
  1836.     ResetRenderer();
  1837.     ReSizeScreen();
  1838. }
  1839.