// @(#)root/gl:$Id$
// Author: Matevz Tadel  7/4/2006

/*************************************************************************
 * 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 "TGLObject.h"
#include "TGLRnrCtx.h"
#include "TObject.h"
#include "TClass.h"
#include "TBaseClass.h"
#include "TList.h"
#include "TString.h"

//==============================================================================
// TGLObject
//==============================================================================

//______________________________________________________________________
//
// Base-class for direct OpenGL renderers.
// This allows classes to circumvent passing of TBuffer3D and
// use user-provided OpenGL code.
// By convention, if you want class TFoo : public TObject to have direct rendering
// you should also provide TFooGL : public TGLObject and implement
// abstract functions SetModel() and SetBBox().
// TAttBBox can be used to facilitate calculation of bounding-boxes.
// See TPointSet3D and TPointSet3DGL.

ClassImp(TGLObject);

TMap TGLObject::fgGLClassMap;

//______________________________________________________________________________
Bool_t TGLObject::ShouldDLCache(const TGLRnrCtx& rnrCtx) const
{
   // Decide if display-list should be used for this pass rendering,
   // as determined by rnrCtx.

   if (!fDLCache ||
       !fScene   ||
       (rnrCtx.SecSelection() && SupportsSecondarySelect()) ||
       (fMultiColor && (rnrCtx.Highlight() || rnrCtx.IsDrawPassOutlineLine())) ||
       (AlwaysSecondarySelect() && rnrCtx.Highlight()))
   {
      return kFALSE;
   }

   return kTRUE;
}

//______________________________________________________________________________
void TGLObject::UpdateBoundingBox()
{
   // Update bounding box from external source.
   // We call abstract SetBBox() and propagate the change to all
   // attached physicals.

   SetBBox();
   UpdateBoundingBoxesOfPhysicals();
}

//______________________________________________________________________________
Bool_t TGLObject::SetModelCheckClass(TObject* obj, TClass* cls)
{
   // Checks if obj is of proper class and sets the model.
   // Protected helper for subclasses.
   // Most sub-classes use exception-throwing SetModelDynCast() instead.

   if(obj->InheritsFrom(cls) == kFALSE) {
      Warning("TGLObject::SetModelCheckClass", "object of wrong class passed.");
      return kFALSE;
   }
   fExternalObj = obj;

   return kTRUE;
}

//______________________________________________________________________________
void TGLObject::SetAxisAlignedBBox(Float_t xmin, Float_t xmax,
                                   Float_t ymin, Float_t ymax,
                                   Float_t zmin, Float_t zmax)
{
   // Set axis-aligned bounding-box.
   // Protected helper for subclasses.

   fBoundingBox.SetAligned(TGLVertex3(xmin, ymin, zmin),
                           TGLVertex3(xmax, ymax, zmax));
}

//______________________________________________________________________________
void TGLObject::SetAxisAlignedBBox(const Float_t* p)
{
   // Set axis-aligned bounding-box.
   // Protected helper for subclasses.

   SetAxisAlignedBBox(p[0], p[1], p[2], p[3], p[4], p[5]);
}


//______________________________________________________________________________
TClass* TGLObject::SearchGLRenderer(TClass* cls)
{
   // Recursively search cls and its base classes for a GL-renderer
   // class.

   TString rnr( cls->GetName() );
   rnr += "GL";
   TClass* c = TClass::GetClass(rnr);
   if (c != 0)
      return c;

   TList* bases = cls->GetListOfBases();
   if (bases == 0 || bases->IsEmpty())
      return 0;

   TIter  next_base(bases);
   TBaseClass* bc;
   while ((bc = (TBaseClass*) next_base()) != 0) {
      cls = bc->GetClassPointer();
      if ((c = SearchGLRenderer(cls)) != 0) {
         return c;
      }
   }
   return 0;
}

//______________________________________________________________________________
TClass* TGLObject::GetGLRenderer(TClass* isa)
{
   // Return direct-rendering GL class for class isa.
   // Zero is a valid response.

   TPair* p = (TPair*) fgGLClassMap.FindObject(isa);
   TClass* cls;
   if (p != 0) {
      cls = (TClass*) p->Value();
   } else {
      cls = SearchGLRenderer(isa);
      fgGLClassMap.Add(isa, cls);
   }
   return cls;
}
 TGLObject.cxx:1
 TGLObject.cxx:2
 TGLObject.cxx:3
 TGLObject.cxx:4
 TGLObject.cxx:5
 TGLObject.cxx:6
 TGLObject.cxx:7
 TGLObject.cxx:8
 TGLObject.cxx:9
 TGLObject.cxx:10
 TGLObject.cxx:11
 TGLObject.cxx:12
 TGLObject.cxx:13
 TGLObject.cxx:14
 TGLObject.cxx:15
 TGLObject.cxx:16
 TGLObject.cxx:17
 TGLObject.cxx:18
 TGLObject.cxx:19
 TGLObject.cxx:20
 TGLObject.cxx:21
 TGLObject.cxx:22
 TGLObject.cxx:23
 TGLObject.cxx:24
 TGLObject.cxx:25
 TGLObject.cxx:26
 TGLObject.cxx:27
 TGLObject.cxx:28
 TGLObject.cxx:29
 TGLObject.cxx:30
 TGLObject.cxx:31
 TGLObject.cxx:32
 TGLObject.cxx:33
 TGLObject.cxx:34
 TGLObject.cxx:35
 TGLObject.cxx:36
 TGLObject.cxx:37
 TGLObject.cxx:38
 TGLObject.cxx:39
 TGLObject.cxx:40
 TGLObject.cxx:41
 TGLObject.cxx:42
 TGLObject.cxx:43
 TGLObject.cxx:44
 TGLObject.cxx:45
 TGLObject.cxx:46
 TGLObject.cxx:47
 TGLObject.cxx:48
 TGLObject.cxx:49
 TGLObject.cxx:50
 TGLObject.cxx:51
 TGLObject.cxx:52
 TGLObject.cxx:53
 TGLObject.cxx:54
 TGLObject.cxx:55
 TGLObject.cxx:56
 TGLObject.cxx:57
 TGLObject.cxx:58
 TGLObject.cxx:59
 TGLObject.cxx:60
 TGLObject.cxx:61
 TGLObject.cxx:62
 TGLObject.cxx:63
 TGLObject.cxx:64
 TGLObject.cxx:65
 TGLObject.cxx:66
 TGLObject.cxx:67
 TGLObject.cxx:68
 TGLObject.cxx:69
 TGLObject.cxx:70
 TGLObject.cxx:71
 TGLObject.cxx:72
 TGLObject.cxx:73
 TGLObject.cxx:74
 TGLObject.cxx:75
 TGLObject.cxx:76
 TGLObject.cxx:77
 TGLObject.cxx:78
 TGLObject.cxx:79
 TGLObject.cxx:80
 TGLObject.cxx:81
 TGLObject.cxx:82
 TGLObject.cxx:83
 TGLObject.cxx:84
 TGLObject.cxx:85
 TGLObject.cxx:86
 TGLObject.cxx:87
 TGLObject.cxx:88
 TGLObject.cxx:89
 TGLObject.cxx:90
 TGLObject.cxx:91
 TGLObject.cxx:92
 TGLObject.cxx:93
 TGLObject.cxx:94
 TGLObject.cxx:95
 TGLObject.cxx:96
 TGLObject.cxx:97
 TGLObject.cxx:98
 TGLObject.cxx:99
 TGLObject.cxx:100
 TGLObject.cxx:101
 TGLObject.cxx:102
 TGLObject.cxx:103
 TGLObject.cxx:104
 TGLObject.cxx:105
 TGLObject.cxx:106
 TGLObject.cxx:107
 TGLObject.cxx:108
 TGLObject.cxx:109
 TGLObject.cxx:110
 TGLObject.cxx:111
 TGLObject.cxx:112
 TGLObject.cxx:113
 TGLObject.cxx:114
 TGLObject.cxx:115
 TGLObject.cxx:116
 TGLObject.cxx:117
 TGLObject.cxx:118
 TGLObject.cxx:119
 TGLObject.cxx:120
 TGLObject.cxx:121
 TGLObject.cxx:122
 TGLObject.cxx:123
 TGLObject.cxx:124
 TGLObject.cxx:125
 TGLObject.cxx:126
 TGLObject.cxx:127
 TGLObject.cxx:128
 TGLObject.cxx:129
 TGLObject.cxx:130
 TGLObject.cxx:131
 TGLObject.cxx:132
 TGLObject.cxx:133
 TGLObject.cxx:134
 TGLObject.cxx:135
 TGLObject.cxx:136
 TGLObject.cxx:137
 TGLObject.cxx:138
 TGLObject.cxx:139
 TGLObject.cxx:140
 TGLObject.cxx:141
 TGLObject.cxx:142
 TGLObject.cxx:143
 TGLObject.cxx:144
 TGLObject.cxx:145
 TGLObject.cxx:146
 TGLObject.cxx:147
 TGLObject.cxx:148
 TGLObject.cxx:149