Logo Search packages:      
Sourcecode: pymol version File versions  Download package

RepCylBond.c

/* 
   A* -------------------------------------------------------------------
   B* This file contains source code for the PyMOL computer program
   C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. 
   D* -------------------------------------------------------------------
   E* It is unlawful to modify or remove this copyright notice.
   F* -------------------------------------------------------------------
   G* Please see the accompanying LICENSE file for further information. 
   H* -------------------------------------------------------------------
   I* Additional authors of this source file include:
   -* 
   -* 
   -*
   Z* -------------------------------------------------------------------
*/

#include"os_predef.h"
#include"os_std.h"
#include"os_gl.h"

#include"Base.h"
#include"OOMac.h"
#include"Vector.h"
#include"ObjectMolecule.h"
#include"RepCylBond.h"
#include"Color.h"
#include"Setting.h"
#include"main.h"
#include"Feedback.h"
#include"Sphere.h"

typedef struct RepCylBond {
  Rep R;
  float *V,*VR;
  int N,NR;
  int NEdge;
  float *VP;
  int NP;
  float *VSP,*VSPC;
  SphereRec *SP;
  int NSP,NSPC;
  float *VarAlpha,*VarAlphaRay,*VarAlphaSph;
} RepCylBond;

static void subdivide( int n, float *x, float *y);
float *RepCylinder(float *v,float *v1,float *v2,int nEdge,
                   int frontCap, int endCap,
                   float tube_size,float overlap,float nub);

void RepCylBondFree(RepCylBond *I);

void RepCylBondFree(RepCylBond *I)
{
  FreeP(I->VarAlpha);
  FreeP(I->VarAlphaRay);
  FreeP(I->VarAlphaSph);
  FreeP(I->VR);
  FreeP(I->VP);
  FreeP(I->V);
  FreeP(I->VSP);
  FreeP(I->VSPC);
  RepPurge(&I->R);
  OOFreeP(I);
}

float *RepCylinderBox(float *v,float *v1,float *v2,float tube_size,
                      float overlap,float nub);


static void RepCylBondRender(RepCylBond *I,RenderInfo *info)
{
  CRay *ray = info->ray;
  Picking **pick = info->pick;
  int a;
  float *v,*var_alpha;
  int c,cc;
  int i,j;
  Pickable *p;
  float alpha;
  SphereRec *sp;
  register PyMOLGlobals *G=I->R.G;


  alpha = SettingGet_f(G,I->R.cs->Setting,I->R.obj->Setting,cSetting_stick_transparency);
  alpha=1.0F-alpha;
  if(fabs(alpha-1.0)<R_SMALL4)
    alpha=1.0F;
  if(ray) {
    ray->fTransparentf(ray,1.0F-alpha);    
    PRINTFD(G,FB_RepCylBond)
      " RepCylBondRender: rendering raytracable...\n"
      ENDFD;

    v=I->VR;
    c=I->NR;
    var_alpha = I->VarAlphaRay;
    while(c--) {
      if(var_alpha) {
        ray->fTransparentf(ray,1.0F-*(var_alpha++));
      }
      ray->fSausage3fv(ray,v+4,v+7,*(v+3),v,v);
      v+=10;
    }
    var_alpha = I->VarAlphaSph;
    if(I->VSPC) {
      v=I->VSPC;
      c=I->NSPC;
      while(c--) {
        if(var_alpha) {
          ray->fTransparentf(ray,1.0F-*(var_alpha++));
        }
        ray->fColor3fv(ray,v);
        v+=3;
        ray->fSphere3fv(ray,v,*(v+3));
        v+=4;
      }
    }

    ray->fTransparentf(ray,0.0);
  } else if(G->HaveGUI && G->ValidContext) {
    if(pick) {
      
      PRINTFD(G,FB_RepCylBond)
        " RepCylBondRender: rendering pickable...\n"
        ENDFD;

      i=(*pick)->src.index;

      v=I->VP;
      c=I->NP;
      p=I->R.P;

      while(c--) {

        i++;

        if(!(*pick)[0].src.bond) {
          /* pass 1 - low order bits */

          glColor3ub((uchar)((i&0xF)<<4),(uchar)((i&0xF0)|0x8),(uchar)((i&0xF00)>>4)); 
          VLACheck((*pick),Picking,i);
          p++;
          (*pick)[i].src = *p; /* copy object and atom info */
          (*pick)[i].context = I->R.context;
        } else { 
          /* pass 2 - high order bits */

          j=i>>12;

          glColor3ub((uchar)((j&0xF)<<4),(uchar)((j&0xF0)|0x8),(uchar)((j&0xF00)>>4)); 

        }                
      
        glBegin(GL_TRIANGLE_STRIP);

        glVertex3fv(v+ 0);
        glVertex3fv(v+ 3);

        glVertex3fv(v+ 6);
        glVertex3fv(v+ 9);

        glVertex3fv(v+12);
        glVertex3fv(v+15);

        glVertex3fv(v+18);
        glVertex3fv(v+21);

        glVertex3fv(v+ 0);
        glVertex3fv(v+ 3);

        glEnd();

        glBegin(GL_TRIANGLE_STRIP);
      
        glVertex3fv(v+ 0);
        glVertex3fv(v+ 6);

        glVertex3fv(v+18);
        glVertex3fv(v+12);

        glEnd();

        glBegin(GL_TRIANGLE_STRIP);
      
        glVertex3fv(v+ 3);
        glVertex3fv(v+ 9);

        glVertex3fv(v+21);
        glVertex3fv(v+15);

        glEnd();

        v+=24;

      }
      (*pick)[0].src.index = i; /* pass the count */

    } else {
      int use_dlst;    

      use_dlst = (int)SettingGet(G,cSetting_use_display_lists);
      if(use_dlst&&I->R.displayList) {
        glCallList(I->R.displayList);
      } else { 
      
        if(use_dlst) {
          if(!I->R.displayList) {
            I->R.displayList = glGenLists(1);
            if(I->R.displayList) {
              glNewList(I->R.displayList,GL_COMPILE_AND_EXECUTE);
            }
          }
        }
      
        v=I->V;
        c=I->N;
        var_alpha = I->VarAlpha;
        PRINTFD(G,FB_RepCylBond)
          " RepCylBondRender: rendering GL...\n"
          ENDFD;
      
        while(c--) {
          /* cylinder entry consists of a color, a fan,
             a cylinder, and another fan (if flagged) */
          
          if((alpha==1.0)&&(!var_alpha)) {
            glColor3fv(v);
          } else if(var_alpha) { 
            glColor4f(v[0],v[1],v[2],*(var_alpha++));
          } else {
            glColor4f(v[0],v[1],v[2],alpha);
          }
          v+=3;
          
          glBegin(GL_TRIANGLE_STRIP);
          a=I->NEdge+1;
          while(a--) {
            glNormal3fv(v);
            v+=3;
            glVertex3fv(v);
            v+=3;
            glVertex3fv(v);
            v+=3;
          }
          glEnd();
          
          if(*(v++)) {          
            glBegin(GL_TRIANGLE_FAN);
            glNormal3fv(v);
            v+=3;
            glVertex3fv(v);
            v+=3;
            a=I->NEdge+1;
            while(a--) {
              glNormal3fv(v);
              v+=3;
              glVertex3fv(v);
              v+=3;
            }
            glEnd();
          }
          
          if(*(v++)) {
            
            glBegin(GL_TRIANGLE_FAN);
            glNormal3fv(v);
            v+=3;
            glVertex3fv(v);
            v+=3;
            a=I->NEdge+1;
            while(a--) {
              glNormal3fv(v);
              v+=3;
              glVertex3fv(v);
              v+=3;
            }
            glEnd();
          }
        }
        
        if(I->VSP) { /* stick spheres, if present */
          
          v = I->VSP;
          c = I->NSP;
          var_alpha = I->VarAlphaSph;

          if((alpha==1.0)&&!(var_alpha)) {
            
            sp=I->SP;
            while(c--)
              {
                glColor3fv(v);
                v+=3;
                for(a=0;a<sp->NStrip;a++) {
                  glBegin(GL_TRIANGLE_STRIP);
                  cc=sp->StripLen[a];
                  while(cc--) {
                    glNormal3fv(v);
                    v+=3;
                    glVertex3fv(v);
                    v+=3;
                  }
                  glEnd();
                }
              }
          } else {
            sp=I->SP;
            while(c--) {
              if(!var_alpha) {
                glColor4f(v[0],v[1],v[2],alpha);
              } else {
                glColor4f(v[0],v[1],v[2],*(var_alpha++));
              }
              v+=3;
              for(a=0;a<sp->NStrip;a++) {
                glBegin(GL_TRIANGLE_STRIP);
                cc=sp->StripLen[a];
                while(cc--) {
                  glNormal3fv(v);
                  v+=3;
                  glVertex3fv(v);
                  v+=3;
                }
                glEnd();
              }
            }
          }
        }
        PRINTFD(G,FB_RepCylBond)
          " RepCylBondRender: done.\n"
          ENDFD;
      
        if(use_dlst&&I->R.displayList) {
          glEndList();
        }
      }
    }
  }
}

static void RepValence(float **v_ptr,int *n_ptr, /* opengl */
                       float **vr_ptr,int *nr_ptr, /* ray */
                       float *v1,float *v2,int *other,
                       int a1,int a2,float *coord,
                       float *color1,float *color2,int ord,
                       int n_edge,
                       float tube_size,
                       float overlap,
                       float nub,
                       int half_bonds,
                       int fixed_r,
                       float scale_r)
{

  float d[3],t[3],p0[3],p1[3],p2[3],*vv;
  float v1t[3],v2t[3],vh[3];
  float *v = *v_ptr,*vr = *vr_ptr;
  int n = *n_ptr,nr = *nr_ptr;
  int a3;
  int double_sided;
      
  /* First, we need to construct a coordinate system */

  /* get direction vector */

  p0[0] = (v2[0] - v1[0]);
  p0[1] = (v2[1] - v1[1]);
  p0[2] = (v2[2] - v1[2]);
  
  copy3f(p0,d);
  normalize3f(p0);
  
  /* need a third atom to get planarity*/
  a3 = ObjectMoleculeGetPrioritizedOther(other,a1,a2,&double_sided);

  if(a3<0) {    
    t[0] = p0[0];
    t[1] = p0[1];
    t[2] = -p0[2];
  } else {
    vv= coord+3*a3;
    t[0] = *(vv++)-v1[0];
    t[1] = *(vv++)-v1[1];
    t[2] = *(vv++)-v1[2];
    normalize3f(t);
  }
  
  cross_product3f(d,t,p1);
  
  normalize3f(p1);

  if(length3f(p1)==0.0) {
    p1[0]=p0[1];
    p1[1]=p0[2];
    p1[2]=p0[0];
    cross_product3f(p0,p1,p2);
    normalize3f(p2);
  } else {
    cross_product3f(d,p1,p2);
    
    normalize3f(p2);
  }

  /* we have a coordinate system*/

  /* Next, we need to determine how many cylinders */
  
  switch(ord) {
  case 2:
    {
      float radius = tube_size;
      float overlap_r;
      float nub_r;
      if(!fixed_r) {
        radius*=scale_r;
        radius/=2.5;
      }

      overlap_r = radius*overlap;
      nub_r = radius*nub;

      t[0] = p2[0]*1.5F*radius;
      t[1] = p2[1]*1.5F*radius;
      t[2] = p2[2]*1.5F*radius;
      
      if(!half_bonds) {

        /* opengl */

        copy3f(color1,v);
        v+=3;
        
        add3f(v1,t,v1t);
        add3f(v2,t,v2t);
        
        v=RepCylinder(v,v1t,v2t,n_edge,1,1,radius,
                      overlap_r,nub_r);
        n++;

        /* ray */

        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius;                                         
        copy3f(v1t,vr);
        vr+=3;        
        copy3f(v2t,vr);
        vr+=3;
        nr++;

        /* opengl */

        copy3f(color1,v);
        
        v+=3;
        
        subtract3f(v1,t,v1t);
        subtract3f(v2,t,v2t);
        
        v=RepCylinder(v,v1t,v2t,n_edge,1,1,radius,
                      overlap_r,nub_r);

        /* ray */

        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius;                                         
        copy3f(v1t,vr);
        vr+=3;        
        copy3f(v2t,vr);
        vr+=3;
        nr++;

        n++;
      } else {
        vh[0] = (v1[0]+v2[0])*0.5F;
        vh[1] = (v1[1]+v2[1])*0.5F;
        vh[2] = (v1[2]+v2[2])*0.5F;

        if(color1) {

          /* opengl */
          copy3f(color1,v);
          v+=3;

          add3f(v1,t,v1t);
          add3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;

          /* opengl */
          copy3f(color1,v);
          v+=3;

          subtract3f(v1,t,v1t);
          subtract3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;
          
        }
        if(color2) {

          copy3f(color2,v);
          v+=3;

          add3f(v2,t,v1t);
          add3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;

          copy3f(color2,v);
          v+=3;

          subtract3f(v2,t,v1t);
          subtract3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;
          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;


        }
      }
    }
    break;
  case 3:
    {
      float radius = tube_size;
      float overlap_r;
      float nub_r;
      if(!fixed_r) {
        radius*=scale_r;
        radius/=3.5;
      }

      overlap_r = radius*overlap;
      nub_r = radius*nub;

      t[0] = p2[0]*2.5F*radius;
      t[1] = p2[1]*2.5F*radius;
      t[2] = p2[2]*2.5F*radius;

      if(!half_bonds) {
        /* opengl */
        copy3f(color1,v);
        
        v+=3;
        copy3f(v1,v1t);
        copy3f(v2,v2t);
        v=RepCylinder(v,v1t,v2t,n_edge,1,1,radius,
                      overlap_r,nub_r);
        n++;

        /* ray */
        
        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius;                                         
        copy3f(v1,vr);
        vr+=3;        
        copy3f(v2,vr);
        vr+=3;
        nr++;

        /* opengl */
        copy3f(color1,v);
        
        v+=3;
        
        add3f(v1,t,v1t);
        add3f(v2,t,v2t);
        
        v=RepCylinder(v,v1t,v2t,n_edge,1,1,radius,
                      overlap_r,nub_r);
        n++;
        
        /* ray */
        
        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius;                                         
        copy3f(v1t,vr);
        vr+=3;        
        copy3f(v2t,vr);
        vr+=3;
        nr++;

        /* opengl */
        copy3f(color1,v);
        
        v+=3;
        
        subtract3f(v1,t,v1t);
        subtract3f(v2,t,v2t);
        
        v=RepCylinder(v,v1t,v2t,n_edge,1,1,radius,
                      overlap_r,nub_r);
        n++;

        /* ray */
        
        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius;                                         
        copy3f(v1t,vr);
        vr+=3;        
        copy3f(v2t,vr);
        vr+=3;
        nr++;

      } else {
        vh[0] = (v1[0]+v2[0])*0.5F;
        vh[1] = (v1[1]+v2[1])*0.5F;
        vh[2] = (v1[2]+v2[2])*0.5F;

        if(color1) {
          /* opengl */
          copy3f(color1,v);
          v+=3;
          
          copy3f(v1,v1t);
          v=RepCylinder(v,v1t,vh,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;
          
          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1,vr);
          vr+=3;        
          copy3f(vh,vr);
          vr+=3;
          nr++;

          /* opengl */
          copy3f(color1,v);
          v+=3;

          add3f(v1,t,v1t);
          add3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;

          /* opengl */
          copy3f(color1,v);
          v+=3;

          subtract3f(v1,t,v1t);
          subtract3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;

          
        }
        if(color2) {
          
          /* opengl */
          copy3f(color2,v);
          v+=3;
          
          copy3f(v2,v2t);
          v=RepCylinder(v,v2t,vh,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v2,vr);
          vr+=3;        
          copy3f(vh,vr);
          vr+=3;
          nr++;

          /* opengl */
          copy3f(color2,v);
          v+=3;

          add3f(v2,t,v1t);
          add3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;

          /* opengl */
          copy3f(color2,v);
          v+=3;

          subtract3f(v2,t,v1t);
          subtract3f(vh,t,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1t,vr);
          vr+=3;        
          copy3f(v2t,vr);
          vr+=3;
          nr++;

        }
      }      
    }
    
    break;
  case 4: 
    {
      float radius = tube_size;
      float radius2 = tube_size;
      float overlap_r,overlap_r2;
      float nub_r,nub_r2;
      float along[3],adj[3],v1tt[3],v2tt[3];
      float inner1a = 0.24F;
      float inner1b = 0.44F;
      float inner2a = 0.5F+(0.5F-inner1b);
      float inner2b = 1.0F-inner1a;

      if(!fixed_r) {
        radius*=scale_r;
        radius2=radius/2.5F;
        t[0] = p2[0]*1.5F*radius;
        t[1] = p2[1]*1.5F*radius;
        t[2] = p2[2]*1.5F*radius;
      } else {
        inner1a -= 0.04F;
        inner2b = 1.0F-inner1a;
        t[0] = p2[0]*3*radius;
        t[1] = p2[1]*3*radius;
        t[2] = p2[2]*3*radius;
      }
      
      overlap_r = radius*overlap;
      nub_r = radius*nub;
      overlap_r2 = radius2*overlap;
      nub_r2 = radius2*nub;

      
      if(!half_bonds) {

        /* opengl */

        copy3f(color1,v);
        v+=3;
        
        copy3f(v1,v1t);
        copy3f(v2,v2t);
        v=RepCylinder(v,v1t,v2t,n_edge,1,1,radius,
                      overlap_r,nub_r);
        n++;

        /* ray */

        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius;                                         
        copy3f(v1,vr);
        vr+=3;        
        copy3f(v2,vr);
        vr+=3;
        nr++;

        subtract3f(v1,t,v1t);
        subtract3f(v2,t,v2t);
        
        subtract3f(v2t,v1t,along);
        scale3f(along,inner1a,adj);
        add3f(adj,v1t,v1tt);
        scale3f(along,inner1b,adj);
        add3f(adj,v1t,v2tt);

        /* ray */

        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius2;                                              
        copy3f(v1tt,vr);
        vr+=3;        
        copy3f(v2tt,vr);
        vr+=3;
        nr++;

        /* opengl */

        copy3f(color1,v); 
        v+=3;
        
        v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                      overlap_r2,nub_r2);
        n++;


        scale3f(along,inner2a,adj);
        add3f(adj,v1t,v1tt);
        scale3f(along,inner2b,adj);
        add3f(adj,v1t,v2tt);

        /* ray */

        copy3f(color1,vr);
        vr+=3;        
        *(vr++)=radius2;                                              
        copy3f(v1tt,vr);
        vr+=3;        
        copy3f(v2tt,vr);
        vr+=3;
        nr++;

        /* opengl */

        copy3f(color1,v);
        v+=3;

        v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                      overlap_r2,nub_r2);        
        n++;

        if(double_sided) {
          
          
          add3f(v1,t,v1t);
          add3f(v2,t,v2t);
          
          subtract3f(v2t,v1t,along);
          scale3f(along,inner1a,adj);
          add3f(adj,v1t,v1tt);
          scale3f(along,inner1b,adj);
          add3f(adj,v1t,v2tt);
          
          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius2;                                            
          copy3f(v1tt,vr);
          vr+=3;        
          copy3f(v2tt,vr);
          vr+=3;
          nr++;
          
          /* opengl */
          
          copy3f(color1,v);
          v+=3;

          v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                        overlap_r2,nub_r2);
          n++;
          
          scale3f(along,inner2a,adj);
          add3f(adj,v1t,v1tt);
          scale3f(along,inner2b,adj);
          add3f(adj,v1t,v2tt);
          
          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius2;                                            
          copy3f(v1tt,vr);
          vr+=3;        
          copy3f(v2tt,vr);
          vr+=3;
          nr++;
          
          /* opengl */
          
          copy3f(color1,v);          
          v+=3;
          
          v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                        overlap_r2,nub_r2);        
          n++;
        
        }

      } else {
        vh[0] = (v1[0]+v2[0])*0.5F;
        vh[1] = (v1[1]+v2[1])*0.5F;
        vh[2] = (v1[2]+v2[2])*0.5F;

        if(color1) {

          /* opengl */

          copy3f(color1,v);
          v+=3;

          copy3f(v1,v1t);
          copy3f(vh,v2t);
          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v1,vr);
          vr+=3;        
          copy3f(vh,vr);
          vr+=3;
          nr++;
          
          subtract3f(v1,t,v1t);
          subtract3f(v2,t,v2t);
          
          subtract3f(v2t,v1t,along);
          scale3f(along,inner1a,adj);
          add3f(adj,v1t,v1tt);
          scale3f(along,inner1b,adj);
          add3f(adj,v1t,v2tt);

          /* ray */
          
          copy3f(color1,vr);
          vr+=3;        
          *(vr++)=radius2;                                            
          copy3f(v1tt,vr);
          vr+=3;        
          copy3f(v2tt,vr);
          vr+=3;
          nr++;
          
          /* open gl */

          copy3f(color1,v);
          v+=3;

          v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                        overlap_r2,nub_r2);
          n++;
         
          if(double_sided) {
            
            add3f(v1,t,v1t);
            add3f(v2,t,v2t);
            
            subtract3f(v2t,v1t,along);
            scale3f(along,inner1a,adj);
            add3f(adj,v1t,v1tt);
            scale3f(along,inner1b,adj);
            add3f(adj,v1t,v2tt);
            
            /* ray */
            
            copy3f(color1,vr);
            vr+=3;        
            *(vr++)=radius2;                                          
            copy3f(v1tt,vr);
            vr+=3;        
            copy3f(v2tt,vr);
            vr+=3;
            nr++;
            
            /* open gl */
            
            copy3f(color1,v);
            v+=3;

            v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                          overlap_r2,nub_r2);
            n++;
            
            
          }
        }

        if(color2) {

          copy3f(color2,v);
          v+=3;

          copy3f(v2,v1t);
          copy3f(vh,v2t);

          v=RepCylinder(v,v1t,v2t,n_edge,1,0,radius,
                        overlap_r,nub_r);
          n++;

          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius;                                             
          copy3f(v2,vr);
          vr+=3;        
          copy3f(vh,vr);
          vr+=3;
          nr++;

          subtract3f(v1,t,v1t);
          subtract3f(v2,t,v2t);
          
          subtract3f(v2t,v1t,along);
          scale3f(along,inner2a,adj);
          add3f(adj,v1t,v1tt);
          scale3f(along,inner2b,adj);
          add3f(adj,v1t,v2tt);

          /* ray */
          
          copy3f(color2,vr);
          vr+=3;        
          *(vr++)=radius2;                                            
          copy3f(v1tt,vr);
          vr+=3;        
          copy3f(v2tt,vr);
          vr+=3;
          nr++;

          /* opengl */

          copy3f(color2,v);
          v+=3;

          v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                        overlap_r2,nub_r2);
          n++;
          
          if(double_sided) {
            
            add3f(v1,t,v1t);
            add3f(v2,t,v2t);
            
            subtract3f(v2t,v1t,along);
            scale3f(along,inner2a,adj);
            add3f(adj,v1t,v1tt);
            scale3f(along,inner2b,adj);
            add3f(adj,v1t,v2tt);
            
            /* ray */
            
            copy3f(color2,vr);
            vr+=3;        
            *(vr++)=radius2;                                          
            copy3f(v1tt,vr);
            vr+=3;        
            copy3f(v2tt,vr);
            vr+=3;
            nr++;
            
            /* opengl */
            
            copy3f(color2,v);
            v+=3;
            
            v=RepCylinder(v,v1tt,v2tt,n_edge,1,1,radius2,
                          overlap_r2,nub_r2);
            n++;
            
          }
        }
      }
    }
    break;
  }
  *v_ptr = v;
  *n_ptr = n;
  *vr_ptr = vr;
  *nr_ptr = nr;

}


Rep *RepCylBondNew(CoordSet *cs,int state)
{
  PyMOLGlobals *G=cs->State.G;
  ObjectMolecule *obj;
  int a,a1,a2,c1,c2,s1,s2;
  register int b1,b2;
  register BondType *b;
  float *v,*vv1,*vv2,*v0,*vr,*vsp,*vspc;
  float v1[3],v2[3],h[3];
  float radius;
  int nEdge;
  float valence;
  float overlap,nub;
  int half_bonds,*other=NULL;
  int visFlag;
  int maxCyl;
  int ord;
  int stick_ball;
  float stick_ball_ratio=1.0F;
  unsigned int v_size,vr_size,rp_size,vp_size;
  Pickable *rp;
  register AtomInfoType *ai1,*ai2;
  SphereRec *sp = NULL;
  float *rgb1,*rgb2,rgb1_buf[3],rgb2_buf[3];
  int fixed_radius = false;
  int caps_req = true;
  int valence_flag = false;
  int hide_long = false;
  int stick_color = 0;
  int cartoon_side_chain_helper = 0;
  int ribbon_side_chain_helper = 1;
  int na_mode;
  int *marked = NULL;
  float scale_r = 1.0F;
  int variable_alpha = false;
  int n_var_alpha=0, n_var_alpha_ray=0,n_var_alpha_sph=0;
  float transp;
  int valence_found  = false;
  const float _0p9 = 0.9F;
  OOAlloc(G,RepCylBond);

  PRINTFD(G,FB_RepCylBond)
    " RepCylBondNew-Debug: entered.\n"
    ENDFD;

  obj = cs->Obj;
  visFlag=false;
  b=obj->Bond;
  ai1=obj->AtomInfo;
  if(obj->RepVisCache[cRepCyl])
    for(a=0;a<obj->NBond;a++)
      {
        b1 = b->index[0];
        b2 = b->index[1];
        
        b++;
        if(ai1[b1].visRep[cRepCyl]||
           ai1[b2].visRep[cRepCyl]) {
          visFlag=true;
          break;
        }
      }
  if(!visFlag) {
    OOFreeP(I);
    return(NULL); /* skip if no dots are visible */
  }

  marked = Calloc(int,obj->NAtom);

  valence = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_valence);
  valence_flag = (valence!=0.0F);
  maxCyl = 0;

  stick_color = SettingGet_color(G,cs->Setting,obj->Obj.Setting,cSetting_stick_color);
  cartoon_side_chain_helper = SettingGet_b(G,cs->Setting, obj->Obj.Setting,
                                           cSetting_cartoon_side_chain_helper);
  ribbon_side_chain_helper = SettingGet_b(G,cs->Setting, obj->Obj.Setting,
                                          cSetting_ribbon_side_chain_helper);

  transp = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_transparency);
  hide_long = SettingGet_b(G,cs->Setting,obj->Obj.Setting,cSetting_hide_long_bonds);

  b=obj->Bond;
  for(a=0;a<obj->NBond;a++) {
      b1 = b->index[0];
      b2 = b->index[1];
      ord = b->order;
      
      if(obj->DiscreteFlag) {
        if((cs==obj->DiscreteCSet[b1])&&(cs==obj->DiscreteCSet[b2])) {
          a1=obj->DiscreteAtmToIdx[b1];
          a2=obj->DiscreteAtmToIdx[b2];
        } else {
          a1=-1;
          a2=-1;
        }
      } else {
        a1=cs->AtmToIdx[b1];
        a2=cs->AtmToIdx[b2];
      }
      if((a1>=0)&&(a2>=0)) {
        int bd_valence_flag;

        if((!variable_alpha) && AtomInfoCheckBondSetting(G,b,cSetting_stick_transparency))
          variable_alpha = true;
        
        AtomInfoGetBondSetting_b(G,b,cSetting_valence,valence_flag,&bd_valence_flag);
        
        if(bd_valence_flag) {
          valence_found = true;
          switch(ord) {
          case 1:
            maxCyl+=2; 
            break;
          case 2:
            maxCyl+=4;
            break;
          case 3:
            maxCyl+=6;
            break;
          case 4:
            maxCyl+=6;
            break;
          }
        } else
          maxCyl+=2;
      }
      b++;
  }


  nEdge = (int)SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_quality);
  radius = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_radius);
  half_bonds = (int)SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_half_bonds);  
  na_mode = SettingGet_i(G,cs->Setting,obj->Obj.Setting,cSetting_cartoon_nucleic_acid_mode);

  RepInit(G,&I->R);
  I->R.fRender=(void (*)(struct Rep *, RenderInfo *))RepCylBondRender;
  I->R.fFree=(void (*)(struct Rep *))RepCylBondFree;
  I->R.obj=(CObject*)obj;
  I->R.cs = cs;

  I->V = NULL;
  I->VR = NULL;
  I->N = 0;
  I->NR = 0;
  I->NP = 0;
  I->VP = NULL;
  I->SP = NULL;
  I->VSP = NULL;
  I->NSP = 0;
  I->VSPC = NULL;
  I->NSPC = 0;
  I->VarAlpha = NULL;
  I->VarAlphaRay = NULL;
  I->VarAlphaSph = NULL;

  if(obj->NBond) {

    if(cartoon_side_chain_helper || ribbon_side_chain_helper) {
      /* mark atoms that are bonded to atoms without a
         visible cartoon or ribbon */

      b=obj->Bond;
      for(a=0;a<obj->NBond;a++) {

          b1 = b->index[0];
          b2 = b->index[1];
          ord = b->order;
          
          if(obj->DiscreteFlag) {
            if((cs==obj->DiscreteCSet[b1])&&(cs==obj->DiscreteCSet[b2])) {
              a1=obj->DiscreteAtmToIdx[b1];
              a2=obj->DiscreteAtmToIdx[b2];
            } else {
              a1=-1;
              a2=-1;
            }
          } else {
            a1=cs->AtmToIdx[b1];
            a2=cs->AtmToIdx[b2];
          }
          if((a1>=0)&&(a2>=0)) {
            register AtomInfoType *ati1=obj->AtomInfo+b1;
            register AtomInfoType *ati2=obj->AtomInfo+b2;


            if((!ati1->hetatm) && (!ati2->hetatm)) {
              if(((cartoon_side_chain_helper && ati1->visRep[cRepCartoon] && !ati2->visRep[cRepCartoon]) ||
                  (ribbon_side_chain_helper && ati1->visRep[cRepRibbon] && !ati2->visRep[cRepRibbon]))) {
                marked[b1] = 1;
              }
              if(((cartoon_side_chain_helper && ati2->visRep[cRepCartoon] && !ati1->visRep[cRepCartoon]) ||
                  (ribbon_side_chain_helper && ati2->visRep[cRepRibbon] && !ati1->visRep[cRepRibbon]))) {
                marked[b2] = 1;
              }
            }
          }
          b++;
      }

    }

    stick_ball = SettingGet_b(G,cs->Setting,obj->Obj.Setting,cSetting_stick_ball);
    overlap = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_overlap);
    nub = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_nub);

    if(valence_found) {/* build list of up to 2 connected atoms for each atom */
      other=ObjectMoleculeGetPrioritizedOtherIndexList(obj,cs);
      fixed_radius = SettingGet_b(G,cs->Setting,obj->Obj.Setting,cSetting_stick_fixed_radius);
      scale_r = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_valence_scale);
    }
    
    /* OpenGL */

    v_size = maxCyl * ( (9+6+6) * (nEdge+1) + 3 );
    /* each cylinder is 9+6+6+3= 21*(nEdge+1) floats for coordinates
       plus 3 more floats for color */

    /*    printf("debug maxCyl: %d nEdge: %d v_size: %d\n",maxCyl,nEdge,v_size);*/
    fflush(stdout);
    if(variable_alpha) 
      I->VarAlpha = Alloc(float,maxCyl);
    I->V = Alloc(float,v_size);
    ErrChkPtr(G,I->V);

    /* RayTrace */

    vr_size = maxCyl*10*3;
    if(variable_alpha) 
      I->VarAlphaRay = Alloc(float,maxCyl);
    I->VR=Alloc(float,vr_size);
    ErrChkPtr(G,I->VR);

    /* spheres for stick & balls */
       
    if(stick_ball) {
      int ds;
      stick_ball_ratio = SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_stick_ball_ratio);

      ds = SettingGet_i(G,cs->Setting,obj->Obj.Setting,cSetting_sphere_quality);
      if(ds<0) ds=0;
      if(ds>4) ds=4;
      sp = G->Sphere->Sphere[ds];

      I->SP = sp;
      I->VSP=Alloc(float,maxCyl*2*(3+sp->NVertTot*6));
      I->VSPC=Alloc(float,maxCyl*2*7);
      I->VarAlphaSph = Alloc(float,maxCyl*2);
      ErrChkPtr(G,I->VSP);
    }
    I->NEdge = nEdge;
       
    v=I->V;
    vr=I->VR;
    vsp = I->VSP;
    vspc = I->VSPC;
    b=obj->Bond;
    for(a=0;a<obj->NBond;a++) {
      
      b1 = b->index[0];
      b2 = b->index[1];
      ord = b->order;
      
      if(obj->DiscreteFlag) {
        if((cs==obj->DiscreteCSet[b1])&&(cs==obj->DiscreteCSet[b2])) {
          a1=obj->DiscreteAtmToIdx[b1];
          a2=obj->DiscreteAtmToIdx[b2];
        } else {
          a1=-1;
          a2=-1;
        }
      } else {
        a1=cs->AtmToIdx[b1];
        a2=cs->AtmToIdx[b2];
      }
      if((a1>=0)&&(a2>=0)) {

        register AtomInfoType *ati1=obj->AtomInfo+b1;
        register AtomInfoType *ati2=obj->AtomInfo+b2;
        int bd_stick_color;        
        float bd_radius;
        float overlap_r,nub_r;
        float bd_transp;

        AtomInfoGetBondSetting_color(G,b,cSetting_stick_color,stick_color,&bd_stick_color);
        AtomInfoGetBondSetting_f(G,b,cSetting_stick_radius,radius,&bd_radius);
        if(variable_alpha) 
          AtomInfoGetBondSetting_f(G,b,cSetting_stick_transparency,transp,&bd_transp);

        overlap_r = overlap * bd_radius;
        nub_r = nub * bd_radius;
        
        if(bd_stick_color<0) {
          if(bd_stick_color==cColorObject) {
            c1 = (c2 = obj->Obj.Color);
          } else if(ColorCheckRamped(G,bd_stick_color)) {
            c1 = (c2 = bd_stick_color);            
          } else {
            c1=*(cs->Color+a1);
            c2=*(cs->Color+a2);
          }
        } else {
          c1 = (c2 = bd_stick_color);
        }
        
        vv1 = cs->Coord+3*a1;
        vv2 = cs->Coord+3*a2;
        
        s1=ati1->visRep[cRepCyl];
        s2=ati2->visRep[cRepCyl];
        
        if(!(s1&&s2))
          if(!half_bonds) {
            s1 = 0;
            s2 = 0;
          }

        if(hide_long && (s1||s2)) {
          float cutoff = (ati1->vdw + ati2->vdw) * _0p9;
          ai1 = obj->AtomInfo + b1;
          ai2 = obj->AtomInfo + b2;
          if(!within3f(vv1,vv2,cutoff)) /* atoms separated by more than 90% of the sum of their vdw radii */
            s1 = s2 = 0;
        }
        
        if( (!ati1->hetatm) && (!ati2->hetatm) &&
            ((cartoon_side_chain_helper && ati1->visRep[cRepCartoon] && ati2->visRep[cRepCartoon]) ||
             (ribbon_side_chain_helper && ati1->visRep[cRepRibbon] && ati2->visRep[cRepRibbon]))) {
          
          register char *name1=ati1->name;
          register int prot1=ati1->protons;
          register char *name2=ati2->name;
          register int prot2=ati2->protons;
          
          if(prot1 == cAN_C) { 
            if((name1[1]=='A')&&(name1[0]=='C')&&(!name1[2])) { /* CA */
              if(prot2 == cAN_C) { 
                if((name2[1]=='B')&&(name2[0]=='C')&&(!name2[2]))
                  c1 = c2;  /* CA-CB */
                else if((!name2[1])&&(name2[0]=='C')&&(!marked[b2]))
                  s1 = s2 = 0; /* suppress CA-C */
              } else if(prot2 == cAN_H) 
                s1 = s2 = 0; /* suppress all CA-hydrogens */
            } else if((na_mode==1)&&(prot2 == cAN_C)) {
              if((((name2[3]==0)&&
                   ((name2[2]=='*')||(name2[2]=='\''))&&
                   (name2[1]=='5')&&
                   (name2[0]=='C')))&&
                 (((name1[3]==0)&&
                   ((name1[2]=='*')||(name1[2]=='\''))&&
                   (name1[1]=='4')&&
                   (name1[0]=='C'))))
                s1 = s2 = 0;
            }
          } else if(prot1 == cAN_N) { 
            if((!name1[1])&&(name1[0]=='N')) { /* N */
              if(prot2 == cAN_C) {
                if((name2[1]=='D')&&(name2[0]=='C')&&(!name2[2])) 
                  c1 = c2; /* N->CD in PRO */
                else if((name2[1]=='A')&&(name2[0]=='C')&&(!name2[2])&&(!marked[b1]))
                  {
                    char *resn2 = ati2->resn;
                    if(!((resn2[0]=='P')&&(resn2[1]=='R')&&(resn2[2]=='O')))
                      s1 = s2 = 0; /* suppress N-CA, except in pro */
                    else
                      c1 = c2;
                  }
                else if((!name2[1])&&(name2[0]=='C')&&(!marked[b1]))
                  s1 = s2 = 0; /* suppress N-C */
              } else if(prot2 == cAN_H)
                s1 = s2 = 0; /* suppress all N-hydrogens */
            }
          } else if((prot1 == cAN_O)&&(prot2 == cAN_C)) { 
            if((!name2[1])&&(name2[0]=='C')&&
               (((!name1[1])&&(name1[0]=='O'))||
                ((name1[3]==0)&&(name1[2]=='T')&&(name1[1]=='X')&&(name1[0]=='O')))
               &&(!marked[b2]))
              s1 = s2 = 0; /* suppress C-O,OXT */
            else if(na_mode==1) {
              if((((name2[3]==0)&&
                   ((name2[2]=='*')||(name2[2]=='\''))&&
                   ((name2[1]=='3')||(name2[1]=='5'))&&
                   (name2[0]=='C')))&&
                 (((name1[3]==0)&&
                   ((name1[2]=='*')||(name1[2]=='\''))&&
                   ((name1[1]=='3')||(name1[1]=='5'))&&
                   (name1[0]=='O'))))
                s1 = s2 = 0; 
            } 
          } else if((prot1 == cAN_P)&&(prot2 == cAN_O)) {
            if((!name1[1])&&(name1[0]=='P')&&
               (((name2[3]==0)&&(name2[2]=='P')&&
                 ((name2[1]=='1')||(name2[1]=='2')||(name2[1]=='3'))
                 &&(name2[0]=='O'))))
              s1 = s2 = 0; /* suppress P-O1P,O2P,O3P */
            else if(na_mode==1) {
              if((!name1[1])&&(name1[0]=='P')&&
                 (((name2[3]==0)&&
                   ((name2[2]=='*')||(name2[2]=='\''))&&
                   ((name2[1]=='3')||(name2[1]=='5'))&&
                   (name2[0]=='O'))))
                s1 = s2 = 0;
            }
          } 
          if(prot2 == cAN_C) {
            if((name2[1]=='A')&&(name2[0]=='C')&&(!name2[2])) { /* CA */
              if(prot1 == cAN_C) { 
                if((name1[1]=='B')&&(name1[0]=='C')&&(!name1[2]))
                  c2 = c1; /* CA-CB */
                else if((!name1[1])&&(name1[0]=='C')&&(!marked[b1]))
                  s1 = s2 = 0; /* suppress CA-C */
              } else if(prot1 == cAN_H) 
                s1 = s2 = 0; /* suppress all CA-hydrogens */
            } else if((na_mode==1)&&(prot2 == cAN_C)) {
              if((((name1[3]==0)&&
                   ((name1[2]=='*')||(name1[2]=='\''))&&
                   (name1[1]=='5')&&
                   (name1[0]=='C')))&&
                 (((name2[3]==0)&&
                   ((name2[2]=='*')||(name2[2]=='\''))&&
                   (name2[1]=='4')&&
                   (name2[0]=='C'))))
                s1 = s2 = 0;
            }
          } else if(prot2 == cAN_N) {
            if((!name2[1])&&(name2[0]=='N')) { /* N */
              if(prot1 == cAN_C) { 
                if((name1[1]=='D')&&(name1[0]=='C')&&(!name1[2]))
                  c2 = c1; /* N->CD in PRO */
                else if((name1[1]=='A')&&(name1[0]=='C')&&(marked[b2])) 
                  { 
                    char *resn1 = ati1->resn;
                    if(!((resn1[0]=='P')&&(resn1[1]=='R')&&(resn1[2]=='O')))
                      s1 = s2 = 0; /* suppress N-CA, except in pro */
                    else
                      c2 = c1;
                  }
                else if((!name1[1])&&(name1[0]=='C')&&(!marked[b2]))
                  s1 = s2 = 0; /* suppress N-C */
              } else if(prot1 == cAN_H)
                s1 = s2 = 0; /* suppress all N-hydrogens */
            }
          } else if((prot2 == cAN_O)&&(prot1 == cAN_C)) {
            if((!name1[1])&&(name1[0]=='C')&&
               (((!name2[1])&&(name2[0]=='O'))||
                ((name2[3]==0)&&(name2[2]=='T')&&(name2[1]=='X')&&(name2[0]=='O')))
               &&(!marked[b1]))
              s1 = s2 = 0; /* suppress C-O,OXT */
            else if (na_mode==1) {
              if((((name1[3]==0)&&
                   ((name1[2]=='*')||(name1[2]=='\''))&&
                   ((name1[1]=='3')||(name1[1]=='5'))&&
                   (name1[0]=='C')))&&
                 (((name2[3]==0)&&
                   ((name2[2]=='*')||(name2[2]=='\''))&&
                   ((name2[1]=='3')||(name2[1]=='5'))&&
                   (name2[0]=='O'))))
                s1 = s2 = 0;
            }
          } else if((prot2 == cAN_P)&&(prot1 == cAN_O)) {
            if((!name2[1])&&(name2[0]=='P')&&
               (((name1[3]==0)&&(name1[2]=='P')&&
                 ((name1[1]=='1')||(name1[1]=='2')||(name1[1]=='3'))
                 &&(name1[0]=='O'))))
              s1 = s2 = 0; /* suppress P-O1P,O2P,O3P */
            else if(na_mode==1) {
              if((!name2[1])&&(name2[0]=='P')&&
                 (((name1[3]==0)&&
                   ((name1[2]=='*')||(name1[2]=='\''))&&
                   ((name1[1]=='3')||(name1[1]=='5'))&&
                   (name1[0]=='O'))))
                s1 = s2 = 0;
            }
          }
        }
          
        if(stick_ball) {
          float vdw = stick_ball_ratio * bd_radius;
          int d,e;
          if(stick_ball_ratio>=1.0F) /* don't use caps if spheres are big enough */
            caps_req = false;
          if(s1&&(!marked[b1])) { /* just once for each atom... */
            int *q=sp->Sequence;
            int *s=sp->StripLen;
            marked[b1]=1;
            {
              if(ColorCheckRamped(G,c1)) {
                ColorGetRamped(G,c1,vv1,rgb2_buf,state);
                rgb1 = rgb1_buf;
              } else {
                rgb1 = ColorGet(G,c1);
              }
            }
            copy3f(rgb1,vsp);
            vsp+=3;
            for(d=0;d<sp->NStrip;d++)
              {
                for(e=0;e<(*s);e++)
                  {
                    *(vsp++)=sp->dot[*q][0]; /* normal */
                    *(vsp++)=sp->dot[*q][1];
                    *(vsp++)=sp->dot[*q][2];
                    *(vsp++)=vv1[0]+vdw*sp->dot[*q][0]; /* point */
                    *(vsp++)=vv1[1]+vdw*sp->dot[*q][1];
                    *(vsp++)=vv1[2]+vdw*sp->dot[*q][2];
                    q++;
                  }
                s++;
              }
            I->NSP++;
            copy3f(rgb1,vspc);
            vspc+=3;
            copy3f(vv1,vspc);
            vspc+=3;
            *(vspc++)=vdw;
            I->NSPC++;
          }

          if(s2&&!(marked[b2])) { /* just once for each atom... */
            int *q=sp->Sequence;
            int *s=sp->StripLen;
            marked[b2]=1;
              
            if(ColorCheckRamped(G,c2)) {
              ColorGetRamped(G,c2,vv2,rgb2_buf,state);
              rgb2 = rgb2_buf;
            } else {
              rgb2 = ColorGet(G,c2);
            }
              
            copy3f(rgb2,vsp);
            vsp+=3;
              
            for(d=0;d<sp->NStrip;d++)
              {
                for(e=0;e<(*s);e++)
                  {
                    *(vsp++)=sp->dot[*q][0]; /* normal */
                    *(vsp++)=sp->dot[*q][1];
                    *(vsp++)=sp->dot[*q][2];
                    *(vsp++)=vv2[0]+vdw*sp->dot[*q][0]; /* point */
                    *(vsp++)=vv2[1]+vdw*sp->dot[*q][1];
                    *(vsp++)=vv2[2]+vdw*sp->dot[*q][2];
                    q++;
                  }
                s++;
              }
            I->NSP++;

            copy3f(rgb2,vspc);
            vspc+=3;
            copy3f(vv2,vspc);
            vspc+=3;
            *(vspc++)=vdw;
            I->NSPC++;
          }
        }

        if(hide_long && (s1||s2)) {
          float cutoff = (ati1->vdw + ati2->vdw) * _0p9;
          ai1 = obj->AtomInfo + b1;
          ai2 = obj->AtomInfo + b2;
          if(!within3f(vv1,vv2,cutoff)) /* atoms separated by more than 90% of the sum of their vdw radii */
            s1 = s2 = 0;
        }

        if(s1||s2)
          {
            int bd_valence_flag;

            AtomInfoGetBondSetting_b(G,b,cSetting_valence,valence_flag,&bd_valence_flag);
            
            if((bd_valence_flag)&&(ord>1)&&(ord<5)) {
                  
              if((c1==c2)&&s1&&s2&&(!ColorCheckRamped(G,c1))) {

                    
                v0 = ColorGet(G,c1);

                RepValence(&v,&I->N,
                           &vr,&I->NR,
                           vv1,vv2,other,
                           a1,a2,cs->Coord,
                           v0,NULL,ord,nEdge,
                           bd_radius,
                           overlap,
                           nub,
                           false,
                           fixed_radius,
                           scale_r);
              } else {

                rgb1 = NULL;
                if(s1) {
                  if(ColorCheckRamped(G,c1)) {
                    ColorGetRamped(G,c1,vv1,rgb1_buf,state);
                    rgb1 = rgb1_buf;
                  } else {
                    rgb1 = ColorGet(G,c1);
                  }
                }

                rgb2 = NULL;
                if(s2) 
                  {
                    if(ColorCheckRamped(G,c2)) {
                      ColorGetRamped(G,c2,vv2,rgb2_buf,state);
                      rgb2 = rgb2_buf;
                    } else {
                      rgb2 = ColorGet(G,c2);
                    }
                  }
                    
                RepValence(&v,&I->N,
                           &vr,&I->NR,
                           vv1,vv2,other,
                           a1,a2,cs->Coord,
                           rgb1,rgb2,ord,nEdge,
                           bd_radius,
                           overlap,
                           nub,
                           true,
                           fixed_radius,
                           scale_r);
              }
                  
            } else {
                  
              if((c1==c2)&&s1&&s2&&(!ColorCheckRamped(G,c1)))
                {
                      
                  copy3f(vv1,v1);
                  copy3f(vv2,v2);
                      
                  v0 = ColorGet(G,c1);
                      
                  /* ray-tracing */
                    
                  copy3f(v0,vr);
                  vr+=3;
                    
                  *(vr++)=bd_radius;                                      
                    
                  copy3f(v1,vr);
                  vr+=3;
                    
                  copy3f(v2,vr);
                  vr+=3;
                    
                  I->NR++;
                    
                  /* store color */
                    
                  copy3f(v0,v);
                  v+=3;
                    
                  I->N++;
                    
                  /* generate a cylinder */
                  v=RepCylinder(v,v1,v2,nEdge,caps_req,caps_req,bd_radius,overlap_r,nub_r);
                } else {                    
                  v1[0]=vv1[0];
                  v1[1]=vv1[1];
                  v1[2]=vv1[2];
                      
                  v2[0]=(vv1[0]+vv2[0])*0.5F;
                  v2[1]=(vv1[1]+vv2[1])*0.5F;
                  v2[2]=(vv1[2]+vv2[2])*0.5F;
                      
                  if(s1) {
                    if(ColorCheckRamped(G,c1)) {
                      ColorGetRamped(G,c1,v1,vr,state);
                      v0=vr;
                      vr+=3;
                    } else {
                      v0 = ColorGet(G,c1);
                      *(vr++)=*(v0);
                      *(vr++)=*(v0+1);
                      *(vr++)=*(v0+2);
                    }
                    *(vr++)=bd_radius;
                    
                    *(vr++)=*(v1);
                    *(vr++)=*(v1+1);
                    *(vr++)=*(v1+2);
                    
                    *(vr++)=*(v2);
                    *(vr++)=*(v2+1);
                    *(vr++)=*(v2+2);
                    
                    I->NR++;
                    
                    *(v++)=*(v0++);
                    *(v++)=*(v0++);
                    *(v++)=*(v0++);
                    
                    I->N++;
                    v=RepCylinder(v,v1,v2,nEdge,caps_req,0,bd_radius,overlap_r,nub_r);
                  }
                      
                  v1[0]=vv2[0];
                  v1[1]=vv2[1];
                  v1[2]=vv2[2];
                      
                  if(s2) {
                    if(ColorCheckRamped(G,c2)) {
                      ColorGetRamped(G,c2,v1,vr,state);
                      v0=vr;
                      vr+=3;
                    } else {
                      v0 = ColorGet(G,c2);
                      
                      *(vr++)=*(v0);
                      *(vr++)=*(v0+1);
                      *(vr++)=*(v0+2);
                    }
                    *(vr++)=bd_radius;
                    
                    *(vr++)=*(v1);
                    *(vr++)=*(v1+1);
                    *(vr++)=*(v1+2);
                    
                    *(vr++)=*(v2);
                    *(vr++)=*(v2+1);
                    *(vr++)=*(v2+2);
                    
                    I->NR++;
                    
                    *(v++)=*(v0++);
                    *(v++)=*(v0++);
                    *(v++)=*(v0++);
                    
                    I->N++;
                    v=RepCylinder(v,v1,v2,nEdge,caps_req,0,bd_radius,overlap_r,nub_r);
                  }
                }
            }

            if(variable_alpha) { /* record alpha values for each */
              float bd_alpha = (1.0F - bd_transp);
              while(n_var_alpha<I->N) {
                I->VarAlpha[n_var_alpha++] = bd_alpha;
              }
              while(n_var_alpha_ray<I->NR) {
                I->VarAlphaRay[n_var_alpha_ray++] = bd_alpha;
              }
              while(n_var_alpha_sph<I->NSP) {
                I->VarAlphaSph[n_var_alpha_sph++] = bd_alpha;
              }
            }
          }
      }
      /*      printf("%d\n",(v-I->V)/( (9+6+6) * (nEdge+1) + 3 ));*/
      b++;
    }

    PRINTFD(G,FB_RepCylBond)
      " RepCylBond-DEBUG: %d triplets\n",(int)(v-I->V)/3
      ENDFD;

    if((signed)v_size<(v-I->V))
      ErrFatal(G,"RepCylBond","V array overrun.");
    if((signed)vr_size<(vr-I->VR))
      ErrFatal(G,"RepCylBond","VR array overrun.");
    
    I->V = ReallocForSure(I->V,float,(v-I->V));
    I->VR = ReallocForSure(I->VR,float,(vr-I->VR));
    if(I->VSP) 
      I->VSP = ReallocForSure(I->VSP,float,(vsp-I->VSP));
    if(I->VSPC) 
      I->VSPC = ReallocForSure(I->VSPC,float,(vspc-I->VSPC));
    if(I->VarAlpha)
      I->VarAlpha = ReallocForSure(I->VarAlpha,float,n_var_alpha);
    if(n_var_alpha_ray) {
      if(I->VarAlphaRay)
        I->VarAlphaRay = ReallocForSure(I->VarAlphaRay,float,n_var_alpha_ray);
    } else {
      FreeP(I->VarAlphaRay);
    }
    if(n_var_alpha_sph) {
      if(I->VarAlphaSph)
        I->VarAlphaSph = ReallocForSure(I->VarAlphaSph,float,n_var_alpha_sph);
    } else {
      FreeP(I->VarAlphaSph);
    }
      
    if(SettingGet_f(G,cs->Setting,obj->Obj.Setting,cSetting_pickable)) { 

      PRINTFD(G,FB_RepCylBond)
        " RepCylBondNEW: generating pickable version\n"
        ENDFD;
      /* pickable versions are simply capped boxes, 
         vertices: 8 points * 3 = 32  * 2 = 48 floats per bond
      */
       
      vp_size = maxCyl*24;
      I->VP=Alloc(float,vp_size);
      ErrChkPtr(G,I->VP);
       
      rp_size = maxCyl+1;
      I->R.P=Alloc(Pickable,rp_size);
      ErrChkPtr(G,I->R.P);
      rp = I->R.P + 1; /* skip first record! */
      I->R.context.object = (void*)obj;
      I->R.context.state = state;
       
      v=I->VP;
      b=obj->Bond;
      for(a=0;a<obj->NBond;a++)     {
        b1 = b->index[0];
        b2 = b->index[1];
        if(obj->DiscreteFlag) {
          if((cs==obj->DiscreteCSet[b1])&&(cs==obj->DiscreteCSet[b2])) {
            a1=obj->DiscreteAtmToIdx[b1];
            a2=obj->DiscreteAtmToIdx[b2];
          } else {
            a1=-1;
            a2=-1;
          }
        } else {
          a1=cs->AtmToIdx[b1];
          a2=cs->AtmToIdx[b2];
        }
        if((a1>=0)&&(a2>=0))  {
          ai1=obj->AtomInfo+b1;
          ai2=obj->AtomInfo+b2;
          s1=ai1->visRep[cRepCyl];
          s2=ai2->visRep[cRepCyl];
                          
          if(!(s1&&s2)) {
            if(!half_bonds) {
              s1 = 0;
              s2 = 0;
            }
          } 

          if(s1||s2) {  
            float bd_radius;
            float overlap_r,nub_r;
                    
            AtomInfoGetBondSetting_f(G,b,cSetting_stick_radius,radius,&bd_radius);
                    
            overlap_r = overlap * bd_radius;
            nub_r = nub * bd_radius;
                    
            copy3f(cs->Coord+3*a1,v1);
            copy3f(cs->Coord+3*a2,v2);
                                    
            h[0]=(v1[0]+v2[0])/2;
            h[1]=(v1[1]+v2[1])/2;
            h[2]=(v1[2]+v2[2])/2;
                                    
            if(s1&(!ai1->masked)) {
              I->NP++;
              rp->index = b1;
              rp->bond = a;
              rp++;
                             
              v = RepCylinderBox(v,v1,h,bd_radius,overlap_r,nub_r);
            }
            if(s2&(!ai2->masked))  {
              I->NP++;
              rp->index = b2;
              rp->bond = a;
              rp++;
                             
              v = RepCylinderBox(v,h,v2,bd_radius,overlap_r,nub_r);
            }
          }
        }
        b++;
      }
      
      if((signed)vp_size<(v-I->VP))
        ErrFatal(G,"RepCylBond","VP array overrun.");
      if((signed)rp_size<=(I->NP))
        ErrFatal(G,"RepCylBond","RP array overrun.");

      I->R.P = Realloc(I->R.P,Pickable,I->NP+1);
      I->R.P[0].index = I->NP;
      I->VP = ReallocForSure(I->VP,float,(v-I->VP));
      
      PRINTFD(G,FB_RepCylBond)
        " RepCylBondNew: I->NP: %d I->VP: %p\n",I->NP,
        (void*)I->VP
        ENDFD;
    }
  }
  FreeP(other);
  FreeP(marked);
  return((void*)(struct Rep*)I);
}

static void subdivide( int n, float *x, float *y)
{
  int a;
  if(n<3) {n=3;}
  for(a=0;a<=n;a++)
       {
            x[a]=(float)cos(a*2*PI/n);
            y[a]=(float)sin(a*2*PI/n);
       }
}


float *RepCylinderBox(float *v,float *vv1,float *vv2,
                      float tube_size,float overlap,float nub)
{
  
  float d[3],t[3],p0[3],p1[3],p2[3],n[3];
  float v1[3],v2[3];

  tube_size *= 0.7F;

  overlap+=(nub/2);

  /* direction vector */

  subtract3f(vv2,vv1,p0);

  normalize3f(p0);

  v1[0]=vv1[0]-p0[0]*overlap;
  v1[1]=vv1[1]-p0[1]*overlap;
  v1[2]=vv1[2]-p0[2]*overlap;
  
  v2[0]=vv2[0]+p0[0]*overlap;
  v2[1]=vv2[1]+p0[1]*overlap;
  v2[2]=vv2[2]+p0[2]*overlap;
    
  d[0] = (v2[0] - v1[0]);
  d[1] = (v2[1] - v1[1]);
  d[2] = (v2[2] - v1[2]);
  
  /*  t[0] = d[1];
  t[1] = d[2];
  t[2] = -d[0];
  */
  get_divergent3f(d,t);

  cross_product3f(d,t,p1);
  
  normalize3f(p1);
  
  cross_product3f(d,p1,p2);
  
  normalize3f(p2);
  
  /* now we have a coordinate system*/

  n[0] = p1[0]*tube_size*(-1) + p2[0]*tube_size*(-1);
  n[1] = p1[1]*tube_size*(-1) + p2[1]*tube_size*(-1);
  n[2] = p1[2]*tube_size*(-1) + p2[2]*tube_size*(-1);

  v[0] = v1[0] + n[0];
  v[1] = v1[1] + n[1];
  v[2] = v1[2] + n[2];
            
  v[3] = v[0] + d[0];
  v[4] = v[1] + d[1];
  v[5] = v[2] + d[2];

  v+=6;

  n[0] = p1[0]*tube_size*( 1) + p2[0]*tube_size*(-1);
  n[1] = p1[1]*tube_size*( 1) + p2[1]*tube_size*(-1);
  n[2] = p1[2]*tube_size*( 1) + p2[2]*tube_size*(-1);

  v[0] = v1[0] + n[0];
  v[1] = v1[1] + n[1];
  v[2] = v1[2] + n[2];
            
  v[3] = v[0] + d[0];
  v[4] = v[1] + d[1];
  v[5] = v[2] + d[2];

  v+=6;

  n[0] = p1[0]*tube_size*( 1) + p2[0]*tube_size*( 1);
  n[1] = p1[1]*tube_size*( 1) + p2[1]*tube_size*( 1);
  n[2] = p1[2]*tube_size*( 1) + p2[2]*tube_size*( 1);

  v[0] = v1[0] + n[0];
  v[1] = v1[1] + n[1];
  v[2] = v1[2] + n[2];
            
  v[3] = v[0] + d[0];
  v[4] = v[1] + d[1];
  v[5] = v[2] + d[2];

  v+=6;

  n[0] = p1[0]*tube_size*(-1) + p2[0]*tube_size*( 1);
  n[1] = p1[1]*tube_size*(-1) + p2[1]*tube_size*( 1);
  n[2] = p1[2]*tube_size*(-1) + p2[2]*tube_size*( 1);

  v[0] = v1[0] + n[0];
  v[1] = v1[1] + n[1];
  v[2] = v1[2] + n[2];
            
  v[3] = v[0] + d[0];
  v[4] = v[1] + d[1];
  v[5] = v[2] + d[2];

  v+=6;

  return(v);
}


float *RepCylinder(float *v,float *v1,float *v2,int nEdge,
                   int frontCap, int endCap,
                   float tube_size,float overlap,float nub)
{

  float d[3],t[3],p0[3],p1[3],p2[3];
  float x[50],y[50];
  int c;

  if(nEdge>50)
    nEdge=50;
  subdivide(nEdge,x,y);
 
  /* direction vector */
  
  p0[0] = (v2[0] - v1[0]);
  p0[1] = (v2[1] - v1[1]);
  p0[2] = (v2[2] - v1[2]);
  
  normalize3f(p0);
  
  v1[0]-=p0[0]*overlap;
  v1[1]-=p0[1]*overlap;
  v1[2]-=p0[2]*overlap;
  
  if(endCap) {
       v2[0]+=p0[0]*overlap;
       v2[1]+=p0[1]*overlap;
       v2[2]+=p0[2]*overlap;
  }
  
  d[0] = (v2[0] - v1[0]);
  d[1] = (v2[1] - v1[1]);
  d[2] = (v2[2] - v1[2]);
  
  /*  t[0] = d[1];
  t[1] = d[2];
  t[2] = -d[0];*/
  
  get_divergent3f(d,t);

  cross_product3f(d,t,p1);
  
  normalize3f(p1);
  
  cross_product3f(d,p1,p2);
  
  normalize3f(p2);
  
  /* now we have a coordinate system*/
  
  for(c=nEdge;c>=0;c--)
       {
            v[0] = p1[0]*tube_size*x[c] + p2[0]*tube_size*y[c];
            v[1] = p1[1]*tube_size*x[c] + p2[1]*tube_size*y[c];
            v[2] = p1[2]*tube_size*x[c] + p2[2]*tube_size*y[c];
            
            v[3] = v1[0] + v[0];
            v[4] = v1[1] + v[1];
            v[5] = v1[2] + v[2];
            
            v[6] = v[3] + d[0];
            v[7] = v[4] + d[1];
            v[8] = v[5] + d[2];
            
            normalize3f(v);
            v+=9;              
       }
  
  if(frontCap) {

    *(v++)=1.0;
    v[0] = -p0[0];
    v[1] = -p0[1];
    v[2] = -p0[2];
    
    v[3] = v1[0] - p0[0]*nub;
    v[4] = v1[1] - p0[1]*nub;
    v[5] = v1[2] - p0[2]*nub;
    
    v+=6;
    
    for(c=nEdge;c>=0;c--)
      {
        
        v[0] = p1[0]*tube_size*x[c] + p2[0]*tube_size*y[c];
        v[1] = p1[1]*tube_size*x[c] + p2[1]*tube_size*y[c];
        v[2] = p1[2]*tube_size*x[c] + p2[2]*tube_size*y[c];
        
        v[3] = v1[0] + v[0];
        v[4] = v1[1] + v[1];
        v[5] = v1[2] + v[2];
        
        v+=6;
      }
  }
  else 
       {
            *(v++)=0.0F;
       }

  if(endCap) 
       {
            *(v++)=1.0;
            v[0] = p0[0];
            v[1] = p0[1];
            v[2] = p0[2];
            
            v[3] = v2[0] + p0[0]*nub;
            v[4] = v2[1] + p0[1]*nub;
            v[5] = v2[2] + p0[2]*nub;
            
            v+=6;
            
      for(c=0;c<=nEdge;c++)
              {
                   
                   v[0] = p1[0]*tube_size*x[c] + p2[0]*tube_size*y[c];
                   v[1] = p1[1]*tube_size*x[c] + p2[1]*tube_size*y[c];
                   v[2] = p1[2]*tube_size*x[c] + p2[2]*tube_size*y[c];
                   
                   v[3] = v2[0] + v[0];
                   v[4] = v2[1] + v[1];
                   v[5] = v2[2] + v[2];
                   
                   v+=6;
              }
       }
  else 
       {
            *(v++)=0.0F;
       }
  
  return(v);
}




Generated by  Doxygen 1.6.0   Back to index