0022819: Redesign of OpenGl driver
[occt.git] / src / OpenGl / OpenGl_Mesh.cxx
diff --git a/src/OpenGl/OpenGl_Mesh.cxx b/src/OpenGl/OpenGl_Mesh.cxx
new file mode 100644 (file)
index 0000000..db63ada
--- /dev/null
@@ -0,0 +1,925 @@
+// File:      OpenGl_Mesh.cxx
+// Created:   13 July 2011
+// Author:    Sergey ZERCHANINOV
+// Copyright: OPEN CASCADE 2011
+
+#define OCC749          /* SAV 19/09/02 added processing of colored vertices */
+#define OCC7824         /* ASL 26/01/05 transparency of polygon with colors assigned to vertices */
+
+/*----------------------------------------------------------------------*/
+/*
+* Includes
+*/ 
+
+#include <OpenGl_tgl_all.hxx>
+#include <GL/gl.h>
+
+#include <OpenGl_Mesh.hxx>
+
+#include <OpenGl_telem_util.hxx>
+#include <OpenGl_TextureBox.hxx>
+
+#include <OpenGl_AspectFace.hxx>
+#include <OpenGl_Structure.hxx>
+
+#include <float.h>
+
+static long s_Rand = 1L;
+# define OPENGL_RAND() ( ( unsigned )( s_Rand = s_Rand * 214013L + 2531011L ) )
+
+/*----------------------------------------------------------------------*/
+/*
+* Prototypes
+*/ 
+
+typedef TEL_INDEXPOLY_DATA* tel_indexpoly_data;
+
+void set_drawable_items ( GLboolean*, int, const float );
+
+/*----------------------------------------------------------------------*/
+
+void OpenGl_Mesh::draw_indexpoly (const Tint front_lighting_model,
+                                 const Aspect_InteriorStyle interior_style,
+                                 const TEL_COLOUR *edge_colour,
+                                 const OPENGL_SURF_PROP *prop,
+                                 const Handle(OpenGl_Workspace) &AWorkspace) const
+{
+  Tint i, j, k, a, newList = 0;
+  Tint  lighting_model;
+
+  /* Following pointers have been provided for performance improvement */
+  Tint       *ind;
+  tel_point  pfn, pvn, pv;
+  tel_colour pvc, pfc;
+  tel_texture_coord pvt;
+
+  ind = myData.indices;
+  pfn = myData.fnormals;
+  pvn = myData.vnormals;
+  pvc = myData.vcolours;
+  pfc = myData.fcolours;
+  pv  = myData.vertices;
+  pvt = myData.vtexturecoord;
+  if ( AWorkspace->DegenerateModel < 2 && interior_style != Aspect_IS_EMPTY )
+  {      
+    if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
+    {
+      pvc = 0;
+      pfc = 0;
+    }
+
+    if ( interior_style == Aspect_IS_HIDDENLINE)
+    {
+      pvc = 0;
+      pfc = 0;
+    }
+
+    if ( front_lighting_model )
+      glEnable(GL_LIGHTING);
+    else
+      glDisable(GL_LIGHTING);
+
+    lighting_model = front_lighting_model;
+
+    if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) == 0 )
+      goto doDraw; /* Disable object display list out of animation */
+    /*  window's context and bitmap's one    */
+
+    if ( myDS->model != lighting_model || !myDS->list ||
+         myDS->model == -1 || ( AWorkspace->DegenerateModel && myDS->skipRatio != AWorkspace->SkipRatio ))
+    {
+        myDS->skipRatio = AWorkspace->SkipRatio;
+        myDS->model     = lighting_model;
+        myDS->degMode   = AWorkspace->DegenerateModel;
+        if ( AWorkspace->SkipRatio <= 0.f ) {
+          if ( !myDS->list ) myDS->list = glGenLists ( 1 );
+
+          glNewList ( myDS->list, GL_COMPILE_AND_EXECUTE );
+          newList = 1;
+doDraw:
+          if ( !lighting_model )
+          {
+            if ( myData.num_bounds == 3 )
+              glBegin ( GL_TRIANGLES );
+            else if ( myData.num_bounds == 4 )
+              glBegin ( GL_QUADS );
+            else glBegin ( GL_POLYGON );
+
+            if ( pvc )
+            {
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i )
+              {
+                a = j + myData.num_bounds;
+                for ( ; j < a; ++j )
+                {
+                  glColor3fv  ( pvc[  ind[ j ]  ].rgb  );
+                  glVertex3fv ( pv[   ind[ j ]  ].xyz  );
+                }
+              }
+            }
+            else if ( pfc )
+            {
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i )
+              {
+                a = j + myData.num_bounds;
+                glColor3fv ( pfc[ i ].rgb );
+                for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz );
+              }
+            }
+            else
+            {
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i )
+              {
+                a = j + myData.num_bounds;
+                for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz  );
+              }
+            }
+            glEnd ();
+          }
+          else
+          {
+            /* lighting_model != TelLModelNone */
+            if ( myData.num_bounds == 3 )
+              glBegin ( GL_TRIANGLES );
+            else if ( myData.num_bounds == 4 )
+              glBegin ( GL_QUADS );
+            else glBegin ( GL_POLYGON );
+
+#ifdef OCC749
+            for ( i = a = 0; i < myData.num_facets; ++i ) {
+              j = a; a += myData.num_bounds;
+              if( pfn ) glNormal3fv ( pfn[ i ].xyz );
+              if( pfc && !prop->isphysic ) {
+                GLfloat diff[4], ambi[4], emsv[4], r, g, b;
+
+                ambi[3] = diff[3] = emsv[3] = prop->trans;
+
+                r = pfc[ i ].rgb[0];  g = pfc[ i ].rgb[1];  b = pfc[ i ].rgb[2];
+
+                if( prop->color_mask & OPENGL_AMBIENT_MASK ) {
+                  ambi[0] = prop->amb * r;
+                  ambi[1] = prop->amb * g;
+                  ambi[2] = prop->amb * b;
+                  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambi);
+                }
+                if( prop->color_mask & OPENGL_DIFFUSE_MASK ) {
+                  diff[0] = prop->diff * r;
+                  diff[1] = prop->diff * g;
+                  diff[2] = prop->diff * b;
+                  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
+                }
+                if( prop->color_mask & OPENGL_EMISSIVE_MASK ) {
+                  emsv[0] = prop->emsv * r;
+                  emsv[1] = prop->emsv * g;
+                  emsv[2] = prop->emsv * b;
+                  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emsv);
+                }
+              }
+              for ( ; j < a; ++j ) {
+                k = ind[ j ];
+                if( pvn ) glNormal3fv ( pvn[ k ].xyz );
+                if( pvc && !prop->isphysic ) {
+                  GLfloat diff[4], ambi[4], emsv[4], r, g, b;
+
+                  ambi[3] = diff[3] = emsv[3] = prop->trans;
+
+                  r = pvc[ k ].rgb[0];  g = pvc[ k ].rgb[1];  b = pvc[ k ].rgb[2];
+
+                  if( prop->color_mask & OPENGL_AMBIENT_MASK ) {
+                    ambi[0] = prop->amb * r;
+                    ambi[1] = prop->amb * g;
+                    ambi[2] = prop->amb * b;
+                    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambi);
+                  }
+                  if( prop->color_mask & OPENGL_DIFFUSE_MASK ) {
+                    diff[0] = prop->diff * r;
+                    diff[1] = prop->diff * g;
+                    diff[2] = prop->diff * b;
+                    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
+                  }
+                  if( prop->color_mask & OPENGL_EMISSIVE_MASK ) {
+                    emsv[0] = prop->emsv * r;
+                    emsv[1] = prop->emsv * g;
+                    emsv[2] = prop->emsv * b;
+                    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emsv);
+                  }
+                }
+                if( pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0 ) glTexCoord2fv ( pvt[ k ].xy  );
+                glVertex3fv ( pv[ k ].xyz );
+              }  /* end for ( j . . . ) */
+            }  /* end for ( i . . . ) */
+            glEnd ();  
+#else
+            if ( pvn ) {
+              if ( pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0 )
+                for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                  a = j + myData.num_bounds;
+                  for ( ; j < a; ++j ) {
+                    glNormal3fv   ( pvn[  ind[ j ]  ].xyz );
+                    glTexCoord2fv ( pvt[  ind[ j ]  ].xy  );
+                    glVertex3fv   ( pv[   ind[ j ]  ].xyz );
+                  }  /* end for ( j . . . ) */
+                }  /* end for ( i . . . ) */
+              else
+                for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                  a = j + myData.num_bounds;
+                  for ( ; j < a; ++j ) {
+                    glNormal3fv ( pvn[  ind[ j ]  ].xyz  );
+                    glVertex3fv ( pv[   ind[ j ]  ].xyz  );
+                  }  /* end for ( j . . . ) */
+                }  /* end for ( i . . . ) */
+            } else { /* !pvn */
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                a = j + myData.num_bounds;
+                glNormal3fv ( pfn[ i ].xyz );
+                for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz  );
+              }  /* end for */
+            }  /* end else */
+            glEnd ();  
+#endif /* OCC749 */
+
+          }  /* end else */
+        } else if ( AWorkspace->SkipRatio < 1.f ) {
+          if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
+          glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
+          newList = 1;
+          set_drawable_items ( myDS->bDraw, myData.num_facets, AWorkspace->SkipRatio );
+          if ( !lighting_model ) {
+            if ( myData.num_bounds == 3 )
+              glBegin ( GL_TRIANGLES );
+            else if ( myData.num_bounds == 4 )
+              glBegin ( GL_QUADS );
+            else glBegin ( GL_POLYGON );
+
+            if ( pvc ) {
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                a = j + myData.num_bounds;
+                if ( myDS->bDraw[ i ] )
+                  for ( ; j < a; ++j ) {
+                    glColor3fv  ( pvc[  ind[ j ]  ].rgb  );
+                    glVertex3fv ( pv[   ind[ j ]  ].xyz  );
+                  }  /* end for ( j . . . ) */
+                else j = a;
+              }  /* end for ( i . . . ) */
+            } else if ( pfc ) {
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                a = j + myData.num_bounds;
+                if ( myDS->bDraw[ i ] ) {
+                  glColor3fv ( pfc[ i ].rgb );
+                  for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz );
+                } else j = a;
+              }  /* end for */
+            } else {
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                a = j + myData.num_bounds;
+                if ( myDS->bDraw[ i ] )
+                  for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz  );
+                else j = a;
+              }  /* end for */
+            }  /* end else */
+            glEnd ();
+          } else {   /* lighting_model != TelLModelNone */
+            if ( myData.num_bounds == 3 )
+              glBegin ( GL_TRIANGLES );
+            else if ( myData.num_bounds == 4 )
+              glBegin ( GL_QUADS );
+            else glBegin ( GL_POLYGON );
+
+            if ( pvn ) {
+              if ( pvt && (AWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0 )
+                for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                  a = j + myData.num_bounds;
+                  if ( myDS->bDraw[ i ] )
+                    for ( ; j < a; ++j ) {
+                      glNormal3fv   ( pvn[  ind[ j ]  ].xyz );
+                      glTexCoord2fv ( pvt[  ind[ j ]  ].xy  );
+                      glVertex3fv   ( pv[   ind[ j ]  ].xyz );
+                    }  /* end for ( j . . . ) */
+                  else j = a;
+                }  /* end for ( i . . . ) */
+              else
+                for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                  a = j + myData.num_bounds;
+                  if ( myDS->bDraw[ i ] )
+                    for ( ; j < a; ++j ) {
+                      glNormal3fv ( pvn[  ind[ j ]  ].xyz  );
+                      glVertex3fv ( pv[   ind[ j ]  ].xyz  );
+                    }  /* end for ( j . . . ) */
+                  else j = a;
+                }  /* end for ( i . . . ) */
+            } else {  /* !pvn */
+              for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+                a = j + myData.num_bounds;
+                if ( myDS->bDraw[ i ] ) {
+                  glNormal3fv ( pfn[ i ].xyz );
+                  for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz  );
+                } else j = a;
+              }  /* end for */
+            }  /* end else */
+            glEnd ();  
+          }  /* end else */
+        } else {
+          if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
+          glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
+          newList = 1;
+        }  /* end else */
+        if ( newList ) glEndList ();
+        if ( AWorkspace->DegenerateModel ) return;
+      } else {
+        glCallList ( AWorkspace->SkipRatio <= 0.f ? myDS->list : myDS->dlist );
+        if ( AWorkspace->DegenerateModel ) return;
+      }  /* end else */
+  }
+
+  i = 0;
+
+  switch ( AWorkspace->DegenerateModel )
+  {
+    default:
+      break;
+
+    case 2:  /* XXX_TDM_WIREFRAME */
+      i = 1;
+      break;
+
+    case 3:  /* XXX_TDM_MARKER */
+      draw_degenerates_as_points ( AWorkspace->SkipRatio );
+      return;
+
+    case 4:  /* XXX_TDM_BBOX */
+      draw_degenerates_as_bboxs ();
+      return;
+  }
+
+  draw_edges ( edge_colour, interior_style, i, AWorkspace );
+}
+
+/*----------------------------------------------------------------------*/
+
+void OpenGl_Mesh::draw_edges (const TEL_COLOUR *edge_colour, const Aspect_InteriorStyle interior_style,
+                             Tint forceDraw, const Handle(OpenGl_Workspace) &AWorkspace) const
+{
+  const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
+
+  if ( interior_style != Aspect_IS_HIDDENLINE && !forceDraw && aspect_face->Context().Edge == TOff )
+    return;
+
+  glDisable(GL_LIGHTING);
+  const GLboolean texture_on = IsTextureEnabled();
+  if (texture_on) DisableTexture();
+
+  // Setup line aspect
+  const OpenGl_AspectLine *aspect_line_old = AWorkspace->SetAspectLine( aspect_face->AspectEdge() );
+  AWorkspace->AspectLine( Standard_True );
+
+  tel_point pv = myData.vertices;
+  Tint *ind = myData.indices;
+  Tint *vis = myData.edge_vis;
+
+  Tint i, j, a, newList = 0;
+
+  if ( !forceDraw ) {
+
+    glColor3fv    ( edge_colour -> rgb         );
+    glPushAttrib  ( GL_POLYGON_BIT             );
+    glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
+
+    for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+
+      a = j + myData.num_bounds;
+
+      glBegin ( GL_POLYGON );
+
+      for ( ; j < a; ++j ) {
+
+        glEdgeFlag (   ( GLboolean )( vis[ j ] == 1 ? GL_TRUE : GL_FALSE )  );
+        glVertex3fv ( pv[  ind[ j ]  ].xyz );
+
+      }  /* end for */
+
+      glEnd();
+
+      glEdgeFlag ( GL_TRUE );
+
+    }  /* end for */
+
+    glPopAttrib ();
+
+  } else {
+
+    if ( (AWorkspace->NamedStatus & OPENGL_NS_ANIMATION) == 0 ) 
+      goto doDraw; /* Disable object display list out of animation */
+
+    if ( myDS->degMode != 2 || myDS->skipRatio != AWorkspace->SkipRatio || !myDS->dlist ) {
+
+      if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
+
+      myDS->degMode   = 2;
+      myDS->skipRatio = AWorkspace->SkipRatio;
+      glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
+      newList = 1;
+
+doDraw:
+      glPushAttrib ( GL_POLYGON_BIT | GL_DEPTH_BUFFER_BIT );
+
+      glEdgeFlag    ( GL_TRUE                    );
+      glDisable     ( GL_DEPTH_TEST              );
+      glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
+
+      if ( AWorkspace->SkipRatio <= 0.f )
+
+        for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+
+          a = j + myData.num_bounds;
+
+          glBegin ( GL_POLYGON );
+
+          for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz );
+
+          glEnd();
+
+        }  /* end for */
+
+      else if ( AWorkspace->SkipRatio < 1.f ) {
+
+        set_drawable_items ( myDS->bDraw, myData.num_facets, AWorkspace->SkipRatio );
+
+        for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+
+          a = j + myData.num_bounds;
+
+          if ( myDS->bDraw[ i ] ) {
+
+            glBegin ( GL_POLYGON );
+
+            for ( ; j < a; ++j ) glVertex3fv ( pv[  ind[ j ]  ].xyz );
+
+            glEnd();
+
+          } else j = a;
+
+        }  /* end for */
+
+      }  /* end if */
+
+      glPopAttrib ();
+      if ( newList ) glEndList ();
+
+    } else glCallList ( myDS->dlist );
+
+  }  /* end else */
+
+  // Restore line context
+  AWorkspace->SetAspectLine( aspect_line_old );
+
+  if (texture_on) EnableTexture();
+}
+
+/*----------------------------------------------------------------------*/
+
+void OpenGl_Mesh::draw_degenerates_as_points (const float aSkipRatio) const
+{
+  Tint*      ind, *vis;
+  Tint       i, j, n, a, newList = 0;
+  GLfloat    pt[ 3 ];
+  tel_point  pv;
+
+  pv  = myData.vertices;
+  ind = myData.indices;
+  vis = myData.edge_vis;
+
+  glDisable(GL_LIGHTING);
+
+  if ( myDS->degMode != 3 || myDS->skipRatio != aSkipRatio || !myDS->dlist ) {
+
+    if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
+
+    myDS->degMode   = 3;
+    myDS->skipRatio = aSkipRatio;
+    glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
+    newList = 1;
+
+    if ( aSkipRatio <= 0.f ) {
+
+      glBegin ( GL_POINTS );
+
+      for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+
+        n = myData.num_bounds;
+        a = j + n;
+
+        for ( pt [ 0 ] = pt[ 1 ] = pt[ 2 ] = 0.; j < a; ++j ) {
+
+          pt[ 0 ] += pv[  ind[ j ]  ].xyz[ 0 ];
+          pt[ 1 ] += pv[  ind[ j ]  ].xyz[ 1 ];
+          pt[ 2 ] += pv[  ind[ j ]  ].xyz[ 2 ];
+
+        }  /* end for ( j ) */
+
+        pt[ 0 ] /= n;
+        pt[ 1 ] /= n;
+        pt[ 2 ] /= n;
+
+        glVertex3fv ( pt );
+
+      }  /* end for ( i ) */
+
+      glEnd ();
+
+    } else if ( aSkipRatio < 1.f ) {
+
+      set_drawable_items ( myDS->bDraw, myData.num_facets, aSkipRatio );
+
+      glBegin ( GL_POINTS );
+
+      for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+
+        n = myData.num_bounds;
+        a = j + n;
+
+        if ( myDS->bDraw[ i ] ) {
+
+          for ( pt [ 0 ] = pt[ 1 ] = pt[ 2 ] = 0.; j < a; ++j ) {
+
+            pt[ 0 ] += pv[  ind[ j ]  ].xyz[ 0 ];
+            pt[ 1 ] += pv[  ind[ j ]  ].xyz[ 1 ];
+            pt[ 2 ] += pv[  ind[ j ]  ].xyz[ 2 ];
+
+          }  /* end for ( j ) */
+
+          pt[ 0 ] /= n;
+          pt[ 1 ] /= n;
+          pt[ 2 ] /= n;
+
+          glVertex3fv ( pt );
+
+        } else j = a;
+
+      }  /* end for ( i ) */
+
+      glEnd ();
+
+    }  /* end if */
+
+    glEndList ();
+
+  } else glCallList ( myDS->dlist );
+
+}
+
+void OpenGl_Mesh::draw_degenerates_as_bboxs () const
+{
+  Tint*     ind, *vis;
+  Tint      i, j, n, a, newList = 0;
+  GLfloat   minp[ 3 ] = { FLT_MAX, FLT_MAX, FLT_MAX };
+  GLfloat   maxp[ 3 ] = { FLT_MIN, FLT_MIN, FLT_MIN };
+  tel_point pv;
+
+  pv  = myData.vertices;
+  ind = myData.indices;
+  vis = myData.edge_vis;
+
+  glDisable(GL_LIGHTING);
+
+  if ( myDS->degMode != 4 || !myDS->dlist ) {
+
+    if ( !myDS->dlist ) myDS->dlist = glGenLists ( 1 );
+
+    myDS->degMode = 4;
+
+    glNewList ( myDS->dlist, GL_COMPILE_AND_EXECUTE );
+    newList = 1;
+
+    for ( i = 0, j = 0, a = 0; i < myData.num_facets; ++i ) {
+
+      n = myData.num_bounds;
+      a = j + n;
+
+      for ( ; j < a; ++j ) {
+
+        if ( pv[  ind[ j ]  ].xyz[ 0 ] < minp[ 0 ] )
+          minp[ 0 ] = pv[  ind[ j ]  ].xyz[ 0 ] ;
+        if ( pv[  ind[ j ]  ].xyz[ 1 ] < minp[ 1 ] )
+          minp[ 1 ] = pv[  ind[ j ]  ].xyz[ 1 ] ;
+        if ( pv[  ind[ j ]  ].xyz[ 2 ] < minp[ 2 ] )
+          minp[ 2 ] = pv[  ind[ j ]  ].xyz[ 2 ] ;
+
+        if ( pv[  ind[ j ]  ].xyz[ 0 ] > maxp[ 0 ] )
+          maxp[ 0 ] = pv[  ind[ j ]  ].xyz[ 0 ] ;
+        if ( pv[  ind[ j ]  ].xyz[ 1 ] > maxp[ 1 ] )
+          maxp[ 1 ] = pv[  ind[ j ]  ].xyz[ 1 ] ;
+        if ( pv[  ind[ j ]  ].xyz[ 2 ] > maxp[ 2 ] )
+          maxp[ 2 ] = pv[  ind[ j ]  ].xyz[ 2 ] ;
+
+      }  /* end for ( j ) */
+
+    }  /* end for ( i ) */
+
+    /* OCC11904 -- Temporarily disable environment mapping */
+    glPushAttrib(GL_ENABLE_BIT);
+    glDisable(GL_TEXTURE_1D);
+    glDisable(GL_TEXTURE_2D);
+
+    glBegin ( GL_LINE_STRIP );
+
+    glVertex3fv ( minp );
+    glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
+    glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
+    glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
+    glVertex3f ( minp[ 0 ], minp[ 1 ], minp[ 2 ] );
+
+    glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
+    glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
+    glVertex3f ( maxp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
+    glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
+    glVertex3f ( maxp[ 0 ], minp[ 1 ], minp[ 2 ] );
+
+    glVertex3f ( maxp[ 0 ], minp[ 1 ], maxp[ 2 ] );
+    glVertex3f ( minp[ 0 ], minp[ 1 ], maxp[ 2 ] );
+    glVertex3f ( minp[ 0 ], maxp[ 1 ], maxp[ 2 ] );
+    glVertex3fv ( maxp );
+    glVertex3f ( maxp[ 0 ], maxp[ 1 ], minp[ 2 ] );
+    glVertex3f ( minp[ 0 ], maxp[ 1 ], minp[ 2 ] );
+
+    glEnd();
+    glPopAttrib();
+    glEndList ();
+
+  } else glCallList ( myDS->dlist );
+}
+
+/*----------------------------------------------------------------------*/
+
+void set_drawable_items ( GLboolean* pbDraw, int n, const float aSkipRatio )
+{
+  memset (  pbDraw, 0, sizeof ( GLboolean ) * n  );
+
+  int i = ( int )(  ( 1.0F - aSkipRatio ) * n  );
+
+  while ( i-- ) pbDraw[ OPENGL_RAND() % n ] = 1;
+}
+
+/*----------------------------------------------------------------------*/
+
+OpenGl_Mesh::OpenGl_Mesh (const Graphic3d_Array1OfVertex& AListVertex, const Aspect_Array1OfEdge& AListEdge)
+{
+  const Standard_Integer nv = AListVertex.Length();
+
+  // Dynamic allocation
+  TEL_POINT *points = new TEL_POINT[nv];
+  memcpy( points, &AListVertex(AListVertex.Lower()), nv*sizeof(TEL_POINT) );
+
+  Init (nv,points,NULL,NULL,NULL,AListEdge,3);
+}
+
+/*----------------------------------------------------------------------*/
+
+OpenGl_Mesh::OpenGl_Mesh (const Graphic3d_Array1OfVertexN& AListVertex, const Aspect_Array1OfEdge& AListEdge)
+{
+  const Standard_Integer nv = AListVertex.Length ();
+
+  // Dynamic allocation
+  TEL_POINT *points = new TEL_POINT[nv];
+  TEL_POINT *normals = new TEL_POINT[nv];
+
+  Standard_Integer i = 0, j = AListVertex.Lower();
+  Standard_Real X, Y, Z;
+  for ( ; i < nv; i++, j++)
+  {
+    AListVertex(j).Coord(X, Y, Z);
+    points[i].xyz[0] = float (X);
+    points[i].xyz[1] = float (Y);
+    points[i].xyz[2] = float (Z);
+    AListVertex(j).Normal(X, Y, Z);
+    normals[i].xyz[0] = float (X);
+    normals[i].xyz[1] = float (Y);
+    normals[i].xyz[2] = float (Z);
+  }
+
+  Init (nv,points,normals,NULL,NULL,AListEdge,3);
+}
+
+/*----------------------------------------------------------------------*/
+
+OpenGl_Mesh::OpenGl_Mesh (const Graphic3d_Array1OfVertexC& AListVertex, const Aspect_Array1OfEdge& AListEdge)
+{
+  const Standard_Integer nv = AListVertex.Length ();
+
+  // Dynamic allocation
+  TEL_POINT *points = new TEL_POINT[nv];
+  TEL_COLOUR *colors = new TEL_COLOUR[nv];
+
+  Standard_Integer i = 0, j = AListVertex.Lower();
+  Standard_Real X, Y, Z;
+  for ( ; i < nv; i++, j++)
+  {
+    AListVertex(j).Coord(X, Y, Z);
+    points[i].xyz[0] = float (X);
+    points[i].xyz[1] = float (Y);
+    points[i].xyz[2] = float (Z);
+    AListVertex(j).Color().Values (X, Y, Z, Quantity_TOC_RGB);
+    colors[i].rgb[0] = float (X);
+    colors[i].rgb[1] = float (Y);
+    colors[i].rgb[2] = float (Z);
+    colors[i].rgb[3] = 1.0F;
+  }
+
+  Init (nv,points,NULL,colors,NULL,AListEdge,3);
+}
+
+/*----------------------------------------------------------------------*/
+
+OpenGl_Mesh::OpenGl_Mesh (const Graphic3d_Array1OfVertexNC& AListVertex, const Aspect_Array1OfEdge& AListEdge)
+{
+  const Standard_Integer nv = AListVertex.Length ();
+
+  // Dynamic allocation
+  TEL_POINT *points = new TEL_POINT[nv];
+  TEL_POINT *normals = new TEL_POINT[nv];
+  TEL_COLOUR *colors = new TEL_COLOUR[nv];
+
+  Standard_Integer i = 0, j = AListVertex.Lower();
+  Standard_Real X, Y, Z;
+  for ( ; i < nv; i++, j++)
+  {
+    AListVertex(j).Coord(X, Y, Z);
+    points[i].xyz[0] = float (X);
+    points[i].xyz[1] = float (Y);
+    points[i].xyz[2] = float (Z);
+    AListVertex(j).Normal(X, Y, Z);
+    normals[i].xyz[0] = float (X);
+    normals[i].xyz[1] = float (Y);
+    normals[i].xyz[2] = float (Z);
+    AListVertex(j).Color().Values (X, Y, Z, Quantity_TOC_RGB);
+    colors[i].rgb[0] = float (X);
+    colors[i].rgb[1] = float (Y);
+    colors[i].rgb[2] = float (Z);
+    colors[i].rgb[3] = 1.0F;
+  }
+
+  Init (nv,points,normals,colors,NULL,AListEdge,3);
+}
+
+/*----------------------------------------------------------------------*/
+
+OpenGl_Mesh::OpenGl_Mesh (const Graphic3d_Array1OfVertexNT& AListVertex, const Aspect_Array1OfEdge& AListEdge)
+{
+  const Standard_Integer nv = AListVertex.Length ();
+
+  // Dynamic allocation
+  TEL_POINT *points = new TEL_POINT[nv];
+  TEL_POINT *normals = new TEL_POINT[nv];
+  TEL_TEXTURE_COORD *tcoords = new TEL_TEXTURE_COORD[nv];
+
+  Standard_Integer i = 0, j = AListVertex.Lower();
+  Standard_Real X, Y, Z;
+  for ( ; i < nv; i++, j++)
+  {
+    AListVertex(j).Coord(X, Y, Z);
+    points[i].xyz[0] = float (X);
+    points[i].xyz[1] = float (Y);
+    points[i].xyz[2] = float (Z);
+    AListVertex(j).Normal(X, Y, Z);
+    normals[i].xyz[0] = float (X);
+    normals[i].xyz[1] = float (Y);
+    normals[i].xyz[2] = float (Z);
+    AListVertex(j).TextureCoordinate(X, Y);
+    tcoords[i].xy[0] = float(X);
+    tcoords[i].xy[1] = float(Y);
+  }
+
+  Init (nv,points,normals,NULL,tcoords,AListEdge,3);
+}
+
+/*----------------------------------------------------------------------*/
+
+void OpenGl_Mesh::Init (const Tint ANbVertices, tel_point AVertices,
+                       tel_point AVNormals, tel_colour AVColors, tel_texture_coord ATCoords,
+                       const Aspect_Array1OfEdge& AListEdge, const Tint ANbBounds)
+{
+  // Get number of bounds in a facet
+  myData.num_bounds = ANbBounds;
+
+  // Get number of vertices
+  myData.num_vertices = ANbVertices;
+
+  // Get vertices
+  myData.vertices = AVertices;
+
+  // Get number of edges
+  const Standard_Integer nb_edges = AListEdge.Length ();
+
+  myData.indices = new Tint[nb_edges];
+  myData.edge_vis = new Tint[nb_edges];
+
+  const Standard_Integer LowerE = AListEdge.Lower ();
+  const Standard_Integer UpperE = AListEdge.Upper ();
+
+  // Loop on edges
+  Standard_Integer i, j;
+  for (j=0, i=LowerE; i<=UpperE; i++, j++)
+  {
+    myData.indices[j] = AListEdge(i).FirstIndex() - LowerE; //LastIndex unused
+    myData.edge_vis[j]  = AListEdge(i).Type() ? TOff : TOn;
+  }
+
+  // Get number of facets
+  myData.num_facets = nb_edges / ANbBounds;
+
+  myData.vnormals = AVNormals;
+  if (AVNormals)
+  {
+    myData.vertex_flag = TEL_VT_NORMAL;
+    for( i = 0; i < ANbVertices; i++ )
+      vecnrm( myData.vnormals[i].xyz );
+  }
+  else
+  {
+    myData.vertex_flag = TEL_VT_NONE;
+  }
+
+  myData.vcolours = AVColors;
+  myData.vtexturecoord = ATCoords;
+
+  myData.facet_flag = TEL_FA_NONE;
+  myData.fnormals = new TEL_POINT[myData.num_facets];
+  for( i = 0, j = 0; i < myData.num_facets; i++ )
+  {
+    TelGetPolygonNormal( myData.vertices, &myData.indices[j], myData.num_bounds, myData.fnormals[i].xyz );
+    j += myData.num_bounds;
+  }
+
+  myData.fcolours = NULL;
+
+  myDS = new DS_INTERNAL();
+  myDS->list      =  0;
+  myDS->dlist     =  0;
+  myDS->degMode   =  0;
+  myDS->model     = -1;
+  myDS->skipRatio =  0.0F;
+  myDS->bDraw = new unsigned char[myData.num_facets];
+}
+
+/*----------------------------------------------------------------------*/
+
+OpenGl_Mesh::~OpenGl_Mesh ()
+{
+  if( myData.edge_vis )
+    delete[] myData.edge_vis;
+  if( myData.indices )
+    delete[] myData.indices;
+  if( myData.fcolours )
+    delete[] myData.fcolours;
+  if( myData.fnormals )
+    delete[] myData.fnormals;
+  if( myData.vertices )
+    delete[] myData.vertices;
+  if( myData.vcolours )
+    delete[] myData.vcolours;
+  if( myData.vnormals )
+    delete[] myData.vnormals;
+  if( myData.vtexturecoord )
+    delete[] myData.vtexturecoord;
+
+  if ( myDS )
+  {
+    if ( GET_GL_CONTEXT() != NULL )
+    {
+      if ( myDS->list ) glDeleteLists ( myDS->list, 1 );
+      if ( myDS->dlist ) glDeleteLists ( myDS->dlist, 1 );
+    }
+
+    if ( myDS->bDraw )
+      delete[] myDS->bDraw;
+
+       delete myDS;
+  }
+}
+
+/*----------------------------------------------------------------------*/
+
+void OpenGl_Mesh::Render (const Handle(OpenGl_Workspace) &AWorkspace) const
+{
+  const OpenGl_AspectFace *aspect_face = AWorkspace->AspectFace( Standard_True );
+
+  Tint front_lighting_model = aspect_face->Context().IntFront.color_mask;
+  const TEL_COLOUR *interior_colour = &aspect_face->Context().IntFront.matcol;
+  const TEL_COLOUR *edge_colour = &aspect_face->AspectEdge()->Color();
+
+  // Use highlight colors
+  if ( AWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT )
+  {                         
+    edge_colour = interior_colour = AWorkspace->HighlightColor;
+    front_lighting_model = 0;
+  }
+
+  glColor3fv( interior_colour->rgb );
+
+  draw_indexpoly( front_lighting_model,
+                  aspect_face->Context().InteriorStyle,
+                  edge_colour,
+                  &aspect_face->Context().IntFront,
+                  AWorkspace );
+}
+
+/*----------------------------------------------------------------------*/