ROOT logo
// @(#)root/gl:$Id: TGLFaceSet.cxx 26148 2008-11-11 19:58:19Z matevz $
// 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"

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

ClassImp(TGLFaceSet);

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

   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);
   {//fix for scope
   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;
   }
   }
   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);
   fNormals.resize(mesh->NumberOfPolys() * 3);
   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));
   }

   CalculateNormals();
}

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

   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
   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;
            }
         }
      }
   }
}
 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