TGLSceneBase.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLSceneBase.cxx 32335 2010-02-12 15:02:40Z matevz $
00002 // Author:  Matevz Tadel, Feb 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 "TGLSceneBase.h"
00013 #include "TGLSceneInfo.h"
00014 #include "TGLViewerBase.h"
00015 #include "TGLRnrCtx.h"
00016 #include "TGLCamera.h"
00017 #include "TGLClip.h"
00018 #include "TGLIncludes.h"
00019 
00020 #include <TMath.h>
00021 
00022 #include <string>
00023 #include <algorithm>
00024 
00025 //==============================================================================
00026 // TGLSceneBase
00027 //==============================================================================
00028 
00029 //______________________________________________________________________
00030 //
00031 // Scene base-class --  provides basic interface expected by the
00032 // TGLViewer or its sub-classes:
00033 // * unique scene id
00034 // * scene locking
00035 // * overall bounding box
00036 // * list of viewers displaying the scene (for update propagation)
00037 // * virtual interface for draw/select/render (?)
00038 //
00039 // The standard ROOT OpenGL scene is implemented in direct sub-class
00040 // TGLScene.
00041 //
00042 // Note that while each scene can be shared among several viewers, ALL
00043 // of them are obliged to share the same display-list space (this can
00044 // be achieved on GL-context creation time; Matevz believes that by
00045 // default all GL contexts must use shared display-lists etc).
00046 
00047 
00048 ClassImp(TGLSceneBase);
00049 
00050 UInt_t TGLSceneBase::fgSceneIDSrc = 1;
00051 
00052 //______________________________________________________________________________
00053 TGLSceneBase::TGLSceneBase() :
00054    TGLLockable(),
00055 
00056    fTimeStamp        (1),
00057    fMinorStamp       (1),
00058    fLOD              (TGLRnrCtx::kLODHigh),
00059    fStyle            (TGLRnrCtx::kStyleUndef),
00060    fWFLineW          (0),
00061    fOLLineW          (0),
00062    fClip             (0),
00063    fSelectable       (kTRUE),
00064    fBoundingBox      (),
00065    fBoundingBoxValid (kFALSE),
00066    fDoFrustumCheck   (kTRUE),
00067    fDoClipCheck      (kTRUE),
00068    fAutoDestruct     (kTRUE)
00069 {
00070    // Default constructor.
00071 
00072    fSceneID = fgSceneIDSrc++;
00073    fName = Form("unnamed-%d", fSceneID);
00074 }
00075 
00076 //______________________________________________________________________________
00077 TGLSceneBase::~TGLSceneBase()
00078 {
00079    // Destructor.
00080 
00081    for (ViewerList_i i=fViewers.begin(); i!=fViewers.end(); ++i)
00082    {
00083       (*i)->SceneDestructing(this);
00084    }
00085 }
00086 
00087 //______________________________________________________________________________
00088 void TGLSceneBase::AddViewer(TGLViewerBase* viewer)
00089 {
00090    // Add viewer to the list.
00091 
00092    ViewerList_i i = std::find(fViewers.begin(), fViewers.end(), viewer);
00093    if (i == fViewers.end())
00094       fViewers.push_back(viewer);
00095    else
00096       Warning("TGLSceneBase::AddViewer", "viewer already in the list.");
00097 }
00098 
00099 //______________________________________________________________________________
00100 void TGLSceneBase::RemoveViewer(TGLViewerBase* viewer)
00101 {
00102    // Remove viewer from the list.
00103    // If auto-destruct is on and the last viewer is removed the scene
00104    // destructs itself.
00105 
00106    ViewerList_i i = std::find(fViewers.begin(), fViewers.end(), viewer);
00107    if (i != fViewers.end())
00108       fViewers.erase(i);
00109    else
00110       Warning("TGLSceneBase::RemoveViewer", "viewer not found in the list.");
00111 
00112    if (fViewers.empty() && fAutoDestruct)
00113    {
00114       if (gDebug > 0)
00115          Info("TGLSceneBase::RemoveViewer", "scene '%s' not used - autodestructing.", GetName());
00116       delete this;
00117    }
00118 }
00119 //______________________________________________________________________________
00120 void TGLSceneBase::TagViewersChanged()
00121 {
00122    // Tag all viewers as changed.
00123 
00124    for (ViewerList_i i=fViewers.begin(); i!=fViewers.end(); ++i)
00125    {
00126       (*i)->Changed();
00127    }
00128 }
00129 
00130 /**************************************************************************/
00131 
00132 //______________________________________________________________________________
00133 const char* TGLSceneBase::LockIdStr() const
00134 {
00135    // Name printed on locking info messages.
00136 
00137    return Form("TGLSceneBase %s", fName.Data());
00138 }
00139 
00140 /**************************************************************************/
00141 // SceneInfo management
00142 /**************************************************************************/
00143 
00144 //______________________________________________________________________________
00145 TGLSceneInfo* TGLSceneBase::CreateSceneInfo(TGLViewerBase* view)
00146 {
00147    // Create a scene-info instance appropriate for this scene class.
00148    // Here we instantiate the scene-info base-class TGLSceneInfo.
00149 
00150    return new TGLSceneInfo(view, this);
00151 }
00152 
00153 //______________________________________________________________________________
00154 void TGLSceneBase::RebuildSceneInfo(TGLRnrCtx& ctx)
00155 {
00156    // Fill scene-info with very basic information that is practically
00157    // view independent. This is called when scene content is changed
00158    // or when camera-interest changes.
00159 
00160    TGLSceneInfo* sinfo = ctx.GetSceneInfo();
00161 
00162    sinfo->SetLastClip(0);
00163    sinfo->SetLastCamera(0);
00164 }
00165 
00166 //______________________________________________________________________________
00167 void TGLSceneBase::UpdateSceneInfo(TGLRnrCtx& ctx)
00168 {
00169    // Fill scene-info with information needed for rendering, take into
00170    // account the render-context (viewer state, camera, clipping).
00171    // Usually called from TGLViewer before rendering a scene if some
00172    // moderately significant part of render-context has changed.
00173    //
00174    // Here we update the basic state (clear last-LOD, mark the time,
00175    // set global <-> scene transforamtion matrices) and potentially
00176    // study and refine the clipping planes based on scene bounding box.
00177 
00178    if (gDebug > 3)
00179    {
00180       Info("TGLSceneBase::UpdateSceneInfo",
00181            "'%s' timestamp=%u",
00182            GetName(), fTimeStamp);
00183    }
00184 
00185    TGLSceneInfo* sinfo = ctx.GetSceneInfo();
00186 
00187    // ------------------------------------------------------------
00188    // Reset
00189    // ------------------------------------------------------------
00190 
00191    sinfo->SetLastLOD   (TGLRnrCtx::kLODUndef);
00192    sinfo->SetLastStyle (TGLRnrCtx::kStyleUndef);
00193    sinfo->SetSceneStamp(fTimeStamp);
00194 
00195    sinfo->InFrustum (kTRUE);
00196    sinfo->InClip    (kTRUE);
00197    sinfo->ClipMode  (TGLSceneInfo::kClipNone);
00198 
00199    // ------------------------------------------------------------
00200    // Setup
00201    // ------------------------------------------------------------
00202 
00203    // !!!
00204    // setup scene transformation matrices
00205    // so far the matrices in scene-base and scene-info are not enabled
00206    // sinfo->fSceneToGlobal = scene-info-trans * scene-base-trans;
00207    // sinfo->fGlobalToScene = inv of above;
00208    // transform to clip and to eye coordinates also interesting
00209    //
00210    // All these are now done in TGLViewerBase::PreRender() via
00211    // TGLSceneInfo::SetupTransformsAndBBox().
00212 
00213    sinfo->SetLastClip(0);
00214    sinfo->FrustumPlanes().clear();
00215    sinfo->ClipPlanes().clear();
00216 
00217    if (fDoFrustumCheck)
00218    {
00219       for (Int_t i=0; i<TGLCamera::kPlanesPerFrustum; ++i)
00220       {
00221          TGLPlane p = ctx.GetCamera()->FrustumPlane((TGLCamera::EFrustumPlane)i);
00222          // !!! transform plane
00223          switch (BoundingBox().Overlap(p))
00224          {
00225             case kInside:  // Whole scene passes ... no need to store it.
00226                break;
00227             case kPartial:
00228                sinfo->FrustumPlanes().push_back(p);
00229                break;
00230             case kOutside:
00231                sinfo->InFrustum(kFALSE);
00232                break;
00233          }
00234       }
00235    }
00236 
00237    if (fDoClipCheck && ctx.HasClip())
00238    {
00239       if (ctx.Clip()->GetMode() == TGLClip::kOutside)
00240          sinfo->ClipMode(TGLSceneInfo::kClipOutside);
00241       else
00242          sinfo->ClipMode(TGLSceneInfo::kClipInside);
00243 
00244       std::vector<TGLPlane> planeSet;
00245       ctx.Clip()->PlaneSet(planeSet);
00246 
00247       // Strip any planes outside the scene bounding box - no effect
00248       std::vector<TGLPlane>::iterator it = planeSet.begin();
00249       while (it != planeSet.end())
00250       {
00251          // !!! transform plane
00252          switch (BoundingBox().Overlap(*it))
00253          {
00254             case kInside:  // Whole scene passes ... no need to store it.
00255                break;
00256             case kPartial:
00257                sinfo->ClipPlanes().push_back(*it);
00258                break;
00259             case kOutside: // Depends on mode
00260                if (sinfo->ClipMode() == TGLSceneInfo::kClipOutside)
00261                {
00262                   // Scene is outside of whole clip object - nothing visible.
00263                   sinfo->InClip(kFALSE);
00264                }
00265                else
00266                {
00267                   // Scene is completely inside of whole clip object -
00268                   // draw all scene without clipping.
00269                   sinfo->ClipMode(TGLSceneInfo::kClipNone);
00270                }
00271                // In either case further checks not needed.
00272                sinfo->ClipPlanes().clear();
00273                return;
00274          }
00275          ++it;
00276       }
00277       sinfo->SetLastClip(ctx.Clip());
00278       sinfo->SetClipStamp(ctx.Clip()->TimeStamp());
00279    }
00280 
00281    sinfo->SetLastCamera(ctx.GetCamera());
00282    sinfo->SetCameraStamp(ctx.GetCamera()->TimeStamp());
00283 }
00284 
00285 //______________________________________________________________________________
00286 void TGLSceneBase::LodifySceneInfo(TGLRnrCtx& ctx)
00287 {
00288    // Setup LOD-dependant values in scene-info.
00289    //
00290    // Nothing to be done here but to store the last LOD.
00291 
00292    if (gDebug > 3)
00293    {
00294       Info("TGLSceneBase::LodifySceneInfo",
00295            "'%s' timestamp=%u lod=%d",
00296            GetName(), fTimeStamp, ctx.CombiLOD());
00297    }
00298 
00299    TGLSceneInfo & sInfo = * ctx.GetSceneInfo();
00300    sInfo.SetLastLOD(ctx.CombiLOD());
00301 }
00302 
00303 
00304 /**************************************************************************/
00305 // Rendering
00306 /**************************************************************************/
00307 
00308 //______________________________________________________________________________
00309 void TGLSceneBase::PreDraw(TGLRnrCtx & rnrCtx)
00310 {
00311    // Perform basic pre-render initialization:
00312    //  - calculate LOD, Style, Clipping,
00313    //  - build draw lists.
00314    //
00315    // This is called in the beginning of the GL-viewer draw cycle.
00316 
00317    if ( ! IsDrawOrSelectLock()) {
00318       Error("TGLSceneBase::FullRender", "expected Draw or Select Lock");
00319    }
00320 
00321    TGLSceneInfo& sInfo = * rnrCtx.GetSceneInfo();
00322 
00323    // Bounding-box check done elsewhere (in viewer::pre-render)
00324 
00325    if (fTimeStamp > sInfo.SceneStamp())
00326    {
00327       RebuildSceneInfo(rnrCtx);
00328    }
00329 
00330 
00331    Bool_t needUpdate =  sInfo.HasUpdateTimeouted();
00332 
00333    if (rnrCtx.GetCamera() != sInfo.LastCamera())
00334    {
00335       sInfo.ResetCameraStamp();
00336       needUpdate = kTRUE;
00337    }
00338    else if (rnrCtx.GetCamera()->TimeStamp() > sInfo.CameraStamp())
00339    {
00340       needUpdate = kTRUE;
00341    }
00342 
00343    TGLClip* clip = 0;
00344    if (sInfo.Clip() != 0) clip = sInfo.Clip();
00345    else if (fClip   != 0) clip = fClip;
00346    else                   clip = rnrCtx.ViewerClip();
00347    if (clip != sInfo.LastClip())
00348    {
00349       sInfo.ResetClipStamp();
00350       needUpdate = kTRUE;
00351    }
00352    else if (clip && clip->TimeStamp() > sInfo.ClipStamp())
00353    {
00354       needUpdate = kTRUE;
00355    }
00356    rnrCtx.SetClip(clip);
00357 
00358    if (needUpdate)
00359    {
00360       UpdateSceneInfo(rnrCtx);
00361    }
00362 
00363 
00364    // Setup LOD ... optionally lodify.
00365    Short_t lod;
00366    if (sInfo.LOD() != TGLRnrCtx::kLODUndef) lod = sInfo.LOD();
00367    else if  (fLOD  != TGLRnrCtx::kLODUndef) lod = fLOD;
00368    else                                     lod = rnrCtx.ViewerLOD();
00369    rnrCtx.SetSceneLOD(lod);
00370    rnrCtx.SetCombiLOD(TMath::Min(rnrCtx.ViewerLOD(), rnrCtx.SceneLOD()));
00371    if (needUpdate || rnrCtx.CombiLOD() != sInfo.LastLOD())
00372    {
00373       LodifySceneInfo(rnrCtx);
00374    }
00375 
00376    // Setup style.
00377    Short_t style;
00378    if (sInfo.Style() != TGLRnrCtx::kStyleUndef) style = sInfo.Style();
00379    else if  (fStyle  != TGLRnrCtx::kStyleUndef) style = fStyle;
00380    else                                         style = rnrCtx.ViewerStyle();
00381    rnrCtx.SetSceneStyle(style);
00382    sInfo.SetLastStyle(style);
00383 
00384    // Wireframe line width.
00385    Float_t wf_linew;
00386    if (sInfo.WFLineW() != 0) wf_linew = sInfo.WFLineW();
00387    else if  (fWFLineW  != 0) wf_linew = fWFLineW;
00388    else                      wf_linew = rnrCtx.ViewerWFLineW();
00389    rnrCtx.SetSceneWFLineW(wf_linew);
00390    sInfo.SetLastWFLineW(wf_linew);
00391    // Outline line width.
00392    Float_t ol_linew;
00393    if (sInfo.OLLineW() != 0) ol_linew = sInfo.OLLineW();
00394    else if  (fOLLineW  != 0) ol_linew = fOLLineW;
00395    else                      ol_linew = rnrCtx.ViewerOLLineW();
00396    rnrCtx.SetSceneOLLineW(ol_linew);
00397    sInfo.SetLastOLLineW(ol_linew);
00398 }
00399 
00400 //______________________________________________________________________________
00401 void TGLSceneBase::PreRender(TGLRnrCtx & rnrCtx)
00402 {
00403    // Perform pre-render initialization - fill rnrCtx with
00404    // values stored during PreDraw().
00405    //
00406    // This is called each time before RenderXyzz().
00407 
00408    TGLSceneInfo& sInfo = * rnrCtx.GetSceneInfo();
00409 
00410    rnrCtx.SetClip         (sInfo.LastClip());
00411    rnrCtx.SetCombiLOD     (sInfo.LastLOD());
00412    rnrCtx.SetSceneStyle   (sInfo.LastStyle());
00413    rnrCtx.SetSceneWFLineW (sInfo.LastWFLineW());
00414    rnrCtx.SetSceneOLLineW (sInfo.LastOLLineW());
00415 
00416    // !!!
00417    // eventually handle matrix stack.
00418    // glPushMatrix();
00419    // glMultMatrix(something-from-scene-info);
00420    // Should also fix camera matrices
00421 }
00422 
00423 //______________________________________________________________________________
00424 void TGLSceneBase::Render(TGLRnrCtx & rnrCtx)
00425 {
00426    // This function does rendering of all stages, the shapes are
00427    // rendered in the following order: opaque, transparent,
00428    // selected-opaque, selected-transparent.
00429    //
00430    // GL-depth buffer is cleared after transparent shapes have been
00431    // rendered.
00432    //
00433    // This is never called from ROOT GL directly. Use it if you know
00434    // you are rendering a single scene.
00435 
00436    RenderOpaque(rnrCtx);
00437    RenderTransp(rnrCtx);
00438    RenderSelOpaque(rnrCtx);
00439    RenderSelTransp(rnrCtx);
00440 }
00441 
00442 //______________________________________________________________________________
00443 void TGLSceneBase::RenderOpaque(TGLRnrCtx & /*rnrCtx*/)
00444 {
00445    // Render opaque elements.
00446 }
00447 
00448 //______________________________________________________________________________
00449 void TGLSceneBase::RenderTransp(TGLRnrCtx & /*rnrCtx*/)
00450 {
00451    // Render transparent elements.
00452 }
00453 
00454 //______________________________________________________________________________
00455 void TGLSceneBase::RenderSelOpaque(TGLRnrCtx & /*rnrCtx*/)
00456 {
00457    // Render selected opaque elements.
00458 }
00459 
00460 //______________________________________________________________________________
00461 void TGLSceneBase::RenderSelTransp(TGLRnrCtx & /*rnrCtx*/)
00462 {
00463    // Render selected transparent elements.
00464 }
00465 
00466 //______________________________________________________________________________
00467 void TGLSceneBase::PostRender(TGLRnrCtx & /*rnrCtx*/)
00468 {
00469    // Perform post-render clean-up.
00470 
00471    // !!!
00472    // Cleanup matrix stack
00473    // glPopMatrix();
00474    // Should also fix camera matrices
00475 }
00476 
00477 //______________________________________________________________________________
00478 void TGLSceneBase::PostDraw(TGLRnrCtx & /*rnrCtx*/)
00479 {
00480    // Finalize drawing.
00481    //
00482    // This is called at the end of the GL-viewer draw cycle.
00483 }
00484 
00485 /**************************************************************************/
00486 // Selection
00487 /**************************************************************************/
00488 
00489 //______________________________________________________________________________
00490 Bool_t TGLSceneBase::ResolveSelectRecord(TGLSelectRecord & /*rec*/,
00491                                          Int_t             /*curIdx*/)
00492 {
00493    // Process selection record rec.
00494    // 'curIdx' is the item position where the scene should start
00495    // its processing.
00496    // Return TRUE if an object has been identified or FALSE otherwise.
00497    // The scene-info member of the record is already set by the caller.
00498    //
00499    // See implementation in sub-class TGLScene, here we just return FALSE.
00500 
00501    return kFALSE;
00502 }

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