TEveBoxSetGL.cxx

Go to the documentation of this file.
00001 // @(#)root/eve:$Id: TEveBoxSetGL.cxx 37398 2010-12-08 13:55:30Z matevz $
00002 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TEveBoxSetGL.h"
00013 #include "TEveBoxSet.h"
00014 #include "TEveFrameBoxGL.h"
00015 
00016 #include "TGLIncludes.h"
00017 #include "TGLRnrCtx.h"
00018 #include "TGLSelectRecord.h"
00019 #include "TGLQuadric.h"
00020 
00021 //==============================================================================
00022 //==============================================================================
00023 // TEveBoxSetGL
00024 //==============================================================================
00025 
00026 //______________________________________________________________________________
00027 //
00028 // A GL rendering class for TEveBoxSet.
00029 //
00030 
00031 ClassImp(TEveBoxSetGL);
00032 
00033 //______________________________________________________________________________
00034 TEveBoxSetGL::TEveBoxSetGL() : TEveDigitSetGL(), fM(0), fBoxDL(0)
00035 {
00036    // Default constructor.
00037 
00038    // fDLCache = false; // Disable display list.
00039    fMultiColor = kTRUE;
00040 }
00041 
00042 //______________________________________________________________________________
00043 TEveBoxSetGL::~TEveBoxSetGL()
00044 {
00045    // Destructor.
00046 
00047    DLCachePurge();
00048 }
00049 
00050 /******************************************************************************/
00051 // Protected methods
00052 /******************************************************************************/
00053 
00054 //______________________________________________________________________________
00055 Int_t TEveBoxSetGL::PrimitiveType() const
00056 {
00057    // Return GL primitive used to render the boxes, based on the
00058    // render-mode specified in the model object.
00059 
00060    return (fM->fRenderMode != TEveDigitSet::kRM_Line) ? GL_QUADS : GL_LINE_LOOP;
00061 }
00062 
00063 //______________________________________________________________________________
00064 void TEveBoxSetGL::MakeOriginBox(Float_t p[8][3], Float_t dx, Float_t dy, Float_t dz) const
00065 {
00066    // Fill array p to represent a box (0,0,0) - (dx,dy,dz).
00067 
00068    // bottom
00069    p[0][0] = 0;  p[0][1] = dy; p[0][2] = 0;
00070    p[1][0] = dx; p[1][1] = dy; p[1][2] = 0;
00071    p[2][0] = dx; p[2][1] = 0;  p[2][2] = 0;
00072    p[3][0] = 0;  p[3][1] = 0;  p[3][2] = 0;
00073    // top
00074    p[4][0] = 0;  p[4][1] = dy; p[4][2] = dz;
00075    p[5][0] = dx; p[5][1] = dy; p[5][2] = dz;
00076    p[6][0] = dx; p[6][1] = 0;  p[6][2] = dz;
00077    p[7][0] = 0;  p[7][1] = 0;  p[7][2] = dz;
00078 }
00079 
00080 //______________________________________________________________________________
00081 inline void TEveBoxSetGL::RenderBoxStdNorm(const Float_t p[8][3]) const
00082 {
00083    // Render a box specified by points in array p with standard
00084    // axis-aligned normals.
00085 
00086    // bottom: 0123
00087    glNormal3f(0, 0, -1);
00088    glVertex3fv(p[0]);  glVertex3fv(p[1]);
00089    glVertex3fv(p[2]);  glVertex3fv(p[3]);
00090    // top:    7654
00091    glNormal3f(0, 0, 1);
00092    glVertex3fv(p[7]); glVertex3fv(p[6]);
00093    glVertex3fv(p[5]); glVertex3fv(p[4]);
00094    // back:  0451
00095    glNormal3f(0, 1, 0);
00096    glVertex3fv(p[0]); glVertex3fv(p[4]);
00097    glVertex3fv(p[5]); glVertex3fv(p[1]);
00098    // front:   3267
00099    glNormal3f(0, -1, 0);
00100    glVertex3fv(p[3]);  glVertex3fv(p[2]);
00101    glVertex3fv(p[6]);  glVertex3fv(p[7]);
00102    // left:    0374
00103    glNormal3f(-1, 0, 0);
00104    glVertex3fv(p[0]);  glVertex3fv(p[3]);
00105    glVertex3fv(p[7]);  glVertex3fv(p[4]);
00106    // right:   1562
00107    glNormal3f(1, 0, 0);
00108    glVertex3fv(p[1]);  glVertex3fv(p[5]);
00109    glVertex3fv(p[6]);  glVertex3fv(p[2]);
00110 }
00111 
00112 namespace
00113 {
00114    void subtract_and_normalize(const Float_t a[3], const Float_t b[3],
00115                                Float_t o[3])
00116    {
00117       // Calculate a - b and normalize the result.
00118       o[0] = a[0] - b[0];
00119       o[1] = a[1] - b[1];
00120       o[2] = a[2] - b[2];
00121       Float_t d = sqrtf(o[0]*o[0] + o[1]*o[1] + o[2]*o[2]);
00122       if (d != 0)
00123       {
00124          d = 1.0f / d;
00125          o[0] *= d;
00126          o[1] *= d;
00127          o[2] *= d;
00128       }
00129    }
00130 }
00131 //______________________________________________________________________________
00132 void TEveBoxSetGL::RenderBoxAutoNorm(const Float_t p[8][3]) const
00133 {
00134    // Render box, calculate normals on the fly from first three points.
00135 
00136    Float_t e[6][3], n[3];
00137    subtract_and_normalize(p[1], p[0], e[0]);
00138    subtract_and_normalize(p[3], p[0], e[1]);
00139    subtract_and_normalize(p[4], p[0], e[2]);
00140    subtract_and_normalize(p[5], p[6], e[3]);
00141    subtract_and_normalize(p[7], p[6], e[4]);
00142    subtract_and_normalize(p[2], p[6], e[5]);
00143 
00144    // bottom: 0123
00145    glNormal3fv(TMath::Cross(e[0], e[1], n));
00146    glVertex3fv(p[0]); glVertex3fv(p[1]);
00147    glVertex3fv(p[2]); glVertex3fv(p[3]);
00148    // top:    7654
00149    glNormal3fv(TMath::Cross(e[3], e[4], n));
00150    glVertex3fv(p[7]); glVertex3fv(p[6]);
00151    glVertex3fv(p[5]); glVertex3fv(p[4]);
00152    // back:  0451
00153    glNormal3fv(TMath::Cross(e[2], e[0], n));
00154    glVertex3fv(p[0]); glVertex3fv(p[4]);
00155    glVertex3fv(p[5]); glVertex3fv(p[1]);
00156    // front:   3267
00157    glNormal3fv(TMath::Cross(e[4], e[5], n));
00158    glVertex3fv(p[3]); glVertex3fv(p[2]);
00159    glVertex3fv(p[6]); glVertex3fv(p[7]);
00160    // left:    0374
00161    glNormal3fv(TMath::Cross(e[1], e[2], n));
00162    glVertex3fv(p[0]); glVertex3fv(p[3]);
00163    glVertex3fv(p[7]); glVertex3fv(p[4]);
00164    // right:   1562
00165    glNormal3fv(TMath::Cross(e[5], e[3], n));
00166    glVertex3fv(p[1]); glVertex3fv(p[5]);
00167    glVertex3fv(p[6]); glVertex3fv(p[2]);
00168 }
00169 
00170 //______________________________________________________________________________
00171 void TEveBoxSetGL::MakeDisplayList() const
00172 {
00173    // Create a display-list for rendering a single box, based on the
00174    // current box-type.
00175    // Some box-types don't benefit from the display-list rendering and
00176    // so display-list is not created.
00177 
00178    if (fM->fBoxType == TEveBoxSet::kBT_AABox         ||
00179        fM->fBoxType == TEveBoxSet::kBT_AABoxFixedDim ||
00180        fM->fBoxType == TEveBoxSet::kBT_Cone          ||
00181        fM->fBoxType == TEveBoxSet::kBT_EllipticCone)
00182    {
00183       if (fBoxDL == 0)
00184          fBoxDL = glGenLists(1);
00185 
00186       glNewList(fBoxDL, GL_COMPILE);
00187 
00188       if (fM->fBoxType < TEveBoxSet::kBT_Cone)
00189       {
00190          glBegin(PrimitiveType());
00191          Float_t p[8][3];
00192          if (fM->fBoxType == TEveBoxSet::kBT_AABox)
00193             MakeOriginBox(p, 1.0f, 1.0f, 1.0f);
00194          else
00195             MakeOriginBox(p, fM->fDefWidth, fM->fDefHeight, fM->fDefDepth);
00196          RenderBoxStdNorm(p);
00197          glEnd();
00198       }
00199       else
00200       {
00201          static TGLQuadric quad;
00202          Int_t nt = 15; // number of corners
00203          gluCylinder(quad.Get(), 0, 1, 1, nt, 1);
00204 
00205          if (fM->fDrawConeCap)
00206          {
00207             glPushMatrix();
00208             glTranslatef(0, 0, 1);
00209             gluDisk(quad.Get(), 0, 1, nt, 1);
00210             glPopMatrix();
00211          }
00212       }
00213 
00214       glEndList();
00215    }
00216 }
00217 
00218 /******************************************************************************/
00219 // Virtuals from base-classes
00220 /******************************************************************************/
00221 
00222 //______________________________________________________________________________
00223 Bool_t TEveBoxSetGL::ShouldDLCache(const TGLRnrCtx& rnrCtx) const
00224 {
00225    // Determines if display-list will be used for rendering.
00226    // Virtual from TGLLogicalShape.
00227 
00228    MakeDisplayList();
00229 
00230    return TEveDigitSetGL::ShouldDLCache(rnrCtx);
00231 }
00232 
00233 //______________________________________________________________________________
00234 void TEveBoxSetGL::DLCacheDrop()
00235 {
00236    // Called when display lists have been destroyed externally and the
00237    // internal display-list data needs to be cleare.
00238    // Virtual from TGLLogicalShape.
00239 
00240    fBoxDL = 0;
00241    TGLObject::DLCacheDrop();
00242 }
00243 
00244 //______________________________________________________________________________
00245 void TEveBoxSetGL::DLCachePurge()
00246 {
00247    // Called when display-lists need to be returned to the system.
00248    // Virtual from TGLLogicalShape.
00249 
00250    if (fBoxDL != 0)
00251    {
00252       PurgeDLRange(fBoxDL, 1);
00253       fBoxDL = 0;
00254    }
00255    TGLObject::DLCachePurge();
00256 }
00257 
00258 /******************************************************************************/
00259 
00260 //______________________________________________________________________________
00261 Bool_t TEveBoxSetGL::SetModel(TObject* obj, const Option_t* /*opt*/)
00262 {
00263    // Set model object.
00264    // Virtual from TGLObject.
00265 
00266    fM = SetModelDynCast<TEveBoxSet>(obj);
00267    return kTRUE;
00268 }
00269 
00270 /******************************************************************************/
00271 
00272 namespace
00273 {
00274   inline void AntiFlick(Float_t x, Float_t y, Float_t z)
00275   {
00276      // Render anti-flickering point.
00277      glBegin(GL_POINTS);
00278      glVertex3f(x, y, z);
00279      glEnd();
00280   }
00281 }
00282 
00283 /******************************************************************************/
00284 
00285 //______________________________________________________________________________
00286 void TEveBoxSetGL::RenderBoxes(TGLRnrCtx& rnrCtx) const
00287 {
00288    // GL rendering for all box-types.
00289 
00290    static const TEveException eH("TEveBoxSetGL::RenderBoxes ");
00291 
00292    if (rnrCtx.SecSelection()) glPushName(0);
00293 
00294    Int_t boxSkip = 0;
00295    if (rnrCtx.ShapeLOD() < 50)
00296       boxSkip = 6 - (rnrCtx.ShapeLOD()+1)/10;
00297 
00298    TEveChunkManager::iterator bi(fM->fPlex);
00299    if (rnrCtx.Highlight() && fHighlightSet)
00300       bi.fSelection = fHighlightSet;
00301 
00302    switch (fM->fBoxType)
00303    {
00304 
00305       case TEveBoxSet::kBT_FreeBox:
00306       {
00307          GLenum primitiveType = PrimitiveType();
00308          while (bi.next())
00309          {
00310             TEveBoxSet::BFreeBox_t& b = * (TEveBoxSet::BFreeBox_t*) bi();
00311             if (SetupColor(b))
00312             {
00313                if (rnrCtx.SecSelection()) glLoadName(bi.index());
00314                glBegin(primitiveType);
00315                RenderBoxAutoNorm(b.fVertices);
00316                glEnd();
00317                if (fM->fAntiFlick)
00318                   AntiFlick(0.5f*(b.fVertices[0][0] + b.fVertices[6][0]),
00319                             0.5f*(b.fVertices[0][1] + b.fVertices[6][1]),
00320                             0.5f*(b.fVertices[0][2] + b.fVertices[6][2]));
00321             }
00322             if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
00323          }
00324          break;
00325       } // end case free-box
00326 
00327       case TEveBoxSet::kBT_AABox:
00328       {
00329          glEnable(GL_NORMALIZE);
00330          while (bi.next())
00331          {
00332             TEveBoxSet::BAABox_t& b = * (TEveBoxSet::BAABox_t*) bi();
00333             if (SetupColor(b))
00334             {
00335                if (rnrCtx.SecSelection()) glLoadName(bi.index());
00336                glPushMatrix();
00337                glTranslatef(b.fA, b.fB, b.fC);
00338                glScalef    (b.fW, b.fH, b.fD);
00339                glCallList(fBoxDL);
00340                if (fM->fAntiFlick)
00341                   AntiFlick(0.5f, 0.5f, 0.5f);
00342                glPopMatrix();
00343             }
00344             if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
00345          }
00346          break;
00347       }
00348 
00349       case TEveBoxSet::kBT_AABoxFixedDim:
00350       {
00351          while (bi.next())
00352          {
00353             TEveBoxSet::BAABoxFixedDim_t& b = * (TEveBoxSet::BAABoxFixedDim_t*) bi();
00354             if (SetupColor(b))
00355             {
00356                if (rnrCtx.SecSelection()) glLoadName(bi.index());
00357                glTranslatef(b.fA, b.fB, b.fC);
00358                glCallList(fBoxDL);
00359                if (fM->fAntiFlick)
00360                   AntiFlick(0.5f*fM->fDefWidth, 0.5f*fM->fDefHeight, 0.5f*fM->fDefDepth);
00361                glTranslatef(-b.fA, -b.fB, -b.fC);
00362             }
00363             if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
00364          }
00365          break;
00366       }
00367 
00368       case TEveBoxSet::kBT_Cone:
00369       {
00370          using namespace TMath;
00371 
00372          glEnable(GL_NORMALIZE);
00373          Float_t theta=0, phi=0, h=0;
00374          while (bi.next())
00375          {
00376             TEveBoxSet::BCone_t& b = * (TEveBoxSet::BCone_t*) bi();
00377             if (SetupColor(b))
00378             {
00379                if (rnrCtx.SecSelection()) glLoadName(bi.index());
00380                h     = b.fDir.Mag();
00381                phi   = ATan2(b.fDir.fY, b.fDir.fX)*RadToDeg();
00382                theta = ATan (b.fDir.fZ / Sqrt(b.fDir.fX*b.fDir.fX + b.fDir.fY*b.fDir.fY))*RadToDeg();
00383                glPushMatrix();
00384                glTranslatef(b.fPos.fX, b.fPos.fY, b.fPos.fZ);
00385                glRotatef(phi,        0, 0, 1);
00386                glRotatef(90 - theta, 0, 1, 0);
00387                glScalef (b.fR, b.fR, h);
00388                glCallList(fBoxDL);
00389                if (fM->fAntiFlick)
00390                   AntiFlick(0.0f, 0.0f, 0.5f);
00391                glPopMatrix();
00392             }
00393             if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
00394          }
00395          break;
00396       }
00397 
00398       case TEveBoxSet::kBT_EllipticCone:
00399       {
00400          using namespace TMath;
00401 
00402          glEnable(GL_NORMALIZE);
00403          Float_t theta=0, phi=0, h=0;
00404          while (bi.next())
00405          {
00406             TEveBoxSet::BEllipticCone_t& b = * (TEveBoxSet::BEllipticCone_t*) bi();
00407             if (SetupColor(b))
00408             {
00409                if (rnrCtx.SecSelection()) glLoadName(bi.index());
00410                h     = b.fDir.Mag();
00411                phi   = ATan2(b.fDir.fY, b.fDir.fX)*RadToDeg();
00412                theta = ATan (b.fDir.fZ / Sqrt(b.fDir.fX*b.fDir.fX + b.fDir.fY*b.fDir.fY))*RadToDeg();
00413                glPushMatrix();
00414                glTranslatef(b.fPos.fX, b.fPos.fY, b.fPos.fZ);
00415                glRotatef(phi,        0, 0, 1);
00416                glRotatef(90 - theta, 0, 1, 0);
00417                glRotatef(b.fAngle,   0, 0, 1);
00418                glScalef (b.fR, b.fR2, h);
00419                glCallList(fBoxDL);
00420                if (fM->fAntiFlick)
00421                   AntiFlick(0.0f, 0.0f, 0.5f);
00422                glPopMatrix();
00423             }
00424             if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
00425          }
00426          break;
00427       }
00428 
00429       default:
00430       {
00431          throw(eH + "unsupported box-type.");
00432       }
00433 
00434    } // end switch box-type
00435 
00436    if (rnrCtx.SecSelection()) glPopName();
00437 }
00438 
00439 //______________________________________________________________________________
00440 void TEveBoxSetGL::DirectDraw(TGLRnrCtx& rnrCtx) const
00441 {
00442    // Actual rendering code.
00443    // Virtual from TGLLogicalShape.
00444 
00445    TEveBoxSet& mB = * fM;
00446    // printf("TEveBoxSetGL::DirectDraw N boxes %d\n", mB.fPlex.Size());
00447 
00448    if (mB.fPlex.Size() > 0)
00449    {
00450       if (! mB.fSingleColor && ! mB.fValueIsColor && mB.fPalette == 0)
00451       {
00452          mB.AssertPalette();
00453       }
00454 
00455       glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
00456 
00457       if ( ! rnrCtx.IsDrawPassOutlineLine())
00458       {
00459          if (mB.fRenderMode == TEveDigitSet::kRM_Fill)
00460             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00461          else if (mB.fRenderMode == TEveDigitSet::kRM_Line)
00462             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00463       }
00464 
00465       if (mB.fBoxType == TEveBoxSet::kBT_Cone ||
00466           mB.fBoxType == TEveBoxSet::kBT_EllipticCone)
00467       {
00468          glDisable(GL_CULL_FACE);
00469       }
00470 
00471       if (mB.fDisableLighting) glDisable(GL_LIGHTING);
00472 
00473       RenderBoxes(rnrCtx);
00474 
00475       glPopAttrib();
00476    }
00477 
00478    if (mB.fFrame != 0 && ! rnrCtx.SecSelection() &&
00479        ! (rnrCtx.Highlight() && AlwaysSecondarySelect()))
00480    {
00481       TEveFrameBoxGL::Render(mB.fFrame);
00482    }
00483 }
00484 
00485 //______________________________________________________________________________
00486 void TEveBoxSetGL::Render(TGLRnrCtx& rnrCtx)
00487 {
00488    // Interface for direct rendering from classes that include TEveBoxSet
00489    // as a member.
00490 
00491    MakeDisplayList();
00492    DirectDraw(rnrCtx);
00493    glDeleteLists(fBoxDL, 1);
00494    fBoxDL = 0;
00495 }

Generated on Tue Jul 5 14:16:10 2011 for ROOT_528-00b_version by  doxygen 1.5.1