Skip to content
Snippets Groups Projects
Select Git revision
  • eeefe8a9f79bf35ca279b5c7933441a71393865e
  • master default protected
  • overlaps_tags_and_distributed_export
  • overlaps_tags_and_distributed_export_rebased
  • relaying
  • alphashapes
  • patches-4.14
  • steplayer
  • bl
  • pluginMeshQuality
  • fixBugsAmaury
  • hierarchical-basis
  • new_export_boris
  • oras_vs_osm
  • reassign_partitions
  • distributed_fwi
  • rename-classes
  • fix/fortran-api-example-t4
  • robust_partitions
  • reducing_files
  • fix_overlaps
  • gmsh_4_14_0
  • gmsh_4_13_1
  • gmsh_4_13_0
  • gmsh_4_12_2
  • gmsh_4_12_1
  • gmsh_4_12_0
  • gmsh_4_11_1
  • gmsh_4_11_0
  • gmsh_4_10_5
  • gmsh_4_10_4
  • gmsh_4_10_3
  • gmsh_4_10_2
  • gmsh_4_10_1
  • gmsh_4_10_0
  • gmsh_4_9_5
  • gmsh_4_9_4
  • gmsh_4_9_3
  • gmsh_4_9_2
  • gmsh_4_9_1
  • gmsh_4_9_0
41 results

Transform.cpp

Blame
  • drawMesh.cpp 24.10 KiB
    // Gmsh - Copyright (C) 1997-2019 C. Geuzaine, J.-F. Remacle
    //
    // See the LICENSE.txt file for license information. Please report all
    // issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
    
    #include <cmath>
    #include "drawContext.h"
    #include "GmshMessage.h"
    #include "GmshDefines.h"
    #include "GModel.h"
    #include "MLine.h"
    #include "MTriangle.h"
    #include "MQuadrangle.h"
    #include "MTetrahedron.h"
    #include "MHexahedron.h"
    #include "MPrism.h"
    #include "MPyramid.h"
    #include "MTrihedron.h"
    #include "MElementCut.h"
    #include "Context.h"
    #include "OS.h"
    #include "gl2ps.h"
    #include "VertexArray.h"
    #include "SmoothData.h"
    #include "PView.h"
    #include "PViewData.h"
    
    #if defined(HAVE_FLTK)
    #include <FL/Fl.H>
    #include <FL/gl.h>
    #endif
    
    // from GModelVertexArrays
    extern unsigned int getColorByEntity(GEntity *e);
    extern bool isElementVisible(MElement *ele);
    
    template <class T>
    static void drawElementLabels(drawContext *ctx, GEntity *e,
                                  std::vector<T *> &elements, int forceColor = 0,
                                  unsigned int color = 0)
    {
      unsigned col = forceColor ? color : getColorByEntity(e);
      glColor4ubv((GLubyte *)&col);
    
      int labelStep = CTX::instance()->mesh.labelSampling;
      if(labelStep <= 0) labelStep = 1;
    
      for(std::size_t i = 0; i < elements.size(); i++) {
        MElement *ele = elements[i];
        if(!isElementVisible(ele)) continue;
        if(i % labelStep == 0) {
          SPoint3 pc = ele->barycenter();
          char str[256];
          if(CTX::instance()->mesh.labelType == 4)
            sprintf(str, "(%g,%g,%g)", pc.x(), pc.y(), pc.z());
          else if(CTX::instance()->mesh.labelType == 3)
            sprintf(str, "%d", ele->getPartition());
          else if(CTX::instance()->mesh.labelType == 2) {
            int np = e->physicals.size();
            int p = np ? e->physicals[np - 1] : 0;
            sprintf(str, "%d", p);
          }
          else if(CTX::instance()->mesh.labelType == 1)
            sprintf(str, "%d", e->tag());
          else
            sprintf(str, "%lu", ele->getNum());
          ctx->drawString(str, pc.x(), pc.y(), pc.z());
        }
      }
    }
    
    template <class T>
    static void drawNormals(drawContext *ctx, std::vector<T *> &elements)
    {
      glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.normals);
      for(std::size_t i = 0; i < elements.size(); i++) {
        MElement *ele = elements[i];
        if(!isElementVisible(ele)) continue;
        SVector3 n = ele->getFace(0).normal();
        for(int j = 0; j < 3; j++)
          n[j] *= CTX::instance()->mesh.normals * ctx->pixel_equiv_x / ctx->s[j];
        SPoint3 pc = ele->barycenter();
        ctx->drawVector(CTX::instance()->vectorType, 0, pc.x(), pc.y(), pc.z(),
                        n[0], n[1], n[2], CTX::instance()->mesh.light);
      }
    }
    
    template <class T>
    static void drawTangents(drawContext *ctx, std::vector<T *> &elements)
    {
      glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.tangents);
      for(std::size_t i = 0; i < elements.size(); i++) {
        MElement *ele = elements[i];
        if(!isElementVisible(ele)) continue;
        SVector3 t = ele->getEdge(0).tangent();
        for(int j = 0; j < 3; j++)
          t[j] *= CTX::instance()->mesh.tangents * ctx->pixel_equiv_x / ctx->s[j];
        SPoint3 pc = ele->barycenter();
        ctx->drawVector(CTX::instance()->vectorType, 0, pc.x(), pc.y(), pc.z(),
                        t[0], t[1], t[2], CTX::instance()->mesh.light);
      }
    }
    
    static void drawVertexLabel(drawContext *ctx, GEntity *e, MVertex *v,
                                int partition = -1)
    {
      if(!v->getVisibility()) return;
    
      int np = e->physicals.size();
      int physical = np ? e->physicals[np - 1] : 0;
      char str[256];
      if(CTX::instance()->mesh.labelType == 4)
        sprintf(str, "(%.16g,%.16g,%.16g)", v->x(), v->y(), v->z());
      else if(CTX::instance()->mesh.labelType == 3) {
        if(partition < 0)
          sprintf(str, "NA");
        else
          sprintf(str, "%d", partition);
      }
      else if(CTX::instance()->mesh.labelType == 2)
        sprintf(str, "%d", physical);
      else if(CTX::instance()->mesh.labelType == 1)
        sprintf(str, "%d", e->tag());
      else
        sprintf(str, "%lu", v->getNum());
    
      if(CTX::instance()->mesh.colorCarousel == 0 ||
         CTX::instance()->mesh.volumesFaces ||
         CTX::instance()->mesh.surfacesFaces) { // by element type
        if(v->getPolynomialOrder() > 1)
          glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.nodeSup);
        else
          glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.node);
      }
      else {
        unsigned int col = getColorByEntity(e);
        glColor4ubv((GLubyte *)&col);
      }
      double offset = (0.5 * CTX::instance()->mesh.pointSize +
                       0.1 * CTX::instance()->glFontSize) *
                      ctx->pixel_equiv_x;
      ctx->drawString(str, v->x() + offset / ctx->s[0], v->y() + offset / ctx->s[1],
                      v->z() + offset / ctx->s[2]);
    }
    
    static void drawVerticesPerEntity(drawContext *ctx, GEntity *e)
    {
      if(CTX::instance()->mesh.points) {
        if(CTX::instance()->mesh.pointType) {
          for(std::size_t i = 0; i < e->mesh_vertices.size(); i++) {
            MVertex *v = e->mesh_vertices[i];
            if(!v->getVisibility()) continue;
            if(CTX::instance()->mesh.colorCarousel == 0 ||
               CTX::instance()->mesh.volumesFaces ||
               CTX::instance()->mesh.surfacesFaces) { // by element type
              if(v->getPolynomialOrder() > 1)
                glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.nodeSup);
              else
                glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.node);
            }
            else {
              unsigned int col = getColorByEntity(e);
              glColor4ubv((GLubyte *)&col);
            }
            ctx->drawSphere(CTX::instance()->mesh.pointSize, v->x(), v->y(), v->z(),
                            CTX::instance()->mesh.light);
          }
        }
        else {
          glBegin(GL_POINTS);
          for(std::size_t i = 0; i < e->mesh_vertices.size(); i++) {
            MVertex *v = e->mesh_vertices[i];
            if(!v->getVisibility()) continue;
            if(CTX::instance()->mesh.colorCarousel == 0 ||
               CTX::instance()->mesh.volumesFaces ||
               CTX::instance()->mesh.surfacesFaces) { // by element type
              if(v->getPolynomialOrder() > 1)
                glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.nodeSup);
              else
                glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.node);
            }
            else {
              unsigned int col = getColorByEntity(e);
              glColor4ubv((GLubyte *)&col);
            }
            glVertex3d(v->x(), v->y(), v->z());
          }
          glEnd();
        }
      }
      if(CTX::instance()->mesh.pointsNum) {
        int labelStep = CTX::instance()->mesh.labelSampling;
        if(labelStep <= 0) labelStep = 1;
        for(std::size_t i = 0; i < e->mesh_vertices.size(); i++)
          if(i % labelStep == 0) drawVertexLabel(ctx, e, e->mesh_vertices[i]);
      }
    }
    
    template <class T>
    static void drawVerticesPerElement(drawContext *ctx, GEntity *e,
                                       std::vector<T *> &elements)
    {
      for(std::size_t i = 0; i < elements.size(); i++) {
        MElement *ele = elements[i];
        for(std::size_t j = 0; j < ele->getNumVertices(); j++) {
          MVertex *v = ele->getVertex(j);
          // FIXME isElementVisible() can be slow: we should also use a
          // vertex array for drawing vertices...
          if(isElementVisible(ele) && v->getVisibility()) {
            if(CTX::instance()->mesh.points) {
              if(CTX::instance()->mesh.colorCarousel == 0 ||
                 CTX::instance()->mesh.volumesFaces ||
                 CTX::instance()->mesh.surfacesFaces) { // by element type
                if(v->getPolynomialOrder() > 1)
                  glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.nodeSup);
                else
                  glColor4ubv((GLubyte *)&CTX::instance()->color.mesh.node);
              }
              else {
                unsigned int col = getColorByEntity(e);
                glColor4ubv((GLubyte *)&col);
              }
              if(CTX::instance()->mesh.pointType)
                ctx->drawSphere(CTX::instance()->mesh.pointSize, v->x(), v->y(),
                                v->z(), CTX::instance()->mesh.light);
              else {
                glBegin(GL_POINTS);
                glVertex3d(v->x(), v->y(), v->z());
                glEnd();
              }
            }
            if(CTX::instance()->mesh.pointsNum)
              drawVertexLabel(ctx, v->onWhat() ? v->onWhat() : e, v);
          }
        }
      }
    }
    
    template <class T> static void drawBarycentricDual(std::vector<T *> &elements)
    {
      glColor4ubv((GLubyte *)&CTX::instance()->color.fg);
      glEnable(GL_LINE_STIPPLE);
      glLineStipple(1, 0x0F0F);
      gl2psEnable(GL2PS_LINE_STIPPLE);
      glBegin(GL_LINES);
      for(std::size_t i = 0; i < elements.size(); i++) {
        MElement *ele = elements[i];
        if(!isElementVisible(ele)) continue;
        SPoint3 pc = ele->barycenter();
        if(ele->getDim() == 2) {
          for(int j = 0; j < ele->getNumEdges(); j++) {
            MEdge e = ele->getEdge(j);
            SPoint3 p = e.barycenter();
            glVertex3d(pc.x(), pc.y(), pc.z());
            glVertex3d(p.x(), p.y(), p.z());
          }
        }
        else if(ele->getDim() == 3) {
          for(int j = 0; j < ele->getNumFaces(); j++) {
            MFace f = ele->getFace(j);
            SPoint3 p = f.barycenter();
            glVertex3d(pc.x(), pc.y(), pc.z());
            glVertex3d(p.x(), p.y(), p.z());
            for(std::size_t k = 0; k < f.getNumVertices(); k++) {
              MEdge e(f.getVertex(k), (k == f.getNumVertices() - 1) ?
                                        f.getVertex(0) :
                                        f.getVertex(k + 1));
              SPoint3 pe = e.barycenter();
              glVertex3d(p.x(), p.y(), p.z());
              glVertex3d(pe.x(), pe.y(), pe.z());
            }
          }
        }
      }
      glEnd();
      glDisable(GL_LINE_STIPPLE);
      gl2psDisable(GL2PS_LINE_STIPPLE);
    }
    
    template <class T> static void drawVoronoiDual(std::vector<T *> &elements)
    {
      glColor4ubv((GLubyte *)&CTX::instance()->color.fg);
      glEnable(GL_LINE_STIPPLE);
      glLineStipple(1, 0x0F0F);
      gl2psEnable(GL2PS_LINE_STIPPLE);
      glBegin(GL_LINES);
      for(std::size_t i = 0; i < elements.size(); i++) {
        T *ele = elements[i];
        if(!isElementVisible(ele)) continue;
        SPoint3 pc = ele->circumcenter();
        if(ele->getDim() == 2) {
          for(int j = 0; j < ele->getNumEdges(); j++) {
            MEdge e = ele->getEdge(j);
            SVector3 p2p1(e.getVertex(1)->x() - e.getVertex(0)->x(),
                          e.getVertex(1)->y() - e.getVertex(0)->y(),
                          e.getVertex(1)->z() - e.getVertex(0)->z());
            SVector3 pcp1(pc.x() - e.getVertex(0)->x(),
                          pc.y() - e.getVertex(0)->y(),
                          pc.z() - e.getVertex(0)->z());
            double alpha = dot(pcp1, p2p1) / dot(p2p1, p2p1);
            SPoint3 p(
              (1 - alpha) * e.getVertex(0)->x() + alpha * e.getVertex(1)->x(),
              (1 - alpha) * e.getVertex(0)->y() + alpha * e.getVertex(1)->y(),
              (1 - alpha) * e.getVertex(0)->z() + alpha * e.getVertex(1)->z());
            glVertex3d(pc.x(), pc.y(), pc.z());
            glVertex3d(p.x(), p.y(), p.z());
          }
        }
        else if(ele->getDim() == 3) {
          for(int j = 0; j < ele->getNumFaces(); j++) {
            MFace f = ele->getFace(j);
            SPoint3 p = f.barycenter();
            glVertex3d(pc.x(), pc.y(), pc.z());
            glVertex3d(p.x(), p.y(), p.z());
            for(std::size_t k = 0; k < f.getNumVertices(); k++) {
              MEdge e(f.getVertex(k), (k == f.getNumVertices() - 1) ?
                                        f.getVertex(0) :
                                        f.getVertex(k + 1));
              SPoint3 pe = e.barycenter();
              glVertex3d(p.x(), p.y(), p.z());
              glVertex3d(pe.x(), pe.y(), pe.z());
            }
          }
        }
      }
      glEnd();
      glDisable(GL_LINE_STIPPLE);
      gl2psDisable(GL2PS_LINE_STIPPLE);
    }
    
    // Routine for drawing the vertex arrays
    
    static void drawArrays(drawContext *ctx, GEntity *e, VertexArray *va,
                           GLint type, bool useNormalArray, int forceColor = 0,
                           unsigned int color = 0)
    {
      if(!va || !va->getNumVertices()) return;
    
      // If we want to be enable picking of individual elements we need to
      // draw each one separately
      bool select =
        (ctx->render_mode == drawContext::GMSH_SELECT &&
         CTX::instance()->pickElements && e->model() == GModel::current());
      if(select) {
        if(va->getNumElementPointers() == va->getNumVertices()) {
          for(int i = 0; i < va->getNumVertices();
              i += va->getNumVerticesPerElement()) {
            glPushName(va->getNumVerticesPerElement());
            glPushName(i);
            glBegin(type);
            for(int j = 0; j < va->getNumVerticesPerElement(); j++)
              glVertex3fv(va->getVertexArray(3 * (i + j)));
            glEnd();
            glPopName();
            glPopName();
          }
          return;
        }
      }
    
      glVertexPointer(3, GL_FLOAT, 0, va->getVertexArray());
      glEnableClientState(GL_VERTEX_ARRAY);
    
      if(useNormalArray) {
        glEnable(GL_LIGHTING);
        glNormalPointer(NORMAL_GLTYPE, 0, va->getNormalArray());
        glEnableClientState(GL_NORMAL_ARRAY);
      }
      else
        glDisableClientState(GL_NORMAL_ARRAY);
    
      if(forceColor) {
        glDisableClientState(GL_COLOR_ARRAY);
        glColor4ubv((GLubyte *)&color);
      }
      else if(CTX::instance()->pickElements ||
              (!e->getSelection() && (CTX::instance()->mesh.colorCarousel == 0 ||
                                      CTX::instance()->mesh.colorCarousel == 3))) {
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, va->getColorArray());
        glEnableClientState(GL_COLOR_ARRAY);
      }
      else {
        glDisableClientState(GL_COLOR_ARRAY);
        color = getColorByEntity(e);
        glColor4ubv((GLubyte *)&color);
      }
    
      if(va->getNumVerticesPerElement() > 2 && CTX::instance()->polygonOffset)
        glEnable(GL_POLYGON_OFFSET_FILL);
    
      glDrawArrays(type, 0, va->getNumVertices());
    
      glDisable(GL_POLYGON_OFFSET_FILL);
      glDisable(GL_LIGHTING);
    
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_NORMAL_ARRAY);
      glDisableClientState(GL_COLOR_ARRAY);
    }
    
    // GVertex drawing routines
    
    class drawMeshGVertex {
    private:
      drawContext *_ctx;
    
    public:
      drawMeshGVertex(drawContext *ctx) : _ctx(ctx) {}
      void operator()(GVertex *v)
      {
        if(!v->getVisibility()) return;
    
        bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
                       v->model() == GModel::current());
        if(select) {
          glPushName(0);
          glPushName(v->tag());
        }
    
        glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
    
        if(CTX::instance()->mesh.points || CTX::instance()->mesh.pointsNum)
          drawVerticesPerEntity(_ctx, v);
    
        if(select) {
          glPopName();
          glPopName();
        }
      }
    };
    
    // GEdge drawing routines
    
    class drawMeshGEdge {
    private:
      drawContext *_ctx;
    
    public:
      drawMeshGEdge(drawContext *ctx) : _ctx(ctx) {}
      void operator()(GEdge *e)
      {
        if(!e->getVisibility()) {
          return;
        }
    
        bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
                       e->model() == GModel::current());
        if(select) {
          glPushName(1);
          glPushName(e->tag());
        }
    
        glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
    
        if(CTX::instance()->mesh.lines)
          drawArrays(_ctx, e, e->va_lines, GL_LINES, false);
    
        if(CTX::instance()->mesh.linesNum) drawElementLabels(_ctx, e, e->lines);
    
        if(CTX::instance()->mesh.points || CTX::instance()->mesh.pointsNum) {
          if(e->getAllElementsVisible())
            drawVerticesPerEntity(_ctx, e);
          else
            drawVerticesPerElement(_ctx, e, e->lines);
        }
    
        if(CTX::instance()->mesh.tangents) drawTangents(_ctx, e->lines);
    
        if(select) {
          glPopName();
          glPopName();
        }
      }
    };
    
    // GFace drawing routines
    
    class drawMeshGFace {
    private:
      drawContext *_ctx;
    
    public:
      drawMeshGFace(drawContext *ctx) : _ctx(ctx) {}
      void operator()(GFace *f)
      {
        if(!f->getVisibility()) {
          return;
        }
    
        bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
                       f->model() == GModel::current());
        if(select) {
          glPushName(2);
          glPushName(f->tag());
        }
    
        glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
    
        drawArrays(_ctx, f, f->va_lines, GL_LINES,
                   CTX::instance()->mesh.light && CTX::instance()->mesh.lightLines,
                   CTX::instance()->mesh.surfacesFaces,
                   CTX::instance()->color.mesh.line);
    
        if(CTX::instance()->mesh.lightTwoSide)
          glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    
        drawArrays(_ctx, f, f->va_triangles, GL_TRIANGLES,
                   CTX::instance()->mesh.light);
    
        if(CTX::instance()->mesh.surfacesNum) {
          if(CTX::instance()->mesh.triangles)
            drawElementLabels(_ctx, f, f->triangles,
                              CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          if(CTX::instance()->mesh.quadrangles)
            drawElementLabels(_ctx, f, f->quadrangles,
                              CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          drawElementLabels(_ctx, f, f->polygons,
                            CTX::instance()->mesh.surfacesFaces,
                            CTX::instance()->color.mesh.line);
        }
    
        if(CTX::instance()->mesh.points || CTX::instance()->mesh.pointsNum) {
          if(f->getAllElementsVisible())
            drawVerticesPerEntity(_ctx, f);
          else {
            if(CTX::instance()->mesh.triangles)
              drawVerticesPerElement(_ctx, f, f->triangles);
            if(CTX::instance()->mesh.quadrangles)
              drawVerticesPerElement(_ctx, f, f->quadrangles);
            drawVerticesPerElement(_ctx, f, f->polygons);
          }
        }
    
        if(CTX::instance()->mesh.normals) {
          if(CTX::instance()->mesh.triangles) drawNormals(_ctx, f->triangles);
          if(CTX::instance()->mesh.quadrangles) drawNormals(_ctx, f->quadrangles);
          drawNormals(_ctx, f->polygons);
        }
    
        if(CTX::instance()->mesh.dual) {
          if(CTX::instance()->mesh.triangles) drawBarycentricDual(f->triangles);
          if(CTX::instance()->mesh.quadrangles) drawBarycentricDual(f->quadrangles);
          drawBarycentricDual(f->polygons);
        }
        else if(CTX::instance()->mesh.voronoi) {
          if(CTX::instance()->mesh.triangles) drawVoronoiDual(f->triangles);
        }
    
        if(select) {
          glPopName();
          glPopName();
        }
      }
    };
    
    // GRegion drawing routines
    
    class drawMeshGRegion {
    private:
      drawContext *_ctx;
    
    public:
      drawMeshGRegion(drawContext *ctx) : _ctx(ctx) {}
      void operator()(GRegion *r)
      {
        if(!r->getVisibility()) return;
    
        bool select = (_ctx->render_mode == drawContext::GMSH_SELECT &&
                       r->model() == GModel::current());
        if(select) {
          glPushName(3);
          glPushName(r->tag());
        }
    
        glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
    
        drawArrays(
          _ctx, r, r->va_lines, GL_LINES,
          CTX::instance()->mesh.light && (CTX::instance()->mesh.lightLines > 1),
          CTX::instance()->mesh.volumesFaces, CTX::instance()->color.mesh.line);
    
        if(CTX::instance()->mesh.lightTwoSide)
          glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
    
        drawArrays(_ctx, r, r->va_triangles, GL_TRIANGLES,
                   CTX::instance()->mesh.light);
    
        if(CTX::instance()->mesh.volumesNum) {
          if(CTX::instance()->mesh.tetrahedra)
            drawElementLabels(_ctx, r, r->tetrahedra,
                              CTX::instance()->mesh.volumesFaces ||
                                CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          if(CTX::instance()->mesh.hexahedra)
            drawElementLabels(_ctx, r, r->hexahedra,
                              CTX::instance()->mesh.volumesFaces ||
                                CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          if(CTX::instance()->mesh.prisms)
            drawElementLabels(_ctx, r, r->prisms,
                              CTX::instance()->mesh.volumesFaces ||
                                CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          if(CTX::instance()->mesh.pyramids)
            drawElementLabels(_ctx, r, r->pyramids,
                              CTX::instance()->mesh.volumesFaces ||
                                CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          if(CTX::instance()->mesh.trihedra)
            drawElementLabels(_ctx, r, r->trihedra,
                              CTX::instance()->mesh.volumesFaces ||
                                CTX::instance()->mesh.surfacesFaces,
                              CTX::instance()->color.mesh.line);
          drawElementLabels(_ctx, r, r->polyhedra,
                            CTX::instance()->mesh.volumesFaces ||
                              CTX::instance()->mesh.surfacesFaces,
                            CTX::instance()->color.mesh.line);
        }
    
        if(CTX::instance()->mesh.points || CTX::instance()->mesh.pointsNum) {
          if(r->getAllElementsVisible())
            drawVerticesPerEntity(_ctx, r);
          else {
            if(CTX::instance()->mesh.tetrahedra)
              drawVerticesPerElement(_ctx, r, r->tetrahedra);
            if(CTX::instance()->mesh.hexahedra)
              drawVerticesPerElement(_ctx, r, r->hexahedra);
            if(CTX::instance()->mesh.prisms)
              drawVerticesPerElement(_ctx, r, r->prisms);
            if(CTX::instance()->mesh.pyramids)
              drawVerticesPerElement(_ctx, r, r->pyramids);
            if(CTX::instance()->mesh.trihedra)
              drawVerticesPerElement(_ctx, r, r->trihedra);
            drawVerticesPerElement(_ctx, r, r->polyhedra);
          }
        }
    
        if(CTX::instance()->mesh.dual) {
          if(CTX::instance()->mesh.tetrahedra) drawBarycentricDual(r->tetrahedra);
          if(CTX::instance()->mesh.hexahedra) drawBarycentricDual(r->hexahedra);
          if(CTX::instance()->mesh.prisms) drawBarycentricDual(r->prisms);
          if(CTX::instance()->mesh.pyramids) drawBarycentricDual(r->pyramids);
          if(CTX::instance()->mesh.trihedra) drawBarycentricDual(r->trihedra);
          drawBarycentricDual(r->polyhedra);
        }
    
        if(CTX::instance()->mesh.voronoi) {
          if(CTX::instance()->mesh.tetrahedra) drawVoronoiDual(r->tetrahedra);
        }
    
        if(select) {
          glPopName();
          glPopName();
        }
      }
    };
    
    static void beginFakeTransparency()
    {
      return;
      // simple additive blending "a la xpost":
      glBlendFunc(GL_SRC_ALPHA, GL_ONE); // glBlendEquation(GL_FUNC_ADD);
      // maximum intensity projection "a la volsuite":
      // glBlendFunc(GL_ONE, GL_ONE); // glBlendEquation(GL_MAX);
      glEnable(GL_BLEND);
      glDisable(GL_DEPTH_TEST);
    }
    
    static void endFakeTransparency()
    {
      return;
      glDisable(GL_BLEND);
      glEnable(GL_DEPTH_TEST);
    }
    
    // Main drawing routine
    
    void drawContext::drawMesh()
    {
      if(!CTX::instance()->mesh.draw) return;
    
      // make sure to flag any model-dependent post-processing view as
      // changed if the underlying mesh has, before resetting the changed
      // flag
      if(CTX::instance()->mesh.changed) {
        for(std::size_t i = 0; i < GModel::list.size(); i++)
          for(std::size_t j = 0; j < PView::list.size(); j++)
            if(PView::list[j]->getData()->hasModel(GModel::list[i]))
              PView::list[j]->setChanged(true);
      }
    
      glPointSize((float)CTX::instance()->mesh.pointSize);
      gl2psPointSize((float)(CTX::instance()->mesh.pointSize *
                             CTX::instance()->print.epsPointSizeFactor));
    
      glLineWidth((float)CTX::instance()->mesh.lineWidth);
      gl2psLineWidth((float)(CTX::instance()->mesh.lineWidth *
                             CTX::instance()->print.epsLineWidthFactor));
    
      if(!CTX::instance()->clipWholeElements) {
        for(int i = 0; i < 6; i++)
          if(CTX::instance()->mesh.clip & (1 << i))
            glEnable((GLenum)(GL_CLIP_PLANE0 + i));
          else
            glDisable((GLenum)(GL_CLIP_PLANE0 + i));
      }
    
      for(std::size_t i = 0; i < GModel::list.size(); i++) {
        GModel *m = GModel::list[i];
        bool changed = m->fillVertexArrays();
        if(changed) Msg::Debug("mesh vertex arrays have changed");
    #if defined(HAVE_FLTK) && defined(__APPLE__)
        // FIXME: resetting texture pile fixes bug with recent MacOS versions
        if(changed) gl_texture_pile_height(gl_texture_pile_height());
    #endif
        if(m->getVisibility() && isVisible(m)) {
          int status = m->getMeshStatus();
          if(status >= 0)
            std::for_each(m->firstVertex(), m->lastVertex(), drawMeshGVertex(this));
          if(status >= 1)
            std::for_each(m->firstEdge(), m->lastEdge(), drawMeshGEdge(this));
          if(status >= 2) {
            beginFakeTransparency();
            std::for_each(m->firstFace(), m->lastFace(), drawMeshGFace(this));
            endFakeTransparency();
          }
          if(status >= 3)
            std::for_each(m->firstRegion(), m->lastRegion(), drawMeshGRegion(this));
        }
      }
    
      CTX::instance()->mesh.changed = 0;
    
      for(int i = 0; i < 6; i++) glDisable((GLenum)(GL_CLIP_PLANE0 + i));
    }