TGLViewer.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLViewer.cxx 37327 2010-12-06 12:23:33Z matevz $
00002 // Author:  Richard Maunder  25/05/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 "TGLViewer.h"
00013 #include "TGLIncludes.h"
00014 #include "TGLStopwatch.h"
00015 #include "TGLRnrCtx.h"
00016 #include "TGLSelectBuffer.h"
00017 #include "TGLLightSet.h"
00018 #include "TGLManipSet.h"
00019 #include "TGLCameraOverlay.h"
00020 #include "TGLAutoRotator.h"
00021 
00022 #include "TGLScenePad.h"
00023 #include "TGLLogicalShape.h"
00024 #include "TGLPhysicalShape.h"
00025 #include "TGLObject.h"
00026 #include "TGLStopwatch.h"
00027 #include "TBuffer3D.h"
00028 #include "TBuffer3DTypes.h"
00029 
00030 #include "TGLOutput.h"
00031 
00032 #include "TVirtualPad.h" // Remove when pad removed - use signal
00033 #include "TVirtualX.h"
00034 
00035 #include "TMath.h"
00036 #include "TColor.h"
00037 #include "TError.h"
00038 #include "TClass.h"
00039 #include "TROOT.h"
00040 
00041 // For event type translation ExecuteEvent
00042 #include "Buttons.h"
00043 #include "GuiTypes.h"
00044 
00045 #include "TVirtualGL.h"
00046 
00047 #include "TGLWidget.h"
00048 #include "TGLFBO.h"
00049 #include "TGLViewerEditor.h"
00050 #include "TGedEditor.h"
00051 #include "TGLPShapeObj.h"
00052 
00053 #include "KeySymbols.h"
00054 #include "TContextMenu.h"
00055 #include "TImage.h"
00056 
00057 #include <stdexcept>
00058 
00059 #ifndef GL_BGRA
00060 #define GL_BGRA GL_BGRA_EXT
00061 #endif
00062 
00063 //==============================================================================
00064 // TGLViewer
00065 //==============================================================================
00066 
00067 //______________________________________________________________________
00068 //
00069 // Base GL viewer object - used by both standalone and embedded (in pad)
00070 // GL. Contains core viewer objects :
00071 //
00072 // GL scene - collection of main drawn objects - see TGLStdScene
00073 // Cameras (fXyzzCamera) - ortho and perspective cameras - see TGLCamera
00074 // Clipping (fClipXyzz) - collection of clip objects - see TGLClip
00075 // Manipulators (fXyzzManip) - collection of manipulators - see TGLManip
00076 //
00077 // It maintains the current active draw styles, clipping object,
00078 // manipulator, camera etc.
00079 //
00080 // TGLViewer is 'GUI free' in that it does not derive from any ROOT GUI
00081 // TGFrame etc - see TGLSAViewer for this. However it contains GUI
00082 // GUI style methods HandleButton() etc to which GUI events can be
00083 // directed from standalone frame or embedding pad to perform
00084 // interaction.
00085 //
00086 // Also, the TGLWidget needs to be created externally. It is not owned
00087 // by the viewer.
00088 //
00089 // For embedded (pad) GL this viewer is created directly by plugin
00090 // manager. For standalone the derived TGLSAViewer is.
00091 //
00092 
00093 ClassImp(TGLViewer);
00094 
00095 TGLColorSet TGLViewer::fgDefaultColorSet;
00096 Bool_t      TGLViewer::fgUseDefaultColorSetForNewViewers = kFALSE;
00097 
00098 //______________________________________________________________________________
00099 TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
00100                      Int_t width, Int_t height) :
00101    fPad(pad),
00102    fContextMenu(0),
00103    fPerspectiveCameraXOZ(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // XOZ floor
00104    fPerspectiveCameraYOZ(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)), // YOZ floor
00105    fPerspectiveCameraXOY(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // XOY floor
00106    fOrthoXOYCamera (TGLOrthoCamera::kXOY,  TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down  Z axis,  X horz, Y vert
00107    fOrthoXOZCamera (TGLOrthoCamera::kXOZ,  TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // Looking along Y axis,  X horz, Z vert
00108    fOrthoZOYCamera (TGLOrthoCamera::kZOY,  TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // Looking along X axis,  Z horz, Y vert
00109    fOrthoXnOYCamera(TGLOrthoCamera::kXnOY, TGLVector3( 0.0, 0.0,-1.0), TGLVector3(0.0, 1.0, 0.0)), // Looking along Z axis, -X horz, Y vert
00110    fOrthoXnOZCamera(TGLOrthoCamera::kXnOZ, TGLVector3( 0.0, 1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // Looking down  Y axis, -X horz, Z vert
00111    fOrthoZnOYCamera(TGLOrthoCamera::kZnOY, TGLVector3( 1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down  X axis, -Z horz, Y vert
00112    fCurrentCamera(&fPerspectiveCameraXOZ),
00113    fAutoRotator(0),
00114 
00115    fStereo               (kFALSE),
00116    fStereoZeroParallax   (0.03f),
00117    fStereoEyeOffsetFac   (1.0f),
00118    fStereoFrustumAsymFac (1.0f),
00119 
00120    fLightSet          (0),
00121    fClipSet           (0),
00122    fSelectedPShapeRef (0),
00123    fCurrentOvlElm     (0),
00124 
00125    fEventHandler(0),
00126    fGedEditor(0),
00127    fPShapeWrap(0),
00128    fPushAction(kPushStd), fDragAction(kDragNone),
00129    fRedrawTimer(0),
00130    fMaxSceneDrawTimeHQ(5000),
00131    fMaxSceneDrawTimeLQ(100),
00132    fPointScale (1), fLineScale(1), fSmoothPoints(kFALSE), fSmoothLines(kFALSE),
00133    fAxesType(TGLUtil::kAxesNone),
00134    fAxesDepthTest(kTRUE),
00135    fReferenceOn(kFALSE),
00136    fReferencePos(0.0, 0.0, 0.0),
00137    fDrawCameraCenter(kFALSE),
00138    fCameraOverlay(0),
00139    fSmartRefresh(kFALSE),
00140    fDebugMode(kFALSE),
00141    fIsPrinting(kFALSE),
00142    fPictureFileName("viewer.jpg"),
00143    fFader(0),
00144    fGLWidget(0),
00145    fGLDevice(-1),
00146    fGLCtxId(0),
00147    fIgnoreSizesOnUpdate(kFALSE),
00148    fResetCamerasOnUpdate(kTRUE),
00149    fResetCamerasOnNextUpdate(kFALSE)
00150 {
00151    // Construct the viewer object, with following arguments:
00152    //    'pad' - external pad viewer is bound to
00153    //    'x', 'y' - initial top left position
00154    //    'width', 'height' - initial width/height
00155 
00156    InitSecondaryObjects();
00157 
00158    SetViewport(x, y, width, height);
00159 }
00160 
00161 //______________________________________________________________________________
00162 TGLViewer::TGLViewer(TVirtualPad * pad) :
00163    fPad(pad),
00164    fContextMenu(0),
00165    fPerspectiveCameraXOZ(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // XOZ floor
00166    fPerspectiveCameraYOZ(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)), // YOZ floor
00167    fPerspectiveCameraXOY(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // XOY floor
00168    fOrthoXOYCamera (TGLOrthoCamera::kXOY,  TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down  Z axis,  X horz, Y vert
00169    fOrthoXOZCamera (TGLOrthoCamera::kXOZ,  TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // Looking along Y axis,  X horz, Z vert
00170    fOrthoZOYCamera (TGLOrthoCamera::kZOY,  TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // Looking along X axis,  Z horz, Y vert
00171    fOrthoXnOYCamera(TGLOrthoCamera::kXnOY, TGLVector3( 0.0, 0.0,-1.0), TGLVector3(0.0, 1.0, 0.0)), // Looking along Z axis, -X horz, Y vert
00172    fOrthoXnOZCamera(TGLOrthoCamera::kXnOZ, TGLVector3( 0.0, 1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // Looking down  Y axis, -X horz, Z vert
00173    fOrthoZnOYCamera(TGLOrthoCamera::kZnOY, TGLVector3( 1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down  X axis, -Z horz, Y vert
00174    fCurrentCamera(&fPerspectiveCameraXOZ),
00175    fAutoRotator(0),
00176 
00177    fStereo               (kFALSE),
00178    fStereoZeroParallax   (0.03f),
00179    fStereoEyeOffsetFac   (1.0f),
00180    fStereoFrustumAsymFac (1.0f),
00181 
00182    fLightSet          (0),
00183    fClipSet           (0),
00184    fSelectedPShapeRef (0),
00185    fCurrentOvlElm     (0),
00186 
00187    fEventHandler(0),
00188    fGedEditor(0),
00189    fPShapeWrap(0),
00190    fPushAction(kPushStd), fDragAction(kDragNone),
00191    fRedrawTimer(0),
00192    fMaxSceneDrawTimeHQ(5000),
00193    fMaxSceneDrawTimeLQ(100),
00194    fPointScale (1), fLineScale(1), fSmoothPoints(kFALSE), fSmoothLines(kFALSE),
00195    fAxesType(TGLUtil::kAxesNone),
00196    fAxesDepthTest(kTRUE),
00197    fReferenceOn(kFALSE),
00198    fReferencePos(0.0, 0.0, 0.0),
00199    fDrawCameraCenter(kFALSE),
00200    fCameraOverlay(0),
00201    fSmartRefresh(kFALSE),
00202    fDebugMode(kFALSE),
00203    fIsPrinting(kFALSE),
00204    fPictureFileName("viewer.jpg"),
00205    fFader(0),
00206    fGLWidget(0),
00207    fGLDevice(fPad->GetGLDevice()),
00208    fGLCtxId(0),
00209    fIgnoreSizesOnUpdate(kFALSE),
00210    fResetCamerasOnUpdate(kTRUE),
00211    fResetCamerasOnNextUpdate(kFALSE)
00212 {
00213    //gl-embedded viewer's ctor
00214    // Construct the viewer object, with following arguments:
00215    //    'pad' - external pad viewer is bound to
00216    //    'x', 'y' - initial top left position
00217    //    'width', 'height' - initial width/height
00218 
00219    InitSecondaryObjects();
00220 
00221    if (fGLDevice != -1) {
00222       // For the moment instantiate a fake context identity.
00223       fGLCtxId = new TGLContextIdentity;
00224       fGLCtxId->AddRef(0);
00225       Int_t viewport[4] = {0};
00226       gGLManager->ExtractViewport(fGLDevice, viewport);
00227       SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
00228    }
00229 }
00230 
00231 //______________________________________________________________________________
00232 void TGLViewer::InitSecondaryObjects()
00233 {
00234    // Common initialization.
00235 
00236    fLightSet = new TGLLightSet;
00237    fClipSet  = new TGLClipSet;
00238    AddOverlayElement(fClipSet);
00239 
00240    fSelectedPShapeRef = new TGLManipSet;
00241    fSelectedPShapeRef->SetDrawBBox(kTRUE);
00242    AddOverlayElement(fSelectedPShapeRef);
00243 
00244    fPShapeWrap = new TGLPShapeObj(0, this);
00245 
00246    fLightColorSet.StdLightBackground();
00247    if (fgUseDefaultColorSetForNewViewers) {
00248       fRnrCtx->ChangeBaseColorSet(&fgDefaultColorSet);
00249    } else {
00250       if (fPad) {
00251          fRnrCtx->ChangeBaseColorSet(&fLightColorSet);
00252          fLightColorSet.Background().SetColor(fPad->GetFillColor());
00253          fLightColorSet.Foreground().SetColor(fPad->GetLineColor());
00254       } else {
00255          fRnrCtx->ChangeBaseColorSet(&fDarkColorSet);
00256       }
00257    }
00258 
00259    fCameraOverlay = new TGLCameraOverlay(kFALSE, kFALSE);
00260    AddOverlayElement(fCameraOverlay);
00261 
00262    fRedrawTimer = new TGLRedrawTimer(*this);
00263 }
00264 
00265 //______________________________________________________________________________
00266 TGLViewer::~TGLViewer()
00267 {
00268    // Destroy viewer object.
00269 
00270    delete fAutoRotator;
00271 
00272    delete fLightSet;
00273    // fClipSet, fSelectedPShapeRef and fCameraOverlay deleted via overlay.
00274 
00275    delete fContextMenu;
00276    delete fRedrawTimer;
00277 
00278    if (fEventHandler) {
00279       if (fGLWidget)
00280          fGLWidget->SetEventHandler(0);
00281       delete fEventHandler;
00282    }
00283 
00284    if (fPad)
00285       fPad->ReleaseViewer3D();
00286    if (fGLDevice != -1)
00287       fGLCtxId->Release(0);
00288 }
00289 
00290 
00291 //______________________________________________________________________________
00292 void TGLViewer::PadPaint(TVirtualPad* pad)
00293 {
00294    // Entry point for updating viewer contents via VirtualViewer3D
00295    // interface.
00296    // We search and forward the request to appropriate TGLScenePad.
00297    // If it is not found we create a new TGLScenePad so this can
00298    // potentially also be used for registration of new pads.
00299 
00300    TGLScenePad* scenepad = 0;
00301    for (SceneInfoList_i si = fScenes.begin(); si != fScenes.end(); ++si)
00302    {
00303       scenepad = dynamic_cast<TGLScenePad*>((*si)->GetScene());
00304       if (scenepad && scenepad->GetPad() == pad)
00305          break;
00306       scenepad = 0;
00307    }
00308    if (scenepad == 0)
00309    {
00310       scenepad = new TGLScenePad(pad);
00311       AddScene(scenepad);
00312    }
00313 
00314    scenepad->PadPaintFromViewer(this);
00315 
00316    PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
00317    fResetCamerasOnNextUpdate = kFALSE;
00318 
00319    RequestDraw();
00320 }
00321 
00322 
00323 /**************************************************************************/
00324 /**************************************************************************/
00325 
00326 //______________________________________________________________________________
00327 void TGLViewer::UpdateScene(Bool_t redraw)
00328 {
00329    // Force update of pad-scenes. Eventually this could be generalized
00330    // to all scene-types via a virtual function in TGLSceneBase.
00331 
00332    // Cancel any pending redraw timer.
00333    fRedrawTimer->Stop();
00334 
00335    for (SceneInfoList_i si = fScenes.begin(); si != fScenes.end(); ++si)
00336    {
00337       TGLScenePad* scenepad = dynamic_cast<TGLScenePad*>((*si)->GetScene());
00338       if (scenepad)
00339          scenepad->PadPaintFromViewer(this);
00340    }
00341 
00342    PostSceneBuildSetup(fResetCamerasOnNextUpdate || fResetCamerasOnUpdate);
00343    fResetCamerasOnNextUpdate = kFALSE;
00344 
00345    if (redraw)
00346       RequestDraw();
00347 }
00348 
00349 //______________________________________________________________________________
00350 void TGLViewer::ResetCurrentCamera()
00351 {
00352    // Resets position/rotation of current camera to default values.
00353 
00354    MergeSceneBBoxes(fOverallBoundingBox);
00355    CurrentCamera().Setup(fOverallBoundingBox, kTRUE);
00356 }
00357 
00358 //______________________________________________________________________________
00359 void TGLViewer::SetupCameras(Bool_t reset)
00360 {
00361    // Setup cameras for current bounding box.
00362 
00363    if (IsLocked()) {
00364       Error("TGLViewer::SetupCameras", "expected kUnlocked, found %s", LockName(CurrentLock()));
00365       return;
00366    }
00367 
00368    // Setup cameras if scene box is not empty
00369    const TGLBoundingBox & box = fOverallBoundingBox;
00370    if (!box.IsEmpty()) {
00371       fPerspectiveCameraYOZ.Setup(box, reset);
00372       fPerspectiveCameraXOZ.Setup(box, reset);
00373       fPerspectiveCameraXOY.Setup(box, reset);
00374       fOrthoXOYCamera.Setup(box, reset);
00375       fOrthoXOZCamera.Setup(box, reset);
00376       fOrthoZOYCamera.Setup(box, reset);
00377       fOrthoXnOYCamera.Setup(box, reset);
00378       fOrthoXnOZCamera.Setup(box, reset);
00379       fOrthoZnOYCamera.Setup(box, reset);
00380    }
00381 }
00382 
00383 //______________________________________________________________________________
00384 void TGLViewer::PostSceneBuildSetup(Bool_t resetCameras)
00385 {
00386    // Perform post scene-build setup.
00387 
00388    MergeSceneBBoxes(fOverallBoundingBox);
00389    SetupCameras(resetCameras);
00390 
00391    // Set default reference to center
00392    fReferencePos.Set(fOverallBoundingBox.Center());
00393    RefreshPadEditor(this);
00394 }
00395 
00396 
00397 /**************************************************************************/
00398 /**************************************************************************/
00399 
00400 //______________________________________________________________________________
00401 void TGLViewer::InitGL()
00402 {
00403    // Initialise GL state.
00404 
00405    glEnable(GL_LIGHTING);
00406    glEnable(GL_DEPTH_TEST);
00407    glEnable(GL_CULL_FACE);
00408    glCullFace(GL_BACK);
00409    glClearColor(0.f, 0.f, 0.f, 0.f);
00410    glClearDepth(1.0);
00411    glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
00412    glEnable(GL_COLOR_MATERIAL);
00413    glMaterialf(GL_BACK, GL_SHININESS, 0.0);
00414    glPolygonMode(GL_FRONT, GL_FILL);
00415    glDisable(GL_BLEND);
00416 
00417    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
00418    Float_t lmodelAmb[] = {0.5f, 0.5f, 1.f, 1.f};
00419    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodelAmb);
00420    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
00421 
00422    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
00423    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00424 
00425    TGLUtil::CheckError("TGLViewer::InitGL");
00426 }
00427 
00428 //______________________________________________________________________________
00429 void TGLViewer::RequestDraw(Short_t LODInput)
00430 {
00431    // Post request for redraw of viewer at level of detail 'LOD'
00432    // Request is directed via cross thread gVirtualGL object.
00433 
00434    fRedrawTimer->Stop();
00435    // Ignore request if GL window or context not yet availible or shown.
00436    if ((!fGLWidget && fGLDevice == -1) || (fGLWidget && !fGLWidget->IsMapped()))
00437    {
00438       return;
00439    }
00440 
00441    // Take scene draw lock - to be revisited
00442    if ( ! TakeLock(kDrawLock)) {
00443       // If taking drawlock fails the previous draw is still in progress
00444       // set timer to do this one later
00445       if (gDebug>3) {
00446          Info("TGLViewer::RequestDraw", "viewer locked - requesting another draw.");
00447       }
00448       fRedrawTimer->RequestDraw(100, LODInput);
00449       return;
00450    }
00451    fLOD = LODInput;
00452 
00453    if (!gVirtualX->IsCmdThread())
00454       gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoDraw()", (ULong_t)this));
00455    else
00456       DoDraw();
00457 }
00458 
00459 //______________________________________________________________________________
00460 void TGLViewer::SetupClipObject()
00461 {
00462    // Setup clip-object. Protected virtual method.
00463 
00464    if (GetClipAutoUpdate())
00465    {
00466       fClipSet->SetupCurrentClip(fOverallBoundingBox);
00467    }
00468    else
00469    {
00470       fClipSet->SetupCurrentClipIfInvalid(fOverallBoundingBox);
00471    }
00472 }
00473 //______________________________________________________________________________
00474 void TGLViewer::PreRender()
00475 {
00476    // Initialize objects that influence rendering.
00477    // Called before every render.
00478 
00479    fCamera = fCurrentCamera;
00480    fClip   = fClipSet->GetCurrentClip();
00481    if (fGLDevice != -1)
00482    {
00483       fRnrCtx->SetGLCtxIdentity(fGLCtxId);
00484       fGLCtxId->DeleteGLResources();
00485    }
00486 
00487    TGLUtil::SetPointSizeScale(fPointScale * fRnrCtx->GetRenderScale());
00488    TGLUtil::SetLineWidthScale(fLineScale  * fRnrCtx->GetRenderScale());
00489 
00490    if (fSmoothPoints) glEnable(GL_POINT_SMOOTH); else glDisable(GL_POINT_SMOOTH);
00491    if (fSmoothLines)  glEnable(GL_LINE_SMOOTH);  else glDisable(GL_LINE_SMOOTH);
00492    if (fSmoothPoints || fSmoothLines)
00493    {
00494       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00495       glEnable(GL_BLEND);
00496    }
00497    else
00498    {
00499       glDisable(GL_BLEND);
00500    }
00501 
00502    TGLViewerBase::PreRender();
00503 
00504    // Setup lighting
00505    fLightSet->StdSetupLights(fOverallBoundingBox, *fCamera, fDebugMode);
00506 }
00507 
00508 //______________________________________________________________________________
00509 void TGLViewer::PostRender()
00510 {
00511    // Restore state set in PreRender().
00512    // Called after every render.
00513 
00514    TGLViewerBase::PostRender();
00515 
00516    TGLUtil::SetPointSizeScale(1);
00517    TGLUtil::SetLineWidthScale(1);
00518 }
00519 
00520 //______________________________________________________________________________
00521 void TGLViewer::DoDraw(Bool_t swap_buffers)
00522 {
00523    // Draw out the viewer.
00524 
00525    // Locking mainly for Win32 multi thread safety - but no harm in all using it
00526    // During normal draws a draw lock is taken in other thread (Win32) in RequestDraw()
00527    // to ensure thread safety. For PrintObjects repeated Draw() calls are made.
00528    // If no draw lock taken get one now.
00529 
00530    fRedrawTimer->Stop();
00531 
00532    if (CurrentLock() != kDrawLock) {
00533       if ( ! TakeLock(kDrawLock)) {
00534          Error("TGLViewer::DoDraw", "viewer is %s", LockName(CurrentLock()));
00535          return;
00536       }
00537    }
00538 
00539    TUnlocker ulck(this);
00540 
00541    if (fGLDevice == -1 && (fViewport.Width() <= 1 || fViewport.Height() <= 1)) {
00542       if (gDebug > 2) {
00543          Info("TGLViewer::DoDraw()", "zero surface area, draw skipped.");
00544       }
00545       return;
00546    }
00547 
00548    if (fGLDevice != -1) {
00549       Int_t viewport[4] = {};
00550       gGLManager->ExtractViewport(fGLDevice, viewport);
00551       SetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
00552    }
00553 
00554    TGLStopwatch timer;
00555    if (gDebug>2) {
00556       timer.Start();
00557    }
00558 
00559    // Setup scene draw time
00560    fRnrCtx->SetRenderTimeOut(fLOD == TGLRnrCtx::kLODHigh ?
00561                              fMaxSceneDrawTimeHQ :
00562                              fMaxSceneDrawTimeLQ);
00563 
00564    if (fStereo && fCurrentCamera->IsPerspective() && !fRnrCtx->GetGrabImage() &&
00565        !fIsPrinting)
00566    {
00567       DoDrawStereo(swap_buffers);
00568    }
00569    else
00570    {
00571       DoDrawMono(swap_buffers);
00572    }
00573 
00574    ReleaseLock(kDrawLock);
00575 
00576    if (gDebug>2) {
00577       Info("TGLViewer::DoDraw()", "Took %f msec", timer.End());
00578    }
00579 
00580    // Check if further redraws are needed and schedule them.
00581 
00582    if (CurrentCamera().UpdateInterest(kFALSE)) {
00583       // Reset major view-dependant cache.
00584       ResetSceneInfos();
00585       fRedrawTimer->RequestDraw(0, fLOD);
00586    }
00587 
00588    if (fLOD != TGLRnrCtx::kLODHigh &&
00589        (fDragAction < kDragCameraRotate || fDragAction > kDragCameraDolly))
00590    {
00591       // Request final draw pass.
00592       fRedrawTimer->RequestDraw(100, TGLRnrCtx::kLODHigh);
00593    }
00594 }
00595 
00596 //______________________________________________________________________________
00597 void TGLViewer::DoDrawMono(Bool_t swap_buffers)
00598 {
00599    // Draw out in monoscopic mode.
00600 
00601    MakeCurrent();
00602 
00603    if (!fIsPrinting) PreDraw();
00604    PreRender();
00605 
00606    fRnrCtx->StartStopwatch();
00607    if (fFader < 1)
00608    {
00609       RenderNonSelected();
00610       RenderSelected();
00611       DrawGuides();
00612       RenderOverlay(TGLOverlayElement::kAllVisible, kFALSE);
00613 
00614       glClear(GL_DEPTH_BUFFER_BIT);
00615       fRnrCtx->SetHighlight(kTRUE);
00616       RenderSelected();
00617       fRnrCtx->SetHighlight(kFALSE);
00618       glClear(GL_DEPTH_BUFFER_BIT);
00619       DrawDebugInfo();
00620    }
00621    fRnrCtx->StopStopwatch();
00622 
00623    PostRender();
00624 
00625    if (fFader > 0)
00626    {
00627       FadeView(fFader);
00628    }
00629 
00630    PostDraw();
00631 
00632    if (swap_buffers)
00633    {
00634       SwapBuffers();
00635    }
00636 }
00637 
00638 //______________________________________________________________________________
00639 void TGLViewer::DoDrawStereo(Bool_t swap_buffers)
00640 {
00641    // Draw out in stereoscopic mode.
00642 
00643    TGLPerspectiveCamera &c = *dynamic_cast<TGLPerspectiveCamera*>(fCurrentCamera);
00644 
00645    Float_t gl_near, gl_far, zero_p_dist;
00646    Float_t h_half, w_half;
00647    Float_t x_len_at_zero_parallax;
00648    Float_t stereo_offset;
00649    Float_t frustum_asym;
00650 
00651    MakeCurrent();
00652 
00653    // Draw left
00654    glDrawBuffer(GL_BACK_LEFT);
00655    PreDraw();
00656    PreRender();
00657 
00658    gl_near = c.GetNearClip();
00659    gl_far  = c.GetFarClip();
00660    zero_p_dist = gl_near + fStereoZeroParallax*(gl_far-gl_near);
00661 
00662    h_half = TMath::Tan(0.5*TMath::DegToRad()*c.GetFOV()) * gl_near;
00663    w_half = h_half * fViewport.Aspect();
00664 
00665    x_len_at_zero_parallax = 2.0f * w_half * zero_p_dist / gl_near;
00666    stereo_offset = 0.035f * x_len_at_zero_parallax * fStereoEyeOffsetFac;
00667 
00668    frustum_asym = stereo_offset * gl_near / zero_p_dist * fStereoFrustumAsymFac;
00669 
00670    TGLMatrix  abs_trans(c.RefCamBase());
00671    abs_trans *= c.RefCamTrans();
00672    TGLVector3 left_vec = abs_trans.GetBaseVec(2);
00673 
00674    glTranslatef(stereo_offset*left_vec[0], stereo_offset*left_vec[1], stereo_offset*left_vec[2]);
00675 
00676    glMatrixMode(GL_PROJECTION);
00677    glLoadIdentity();
00678    glFrustum(-w_half + frustum_asym, w_half + frustum_asym,
00679              -h_half, h_half, gl_near, gl_far);
00680    glMatrixMode(GL_MODELVIEW);
00681 
00682    fRnrCtx->StartStopwatch();
00683    if (fFader < 1)
00684    {
00685       RenderNonSelected();
00686       RenderSelected();
00687       DrawGuides();
00688       RenderOverlay(TGLOverlayElement::kAllVisible, kFALSE);
00689 
00690       glClear(GL_DEPTH_BUFFER_BIT);
00691       fRnrCtx->SetHighlight(kTRUE);
00692       RenderSelected();
00693       fRnrCtx->SetHighlight(kFALSE);
00694       glClear(GL_DEPTH_BUFFER_BIT);
00695       DrawDebugInfo();
00696    }
00697    fRnrCtx->StopStopwatch();
00698 
00699    PostRender();
00700 
00701    if (fFader > 0)
00702    {
00703       FadeView(fFader);
00704    }
00705    PostDraw();
00706 
00707    // Draw right
00708    glDrawBuffer(GL_BACK_RIGHT);
00709    PreDraw();
00710    PreRender();
00711 
00712    glTranslatef(-stereo_offset*left_vec[0], -stereo_offset*left_vec[1], -stereo_offset*left_vec[2]);
00713 
00714    glMatrixMode(GL_PROJECTION);
00715    glLoadIdentity();
00716    glFrustum(-w_half - frustum_asym, w_half - frustum_asym,
00717              -h_half, h_half, gl_near, gl_far);
00718    glMatrixMode(GL_MODELVIEW);
00719 
00720    fRnrCtx->StartStopwatch();
00721    if (fFader < 1)
00722    {
00723       RenderNonSelected();
00724       RenderSelected();
00725       DrawGuides();
00726       RenderOverlay(TGLOverlayElement::kAllVisible, kFALSE);
00727 
00728       glClear(GL_DEPTH_BUFFER_BIT);
00729       fRnrCtx->SetHighlight(kTRUE);
00730       RenderSelected();
00731       fRnrCtx->SetHighlight(kFALSE);
00732       glClear(GL_DEPTH_BUFFER_BIT);
00733       DrawDebugInfo();
00734    }
00735    fRnrCtx->StopStopwatch();
00736 
00737    PostRender();
00738 
00739    if (fFader > 0)
00740    {
00741       FadeView(fFader);
00742    }
00743    PostDraw();
00744 
00745    // End
00746    if (swap_buffers)
00747    {
00748       SwapBuffers();
00749    }
00750 
00751    glDrawBuffer(GL_BACK);
00752 }
00753 
00754 //______________________________________________________________________________
00755 Bool_t TGLViewer::SavePicture()
00756 {
00757    // Save current image using the defualt file name which can be set
00758    // via SetPictureFileName() and defaults to "viewer.jpg".
00759    // Really useful for the files ending with 'gif+'.
00760 
00761    return SavePicture(fPictureFileName);
00762 }
00763 
00764 //______________________________________________________________________________
00765 Bool_t TGLViewer::SavePicture(const TString &fileName)
00766 {
00767    // Save current image in various formats (gif, gif+, jpg, png, eps, pdf).
00768    // 'gif+' will append image to an existng file (animated gif).
00769    // 'eps' and 'pdf' do not fully support transparency and texturing.
00770    // The viewer window most be fully contained within the desktop but
00771    // can be covered by other windows.
00772    // Returns false if something obvious goes wrong, true otherwise.
00773 
00774    if (fileName.EndsWith(".eps"))
00775    {
00776       return TGLOutput::Capture(*this, TGLOutput::kEPS_BSP, fileName.Data());
00777    }
00778    else if (fileName.EndsWith(".pdf"))
00779    {
00780       return TGLOutput::Capture(*this, TGLOutput::kPDF_BSP, fileName.Data());
00781    }
00782    else
00783    {
00784       if (GLEW_EXT_framebuffer_object)
00785       {
00786          return SavePictureUsingFBO(fileName, fViewport.Width(), fViewport.Height(), kFALSE);
00787       }
00788       else
00789       {
00790          return SavePictureUsingBB(fileName);
00791       }
00792    }
00793 }
00794 
00795 //______________________________________________________________________________
00796 Bool_t TGLViewer::SavePictureUsingBB(const TString &fileName)
00797 {
00798    // Save current image in various formats (gif, gif+, jpg, png).
00799    // 'gif+' will append image to an existng file (animated gif).
00800    // Back-Buffer is used for capturing of the image.
00801    // The viewer window most be fully contained within the desktop but
00802    // can be covered by other windows.
00803    // Returns false if something obvious goes wrong, true otherwise.
00804 
00805    static const TString eh("TGLViewer::SavePictureUsingBB");
00806 
00807    if (! fileName.EndsWith(".gif") && ! fileName.Contains(".gif+") &&
00808        ! fileName.EndsWith(".jpg") && ! fileName.EndsWith(".png"))
00809    {
00810       Warning(eh, "file %s cannot be saved with this extension.", fileName.Data());
00811       return kFALSE;
00812    }
00813 
00814    if ( ! TakeLock(kDrawLock)) {
00815       Error(eh, "viewer locked - try later.");
00816       return kFALSE;
00817    }
00818 
00819    TUnlocker ulck(this);
00820 
00821    fLOD = TGLRnrCtx::kLODHigh;
00822    fRnrCtx->SetGrabImage(kTRUE);
00823 
00824    if (!gVirtualX->IsCmdThread())
00825       gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoDraw(kFALSE)", (ULong_t)this));
00826    else
00827       DoDraw(kFALSE);
00828 
00829    fRnrCtx->SetGrabImage(kFALSE);
00830 
00831    glReadBuffer(GL_BACK);
00832 
00833    UChar_t* xx = new UChar_t[4 * fViewport.Width() * fViewport.Height()];
00834    glPixelStorei(GL_PACK_ALIGNMENT, 1);
00835    glReadPixels(0, 0, fViewport.Width(), fViewport.Height(),
00836                 GL_BGRA, GL_UNSIGNED_BYTE, xx);
00837 
00838    std::auto_ptr<TImage> image(TImage::Create());
00839    image->FromGLBuffer(xx, fViewport.Width(), fViewport.Height());
00840    image->WriteImage(fileName);
00841 
00842    delete [] xx;
00843 
00844    return kTRUE;
00845 }
00846 
00847 //______________________________________________________________________________
00848 Bool_t TGLViewer::SavePictureUsingFBO(const TString &fileName, Int_t w, Int_t h,
00849                                       Float_t pixel_object_scale)
00850 {
00851    // Save current image in various formats (gif, gif+, jpg, png).
00852    // 'gif+' will append image to an existng file (animated gif).
00853    // Frame-Buffer-Object is used for capturing of the image - OpenGL
00854    // 1.5 is required.
00855    // The viewer window does not have to be visible at all.
00856    // Returns false if something obvious goes wrong, true otherwise.
00857    //
00858    // pixel_object_scale is used to scale (as much as possible) the
00859    // objects whose representation size is pixel based (point-sizes,
00860    // line-widths, bitmap/pixmap font-sizes).
00861    // If set to 0 (default) no scaling is applied.
00862 
00863    static const TString eh("TGLViewer::SavePictureUsingFBO");
00864 
00865    if (! fileName.EndsWith(".gif") && ! fileName.Contains(".gif+") &&
00866        ! fileName.EndsWith(".jpg") && ! fileName.EndsWith(".png"))
00867    {
00868       Warning(eh, "file %s cannot be saved with this extension.", fileName.Data());
00869       return kFALSE;
00870    }
00871 
00872    if ( ! TakeLock(kDrawLock)) {
00873       Error(eh, "viewer locked - try later.");
00874       return kFALSE;
00875    }
00876 
00877    TUnlocker ulck(this);
00878 
00879    MakeCurrent();
00880 
00881    TGLFBO *fbo = new TGLFBO();
00882    try
00883    {
00884       fbo->Init(w, h, fGLWidget->GetPixelFormat()->GetSamples());
00885    }
00886    catch (std::runtime_error& exc)
00887    {
00888       Error(eh, "%s",exc.what());
00889       return kFALSE;
00890    }
00891 
00892    TGLRect old_vp(fViewport);
00893    SetViewport(0, 0, w, h);
00894 
00895    Float_t old_scale = 1;
00896    if (pixel_object_scale != 0)
00897    {
00898       old_scale = fRnrCtx->GetRenderScale();
00899       fRnrCtx->SetRenderScale(old_scale * pixel_object_scale);
00900    }
00901 
00902    fbo->Bind();
00903 
00904    fLOD = TGLRnrCtx::kLODHigh;
00905    fRnrCtx->SetGrabImage(kTRUE);
00906 
00907    if (!gVirtualX->IsCmdThread())
00908       gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoDraw(kFALSE)", (ULong_t)this));
00909    else
00910       DoDraw(kFALSE);
00911 
00912    fRnrCtx->SetGrabImage(kFALSE);
00913 
00914    fbo->Unbind();
00915 
00916    fbo->SetAsReadBuffer();
00917 
00918    UChar_t* xx = new UChar_t[4 * fViewport.Width() * fViewport.Height()];
00919    glPixelStorei(GL_PACK_ALIGNMENT, 1);
00920    glReadPixels(0, 0, fViewport.Width(), fViewport.Height(),
00921                 GL_BGRA, GL_UNSIGNED_BYTE, xx);
00922 
00923    std::auto_ptr<TImage> image(TImage::Create());
00924    image->FromGLBuffer(xx, fViewport.Width(), fViewport.Height());
00925    image->WriteImage(fileName);
00926 
00927    delete [] xx;
00928 
00929    delete fbo;
00930 
00931    if (pixel_object_scale != 0)
00932    {
00933       fRnrCtx->SetRenderScale(old_scale);
00934    }
00935 
00936    SetViewport(old_vp);
00937 
00938    return kTRUE;
00939 }
00940 
00941 //______________________________________________________________________________
00942 Bool_t TGLViewer::SavePictureWidth(const TString &fileName, Int_t width,
00943                                    Bool_t pixel_object_scale)
00944 {
00945    // Save picture with given width (height scaled proportinally).
00946    // If pixel_object_scale is true (default), the corresponding
00947    // scaling gets calculated from the current window size.
00948 
00949    Float_t scale  = Float_t(width) / fViewport.Width();
00950    Int_t   height = TMath::Nint(scale*fViewport.Height());
00951 
00952    return SavePictureUsingFBO(fileName, width, height, pixel_object_scale ? scale : 0);
00953 }
00954 
00955 //______________________________________________________________________________
00956 Bool_t TGLViewer::SavePictureHeight(const TString &fileName, Int_t height,
00957                                     Bool_t pixel_object_scale)
00958 {
00959    // Save picture with given height (width scaled proportinally).
00960    // If pixel_object_scale is true (default), the corresponding
00961    // scaling gets calculated from the current window size.
00962 
00963    Float_t scale = Float_t(height) / fViewport.Height();
00964    Int_t   width = TMath::Nint(scale*fViewport.Width());
00965 
00966    return SavePictureUsingFBO(fileName, width, height, pixel_object_scale ? scale : 0);
00967 }
00968 
00969 //______________________________________________________________________________
00970 Bool_t TGLViewer::SavePictureScale (const TString &fileName, Float_t scale,
00971                                     Bool_t pixel_object_scale)
00972 {
00973    // Save picture with given scale to current window size.
00974    // If pixel_object_scale is true (default), the same scaling is
00975    // used.
00976 
00977    Int_t w = TMath::Nint(scale*fViewport.Width());
00978    Int_t h = TMath::Nint(scale*fViewport.Height());
00979 
00980    return SavePictureUsingFBO(fileName, w, h, pixel_object_scale ? scale : 0);
00981 }
00982 
00983 //______________________________________________________________________________
00984 void TGLViewer::DrawGuides()
00985 {
00986    // Draw reference marker and coordinate axes.
00987 
00988    Bool_t disabled = kFALSE;
00989    if (fReferenceOn)
00990    {
00991       glDisable(GL_DEPTH_TEST);
00992       TGLUtil::DrawReferenceMarker(*fCamera, fReferencePos);
00993       disabled = kTRUE;
00994    }
00995    if (fDrawCameraCenter)
00996    {
00997       glDisable(GL_DEPTH_TEST);
00998       Float_t radius = fCamera->ViewportDeltaToWorld(TGLVertex3(fCamera->GetCenterVec()), 3, 3).Mag();
00999       const UChar_t rgba[4] = { 0, 255, 255, 255 };
01000       TGLUtil::DrawSphere(fCamera->GetCenterVec(), radius, rgba);
01001       disabled = kTRUE;
01002    }
01003    if (fAxesDepthTest && disabled)
01004    {
01005       glEnable(GL_DEPTH_TEST);
01006       disabled = kFALSE;
01007    }
01008    else if (fAxesDepthTest == kFALSE && disabled == kFALSE)
01009    {
01010       glDisable(GL_DEPTH_TEST);
01011       disabled = kTRUE;
01012    }
01013    TGLUtil::DrawSimpleAxes(*fCamera, fOverallBoundingBox, fAxesType);
01014    if (disabled)
01015       glEnable(GL_DEPTH_TEST);
01016 }
01017 
01018 //______________________________________________________________________________
01019 void TGLViewer::DrawDebugInfo()
01020 {
01021    // If in debug mode draw camera aids and overall bounding box.
01022 
01023    if (fDebugMode)
01024    {
01025       glDisable(GL_LIGHTING);
01026       CurrentCamera().DrawDebugAids();
01027 
01028       // Green scene bounding box
01029       glColor3d(0.0, 1.0, 0.0);
01030       fOverallBoundingBox.Draw();
01031 
01032       // Scene bounding box center sphere (green) and
01033       glDisable(GL_DEPTH_TEST);
01034       Double_t size = fOverallBoundingBox.Extents().Mag() / 200.0;
01035       TGLUtil::DrawSphere(TGLVertex3(0.0, 0.0, 0.0), size, TGLUtil::fgWhite);
01036       const TGLVertex3 & center = fOverallBoundingBox.Center();
01037       TGLUtil::DrawSphere(center, size, TGLUtil::fgGreen);
01038       glEnable(GL_DEPTH_TEST);
01039 
01040       glEnable(GL_LIGHTING);
01041    }
01042 }
01043 
01044 //______________________________________________________________________________
01045 void TGLViewer::PreDraw()
01046 {
01047    // Perform GL work which must be done before each draw.
01048 
01049    InitGL();
01050 
01051    // For embedded gl clear color must be pad's background color.
01052    {
01053       Color_t ci = (fGLDevice != -1) ? gPad->GetFillColor() : fRnrCtx->ColorSet().Background().GetColorIndex();
01054       TColor *color = gROOT->GetColor(ci);
01055       Float_t rgb[3];
01056       if (color)
01057          color->GetRGB(rgb[0], rgb[1], rgb[2]);
01058       else
01059          rgb[0] = rgb[1] = rgb[2] = 0.0f;
01060 
01061       glClearColor(rgb[0], rgb[1], rgb[2], 0.0f);
01062    }
01063 
01064    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
01065 
01066    TGLUtil::CheckError("TGLViewer::PreDraw");
01067 }
01068 
01069 //______________________________________________________________________________
01070 void TGLViewer::PostDraw()
01071 {
01072    // Perform GL work which must be done after each draw.
01073 
01074    glFlush();
01075    TGLUtil::CheckError("TGLViewer::PostDraw");
01076 }
01077 
01078 //______________________________________________________________________________
01079 void TGLViewer::FadeView(Float_t alpha)
01080 {
01081    // Draw a rectangle (background color and given alpha) across the
01082    // whole viewport.
01083 
01084    static const Float_t z = -1.0f;
01085 
01086    glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();
01087    glMatrixMode(GL_MODELVIEW);  glPushMatrix(); glLoadIdentity();
01088 
01089    {
01090       TGLCapabilitySwitch blend(GL_BLEND,    kTRUE);
01091       TGLCapabilitySwitch light(GL_LIGHTING, kFALSE);
01092       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01093       TGLUtil::ColorAlpha(fRnrCtx->ColorSet().Background(), alpha);
01094       glBegin(GL_QUADS);
01095       glVertex3f(-1, -1, z);  glVertex3f( 1, -1, z);
01096       glVertex3f( 1,  1, z);  glVertex3f(-1,  1, z);
01097       glEnd();
01098    }
01099 
01100    glMatrixMode(GL_PROJECTION); glPopMatrix();
01101    glMatrixMode(GL_MODELVIEW);  glPopMatrix();
01102 }
01103 
01104 //______________________________________________________________________________
01105 void TGLViewer::MakeCurrent() const
01106 {
01107    // Make GL context current
01108    if (fGLDevice == -1)
01109       fGLWidget->MakeCurrent();
01110    else
01111       gGLManager->MakeCurrent(fGLDevice);
01112 }
01113 
01114 //______________________________________________________________________________
01115 void TGLViewer::SwapBuffers() const
01116 {
01117    // Swap GL buffers
01118    if ( ! IsDrawOrSelectLock()) {
01119       Error("TGLViewer::SwapBuffers", "viewer is %s", LockName(CurrentLock()));
01120    }
01121    if (fGLDevice == -1)
01122       fGLWidget->SwapBuffers();
01123    else {
01124       gGLManager->ReadGLBuffer(fGLDevice);
01125       gGLManager->Flush(fGLDevice);
01126       gGLManager->MarkForDirectCopy(fGLDevice, kFALSE);
01127    }
01128 }
01129 
01130 //______________________________________________________________________________
01131 Bool_t TGLViewer::RequestSelect(Int_t x, Int_t y)
01132 {
01133    // Post request for selection render pass viewer, picking objects
01134    // around the window point (x,y).
01135 
01136    // Take select lock on scene immediately we enter here - it is released
01137    // in the other (drawing) thread - see TGLViewer::DoSelect()
01138 
01139    if ( ! TakeLock(kSelectLock)) {
01140       return kFALSE;
01141    }
01142 
01143    if (!gVirtualX->IsCmdThread())
01144       return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoSelect(%d, %d)", (ULong_t)this, x, y)));
01145    else
01146       return DoSelect(x, y);
01147 }
01148 
01149 //______________________________________________________________________________
01150 Bool_t TGLViewer::DoSelect(Int_t x, Int_t y)
01151 {
01152    // Perform GL selection, picking objects overlapping WINDOW
01153    // area described by 'rect'. Return kTRUE if selection should be
01154    // changed, kFALSE otherwise.
01155    // Select lock should already been taken in other thread in
01156    // TGLViewer::ReqSelect().
01157 
01158    if (CurrentLock() != kSelectLock) {
01159       Error("TGLViewer::DoSelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
01160       return kFALSE;
01161    }
01162 
01163    TUnlocker ulck(this);
01164 
01165    MakeCurrent();
01166 
01167    fRnrCtx->BeginSelection(x, y, 3);
01168    glRenderMode(GL_SELECT);
01169 
01170    PreRender();
01171    Render();
01172    PostRender();
01173 
01174    Int_t nHits = glRenderMode(GL_RENDER);
01175    fRnrCtx->EndSelection(nHits);
01176 
01177    // Process selection.
01178    if (gDebug > 0) Info("TGLViewer::DoSelect", "Primary select nHits=%d.", nHits);
01179 
01180    if (nHits > 0)
01181    {
01182       Int_t idx = 0;
01183       if (FindClosestRecord(fSelRec, idx))
01184       {
01185          if (fSelRec.GetTransparent())
01186          {
01187             TGLSelectRecord opaque;
01188             if (FindClosestOpaqueRecord(opaque, ++idx))
01189                fSelRec = opaque;
01190          }
01191          if (gDebug > 1) fSelRec.Print();
01192       }
01193    } else {
01194       fSelRec.Reset();
01195    }
01196 
01197    ReleaseLock(kSelectLock);
01198    return ! TGLSelectRecord::AreSameSelectionWise(fSelRec, fCurrentSelRec);
01199 }
01200 
01201 //______________________________________________________________________________
01202 Bool_t TGLViewer::RequestSecondarySelect(Int_t x, Int_t y)
01203 {
01204    // Request secondary select.
01205 
01206    if ( ! TakeLock(kSelectLock)) {
01207       return kFALSE;
01208    }
01209 
01210    if (!gVirtualX->IsCmdThread())
01211       return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoSecondarySelect(%d, %d)", (ULong_t)this, x, y)));
01212    else
01213       return DoSecondarySelect(x, y);
01214 }
01215 
01216 //______________________________________________________________________________
01217 Bool_t TGLViewer::DoSecondarySelect(Int_t x, Int_t y)
01218 {
01219    // Secondary selection.
01220 
01221    if (CurrentLock() != kSelectLock) {
01222       Error("TGLViewer::DoSecondarySelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
01223       return kFALSE;
01224    }
01225 
01226    TUnlocker ulck(this);
01227 
01228    if (! fSelRec.GetSceneInfo() || ! fSelRec.GetPhysShape() ||
01229        ! fSelRec.GetPhysShape()->GetLogical()->SupportsSecondarySelect())
01230    {
01231       if (gDebug > 0)
01232          Info("TGLViewer::SecondarySelect", "Skipping secondary selection "
01233               "(sinfo=0x%lx, pshape=0x%lx).\n",
01234               (Long_t)fSelRec.GetSceneInfo(), (Long_t)fSelRec.GetPhysShape());
01235       fSecSelRec.Reset();
01236       return kFALSE;
01237    }
01238 
01239    MakeCurrent();
01240 
01241    TGLSceneInfo*    sinfo = fSelRec.GetSceneInfo();
01242    TGLSceneBase*    scene = sinfo->GetScene();
01243    TGLPhysicalShape* pshp = fSelRec.GetPhysShape();
01244 
01245    SceneInfoList_t foo;
01246    foo.push_back(sinfo);
01247    fScenes.swap(foo);
01248    fRnrCtx->BeginSelection(x, y, 3);
01249    fRnrCtx->SetSecSelection(kTRUE);
01250    glRenderMode(GL_SELECT);
01251 
01252    PreRender();
01253    fRnrCtx->SetSceneInfo(sinfo);
01254    scene->PreRender(*fRnrCtx);
01255    fRnrCtx->SetDrawPass(TGLRnrCtx::kPassFill);
01256    fRnrCtx->SetShapeLOD(TGLRnrCtx::kLODHigh);
01257    glPushName(pshp->ID());
01258    // !!! Hack: does not use clipping and proper draw-pass settings.
01259    pshp->Draw(*fRnrCtx);
01260    glPopName();
01261    scene->PostRender(*fRnrCtx);
01262    fRnrCtx->SetSceneInfo(0);
01263    PostRender();
01264 
01265    Int_t nSecHits = glRenderMode(GL_RENDER);
01266    fRnrCtx->EndSelection(nSecHits);
01267    fScenes.swap(foo);
01268 
01269    if (gDebug > 0) Info("TGLViewer::DoSelect", "Secondary select nSecHits=%d.", nSecHits);
01270 
01271    ReleaseLock(kSelectLock);
01272 
01273    if (nSecHits > 0)
01274    {
01275       fSecSelRec = fSelRec;
01276       fSecSelRec.SetRawOnly(fRnrCtx->GetSelectBuffer()->RawRecord(0));
01277       if (gDebug > 1) fSecSelRec.Print();
01278       return kTRUE;
01279    } else {
01280       fSecSelRec.Reset();
01281       return kFALSE;
01282    }
01283 }
01284 
01285 //______________________________________________________________________________
01286 void TGLViewer::ApplySelection()
01287 {
01288    // Process result from last selection (in fSelRec) and
01289    // extract a new current selection from it.
01290    // Here we only use physical shape.
01291 
01292    fCurrentSelRec = fSelRec;
01293 
01294    TGLPhysicalShape *selPhys = fSelRec.GetPhysShape();
01295    fSelectedPShapeRef->SetPShape(selPhys);
01296 
01297    // Inform external client selection has been modified.
01298    SelectionChanged();
01299 
01300    RequestDraw(TGLRnrCtx::kLODHigh);
01301 }
01302 
01303 //______________________________________________________________________________
01304 Bool_t TGLViewer::RequestOverlaySelect(Int_t x, Int_t y)
01305 {
01306    // Post request for secondary selection rendering of selected object
01307    // around the window point (x,y).
01308 
01309    // Take select lock on viewer immediately - it is released
01310    // in the other (drawing) thread - see TGLViewer::DoSecondarySelect().
01311 
01312    if ( ! TakeLock(kSelectLock)) {
01313       return kFALSE;
01314    }
01315 
01316    if (!gVirtualX->IsCmdThread())
01317       return Bool_t(gROOT->ProcessLineFast(Form("((TGLViewer *)0x%lx)->DoOverlaySelect(%d, %d)", (ULong_t)this, x, y)));
01318    else
01319       return DoOverlaySelect(x, y);
01320 }
01321 
01322 //______________________________________________________________________________
01323 Bool_t TGLViewer::DoOverlaySelect(Int_t x, Int_t y)
01324 {
01325    // Perform GL selection, picking overlay objects only.
01326    // Return TRUE if the selected overlay-element has changed.
01327 
01328    if (CurrentLock() != kSelectLock) {
01329       Error("TGLViewer::DoOverlaySelect", "expected kSelectLock, found %s", LockName(CurrentLock()));
01330       return kFALSE;
01331    }
01332 
01333    TUnlocker ulck(this);
01334 
01335    MakeCurrent();
01336 
01337    fRnrCtx->BeginSelection(x, y, 3);
01338    glRenderMode(GL_SELECT);
01339 
01340    PreRenderOverlaySelection();
01341    RenderOverlay(TGLOverlayElement::kActive, kTRUE);
01342    PostRenderOverlaySelection();
01343 
01344    Int_t nHits = glRenderMode(GL_RENDER);
01345    fRnrCtx->EndSelection(nHits);
01346 
01347    // Process overlay selection.
01348    TGLOverlayElement * selElm = 0;
01349    if (nHits > 0)
01350    {
01351       Int_t idx = 0;
01352       while (idx < nHits && FindClosestOverlayRecord(fOvlSelRec, idx))
01353       {
01354          TGLOverlayElement* el = fOvlSelRec.GetOvlElement();
01355          if (el == fCurrentOvlElm)
01356          {
01357             if (el->MouseStillInside(fOvlSelRec))
01358             {
01359                selElm = el;
01360                break;
01361             }
01362          }
01363          else if (el->MouseEnter(fOvlSelRec))
01364          {
01365             selElm = el;
01366             break;
01367          }
01368          ++idx;
01369       }
01370    }
01371    else
01372    {
01373       fOvlSelRec.Reset();
01374    }
01375 
01376    ReleaseLock(kSelectLock);
01377 
01378    if (fCurrentOvlElm != selElm)
01379    {
01380       if (fCurrentOvlElm) fCurrentOvlElm->MouseLeave();
01381       fCurrentOvlElm = selElm;
01382       return kTRUE;
01383    }
01384    else
01385    {
01386       return kFALSE;
01387    }
01388 }
01389 
01390 //______________________________________________________________________________
01391 void TGLFaderHelper::MakeFadeStep()
01392 {
01393    // Make one fading step and request redraw.
01394 
01395    Float_t fade = fViewer->GetFader();
01396 
01397    if (fade == fFadeTarget) {
01398       delete this; return;
01399    }
01400    if (TMath::Abs(fFadeTarget - fade) < 1e-3) {
01401       fViewer->SetFader(fFadeTarget);
01402       fViewer->RequestDraw(TGLRnrCtx::kLODHigh);
01403       delete this;
01404       return;
01405    }
01406 
01407    Float_t dt = fTime/fNSteps;
01408    Float_t df = (fFadeTarget - fade)/fNSteps;
01409    fViewer->SetFader(fade + df);
01410    fViewer->RequestDraw(TGLRnrCtx::kLODHigh);
01411    fTime -= dt; --fNSteps;
01412    TTimer::SingleShot(TMath::CeilNint(1000*dt),
01413                       "TGLFaderHelper", this, "MakeFadeStep()");
01414 }
01415 
01416 //______________________________________________________________________________
01417 void TGLViewer::AutoFade(Float_t fade, Float_t time, Int_t steps)
01418 {
01419    // Animate fading from curernt value to fade over given time (sec)
01420    // and number of steps.
01421 
01422    TGLFaderHelper* fh = new TGLFaderHelper(this, fade, time, steps);
01423    fh->MakeFadeStep();
01424 }
01425 
01426 //______________________________________________________________________________
01427 void TGLViewer::UseDarkColorSet()
01428 {
01429    // Use the dark color-set.
01430 
01431    fRnrCtx->ChangeBaseColorSet(&fDarkColorSet);
01432    RefreshPadEditor(this);
01433 }
01434 
01435 //______________________________________________________________________________
01436 void TGLViewer::UseLightColorSet()
01437 {
01438    // Use the light color-set.
01439 
01440    fRnrCtx->ChangeBaseColorSet(&fLightColorSet);
01441    RefreshPadEditor(this);
01442 }
01443 
01444 //______________________________________________________________________________
01445 void TGLViewer::SwitchColorSet()
01446 {
01447    // Swtich between dark and light colorsets.
01448 
01449    if (IsUsingDefaultColorSet())
01450    {
01451       Info("SwitchColorSet()", "Global color-set is in use, switch not supported.");
01452       return;
01453    }
01454 
01455    if (fRnrCtx->GetBaseColorSet() == &fLightColorSet)
01456       UseDarkColorSet();
01457    else
01458       UseLightColorSet();
01459 }
01460 
01461 //______________________________________________________________________________
01462 void TGLViewer::UseDefaultColorSet(Bool_t x)
01463 {
01464    // Set usage of the default color set.
01465 
01466    if (x)
01467       fRnrCtx->ChangeBaseColorSet(&fgDefaultColorSet);
01468    else
01469       fRnrCtx->ChangeBaseColorSet(&fDarkColorSet);
01470    RefreshPadEditor(this);
01471 }
01472 
01473 //______________________________________________________________________________
01474 Bool_t TGLViewer::IsUsingDefaultColorSet() const
01475 {
01476    // Check if the viewer is using the default color set.
01477    // If yes, some operations might be disabled.
01478 
01479    return fRnrCtx->GetBaseColorSet() == &fgDefaultColorSet;
01480 }
01481 
01482 //______________________________________________________________________________
01483 void TGLViewer::SetClearColor(Color_t col)
01484 {
01485    // Set background method.
01486    // Deprecated method - set background color in the color-set.
01487 
01488    fRnrCtx->GetBaseColorSet()->Background().SetColor(col);
01489 }
01490 
01491 //______________________________________________________________________________
01492 TGLColorSet& TGLViewer::GetDefaultColorSet()
01493 {
01494    // Returns reference to the default color-set.
01495    // Static function.
01496 
01497    return fgDefaultColorSet;
01498 }
01499 
01500 //______________________________________________________________________________
01501 void TGLViewer::UseDefaultColorSetForNewViewers(Bool_t x)
01502 {
01503    // Sets static flag that determines if new viewers should use the
01504    // default color-set.
01505    // This is false at startup.
01506 
01507    fgUseDefaultColorSetForNewViewers = x;
01508 }
01509 
01510 //______________________________________________________________________________
01511 Bool_t TGLViewer::IsUsingDefaultColorSetForNewViewers()
01512 {
01513    // Returns the value of the static flag that determines if new
01514    // viewers should use the default color-set.
01515    // This is false at startup.
01516 
01517    return fgUseDefaultColorSetForNewViewers;
01518 }
01519 
01520 //______________________________________________________________________________
01521 Bool_t TGLViewer::IsColorSetDark() const
01522 {
01523    // Returns true if curremt color set is dark.
01524 
01525    return fRnrCtx->GetBaseColorSet() == &fDarkColorSet;
01526 }
01527 
01528 /**************************************************************************/
01529 // Viewport
01530 /**************************************************************************/
01531 
01532 //______________________________________________________________________________
01533 void TGLViewer::SetViewport(Int_t x, Int_t y, Int_t width, Int_t height)
01534 {
01535    // Set viewer viewport (window area) with bottom/left at (x,y), with
01536    // dimensions 'width'/'height'
01537 
01538    // Only process if changed
01539    if (fViewport.X() == x && fViewport.Y() == y &&
01540        fViewport.Width() == width && fViewport.Height() == height) {
01541       return;
01542    }
01543 
01544    fViewport.Set(x, y, width, height);
01545    fCurrentCamera->SetViewport(fViewport);
01546 
01547    if (gDebug > 2) {
01548       Info("TGLViewer::SetViewport", "updated - corner %d,%d dimensions %d,%d", x, y, width, height);
01549    }
01550 }
01551 
01552 void TGLViewer::SetViewport(const TGLRect& vp)
01553 {
01554    // Set viewr viewport from TGLRect.
01555 
01556    SetViewport(vp.X(), vp.Y(), vp.Width(), vp.Height());
01557 }
01558 
01559 /**************************************************************************/
01560 // Camera methods
01561 /**************************************************************************/
01562 
01563 //______________________________________________________________________________
01564 TGLCamera& TGLViewer::RefCamera(ECameraType cameraType)
01565 {
01566    // Return camera reference by type.
01567 
01568    // TODO: Move these into a vector!
01569    switch(cameraType) {
01570       case kCameraPerspXOZ:
01571          return fPerspectiveCameraXOZ;
01572       case kCameraPerspYOZ:
01573          return fPerspectiveCameraYOZ;
01574       case kCameraPerspXOY:
01575          return fPerspectiveCameraXOY;
01576       case kCameraOrthoXOY:
01577          return fOrthoXOYCamera;
01578       case kCameraOrthoXOZ:
01579          return fOrthoXOZCamera;
01580       case kCameraOrthoZOY:
01581          return fOrthoZOYCamera;
01582       case kCameraOrthoXnOY:
01583          return fOrthoXnOYCamera;
01584       case kCameraOrthoXnOZ:
01585          return fOrthoXnOZCamera;
01586       case kCameraOrthoZnOY:
01587          return fOrthoZnOYCamera;
01588       default:
01589          Error("TGLViewer::SetCurrentCamera", "invalid camera type");
01590          return *fCurrentCamera;
01591    }
01592 }
01593 
01594 //______________________________________________________________________________
01595 void TGLViewer::SetCurrentCamera(ECameraType cameraType)
01596 {
01597    // Set current active camera - 'cameraType' one of:
01598    //   kCameraPerspX,    kCameraPerspY,    kCameraPerspZ,
01599    //   kCameraOrthoXOY,  kCameraOrthoXOZ,  kCameraOrthoZOY,
01600    //   kCameraOrthoXnOY, kCameraOrthoXnOZ, kCameraOrthoZnOY
01601 
01602    if (IsLocked()) {
01603       Error("TGLViewer::SetCurrentCamera", "expected kUnlocked, found %s", LockName(CurrentLock()));
01604       return;
01605    }
01606 
01607    // TODO: Move these into a vector!
01608    TGLCamera *prev = fCurrentCamera;
01609    switch (cameraType)
01610    {
01611       case kCameraPerspXOZ: {
01612          fCurrentCamera = &fPerspectiveCameraXOZ;
01613          break;
01614       }
01615       case kCameraPerspYOZ: {
01616          fCurrentCamera = &fPerspectiveCameraYOZ;
01617          break;
01618       }
01619       case kCameraPerspXOY: {
01620          fCurrentCamera = &fPerspectiveCameraXOY;
01621          break;
01622       }
01623       case kCameraOrthoXOY: {
01624          fCurrentCamera = &fOrthoXOYCamera;
01625          break;
01626       }
01627       case kCameraOrthoXOZ: {
01628          fCurrentCamera = &fOrthoXOZCamera;
01629          break;
01630       }
01631       case kCameraOrthoZOY: {
01632          fCurrentCamera = &fOrthoZOYCamera;
01633          break;
01634       }
01635       case kCameraOrthoXnOY: {
01636          fCurrentCamera = &fOrthoXnOYCamera;
01637          break;
01638       }
01639       case kCameraOrthoXnOZ: {
01640          fCurrentCamera = &fOrthoXnOZCamera;
01641          break;
01642       }
01643       case kCameraOrthoZnOY: {
01644          fCurrentCamera = &fOrthoZnOYCamera;
01645          break;
01646       }
01647       default: {
01648          Error("TGLViewer::SetCurrentCamera", "invalid camera type");
01649          break;
01650       }
01651    }
01652 
01653    if (fCurrentCamera != prev)
01654    {
01655       // Ensure any viewport has been propigated to the current camera
01656       fCurrentCamera->SetViewport(fViewport);
01657       RefreshPadEditor(this);
01658 
01659       if (fAutoRotator)
01660       {
01661          if (fAutoRotator->IsRunning())
01662          {
01663             fAutoRotator->Stop();
01664          }
01665          else
01666          {
01667             if (fAutoRotator->GetCamera() == fCurrentCamera)
01668             {
01669                fAutoRotator->Start();
01670             }
01671          }
01672       }
01673 
01674       RequestDraw(TGLRnrCtx::kLODHigh);
01675    }
01676 }
01677 
01678 //______________________________________________________________________________
01679 void TGLViewer::SetOrthoCamera(ECameraType camera,
01680                                Double_t zoom, Double_t dolly,
01681                                Double_t center[3],
01682                                Double_t hRotate, Double_t vRotate)
01683 {
01684    // Set an orthographic camera to supplied configuration - note this
01685    // does not need to be the current camera - though you will not see
01686    // the effect if it is not.
01687    //
01688    // 'camera' defines the ortho camera - one of kCameraOrthoXOY / XOZ / ZOY
01689    // 'left' / 'right' / 'top' / 'bottom' define the WORLD coordinates which
01690    // corresepond with the left/right/top/bottom positions on the GL viewer viewport
01691    // E.g. for kCameraOrthoXOY camera left/right are X world coords,
01692    // top/bottom are Y world coords
01693    // As this is an orthographic camera the other axis (in eye direction) is
01694    // no relevant. The near/far clip planes are set automatically based in scene
01695    // contents
01696 
01697    // TODO: Move these into a vector!
01698    switch(camera) {
01699       case kCameraOrthoXOY: {
01700          fOrthoXOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
01701          if (fCurrentCamera == &fOrthoXOYCamera) {
01702             RequestDraw(TGLRnrCtx::kLODHigh);
01703          }
01704          break;
01705       }
01706       case kCameraOrthoXOZ: {
01707          fOrthoXOZCamera.Configure(zoom, dolly, center, hRotate, vRotate);
01708          if (fCurrentCamera == &fOrthoXOZCamera) {
01709             RequestDraw(TGLRnrCtx::kLODHigh);
01710          }
01711          break;
01712       }
01713       case kCameraOrthoZOY: {
01714          fOrthoZOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
01715          if (fCurrentCamera == &fOrthoZOYCamera) {
01716             RequestDraw(TGLRnrCtx::kLODHigh);
01717          }
01718          break;
01719       }
01720       default: {
01721          Error("TGLViewer::SetOrthoCamera", "invalid camera type");
01722          break;
01723       }
01724    }
01725 }
01726 
01727 //______________________________________________________________________________
01728 void TGLViewer::SetPerspectiveCamera(ECameraType camera,
01729                                      Double_t fov, Double_t dolly,
01730                                      Double_t center[3],
01731                                      Double_t hRotate, Double_t vRotate)
01732 {
01733    // Set a perspective camera to supplied configuration - note this
01734    // does not need to be the current camera - though you will not see
01735    // the effect if it is not.
01736    //
01737    // 'camera' defines the persp camera - one of kCameraPerspXOZ, kCameraPerspYOZ, kCameraPerspXOY
01738    // 'fov' - field of view (lens angle) in degrees (clamped to 0.1 - 170.0)
01739    // 'dolly' - distance from 'center'
01740    // 'center' - world position from which dolly/hRotate/vRotate are measured
01741    //             camera rotates round this, always facing in (in center of viewport)
01742    // 'hRotate' - horizontal rotation from initial configuration in degrees
01743    // 'hRotate' - vertical rotation from initial configuration in degrees
01744 
01745    // TODO: Move these into a vector!
01746    switch(camera) {
01747       case kCameraPerspXOZ: {
01748          fPerspectiveCameraXOZ.Configure(fov, dolly, center, hRotate, vRotate);
01749          if (fCurrentCamera == &fPerspectiveCameraXOZ) {
01750             RequestDraw(TGLRnrCtx::kLODHigh);
01751          }
01752          break;
01753       }
01754       case kCameraPerspYOZ: {
01755          fPerspectiveCameraYOZ.Configure(fov, dolly, center, hRotate, vRotate);
01756          if (fCurrentCamera == &fPerspectiveCameraYOZ) {
01757             RequestDraw(TGLRnrCtx::kLODHigh);
01758          }
01759          break;
01760       }
01761       case kCameraPerspXOY: {
01762          fPerspectiveCameraXOY.Configure(fov, dolly, center, hRotate, vRotate);
01763          if (fCurrentCamera == &fPerspectiveCameraXOY) {
01764             RequestDraw(TGLRnrCtx::kLODHigh);
01765          }
01766          break;
01767       }
01768       default: {
01769          Error("TGLViewer::SetPerspectiveCamera", "invalid camera type");
01770          break;
01771       }
01772    }
01773 }
01774 
01775 //______________________________________________________________________________
01776 TGLAutoRotator* TGLViewer::GetAutoRotator()
01777 {
01778    // Get the auto-rotator for this viewer.
01779 
01780    if (fAutoRotator == 0)
01781       fAutoRotator = new TGLAutoRotator(this);
01782    return fAutoRotator;
01783 }
01784 
01785 //______________________________________________________________________________
01786 void TGLViewer::SetAutoRotator(TGLAutoRotator* ar)
01787 {
01788    // Set the auto-rotator for this viewer. The old rotator is deleted.
01789 
01790    delete fAutoRotator;
01791    fAutoRotator = ar;
01792 }
01793 
01794 
01795 /**************************************************************************/
01796 // Guide methods
01797 /**************************************************************************/
01798 
01799 //______________________________________________________________________________
01800 void TGLViewer::GetGuideState(Int_t & axesType, Bool_t & axesDepthTest, Bool_t & referenceOn, Double_t referencePos[3]) const
01801 {
01802    // Fetch the state of guides (axes & reference markers) into arguments
01803 
01804    axesType = fAxesType;
01805    axesDepthTest = fAxesDepthTest;
01806 
01807    referenceOn = fReferenceOn;
01808    referencePos[0] = fReferencePos.X();
01809    referencePos[1] = fReferencePos.Y();
01810    referencePos[2] = fReferencePos.Z();
01811 }
01812 
01813 //______________________________________________________________________________
01814 void TGLViewer::SetGuideState(Int_t axesType, Bool_t axesDepthTest, Bool_t referenceOn, const Double_t referencePos[3])
01815 {
01816    // Set the state of guides (axes & reference markers) from arguments.
01817 
01818    fAxesType    = axesType;
01819    fAxesDepthTest = axesDepthTest;
01820    fReferenceOn = referenceOn;
01821    if (referencePos)
01822       fReferencePos.Set(referencePos[0], referencePos[1], referencePos[2]);
01823    if (fGLDevice != -1)
01824       gGLManager->MarkForDirectCopy(fGLDevice, kTRUE);
01825    RequestDraw();
01826 }
01827 
01828 //______________________________________________________________________________
01829 void TGLViewer::SetDrawCameraCenter(Bool_t x)
01830 {
01831    // Draw camera look at and rotation point.
01832 
01833    fDrawCameraCenter = x;
01834    RequestDraw();
01835 }
01836 
01837 // Selected physical
01838 //______________________________________________________________________________
01839 const TGLPhysicalShape * TGLViewer::GetSelected() const
01840 {
01841    // Return selected physical shape.
01842 
01843    return fSelectedPShapeRef->GetPShape();
01844 }
01845 
01846 /**************************************************************************/
01847 /**************************************************************************/
01848 
01849 //______________________________________________________________________________
01850 void TGLViewer::MouseOver(TGLPhysicalShape *shape)
01851 {
01852    // Emit MouseOver signal.
01853 
01854    Emit("MouseOver(TGLPhysicalShape*)", (Long_t)shape);
01855 }
01856 
01857 //______________________________________________________________________________
01858 void TGLViewer::MouseOver(TGLPhysicalShape *shape, UInt_t state)
01859 {
01860    // Emit MouseOver signal.
01861 
01862    Long_t args[2];
01863    args[0] = (Long_t)shape;
01864    args[1] = state;
01865    Emit("MouseOver(TGLPhysicalShape*,UInt_t)", args);
01866 }
01867 
01868 //______________________________________________________________________________
01869 void TGLViewer::MouseOver(TObject *obj, UInt_t state)
01870 {
01871    // Emit MouseOver signal.
01872 
01873    Long_t args[2];
01874    args[0] = (Long_t)obj;
01875    args[1] = state;
01876    Emit("MouseOver(TObject*,UInt_t)", args);
01877 }
01878 
01879 //______________________________________________________________________________
01880 void TGLViewer::ReMouseOver(TObject *obj, UInt_t state)
01881 {
01882    // Emit MouseOver signal.
01883 
01884    Long_t args[2];
01885    args[0] = (Long_t)obj;
01886    args[1] = state;
01887    Emit("ReMouseOver(TObject*,UInt_t)", args);
01888 }
01889 
01890 
01891 //______________________________________________________________________________
01892 void TGLViewer::UnMouseOver(TObject *obj, UInt_t state)
01893 {
01894    // Emit UnMouseOver signal.
01895 
01896    Long_t args[2];
01897    args[0] = (Long_t)obj;
01898    args[1] = state;
01899    Emit("UnMouseOver(TObject*,UInt_t)", args);
01900 }
01901 
01902 //______________________________________________________________________________
01903 void TGLViewer::Clicked(TObject *obj)
01904 {
01905    // Emit Clicked signal.
01906 
01907    Emit("Clicked(TObject*)", (Long_t)obj);
01908 }
01909 
01910 //______________________________________________________________________________
01911 void TGLViewer::Clicked(TObject *obj, UInt_t button, UInt_t state)
01912 {
01913    // Emit Clicked signal with button id and modifier state.
01914 
01915    Long_t args[3];
01916    args[0] = (Long_t)obj;
01917    args[1] = button;
01918    args[2] = state;
01919    Emit("Clicked(TObject*,UInt_t,UInt_t)", args);
01920 }
01921 
01922 
01923 //______________________________________________________________________________
01924 void TGLViewer::ReClicked(TObject *obj, UInt_t button, UInt_t state)
01925 {
01926    // Emit ReClicked signal with button id and modifier state.
01927 
01928    Long_t args[3];
01929    args[0] = (Long_t)obj;
01930    args[1] = button;
01931    args[2] = state;
01932    Emit("ReClicked(TObject*,UInt_t,UInt_t)", args);
01933 }
01934 
01935 //______________________________________________________________________________
01936 void TGLViewer::UnClicked(TObject *obj, UInt_t button, UInt_t state)
01937 {
01938    // Emit UnClicked signal with button id and modifier state.
01939 
01940    Long_t args[3];
01941    args[0] = (Long_t)obj;
01942    args[1] = button;
01943    args[2] = state;
01944    Emit("UnClicked(TObject*,UInt_t,UInt_t)", args);
01945 }
01946 
01947 //______________________________________________________________________________
01948 void TGLViewer::MouseIdle(TGLPhysicalShape *shape, UInt_t posx, UInt_t posy)
01949 {
01950    // Emit MouseIdle signal.
01951 
01952    Long_t args[3];
01953    static UInt_t oldx = 0, oldy = 0;
01954 
01955    if (oldx != posx || oldy != posy) {
01956       args[0] = (Long_t)shape;
01957       args[1] = posx;
01958       args[2] = posy;
01959       Emit("MouseIdle(TGLPhysicalShape*,UInt_t,UInt_t)", args);
01960       oldx = posx;
01961       oldy = posy;
01962    }
01963 }
01964 
01965 /**************************************************************************/
01966 /**************************************************************************/
01967 //______________________________________________________________________________
01968 Int_t TGLViewer::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
01969 {
01970    // Calcaulate and return pixel distance to nearest viewer object from
01971    // window location px, py
01972    // This is provided for use when embedding GL viewer into pad
01973 
01974    // Can't track the indvidual objects in rollover. Just set the viewer as the
01975    // selected object, and return 0 (object identified) so we receive ExecuteEvent calls
01976    gPad->SetSelected(this);
01977    return 0;
01978 }
01979 
01980 //______________________________________________________________________________
01981 void TGLViewer::ExecuteEvent(Int_t event, Int_t px, Int_t py)
01982 {
01983    // Process event of type 'event' - one of EEventType types,
01984    // occuring at window location px, py
01985    // This is provided for use when embedding GL viewer into pad
01986 
01987    if (fEventHandler)
01988       return fEventHandler->ExecuteEvent(event, px, py);
01989 }
01990 
01991 //______________________________________________________________________________
01992 void TGLViewer::PrintObjects()
01993 {
01994    // Pass viewer for print capture by TGLOutput.
01995 
01996    TGLOutput::Capture(*this);
01997 }
01998 
01999 //______________________________________________________________________________
02000 void TGLViewer::SelectionChanged()
02001 {
02002    // Update GUI components for embedded viewer selection change.
02003 
02004    if (!fGedEditor)
02005       return;
02006 
02007    TGLPhysicalShape *selected = const_cast<TGLPhysicalShape*>(GetSelected());
02008 
02009    if (selected) {
02010       fPShapeWrap->fPShape = selected;
02011       fGedEditor->SetModel(fPad, fPShapeWrap, kButton1Down);
02012    } else {
02013       fPShapeWrap->fPShape = 0;
02014       fGedEditor->SetModel(fPad, this, kButton1Down);
02015    }
02016 }
02017 
02018 //______________________________________________________________________________
02019 void TGLViewer::OverlayDragFinished()
02020 {
02021    // An overlay operation can result in change to an object.
02022    // Refresh geditor.
02023 
02024    if (fGedEditor)
02025    {
02026       fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
02027    }
02028 }
02029 
02030 //______________________________________________________________________________
02031 void TGLViewer::RefreshPadEditor(TObject* obj)
02032 {
02033    // Update GED editor if it is set.
02034 
02035    if (fGedEditor && (obj == 0 || fGedEditor->GetModel() == obj))
02036    {
02037       fGedEditor->SetModel(fPad, fGedEditor->GetModel(), kButton1Down);
02038    }
02039 }
02040 
02041 //______________________________________________________________________________
02042 void TGLViewer::SetEventHandler(TGEventHandler *handler)
02043 {
02044    // Set the event-handler. The event-handler is owned by the viewer.
02045    // If GLWidget is set, the handler is propagated to it.
02046    //
02047    // If called with handler=0, the current handler will be deleted
02048    // (also from TGLWidget).
02049 
02050    if (fEventHandler)
02051       delete fEventHandler;
02052 
02053    fEventHandler = handler;
02054    if (fGLWidget)
02055       fGLWidget->SetEventHandler(fEventHandler);
02056 }
02057 
02058 //______________________________________________________________________________
02059 void  TGLViewer::RemoveOverlayElement(TGLOverlayElement* el)
02060 {
02061    // Remove overlay element.
02062 
02063    if (el == fCurrentOvlElm)
02064    {
02065       fCurrentOvlElm = 0;
02066    }
02067    TGLViewerBase::RemoveOverlayElement(el);
02068 }
02069 
02070 //______________________________________________________________________________
02071 void TGLViewer::ClearCurrentOvlElm()
02072 {
02073    // Reset current overlay-element to zero, eventually notifying the
02074    // old one that the mouse has left.
02075    // Usually called when mouse leaves the window.
02076 
02077    if (fCurrentOvlElm)
02078    {
02079       fCurrentOvlElm->MouseLeave();
02080       fCurrentOvlElm = 0;
02081       RequestDraw();
02082    }
02083 }

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