ROOT logo
// @(#)root/gl:$Id: TGLScenePad.cxx 29526 2009-07-20 17:41:53Z matevz $
// Author:  Matevz Tadel, Jun 2007

/*************************************************************************
 * Copyright (C) 1995-2004, 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 "TGLScenePad.h"

#include "TGLViewer.h"
#include "TGLLogicalShape.h"
#include "TGLPhysicalShape.h"
#include "TGLObject.h"
#include "TGLStopwatch.h"
#include "TBuffer3D.h"
#include "TBuffer3DTypes.h"

#include "TGLFaceSet.h"
#include "TGLPolyLine.h"
#include "TGLPolyMarker.h"
#include "TGLCylinder.h"
#include "TGLSphere.h"

#include "TVirtualPad.h"
#include "TAtt3D.h"
#include "TClass.h"
#include "TList.h"
#include "TMath.h"

#include "TGLPlot3D.h"


//______________________________________________________________________________
// TGLScenePad
//
// Implements VirtualViewer3D interface and fills the base-class
// visualization structures from pad contents.
//

ClassImp(TGLScenePad)


//______________________________________________________________________________
TGLScenePad::TGLScenePad(TVirtualPad* pad) :
   TVirtualViewer3D(),
   TGLScene(),

   fPad               (pad),
   fInternalPIDs      (kFALSE),
   fNextInternalPID   (1), // 0 reserved
   fLastPID           (0), // 0 reserved
   fAcceptedPhysicals (0),
   fComposite         (0),
   fCSLevel           (0),
   fSmartRefresh      (kFALSE)
{
   // Constructor.
}


/******************************************************************************/
// Histo import and Sub-pad traversal
/******************************************************************************/

//______________________________________________________________________________
void TGLScenePad::AddHistoPhysical(TGLLogicalShape* log)
{
   // Scale and rotate a histo object to mimic placement in canvas.

   Double_t how = ((Double_t) gPad->GetWh()) / gPad->GetWw();

   Double_t lw = gPad->GetAbsWNDC();
   Double_t lh = gPad->GetAbsHNDC() * how;
   Double_t lm = TMath::Min(lw, lh);

   const TGLBoundingBox& bb = log->BoundingBox();

   // Timur always packs histos in a square: let's just take x-diff.
   Double_t size  = TMath::Sqrt(3) * (bb.XMax() - bb.XMin());
   Double_t scale = lm / size;
   TGLVector3 scaleVec(scale, scale, scale);

   Double_t tx = gPad->GetAbsXlowNDC() + lw;
   Double_t ty = gPad->GetAbsYlowNDC() * how + lh;
   TGLVector3 transVec(0, ty, tx); // For viewer convention (starts looking along -x).

   // XXXX plots no longer centered at 0. Or they never were?
   // Impossible to translate and scale them as they should be, it
   // seems. This requers further investigation, eventually.
   //
   // bb.Dump();
   // printf("lm=%f, size=%f, scale=%f, tx=%f, ty=%f\n",
   //        lm, size, scale, tx, ty);
   //
   // TGLVector3 c(bb.Center().Arr());
   // c.Negate();
   // c.Dump();
   // mat.Translate(c);

   TGLMatrix mat;
   mat.Scale(scaleVec);
   mat.Translate(transVec);
   mat.RotateLF(3, 2, TMath::PiOver2());
   mat.RotateLF(1, 3, TMath::DegToRad()*gPad->GetTheta());
   mat.RotateLF(1, 2, TMath::DegToRad()*(gPad->GetPhi() - 90));
   Float_t rgba[4] = { 1, 1, 1, 1};
   TGLPhysicalShape* phys = new TGLPhysicalShape
      (fNextInternalPID++, *log, mat, false, rgba);
   AdoptPhysical(*phys);

   // Part of XXXX above.
   // phys->BoundingBox().Dump();
}

//______________________________________________________________________________
void TGLScenePad::SubPadPaint(TVirtualPad* pad)
{
   // Iterate over pad-primitves and import them.

   TVirtualPad      *padsav  = gPad;
   TVirtualViewer3D *vv3dsav = pad->GetViewer3D();
   gPad = pad;
   pad->SetViewer3D(this);

   TList       *prims = pad->GetListOfPrimitives();
   TObjOptLink *lnk   = (prims) ? (TObjOptLink*)prims->FirstLink() : 0;
   while (lnk)
   {
      ObjectPaint(lnk->GetObject(), lnk->GetOption());
      lnk = (TObjOptLink*)lnk->Next();
   }

   pad->SetViewer3D(vv3dsav);
   gPad = padsav;
}


//______________________________________________________________________________
void TGLScenePad::ObjectPaint(TObject* obj, Option_t* opt)
{
   // Override of virtual TVirtualViewer3D::ObjectPaint().
   // Special handling of 2D/3D histograms to activate Timur's
   // histo-painters.

   TGLPlot3D* log = TGLPlot3D::CreatePlot(obj, opt, gPad);
   if (log)
   {
      AdoptLogical(*log);
      AddHistoPhysical(log);
   }
   else if (obj->InheritsFrom(TAtt3D::Class()))
   {
      //Since TH3's derived from TAtt3D, it should be checked here.
      //printf("normal-painting %s / %s\n", obj->GetName(), obj->ClassName());
      obj->Paint(opt);
   }
   else if (obj->InheritsFrom(TVirtualPad::Class()))
   {
      SubPadPaint(dynamic_cast<TVirtualPad*>(obj));
   }
   else
   {
      // Handle 2D primitives here.
      // printf("TGLScenePad::ObjectPaint skipping %p, %s, %s.\n",
      //        obj, obj->GetName(), obj->ClassName());
      obj->Paint(opt);
   }
}

//______________________________________________________________________________
void TGLScenePad::PadPaintFromViewer(TGLViewer* viewer)
{
   // Entry point for requesting update of scene's contents from
   // gl-viewer.

   Bool_t sr = fSmartRefresh;
   fSmartRefresh = viewer->GetSmartRefresh();

   PadPaint(fPad);

   fSmartRefresh = sr;
}

//______________________________________________________________________________
void TGLScenePad::PadPaint(TVirtualPad* pad)
{
   // Entry point for updating scene contents via VirtualViewer3D
   // interface.
   // For now this is handled by TGLViewer as it remains
   // the 'Viewer3D' of given pad.

   if (pad != fPad)
   {
      Error("TGLScenePad::PadPaint", "Mismatch between pad argument and data-member!");
      return;
   }

   BeginScene();
   SubPadPaint(fPad);
   EndScene();
}


//==============================================================================
// VV3D
//==============================================================================

//______________________________________________________________________________
void TGLScenePad::BeginScene()
{
   // Start building of the scene.
   // Old contents is dropped, unless smart-refresh is in active. Then
   // the object supporting it are kept in a cache and possibly reused.
   //
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture.

   if (gDebug>2) {
      Info("TGLScenePad::BeginScene", "entering.");
   }

   if ( ! BeginUpdate()) {
      Error("TGLScenePad::BeginScene", "could not take scene lock.");
      return;
   }

   UInt_t destroyedLogicals  = 0;
   UInt_t destroyedPhysicals = 0;

   TGLStopwatch stopwatch;
   if (gDebug > 2) {
      stopwatch.Start();
   }

   // Rebuilds can potentially invalidate all logical and
   // physical shapes - including any modified physicals.
   // Physicals must be removed first.
   destroyedPhysicals = DestroyPhysicals(kTRUE); // include modified
   if (fSmartRefresh) {
      destroyedLogicals = BeginSmartRefresh();
   } else {
      destroyedLogicals = DestroyLogicals();
   }

   // Potentially using external physical IDs
   fInternalPIDs = kFALSE;

   // Reset internal physical ID counter
   fNextInternalPID = 1;
   fLastPID         = 0;

   // Reset tracing info
   fAcceptedPhysicals = 0;

   if (gDebug > 2) {
      Info("TGLScenePad::BeginScene", "destroyed %d physicals %d logicals in %f msec",
            destroyedPhysicals, destroyedLogicals, stopwatch.End());
      DumpMapSizes();
   }
}

//______________________________________________________________________________
void TGLScenePad::EndScene()
{
   // End building of the scene.
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture

   if (fSmartRefresh) {
      EndSmartRefresh();
   }

   EndUpdate();

   if (gDebug > 2) {
      Info("TGLScenePad::EndScene", "Accepted %d physicals", fAcceptedPhysicals);
      DumpMapSizes();
   }
}

//______________________________________________________________________________
Int_t TGLScenePad::AddObject(const TBuffer3D& buffer, Bool_t* addChildren)
{
   // Add an object to the viewer, using internal physical IDs
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture

   // If this is called we are generating internal physical IDs
   fInternalPIDs = kTRUE;
   Int_t sections = AddObject(fNextInternalPID, buffer, addChildren);
   return sections;
}

//______________________________________________________________________________
Int_t TGLScenePad::AddObject(UInt_t physicalID, const TBuffer3D& buffer, Bool_t* addChildren)
{
   // Add an object to the scene, using an external physical ID
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture

   // TODO: Break this up and make easier to understand. This is
   // pretty convoluted due to the large number of cases it has to
   // deal with:
   // i)   exisiting physical and/or logical;
   // ii)  external provider may or may not supply bounding box;
   // iii) local/global reference frame;
   // iv)  deferred filling of some sections of the buffer;
   // v)   internal or external physical IDs;
   // vi)  composite components as special case.
   //
   // The buffer filling means the function is re-entrant which adds
   // to complication.

   if (physicalID == 0) {
      Error("TGLScenePad::AddObject", "0 physical ID reserved");
      return TBuffer3D::kNone;
   }

   // Internal and external physical IDs cannot be mixed in a scene build
   if (fInternalPIDs && physicalID != fNextInternalPID) {
      Error("TGLScenePad::AddObject", "invalid next physical ID - mix of internal + external IDs?");
      return TBuffer3D::kNone;
   }

   // We always take all children ... interest is viewer dependent.
   if (addChildren)
      *addChildren = kTRUE;

   // Scene should be modify locked
   if (CurrentLock() != kModifyLock) {
      Error("TGLScenePad::AddObject", "expected scene to be modify-locked.");
      return TBuffer3D::kNone;
   }

   // Note that 'object' here is really a physical/logical pair described
   // in buffer + physical ID.

   // If adding component to a current partial composite do this now
   if (fComposite) {
      RootCsg::TBaseMesh *newMesh = RootCsg::ConvertToMesh(buffer);
      // Solaris CC can't create stl pair with enumerate type
      fCSTokens.push_back(std::make_pair(static_cast<UInt_t>(TBuffer3D::kCSNoOp), newMesh));
      return TBuffer3D::kNone;
   }

   // TODO: Could be a data member - save possible double lookup?
   TGLPhysicalShape *physical = FindPhysical(physicalID);
   TGLLogicalShape  *logical  = 0;

   // If we have a valid (non-zero) ID, see if the logical is already cached.
   // If it is not, try to create a direct renderer object.
   if (buffer.fID)
   {
      logical = FindLogical(buffer.fID);
      if (!logical)
         logical = AttemptDirectRenderer(buffer.fID);
   }

   // First attempt to add this physical.
   if (physicalID != fLastPID)
   {
      // Existing physical.
      // MT comment: I don't think this should ever happen.
      if (physical)
      {
         // If we have physical we should have logical cached, too.
         if (!logical) {
            Error("TGLScenePad::AddObject", "cached physical with no assocaited cached logical");
         }

         // Since we already have logical no need for further checks.
         // Done ... prepare for next object.
         if (fInternalPIDs)
            ++fNextInternalPID;

         return TBuffer3D::kNone;
      }

      // Need any extra sections in buffer?
      Bool_t includeRaw    = (logical == 0);
      Int_t  extraSections = ValidateObjectBuffer(buffer, includeRaw);
      if (extraSections != TBuffer3D::kNone)
         return extraSections;

      fLastPID = physicalID;
   }

   if (fLastPID != physicalID) {
      Error("TGLScenePad::AddObject", "internal physical ID tracking error?");
   }

   // Being here means we need to add a physical, maybe logical as well.
   if (physical) {
      Error("TGLScenePad::AddObject", "expecting to require physical");
      return TBuffer3D::kNone;
   }

   // Create logical if required.
   if (!logical)
   {
      logical = CreateNewLogical(buffer);
      if (!logical) {
         Error("TGLScenePad::AddObject", "failed to create logical");
         return TBuffer3D::kNone;
      }
      // Add logical to scene
      AdoptLogical(*logical);
   }

   // Create the physical, bind it to the logical and add it to the scene.
   physical = CreateNewPhysical(physicalID, buffer, *logical);

   if (physical)
   {
      AdoptPhysical(*physical);
      buffer.fPhysicalID = physicalID;
      ++fAcceptedPhysicals;
      if (gDebug>3 && fAcceptedPhysicals%1000 == 0) {
         Info("TGLScenePad::AddObject", "added %d physicals", fAcceptedPhysicals);
      }
   }
   else
   {
      Error("TGLScenePad::AddObject", "failed to create physical");
   }

   // Done ... prepare for next object.
   if (fInternalPIDs)
      fNextInternalPID++;

   return TBuffer3D::kNone;
}

//______________________________________________________________________________
Bool_t TGLScenePad::OpenComposite(const TBuffer3D& buffer, Bool_t* addChildren)
{
   // Open new composite container.
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture.

   if (fComposite) {
      Error("TGLScenePad::OpenComposite", "composite already open");
      return kFALSE;
   }
   UInt_t extraSections = AddObject(buffer, addChildren);
   if (extraSections != TBuffer3D::kNone) {
      Error("TGLScenePad::OpenComposite", "expected top level composite to not require extra buffer sections");
   }

   // If composite was created it is of interest - we want the rest of the
   // child components
   if (fComposite) {
      return kTRUE;
   } else {
      return kFALSE;
   }
}

//______________________________________________________________________________
void TGLScenePad::CloseComposite()
{
   // Close composite container
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture

   // If we have a partially complete composite build it now
   if (fComposite) {
      // TODO: Why is this member and here - only used in BuildComposite()
      fCSLevel = 0;

      RootCsg::TBaseMesh *resultMesh = BuildComposite();
      fComposite->SetFromMesh(resultMesh);
      delete resultMesh;
      for (UInt_t i = 0; i < fCSTokens.size(); ++i) delete fCSTokens[i].second;
      fCSTokens.clear();
      fComposite = 0;
   }
}

//______________________________________________________________________________
void TGLScenePad::AddCompositeOp(UInt_t operation)
{
   // Add composite operation used to combine objects added via AddObject
   // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
   // for description of viewer architecture

   fCSTokens.push_back(std::make_pair(operation, (RootCsg::TBaseMesh *)0));
}


// Protected methods

//______________________________________________________________________________
Int_t TGLScenePad::ValidateObjectBuffer(const TBuffer3D& buffer, Bool_t includeRaw) const
{
   // Validate if the passed 'buffer' contains all sections we require to add object.
   // Returns Int_t combination of TBuffer::ESection flags still required - or
   // TBuffer3D::kNone if buffer is valid.
   // If 'includeRaw' is kTRUE check for kRaw/kRawSizes - skip otherwise.
   // See base/src/TVirtualViewer3D.cxx for description of viewer architecture

   // kCore: Should always be filled
   if (!buffer.SectionsValid(TBuffer3D::kCore)) {
      Error("TGLScenePad::ValidateObjectBuffer", "kCore section of buffer should be filled always");
      return TBuffer3D::kNone;
   }

   // Need to check raw (kRaw/kRawSizes)?
   if (!includeRaw) {
      return TBuffer3D::kNone;
   }

   // kRawSizes / kRaw: These are on demand based on shape type
   Bool_t needRaw = kFALSE;

   // We need raw tesselation in these cases:
   //
   // 1. Shape type is NOT kSphere / kTube / kTubeSeg / kCutTube / kComposite
   if (buffer.Type() != TBuffer3DTypes::kSphere  &&
       buffer.Type() != TBuffer3DTypes::kTube    &&
       buffer.Type() != TBuffer3DTypes::kTubeSeg &&
       buffer.Type() != TBuffer3DTypes::kCutTube &&
       buffer.Type() != TBuffer3DTypes::kComposite)
   {
      needRaw = kTRUE;
   }
   // 2. Sphere type is kSPHE, but the sphere is hollow and/or cut - we
   //    do not support native drawing of these currently
   else if (buffer.Type() == TBuffer3DTypes::kSphere)
   {
      const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
      if (sphereBuffer) {
         if (!sphereBuffer->IsSolidUncut()) {
            needRaw = kTRUE;
         }
      } else {
         Error("TGLScenePad::ValidateObjectBuffer", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
         return TBuffer3D::kNone;
      }
   }
   // 3. kBoundingBox is not filled - we generate a bounding box from
   else if (!buffer.SectionsValid(TBuffer3D::kBoundingBox))
   {
      needRaw = kTRUE;
   }
   // 4. kShapeSpecific is not filled - except in case of top level composite
   else if (!buffer.SectionsValid(TBuffer3D::kShapeSpecific) &&
             buffer.Type() != TBuffer3DTypes::kComposite)
   {
      needRaw = kTRUE;
   }
   // 5. We are a component (not the top level) of a composite shape
   else if (fComposite)
   {
      needRaw = kTRUE;
   }

   if (needRaw && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
      return TBuffer3D::kRawSizes|TBuffer3D::kRaw;
   } else {
      return TBuffer3D::kNone;
   }
}

//______________________________________________________________________________
TGLLogicalShape* TGLScenePad::CreateNewLogical(const TBuffer3D& buffer) const
{
   // Create and return a new TGLLogicalShape from the supplied buffer
   TGLLogicalShape * newLogical = 0;

   if (buffer.fColor == 1) // black -> light-brown; std behaviour for geom
      const_cast<TBuffer3D&>(buffer).fColor = 42;

   switch (buffer.Type())
   {
      case TBuffer3DTypes::kLine:
         newLogical = new TGLPolyLine(buffer);
         break;
      case TBuffer3DTypes::kMarker:
         newLogical = new TGLPolyMarker(buffer);
         break;
      case TBuffer3DTypes::kSphere:
      {
         const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
         if (sphereBuffer)
         {
            // We can only draw solid uncut spheres natively at present.
            // If somebody already passed the raw buffer, he probably wants us to use it.
            if (sphereBuffer->IsSolidUncut() && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw))
            {
               newLogical = new TGLSphere(*sphereBuffer);
            } else {
               newLogical = new TGLFaceSet(buffer);
            }
         } else {
            Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
         }
         break;
      }
      case TBuffer3DTypes::kTube:
      case TBuffer3DTypes::kTubeSeg:
      case TBuffer3DTypes::kCutTube:
      {
         const TBuffer3DTube * tubeBuffer = dynamic_cast<const TBuffer3DTube *>(&buffer);
         if (tubeBuffer)
         {
            // If somebody already passed the raw buffer, he probably wants us to use it.
            if (!buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
               newLogical = new TGLCylinder(*tubeBuffer);
            } else {
               newLogical = new TGLFaceSet(buffer);
            }
         } else {
            Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kTube/kTubeSeg/kCutTube' to TBuffer3DTube");
         }
         break;
      }
      case TBuffer3DTypes::kComposite:
      {
         // Create empty faceset and record partial complete composite object
         // Will be populated with mesh in CloseComposite()
         if (fComposite)
         {
            Error("TGLScenePad::CreateNewLogical", "composite already open");
         }
         fComposite = new TGLFaceSet(buffer);
         newLogical = fComposite;
         break;
      }
      default:
         newLogical = new TGLFaceSet(buffer);
         break;
   }

   return newLogical;
}

//______________________________________________________________________________
TGLPhysicalShape*
TGLScenePad::CreateNewPhysical(UInt_t ID, const TBuffer3D& buffer,
                               const TGLLogicalShape& logical) const
{
   // Create and return a new TGLPhysicalShape with id 'ID', using
   // 'buffer' placement information (translation etc), and bound to
   // suppled 'logical'

   // Extract indexed color from buffer
   // TODO: Still required? Better use proper color triplet in buffer?
   Int_t colorIndex = buffer.fColor;
   if (colorIndex < 0) colorIndex = 42;
   Float_t rgba[4];
   TGLScene::RGBAFromColorIdx(rgba, colorIndex, buffer.fTransparency);
   return new TGLPhysicalShape(ID, logical, buffer.fLocalMaster,
                               buffer.fReflection, rgba);
}

//______________________________________________________________________________
RootCsg::TBaseMesh* TGLScenePad::BuildComposite()
{
   // Build and return composite shape mesh
   const CSPart_t &currToken = fCSTokens[fCSLevel];
   UInt_t opCode = currToken.first;

   if (opCode != TBuffer3D::kCSNoOp) {
      ++fCSLevel;
      RootCsg::TBaseMesh *left = BuildComposite();
      RootCsg::TBaseMesh *right = BuildComposite();
      //RootCsg::TBaseMesh *result = 0;
      switch (opCode) {
      case TBuffer3D::kCSUnion:
         return RootCsg::BuildUnion(left, right);
      case TBuffer3D::kCSIntersection:
         return RootCsg::BuildIntersection(left, right);
      case TBuffer3D::kCSDifference:
         return RootCsg::BuildDifference(left, right);
      default:
         Error("BuildComposite", "Wrong operation code %d\n", opCode);
         return 0;
      }
   } else return fCSTokens[fCSLevel++].second;
}

//______________________________________________________________________________
TGLLogicalShape* TGLScenePad::AttemptDirectRenderer(TObject* id)
{
   // Try to construct an appropriate logical-shape sub-class based
   // on id'class, following convention that SomeClassGL is a suitable
   // renderer for class SomeClass.

   TClass* cls = TGLObject::GetGLRenderer(id->IsA());
   if (cls == 0)
      return 0;

   TGLObject* rnr = reinterpret_cast<TGLObject*>(cls->New());
   if (rnr) {
      if (rnr->SetModel(id) == kFALSE) {
         Warning("TGLScenePad::AttemptDirectRenderer", "failed initializing direct rendering.");
         delete rnr;
         return 0;
      }
      rnr->SetBBox();
      AdoptLogical(*rnr);
   }
   return rnr;
}
 TGLScenePad.cxx:1
 TGLScenePad.cxx:2
 TGLScenePad.cxx:3
 TGLScenePad.cxx:4
 TGLScenePad.cxx:5
 TGLScenePad.cxx:6
 TGLScenePad.cxx:7
 TGLScenePad.cxx:8
 TGLScenePad.cxx:9
 TGLScenePad.cxx:10
 TGLScenePad.cxx:11
 TGLScenePad.cxx:12
 TGLScenePad.cxx:13
 TGLScenePad.cxx:14
 TGLScenePad.cxx:15
 TGLScenePad.cxx:16
 TGLScenePad.cxx:17
 TGLScenePad.cxx:18
 TGLScenePad.cxx:19
 TGLScenePad.cxx:20
 TGLScenePad.cxx:21
 TGLScenePad.cxx:22
 TGLScenePad.cxx:23
 TGLScenePad.cxx:24
 TGLScenePad.cxx:25
 TGLScenePad.cxx:26
 TGLScenePad.cxx:27
 TGLScenePad.cxx:28
 TGLScenePad.cxx:29
 TGLScenePad.cxx:30
 TGLScenePad.cxx:31
 TGLScenePad.cxx:32
 TGLScenePad.cxx:33
 TGLScenePad.cxx:34
 TGLScenePad.cxx:35
 TGLScenePad.cxx:36
 TGLScenePad.cxx:37
 TGLScenePad.cxx:38
 TGLScenePad.cxx:39
 TGLScenePad.cxx:40
 TGLScenePad.cxx:41
 TGLScenePad.cxx:42
 TGLScenePad.cxx:43
 TGLScenePad.cxx:44
 TGLScenePad.cxx:45
 TGLScenePad.cxx:46
 TGLScenePad.cxx:47
 TGLScenePad.cxx:48
 TGLScenePad.cxx:49
 TGLScenePad.cxx:50
 TGLScenePad.cxx:51
 TGLScenePad.cxx:52
 TGLScenePad.cxx:53
 TGLScenePad.cxx:54
 TGLScenePad.cxx:55
 TGLScenePad.cxx:56
 TGLScenePad.cxx:57
 TGLScenePad.cxx:58
 TGLScenePad.cxx:59
 TGLScenePad.cxx:60
 TGLScenePad.cxx:61
 TGLScenePad.cxx:62
 TGLScenePad.cxx:63
 TGLScenePad.cxx:64
 TGLScenePad.cxx:65
 TGLScenePad.cxx:66
 TGLScenePad.cxx:67
 TGLScenePad.cxx:68
 TGLScenePad.cxx:69
 TGLScenePad.cxx:70
 TGLScenePad.cxx:71
 TGLScenePad.cxx:72
 TGLScenePad.cxx:73
 TGLScenePad.cxx:74
 TGLScenePad.cxx:75
 TGLScenePad.cxx:76
 TGLScenePad.cxx:77
 TGLScenePad.cxx:78
 TGLScenePad.cxx:79
 TGLScenePad.cxx:80
 TGLScenePad.cxx:81
 TGLScenePad.cxx:82
 TGLScenePad.cxx:83
 TGLScenePad.cxx:84
 TGLScenePad.cxx:85
 TGLScenePad.cxx:86
 TGLScenePad.cxx:87
 TGLScenePad.cxx:88
 TGLScenePad.cxx:89
 TGLScenePad.cxx:90
 TGLScenePad.cxx:91
 TGLScenePad.cxx:92
 TGLScenePad.cxx:93
 TGLScenePad.cxx:94
 TGLScenePad.cxx:95
 TGLScenePad.cxx:96
 TGLScenePad.cxx:97
 TGLScenePad.cxx:98
 TGLScenePad.cxx:99
 TGLScenePad.cxx:100
 TGLScenePad.cxx:101
 TGLScenePad.cxx:102
 TGLScenePad.cxx:103
 TGLScenePad.cxx:104
 TGLScenePad.cxx:105
 TGLScenePad.cxx:106
 TGLScenePad.cxx:107
 TGLScenePad.cxx:108
 TGLScenePad.cxx:109
 TGLScenePad.cxx:110
 TGLScenePad.cxx:111
 TGLScenePad.cxx:112
 TGLScenePad.cxx:113
 TGLScenePad.cxx:114
 TGLScenePad.cxx:115
 TGLScenePad.cxx:116
 TGLScenePad.cxx:117
 TGLScenePad.cxx:118
 TGLScenePad.cxx:119
 TGLScenePad.cxx:120
 TGLScenePad.cxx:121
 TGLScenePad.cxx:122
 TGLScenePad.cxx:123
 TGLScenePad.cxx:124
 TGLScenePad.cxx:125
 TGLScenePad.cxx:126
 TGLScenePad.cxx:127
 TGLScenePad.cxx:128
 TGLScenePad.cxx:129
 TGLScenePad.cxx:130
 TGLScenePad.cxx:131
 TGLScenePad.cxx:132
 TGLScenePad.cxx:133
 TGLScenePad.cxx:134
 TGLScenePad.cxx:135
 TGLScenePad.cxx:136
 TGLScenePad.cxx:137
 TGLScenePad.cxx:138
 TGLScenePad.cxx:139
 TGLScenePad.cxx:140
 TGLScenePad.cxx:141
 TGLScenePad.cxx:142
 TGLScenePad.cxx:143
 TGLScenePad.cxx:144
 TGLScenePad.cxx:145
 TGLScenePad.cxx:146
 TGLScenePad.cxx:147
 TGLScenePad.cxx:148
 TGLScenePad.cxx:149
 TGLScenePad.cxx:150
 TGLScenePad.cxx:151
 TGLScenePad.cxx:152
 TGLScenePad.cxx:153
 TGLScenePad.cxx:154
 TGLScenePad.cxx:155
 TGLScenePad.cxx:156
 TGLScenePad.cxx:157
 TGLScenePad.cxx:158
 TGLScenePad.cxx:159
 TGLScenePad.cxx:160
 TGLScenePad.cxx:161
 TGLScenePad.cxx:162
 TGLScenePad.cxx:163
 TGLScenePad.cxx:164
 TGLScenePad.cxx:165
 TGLScenePad.cxx:166
 TGLScenePad.cxx:167
 TGLScenePad.cxx:168
 TGLScenePad.cxx:169
 TGLScenePad.cxx:170
 TGLScenePad.cxx:171
 TGLScenePad.cxx:172
 TGLScenePad.cxx:173
 TGLScenePad.cxx:174
 TGLScenePad.cxx:175
 TGLScenePad.cxx:176
 TGLScenePad.cxx:177
 TGLScenePad.cxx:178
 TGLScenePad.cxx:179
 TGLScenePad.cxx:180
 TGLScenePad.cxx:181
 TGLScenePad.cxx:182
 TGLScenePad.cxx:183
 TGLScenePad.cxx:184
 TGLScenePad.cxx:185
 TGLScenePad.cxx:186
 TGLScenePad.cxx:187
 TGLScenePad.cxx:188
 TGLScenePad.cxx:189
 TGLScenePad.cxx:190
 TGLScenePad.cxx:191
 TGLScenePad.cxx:192
 TGLScenePad.cxx:193
 TGLScenePad.cxx:194
 TGLScenePad.cxx:195
 TGLScenePad.cxx:196
 TGLScenePad.cxx:197
 TGLScenePad.cxx:198
 TGLScenePad.cxx:199
 TGLScenePad.cxx:200
 TGLScenePad.cxx:201
 TGLScenePad.cxx:202
 TGLScenePad.cxx:203
 TGLScenePad.cxx:204
 TGLScenePad.cxx:205
 TGLScenePad.cxx:206
 TGLScenePad.cxx:207
 TGLScenePad.cxx:208
 TGLScenePad.cxx:209
 TGLScenePad.cxx:210
 TGLScenePad.cxx:211
 TGLScenePad.cxx:212
 TGLScenePad.cxx:213
 TGLScenePad.cxx:214
 TGLScenePad.cxx:215
 TGLScenePad.cxx:216
 TGLScenePad.cxx:217
 TGLScenePad.cxx:218
 TGLScenePad.cxx:219
 TGLScenePad.cxx:220
 TGLScenePad.cxx:221
 TGLScenePad.cxx:222
 TGLScenePad.cxx:223
 TGLScenePad.cxx:224
 TGLScenePad.cxx:225
 TGLScenePad.cxx:226
 TGLScenePad.cxx:227
 TGLScenePad.cxx:228
 TGLScenePad.cxx:229
 TGLScenePad.cxx:230
 TGLScenePad.cxx:231
 TGLScenePad.cxx:232
 TGLScenePad.cxx:233
 TGLScenePad.cxx:234
 TGLScenePad.cxx:235
 TGLScenePad.cxx:236
 TGLScenePad.cxx:237
 TGLScenePad.cxx:238
 TGLScenePad.cxx:239
 TGLScenePad.cxx:240
 TGLScenePad.cxx:241
 TGLScenePad.cxx:242
 TGLScenePad.cxx:243
 TGLScenePad.cxx:244
 TGLScenePad.cxx:245
 TGLScenePad.cxx:246
 TGLScenePad.cxx:247
 TGLScenePad.cxx:248
 TGLScenePad.cxx:249
 TGLScenePad.cxx:250
 TGLScenePad.cxx:251
 TGLScenePad.cxx:252
 TGLScenePad.cxx:253
 TGLScenePad.cxx:254
 TGLScenePad.cxx:255
 TGLScenePad.cxx:256
 TGLScenePad.cxx:257
 TGLScenePad.cxx:258
 TGLScenePad.cxx:259
 TGLScenePad.cxx:260
 TGLScenePad.cxx:261
 TGLScenePad.cxx:262
 TGLScenePad.cxx:263
 TGLScenePad.cxx:264
 TGLScenePad.cxx:265
 TGLScenePad.cxx:266
 TGLScenePad.cxx:267
 TGLScenePad.cxx:268
 TGLScenePad.cxx:269
 TGLScenePad.cxx:270
 TGLScenePad.cxx:271
 TGLScenePad.cxx:272
 TGLScenePad.cxx:273
 TGLScenePad.cxx:274
 TGLScenePad.cxx:275
 TGLScenePad.cxx:276
 TGLScenePad.cxx:277
 TGLScenePad.cxx:278
 TGLScenePad.cxx:279
 TGLScenePad.cxx:280
 TGLScenePad.cxx:281
 TGLScenePad.cxx:282
 TGLScenePad.cxx:283
 TGLScenePad.cxx:284
 TGLScenePad.cxx:285
 TGLScenePad.cxx:286
 TGLScenePad.cxx:287
 TGLScenePad.cxx:288
 TGLScenePad.cxx:289
 TGLScenePad.cxx:290
 TGLScenePad.cxx:291
 TGLScenePad.cxx:292
 TGLScenePad.cxx:293
 TGLScenePad.cxx:294
 TGLScenePad.cxx:295
 TGLScenePad.cxx:296
 TGLScenePad.cxx:297
 TGLScenePad.cxx:298
 TGLScenePad.cxx:299
 TGLScenePad.cxx:300
 TGLScenePad.cxx:301
 TGLScenePad.cxx:302
 TGLScenePad.cxx:303
 TGLScenePad.cxx:304
 TGLScenePad.cxx:305
 TGLScenePad.cxx:306
 TGLScenePad.cxx:307
 TGLScenePad.cxx:308
 TGLScenePad.cxx:309
 TGLScenePad.cxx:310
 TGLScenePad.cxx:311
 TGLScenePad.cxx:312
 TGLScenePad.cxx:313
 TGLScenePad.cxx:314
 TGLScenePad.cxx:315
 TGLScenePad.cxx:316
 TGLScenePad.cxx:317
 TGLScenePad.cxx:318
 TGLScenePad.cxx:319
 TGLScenePad.cxx:320
 TGLScenePad.cxx:321
 TGLScenePad.cxx:322
 TGLScenePad.cxx:323
 TGLScenePad.cxx:324
 TGLScenePad.cxx:325
 TGLScenePad.cxx:326
 TGLScenePad.cxx:327
 TGLScenePad.cxx:328
 TGLScenePad.cxx:329
 TGLScenePad.cxx:330
 TGLScenePad.cxx:331
 TGLScenePad.cxx:332
 TGLScenePad.cxx:333
 TGLScenePad.cxx:334
 TGLScenePad.cxx:335
 TGLScenePad.cxx:336
 TGLScenePad.cxx:337
 TGLScenePad.cxx:338
 TGLScenePad.cxx:339
 TGLScenePad.cxx:340
 TGLScenePad.cxx:341
 TGLScenePad.cxx:342
 TGLScenePad.cxx:343
 TGLScenePad.cxx:344
 TGLScenePad.cxx:345
 TGLScenePad.cxx:346
 TGLScenePad.cxx:347
 TGLScenePad.cxx:348
 TGLScenePad.cxx:349
 TGLScenePad.cxx:350
 TGLScenePad.cxx:351
 TGLScenePad.cxx:352
 TGLScenePad.cxx:353
 TGLScenePad.cxx:354
 TGLScenePad.cxx:355
 TGLScenePad.cxx:356
 TGLScenePad.cxx:357
 TGLScenePad.cxx:358
 TGLScenePad.cxx:359
 TGLScenePad.cxx:360
 TGLScenePad.cxx:361
 TGLScenePad.cxx:362
 TGLScenePad.cxx:363
 TGLScenePad.cxx:364
 TGLScenePad.cxx:365
 TGLScenePad.cxx:366
 TGLScenePad.cxx:367
 TGLScenePad.cxx:368
 TGLScenePad.cxx:369
 TGLScenePad.cxx:370
 TGLScenePad.cxx:371
 TGLScenePad.cxx:372
 TGLScenePad.cxx:373
 TGLScenePad.cxx:374
 TGLScenePad.cxx:375
 TGLScenePad.cxx:376
 TGLScenePad.cxx:377
 TGLScenePad.cxx:378
 TGLScenePad.cxx:379
 TGLScenePad.cxx:380
 TGLScenePad.cxx:381
 TGLScenePad.cxx:382
 TGLScenePad.cxx:383
 TGLScenePad.cxx:384
 TGLScenePad.cxx:385
 TGLScenePad.cxx:386
 TGLScenePad.cxx:387
 TGLScenePad.cxx:388
 TGLScenePad.cxx:389
 TGLScenePad.cxx:390
 TGLScenePad.cxx:391
 TGLScenePad.cxx:392
 TGLScenePad.cxx:393
 TGLScenePad.cxx:394
 TGLScenePad.cxx:395
 TGLScenePad.cxx:396
 TGLScenePad.cxx:397
 TGLScenePad.cxx:398
 TGLScenePad.cxx:399
 TGLScenePad.cxx:400
 TGLScenePad.cxx:401
 TGLScenePad.cxx:402
 TGLScenePad.cxx:403
 TGLScenePad.cxx:404
 TGLScenePad.cxx:405
 TGLScenePad.cxx:406
 TGLScenePad.cxx:407
 TGLScenePad.cxx:408
 TGLScenePad.cxx:409
 TGLScenePad.cxx:410
 TGLScenePad.cxx:411
 TGLScenePad.cxx:412
 TGLScenePad.cxx:413
 TGLScenePad.cxx:414
 TGLScenePad.cxx:415
 TGLScenePad.cxx:416
 TGLScenePad.cxx:417
 TGLScenePad.cxx:418
 TGLScenePad.cxx:419
 TGLScenePad.cxx:420
 TGLScenePad.cxx:421
 TGLScenePad.cxx:422
 TGLScenePad.cxx:423
 TGLScenePad.cxx:424
 TGLScenePad.cxx:425
 TGLScenePad.cxx:426
 TGLScenePad.cxx:427
 TGLScenePad.cxx:428
 TGLScenePad.cxx:429
 TGLScenePad.cxx:430
 TGLScenePad.cxx:431
 TGLScenePad.cxx:432
 TGLScenePad.cxx:433
 TGLScenePad.cxx:434
 TGLScenePad.cxx:435
 TGLScenePad.cxx:436
 TGLScenePad.cxx:437
 TGLScenePad.cxx:438
 TGLScenePad.cxx:439
 TGLScenePad.cxx:440
 TGLScenePad.cxx:441
 TGLScenePad.cxx:442
 TGLScenePad.cxx:443
 TGLScenePad.cxx:444
 TGLScenePad.cxx:445
 TGLScenePad.cxx:446
 TGLScenePad.cxx:447
 TGLScenePad.cxx:448
 TGLScenePad.cxx:449
 TGLScenePad.cxx:450
 TGLScenePad.cxx:451
 TGLScenePad.cxx:452
 TGLScenePad.cxx:453
 TGLScenePad.cxx:454
 TGLScenePad.cxx:455
 TGLScenePad.cxx:456
 TGLScenePad.cxx:457
 TGLScenePad.cxx:458
 TGLScenePad.cxx:459
 TGLScenePad.cxx:460
 TGLScenePad.cxx:461
 TGLScenePad.cxx:462
 TGLScenePad.cxx:463
 TGLScenePad.cxx:464
 TGLScenePad.cxx:465
 TGLScenePad.cxx:466
 TGLScenePad.cxx:467
 TGLScenePad.cxx:468
 TGLScenePad.cxx:469
 TGLScenePad.cxx:470
 TGLScenePad.cxx:471
 TGLScenePad.cxx:472
 TGLScenePad.cxx:473
 TGLScenePad.cxx:474
 TGLScenePad.cxx:475
 TGLScenePad.cxx:476
 TGLScenePad.cxx:477
 TGLScenePad.cxx:478
 TGLScenePad.cxx:479
 TGLScenePad.cxx:480
 TGLScenePad.cxx:481
 TGLScenePad.cxx:482
 TGLScenePad.cxx:483
 TGLScenePad.cxx:484
 TGLScenePad.cxx:485
 TGLScenePad.cxx:486
 TGLScenePad.cxx:487
 TGLScenePad.cxx:488
 TGLScenePad.cxx:489
 TGLScenePad.cxx:490
 TGLScenePad.cxx:491
 TGLScenePad.cxx:492
 TGLScenePad.cxx:493
 TGLScenePad.cxx:494
 TGLScenePad.cxx:495
 TGLScenePad.cxx:496
 TGLScenePad.cxx:497
 TGLScenePad.cxx:498
 TGLScenePad.cxx:499
 TGLScenePad.cxx:500
 TGLScenePad.cxx:501
 TGLScenePad.cxx:502
 TGLScenePad.cxx:503
 TGLScenePad.cxx:504
 TGLScenePad.cxx:505
 TGLScenePad.cxx:506
 TGLScenePad.cxx:507
 TGLScenePad.cxx:508
 TGLScenePad.cxx:509
 TGLScenePad.cxx:510
 TGLScenePad.cxx:511
 TGLScenePad.cxx:512
 TGLScenePad.cxx:513
 TGLScenePad.cxx:514
 TGLScenePad.cxx:515
 TGLScenePad.cxx:516
 TGLScenePad.cxx:517
 TGLScenePad.cxx:518
 TGLScenePad.cxx:519
 TGLScenePad.cxx:520
 TGLScenePad.cxx:521
 TGLScenePad.cxx:522
 TGLScenePad.cxx:523
 TGLScenePad.cxx:524
 TGLScenePad.cxx:525
 TGLScenePad.cxx:526
 TGLScenePad.cxx:527
 TGLScenePad.cxx:528
 TGLScenePad.cxx:529
 TGLScenePad.cxx:530
 TGLScenePad.cxx:531
 TGLScenePad.cxx:532
 TGLScenePad.cxx:533
 TGLScenePad.cxx:534
 TGLScenePad.cxx:535
 TGLScenePad.cxx:536
 TGLScenePad.cxx:537
 TGLScenePad.cxx:538
 TGLScenePad.cxx:539
 TGLScenePad.cxx:540
 TGLScenePad.cxx:541
 TGLScenePad.cxx:542
 TGLScenePad.cxx:543
 TGLScenePad.cxx:544
 TGLScenePad.cxx:545
 TGLScenePad.cxx:546
 TGLScenePad.cxx:547
 TGLScenePad.cxx:548
 TGLScenePad.cxx:549
 TGLScenePad.cxx:550
 TGLScenePad.cxx:551
 TGLScenePad.cxx:552
 TGLScenePad.cxx:553
 TGLScenePad.cxx:554
 TGLScenePad.cxx:555
 TGLScenePad.cxx:556
 TGLScenePad.cxx:557
 TGLScenePad.cxx:558
 TGLScenePad.cxx:559
 TGLScenePad.cxx:560
 TGLScenePad.cxx:561
 TGLScenePad.cxx:562
 TGLScenePad.cxx:563
 TGLScenePad.cxx:564
 TGLScenePad.cxx:565
 TGLScenePad.cxx:566
 TGLScenePad.cxx:567
 TGLScenePad.cxx:568
 TGLScenePad.cxx:569
 TGLScenePad.cxx:570
 TGLScenePad.cxx:571
 TGLScenePad.cxx:572
 TGLScenePad.cxx:573
 TGLScenePad.cxx:574
 TGLScenePad.cxx:575
 TGLScenePad.cxx:576
 TGLScenePad.cxx:577
 TGLScenePad.cxx:578
 TGLScenePad.cxx:579
 TGLScenePad.cxx:580
 TGLScenePad.cxx:581
 TGLScenePad.cxx:582
 TGLScenePad.cxx:583
 TGLScenePad.cxx:584
 TGLScenePad.cxx:585
 TGLScenePad.cxx:586
 TGLScenePad.cxx:587
 TGLScenePad.cxx:588
 TGLScenePad.cxx:589
 TGLScenePad.cxx:590
 TGLScenePad.cxx:591
 TGLScenePad.cxx:592
 TGLScenePad.cxx:593
 TGLScenePad.cxx:594
 TGLScenePad.cxx:595
 TGLScenePad.cxx:596
 TGLScenePad.cxx:597
 TGLScenePad.cxx:598
 TGLScenePad.cxx:599
 TGLScenePad.cxx:600
 TGLScenePad.cxx:601
 TGLScenePad.cxx:602
 TGLScenePad.cxx:603
 TGLScenePad.cxx:604
 TGLScenePad.cxx:605
 TGLScenePad.cxx:606
 TGLScenePad.cxx:607
 TGLScenePad.cxx:608
 TGLScenePad.cxx:609
 TGLScenePad.cxx:610
 TGLScenePad.cxx:611
 TGLScenePad.cxx:612
 TGLScenePad.cxx:613
 TGLScenePad.cxx:614
 TGLScenePad.cxx:615
 TGLScenePad.cxx:616
 TGLScenePad.cxx:617
 TGLScenePad.cxx:618
 TGLScenePad.cxx:619
 TGLScenePad.cxx:620
 TGLScenePad.cxx:621
 TGLScenePad.cxx:622
 TGLScenePad.cxx:623
 TGLScenePad.cxx:624
 TGLScenePad.cxx:625
 TGLScenePad.cxx:626
 TGLScenePad.cxx:627
 TGLScenePad.cxx:628
 TGLScenePad.cxx:629
 TGLScenePad.cxx:630
 TGLScenePad.cxx:631
 TGLScenePad.cxx:632
 TGLScenePad.cxx:633
 TGLScenePad.cxx:634
 TGLScenePad.cxx:635
 TGLScenePad.cxx:636
 TGLScenePad.cxx:637
 TGLScenePad.cxx:638
 TGLScenePad.cxx:639
 TGLScenePad.cxx:640
 TGLScenePad.cxx:641
 TGLScenePad.cxx:642
 TGLScenePad.cxx:643
 TGLScenePad.cxx:644
 TGLScenePad.cxx:645
 TGLScenePad.cxx:646
 TGLScenePad.cxx:647
 TGLScenePad.cxx:648
 TGLScenePad.cxx:649
 TGLScenePad.cxx:650
 TGLScenePad.cxx:651
 TGLScenePad.cxx:652
 TGLScenePad.cxx:653
 TGLScenePad.cxx:654
 TGLScenePad.cxx:655
 TGLScenePad.cxx:656
 TGLScenePad.cxx:657
 TGLScenePad.cxx:658
 TGLScenePad.cxx:659
 TGLScenePad.cxx:660
 TGLScenePad.cxx:661
 TGLScenePad.cxx:662
 TGLScenePad.cxx:663
 TGLScenePad.cxx:664
 TGLScenePad.cxx:665
 TGLScenePad.cxx:666
 TGLScenePad.cxx:667
 TGLScenePad.cxx:668
 TGLScenePad.cxx:669
 TGLScenePad.cxx:670
 TGLScenePad.cxx:671
 TGLScenePad.cxx:672
 TGLScenePad.cxx:673
 TGLScenePad.cxx:674
 TGLScenePad.cxx:675
 TGLScenePad.cxx:676
 TGLScenePad.cxx:677
 TGLScenePad.cxx:678
 TGLScenePad.cxx:679
 TGLScenePad.cxx:680
 TGLScenePad.cxx:681
 TGLScenePad.cxx:682
 TGLScenePad.cxx:683
 TGLScenePad.cxx:684
 TGLScenePad.cxx:685
 TGLScenePad.cxx:686
 TGLScenePad.cxx:687
 TGLScenePad.cxx:688
 TGLScenePad.cxx:689
 TGLScenePad.cxx:690
 TGLScenePad.cxx:691
 TGLScenePad.cxx:692
 TGLScenePad.cxx:693
 TGLScenePad.cxx:694
 TGLScenePad.cxx:695
 TGLScenePad.cxx:696
 TGLScenePad.cxx:697
 TGLScenePad.cxx:698
 TGLScenePad.cxx:699
 TGLScenePad.cxx:700
 TGLScenePad.cxx:701
 TGLScenePad.cxx:702
 TGLScenePad.cxx:703
 TGLScenePad.cxx:704
 TGLScenePad.cxx:705
 TGLScenePad.cxx:706
 TGLScenePad.cxx:707
 TGLScenePad.cxx:708
 TGLScenePad.cxx:709