static void RepSurfaceRender()

in layer2/RepSurface.cpp [1426:2139]


static void RepSurfaceRender(RepSurface * I, RenderInfo * info)
{
  CRay *ray = info->ray;
  auto pick = info->pick;
  PyMOLGlobals *G = I->R.G;
  float *v = I->V;
  float *vn = I->VN;
  float *vc = I->VC;
  float *va = I->VA;
  int *rc = I->RC;
  int *t = I->T;
  int *s = I->S;
  int c = I->N;
  int *vi = I->Vis;
  int ok = true;
  float alpha;
  int t_mode;
  float ambient_occlusion_scale = 0.f;
  int ambient_occlusion_mode = SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_ambient_occlusion_mode);
  int ambient_occlusion_mode_div_4 = 0;
  if (ambient_occlusion_mode){
    ambient_occlusion_scale = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_ambient_occlusion_scale);
    ambient_occlusion_mode_div_4 = ambient_occlusion_mode / 4;
  }

  if((I->Type != 1) && (!s)) {
    return;
  }

  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;
  if(ray) {
#ifndef _PYMOL_NO_RAY
    ray->transparentf(1.0F - alpha);
    if(I->Type == 1) {
      /* dot surface */
      float radius;
      radius = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_radius);
      if(radius == 0.0F) {
        radius = ray->PixelRadius * SettingGet_f(G, I->R.cs->Setting,
                                                 I->R.obj->Setting,
                                                 cSetting_dot_width) / 1.4142F;
      }

      if(I->oneColorFlag) {
        float col[3];
        ColorGetEncoded(G, I->oneColor, col);
        ray->color3fv(col);
      }

      if(c)
        while(ok && c--) {
          if(*vi) {
            if(!I->oneColorFlag) {
              ray->color3fv(vc);
            }
            ok &= ray->sphere3fv(v, radius);
          }
          vi++;
          vc += 3;
          v += 3;
        }
    } else if((I->Type == 0) || (I->Type == 3) || (I->Type == 4) || (I->Type == 5)) {   /* solid surface */
      c = I->NT;

      if(I->oneColorFlag) {
        float col[3], col1[3], col2[3], col3[3];
        ColorGetEncoded(G, I->oneColor, col);
        while(ok && c--) {
          if (visibility_test(I->proximity, vi, t)) {
	    copy3f(col, col1);
	    copy3f(col, col2);
	    copy3f(col, col3);
	    if (I->VAO){
	      float ao1, ao2, ao3;
	      switch (ambient_occlusion_mode_div_4){
	      case 1:
		ao1 = 1.f-ambient_occlusion_scale*(*(I->VAO + *t));
		ao2 = 1.f-ambient_occlusion_scale*(*(I->VAO + *(t+1)));
		ao3 = 1.f-ambient_occlusion_scale*(*(I->VAO + *(t+2)));
		break;
	      case 2:
		ao1 = cos(.5f * PI * CLAMP_VALUE(ambient_occlusion_scale*(*(I->VAO + *t))));
		ao2 = cos(.5f * PI * CLAMP_VALUE(ambient_occlusion_scale*(*(I->VAO + *(t+1)))));
		ao3 = cos(.5f * PI * CLAMP_VALUE(ambient_occlusion_scale*(*(I->VAO + *(t+2)))));
		break;
	      default:
		ao1 = CLAMP_VALUE(1.f / (1.f + exp(.5f*((ambient_occlusion_scale*(*(I->VAO + *t))) - 10.f))));
		ao2 = CLAMP_VALUE(1.f / (1.f + exp(.5f*((ambient_occlusion_scale*(*(I->VAO + *(t+1)))) - 10.f))));
		ao3 = CLAMP_VALUE(1.f / (1.f + exp(.5f*((ambient_occlusion_scale*(*(I->VAO + *(t+2)))) - 10.f))));
	      }
	      mult3f(col1, ao1, col1);
	      mult3f(col2, ao2, col2);
	      mult3f(col3, ao3, col3);
	    }
	    ok &= ray->triangle3fv(v + (*t) * 3, v + (*(t + 1)) * 3, v + (*(t + 2)) * 3,
				    vn + (*t) * 3, vn + (*(t + 1)) * 3, vn + (*(t + 2)) * 3,
				    col1, col2, col3);
	  }
          t += 3;
        }
      } else {
        while(ok && c--) {
          int ttA = *t, ttB = *(t + 1), ttC = *(t + 2);
          if (visibility_test(I->proximity, vi, t)) {
            int ttA3 = ttA * 3, ttB3 = ttB * 3, ttC3 = ttC * 3;
            float cA[3], cB[3], cC[3];
	    copy3f(vc + ttA3, cA);
	    copy3f(vc + ttB3, cB);
	    copy3f(vc + ttC3, cC);
	    //            register float *cA = vc + ttA3, *cB = vc + ttB3, *cC = vc + ttC3;
            if(rc) {
              if(rc[ttA] < -1)
                ColorGetEncoded(G, rc[ttA], cA);
	      //                ColorGetEncoded(G, rc[ttA], (cA = colA));
              if(rc[ttB] < -1)
                ColorGetEncoded(G, rc[ttB], cB);
	      //                ColorGetEncoded(G, rc[ttB], (cB = colB));
              if(rc[ttC] < -1)
                ColorGetEncoded(G, rc[ttC], cC);
	      //                ColorGetEncoded(G, rc[ttC], (cC = colC));
            }
            if((*(vi + ttA)) || (*(vi + ttB)) || (*(vi + ttC))) {
	      if (I->VAO){
		float ao1, ao2, ao3;
		switch (ambient_occlusion_mode_div_4){
		case 1:
		  ao1 = 1.f-ambient_occlusion_scale*(*(I->VAO + *t));
		  ao2 = 1.f-ambient_occlusion_scale*(*(I->VAO + *(t+1)));
		  ao3 = 1.f-ambient_occlusion_scale*(*(I->VAO + *(t+2)));
		  break;
		case 2:
		  ao1 = cos(.5f * PI * CLAMP_VALUE(ambient_occlusion_scale*(*(I->VAO + *t))));
		  ao2 = cos(.5f * PI * CLAMP_VALUE(ambient_occlusion_scale*(*(I->VAO + *(t+1)))));
		  ao3 = cos(.5f * PI * CLAMP_VALUE(ambient_occlusion_scale*(*(I->VAO + *(t+2)))));
		  break;
		default:
		  ao1 = CLAMP_VALUE(1.f / (1.f + exp(.5f*((ambient_occlusion_scale*(*(I->VAO + *t))) - 10.f))));
		  ao2 = CLAMP_VALUE(1.f / (1.f + exp(.5f*((ambient_occlusion_scale*(*(I->VAO + *(t+1)))) - 10.f))));
		  ao3 = CLAMP_VALUE(1.f / (1.f + exp(.5f*((ambient_occlusion_scale*(*(I->VAO + *(t+2)))) - 10.f))));
		}
		mult3f(cA, ao1, cA);
		mult3f(cB, ao2, cB);
		mult3f(cC, ao3, cC);
	      }
              if(va) {
                ok &= ray->triangleTrans3fv(v + ttA3, v + ttB3, v + ttC3,
					     vn + ttA3, vn + ttB3, vn + ttC3,
					     cA, cB, cC,
					     1.0F - va[ttA], 1.0F - va[ttB], 1.0F - va[ttC]);
              } else {
                ok &= ray->triangle3fv(v + ttA3, v + ttB3, v + ttC3,
					vn + ttA3, vn + ttB3, vn + ttC3, cA, cB, cC);
              }
            }
          }
          t += 3;
        }
      }
    } else if(I->Type == 2) {   /* triangle mesh surface */

      float radius;
      int t0, t1, t2;
      int spacing = 10;
      int *cache = Calloc(int, spacing * (I->N + 1));
      CHECKOK(ok, cache);

      radius = SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_radius);

      if(ok && radius == 0.0F) {
        float line_width =
          SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_width);
        line_width = SceneGetDynamicLineWidth(info, line_width);

        radius = ray->PixelRadius * line_width / 2.0F;
      }
      if (ok){
        float col[3], *col0, *col1, *col2;
	c = I->NT;
	if(I->oneColorFlag) {
	  ColorGetEncoded(G, I->oneColor, col);
          col0 = col1 = col2 = col;
        }
        while(ok && c--) {
	    t0 = (*t);
	    t1 = (*(t + 1));
	    t2 = (*(t + 2));
            if (visibility_test(I->proximity, vi, t)) {
              if (!I->oneColorFlag) {
                col0 = vc + t0 * 3;
                col1 = vc + t1 * 3;
                col2 = vc + t2 * 3;
              }
	      if(!check_and_add(cache, spacing, t0, t1))
		ok &= ray->sausage3fv(v + t0 * 3, v + t1 * 3, radius, col0, col1);
	      if(!check_and_add(cache, spacing, t1, t2))
		ok &= ray->sausage3fv(v + t1 * 3, v + t2 * 3, radius, col1, col2);
	      if(!check_and_add(cache, spacing, t2, t0))
		ok &= ray->sausage3fv(v + t2 * 3, v + t0 * 3, radius, col2, col0);
	    }
	    t += 3;
	}
	FreeP(cache);
      }
    }
    if (ok){
      ray->transparentf(0.0);
    } else {
      /* If not ok, then Clear Entire RepSurface, not just the ray object */
      
    }
#endif
  } else if(G->HaveGUI && G->ValidContext) {
    /* Not ray tracing, but rendering */
    if(pick) {
      // Don't render transparent unpickable surfaces. Do render solid but
      // unpickable surfaces to write the depth buffer and prevent
      // through-picking.
      if (I->pickingCGO && !(I->pickingCGO->no_pick && alpha < 1.F)) {
	CGORenderGLPicking(I->pickingCGO, info, &I->R.context, I->R.cs->Setting, I->R.obj->Setting);
      }
    } else {

#ifndef PURE_OPENGL_ES_2
      bool use_shader = SettingGetGlobal_b(G, cSetting_surface_use_shader) &&
        SettingGetGlobal_b(G, cSetting_use_shaders);

      if (use_shader && !info->alpha_cgo)
#endif
      {
        bool dot_as_spheres = SettingGet_b(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_as_spheres);

        if (!I->shaderCGO || CGOCheckWhetherToFree(G, I->shaderCGO) ||
            (I->Type == 1 && I->dot_as_spheres != dot_as_spheres)) {
          ok &= RepSurfaceCGOGenerate(I, info);
        }

        if (ok && I->shaderCGO) {
          const float *color = ColorGet(G, I->R.obj->Color);
          CGORenderGL(I->shaderCGO, color, NULL, NULL, info, &I->R);
          return;
        }

        PRINTFB(G, FB_RepSurface, FB_Errors)
          " RepSurfaceCGOGenerate failed\n" ENDFB(G);
      }

      setShaderCGO(I, NULL);

#ifndef PURE_OPENGL_ES_2
      bool two_sided_lighting =
        SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting,
            cSetting_two_sided_lighting) > 0;
      if (two_sided_lighting){
        GLLIGHTMODELI(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
      }

      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);
          int lighting = info->line_lighting ||
            SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_lighting);

          if(!normals){
            SceneResetNormal(G, true);
            vn = NULL;
          }

          if(!lighting)
            glDisable(GL_LIGHTING);

          glPointSize(SettingGet_f
              (G, I->R.cs->Setting, I->R.obj->Setting, cSetting_dot_width));
          if(c) {
            glBegin(GL_POINTS);
            if(I->oneColorFlag) {
              glColor3fv(ColorGet(G, I->oneColor));
              vc = NULL;
            } else {
              glColor3f(1.0, 0.0, 0.0);
            }

            immediate_draw_masked_vertices(vc, vn, v, vi, c);
            glEnd();
          }

          if(!lighting)
            glEnable(GL_LIGHTING);
        } /* else use shader */
      } else if(I->Type == 2) { /* rendering triangle mesh */
        if (ok) {

          c = I->NT;
          if(ok && c) {
              int normals =
                SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_normals);
              int lighting = info->line_lighting ||
                SettingGet_i(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_lighting);

              if(!normals){
                SceneResetNormal(G, true);
                vn = NULL;
              }

              if(!lighting)
                glDisable(GL_LIGHTING);

              float line_width =
                SettingGet_f(G, I->R.cs->Setting, I->R.obj->Setting, cSetting_mesh_width);
              glLineWidth(SceneGetDynamicLineWidth(info, line_width));

              if(I->oneColorFlag) {
                glColor3fv(ColorGet(G, I->oneColor));
                vc = NULL;
              }

              glBegin(GL_LINES);
              for (; c--; t += 3) {
                if (visibility_test(I->proximity, vi, t)) {
                  int indices[] = {t[0], t[1], t[1], t[2], t[2], t[0]};
                  immediate_draw_indexed_vertices(vc, vn, v, indices, 6);
                }
              }
              glEnd();

              if(!lighting)
                glEnable(GL_LIGHTING);
          }
	}
      } 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){
		glColor4f(col[0], col[1], col[2], alpha);
		glBegin(GL_TRIANGLES);
		for(c = 0; c < n_tri; c++) {
		  tb = t_buf + 6 * ix[c];
		  glNormal3fv(*(tb++));
		  glVertex3fv(*(tb++));
		  glNormal3fv(*(tb++));
		  glVertex3fv(*(tb++));
		  glNormal3fv(*(tb++));
		  glVertex3fv(*(tb++));
		}
		glEnd();
	      }
            } else { /* else I->oneColorFlag */
		glBegin(GL_TRIANGLES);
		for(c = 0; c < n_tri; c++) {
		  float *vv, *v_alpha;
		  
		  tb = t_buf + 12 * ix[c];
		  
		  v_alpha = *(tb++);
		  vv = *(tb++);
		  glColor4f(vv[0], vv[1], vv[2], *v_alpha);
		  glNormal3fv(*(tb++));
		  glVertex3fv(*(tb++));
		  
		  v_alpha = *(tb++);
		  vv = *(tb++);
		  glColor4f(vv[0], vv[1], vv[2], *v_alpha);
		  glNormal3fv(*(tb++));
		  glVertex3fv(*(tb++));
		  
		  v_alpha = *(tb++);
		  vv = *(tb++);
		  glColor4f(vv[0], vv[1], vv[2], *v_alpha);
		  glNormal3fv(*(tb++));
		  glVertex3fv(*(tb++));
		}
		glEnd();
	      }
	    {
	      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);

                  glColor4f(col[0], col[1], col[2], alpha);
                  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 */
                if(I->oneColorFlag) {
                  float col[3];
                  ColorGetEncoded(G, I->oneColor, col);
                  glColor4f(col[0], col[1], col[2], alpha);
                  vc = NULL;
                }

                if(I->allVisibleFlag) {
                  for (; (c = *(s++)); s += c + 2) {
                    glBegin(GL_TRIANGLE_STRIP);
                    immediate_draw_indexed_vertices_alpha(vc, va, alpha, vn, v, s, c + 2);
                    glEnd();
                  }
                } else {
                  c = I->NT;
                  if(c) {
                    glBegin(GL_TRIANGLES);
                    for (; c--; t += 3) {
                      if (visibility_test(I->proximity, vi, t)) {
                        immediate_draw_indexed_vertices_alpha(vc, va, alpha, vn, v, t, 3);
                      }
                    }
                    glEnd();
                  }
                }
            }
          }
        } else if (ok) {                /* opaque */
            if(I->oneColorFlag) {
              glColor3fv(ColorGet(G, I->oneColor));
              vc = NULL;
            }

            if(I->allVisibleFlag) {
              for (; (c = *(s++)); s += c + 2) {
                glBegin(GL_TRIANGLE_STRIP);
                immediate_draw_indexed_vertices(vc, vn, v, s, c + 2);
                glEnd();
              }
            } else {
              c = I->NT;
              if(c) {
                glBegin(GL_TRIANGLES);
                for (; c--; t += 3) {
                  if (visibility_test(I->proximity, vi, t)) {
                    immediate_draw_indexed_vertices(vc, vn, v, t, 3);
                  }
                }
                glEnd();
              }
            }
        }
      }
      if(ok && SettingGetGlobal_i(G, cSetting_surface_debug)) {
        t = I->T;
        c = I->NT;

        glLineWidth(1.0F);

        // draw green triangles, either filled or as line edges,
        // depending on surface_type
        if(c) {
          glColor3f(0.0, 1.0, 0.0);
          if (I->Type == 2) {
            // filled green triangles for surface as mesh
            glBegin(GL_TRIANGLES);
            for (; c--; t += 3) {
              if(I->allVisibleFlag
                  || visibility_test(I->proximity, vi, t)) {
                immediate_draw_indexed_vertices(NULL, vn, v, t, 3);
              }
            }
            glEnd();
          } else {
            // line edges as green lines
            glBegin(GL_LINES);
            for (; c--; t += 3) {
              if(I->allVisibleFlag
                  || visibility_test(I->proximity, vi, t)) {
                int indices[] = {t[0], t[1], t[1], t[2], t[2], t[0]};
                immediate_draw_indexed_vertices(NULL, vn, v, indices, 6);
              }
            }
            glEnd();
          }
        }

        // draw normals as red lines
        c = I->N;
        if(c) {
          SceneResetNormal(G, true);
          glColor3f(1.0, 0.0, 0.0);
          glBegin(GL_LINES);
          while(c--) {
            glVertex3fv(v);
            glVertex3f(v[0] + vn[0] / 2, v[1] + vn[1] / 2, v[2] + vn[2] / 2);
            v += 3;
            vn += 3;
          }
          glEnd();
        }
      }

      if (two_sided_lighting){
        GLLIGHTMODELI(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
      }
#endif
    }
  }
  if (!ok){
    I->R.fInvalidate(&I->R, I->R.cs, cRepInvPurge);
    I->R.cs->Active[cRepSurface] = false;
  }
}