TGLScenePad.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLScenePad.cxx 36884 2010-11-23 17:52:08Z matevz $
00002 // Author:  Matevz Tadel, Jun 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, 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 "TGLScenePad.h"
00013 
00014 #include "TGLViewer.h"
00015 #include "TGLLogicalShape.h"
00016 #include "TGLPhysicalShape.h"
00017 #include "TGLObject.h"
00018 #include "TGLStopwatch.h"
00019 #include "TBuffer3D.h"
00020 #include "TBuffer3DTypes.h"
00021 
00022 #include "TGLFaceSet.h"
00023 #include "TGLPolyLine.h"
00024 #include "TGLPolyMarker.h"
00025 #include "TGLCylinder.h"
00026 #include "TGLSphere.h"
00027 
00028 #include "TVirtualPad.h"
00029 #include "TAtt3D.h"
00030 #include "TClass.h"
00031 #include "TList.h"
00032 #include "TMath.h"
00033 
00034 #include "TGLPlot3D.h"
00035 
00036 
00037 //______________________________________________________________________________
00038 // TGLScenePad
00039 //
00040 // Implements VirtualViewer3D interface and fills the base-class
00041 // visualization structures from pad contents.
00042 //
00043 
00044 ClassImp(TGLScenePad)
00045 
00046 
00047 //______________________________________________________________________________
00048 TGLScenePad::TGLScenePad(TVirtualPad* pad) :
00049    TVirtualViewer3D(),
00050    TGLScene(),
00051 
00052    fPad               (pad),
00053    fInternalPIDs      (kFALSE),
00054    fNextInternalPID   (1), // 0 reserved
00055    fLastPID           (0), // 0 reserved
00056    fAcceptedPhysicals (0),
00057    fComposite         (0),
00058    fCSLevel           (0),
00059    fSmartRefresh      (kFALSE)
00060 {
00061    // Constructor.
00062 }
00063 
00064 
00065 /******************************************************************************/
00066 // Histo import and Sub-pad traversal
00067 /******************************************************************************/
00068 
00069 //______________________________________________________________________________
00070 void TGLScenePad::AddHistoPhysical(TGLLogicalShape* log)
00071 {
00072    // Scale and rotate a histo object to mimic placement in canvas.
00073 
00074    Double_t how = ((Double_t) gPad->GetWh()) / gPad->GetWw();
00075 
00076    Double_t lw = gPad->GetAbsWNDC();
00077    Double_t lh = gPad->GetAbsHNDC() * how;
00078    Double_t lm = TMath::Min(lw, lh);
00079 
00080    const TGLBoundingBox& bb = log->BoundingBox();
00081 
00082    // Timur always packs histos in a square: let's just take x-diff.
00083    Double_t size  = TMath::Sqrt(3) * (bb.XMax() - bb.XMin());
00084    Double_t scale = lm / size;
00085    TGLVector3 scaleVec(scale, scale, scale);
00086 
00087    Double_t tx = gPad->GetAbsXlowNDC() + lw;
00088    Double_t ty = gPad->GetAbsYlowNDC() * how + lh;
00089    TGLVector3 transVec(0, ty, tx); // For viewer convention (starts looking along -x).
00090 
00091    // XXXX plots no longer centered at 0. Or they never were?
00092    // Impossible to translate and scale them as they should be, it
00093    // seems. This requers further investigation, eventually.
00094    //
00095    // bb.Dump();
00096    // printf("lm=%f, size=%f, scale=%f, tx=%f, ty=%f\n",
00097    //        lm, size, scale, tx, ty);
00098    //
00099    // TGLVector3 c(bb.Center().Arr());
00100    // c.Negate();
00101    // c.Dump();
00102    // mat.Translate(c);
00103 
00104    TGLMatrix mat;
00105    mat.Scale(scaleVec);
00106    mat.Translate(transVec);
00107    mat.RotateLF(3, 2, TMath::PiOver2());
00108    mat.RotateLF(1, 3, TMath::DegToRad()*gPad->GetTheta());
00109    mat.RotateLF(1, 2, TMath::DegToRad()*(gPad->GetPhi() - 90));
00110    Float_t rgba[4] = { 1, 1, 1, 1};
00111    TGLPhysicalShape* phys = new TGLPhysicalShape
00112       (fNextInternalPID++, *log, mat, false, rgba);
00113    AdoptPhysical(*phys);
00114 
00115    // Part of XXXX above.
00116    // phys->BoundingBox().Dump();
00117 }
00118 
00119 //______________________________________________________________________________
00120 void TGLScenePad::SubPadPaint(TVirtualPad* pad)
00121 {
00122    // Iterate over pad-primitves and import them.
00123 
00124    TVirtualPad      *padsav  = gPad;
00125    TVirtualViewer3D *vv3dsav = pad->GetViewer3D();
00126    gPad = pad;
00127    pad->SetViewer3D(this);
00128 
00129    TList       *prims = pad->GetListOfPrimitives();
00130    TObjOptLink *lnk   = (prims) ? (TObjOptLink*)prims->FirstLink() : 0;
00131    while (lnk)
00132    {
00133       ObjectPaint(lnk->GetObject(), lnk->GetOption());
00134       lnk = (TObjOptLink*)lnk->Next();
00135    }
00136 
00137    pad->SetViewer3D(vv3dsav);
00138    gPad = padsav;
00139 }
00140 
00141 
00142 //______________________________________________________________________________
00143 void TGLScenePad::ObjectPaint(TObject* obj, Option_t* opt)
00144 {
00145    // Override of virtual TVirtualViewer3D::ObjectPaint().
00146    // Special handling of 2D/3D histograms to activate Timur's
00147    // histo-painters.
00148 
00149    TGLPlot3D* log = TGLPlot3D::CreatePlot(obj, opt, gPad);
00150    if (log)
00151    {
00152       AdoptLogical(*log);
00153       AddHistoPhysical(log);
00154    }
00155    else if (obj->InheritsFrom(TAtt3D::Class()))
00156    {
00157       // Handle 3D primitives here.
00158       obj->Paint(opt);
00159    }
00160    else if (obj->InheritsFrom(TVirtualPad::Class()))
00161    {
00162       SubPadPaint(dynamic_cast<TVirtualPad*>(obj));
00163    }
00164    else
00165    {
00166       // Handle 2D primitives here.
00167       obj->Paint(opt);
00168    }
00169 }
00170 
00171 //______________________________________________________________________________
00172 void TGLScenePad::PadPaintFromViewer(TGLViewer* viewer)
00173 {
00174    // Entry point for requesting update of scene's contents from
00175    // gl-viewer.
00176 
00177    Bool_t sr = fSmartRefresh;
00178    fSmartRefresh = viewer->GetSmartRefresh();
00179 
00180    PadPaint(fPad);
00181 
00182    fSmartRefresh = sr;
00183 }
00184 
00185 //______________________________________________________________________________
00186 void TGLScenePad::PadPaint(TVirtualPad* pad)
00187 {
00188    // Entry point for updating scene contents via VirtualViewer3D
00189    // interface.
00190    // For now this is handled by TGLViewer as it remains
00191    // the 'Viewer3D' of given pad.
00192 
00193    if (pad != fPad)
00194    {
00195       Error("TGLScenePad::PadPaint", "Mismatch between pad argument and data-member!");
00196       return;
00197    }
00198 
00199    BeginScene();
00200    SubPadPaint(fPad);
00201    EndScene();
00202 }
00203 
00204 
00205 //==============================================================================
00206 // VV3D
00207 //==============================================================================
00208 
00209 //______________________________________________________________________________
00210 void TGLScenePad::BeginScene()
00211 {
00212    // Start building of the scene.
00213    // Old contents is dropped, unless smart-refresh is in active. Then
00214    // the object supporting it are kept in a cache and possibly reused.
00215    //
00216    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00217    // for description of viewer architecture.
00218 
00219    if (gDebug>2) {
00220       Info("TGLScenePad::BeginScene", "entering.");
00221    }
00222 
00223    if ( ! BeginUpdate()) {
00224       Error("TGLScenePad::BeginScene", "could not take scene lock.");
00225       return;
00226    }
00227 
00228    UInt_t destroyedLogicals  = 0;
00229    UInt_t destroyedPhysicals = 0;
00230 
00231    TGLStopwatch stopwatch;
00232    if (gDebug > 2) {
00233       stopwatch.Start();
00234    }
00235 
00236    // Rebuilds can potentially invalidate all logical and
00237    // physical shapes.
00238    // Physicals must be removed first.
00239    destroyedPhysicals = DestroyPhysicals();
00240    if (fSmartRefresh) {
00241       destroyedLogicals = BeginSmartRefresh();
00242    } else {
00243       destroyedLogicals = DestroyLogicals();
00244    }
00245 
00246    // Potentially using external physical IDs
00247    fInternalPIDs = kFALSE;
00248 
00249    // Reset internal physical ID counter
00250    fNextInternalPID = 1;
00251    fLastPID         = 0;
00252 
00253    // Reset tracing info
00254    fAcceptedPhysicals = 0;
00255 
00256    if (gDebug > 2) {
00257       Info("TGLScenePad::BeginScene", "destroyed %d physicals %d logicals in %f msec",
00258             destroyedPhysicals, destroyedLogicals, stopwatch.End());
00259       DumpMapSizes();
00260    }
00261 }
00262 
00263 //______________________________________________________________________________
00264 void TGLScenePad::EndScene()
00265 {
00266    // End building of the scene.
00267    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00268    // for description of viewer architecture
00269 
00270    if (fSmartRefresh) {
00271       EndSmartRefresh();
00272    }
00273 
00274    EndUpdate();
00275 
00276    if (gDebug > 2) {
00277       Info("TGLScenePad::EndScene", "Accepted %d physicals", fAcceptedPhysicals);
00278       DumpMapSizes();
00279    }
00280 }
00281 
00282 //______________________________________________________________________________
00283 Int_t TGLScenePad::AddObject(const TBuffer3D& buffer, Bool_t* addChildren)
00284 {
00285    // Add an object to the viewer, using internal physical IDs
00286    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00287    // for description of viewer architecture
00288 
00289    // If this is called we are generating internal physical IDs
00290    fInternalPIDs = kTRUE;
00291    Int_t sections = AddObject(fNextInternalPID, buffer, addChildren);
00292    return sections;
00293 }
00294 
00295 //______________________________________________________________________________
00296 Int_t TGLScenePad::AddObject(UInt_t physicalID, const TBuffer3D& buffer, Bool_t* addChildren)
00297 {
00298    // Add an object to the scene, using an external physical ID
00299    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00300    // for description of viewer architecture
00301 
00302    // TODO: Break this up and make easier to understand. This is
00303    // pretty convoluted due to the large number of cases it has to
00304    // deal with:
00305    // i)   exisiting physical and/or logical;
00306    // ii)  external provider may or may not supply bounding box;
00307    // iii) local/global reference frame;
00308    // iv)  deferred filling of some sections of the buffer;
00309    // v)   internal or external physical IDs;
00310    // vi)  composite components as special case.
00311    //
00312    // The buffer filling means the function is re-entrant which adds
00313    // to complication.
00314 
00315    if (physicalID == 0) {
00316       Error("TGLScenePad::AddObject", "0 physical ID reserved");
00317       return TBuffer3D::kNone;
00318    }
00319 
00320    // Internal and external physical IDs cannot be mixed in a scene build
00321    if (fInternalPIDs && physicalID != fNextInternalPID) {
00322       Error("TGLScenePad::AddObject", "invalid next physical ID - mix of internal + external IDs?");
00323       return TBuffer3D::kNone;
00324    }
00325 
00326    // We always take all children ... interest is viewer dependent.
00327    if (addChildren)
00328       *addChildren = kTRUE;
00329 
00330    // Scene should be modify locked
00331    if (CurrentLock() != kModifyLock) {
00332       Error("TGLScenePad::AddObject", "expected scene to be modify-locked.");
00333       return TBuffer3D::kNone;
00334    }
00335 
00336    // Note that 'object' here is really a physical/logical pair described
00337    // in buffer + physical ID.
00338 
00339    // If adding component to a current partial composite do this now
00340    if (fComposite) {
00341       RootCsg::TBaseMesh *newMesh = RootCsg::ConvertToMesh(buffer);
00342       // Solaris CC can't create stl pair with enumerate type
00343       fCSTokens.push_back(std::make_pair(static_cast<UInt_t>(TBuffer3D::kCSNoOp), newMesh));
00344       return TBuffer3D::kNone;
00345    }
00346 
00347    // TODO: Could be a data member - save possible double lookup?
00348    TGLPhysicalShape *physical = FindPhysical(physicalID);
00349    TGLLogicalShape  *logical  = 0;
00350 
00351    // If we have a valid (non-zero) ID, see if the logical is already cached.
00352    // If it is not, try to create a direct renderer object.
00353    if (buffer.fID)
00354    {
00355       logical = FindLogical(buffer.fID);
00356       if (!logical)
00357          logical = AttemptDirectRenderer(buffer.fID);
00358    }
00359 
00360    // First attempt to add this physical.
00361    if (physicalID != fLastPID)
00362    {
00363       // Existing physical.
00364       // MT comment: I don't think this should ever happen.
00365       if (physical)
00366       {
00367          // If we have physical we should have logical cached, too.
00368          if (!logical) {
00369             Error("TGLScenePad::AddObject", "cached physical with no assocaited cached logical");
00370          }
00371 
00372          // Since we already have logical no need for further checks.
00373          // Done ... prepare for next object.
00374          if (fInternalPIDs)
00375             ++fNextInternalPID;
00376 
00377          return TBuffer3D::kNone;
00378       }
00379 
00380       // Need any extra sections in buffer?
00381       Bool_t includeRaw    = (logical == 0);
00382       Int_t  extraSections = ValidateObjectBuffer(buffer, includeRaw);
00383       if (extraSections != TBuffer3D::kNone)
00384          return extraSections;
00385 
00386       fLastPID = physicalID;
00387    }
00388 
00389    if (fLastPID != physicalID) {
00390       Error("TGLScenePad::AddObject", "internal physical ID tracking error?");
00391    }
00392 
00393    // Being here means we need to add a physical, maybe logical as well.
00394    if (physical) {
00395       Error("TGLScenePad::AddObject", "expecting to require physical");
00396       return TBuffer3D::kNone;
00397    }
00398 
00399    // Create logical if required.
00400    if (!logical)
00401    {
00402       logical = CreateNewLogical(buffer);
00403       if (!logical) {
00404          Error("TGLScenePad::AddObject", "failed to create logical");
00405          return TBuffer3D::kNone;
00406       }
00407       // Add logical to scene
00408       AdoptLogical(*logical);
00409    }
00410 
00411    // Create the physical, bind it to the logical and add it to the scene.
00412    physical = CreateNewPhysical(physicalID, buffer, *logical);
00413 
00414    if (physical)
00415    {
00416       AdoptPhysical(*physical);
00417       buffer.fPhysicalID = physicalID;
00418       ++fAcceptedPhysicals;
00419       if (gDebug>3 && fAcceptedPhysicals%1000 == 0) {
00420          Info("TGLScenePad::AddObject", "added %d physicals", fAcceptedPhysicals);
00421       }
00422    }
00423    else
00424    {
00425       Error("TGLScenePad::AddObject", "failed to create physical");
00426    }
00427 
00428    // Done ... prepare for next object.
00429    if (fInternalPIDs)
00430       fNextInternalPID++;
00431 
00432    return TBuffer3D::kNone;
00433 }
00434 
00435 //______________________________________________________________________________
00436 Bool_t TGLScenePad::OpenComposite(const TBuffer3D& buffer, Bool_t* addChildren)
00437 {
00438    // Open new composite container.
00439    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00440    // for description of viewer architecture.
00441 
00442    if (fComposite) {
00443       Error("TGLScenePad::OpenComposite", "composite already open");
00444       return kFALSE;
00445    }
00446    UInt_t extraSections = AddObject(buffer, addChildren);
00447    if (extraSections != TBuffer3D::kNone) {
00448       Error("TGLScenePad::OpenComposite", "expected top level composite to not require extra buffer sections");
00449    }
00450 
00451    // If composite was created it is of interest - we want the rest of the
00452    // child components
00453    if (fComposite) {
00454       return kTRUE;
00455    } else {
00456       return kFALSE;
00457    }
00458 }
00459 
00460 //______________________________________________________________________________
00461 void TGLScenePad::CloseComposite()
00462 {
00463    // Close composite container
00464    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00465    // for description of viewer architecture
00466 
00467    // If we have a partially complete composite build it now
00468    if (fComposite) {
00469       // TODO: Why is this member and here - only used in BuildComposite()
00470       fCSLevel = 0;
00471 
00472       RootCsg::TBaseMesh *resultMesh = BuildComposite();
00473       fComposite->SetFromMesh(resultMesh);
00474       delete resultMesh;
00475       for (UInt_t i = 0; i < fCSTokens.size(); ++i) delete fCSTokens[i].second;
00476       fCSTokens.clear();
00477       fComposite = 0;
00478    }
00479 }
00480 
00481 //______________________________________________________________________________
00482 void TGLScenePad::AddCompositeOp(UInt_t operation)
00483 {
00484    // Add composite operation used to combine objects added via AddObject
00485    // TVirtualViewer3D interface overload - see base/src/TVirtualViewer3D.cxx
00486    // for description of viewer architecture
00487 
00488    fCSTokens.push_back(std::make_pair(operation, (RootCsg::TBaseMesh *)0));
00489 }
00490 
00491 
00492 // Protected methods
00493 
00494 //______________________________________________________________________________
00495 Int_t TGLScenePad::ValidateObjectBuffer(const TBuffer3D& buffer, Bool_t includeRaw) const
00496 {
00497    // Validate if the passed 'buffer' contains all sections we require to add object.
00498    // Returns Int_t combination of TBuffer::ESection flags still required - or
00499    // TBuffer3D::kNone if buffer is valid.
00500    // If 'includeRaw' is kTRUE check for kRaw/kRawSizes - skip otherwise.
00501    // See base/src/TVirtualViewer3D.cxx for description of viewer architecture
00502 
00503    // kCore: Should always be filled
00504    if (!buffer.SectionsValid(TBuffer3D::kCore)) {
00505       Error("TGLScenePad::ValidateObjectBuffer", "kCore section of buffer should be filled always");
00506       return TBuffer3D::kNone;
00507    }
00508 
00509    // Need to check raw (kRaw/kRawSizes)?
00510    if (!includeRaw) {
00511       return TBuffer3D::kNone;
00512    }
00513 
00514    // kRawSizes / kRaw: These are on demand based on shape type
00515    Bool_t needRaw = kFALSE;
00516 
00517    // We need raw tesselation in these cases:
00518    //
00519    // 1. Shape type is NOT kSphere / kTube / kTubeSeg / kCutTube / kComposite
00520    if (buffer.Type() != TBuffer3DTypes::kSphere  &&
00521        buffer.Type() != TBuffer3DTypes::kTube    &&
00522        buffer.Type() != TBuffer3DTypes::kTubeSeg &&
00523        buffer.Type() != TBuffer3DTypes::kCutTube &&
00524        buffer.Type() != TBuffer3DTypes::kComposite)
00525    {
00526       needRaw = kTRUE;
00527    }
00528    // 2. Sphere type is kSPHE, but the sphere is hollow and/or cut - we
00529    //    do not support native drawing of these currently
00530    else if (buffer.Type() == TBuffer3DTypes::kSphere)
00531    {
00532       const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
00533       if (sphereBuffer) {
00534          if (!sphereBuffer->IsSolidUncut()) {
00535             needRaw = kTRUE;
00536          }
00537       } else {
00538          Error("TGLScenePad::ValidateObjectBuffer", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
00539          return TBuffer3D::kNone;
00540       }
00541    }
00542    // 3. kBoundingBox is not filled - we generate a bounding box from
00543    else if (!buffer.SectionsValid(TBuffer3D::kBoundingBox))
00544    {
00545       needRaw = kTRUE;
00546    }
00547    // 4. kShapeSpecific is not filled - except in case of top level composite
00548    else if (!buffer.SectionsValid(TBuffer3D::kShapeSpecific) &&
00549              buffer.Type() != TBuffer3DTypes::kComposite)
00550    {
00551       needRaw = kTRUE;
00552    }
00553    // 5. We are a component (not the top level) of a composite shape
00554    else if (fComposite)
00555    {
00556       needRaw = kTRUE;
00557    }
00558 
00559    if (needRaw && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
00560       return TBuffer3D::kRawSizes|TBuffer3D::kRaw;
00561    } else {
00562       return TBuffer3D::kNone;
00563    }
00564 }
00565 
00566 //______________________________________________________________________________
00567 TGLLogicalShape* TGLScenePad::CreateNewLogical(const TBuffer3D& buffer) const
00568 {
00569    // Create and return a new TGLLogicalShape from the supplied buffer
00570    TGLLogicalShape * newLogical = 0;
00571 
00572    if (buffer.fColor == 1) // black -> light-brown; std behaviour for geom
00573       const_cast<TBuffer3D&>(buffer).fColor = 42;
00574 
00575    switch (buffer.Type())
00576    {
00577       case TBuffer3DTypes::kLine:
00578          newLogical = new TGLPolyLine(buffer);
00579          break;
00580       case TBuffer3DTypes::kMarker:
00581          newLogical = new TGLPolyMarker(buffer);
00582          break;
00583       case TBuffer3DTypes::kSphere:
00584       {
00585          const TBuffer3DSphere * sphereBuffer = dynamic_cast<const TBuffer3DSphere *>(&buffer);
00586          if (sphereBuffer)
00587          {
00588             // We can only draw solid uncut spheres natively at present.
00589             // If somebody already passed the raw buffer, he probably wants us to use it.
00590             if (sphereBuffer->IsSolidUncut() && !buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw))
00591             {
00592                newLogical = new TGLSphere(*sphereBuffer);
00593             } else {
00594                newLogical = new TGLFaceSet(buffer);
00595             }
00596          } else {
00597             Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kSphere' to TBuffer3DSphere");
00598          }
00599          break;
00600       }
00601       case TBuffer3DTypes::kTube:
00602       case TBuffer3DTypes::kTubeSeg:
00603       case TBuffer3DTypes::kCutTube:
00604       {
00605          const TBuffer3DTube * tubeBuffer = dynamic_cast<const TBuffer3DTube *>(&buffer);
00606          if (tubeBuffer)
00607          {
00608             // If somebody already passed the raw buffer, he probably wants us to use it.
00609             if (!buffer.SectionsValid(TBuffer3D::kRawSizes|TBuffer3D::kRaw)) {
00610                newLogical = new TGLCylinder(*tubeBuffer);
00611             } else {
00612                newLogical = new TGLFaceSet(buffer);
00613             }
00614          } else {
00615             Error("TGLScenePad::CreateNewLogical", "failed to cast buffer of type 'kTube/kTubeSeg/kCutTube' to TBuffer3DTube");
00616          }
00617          break;
00618       }
00619       case TBuffer3DTypes::kComposite:
00620       {
00621          // Create empty faceset and record partial complete composite object
00622          // Will be populated with mesh in CloseComposite()
00623          if (fComposite)
00624          {
00625             Error("TGLScenePad::CreateNewLogical", "composite already open");
00626          }
00627          fComposite = new TGLFaceSet(buffer);
00628          newLogical = fComposite;
00629          break;
00630       }
00631       default:
00632          newLogical = new TGLFaceSet(buffer);
00633          break;
00634    }
00635 
00636    return newLogical;
00637 }
00638 
00639 //______________________________________________________________________________
00640 TGLPhysicalShape*
00641 TGLScenePad::CreateNewPhysical(UInt_t ID, const TBuffer3D& buffer,
00642                                const TGLLogicalShape& logical) const
00643 {
00644    // Create and return a new TGLPhysicalShape with id 'ID', using
00645    // 'buffer' placement information (translation etc), and bound to
00646    // suppled 'logical'
00647 
00648    // Extract indexed color from buffer
00649    // TODO: Still required? Better use proper color triplet in buffer?
00650    Int_t colorIndex = buffer.fColor;
00651    if (colorIndex < 0) colorIndex = 42;
00652    Float_t rgba[4];
00653    TGLScene::RGBAFromColorIdx(rgba, colorIndex, buffer.fTransparency);
00654    return new TGLPhysicalShape(ID, logical, buffer.fLocalMaster,
00655                                buffer.fReflection, rgba);
00656 }
00657 
00658 //______________________________________________________________________________
00659 RootCsg::TBaseMesh* TGLScenePad::BuildComposite()
00660 {
00661    // Build and return composite shape mesh
00662    const CSPart_t &currToken = fCSTokens[fCSLevel];
00663    UInt_t opCode = currToken.first;
00664 
00665    if (opCode != TBuffer3D::kCSNoOp) {
00666       ++fCSLevel;
00667       RootCsg::TBaseMesh *left = BuildComposite();
00668       RootCsg::TBaseMesh *right = BuildComposite();
00669       //RootCsg::TBaseMesh *result = 0;
00670       switch (opCode) {
00671       case TBuffer3D::kCSUnion:
00672          return RootCsg::BuildUnion(left, right);
00673       case TBuffer3D::kCSIntersection:
00674          return RootCsg::BuildIntersection(left, right);
00675       case TBuffer3D::kCSDifference:
00676          return RootCsg::BuildDifference(left, right);
00677       default:
00678          Error("BuildComposite", "Wrong operation code %d\n", opCode);
00679          return 0;
00680       }
00681    } else return fCSTokens[fCSLevel++].second;
00682 }
00683 
00684 //______________________________________________________________________________
00685 TGLLogicalShape* TGLScenePad::AttemptDirectRenderer(TObject* id)
00686 {
00687    // Try to construct an appropriate logical-shape sub-class based
00688    // on id'class, following convention that SomeClassGL is a suitable
00689    // renderer for class SomeClass.
00690 
00691    TClass* cls = TGLObject::GetGLRenderer(id->IsA());
00692    if (cls == 0)
00693       return 0;
00694 
00695    TGLObject* rnr = reinterpret_cast<TGLObject*>(cls->New());
00696    if (rnr) {
00697       Bool_t status;
00698       try
00699       {
00700          status = rnr->SetModel(id);
00701       }
00702       catch (std::exception&)
00703       {
00704          status = kFALSE;
00705       }
00706       if (!status)
00707       {
00708          Warning("TGLScenePad::AttemptDirectRenderer", "failed initializing direct rendering.");
00709          delete rnr;
00710          return 0;
00711       }
00712       rnr->SetBBox();
00713       AdoptLogical(*rnr);
00714    }
00715    return rnr;
00716 }

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