static int RepSurfaceCGOGenerate()

in layer2/RepSurface.cpp [262:1424]


static int RepSurfaceCGOGenerate(RepSurface * I, RenderInfo * info)
{
  PyMOLGlobals *G = I->R.G;
  float *v = I->V;
  float *vn = I->VN;
  float *vc = I->VC;
  float *va = I->VA;
  int *t = I->T;
  int *s = I->S;
  int c = I->N;
  int *vi = I->Vis;
  int *at = I->AT;
  int ok = true;
  float alpha;
  int t_mode;
  CGO *convertcgo = NULL;
  bool pick_surface = SettingGet_b(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_pick_surface);
  short dot_as_spheres = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_as_spheres);
  alpha = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_transparency);
  alpha = 1.0F - alpha;
  if(fabs(alpha - 1.0) < R_SMALL4)
    alpha = 1.0F;

  setShaderCGO(I, CGONew(G));

  if (!I->shaderCGO)
    return false;

  I->shaderCGO->use_shader = true;
  I->dot_as_spheres = dot_as_spheres;

  if (I->Type == 1) {
    /* no triangle information, so we're rendering dots only */
    int normals =
      SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_normals);
    if(!normals){
      CGOResetNormal(I->shaderCGO, true);
    }
      if((alpha != 1.0)) {
	CGOAlpha(I->shaderCGO, alpha);
      }
      if (dot_as_spheres){
	if(c) {
	  ok &= CGOColor(I->shaderCGO, 1.0, 0.0, 0.0);
	  if(ok && I->oneColorFlag) {
	    ok &= CGOColorv(I->shaderCGO, ColorGet(G, I->oneColor));
	  }
	  while(ok && c--) {
	    if(*vi) {
	      if(!I->oneColorFlag) {
		ok &= CGOColorv(I->shaderCGO, vc);
	      }
	      if(ok && normals)
		ok &= CGONormalv(I->shaderCGO, vn);
	      if (ok && pick_surface)
		ok &= CGOPickColor(I->shaderCGO, *at, AtomInfoIsMasked((ObjectMolecule*)I->R.obj, *at));

	      if (ok)
		ok &= CGOSphere(I->shaderCGO, v, 1.f);
	    }
	    vi++;
	    vc += 3;
	    vn += 3;
	    v += 3;
	    at++;
	  }
	}
      } else {
	ok &= CGODotwidth(I->shaderCGO, SettingGet_f
			  (G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_width));
	if(ok && c) {
	  ok &= CGOColor(I->shaderCGO, 1.0, 0.0, 0.0);
	  ok &= CGOBegin(I->shaderCGO, GL_POINTS);
	  if(ok && I->oneColorFlag) {
	    ok &= CGOColorv(I->shaderCGO, ColorGet(G, I->oneColor));
	  }
	      
	  while(ok && c--) {
	    if(*vi) {
	      if(!I->oneColorFlag) {
		ok &= CGOColorv(I->shaderCGO, vc);
	      }
	      if(normals){
		CGONormalv(I->shaderCGO, vn);
	      }
	      if (ok && pick_surface)
		ok &= CGOPickColor(I->shaderCGO, *at, AtomInfoIsMasked((ObjectMolecule*)I->R.obj, *at));
	      if (ok)
		ok &= CGOVertexv(I->shaderCGO, v);
	    }
	    vi++;
	    vc += 3;
	    vn += 3;
	    v += 3;
	    at++;
	  }
	  if (ok)
	    ok &= CGOEnd(I->shaderCGO);
	}
      }
      } else if(I->Type == 2) { /* rendering triangle mesh */
        int normals =
          SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_normals);
        if(ok && !normals){
	    ok &= CGOResetNormal(I->shaderCGO, true);
	}
	if (ok) {
          float line_width =
            SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_width);
          line_width = SceneGetDynamicLineWidth(info, line_width);

	ok &= CGOSpecial(I->shaderCGO, LINEWIDTH_DYNAMIC_MESH);

          c = I->NT;
          if(ok && c) {
            if(I->oneColorFlag) {
		  ok &= CGOColorv(I->shaderCGO, ColorGet(G, I->oneColor));
		  while(ok && c--) {
              if (visibility_test(I->proximity, vi, t)) {
		      if(normals) {
			int idx;
			ok &= CGOBegin(I->shaderCGO, GL_LINE_STRIP);
			idx = (*(t + 2));
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);

			idx = (*t);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = (*t);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = (*t);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			if (ok)
			  ok &= CGOEnd(I->shaderCGO);
		      } else {
			int idx;
			ok &= CGOBegin(I->shaderCGO, GL_LINE_STRIP);

			idx = (*(t + 2));
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			idx = *t;
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = *t;
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = *t;
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			if (ok)
			  ok &= CGOEnd(I->shaderCGO);
		      }
                } else
                  t += 3;
              }
            } else { /* not oneColorFlag */
		  while(ok && c--) {
              if (visibility_test(I->proximity, vi, t)) {
		      if(normals) {
			int idx;
			ok &= CGOBegin(I->shaderCGO, GL_LINE_STRIP);
			
			idx = (*(t + 2));
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			
			idx = (*t);
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = (*t);
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = (*t);
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
			if (ok)
			  ok &= CGONormalv(I->shaderCGO, vn + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			if (ok)
			  ok &= CGOEnd(I->shaderCGO);
		      } else {
			int idx;
			ok &= CGOBegin(I->shaderCGO, GL_LINE_STRIP);

			idx = (*(t + 2));
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);

			idx = (*t);
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = (*t);
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			idx = (*t);
			if (ok)
			  ok &= CGOColorv(I->shaderCGO, vc + idx * 3);
		  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
			if (ok)
			  ok &= CGOVertexv(I->shaderCGO, v + idx * 3);
			t++;
			if (ok)
			  ok &= CGOEnd(I->shaderCGO);
		      }
		    } else
		      t += 3;
	    }
          }
      }
    }
      } else {
        /* we're rendering triangles */

        if((alpha != 1.0) || va) {

          t_mode =
            SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
                         cSetting_transparency_mode);

          if(info && info->alpha_cgo) {
            t_mode = 0;
          }

          if(t_mode) {

            float **t_buf = NULL, **tb;
            float *z_value = NULL, *zv;
            int *ix = NULL;
	int n_tri = 0;
            float sum[3];
            float matrix[16];

            glGetFloatv(GL_MODELVIEW_MATRIX, matrix);

            if(I->oneColorFlag) {
              t_buf = Alloc(float *, I->NT * 6);
            } else {
              t_buf = Alloc(float *, I->NT * 12);
            }
	    CHECKOK(ok, t_buf);
	    if (ok){
	      z_value = Alloc(float, I->NT);
	      CHECKOK(ok, z_value);
	    }
	    if (ok){
	      ix = Alloc(int, I->NT);
	      CHECKOK(ok, ix);
	    }
            zv = z_value;
            tb = t_buf;
            c = I->NT;
	    if (ok){
	      if(I->oneColorFlag) {
		while(c--) {
              if (visibility_test(I->proximity, vi, t)) {
		    *(tb++) = vn + (*t) * 3;
		    *(tb++) = v + (*t) * 3;
		    *(tb++) = vn + (*(t + 1)) * 3;
		    *(tb++) = v + (*(t + 1)) * 3;
		    *(tb++) = vn + (*(t + 2)) * 3;
		    *(tb++) = v + (*(t + 2)) * 3;
		    
		    add3f(tb[-1], tb[-3], sum);
		    add3f(sum, tb[-5], sum);
		    
		    *(zv++) = matrix[2] * sum[0] + matrix[6] * sum[1] + matrix[10] * sum[2];
		    n_tri++;
		  }
		  t += 3;
		}
	      } else {
		while(c--) {
              if (visibility_test(I->proximity, vi, t)) {
		      
		      if(va)
			*(tb++) = va + (*t);
		      else
			*(tb++) = &alpha;
		      *(tb++) = vc + (*t) * 3;
		      *(tb++) = vn + (*t) * 3;
		      *(tb++) = v + (*t) * 3;
		      
		      if(va)
			*(tb++) = va + (*(t + 1));
		      else
			*(tb++) = &alpha;
		      *(tb++) = vc + (*(t + 1)) * 3;
		      *(tb++) = vn + (*(t + 1)) * 3;
		      *(tb++) = v + (*(t + 1)) * 3;
		      
		      if(va)
			*(tb++) = va + (*(t + 2));
		      else
			*(tb++) = &alpha;
		      *(tb++) = vc + (*(t + 2)) * 3;
		      *(tb++) = vn + (*(t + 2)) * 3;
		      *(tb++) = v + (*(t + 2)) * 3;
		      
		      add3f(tb[-1], tb[-5], sum);
		      add3f(sum, tb[-9], sum);
		      *(zv++) =
			matrix[2] * sum[0] + matrix[6] * sum[1] + matrix[10] * sum[2];
		      n_tri++;
		    }
		  t += 3;
		}
	      }
	    }
            switch (t_mode) {
            case 1:
              ok &= UtilSemiSortFloatIndex(n_tri, z_value, ix, true);
              /* UtilSortIndex(n_tri,z_value,ix,(UtilOrderFn*)ZOrderFn); */
              break;
            default:
              ok &= UtilSemiSortFloatIndex(n_tri, z_value, ix, false);
              /* UtilSortIndex(n_tri,z_value,ix,(UtilOrderFn*)ZRevOrderFn); */
              break;
            }
            c = n_tri;
            if(I->oneColorFlag) {
              float col[3];
              ColorGetEncoded(G, I->oneColor, col);
	      if (ok){
		  CGOAlpha(I->shaderCGO, alpha);
		  if (ok)
		    ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
		  if (ok)
		    ok &= CGOBegin(I->shaderCGO, GL_TRIANGLES);
		  for(c = 0; ok && c < n_tri; c++) {
		    int idx;
		    tb = t_buf + 6 * c;
		    //		    tb = t_buf + 6 * ix[c];
		  if (ok)
		    ok &= CGONormalv(I->shaderCGO, *(tb++));
		  idx = ((*tb - v)/3);
		if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
		    if (ok && I->VAO){
		      ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + idx));
		    }
		    if (ok)
		      ok &= CGOVertexv(I->shaderCGO, *(tb++));
		    if (ok)
		      ok &= CGONormalv(I->shaderCGO, *(tb++));
		    idx = ((*tb - v)/3);
		if (ok && pick_surface)
		      ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
		    if (ok && I->VAO){
		      ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + idx));
		    }
		    if (ok)
		      ok &= CGOVertexv(I->shaderCGO, *(tb++));
		    if (ok)
		      ok &= CGONormalv(I->shaderCGO, *(tb++));
		    idx = ((*tb - v)/3);
		if (ok && pick_surface)
		      ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
		    if (ok && I->VAO){
		    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + idx));
		    }
		    if (ok)
		      ok &= CGOVertexv(I->shaderCGO, *(tb++));
		  }
		  if (ok)
		    ok &= CGOEnd(I->shaderCGO);
	      }
            } else { /* else I->oneColorFlag */
		  if (ok)
		    ok &= CGOBegin(I->shaderCGO, GL_TRIANGLES);
		  for(c = 0; ok && c < n_tri; c++) {
		    float *vv, *v_alpha;
		    int idx;
		    tb = t_buf + 12 * c; /* need to update index every frame */
		    //		    tb = t_buf + 12 * ix[c];
		    v_alpha = *(tb++);
		    vv = *(tb++);
		    ok &= CGOAlpha(I->shaderCGO, *v_alpha);
		    if (ok) ok &= CGOColor(I->shaderCGO, vv[0], vv[1], vv[2]);
		    if (ok) ok &= CGONormalv(I->shaderCGO, *(tb++));
		    idx = ((*tb - v)/3);
	      if (ok && pick_surface)
		      ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
		    if (ok && I->VAO){
		      ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + idx));
		    }
		    if (ok) ok &= CGOVertexv(I->shaderCGO, *(tb++));
		    
		    v_alpha = *(tb++);
		    vv = *(tb++);
		    if (ok) ok &= CGOAlpha(I->shaderCGO, *v_alpha);
		    if (ok) ok &= CGOColor(I->shaderCGO, vv[0], vv[1], vv[2]);
		    if (ok) ok &= CGONormalv(I->shaderCGO, *(tb++));
		    idx = ((*tb - v)/3);
	      if (ok && pick_surface)
		      ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
		    if (ok && I->VAO){
		      ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + idx));
		    }
		    if (ok) ok &= CGOVertexv(I->shaderCGO, *(tb++));
		    
		    v_alpha = *(tb++);
		    vv = *(tb++);
		    if (ok) ok &= CGOAlpha(I->shaderCGO, *v_alpha);
		    if (ok) ok &= CGOColor(I->shaderCGO, vv[0], vv[1], vv[2]);
		    if (ok) ok &= CGONormalv(I->shaderCGO, *(tb++));
		    idx = ((*tb - v)/3);
	      if (ok && pick_surface)
		      ok &= CGOPickColor(I->shaderCGO, I->AT[idx], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[idx]));
		    if (ok && I->VAO){
		      ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + idx));
		    }
		    if (ok) ok &= CGOVertexv(I->shaderCGO, *(tb++));
		  }
		  if (ok) ok &= CGOEnd(I->shaderCGO);
		}
	      FreeP(ix);
	      FreeP(z_value);
	      FreeP(t_buf);
          } else if (ok) {
            if(info->alpha_cgo) {       /* global transparency sort */
              if(I->allVisibleFlag) {
                if(I->oneColorFlag) {
                  float col[3];
                  ColorGetEncoded(G, I->oneColor, col);

                  c = *(s++);
                  while(c) {
                    int parity = 0;
                    s += 2;
                    while(ok && c--) {
                      ok &= CGOAlphaTriangle(info->alpha_cgo,
					     v + s[-2] * 3, v + s[-1] * 3, v + (*s) * 3,
					     vn + s[-2] * 3, vn + s[-1] * 3, vn + (*s) * 3,
					     col, col, col, alpha, alpha, alpha, parity);
                      s++;
                      parity = !parity;
                    }
                    c = *(s++);
                  }
                } else {
                  c = *(s++);
                  while(ok && c) {
                    float *col0, *col1, *col2;
                    int parity = 0;
                    float alpha0, alpha1, alpha2;
                    col0 = vc + (*s) * 3;
                    if(va) {
                      alpha0 = va[(*s)];
                    } else {
                      alpha0 = alpha;
                    }
                    s++;
                    col1 = vc + (*s) * 3;
                    if(va) {
                      alpha1 = va[(*s)];
                    } else {
                      alpha1 = alpha;
                    }
                    s++;
                    while(ok && c--) {
                      col2 = vc + (*s) * 3;
                      if(va) {
                        alpha2 = va[(*s)];
                      } else {
                        alpha2 = alpha;
                      }
                      ok &= CGOAlphaTriangle(info->alpha_cgo,
					     v + s[-2] * 3, v + s[-1] * 3, v + (*s) * 3,
					     vn + s[-2] * 3, vn + s[-1] * 3, vn + (*s) * 3,
					     col0, col1, col2, alpha0, alpha1, alpha2, parity);
                      alpha0 = alpha1;
                      alpha1 = alpha2;
                      col0 = col1;
                      col1 = col2;
                      s++;
                      parity = !parity;
                    }
                    c = *(s++);
                  }
                }
              } else if (ok){          /* subset s */
                c = I->NT;
                if(c) {
                  if(I->oneColorFlag) {
                    float color[3];
                    ColorGetEncoded(G, I->oneColor, color);
                    while(ok && c--) {
                  if (visibility_test(I->proximity, vi, t)) {

                        ok &= CGOAlphaTriangle(info->alpha_cgo,
					       v + t[0] * 3, v + t[1] * 3, v + t[2] * 3,
					       vn + t[0] * 3, vn + t[1] * 3, vn + t[2] * 3,
					       color, color, color, alpha, alpha, alpha, 0);
                      }
                      t += 3;
                    }
                  } else {
                    while(ok && c--) {
                  if (visibility_test(I->proximity, vi, t)) {

                        if(va) {
                          ok &= CGOAlphaTriangle(info->alpha_cgo,
						 v + t[0] * 3, v + t[1] * 3, v + t[2] * 3,
						 vn + t[0] * 3, vn + t[1] * 3, vn + t[2] * 3,
						 vc + t[0] * 3, vc + t[1] * 3, vc + t[2] * 3,
						 va[t[0]], va[t[1]], va[t[2]], 0);
                        } else {
                          ok &= CGOAlphaTriangle(info->alpha_cgo,
						 v + t[0] * 3, v + t[1] * 3, v + t[2] * 3,
						 vn + t[0] * 3, vn + t[1] * 3, vn + t[2] * 3,
						 vc + t[0] * 3, vc + t[1] * 3, vc + t[2] * 3,
						 alpha, alpha, alpha, 0);
                        }
                      }
                      t += 3;
                    }
                  }
		  if (ok)
		    CGOEnd(info->alpha_cgo);
                }
              }
            } else if (ok){

              /* fast and ugly */
              /*          glCullFace(GL_BACK);
                 glEnable(GL_CULL_FACE);
                 glDepthMask(GL_FALSE); */
              if(I->allVisibleFlag) {
                if(I->oneColorFlag) {
                  float col[3];
                  ColorGetEncoded(G, I->oneColor, col);

		      if (ok) ok &= CGOAlpha(I->shaderCGO, alpha);
		      if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
		      c = *(s++);
		      while(ok && c) {
			if (ok) ok &= CGOBegin(I->shaderCGO, GL_TRIANGLE_STRIP);
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
                  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
                  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			while(ok && c--) {
			  ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			  }
                    if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			  s++;
			}
			if (ok) ok &= CGOEnd(I->shaderCGO);
			c = *(s++);
		      }
		} else { /* I->oneColorFlag */
		      c = *(s++);
		      while(ok && c) {
			float *col;
			if (ok) ok &= CGOBegin(I->shaderCGO, GL_TRIANGLE_STRIP);
			col = vc + (*s) * 3;
			if(va) {
			  if (ok) ok &= CGOAlpha(I->shaderCGO, va[(*s)]);
			  if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
			} else {
			  if (ok) ok &= CGOAlpha(I->shaderCGO, alpha);
			  if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
			}
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
                  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			col = vc + (*s) * 3;
			if(va) {
			  if (ok) ok &= CGOAlpha(I->shaderCGO, va[(*s)]);
			  if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
			} else {
			  if (ok) ok &= CGOAlpha(I->shaderCGO, alpha);
			  if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
			}
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
                  if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			while(ok && c--) {
			  col = vc + (*s) * 3;
			  if(va) {
			    ok &= CGOAlpha(I->shaderCGO, va[(*s)]);
			    if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
			  } else {
			    ok &= CGOAlpha(I->shaderCGO, alpha);
			    if (ok) ok &= CGOColor(I->shaderCGO, col[0], col[1], col[2]);
			  }
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			  }
                    if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			  s++;
			}
			if (ok) ok &= CGOEnd(I->shaderCGO);
			c = *(s++);
		      }
		  }
              } else {          /* subset s */
		    c = I->NT;
		    if(ok && c) {
		      if (ok) ok &= CGOBegin(I->shaderCGO, GL_TRIANGLES);
		      if(I->oneColorFlag) {
			float color[3];
			ColorGetEncoded(G, I->oneColor, color);
			if (ok) ok &= CGOAlpha(I->shaderCGO, alpha);
			if (ok) ok &= CGOColor(I->shaderCGO, color[0], color[1], color[2]);
			while(ok && c--) {
                    if (visibility_test(I->proximity, vi, t))
			    {
			      CGONormalv(I->shaderCGO, vn + (*t) * 3);
			      if (ok && I->VAO){
				ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			      }
                      if (ok && pick_surface)
				ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			      if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			      t++;
			      if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			      if (ok && I->VAO){
				ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			      }
                      if (ok && pick_surface)
				ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			      if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			      t++;
			      if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			      if (ok && I->VAO){
				ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			      }
                      if (ok && pick_surface)
				ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			      if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			      t++;
			    } else
			    t += 3;
			}
		      } else {
			float *col;
			while(ok && c--) {
                    if (visibility_test(I->proximity, vi, t))
			    {
			      
			      col = vc + (*t) * 3;
			      if(va) {
				ok &= CGOAlpha(I->shaderCGO, va[(*t)]);
			      } else {
				ok &= CGOAlpha(I->shaderCGO, alpha);
			      }
			      if (ok) ok &= CGOColorv(I->shaderCGO, col);
			      if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			      if (ok && I->VAO){
				ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			      }
                      if (ok && pick_surface)
				ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			      if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			      t++;
			      col = vc + (*t) * 3;
			      if(va) {
				if (ok) ok &= CGOAlpha(I->shaderCGO, va[(*t)]);
			      } else {
				if (ok) ok &= CGOAlpha(I->shaderCGO, alpha);
			      }
			      if (ok) ok &= CGOColorv(I->shaderCGO, col);
			      if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			      if (ok && I->VAO){
				ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			      }
                      if (ok && pick_surface)
				ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			      if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			      t++;
			      col = vc + (*t) * 3;
			      if(va) {
				if (ok) ok &= CGOAlpha(I->shaderCGO, va[(*t)]);
			      } else {
				if (ok) ok &= CGOAlpha(I->shaderCGO, alpha);
			      }
			      if (ok) ok &= CGOColorv(I->shaderCGO, col);
			      if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			      if (ok && I->VAO){
				ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			      }
                      if (ok && pick_surface)
				ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			      if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			      t++;
			    } else
			    t += 3;
			}
		      }
		      if (ok) ok &= CGOEnd(I->shaderCGO);
		    }
                }
            }
            /*          glDisable(GL_CULL_FACE);
               glDepthMask(GL_TRUE); */
          }
        } else if (ok) {                /* opaque */
            if(I->allVisibleFlag) {
              if(I->oneColorFlag) {
                if (ok) {
		      CGOColorv(I->shaderCGO, ColorGet(G, I->oneColor));
		      c = *(s++);
		      while(ok && c) {
			if (ok) ok &= CGOBegin(I->shaderCGO, GL_TRIANGLE_STRIP);
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
                if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
                if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			while(ok && c--) {
			  ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			  }
                  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			  s++;
			}
			if (ok) ok &= CGOEnd(I->shaderCGO);
			c = *(s++);
		      }
		  }
	      } else {          /* not one color */
                    {
		      c = *(s++);
		      while(ok && c) {
			ok &= CGOBegin(I->shaderCGO, GL_TRIANGLE_STRIP);
			if (ok) ok &= CGOColorv(I->shaderCGO, vc + (*s) * 3);
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
                if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			if (ok) ok &= CGOColorv(I->shaderCGO, vc + (*s) * 3);
			if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			if (ok && I->VAO){
			  ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			}
                if (ok && pick_surface)
			  ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			s++;
			while(ok && c--) {
			  ok &= CGOColorv(I->shaderCGO, vc + (*s) * 3);
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*s) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *s));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*s], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*s]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*s) * 3);
			  s++;
			}
			if (ok) ok &= CGOEnd(I->shaderCGO );
			c = *(s++);
		      }
		    }
              }                 /* one color */
            } else if (ok) {            /* subsets */
		  c = I->NT;
		  if(ok && c) {
		    ok &= CGOBegin(I->shaderCGO, GL_TRIANGLES);
		    if(I->oneColorFlag) {
		      if (ok) ok &= CGOColorv(I->shaderCGO, ColorGet(G, I->oneColor));
		      while(ok && c--) {
                if (visibility_test(I->proximity, vi, t)) {
			  ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			  t++;
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			  t++;
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			  t++;
			} else
			  t += 3;
		      }
		    } else {
		      while(ok && c--) {
                if (visibility_test(I->proximity, vi, t)) {
			  ok &= CGOColorv(I->shaderCGO, vc + (*t) * 3);
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			  t++;
			  if (ok) ok &= CGOColorv(I->shaderCGO, vc + (*t) * 3);
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			  t++;
			  if (ok) ok &= CGOColorv(I->shaderCGO, vc + (*t) * 3);
			  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
			  if (ok && I->VAO){
			    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
			  }
		  if (ok && pick_surface)
			    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
			  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
			  t++;
			} else
			  t += 3;
		      }
		    }
		    if (ok) ok &= CGOEnd(I->shaderCGO);
		  }
            }
	  /*          if (use_shader) {
	    CShaderPrg_Disable(shaderPrg);
	    }*/
        }
      }
      if(ok && SettingGetGlobal_i(G, cSetting_surface_debug)) {
        t = I->T;
        c = I->NT;
	    if(c) {
	      ok &= CGOBegin(I->shaderCGO, GL_TRIANGLES);
	      while(ok && c--) {
		if(I->allVisibleFlag
              || visibility_test(I->proximity, vi, t)) {
		  ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
		  if (ok && I->VAO){
		    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
		  }
	    if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
		  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
		  t++;
		  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
		  if (ok && I->VAO){
		    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
		  }
	    if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
		  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
		  t++;
		  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
		  if (ok && I->VAO){
		    ok &= CGOAccessibility(I->shaderCGO, *(I->VAO + *t));
		  }
	    if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
		  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
		  t++;
		} else {
		  t += 3;
		}
	      }
	      if (ok) ok &= CGOEnd(I->shaderCGO);
	    }
        t = I->T;
        c = I->NT;

	    if(ok && c) {
	      ok &= CGOColor(I->shaderCGO, 0.0, 1.0, 0.0);
	      if (ok) ok &= CGODotwidth(I->shaderCGO, 1.0F);
	      while(ok && c--) {
		ok &= CGOBegin(I->shaderCGO, GL_LINE_STRIP);
		if(I->allVisibleFlag
              || visibility_test(I->proximity, vi, t)) {
		  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
	    if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
		  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
		  t++;
		  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
	    if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
		  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
		  t++;
		  if (ok) ok &= CGONormalv(I->shaderCGO, vn + (*t) * 3);
	    if (ok && pick_surface)
		    ok &= CGOPickColor(I->shaderCGO, I->AT[*t], AtomInfoIsMasked((ObjectMolecule*)I->R.obj, I->AT[*t]));
		  if (ok) ok &= CGOVertexv(I->shaderCGO, v + (*t) * 3);
		  t++;
		} else {
		  t += 3;
		}
		if (ok) ok &= CGOEnd(I->shaderCGO);
	      }
	    }

    c = I->N;
      if(ok && c) {
	ok &= CGOColor(I->shaderCGO, 1.0, 0.0, 0.0);
	if (ok) ok &= CGOResetNormal(I->shaderCGO, true);
	if (ok) ok &= CGOBegin(I->shaderCGO, GL_LINES);
	while(ok && c--) {
	  ok &= CGOVertexv(I->shaderCGO, v);
	  if (ok) ok &= CGOVertex(I->shaderCGO, v[0] + vn[0] / 2, v[1] + vn[1] / 2, v[2] + vn[2] / 2);
	  v += 3;
	  vn += 3;
	}
	if (ok) ok &= CGOEnd(I->shaderCGO);
      }
  }


  
  if (ok) ok &= CGOStop(I->shaderCGO);
  if (I->Type != 2){
    CGOCombineBeginEnd(&I->shaderCGO);
    if (I->Type == 1){
      /* Only needed to simplify spheres in surface_type=1 */
      CGO *simple = CGOSimplify(I->shaderCGO, 0);
      CGOCombineBeginEnd(&simple, 0);
      CHECKOK(ok, simple);
      setPickingCGO(I, simple);
    } else {
      setPickingCGO(I, I->shaderCGO);
    }
  }
  if(I->Type == 1){
    if (dot_as_spheres) {
      CGO *tmpCGO = CGONew(G);
      CHECKOK(ok, tmpCGO);
      ok &= CGOEnable(tmpCGO, GL_SPHERE_SHADER);
      ok &= CGOEnable(tmpCGO, GL_DOT_LIGHTING);  // TODO: this needs normals in sphere shader PYMOL-1870
      ok &= CGOSpecial(tmpCGO, DOTSIZE_WITH_SPHERESCALE);
      convertcgo = CGOOptimizeSpheresToVBONonIndexedNoShader(I->shaderCGO,
          CGO_BOUNDING_BOX_SZ + fsizeof<cgo::draw::sphere_buffers>() + 2);
      ok &= CGOAppendNoStop(tmpCGO, convertcgo); 
      CGOFreeWithoutVBOs(convertcgo);
      ok &= CGODisable(tmpCGO, GL_SPHERE_SHADER);
      CGOStop(tmpCGO);
      convertcgo = tmpCGO;
    } else {
      convertcgo = CGOOptimizeToVBONotIndexedNoShader(I->shaderCGO, 0);
    }
    CHECKOK(ok, convertcgo);
    if (ok)
      convertcgo->use_shader = true;
  } else if (I->Type == 2) {
    CGO *convertcgo2, *simple = NULL;

    CGO *tmpCGO = CGONew(G);
    CHECKOK(ok, tmpCGO);
    convertcgo2 = CGOConvertLinesToShaderCylinders(I->shaderCGO, 0);
    CHECKOK(ok, convertcgo2);
    CGOEnable(tmpCGO, GL_CYLINDER_SHADER);
    CGOSpecial(tmpCGO, MESH_WIDTH_FOR_SURFACES);
    convertcgo = CGOConvertShaderCylindersToCylinderShader(convertcgo2, tmpCGO);
    CGOAppendNoStop(tmpCGO, convertcgo);
    CGOFreeWithoutVBOs(convertcgo);
    CGODisable(tmpCGO, GL_CYLINDER_SHADER);
    CGOStop(tmpCGO);
    convertcgo = tmpCGO;
    convertcgo->use_shader = true;

    if (ok)
      simple = CGOSimplify(convertcgo2, 0);
    CHECKOK(ok, simple);
    if (ok)
      setPickingCGO(I, CGOCombineBeginEnd(simple, 0));
    CHECKOK(ok, I->pickingCGO);
    CGOFree(simple);
    CGOFree(convertcgo2);
  } else {
    if((alpha != 1.0) || va) { // semi-transparent
      if (ok)
	convertcgo = CGOOptimizeToVBOIndexedWithColorEmbedTransparentInfo(I->shaderCGO, 0, 0, 0);
      CHECKOK(ok, convertcgo);
#ifdef _PYMOL_IOS
#endif
    } else {
      if (ok)
	convertcgo = CGOOptimizeToVBONotIndexedWithReturnedData(I->shaderCGO, 0, false, NULL);
      CHECKOK(ok, convertcgo);
    }
    if (ok)
      convertcgo->use_shader = true;
    {
      CGO *tmpCGO = NULL;
      tmpCGO = CGONew(G);
      CGOEnable(tmpCGO, GL_SURFACE_SHADER);
      //CGOEnable(tmpCGO, CGO_GL_LIGHTING); // do we need this?
      CGOSpecial(tmpCGO, SET_SURFACE_UNIFORMS);
      CGOAppendNoStop(tmpCGO, convertcgo);
      CGODisable(tmpCGO, GL_SURFACE_SHADER);
      CGOStop(tmpCGO);
      CGOFreeWithoutVBOs(convertcgo);
      convertcgo = tmpCGO;
      convertcgo->use_shader = true;
    }

  }

  if(ok && I->Type == 1 && !dot_as_spheres) {
    setShaderCGO(I, CGONew(G));
    CHECKOK(ok, I->shaderCGO);
    if (ok){
      I->shaderCGO->use_shader = true;
      if (ok) ok &= CGOResetNormal(I->shaderCGO, true);
      if (ok) ok &= CGOEnable(I->shaderCGO, GL_SURFACE_SHADER);
      if (ok) ok &= CGOSpecial(I->shaderCGO, POINTSIZE_DYNAMIC_DOT_WIDTH);
      if (ok) CGOAppendNoStop(I->shaderCGO, convertcgo);
      if (ok) ok &= CGODisable(I->shaderCGO, GL_SURFACE_SHADER);
      if (ok) ok &= CGOStop(I->shaderCGO);
      CGOFreeWithoutVBOs(convertcgo);
      convertcgo = NULL;
    }
  } else {
    setShaderCGO(I, convertcgo);
    convertcgo = NULL;
  }
  {
    CGO *simple = NULL;
    if (ok)
      simple = CGOOptimizeToVBONotIndexed(I->pickingCGO, 0);
    CHECKOK(ok, simple);
    if (ok){
      CGOChangeShadersTo(simple, GL_DEFAULT_SHADER, GL_SURFACE_SHADER);
    }
    if (ok){
      setPickingCGO(I, simple);
      I->pickingCGO->use_shader = true;
      I->pickingCGO->no_pick = !pick_surface;
    }
  }

  return ok;
}