ROOT logo
// @(#)root/gl:$Id$
// Author:  Timur Pocheptsov  03/08/2004
// NOTE: This code moved from obsoleted TGLSceneObject.h / .cxx - see these
// attic files for previous CVS history

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TGLFaceSet.h"
#include "TGLRnrCtx.h"
#include "TGLIncludes.h"

#include "TBuffer3D.h"
#include "TMath.h"

// For debug tracing
#include "TClass.h"
#include "TError.h"

#include <stdexcept>

// Clone from TGLUtil -- typedefs needed for portable tesselator function typedef.

#ifndef CALLBACK
#define CALLBACK
#endif

extern "C"
{
#if defined(__APPLE_CC__) && __APPLE_CC__ > 4000 && __APPLE_CC__ < 5450 && !defined(__INTEL_COMPILER)
    typedef GLvoid (*tessfuncptr_t)(...);
#elif defined(__mips) || defined(__linux__) || defined(__FreeBSD__) || defined( __OpenBSD__ ) || defined(__sun) || defined (__CYGWIN__) || defined (__APPLE__)
    typedef GLvoid (*tessfuncptr_t)();
#elif defined (WIN32)
    typedef GLvoid (CALLBACK *tessfuncptr_t)();
#else
    #error "Error - need to define type tessfuncptr_t for this platform/compiler"
#endif
}

//______________________________________________________________________________
//
// Implementss a native ROOT-GL representation of an arbitrary set of
// polygons.

ClassImp(TGLFaceSet);

Bool_t TGLFaceSet::fgEnforceTriangles = kFALSE;

//______________________________________________________________________________
TGLFaceSet::TGLFaceSet(const TBuffer3D & buffer) :
   TGLLogicalShape(buffer),
   fVertices(buffer.fPnts, buffer.fPnts + 3 * buffer.NbPnts()),
   fNormals(0)
{
   // constructor
   fNbPols = buffer.NbPols();

   if (fNbPols == 0) return;

   Int_t *segs = buffer.fSegs;
   Int_t *pols = buffer.fPols;

   Int_t descSize = 0;

   for (UInt_t i = 0, j = 1; i < fNbPols; ++i, ++j)
   {
      descSize += pols[j] + 1;
      j += pols[j] + 1;
   }

   fPolyDesc.resize(descSize);

   for (UInt_t numPol = 0, currInd = 0, j = 1; numPol < fNbPols; ++numPol)
   {
      Int_t segmentInd = pols[j] + j;
      Int_t segmentCol = pols[j];
      Int_t s1 = pols[segmentInd];
      segmentInd--;
      Int_t s2 = pols[segmentInd];
      segmentInd--;
      Int_t segEnds[] = {segs[s1 * 3 + 1], segs[s1 * 3 + 2],
                         segs[s2 * 3 + 1], segs[s2 * 3 + 2]};
      Int_t numPnts[3] = {0};

      if (segEnds[0] == segEnds[2]) {
         numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[3];
      } else if (segEnds[0] == segEnds[3]) {
         numPnts[0] = segEnds[1], numPnts[1] = segEnds[0], numPnts[2] = segEnds[2];
      } else if (segEnds[1] == segEnds[2]) {
         numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[3];
      } else {
         numPnts[0] = segEnds[0], numPnts[1] = segEnds[1], numPnts[2] = segEnds[2];
      }

      fPolyDesc[currInd] = 3;
      Int_t sizeInd = currInd++;
      fPolyDesc[currInd++] = numPnts[0];
      fPolyDesc[currInd++] = numPnts[1];
      fPolyDesc[currInd++] = numPnts[2];
      Int_t lastAdded = numPnts[2];

      Int_t end = j + 1;
      for (; segmentInd != end; segmentInd--) {
         segEnds[0] = segs[pols[segmentInd] * 3 + 1];
         segEnds[1] = segs[pols[segmentInd] * 3 + 2];
         if (segEnds[0] == lastAdded) {
            fPolyDesc[currInd++] = segEnds[1];
            lastAdded = segEnds[1];
         } else {
            fPolyDesc[currInd++] = segEnds[0];
            lastAdded = segEnds[0];
         }
         ++fPolyDesc[sizeInd];
      }
      j += segmentCol + 2;
   }

   if (fgEnforceTriangles) {
      EnforceTriangles();
   }
   CalculateNormals();
}

//______________________________________________________________________________
void TGLFaceSet::SetFromMesh(const RootCsg::TBaseMesh *mesh)
{
   // Should only be done on an empty faceset object
   assert(fNbPols == 0);

   UInt_t nv = mesh->NumberOfVertices();
   fVertices.reserve(3 * nv);
   UInt_t i;

   for (i = 0; i < nv; ++i) {
      const Double_t *v = mesh->GetVertex(i);
      fVertices.insert(fVertices.end(), v, v + 3);
   }

   fNbPols = mesh->NumberOfPolys();

   UInt_t descSize = 0;

   for (i = 0; i < fNbPols; ++i) descSize += mesh->SizeOfPoly(i) + 1;

   fPolyDesc.reserve(descSize);

   for (UInt_t polyIndex = 0; polyIndex < fNbPols; ++polyIndex) {
      UInt_t polySize = mesh->SizeOfPoly(polyIndex);

      fPolyDesc.push_back(polySize);

      for(i = 0; i < polySize; ++i) fPolyDesc.push_back(mesh->GetVertexIndex(polyIndex, i));
   }

   if (fgEnforceTriangles) {
      EnforceTriangles();
   }
   CalculateNormals();
}

//______________________________________________________________________________
void TGLFaceSet::EnforceTriangles()
{
   // Use GLU tesselator to replace all polygons with N > 3 with triangles.
   // After this call polygon descriptions are changed.
   // New vertices are not expected -- exception is thrown if this is
   // requested by the triangulator. Support for adding of new vertices can be
   // provided.

   class TriangleCollector
   {
   protected:
      Int_t              fNTriangles;
      Int_t              fNVertices;
      Int_t              fV0, fV1;
      GLenum             fType;
      std::vector<Int_t> fPolyDesc;

      void add_triangle(Int_t v0, Int_t v1, Int_t v2)
      {
         fPolyDesc.push_back(3);
         fPolyDesc.push_back(v0);
         fPolyDesc.push_back(v1);
         fPolyDesc.push_back(v2);
         ++fNTriangles;
      }

      void process_vertex(Int_t vi)
      {
         ++fNVertices;

         if (fV0 == -1) {
            fV0 = vi;
            return;
         }
         if (fV1 == -1) {
            fV1 = vi;
            return;
         }

         switch (fType)
         {
            case GL_TRIANGLES:
            {
               add_triangle(fV0, fV1, vi);
               fV0 = fV1 = -1;
               break;
            }
            case GL_TRIANGLE_STRIP:
            {
               if (fNVertices % 2 == 0)
                  add_triangle(fV1, fV0, vi);
               else
                  add_triangle(fV0, fV1, vi);
               fV0 = fV1;
               fV1 = vi;
               break;
            }
            case GL_TRIANGLE_FAN:
            {
               add_triangle(fV0, fV1, vi);
               fV1 = vi;
               break;
            }
            default:
            {
               throw std::runtime_error("TGLFaceSet::EnforceTriangles unexpected type in tess_vertex callback.");
            }
         }
      }

   public:
      TriangleCollector(GLUtesselator* ts) :
         fNTriangles(0), fNVertices(0), fV0(-1), fV1(-1), fType(GL_NONE)
      {
         gluTessCallback(ts, (GLenum)GLU_TESS_BEGIN_DATA,   (tessfuncptr_t) tess_begin);
         gluTessCallback(ts, (GLenum)GLU_TESS_VERTEX_DATA,  (tessfuncptr_t) tess_vertex);
         gluTessCallback(ts, (GLenum)GLU_TESS_COMBINE_DATA, (tessfuncptr_t) tess_combine);
         gluTessCallback(ts, (GLenum)GLU_TESS_END_DATA,     (tessfuncptr_t) tess_end);
      }

      Int_t               GetNTrianlges() { return fNTriangles; }
      std::vector<Int_t>& RefPolyDesc()   { return fPolyDesc; }

      static void tess_begin(GLenum type, TriangleCollector* tc)
      {
         tc->fNVertices = 0;
         tc->fV0 = tc->fV1 = -1;
         tc->fType = type;
      }

      static void tess_vertex(Int_t* vi, TriangleCollector* tc)
      {
         tc->process_vertex(*vi);
      }

      static void tess_combine(GLdouble /*coords*/[3], void* /*vertex_data*/[4], 
                               GLfloat  /*weight*/[4], void** /*outData*/, 
                               TriangleCollector* /*tc*/)
      {
         throw std::runtime_error("TGLFaceSet::EnforceTriangles tesselator requested vertex combining -- not supported yet.");
      }

      static void tess_end(TriangleCollector* tc)
      {
         tc->fType = GL_NONE;
      }
   };

   GLUtesselator *tess = gluNewTess();
   if (!tess) throw std::bad_alloc();

   TriangleCollector tc(tess);

   // Loop ...
   const Double_t *pnts = &fVertices[0];
   const Int_t    *pols = &fPolyDesc[0];

   for (UInt_t i = 0, j = 0; i < fNbPols; ++i)
   {
      Int_t npoints = pols[j++];

      gluTessBeginPolygon(tess, &tc);
      gluTessBeginContour(tess);

      for (Int_t k = 0; k < npoints; ++k, ++j)
      {
         gluTessVertex(tess, (Double_t*) pnts + pols[j] * 3, (GLvoid*) &pols[j]);
      }

      gluTessEndContour(tess);
      gluTessEndPolygon(tess);
   }

   gluDeleteTess(tess);

   fPolyDesc.swap(tc.RefPolyDesc());
   fNbPols = tc.GetNTrianlges();
}

//______________________________________________________________________________
void TGLFaceSet::DirectDraw(TGLRnrCtx & rnrCtx) const
{
   // Debug tracing
   if (gDebug > 4) {
      Info("TGLFaceSet::DirectDraw", "this %ld (class %s) LOD %d", (Long_t)this, IsA()->GetName(), rnrCtx.ShapeLOD());
   }

   if (fNbPols == 0) return;

   GLUtesselator  *tessObj = TGLUtil::GetDrawTesselator3dv();
   const Double_t *pnts = &fVertices[0];
   const Double_t *normals = &fNormals[0];
   const Int_t *pols = &fPolyDesc[0];

   for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
      Int_t npoints = pols[j++];

      if (tessObj && npoints > 4) {
         gluBeginPolygon(tessObj);
         gluNextContour(tessObj, (GLenum)GLU_UNKNOWN);
         glNormal3dv(normals + i * 3);

         for (Int_t k = 0; k < npoints; ++k, ++j) {
            gluTessVertex(tessObj, (Double_t *)pnts + pols[j] * 3, (Double_t *)pnts + pols[j] * 3);
         }
         gluEndPolygon(tessObj);
      } else {
         glBegin(GL_POLYGON);
         glNormal3dv(normals + i * 3);

         for (Int_t k = 0; k < npoints; ++k, ++j) {
            glVertex3dv(pnts + pols[j] * 3);
         }
         glEnd();
      }
   }
}

//______________________________________________________________________________
Int_t TGLFaceSet::CheckPoints(const Int_t *source, Int_t *dest) const
{
   // CheckPoints
   const Double_t * p1 = &fVertices[source[0] * 3];
   const Double_t * p2 = &fVertices[source[1] * 3];
   const Double_t * p3 = &fVertices[source[2] * 3];
   Int_t retVal = 1;

   if (Eq(p1, p2)) {
      dest[0] = source[0];
      if (!Eq(p1, p3) ) {
         dest[1] = source[2];
         retVal = 2;
      }
   } else if (Eq(p1, p3)) {
      dest[0] = source[0];
      dest[1] = source[1];
      retVal = 2;
   } else {
      dest[0] = source[0];
      dest[1] = source[1];
      retVal = 2;
      if (!Eq(p2, p3)) {
         dest[2] = source[2];
         retVal = 3;
      }
   }

   return retVal;
}

//______________________________________________________________________________
Bool_t TGLFaceSet::Eq(const Double_t *p1, const Double_t *p2)
{
   // test equality
   Double_t dx = TMath::Abs(p1[0] - p2[0]);
   Double_t dy = TMath::Abs(p1[1] - p2[1]);
   Double_t dz = TMath::Abs(p1[2] - p2[2]);
   return dx < 1e-10 && dy < 1e-10 && dz < 1e-10;
}

//______________________________________________________________________________
void TGLFaceSet::CalculateNormals()
{
   // CalculateNormals

   fNormals.resize(3 *fNbPols);
   if (fNbPols == 0) return;
   Double_t *pnts = &fVertices[0];
   for (UInt_t i = 0, j = 0; i < fNbPols; ++i) {
      Int_t polEnd = fPolyDesc[j] + j + 1;
      Int_t norm[] = {fPolyDesc[j + 1], fPolyDesc[j + 2], fPolyDesc[j + 3]};
      j += 4;
      Int_t check = CheckPoints(norm, norm), ngood = check;
      if (check == 3) {
         TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
                             pnts + norm[2] * 3, &fNormals[i * 3]);
         j = polEnd;
         continue;
      }
      while (j < (UInt_t)polEnd) {
         norm[ngood++] = fPolyDesc[j++];
         if (ngood == 3) {
            ngood = CheckPoints(norm, norm);
            if (ngood == 3) {
               TMath::Normal2Plane(pnts + norm[0] * 3, pnts + norm[1] * 3,
                                   pnts + norm[2] * 3, &fNormals[i * 3]);
               j = polEnd;
               break;
            }
         }
      }
   }
}

//______________________________________________________________________________
Bool_t TGLFaceSet::GetEnforceTriangles()
{
   // Get current state of static flag EnforceTriangles.

   return fgEnforceTriangles;
}

//______________________________________________________________________________
void TGLFaceSet::SetEnforceTriangles(Bool_t e)
{
   // Set state of static flag EnforceTriangles.
   // When this is set, all tesselations will be automatically converted into
   // triangle-only meshes.
   // This is needed to export TGeo shapes and CSG meshes to external
   // triangle-mesh libraries that can not handle arbitrary polygons.

   fgEnforceTriangles = e;
}
 TGLFaceSet.cxx:1
 TGLFaceSet.cxx:2
 TGLFaceSet.cxx:3
 TGLFaceSet.cxx:4
 TGLFaceSet.cxx:5
 TGLFaceSet.cxx:6
 TGLFaceSet.cxx:7
 TGLFaceSet.cxx:8
 TGLFaceSet.cxx:9
 TGLFaceSet.cxx:10
 TGLFaceSet.cxx:11
 TGLFaceSet.cxx:12
 TGLFaceSet.cxx:13
 TGLFaceSet.cxx:14
 TGLFaceSet.cxx:15
 TGLFaceSet.cxx:16
 TGLFaceSet.cxx:17
 TGLFaceSet.cxx:18
 TGLFaceSet.cxx:19
 TGLFaceSet.cxx:20
 TGLFaceSet.cxx:21
 TGLFaceSet.cxx:22
 TGLFaceSet.cxx:23
 TGLFaceSet.cxx:24
 TGLFaceSet.cxx:25
 TGLFaceSet.cxx:26
 TGLFaceSet.cxx:27
 TGLFaceSet.cxx:28
 TGLFaceSet.cxx:29
 TGLFaceSet.cxx:30
 TGLFaceSet.cxx:31
 TGLFaceSet.cxx:32
 TGLFaceSet.cxx:33
 TGLFaceSet.cxx:34
 TGLFaceSet.cxx:35
 TGLFaceSet.cxx:36
 TGLFaceSet.cxx:37
 TGLFaceSet.cxx:38
 TGLFaceSet.cxx:39
 TGLFaceSet.cxx:40
 TGLFaceSet.cxx:41
 TGLFaceSet.cxx:42
 TGLFaceSet.cxx:43
 TGLFaceSet.cxx:44
 TGLFaceSet.cxx:45
 TGLFaceSet.cxx:46
 TGLFaceSet.cxx:47
 TGLFaceSet.cxx:48
 TGLFaceSet.cxx:49
 TGLFaceSet.cxx:50
 TGLFaceSet.cxx:51
 TGLFaceSet.cxx:52
 TGLFaceSet.cxx:53
 TGLFaceSet.cxx:54
 TGLFaceSet.cxx:55
 TGLFaceSet.cxx:56
 TGLFaceSet.cxx:57
 TGLFaceSet.cxx:58
 TGLFaceSet.cxx:59
 TGLFaceSet.cxx:60
 TGLFaceSet.cxx:61
 TGLFaceSet.cxx:62
 TGLFaceSet.cxx:63
 TGLFaceSet.cxx:64
 TGLFaceSet.cxx:65
 TGLFaceSet.cxx:66
 TGLFaceSet.cxx:67
 TGLFaceSet.cxx:68
 TGLFaceSet.cxx:69
 TGLFaceSet.cxx:70
 TGLFaceSet.cxx:71
 TGLFaceSet.cxx:72
 TGLFaceSet.cxx:73
 TGLFaceSet.cxx:74
 TGLFaceSet.cxx:75
 TGLFaceSet.cxx:76
 TGLFaceSet.cxx:77
 TGLFaceSet.cxx:78
 TGLFaceSet.cxx:79
 TGLFaceSet.cxx:80
 TGLFaceSet.cxx:81
 TGLFaceSet.cxx:82
 TGLFaceSet.cxx:83
 TGLFaceSet.cxx:84
 TGLFaceSet.cxx:85
 TGLFaceSet.cxx:86
 TGLFaceSet.cxx:87
 TGLFaceSet.cxx:88
 TGLFaceSet.cxx:89
 TGLFaceSet.cxx:90
 TGLFaceSet.cxx:91
 TGLFaceSet.cxx:92
 TGLFaceSet.cxx:93
 TGLFaceSet.cxx:94
 TGLFaceSet.cxx:95
 TGLFaceSet.cxx:96
 TGLFaceSet.cxx:97
 TGLFaceSet.cxx:98
 TGLFaceSet.cxx:99
 TGLFaceSet.cxx:100
 TGLFaceSet.cxx:101
 TGLFaceSet.cxx:102
 TGLFaceSet.cxx:103
 TGLFaceSet.cxx:104
 TGLFaceSet.cxx:105
 TGLFaceSet.cxx:106
 TGLFaceSet.cxx:107
 TGLFaceSet.cxx:108
 TGLFaceSet.cxx:109
 TGLFaceSet.cxx:110
 TGLFaceSet.cxx:111
 TGLFaceSet.cxx:112
 TGLFaceSet.cxx:113
 TGLFaceSet.cxx:114
 TGLFaceSet.cxx:115
 TGLFaceSet.cxx:116
 TGLFaceSet.cxx:117
 TGLFaceSet.cxx:118
 TGLFaceSet.cxx:119
 TGLFaceSet.cxx:120
 TGLFaceSet.cxx:121
 TGLFaceSet.cxx:122
 TGLFaceSet.cxx:123
 TGLFaceSet.cxx:124
 TGLFaceSet.cxx:125
 TGLFaceSet.cxx:126
 TGLFaceSet.cxx:127
 TGLFaceSet.cxx:128
 TGLFaceSet.cxx:129
 TGLFaceSet.cxx:130
 TGLFaceSet.cxx:131
 TGLFaceSet.cxx:132
 TGLFaceSet.cxx:133
 TGLFaceSet.cxx:134
 TGLFaceSet.cxx:135
 TGLFaceSet.cxx:136
 TGLFaceSet.cxx:137
 TGLFaceSet.cxx:138
 TGLFaceSet.cxx:139
 TGLFaceSet.cxx:140
 TGLFaceSet.cxx:141
 TGLFaceSet.cxx:142
 TGLFaceSet.cxx:143
 TGLFaceSet.cxx:144
 TGLFaceSet.cxx:145
 TGLFaceSet.cxx:146
 TGLFaceSet.cxx:147
 TGLFaceSet.cxx:148
 TGLFaceSet.cxx:149
 TGLFaceSet.cxx:150
 TGLFaceSet.cxx:151
 TGLFaceSet.cxx:152
 TGLFaceSet.cxx:153
 TGLFaceSet.cxx:154
 TGLFaceSet.cxx:155
 TGLFaceSet.cxx:156
 TGLFaceSet.cxx:157
 TGLFaceSet.cxx:158
 TGLFaceSet.cxx:159
 TGLFaceSet.cxx:160
 TGLFaceSet.cxx:161
 TGLFaceSet.cxx:162
 TGLFaceSet.cxx:163
 TGLFaceSet.cxx:164
 TGLFaceSet.cxx:165
 TGLFaceSet.cxx:166
 TGLFaceSet.cxx:167
 TGLFaceSet.cxx:168
 TGLFaceSet.cxx:169
 TGLFaceSet.cxx:170
 TGLFaceSet.cxx:171
 TGLFaceSet.cxx:172
 TGLFaceSet.cxx:173
 TGLFaceSet.cxx:174
 TGLFaceSet.cxx:175
 TGLFaceSet.cxx:176
 TGLFaceSet.cxx:177
 TGLFaceSet.cxx:178
 TGLFaceSet.cxx:179
 TGLFaceSet.cxx:180
 TGLFaceSet.cxx:181
 TGLFaceSet.cxx:182
 TGLFaceSet.cxx:183
 TGLFaceSet.cxx:184
 TGLFaceSet.cxx:185
 TGLFaceSet.cxx:186
 TGLFaceSet.cxx:187
 TGLFaceSet.cxx:188
 TGLFaceSet.cxx:189
 TGLFaceSet.cxx:190
 TGLFaceSet.cxx:191
 TGLFaceSet.cxx:192
 TGLFaceSet.cxx:193
 TGLFaceSet.cxx:194
 TGLFaceSet.cxx:195
 TGLFaceSet.cxx:196
 TGLFaceSet.cxx:197
 TGLFaceSet.cxx:198
 TGLFaceSet.cxx:199
 TGLFaceSet.cxx:200
 TGLFaceSet.cxx:201
 TGLFaceSet.cxx:202
 TGLFaceSet.cxx:203
 TGLFaceSet.cxx:204
 TGLFaceSet.cxx:205
 TGLFaceSet.cxx:206
 TGLFaceSet.cxx:207
 TGLFaceSet.cxx:208
 TGLFaceSet.cxx:209
 TGLFaceSet.cxx:210
 TGLFaceSet.cxx:211
 TGLFaceSet.cxx:212
 TGLFaceSet.cxx:213
 TGLFaceSet.cxx:214
 TGLFaceSet.cxx:215
 TGLFaceSet.cxx:216
 TGLFaceSet.cxx:217
 TGLFaceSet.cxx:218
 TGLFaceSet.cxx:219
 TGLFaceSet.cxx:220
 TGLFaceSet.cxx:221
 TGLFaceSet.cxx:222
 TGLFaceSet.cxx:223
 TGLFaceSet.cxx:224
 TGLFaceSet.cxx:225
 TGLFaceSet.cxx:226
 TGLFaceSet.cxx:227
 TGLFaceSet.cxx:228
 TGLFaceSet.cxx:229
 TGLFaceSet.cxx:230
 TGLFaceSet.cxx:231
 TGLFaceSet.cxx:232
 TGLFaceSet.cxx:233
 TGLFaceSet.cxx:234
 TGLFaceSet.cxx:235
 TGLFaceSet.cxx:236
 TGLFaceSet.cxx:237
 TGLFaceSet.cxx:238
 TGLFaceSet.cxx:239
 TGLFaceSet.cxx:240
 TGLFaceSet.cxx:241
 TGLFaceSet.cxx:242
 TGLFaceSet.cxx:243
 TGLFaceSet.cxx:244
 TGLFaceSet.cxx:245
 TGLFaceSet.cxx:246
 TGLFaceSet.cxx:247
 TGLFaceSet.cxx:248
 TGLFaceSet.cxx:249
 TGLFaceSet.cxx:250
 TGLFaceSet.cxx:251
 TGLFaceSet.cxx:252
 TGLFaceSet.cxx:253
 TGLFaceSet.cxx:254
 TGLFaceSet.cxx:255
 TGLFaceSet.cxx:256
 TGLFaceSet.cxx:257
 TGLFaceSet.cxx:258
 TGLFaceSet.cxx:259
 TGLFaceSet.cxx:260
 TGLFaceSet.cxx:261
 TGLFaceSet.cxx:262
 TGLFaceSet.cxx:263
 TGLFaceSet.cxx:264
 TGLFaceSet.cxx:265
 TGLFaceSet.cxx:266
 TGLFaceSet.cxx:267
 TGLFaceSet.cxx:268
 TGLFaceSet.cxx:269
 TGLFaceSet.cxx:270
 TGLFaceSet.cxx:271
 TGLFaceSet.cxx:272
 TGLFaceSet.cxx:273
 TGLFaceSet.cxx:274
 TGLFaceSet.cxx:275
 TGLFaceSet.cxx:276
 TGLFaceSet.cxx:277
 TGLFaceSet.cxx:278
 TGLFaceSet.cxx:279
 TGLFaceSet.cxx:280
 TGLFaceSet.cxx:281
 TGLFaceSet.cxx:282
 TGLFaceSet.cxx:283
 TGLFaceSet.cxx:284
 TGLFaceSet.cxx:285
 TGLFaceSet.cxx:286
 TGLFaceSet.cxx:287
 TGLFaceSet.cxx:288
 TGLFaceSet.cxx:289
 TGLFaceSet.cxx:290
 TGLFaceSet.cxx:291
 TGLFaceSet.cxx:292
 TGLFaceSet.cxx:293
 TGLFaceSet.cxx:294
 TGLFaceSet.cxx:295
 TGLFaceSet.cxx:296
 TGLFaceSet.cxx:297
 TGLFaceSet.cxx:298
 TGLFaceSet.cxx:299
 TGLFaceSet.cxx:300
 TGLFaceSet.cxx:301
 TGLFaceSet.cxx:302
 TGLFaceSet.cxx:303
 TGLFaceSet.cxx:304
 TGLFaceSet.cxx:305
 TGLFaceSet.cxx:306
 TGLFaceSet.cxx:307
 TGLFaceSet.cxx:308
 TGLFaceSet.cxx:309
 TGLFaceSet.cxx:310
 TGLFaceSet.cxx:311
 TGLFaceSet.cxx:312
 TGLFaceSet.cxx:313
 TGLFaceSet.cxx:314
 TGLFaceSet.cxx:315
 TGLFaceSet.cxx:316
 TGLFaceSet.cxx:317
 TGLFaceSet.cxx:318
 TGLFaceSet.cxx:319
 TGLFaceSet.cxx:320
 TGLFaceSet.cxx:321
 TGLFaceSet.cxx:322
 TGLFaceSet.cxx:323
 TGLFaceSet.cxx:324
 TGLFaceSet.cxx:325
 TGLFaceSet.cxx:326
 TGLFaceSet.cxx:327
 TGLFaceSet.cxx:328
 TGLFaceSet.cxx:329
 TGLFaceSet.cxx:330
 TGLFaceSet.cxx:331
 TGLFaceSet.cxx:332
 TGLFaceSet.cxx:333
 TGLFaceSet.cxx:334
 TGLFaceSet.cxx:335
 TGLFaceSet.cxx:336
 TGLFaceSet.cxx:337
 TGLFaceSet.cxx:338
 TGLFaceSet.cxx:339
 TGLFaceSet.cxx:340
 TGLFaceSet.cxx:341
 TGLFaceSet.cxx:342
 TGLFaceSet.cxx:343
 TGLFaceSet.cxx:344
 TGLFaceSet.cxx:345
 TGLFaceSet.cxx:346
 TGLFaceSet.cxx:347
 TGLFaceSet.cxx:348
 TGLFaceSet.cxx:349
 TGLFaceSet.cxx:350
 TGLFaceSet.cxx:351
 TGLFaceSet.cxx:352
 TGLFaceSet.cxx:353
 TGLFaceSet.cxx:354
 TGLFaceSet.cxx:355
 TGLFaceSet.cxx:356
 TGLFaceSet.cxx:357
 TGLFaceSet.cxx:358
 TGLFaceSet.cxx:359
 TGLFaceSet.cxx:360
 TGLFaceSet.cxx:361
 TGLFaceSet.cxx:362
 TGLFaceSet.cxx:363
 TGLFaceSet.cxx:364
 TGLFaceSet.cxx:365
 TGLFaceSet.cxx:366
 TGLFaceSet.cxx:367
 TGLFaceSet.cxx:368
 TGLFaceSet.cxx:369
 TGLFaceSet.cxx:370
 TGLFaceSet.cxx:371
 TGLFaceSet.cxx:372
 TGLFaceSet.cxx:373
 TGLFaceSet.cxx:374
 TGLFaceSet.cxx:375
 TGLFaceSet.cxx:376
 TGLFaceSet.cxx:377
 TGLFaceSet.cxx:378
 TGLFaceSet.cxx:379
 TGLFaceSet.cxx:380
 TGLFaceSet.cxx:381
 TGLFaceSet.cxx:382
 TGLFaceSet.cxx:383
 TGLFaceSet.cxx:384
 TGLFaceSet.cxx:385
 TGLFaceSet.cxx:386
 TGLFaceSet.cxx:387
 TGLFaceSet.cxx:388
 TGLFaceSet.cxx:389
 TGLFaceSet.cxx:390
 TGLFaceSet.cxx:391
 TGLFaceSet.cxx:392
 TGLFaceSet.cxx:393
 TGLFaceSet.cxx:394
 TGLFaceSet.cxx:395
 TGLFaceSet.cxx:396
 TGLFaceSet.cxx:397
 TGLFaceSet.cxx:398
 TGLFaceSet.cxx:399
 TGLFaceSet.cxx:400
 TGLFaceSet.cxx:401
 TGLFaceSet.cxx:402
 TGLFaceSet.cxx:403
 TGLFaceSet.cxx:404
 TGLFaceSet.cxx:405
 TGLFaceSet.cxx:406
 TGLFaceSet.cxx:407
 TGLFaceSet.cxx:408
 TGLFaceSet.cxx:409
 TGLFaceSet.cxx:410
 TGLFaceSet.cxx:411
 TGLFaceSet.cxx:412
 TGLFaceSet.cxx:413
 TGLFaceSet.cxx:414
 TGLFaceSet.cxx:415
 TGLFaceSet.cxx:416
 TGLFaceSet.cxx:417
 TGLFaceSet.cxx:418
 TGLFaceSet.cxx:419
 TGLFaceSet.cxx:420
 TGLFaceSet.cxx:421
 TGLFaceSet.cxx:422
 TGLFaceSet.cxx:423
 TGLFaceSet.cxx:424
 TGLFaceSet.cxx:425
 TGLFaceSet.cxx:426
 TGLFaceSet.cxx:427
 TGLFaceSet.cxx:428
 TGLFaceSet.cxx:429
 TGLFaceSet.cxx:430
 TGLFaceSet.cxx:431
 TGLFaceSet.cxx:432
 TGLFaceSet.cxx:433
 TGLFaceSet.cxx:434
 TGLFaceSet.cxx:435
 TGLFaceSet.cxx:436
 TGLFaceSet.cxx:437
 TGLFaceSet.cxx:438
 TGLFaceSet.cxx:439
 TGLFaceSet.cxx:440