From cebe7ef57fa726c3f03d91bde0348593286f6acf Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Wed, 10 Oct 2007 14:08:48 +0000
Subject: [PATCH] From Matevz & Alja

	* base/inc/TVirtualViewer3D.h:
	Add function virtual void ObjectPaint(TObject*, Option_t*).


/**************************************************************************/

	* ged/src/TGedEditor.cxx:
	When adding top-level TGFrame for the extra tabs specify layout
	hints with kLHintsExpandX.


/**************************************************************************/

	* gl/inc/TGLScenePad.h:
	* gl/src/TGLScenePad.cxx:
	Implement virtual TVirtualViewer3D::ObjectPaint().

	* gl/src/TGLCamera.cxx:
	* gl/inc/TGLCamera.h:
	* gl/src/TGLPerspectiveCamera.cxx:
	* gl/inc/TGLPerspectiveCamera.h:
	* gl/src/TGLOrthoCamera.cxx:
	* gl/inc/TGLOrthoCamera.h:
	Introduce two transformation matrices to clearly define movement
	of camera around the center point. The first transformation matrix
	fCamBase defines the coordinate system placed at the camera center
	point with camera up-vector as the third base vector. The second
	transformation matrix fCamTrans defines the camera transformation
	relative to fCamBase.

        Implement a common Truck(), Rotate() and Dolly() function for
	orthographic and perspective camera.

	Implement an option to define camera center point
	externally. Center can also be determined via picking.

	* gl/src/TGLUtil.cxx:
	* gl/inc/TGLUtil.h:
	TGLMatrix: add new functions to get/set the base vectors
	directly.

	TGLUtil: add member UInt_t fgDefaultDrawQuality.

	TGLRect: bugfix in Diagonal(), integer calculation overflowed.

	* gl/src/TGLViewer.cxx:
	* gl/inc/TGLViewer.h:
	Make interface to draw camera center point.
	Add option to disable/enable depth test when drawing axis guides.

	* gl/src/TGLViewerEditor.cxx:
	* gl/inc/TGLViewerEditor.h:
	Add GUI to manipulate camera center and to disable/enable depth
	test when drawing axis guides.

	* gl/src/TGLClipSetEditor.cxx:
	Change layout of labeled number entries.

	* gl/src/TGLLightSet.cxx:
	Fix positioning of front light. White-space consolidation.

	* gl/src/TGLLightSetEditor.cxx:
	* gl/inc/TGLLightSetEditor.h:
        Put GUI for the 6 lights in two columns.


/**************************************************************************/

	* tutorials/gl/glViewerExercise.C:
	Follow-up on changes in TGLCamera. Enable rotation on
	orthographic camera.

	* tutorials/gl/glViewerLOD.C:
	Workourond for cint bug with switch statements.


git-svn-id: http://root.cern.ch/svn/root/trunk@20292 27541ba8-7e3a-0410-8455-c3a389f83636
---
 base/inc/TVirtualViewer3D.h     |   1 +
 ged/src/TGedEditor.cxx          |   2 +-
 gl/inc/TGLCamera.h              |  55 +++-
 gl/inc/TGLLightSetEditor.h      |   4 +-
 gl/inc/TGLOrthoCamera.h         |  37 ++-
 gl/inc/TGLPerspectiveCamera.h   |  27 +-
 gl/inc/TGLScenePad.h            |   1 +
 gl/inc/TGLUtil.h                | 129 +++++++--
 gl/inc/TGLViewer.h              |  21 +-
 gl/inc/TGLViewerEditor.h        |  21 +-
 gl/src/TGLCamera.cxx            | 196 ++++++++++++-
 gl/src/TGLClipSetEditor.cxx     |  32 +--
 gl/src/TGLLightSet.cxx          |  32 +--
 gl/src/TGLLightSetEditor.cxx    |  49 ++--
 gl/src/TGLOrthoCamera.cxx       | 470 ++++++++++++++------------------
 gl/src/TGLPerspectiveCamera.cxx | 209 ++++----------
 gl/src/TGLScenePad.cxx          |  98 ++++---
 gl/src/TGLUtil.cxx              | 188 +++++++++++--
 gl/src/TGLViewer.cxx            | 134 ++++++---
 gl/src/TGLViewerEditor.cxx      | 252 ++++++++++++-----
 tutorials/gl/glViewerExercise.C | 167 +++++-------
 tutorials/gl/glViewerLOD.C      |  54 ++--
 22 files changed, 1311 insertions(+), 868 deletions(-)

diff --git a/base/inc/TVirtualViewer3D.h b/base/inc/TVirtualViewer3D.h
index 6dd0148c015..93d04ff5850 100644
--- a/base/inc/TVirtualViewer3D.h
+++ b/base/inc/TVirtualViewer3D.h
@@ -56,6 +56,7 @@ public:
    // When they can, TPad::Paint() and TPad::PaintModified() simply
    // call the following function:
    virtual void   PadPaint(TVirtualPad*) {}
+   virtual void   ObjectPaint(TObject*, Option_t* = "")  {}
 
    // Addition/removal of objects must occur between Begin/EndUpdate calls
    virtual void   BeginScene() = 0;
diff --git a/ged/src/TGedEditor.cxx b/ged/src/TGedEditor.cxx
index bb60c004596..409b67abf26 100644
--- a/ged/src/TGedEditor.cxx
+++ b/ged/src/TGedEditor.cxx
@@ -538,7 +538,7 @@ void TGedEditor::ActivateEditor(TClass* cl, Bool_t recurse)
             while ((subf = (TGedFrame::TGedSubFrame*)next())) {
                // locate the composite frame on created tabs
                TGedTabInfo* ti = GetEditorTabInfo(subf->fName);
-               ti->fContainer->AddFrame(subf->fFrame);
+               ti->fContainer->AddFrame(subf->fFrame, new TGLayoutHints(kLHintsNormal | kLHintsExpandX));
                if (fVisibleTabs.FindObject(ti) == 0)
                   fVisibleTabs.Add(ti);
             }
diff --git a/gl/inc/TGLCamera.h b/gl/inc/TGLCamera.h
index 7321dc54798..a9ac83c1bf9 100644
--- a/gl/inc/TGLCamera.h
+++ b/gl/inc/TGLCamera.h
@@ -22,8 +22,8 @@
 #include "TPoint.h"
 #endif
 
-#include <assert.h>
-#include <math.h>
+#include <cassert>
+#include <cmath>
 
 //////////////////////////////////////////////////////////////////////////
 //                                                                      //
@@ -128,6 +128,20 @@ private:
 
 protected:
    // Fields
+   TGLMatrix   fCamBase;         //! tranformation to center and rotation from up to x vector
+   TGLMatrix   fCamTrans;        //! transformation relative to fCamTrans
+   Bool_t      fExternalCenter;  //! use external center insead of scene center
+   TGLVector3  fExtCenter;       //! external camera center
+   TGLVector3  fDefCenter;       //! deafult camera center
+   TGLVector3 *fCenter;          //! current camera center
+
+   mutable Double_t fNearClip;   //! last applied near-clip
+   mutable Double_t fFarClip;    //! last applied far-clip
+
+   // Set in Setup()
+   Double_t    fDollyDefault;    //! default distnce from viewing centre
+   Double_t    fDollyDistance;   //! unit distance for camera movement in fwd/bck direction
+   Float_t     fVAxisMinAngle;	 //! minimal allowed angle between up and fCamTrans Z vector
 
    // Internal cached matrices and frustum planes
    mutable Bool_t    fCacheDirty;                      //! cached items dirty?
@@ -147,12 +161,16 @@ protected:
    Bool_t     AdjustAndClampVal(Double_t & val, Double_t min, Double_t max,
                                 Int_t screenShift, Int_t screenShiftRange,
                                 Bool_t mod1, Bool_t mod2) const;
+   Double_t   AdjustDelta(Int_t screenShift, Double_t deltaFactor,
+                                Bool_t mod1, Bool_t mod2) const;
 
    // Internal cache update - const as the actual camera configuration is unaffected
    void       UpdateCache() const;
 
+   static     UInt_t   fgDollyDeltaSens;
 public:
    TGLCamera();
+   TGLCamera(const TGLVector3 & hAxis, const TGLVector3 & vAxis);
    virtual ~TGLCamera();
 
    Bool_t IsCacheDirty() const { return fCacheDirty; }
@@ -165,20 +183,32 @@ public:
    // Camera manipulation interface (GL coord - origin bottom left)
    virtual void   Setup(const TGLBoundingBox & box, Bool_t reset=kTRUE) = 0;
    virtual void   Reset() = 0;
-   // virtual void   Frame(const TGLBoundingBox & box) = 0; // TODO
-   // virtual void   Frame(const TGLRec & rect) = 0; // TODO
-   virtual Bool_t Dolly(Int_t delta, Bool_t mod1, Bool_t mod2) = 0;
+
+   virtual Bool_t Dolly(Int_t delta, Bool_t mod1, Bool_t mod2);
    virtual Bool_t Zoom (Int_t delta, Bool_t mod1, Bool_t mod2) = 0;
-   virtual Bool_t Truck(Int_t x, Int_t y, Int_t xDelta, Int_t yDelta) = 0;
-   virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta) = 0;
+   virtual Bool_t Truck(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2);
+   virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2);
+   virtual Bool_t RotateRad(Double_t hRotate, Double_t vRotate);
 
    virtual void   Apply(const TGLBoundingBox & sceneBox, const TGLRect * pickRect = 0) const = 0;
    virtual void   Markup(TGLCameraMarkupStyle* /* ms */) const {}
 
+   void    SetExternalCenter(Bool_t x);
+   Bool_t  GetExternalCenter(){ return fExternalCenter; }
+
+   void    SetCenterVec( Double_t x, Double_t y, Double_t z);
+   Double_t* GetCenterVec() { return fCenter->Arr(); }
+
+   Double_t GetNearClip() const { return fNearClip; }
+   Double_t GetFarClip()  const { return fFarClip;  }
+
+   const TGLMatrix& GetCamBase()  const { return fCamBase;  }
+   const TGLMatrix& GetCamTrans() const { return fCamTrans; }
+
    // Current orientation and frustum
-         TGLVertex3 EyePoint() const;
-         TGLVector3 EyeDirection() const;
-         TGLVertex3 FrustumCenter() const;
+   TGLVertex3 EyePoint() const;
+   TGLVector3 EyeDirection() const;
+   TGLVertex3 FrustumCenter() const;
    const TGLPlane & FrustumPlane(EFrustumPlane plane) const;
 
    // Overlap / projection / intersection tests
@@ -204,6 +234,11 @@ public:
 
    const TGLRect& RefViewport() const { return fViewport; }
 
+   Float_t GetVAxisMinAngle(){return fVAxisMinAngle;}
+   void    SetVAxisMinAngle(Float_t x){fVAxisMinAngle = x;}
+
+   virtual void Configure(Double_t zoom, Double_t dolly, Double_t center[3],
+                  Double_t hRotate, Double_t vRotate) = 0;
    // Cameras expanded-frustum interest box
    Bool_t OfInterest(const TGLBoundingBox & box, Bool_t ignoreSize) const;
    Bool_t UpdateInterest(Bool_t force);
diff --git a/gl/inc/TGLLightSetEditor.h b/gl/inc/TGLLightSetEditor.h
index c9fba2ad523..6c774a133d8 100644
--- a/gl/inc/TGLLightSetEditor.h
+++ b/gl/inc/TGLLightSetEditor.h
@@ -24,7 +24,7 @@ private:
    TGLLightSetSubEditor& operator=(const TGLLightSetSubEditor&); // Not implemented
 
 protected:
-   TGLLightSet       *fM;
+   TGLLightSet      *fM;
 
    TGGroupFrame     *fLightFrame;
    TGButton         *fTopLight;
@@ -35,7 +35,7 @@ protected:
 
    TGButton         *fSpecularLight;
 
-   TGButton* MakeLampButton(const Text_t* name, Int_t wid);
+   TGButton* MakeLampButton(const Text_t* name, Int_t wid, TGCompositeFrame* parent);
 
 public:
    TGLLightSetSubEditor(const TGWindow* p);
diff --git a/gl/inc/TGLOrthoCamera.h b/gl/inc/TGLOrthoCamera.h
index 4abe2ca81b6..2ba718b17c0 100644
--- a/gl/inc/TGLOrthoCamera.h
+++ b/gl/inc/TGLOrthoCamera.h
@@ -39,28 +39,27 @@ class TGLPaintDevice;
 
 class TGLOrthoCamera : public TGLCamera {
 public:
-   enum EType { kXOY, kXOZ, kZOY  }; // pair of world axes aligned to h/v screen
+   enum EType { kZOY, kXOZ, kX0Y  }; // pair of world axes aligned to h/v screen
 private:
    // Fields
-   EType          fType;         //! type (EType) - one of kXOY, kXOZ, kZOY
+   EType          fType;         //! camera type
+   Bool_t         fEnableRotate; //! enable rotation
 
    // Limits - set in Setup()
    Double_t       fZoomMin;      //! minimum zoom factor
    Double_t       fZoomDefault;  //! default zoom factor
    Double_t       fZoomMax;      //! maximum zoom factor
-   TGLBoundingBox fVolume;       //!
+   TGLBoundingBox fVolume;       //! scene volume
 
    // Current interaction
-   Double_t       fZoom;         //! current zoom
-   TGLVector3     fTruck;        //! current truck vector
-   TGLMatrix      fMatrix;       //! orthographic orientation matrix
+   Double_t       fDefXSize, fDefYSize; //! x, y size of scene from camera view
+   Double_t       fZoom;                //! current zoom
 
-   static   UInt_t   fgZoomDeltaSens;
-
-   //Stuff for TGLPlotPainter.
+   //Stuff for TGLPlotPainter. MT: This *must* go to a special subclass.
    Double_t       fShift;
    Double_t       fOrthoBox[4];
    TGLVertex3     fCenter;
+   TGLVector3     fTruck;
    TArcBall       fArcBall;
    TPoint         fMousePos;
    Bool_t         fVpChanged;
@@ -68,26 +67,27 @@ private:
    // Methods
    void Init();
 
+   static   UInt_t   fgZoomDeltaSens;
 public:
-
-   // TODO: Convert this so define by pair of vectors as per perspective
-   // camera
    TGLOrthoCamera();
-   TGLOrthoCamera(EType type);
+   TGLOrthoCamera(const TGLVector3 & hAxis, const TGLVector3 & vAxis);
    virtual ~TGLOrthoCamera();
 
    virtual void   Setup(const TGLBoundingBox & box, Bool_t reset=kTRUE);
    virtual void   Reset();
-   virtual Bool_t Dolly(Int_t delta, Bool_t mod1, Bool_t mod2);
    virtual Bool_t Zoom (Int_t delta, Bool_t mod1, Bool_t mod2);
-   virtual Bool_t Truck(Int_t x, Int_t y, Int_t xDelta, Int_t yDelta);
-   virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta);
-
+   virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2);
    virtual void   Apply(const TGLBoundingBox & sceneBox, const TGLRect * pickRect = 0) const;
+
    virtual void   Markup (TGLCameraMarkupStyle* ms) const;
 
    // External scripting control
-   void Configure(Double_t left, Double_t right, Double_t top, Double_t bottom);
+   //   void Configure(Double_t left, Double_t right, Double_t top, Double_t bottom);
+   virtual void Configure(Double_t zoom, Double_t dolly, Double_t center[3],
+                  Double_t hRotate, Double_t vRotate);
+
+   void   SetEnableRotate(Bool_t x){ fEnableRotate = x; }
+   Bool_t GetEnableRotate(){ return fEnableRotate; }
 
    //Stuff for TGLPlotPainter.
    void   SetViewport(TGLPaintDevice *dev);
@@ -100,7 +100,6 @@ public:
    void   ZoomOut();
    void   SetCamera()const;
    void   Apply()const;
-
    Bool_t ViewportChanged()const{return fVpChanged;}
    Int_t  GetX()const;
    Int_t  GetY()const;
diff --git a/gl/inc/TGLPerspectiveCamera.h b/gl/inc/TGLPerspectiveCamera.h
index 0dc4179ab84..525cc669af8 100644
--- a/gl/inc/TGLPerspectiveCamera.h
+++ b/gl/inc/TGLPerspectiveCamera.h
@@ -31,43 +31,24 @@
 
 class TGLPerspectiveCamera : public TGLCamera
 {
-   private:
+private:
    // Fields
-   TGLVector3  fHAxis;           //!
-   TGLVector3  fVAxis;           //!
-
-   // Set in Setup()
-   Double_t    fDollyMin;        //!
-   Double_t    fDollyDefault;    //!
-   Double_t    fDollyMax;        //!
-
    Double_t    fFOV;             //!
-   Double_t    fDolly;           //!
-   Double_t    fVRotate;         //!
-   Double_t    fHRotate;         //!
-   TGLVertex3  fCenter;          //!
-   TGLVector3  fTruck;           //!
 
-   // These are fixed for any perspective camera
    static   Double_t fgFOVMin, fgFOVDefault, fgFOVMax;
-   static   UInt_t   fgDollyDeltaSens, fgFOVDeltaSens;
-
+   static   UInt_t   fgFOVDeltaSens;
 public:
    TGLPerspectiveCamera(const TGLVector3 & hAxis, const TGLVector3 & vAxis);
    virtual ~TGLPerspectiveCamera();
 
    virtual void   Setup(const TGLBoundingBox & box, Bool_t reset=kTRUE);
    virtual void   Reset();
-   virtual Bool_t Dolly(Int_t delta, Bool_t mod1, Bool_t mod2);
    virtual Bool_t Zoom (Int_t delta, Bool_t mod1, Bool_t mod2);
-   virtual Bool_t Truck(Int_t x, Int_t y, Int_t xDelta, Int_t yDelta);
-   virtual Bool_t Rotate(Int_t xDelta, Int_t yDelta);
-
    virtual void   Apply(const TGLBoundingBox & box, const TGLRect * pickRect = 0) const;
 
    // External scripting control
-   void Configure(Double_t fov, Double_t dolly, Double_t center[3],
-                  Double_t hRotate, Double_t vRotate);
+   virtual void Configure(Double_t fov, Double_t dolly, Double_t center[3],
+                          Double_t hRotate, Double_t vRotate);
 
    ClassDef(TGLPerspectiveCamera,0) // a perspective view camera
 };
diff --git a/gl/inc/TGLScenePad.h b/gl/inc/TGLScenePad.h
index 8ddd6d3438a..24601ea654d 100644
--- a/gl/inc/TGLScenePad.h
+++ b/gl/inc/TGLScenePad.h
@@ -79,6 +79,7 @@ public:
 
    virtual Bool_t CanLoopOnPrimitives() const { return kTRUE; }
    virtual void   PadPaint(TVirtualPad* pad);
+   virtual void   ObjectPaint(TObject* obj, Option_t* opt="");
 
    // For now handled by viewer
    virtual Int_t  DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/) { return 9999; }
diff --git a/gl/inc/TGLUtil.h b/gl/inc/TGLUtil.h
index ff20af12dbc..a8ce107ef07 100644
--- a/gl/inc/TGLUtil.h
+++ b/gl/inc/TGLUtil.h
@@ -25,7 +25,7 @@ class TGLCamera;
 
 #include <cmath>
 #include <vector>
-#include <assert.h>
+#include <cassert>
 
 // TODO:Find a better place for these enums - TGLEnum.h?
 // Whole GL viewer should be moved into own namespace
@@ -103,14 +103,16 @@ protected:
 public:
    TGLVertex3();
    TGLVertex3(Double_t x, Double_t y, Double_t z);
+   TGLVertex3(Double_t* v);
    TGLVertex3(const TGLVertex3 & other);
    virtual ~TGLVertex3();
 
-         Bool_t       operator == (const TGLVertex3 & rhs) const;
-         TGLVertex3 & operator =  (const TGLVertex3 & rhs);
+   Bool_t       operator == (const TGLVertex3 & rhs) const;
+   TGLVertex3 & operator =  (const TGLVertex3 & rhs);
+   TGLVertex3 & operator *= (Double_t f);
+   TGLVertex3   operator -  () const;
    const TGLVertex3 & operator -= (const TGLVector3 & val);
    const TGLVertex3 & operator += (const TGLVector3 & val);
-         TGLVertex3   operator -  () const;
 
    // Manipulators
    void Fill(Double_t val);
@@ -141,6 +143,12 @@ public:
    ClassDef(TGLVertex3,0) // GL 3 component vertex helper/wrapper class
 };
 
+//______________________________________________________________________________
+inline TGLVertex3 operator*(Double_t f, const TGLVertex3& v)
+{
+   return TGLVertex3(f*v.X(), f*v.Y(), f*v.Z());
+}
+
 //______________________________________________________________________________
 inline void TGLVertex3::Negate()
 {
@@ -173,6 +181,15 @@ inline TGLVertex3 TGLVertex3::operator - () const
    return TGLVertex3(-fVals[0], -fVals[1], -fVals[2]);
 }
 
+//______________________________________________________________________________
+inline TGLVertex3& TGLVertex3::operator *= (Double_t f)
+{
+   fVals[0] *= f;
+   fVals[1] *= f;
+   fVals[2] *= f;
+   return *this;
+}
+
 //______________________________________________________________________________
 inline Double_t & TGLVertex3::operator [] (Int_t index)
 {
@@ -240,9 +257,11 @@ public:
    TGLVector3(const TGLVector3 & other);
    virtual ~TGLVector3();
 
-   const TGLVector3 & operator /= (Double_t val);
-   const TGLVector3 & operator *= (Double_t val);
-         TGLVector3   operator -  () const;
+   TGLVector3& operator = (const TGLVertex3& v)
+   { fVals[0] = v[0]; fVals[1] = v[1]; fVals[2] = v[2]; return *this; }
+
+   TGLVector3 & operator /= (Double_t val);
+   TGLVector3   operator -  () const;
 
    Double_t Mag() const;
    void     Normalise();
@@ -267,7 +286,7 @@ inline const TGLVertex3 & TGLVertex3::operator += (const TGLVector3 & vec)
 }
 
 //______________________________________________________________________________
-inline const TGLVector3 & TGLVector3::operator /= (Double_t val)
+inline TGLVector3 & TGLVector3::operator /= (Double_t val)
 {
    fVals[0] /= val;
    fVals[1] /= val;
@@ -275,15 +294,6 @@ inline const TGLVector3 & TGLVector3::operator /= (Double_t val)
    return *this;
 }
 
-//______________________________________________________________________________
-inline const TGLVector3 & TGLVector3::operator *= (Double_t val)
-{
-   fVals[0] *= val;
-   fVals[1] *= val;
-   fVals[2] *= val;
-   return *this;
-}
-
 //______________________________________________________________________________
 inline TGLVector3 TGLVector3::operator - () const
 {
@@ -363,6 +373,13 @@ inline TGLVector3 operator - (const TGLVector3 & vector1, const TGLVector3 & vec
    return TGLVector3(vector1[0] - vector2[0], vector1[1] - vector2[1], vector1[2] - vector2[2]);
 }
 
+//______________________________________________________________________________
+// Dot-product
+inline Double_t operator * (const TGLVector3 & a, const TGLVector3 & b)
+{
+   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+}
+
 //////////////////////////////////////////////////////////////////////////
 //                                                                      //
 // TGLLine3                                                             //
@@ -506,7 +523,9 @@ inline void TGLRect::Expand(Int_t x, Int_t y)
 //______________________________________________________________________________
 inline Int_t TGLRect::Diagonal() const
 {
-   return static_cast<Int_t>(sqrt(static_cast<Double_t>(fWidth*fWidth + fHeight*fHeight)));
+   const Double_t w = static_cast<Double_t>(fWidth);
+   const Double_t h = static_cast<Double_t>(fHeight);
+   return static_cast<Int_t>(sqrt(w*w + h*h));
 }
 
 //______________________________________________________________________________
@@ -709,22 +728,23 @@ public:
    TGLMatrix();
    TGLMatrix(Double_t x, Double_t y, Double_t z);
    TGLMatrix(const TGLVertex3 & translation);
-   TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 * xAxis = 0);
+   TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis);
+   TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis);
    TGLMatrix(const Double_t vals[16]);
    TGLMatrix(const TGLMatrix & other);
    virtual ~TGLMatrix(); // ClassDef introduces virtual fns
 
    // Operators
    TGLMatrix & operator =(const TGLMatrix & rhs);
-   Double_t & operator [] (Int_t index);
-   Double_t operator [] (Int_t index) const;
+   Double_t  & operator [] (Int_t index);
+   Double_t    operator [] (Int_t index) const;
 
    void MultRight(const TGLMatrix & rhs);
    void MultLeft (const TGLMatrix & lhs);
    TGLMatrix & operator*=(const TGLMatrix & rhs) { MultRight(rhs); return *this; }
 
    // Manipulators
-   void Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 * xAxis = 0);
+   void Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis = 0);
    void Set(const Double_t vals[16]);
    void SetIdentity();
 
@@ -732,16 +752,30 @@ public:
    void SetTranslation(const TGLVertex3 & translation);
 
    void Translate(const TGLVector3 & vect);
+   void MoveLF(Int_t ai, Double_t amount);
    void Scale(const TGLVector3 & scale);
    void Rotate(const TGLVertex3 & pivot, const TGLVector3 & axis, Double_t angle);
    void RotateLF(Int_t i1, Int_t i2, Double_t amount);
+   void RotatePF(Int_t i1, Int_t i2, Double_t amount);
    void TransformVertex(TGLVertex3 & vertex) const;
    void Transpose3x3();
+   Double_t Invert();
 
    // Accesors
-   TGLVertex3  GetTranslation() const;
+   TGLVector3  GetTranslation() const;
    TGLVector3  GetScale() const;
 
+   void SetBaseVec(Int_t b, Double_t x, Double_t y, Double_t z);
+   void SetBaseVec(Int_t b, const TGLVector3& v);
+   void SetBaseVec(Int_t b, Double_t* x);
+
+   TGLVector3 GetBaseVec(Int_t b) const;
+   void       GetBaseVec(Int_t b, TGLVector3& v) const;
+   void       GetBaseVec(Int_t b, Double_t* x) const;
+
+   void       MultiplyIP(TGLVector3& v, Double_t w=1) const;
+   void       RotateIP(TGLVector3& v) const;
+
    // Internal data accessors - for GL API
    const Double_t * CArr() const { return fVals; }
    Double_t * Arr() { return fVals; }
@@ -811,6 +845,48 @@ inline TGLMatrix operator * (const TGLMatrix & lhs, const TGLMatrix & rhs)
    return res;
 }
 
+//______________________________________________________________________________
+inline void TGLMatrix::SetBaseVec(Int_t b, Double_t x, Double_t y, Double_t z)
+{
+   Double_t* C = fVals + 4*--b;
+   C[0] = x; C[1] = y; C[2] = z;
+}
+
+//______________________________________________________________________________
+inline void TGLMatrix::SetBaseVec(Int_t b, const TGLVector3& v)
+{
+   Double_t* C = fVals + 4*--b;
+   C[0] = v[0]; C[1] = v[1]; C[2] = v[2];
+}
+
+//______________________________________________________________________________
+inline void TGLMatrix::SetBaseVec(Int_t b, Double_t* x)
+{
+   Double_t* C = fVals + 4*--b;
+   C[0] = x[0]; C[1] = x[1]; C[2] = x[2];
+}
+
+//______________________________________________________________________________
+inline TGLVector3 TGLMatrix::GetBaseVec(Int_t b) const
+{
+   return TGLVector3(&fVals[4*--b]);
+}
+
+//______________________________________________________________________________
+inline void TGLMatrix::GetBaseVec(Int_t b, TGLVector3& v) const
+{
+   const Double_t* C = fVals + 4*--b;
+   v[0] = C[0]; v[1] = C[1]; v[2] = C[2];
+}
+
+//______________________________________________________________________________
+inline void TGLMatrix::GetBaseVec(Int_t b, Double_t* x) const
+{
+   const Double_t* C = fVals + 4*--b;
+   x[0] = C[0], x[1] = C[1], x[2] = C[2];
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //                                                                      //
 // TGLUtil                                                              //
@@ -823,6 +899,7 @@ inline TGLMatrix operator * (const TGLMatrix & lhs, const TGLMatrix & rhs)
 class TGLUtil
 {
 private:
+   static UInt_t fgDefaultDrawQuality;
    static UInt_t fgDrawQuality;
 
 protected:
@@ -840,8 +917,10 @@ public:
    enum ELineHeadShape { kLineHeadNone, kLineHeadArrow, kLineHeadBox };
    enum EAxesType      { kAxesNone, kAxesEdge, kAxesOrigin };
 
-   static void SetDrawQuality(UInt_t dq) { fgDrawQuality = dq; }
-   static void ResetDrawQuality()        { fgDrawQuality = 60; }
+   static void   SetDrawQuality(UInt_t dq)        { fgDrawQuality = dq; }
+   static void   ResetDrawQuality()               { fgDrawQuality = fgDefaultDrawQuality; }
+   static UInt_t GetDefaultDrawQuality()          { return fgDefaultDrawQuality; }
+   static void   SetDefaultDrawQuality(UInt_t dq) { fgDefaultDrawQuality = dq; }
 
    // TODO: These draw routines should take LOD hints
    static void SetDrawColors(const Float_t rgba[4]);
diff --git a/gl/inc/TGLViewer.h b/gl/inc/TGLViewer.h
index 69d48a52f43..a66c8c31bff 100644
--- a/gl/inc/TGLViewer.h
+++ b/gl/inc/TGLViewer.h
@@ -91,10 +91,14 @@ protected:
    TGLOvlSelectRecord   fOvlSelRec;            //! select record from last overlay select
 
    // Mouse ineraction
+public:
+   enum EPushAction   { kPushStd,
+                        kPushCamCenter };
    enum EDragAction   { kDragNone,
                         kDragCameraRotate, kDragCameraTruck, kDragCameraDolly,
                         kDragOverlay };
-
+protected:
+   EPushAction          fPushAction;
    EDragAction          fAction;
    TPoint               fLastPos;
    UInt_t               fActiveButtonID;
@@ -105,8 +109,10 @@ protected:
    TGLRect        fViewport;       //! viewport - drawn area
    Color_t        fClearColor;     //! clear-color
    Int_t          fAxesType;       //! axes type
+   Bool_t         fAxesDepthTest;  //! remove guides hidden-lines
    Bool_t         fReferenceOn;    //! reference marker on?
    TGLVertex3     fReferencePos;   //! reference position
+   Bool_t         fDrawCameraCenter; //! reference marker on?
    TGLCameraMarkupStyle * fCameraMarkup; //! markup size of viewport in scene units
 
    Bool_t         fInitGL;         //! has GL been initialised?
@@ -184,14 +190,21 @@ public:
    // External GUI component interface
    TGLCamera & CurrentCamera() const { return *fCurrentCamera; }
    void SetCurrentCamera(ECameraType camera);
-   void SetOrthoCamera(ECameraType camera, Double_t left, Double_t right, Double_t top, Double_t bottom);
+   void SetOrthoCamera(ECameraType camera, Double_t zoom, Double_t dolly,
+                             Double_t center[3], Double_t hRotate, Double_t vRotate);
    void SetPerspectiveCamera(ECameraType camera, Double_t fov, Double_t dolly,
                              Double_t center[3], Double_t hRotate, Double_t vRotate);
-   void GetGuideState(Int_t & axesType, Bool_t & referenceOn, Double_t referencePos[3]) const;
-   void SetGuideState(Int_t axesType, Bool_t referenceOn, const Double_t referencePos[3]);
+   void GetGuideState(Int_t & axesType, Bool_t & axesDepthTest, Bool_t & referenceOn, Double_t* referencePos) const;
+   void SetGuideState(Int_t axesType, Bool_t axesDepthTest, Bool_t referenceOn, const Double_t* referencePos);
+   void SetDrawCameraCenter(Bool_t x);
+   Bool_t GetDrawCameraCenter() { return fDrawCameraCenter; }
+   void   PickCameraCenter()    { fPushAction = kPushCamCenter; RefreshPadEditor(this); }
    TGLCameraMarkupStyle* GetCameraMarkup() const { return fCameraMarkup; }
    void SetCameraMarkup(TGLCameraMarkupStyle* m) { fCameraMarkup = m; }
 
+   EPushAction GetPushAction() const { return fPushAction; }
+   EDragAction GetAction()     const { return fAction; }
+
    const TGLPhysicalShape * GetSelected() const;
 
    // Draw and selection
diff --git a/gl/inc/TGLViewerEditor.h b/gl/inc/TGLViewerEditor.h
index bd5ae06325a..ab97dfd37e0 100644
--- a/gl/inc/TGLViewerEditor.h
+++ b/gl/inc/TGLViewerEditor.h
@@ -42,10 +42,19 @@ private:
    TGTextButton     *fCameraHome;
 
    //"Guides" tab's controls
+   TGCheckButton    *fCameraCenterExt;
+   TGTextButton     *fCaptureCenter;
+   TGCheckButton    *fDrawCameraCenter;
+   TGNumberEntry    *fCameraCenterX;
+   TGNumberEntry    *fCameraCenterY;
+   TGNumberEntry    *fCameraCenterZ;
+
+   Int_t             fAxesType;
    TGButtonGroup    *fAxesContainer;
    TGRadioButton    *fAxesNone;
    TGRadioButton    *fAxesEdge;
    TGRadioButton    *fAxesOrigin;
+   TGCheckButton    *fAxesDepthTest;
 
    TGGroupFrame     *fRefContainer;
    TGCheckButton    *fReferenceOn;
@@ -72,6 +81,8 @@ private:
    void CreateGuidesTab();
    void CreateClippingTab();
 
+   void UpdateReferencePosState();
+
 public:
    TGLViewerEditor(const TGWindow *p=0, Int_t width=140, Int_t height=30,
                    UInt_t options=kChildFrame, Pixel_t back=GetDefaultFrameBackground());
@@ -88,13 +99,19 @@ public:
    void DoResetCameraOnDoubleClick();
    void DoUpdateScene();
    void DoCameraHome();
+   void DoCameraCenterExt();
+   void DoCaptureCenter();
+   void DoDrawCameraCenter();
+   void UpdateCameraCenter();
    //Axis manipulation
-   void UpdateViewerGuides();
-   void UpdateReferencePos();
+   void UpdateViewerAxes(Int_t id);
+   void UpdateViewerReference();
    void DoCameraMarkup();
 
    void DetachFromPad(){fIsInPad = kFALSE;}
 
+   static TGNumberEntry* MakeLabeledNEntry(TGCompositeFrame* p, const char* name, Int_t labelw,Int_t nd=7, Int_t s=5);
+
    ClassDef(TGLViewerEditor, 0) //GUI for editing TGLViewer attributes
 };
 
diff --git a/gl/src/TGLCamera.cxx b/gl/src/TGLCamera.cxx
index 4e575a2828e..cc15051f38e 100644
--- a/gl/src/TGLCamera.cxx
+++ b/gl/src/TGLCamera.cxx
@@ -13,6 +13,7 @@
 #include "TGLIncludes.h"
 #include "TGLBoundingBox.h"
 #include "TError.h"
+#include "TMath.h"
 
 //////////////////////////////////////////////////////////////////////////
 //                                                                      //
@@ -37,9 +38,15 @@
 ClassImp(TGLCamera)
 
 const Double_t TGLCamera::fgInterestBoxExpansion = 1.3;
+UInt_t         TGLCamera::fgDollyDeltaSens       = 500;
 
 //______________________________________________________________________________
 TGLCamera::TGLCamera() :
+   fExternalCenter(kFALSE),
+   fCenter(&fDefCenter),
+   fNearClip(0), fFarClip(0),
+   fDollyDefault(1.0), fDollyDistance(1.0),
+   fVAxisMinAngle(0.01f),
    fCacheDirty(kTRUE),
    fTimeStamp (1),
    fProjM(), fModVM(), fClipM(),
@@ -50,6 +57,29 @@ TGLCamera::TGLCamera() :
    for (UInt_t i = 0; i < kPlanesPerFrustum; i++ ) {
       fFrustumPlanes[i].Set(1.0, 0.0, 0.0, 0.0);
    }
+   TGLVertex3 origin;
+   fCamBase.Set(origin, TGLVector3(1, 0, 0), TGLVector3(0, 0, 1));
+}
+
+//______________________________________________________________________________
+TGLCamera::TGLCamera(const TGLVector3 & hAxis, const TGLVector3 & vAxis) :
+   fExternalCenter(kFALSE),
+   fCenter(&fDefCenter),
+   fNearClip(0), fFarClip(0),
+   fDollyDefault(1.0), fDollyDistance(1.0),
+   fVAxisMinAngle(0.01f),
+   fCacheDirty(kTRUE),
+   fTimeStamp (1),
+   fProjM(), fModVM(), fClipM(),
+   fViewport(0,0,100,100),
+   fLargestSeen(0.0)
+{
+   // Default base camera constructor
+   for (UInt_t i = 0; i < kPlanesPerFrustum; i++ ) {
+      fFrustumPlanes[i].Set(1.0, 0.0, 0.0, 0.0);
+   }
+   TGLVertex3 origin;
+   fCamBase.Set(origin, vAxis, hAxis);
 }
 
 //______________________________________________________________________________
@@ -690,14 +720,34 @@ Bool_t TGLCamera::AdjustAndClampVal(Double_t & val, Double_t min, Double_t max,
       val = max;
    }
 
-   if (val != oldVal)
-   {
-      return kTRUE;
-   }
-   else
-   {
-      return kFALSE;
+   return val != oldVal;
+}
+
+//______________________________________________________________________________
+Double_t TGLCamera::AdjustDelta(Int_t screenShift, Double_t deltaFactor,
+                                Bool_t mod1, Bool_t mod2) const
+{
+   // Adjust a passed screen value and apply modifiers.
+   // See AdjustAndClampVal() for details.
+
+   if (screenShift == 0)
+      return 0;
+
+   // Calculate a sensitivity based on passed modifiers
+   Double_t sens = 1.0;
+
+   if (mod1) {
+      sens *= 0.1;
+      if (mod2) {
+         sens *= 0.1;
+      }
+   } else {
+      if (mod2) {
+         sens *= 10.0;
+      }
    }
+
+   return sens * deltaFactor * screenShift;
 }
 
 //______________________________________________________________________________
@@ -736,3 +786,135 @@ void TGLCamera::DrawDebugAids() const
    glVertex3dv(end.CArr());
    glEnd();
 }
+
+//______________________________________________________________________________
+void TGLCamera::SetExternalCenter(Bool_t enable)
+{
+   // Set camera center diffrent than scene center, if enable is kTRUE.
+
+   if (fExternalCenter == enable)
+      return;
+
+   fExternalCenter = enable;
+   if (fExternalCenter)
+      fCenter = &fExtCenter;
+   else
+      fCenter = &fDefCenter;
+
+   TGLMatrix bt = fCamBase * fCamTrans;
+   fCamBase.SetBaseVec(4, *fCenter);
+   TGLMatrix binv = fCamBase; binv.Invert();
+   fCamTrans = binv * bt;
+
+   IncTimeStamp();
+}
+
+//______________________________________________________________________________
+void TGLCamera::SetCenterVec(Double_t x, Double_t y, Double_t z)
+{
+   // Set camera center vector.
+
+   if (fExternalCenter)
+      fExtCenter.Set(x, y, z);
+   else
+      fDefCenter.Set(x, y, z);
+
+   TGLMatrix bt = fCamBase * fCamTrans;
+   fCamBase.SetBaseVec(4, *fCenter);
+   TGLMatrix binv = fCamBase; binv.Invert();
+   fCamTrans = binv * bt;
+
+   IncTimeStamp();
+}
+
+//______________________________________________________________________________
+Bool_t TGLCamera::Truck(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
+{
+   // Truck the camera - 'move camera parallel to film plane'.
+   // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
+
+   Double_t xstep = AdjustDelta(xDelta, 0.2*fDollyDistance, mod1, mod2);
+   fCamTrans.MoveLF(2, -xstep);
+
+   Double_t ystep = AdjustDelta(yDelta, 0.2*fDollyDistance, mod1, mod2);
+   fCamTrans.MoveLF(3, -ystep);
+
+   IncTimeStamp();
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TGLCamera::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
+{
+   // Rotate the camera round view volume center established in Setup().
+   // Arguments are:
+   // xDelta - horizontal delta (pixels)
+   // YDelta - vertical delta (pixels)
+
+   Double_t vRotate = AdjustDelta(xDelta, TMath::TwoPi() / fViewport.Width(), mod1, mod2);
+   Double_t hRotate = AdjustDelta(yDelta, TMath::Pi()   / fViewport.Height(), mod1, mod2);
+
+   return RotateRad(hRotate, vRotate);
+}
+
+//______________________________________________________________________________
+Bool_t TGLCamera::RotateRad(Double_t hRotate, Double_t vRotate)
+{
+   // Rotate camera around center.
+
+   using namespace TMath;
+   if (hRotate != 0.0)
+   {
+      TGLVector3 fwd  = fCamTrans.GetBaseVec(1);
+      TGLVector3 lft  = fCamTrans.GetBaseVec(2);
+      TGLVector3 up   = fCamTrans.GetBaseVec(3);
+      TGLVector3 pos  = fCamTrans.GetTranslation();
+
+      TGLVector3 deltaT = pos - (pos*lft)*lft;
+      Double_t   deltaF = deltaT * fwd;
+      Double_t   deltaU = deltaT * up;
+
+      // up vector lock
+      TGLVector3 zdir = fCamBase.GetBaseVec(3);
+      fCamBase.RotateIP(fwd);
+      Double_t theta = ACos(fwd*zdir);
+      if(theta+hRotate < fVAxisMinAngle)
+         hRotate = fVAxisMinAngle - theta;
+      else if(theta+hRotate > Pi() - fVAxisMinAngle)
+         hRotate = Pi() - fVAxisMinAngle - theta;
+
+      fCamTrans.MoveLF(1, -deltaF);
+      fCamTrans.MoveLF(3, -deltaU);
+      fCamTrans.RotateLF(3, 1, hRotate);
+      fCamTrans.MoveLF(3,  deltaU);
+      fCamTrans.MoveLF(1,  deltaF);
+   }
+   if (vRotate != 0.0)
+   {
+      fCamTrans.RotatePF(1, 2, -vRotate);
+   }
+
+   IncTimeStamp();
+   return kTRUE;
+}
+
+//______________________________________________________________________________
+Bool_t TGLCamera::Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
+{
+   // Dolly the camera - 'move camera along eye line, retaining lens focal length'.
+   // Arguments are:
+   //
+   // 'delta' - mouse viewport delta (pixels) - +ive dolly in, -ive dolly out
+   // 'mod1' / 'mod2' - sensitivity modifiers - see TGLCamera::AdjustAndClampVal()
+   //
+   // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
+
+   Double_t step = AdjustDelta(delta, fDollyDistance, mod1, mod2);
+   if (step == 0)
+      return kFALSE;
+
+   fCamTrans.MoveLF(1, -step);
+
+   IncTimeStamp();
+   return kTRUE;
+}
diff --git a/gl/src/TGLClipSetEditor.cxx b/gl/src/TGLClipSetEditor.cxx
index abcecb716a9..eeb7a69bc08 100644
--- a/gl/src/TGLClipSetEditor.cxx
+++ b/gl/src/TGLClipSetEditor.cxx
@@ -18,6 +18,7 @@
 #include "TGButtonGroup.h"
 #include "TGNumberEntry.h"
 
+#include "TGLViewerEditor.h"
 
 //______________________________________________________________________________
 // TGLClipSetSubEditor
@@ -49,45 +50,36 @@ TGLClipSetSubEditor::TGLClipSetSubEditor(const TGWindow *p) :
    new TGRadioButton(fTypeButtons, "Plane");
    new TGRadioButton(fTypeButtons, "Box");
 
-   AddFrame(fTypeButtons, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fTypeButtons, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
    // Clip inside / edit
    fClipInside = new TGCheckButton(this, "Clip away inside");
-   AddFrame(fClipInside, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fClipInside, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
    fClipEdit   = new TGCheckButton(this, "Edit In Viewer");
-   AddFrame(fClipEdit, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fClipEdit, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
    fClipShow   = new TGCheckButton(this, "Show In Viewer");
-   AddFrame(fClipShow, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fClipShow, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
 
    // Plane properties
    fPlanePropFrame = new TGCompositeFrame(this);
-   //fPlanePropFrame->SetCleanup(kDeepCleanup);
-   AddFrame(fPlanePropFrame, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fPlanePropFrame, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
 
    static const char * const planeStr[] = { "aX + ", "bY +", "cZ + ", "d = 0" };
 
-   for (Int_t i = 0; i < 4; ++i) {
-      TGLabel *label = new TGLabel(fPlanePropFrame, planeStr[i]);
-      fPlanePropFrame->AddFrame(label, new TGLayoutHints(kLHintsTop | kLHintsLeft, 3, 3, 3, 3));
-      fPlaneProp[i] = new TGNumberEntry(fPlanePropFrame, 1., 8);
-      fPlanePropFrame->AddFrame(fPlaneProp[i], new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-   }
+   for (Int_t i = 0; i < 4; ++i)
+     fPlaneProp[i] = TGLViewerEditor::MakeLabeledNEntry(fPlanePropFrame, planeStr[i] , 40);
 
    // Box properties
    fBoxPropFrame = new TGCompositeFrame(this);
-   AddFrame(fBoxPropFrame, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fBoxPropFrame, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
 
    static const char * const boxStr[] = {"Center X", "Center Y", "Center Z", "Length X", "Length Y", "Length Z" };
 
-   for (Int_t i = 0; i < 6; ++i) {
-      TGLabel *label = new TGLabel(fBoxPropFrame, boxStr[i]);
-      fBoxPropFrame->AddFrame(label, new TGLayoutHints(kLHintsTop | kLHintsLeft, 3, 3, 3, 3));
-      fBoxProp[i] = new TGNumberEntry(fBoxPropFrame, 1., 8);
-      fBoxPropFrame->AddFrame(fBoxProp[i], new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-   }
+   for (Int_t i = 0; i < 6; ++i)
+     fBoxProp[i] = TGLViewerEditor::MakeLabeledNEntry(fBoxPropFrame, boxStr[i] , 60);
 
    // Apply button
    fApplyButton = new TGTextButton(this, "Apply");
-   AddFrame(fApplyButton, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   AddFrame(fApplyButton, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 2, 2));
 
    fTypeButtons->Connect("Clicked(Int_t)", "TGLClipSetSubEditor", this, "ClipTypeChanged(Int_t)");
    fClipInside->Connect("Clicked()", "TGLClipSetSubEditor", this, "UpdateViewerClip()");
diff --git a/gl/src/TGLLightSet.cxx b/gl/src/TGLLightSet.cxx
index 283f9411c50..5d372322d4b 100644
--- a/gl/src/TGLLightSet.cxx
+++ b/gl/src/TGLLightSet.cxx
@@ -83,9 +83,6 @@ void TGLLightSet::StdSetupLights(const TGLBoundingBox& bbox,
       Double_t lightRadius = bbox.Extents().Mag() * 2.9;
       Double_t sideLightsZ, frontLightZ;
 
-      // Find Z depth (in eye coords) for front and side lights
-      // Has to be handlded differently due to ortho camera infinite
-      // viewpoint. TODO: Move into camera classes?
       const TGLOrthoCamera* orthoCamera = dynamic_cast<const TGLOrthoCamera*>(&camera);
       if (orthoCamera) {
          // Find distance from near clip plane to furstum center - i.e. vector of half
@@ -95,14 +92,13 @@ void TGLLightSet::StdSetupLights(const TGLBoundingBox& bbox,
          frontLightZ = sideLightsZ;
       } else {
          // Perspective camera
-
-         // Extract vector from camera eye point to center
-         // Camera must have been applied already
+         // Extract vector from camera eye point to center.
+         // Camera must have been applied already.
          TGLVector3 eyeVector = camera.EyePoint() - camera.FrustumCenter();
 
          // Pull forward slightly (0.85) to avoid to sharp a cutoff
          sideLightsZ = eyeVector.Mag() * -0.85;
-         frontLightZ = 0.0;
+         frontLightZ = 0.2 * lightRadius;
       }
 
       // Reset the modelview so static lights are placed in fixed eye space
@@ -111,26 +107,22 @@ void TGLLightSet::StdSetupLights(const TGLBoundingBox& bbox,
 
       // 0: Front, 1: Top, 2: Bottom, 3: Left, 4: Right
       TGLVertex3 center = bbox.Center();
-      Float_t pos0[] = { center.X(), center.Y(), frontLightZ, 1.0 };
+      // Float_t pos0[] = { center.X(), center.Y(), frontLightZ, 1.0 };
+      Float_t pos0[] = { 0.0,        0.0,                      frontLightZ, 1.0 };
       Float_t pos1[] = { center.X(), center.Y() + lightRadius, sideLightsZ, 1.0 };
       Float_t pos2[] = { center.X(), center.Y() - lightRadius, sideLightsZ, 1.0 };
       Float_t pos3[] = { center.X() - lightRadius, center.Y(), sideLightsZ, 1.0 };
       Float_t pos4[] = { center.X() + lightRadius, center.Y(), sideLightsZ, 1.0 };
 
-      Float_t frontLightColor[] = {0.35, 0.35, 0.35, 1.0};
-      Float_t sideLightColor[] = {0.7, 0.7, 0.7, 1.0};
+      const Float_t frontLightColor[] = { 0.4, 0.4, 0.4, 1.0 };
+      const Float_t sideLightColor[]  = { 0.7, 0.7, 0.7, 1.0 };
+      const Float_t whiteSpec[]       = { 0.8, 0.8, 0.8, 1.0 };
+      const Float_t nullSpec[]        = { 0.0, 0.0, 0.0, 1.0 };
+
       glLightfv(GL_LIGHT0, GL_POSITION, pos0);
       glLightfv(GL_LIGHT0, GL_DIFFUSE, frontLightColor);
-      if (fUseSpecular)
-      {
-         const Float_t whiteSpec[] = {1.f, 1.f, 1.f, 1.f};
-         glLightfv(GL_LIGHT0, GL_SPECULAR, whiteSpec);
-      }
-      else
-      {
-         const Float_t nullSpec[] = {0.f, 0.f, 0.f, 1.f};
-         glLightfv(GL_LIGHT0, GL_SPECULAR, nullSpec);
-      }
+      glLightfv(GL_LIGHT0, GL_SPECULAR, fUseSpecular ? whiteSpec : nullSpec);
+
       glLightfv(GL_LIGHT1, GL_POSITION, pos1);
       glLightfv(GL_LIGHT1, GL_DIFFUSE,  sideLightColor);
       glLightfv(GL_LIGHT2, GL_POSITION, pos2);
diff --git a/gl/src/TGLLightSetEditor.cxx b/gl/src/TGLLightSetEditor.cxx
index 3300b6c0fa2..a3eb025e7a9 100644
--- a/gl/src/TGLLightSetEditor.cxx
+++ b/gl/src/TGLLightSetEditor.cxx
@@ -28,6 +28,7 @@
 
 ClassImp(TGLLightSetSubEditor)
 
+//______________________________________________________________________________
 TGLLightSetSubEditor::TGLLightSetSubEditor(const TGWindow *p) :
    TGVerticalFrame(p),
    fM             (0),
@@ -42,32 +43,41 @@ TGLLightSetSubEditor::TGLLightSetSubEditor(const TGWindow *p) :
 {
    // Constructor.
 
-   fLightFrame = new TGGroupFrame(this, "Light sources:", kLHintsTop | kLHintsCenterX);
-
+   fLightFrame = new TGGroupFrame(this, "Light sources:", kVerticalFrame);//, kLHintsTop | kLHintsCenterX);
    fLightFrame->SetTitlePos(TGGroupFrame::kLeft);
-   AddFrame(fLightFrame, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));//-
+   AddFrame(fLightFrame, new TGLayoutHints(kLHintsTop| kLHintsExpandX, 1, 1, 1, 1));//-
+   TGCompositeFrame* hf =0;
+
+   hf = new TGHorizontalFrame(fLightFrame);
+   fTopLight      = MakeLampButton("Top",      TGLLightSet::kLightTop, hf);
+   fBottomLight   = MakeLampButton("Bottom",   TGLLightSet::kLightBottom, hf);
+   fLightFrame->AddFrame(hf, new TGLayoutHints(kLHintsTop|kLHintsExpandX, 0, 0, 2, 2));
+
+   hf = new TGHorizontalFrame(fLightFrame);
+   fLeftLight     = MakeLampButton("Left",     TGLLightSet::kLightLeft, hf);
+   fRightLight    = MakeLampButton("Right",    TGLLightSet::kLightRight, hf);
+   fLightFrame->AddFrame(hf, new TGLayoutHints(kLHintsTop|kLHintsExpandX , 0, 0, 0, 2));
 
-   TGMatrixLayout *ml = new TGMatrixLayout(fLightFrame, 0, 1, 10);
-   fLightFrame->SetLayoutManager(ml);
+   hf = new TGHorizontalFrame(fLightFrame);
+   fFrontLight    = MakeLampButton("Front",    TGLLightSet::kLightFront, hf);
+   fSpecularLight = MakeLampButton("Specular", TGLLightSet::kLightSpecular, hf);
 
-   fTopLight      = MakeLampButton("Top",      TGLLightSet::kLightTop);
-   fRightLight    = MakeLampButton("Right",    TGLLightSet::kLightRight);
-   fBottomLight   = MakeLampButton("Bottom",   TGLLightSet::kLightBottom);
-   fLeftLight     = MakeLampButton("Left",     TGLLightSet::kLightLeft);
-   fFrontLight    = MakeLampButton("Front",    TGLLightSet::kLightFront);
-   fSpecularLight = MakeLampButton("Specular", TGLLightSet::kLightSpecular);
+   fLightFrame->AddFrame(hf, new TGLayoutHints(kLHintsTop|kLHintsExpandX, 0, 0, 0, 2));
 }
 
-TGButton* TGLLightSetSubEditor::MakeLampButton(const Text_t* name, Int_t wid)
+//______________________________________________________________________________
+TGButton* TGLLightSetSubEditor::MakeLampButton(const Text_t* name, Int_t wid,
+                                               TGCompositeFrame* parent)
 {
    // Create a button for given lamp and set it up.
 
-   TGButton* b = new TGCheckButton(fLightFrame, name,  wid);
-   fLightFrame->AddFrame(b);
+   TGButton* b = new TGCheckButton(parent, name, wid);
+   parent->AddFrame(b, new TGLayoutHints(kLHintsNormal|kLHintsExpandX, -2, 0, 0, 2));
    b->Connect("Clicked()", "TGLLightSetSubEditor", this, "DoButton()");
    return b;
 }
 
+//______________________________________________________________________________
 void TGLLightSetSubEditor::SetModel(TGLLightSet* m)
 {
    // New model was set, refresh data.
@@ -84,6 +94,7 @@ void TGLLightSetSubEditor::SetModel(TGLLightSet* m)
    fSpecularLight->SetState(fM->GetUseSpecular() ? kButtonDown : kButtonUp);
 }
 
+//______________________________________________________________________________
 void TGLLightSetSubEditor::Changed()
 {
    // Data in sub-editor has been changed, emit "Changed()" signal.
@@ -102,14 +113,16 @@ void TGLLightSetSubEditor::DoButton()
 }
 
 
-//______________________________________________________________________
+//______________________________________________________________________________
 // TGLLightSetEditor
 //
 // Editor for TGLLightSet.
 
 ClassImp(TGLLightSetEditor)
 
-TGLLightSetEditor::TGLLightSetEditor(const TGWindow *p, Int_t width, Int_t height,
+//______________________________________________________________________________
+TGLLightSetEditor::TGLLightSetEditor(const TGWindow *p,
+                                     Int_t width, Int_t height,
                                      UInt_t options, Pixel_t back) :
    TGedFrame(p, width, height, options | kVerticalFrame, back),
    fM  (0),
@@ -124,13 +137,13 @@ TGLLightSetEditor::TGLLightSetEditor(const TGWindow *p, Int_t width, Int_t heigh
    fSE->Connect("Changed()", "TGLLightSetEditor", this, "Update()");
 }
 
+//______________________________________________________________________________
 TGLLightSetEditor::~TGLLightSetEditor()
 {
    // Destructor.
 }
 
-/**************************************************************************/
-
+//______________________________________________________________________________
 void TGLLightSetEditor::SetModel(TObject* obj)
 {
    // SetModel ... forward to sub-editor.
diff --git a/gl/src/TGLOrthoCamera.cxx b/gl/src/TGLOrthoCamera.cxx
index 4eee3733233..dde467777e7 100644
--- a/gl/src/TGLOrthoCamera.cxx
+++ b/gl/src/TGLOrthoCamera.cxx
@@ -37,39 +37,33 @@ ClassImp(TGLOrthoCamera)
 UInt_t   TGLOrthoCamera::fgZoomDeltaSens = 500;
 
 //______________________________________________________________________________
-TGLOrthoCamera::TGLOrthoCamera(EType type) :
-   fType(type), fZoomMin(0.01), fZoomDefault(0.78), fZoomMax(1000.0),
+TGLOrthoCamera::TGLOrthoCamera(const TGLVector3 & hAxes, const TGLVector3 & vAxes) :
+   TGLCamera(hAxes, vAxes),
+   fType(kZOY),
+   fEnableRotate(kFALSE), fZoomMin(0.001), fZoomDefault(0.78), fZoomMax(1000.0),
    fVolume(TGLVertex3(-100.0, -100.0, -100.0), TGLVertex3(100.0, 100.0, 100.0)),
-   fZoom(1.0), fTruck(0.0, 0.0, 0.0), fMatrix()
+   fZoom(1.0)
 {
-   // Construct orthographic camera with 'type' defining fixed view direction
-   // & orientation (in world frame):
-   //
-   // kXOY : X Horz. / Y Vert (looking towards +Z, Y up)
-   // kXOZ : X Horz. / Z Vert (looking towards +Y, Z up)
-   // kZOY : Z Horz. / Y Vert (looking towards +X, Y up)
-   //
+   // Construct orthographic camera.
+
    Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
-}
 
-//______________________________________________________________________________
-TGLOrthoCamera::TGLOrthoCamera() :
-   fType(kXOY), fZoomMin(0.01), fZoomDefault(0.78), fZoomMax(1000.0),
-   fVolume(TGLVertex3(-100.0, -100.0, -100.0), TGLVertex3(100.0, 100.0, 100.0)),
-   fZoom(1.0), fTruck(0.0, 0.0, 0.0), fShift(0.), fCenter(),
-   fVpChanged(kFALSE)
-{
-   // Construct orthographic camera.
-   fOrthoBox[0] = 1.;
-   fOrthoBox[1] = 1.;
-   fOrthoBox[2] = -1.;
-   fOrthoBox[3] = 1.;
+   // define camera type relative to horizontal vector
+   TGLVector3 v = fCamBase.GetBaseVec(1);
+   for(Int_t i=0; i<3; i++)
+   {
+      if(TMath::Abs(v[i]) == 1)
+      {
+        fType = (TGLOrthoCamera::EType)i;
+        break;
+      }
+   }
 }
 
 //______________________________________________________________________________
 TGLOrthoCamera::~TGLOrthoCamera()
 {
-   // Destroy orthographic camera
+   // Destroy orthographic camera.
 }
 
 //______________________________________________________________________________
@@ -77,51 +71,13 @@ void TGLOrthoCamera::Setup(const TGLBoundingBox & box, Bool_t reset)
 {
    // Setup camera limits suitible to view the world volume defined by 'box'
    // and call Reset() to initialise camera.
-   static const Double_t rotMatrixXOY[] = { 1.,  0.,  0.,  0.,
-                                            0.,  1.,  0.,  0.,
-                                            0.,  0.,  1.,  0.,
-                                            0.,  0.,  0.,  1. };
-
-   static const Double_t rotMatrixXOZ[] = { 1.,  0.,  0.,  0.,
-                                            0.,  0., -1.,  0.,
-                                            0.,  1.,  0.,  0.,
-                                            0.,  0.,  0.,  1. };
 
-   static const Double_t rotMatrixZOY[] = { 0.,  0., -1.,  0.,
-                                            0.,  1.,  0.,  0.,
-                                            1.,  0.,  0.,  0.,
-                                            0.,  0.,  0.,  1. };
+   fVolume = box;
 
-   switch (fType) {
-		// Looking down Z axis, X horz, Y vert
-      case (kXOY): {
-         // X -> X
-         // Y -> Y
-         // Z -> Z
-         fVolume = box;
-         fMatrix.Set(rotMatrixXOY);
-         break;
-      }
-		// Looking down Y axis, X horz, Z vert
-      case (kXOZ): {
-         // X -> X
-         // Z -> Y
-         // Y -> Z
-         fVolume.SetAligned(TGLVertex3(box.XMin(), box.ZMin(), box.YMin()),
-                            TGLVertex3(box.XMax(), box.ZMax(), box.YMax()));
-         fMatrix.Set(rotMatrixXOZ);
-         break;
-      }
-		// Looking down X axis, Z horz, Y vert
-      case (kZOY): {
-         // Z -> X
-         // Y -> Y
-         // X -> Z
-         fVolume.SetAligned(TGLVertex3(box.ZMin(), box.YMin(), box.XMin()),
-                            TGLVertex3(box.ZMax(), box.YMax(), box.XMax()));
-         fMatrix.Set(rotMatrixZOY);
-         break;
-      }
+   if (fExternalCenter == kFALSE)
+   {
+      TGLVertex3 center = box.Center();
+      SetCenterVec(center.X(), center.Y(), center.Z());
    }
    if (reset)
       Reset();
@@ -132,29 +88,33 @@ void TGLOrthoCamera::Reset()
 {
    // Reset the camera to defaults - trucking, zooming to reframe the world volume
    // established in Setup(). Note: limits defined in Setup() are not adjusted.
-   fTruck.Set(0.0, 0.0, 0.0);
-   fZoom   = fZoomDefault;
-   IncTimeStamp();
-}
 
-//______________________________________________________________________________
-Bool_t TGLOrthoCamera::Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
-{
-   // Dolly the camera - 'move camera along eye line, retaining lens focal length'.
-   // Arguments are:
-   //
-   // 'delta' - mouse viewport delta (pixels) - +ive dolly in, -ive dolly out
-   // 'mod1' / 'mod2' - sensitivity modifiers - see TGLCamera::AdjustAndClampVal()
-   //
-   // For an orthographic camera dollying and zooming are identical and both equate
-   // logically to a rescaling of the viewport limits - without center shift.
-   // There is no perspective foreshortening or lens 'focal length'.
-   //
-   // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
+   TGLVector3 e = fVolume.Extents();
+   switch (fType) {
+      case kX0Y: {
+         // X -> X, Y -> Y, Z -> Z
+         fDefXSize = e.X(); fDefYSize = e.Y();
+         break;
+      }
+      case kXOZ: {
+         // X -> X, Z -> Y, Y -> Z
+         fDefXSize = e.X(); fDefYSize = e.Z();
+         break;
+      }
+
+      case kZOY: {
+         // Z -> X, Y -> Y, X -> Z
+         fDefXSize = e.Z(); fDefYSize = e.Y();
+         break;
+      }
+   }
 
-   // TODO: Bring all mouse handling into camera classes - would simplify interface and
-   // remove these non-generic cases.
-   return Zoom(delta, mod1, mod2);
+   fDollyDefault  = 1.25*0.5*TMath::Sqrt(3)*fVolume.Extents().Mag();
+   fDollyDistance = 0.002 * fDollyDefault;
+   fZoom   = fZoomDefault;
+   fCamTrans.SetIdentity();
+   fCamTrans.MoveLF(1, fDollyDefault);
+   IncTimeStamp();
 }
 
 //______________________________________________________________________________
@@ -172,8 +132,6 @@ Bool_t TGLOrthoCamera::Zoom (Int_t delta, Bool_t mod1, Bool_t mod2)
    //
    // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
 
-   // TODO: Bring all mouse handling into camera classes - would simplify interface and
-   // remove these non-generic cases.
    if (AdjustAndClampVal(fZoom, fZoomMin, fZoomMax, -delta*2, fgZoomDeltaSens, mod1, mod2))
    {
       IncTimeStamp();
@@ -186,39 +144,15 @@ Bool_t TGLOrthoCamera::Zoom (Int_t delta, Bool_t mod1, Bool_t mod2)
 }
 
 //______________________________________________________________________________
-Bool_t TGLOrthoCamera::Truck(Int_t x, Int_t y, Int_t xDelta, Int_t yDelta)
-{
-   // Truck the camera - 'move camera parallel to film plane'. The film
-   // plane is defined by the EyePoint() / EyeDirection() pair. Define motion
-   // using center point (x/y) and delta (xDelta/yDelta) - the mouse motion.
-   //
-   // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
-   //
-   // Note: Trucking is often mistakenly refered to as 'pan' or 'panning'.
-   // Panning is swivelling the camera on it's own axis - the eye point.
-
-   //TODO: Convert TGLRect so this not required
-   GLint viewport[4] = { fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height() };
-   TGLVertex3 start, end;
-   // Trucking done at near clipping plane
-   gluUnProject(x, y, 0.0, fModVM.CArr(), fProjM.CArr(), viewport, &start.X(), &start.Y(), &start.Z());
-   gluUnProject(x + xDelta, y + yDelta, 0.0, fModVM.CArr(), fProjM.CArr(), viewport, &end.X(), &end.Y(), &end.Z());
-   fTruck = fTruck + (end - start);
-   IncTimeStamp();
-   return kTRUE;
-}
-
-//______________________________________________________________________________
-Bool_t TGLOrthoCamera::Rotate(Int_t /*xDelta*/, Int_t /*yDelta*/)
+Bool_t TGLOrthoCamera::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
 {
    // Rotate the camera - 'swivel round the view volume center'.
-   // Ignored at present for orthographic cameras - have a fixed direction.
-   // Could let the user or external code create non-axis
-   // ortho projects by adjusting H/V rotations in future.
-   //
    // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
 
-   return kFALSE;
+   if (fEnableRotate)
+      return kFALSE;
+   else
+      return TGLCamera::Rotate(xDelta, yDelta, mod1, mod2);
 }
 
 //______________________________________________________________________________
@@ -235,8 +169,18 @@ void TGLOrthoCamera::Apply(const TGLBoundingBox & /*box*/,
    // as one passed to Setup().
    // 'pickRect' - optional picking rect. If non-null, restrict drawing to this
    // viewport rect.
+
    glViewport(fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height());
 
+   if(fViewport.Width() == 0 || fViewport.Height() == 0)
+   {
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
+      glMatrixMode(GL_MODELVIEW);
+      glLoadIdentity();
+      return;
+   }
+
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
 
@@ -249,82 +193,161 @@ void TGLOrthoCamera::Apply(const TGLBoundingBox & /*box*/,
                     (Int_t*) fViewport.CArr());
    }
 
-   if(fViewport.Width() == 0 || fViewport.Height() == 0) {
-      glMatrixMode(GL_MODELVIEW);
-      glLoadIdentity();
-      return;
-   }
-
-   TGLVector3 extents = fVolume.Extents();
-   Double_t width = extents.X();
-   Double_t height = extents.Y();
-   Double_t halfRange;
-   if (width > height) {
-      halfRange = width / 2.0;
+   Double_t halfRangeX, halfRangeY;
+   if (fDefYSize*fViewport.Width()/fDefXSize > fViewport.Height()) {
+      halfRangeY = 0.5 *fDefYSize;
+      halfRangeX = halfRangeY*fViewport.Width()/fViewport.Height();
    } else {
-      halfRange = height / 2.0;
+      halfRangeX = 0.5 *fDefXSize;
+      halfRangeY = halfRangeX*fViewport.Height()/fViewport.Width();
    }
-   halfRange /= fZoom;
-
-   // For near/far clipping half depth give extra slack so clip objects/manips
-   // are visible
-   Double_t halfDepth = extents.Mag();
-   const TGLVertex3 & center = fVolume.Center();
 
-   glOrtho(center.X() - halfRange,
-           center.X() + halfRange,
-           center.Y() - halfRange,
-           center.Y() + halfRange,
-          -center.Z() + halfDepth,
-          -center.Z() - halfDepth);
+   halfRangeX /= fZoom;
+   halfRangeY /= fZoom;
 
+   fNearClip = 0.05*fDollyDefault;
+   fFarClip  = 2.0*fDollyDefault;
+   glOrtho(-halfRangeX, halfRangeX,
+           -halfRangeY, halfRangeY,
+            fNearClip,  fFarClip);
 
+   // ii) setup modelview
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
+   TGLMatrix  mx     = fCamBase*fCamTrans;
+   TGLVector3 pos    = mx.GetTranslation();
+   TGLVector3 fwd    = mx.GetBaseVec(1);
+   TGLVector3 center = pos - fwd;
+   TGLVector3 up     = fCamBase.GetBaseVec(3);
 
-   glScaled(1.0 / fViewport.Aspect(), 1.0, 1.0);
+   gluLookAt(pos[0],    pos[1],    pos[2],
+             center[0], center[1], center[2],
+             up[0],     up[1],     up[2]);
 
-   // Debug aid - show current volume
-   /*glDisable(GL_LIGHTING);
-   glColor3d(0.0, 0.0, 1.0);
-   fVolume.Draw();
-   glEnable(GL_LIGHTING);*/
+   if (fCacheDirty) UpdateCache();
+}
 
-   glMultMatrixd(fMatrix.CArr());
-   glTranslated(fTruck.X(), fTruck.Y(), fTruck.Z());
 
-   if (fCacheDirty) {
-      UpdateCache();
-   }
+//______________________________________________________________________________
+void TGLOrthoCamera::Configure(Double_t zoom, Double_t dolly, Double_t center[3],
+                                     Double_t hRotate, Double_t vRotate)
+{
+   // Configure the camera state.
+
+   fZoom = zoom;
+   SetCenterVec(center[0], center[1], center[2]);
+   fCamTrans.MoveLF(1, dolly);
+   RotateRad(hRotate, vRotate);
+
+   IncTimeStamp();
 }
 
 //______________________________________________________________________________
-void TGLOrthoCamera::Configure(Double_t left, Double_t right,
-                               Double_t top, Double_t bottom)
+void TGLOrthoCamera::Markup(TGLCameraMarkupStyle* ms) const
 {
-   // Configure the camera state
-   Double_t width = right - left;
-   Double_t height = top - bottom;
-
-   Double_t xZoom = width/fVolume.Extents().X();
-   Double_t yZoom = height/fVolume.Extents().Y();
-
-   fZoom = (xZoom > yZoom) ? xZoom : yZoom;
-
-   // kXOY : X Horz. / Y Vert (looking towards +Z, Y up)
-   // kXOZ : X Horz. / Z Vert (looking towards +Y, Z up)
-   // kZOY : Z Horz. / Y Vert (looking towards +X, Y up)
-   if (fType == kXOY) {
-      fTruck.X() = right - left;
-      fTruck.Y() = top - bottom;
-   } else if (fType == kXOZ) {
-      fTruck.X() = right - left;
-      fTruck.Z() = top - bottom;
-   } else if (fType == kZOY) {
-      fTruck.Z() = right - left;
-      fTruck.Y() = top - bottom;
+   // Write viewport dimensions on screen.
+
+   Double_t width     = fFrustumPlanes[kLeft].D() + fFrustumPlanes[kRight].D();
+   Double_t maxbarw0  = ms->Barsize()*width;
+
+   // get 10-exponent
+   Int_t exp = (Int_t) TMath::Floor(TMath::Log10(maxbarw0));
+
+   Double_t fact = maxbarw0/TMath::Power(10, exp);
+   Float_t barw;
+
+   if (fact > 5) {
+      barw = 5*TMath::Power(10, exp);
+      glColor3d(1., 0., 1.0);
    }
-   IncTimeStamp();
+   else if (fact > 2) {
+      barw = 2*TMath::Power(10, exp);
+      glColor3d(0., 1., 1.0);
+   } else {
+      barw = TMath::Power(10, exp);
+      glColor3d(0., 0., 1.0);
+   }
+   Double_t wproc = barw / width;
+   Int_t screenw = fViewport.Width();
+   Int_t screenh = fViewport.Height();
+
+   Double_t sX, sY;
+   Double_t offX, offY, txtOffX, txtOffY;
+   ms->Offsets(offX, offY, txtOffX, txtOffY);
+
+   switch (ms->Position())
+   {
+      case TGLCameraMarkupStyle::kLUp:
+         sX = offX;
+         sY = screenh - offY -  txtOffY - 8;
+         break;
+      case TGLCameraMarkupStyle::kLDn:
+         sX = offX;
+         sY = offY;
+         break;
+      case TGLCameraMarkupStyle::kRUp:
+         sX = screenw - ms->Barsize()*screenw - offX;
+         sY = screenh - offY  -  txtOffY - 8;
+         break;
+      case TGLCameraMarkupStyle::kRDn:
+         sX = screenw - ms->Barsize()*screenw -  offX;
+         sY = offY;
+         break;
+      default:
+         sX = 0.5*screenw;
+         sY = 0.5*screenh;
+         break;
+   }
+
+   glTranslatef(sX, sY, 0);
+
+   glLineWidth(2.);
+   glColor3d(1., 1., 1.);
+
+   Double_t mH = 2;
+
+   glBegin(GL_LINES);
+   // horizontal static
+   glVertex3d(0, 0.,0.);
+   glVertex3d(ms->Barsize()*screenw, 0., 0.);
+   // corner bars
+   glVertex3d(ms->Barsize()*screenw,  mH, 0.);
+   glVertex3d(ms->Barsize()*screenw, -mH, 0.);
+   // marker cormer bar
+   glColor3d(1., 0., 0.);
+   glVertex3d(0.,  mH, 0.);
+   glVertex3d(0., -mH, 0.);
+   // marker pointer
+   glVertex3d(screenw*wproc, 0., 0.);
+   glVertex3d(screenw*wproc, mH, 0.);
+   //marker line
+   glVertex3d(0, 0.,0.);
+   glVertex3d(screenw*wproc, 0., 0.);
+   glEnd();
+
+   glTranslated(-sX, -sY, 0);
+
+   TString str = Form("%.*f", (exp < 0) ? -exp : 0, barw);
+   TGLUtil::DrawNumber(str, TGLVertex3(sX + txtOffX, sY + txtOffY, -1));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+//   TGLPlotPainter
+//
+/////////////////////////////////////////////////////////////////////////////
+//______________________________________________________________________________
+TGLOrthoCamera::TGLOrthoCamera() :
+   fZoomMin(0.01), fZoomDefault(0.78), fZoomMax(1000.0),
+   fVolume(TGLVertex3(-100.0, -100.0, -100.0), TGLVertex3(100.0, 100.0, 100.0)),
+   fZoom(1.0), fShift(0.), fCenter(),
+   fVpChanged(kFALSE)
+{
+   // Construct orthographic camera.
+   fOrthoBox[0] = 1.;
+   fOrthoBox[1] = 1.;
+   fOrthoBox[2] = -1.;
+   fOrthoBox[3] = 1.;
 }
 
 //______________________________________________________________________________
@@ -480,92 +503,3 @@ void TGLOrthoCamera::ZoomOut()
    fZoom *= 1.2;
 }
 
-//______________________________________________________________________________
-void TGLOrthoCamera::Markup(TGLCameraMarkupStyle* ms) const
-{
-   // Write viewport dimensions on screen.
-
-   TGLVector3 extents = fVolume.Extents();
-   Double_t width     = extents.X()/fZoom;
-   Double_t maxbarw0  = ms->Barsize()*width;
-
-   // get 10-exponent
-   Int_t exp = (Int_t) TMath::Floor(TMath::Log10(maxbarw0));
-
-   Double_t fact = maxbarw0/TMath::Power(10, exp);
-   Float_t barw;
-
-   if (fact > 5) {
-      barw = 5*TMath::Power(10, exp);
-      glColor3d(1., 0., 1.0);
-   }
-   else if (fact > 2) {
-      barw = 2*TMath::Power(10, exp);
-      glColor3d(0., 1., 1.0);
-   } else {
-      barw = TMath::Power(10, exp);
-      glColor3d(0., 0., 1.0);
-   }
-   Double_t wproc = barw / width;
-   Int_t screenw = fViewport.Width();
-   Int_t screenh = fViewport.Height();
-
-   Double_t sX, sY;
-   Double_t offX, offY, txtOffX, txtOffY;
-   ms->Offsets(offX, offY, txtOffX, txtOffY);
-
-   switch (ms->Position())
-   {
-      case TGLCameraMarkupStyle::kLUp:
-         sX = offX;
-         sY = screenh - offY -  txtOffY - 8;
-         break;
-      case TGLCameraMarkupStyle::kLDn:
-         sX = offX;
-         sY = offY;
-         break;
-      case TGLCameraMarkupStyle::kRUp:
-         sX = screenw - ms->Barsize()*screenw - offX;
-         sY = screenh - offY  -  txtOffY - 8;
-         break;
-      case TGLCameraMarkupStyle::kRDn:
-         sX = screenw - ms->Barsize()*screenw -  offX;
-         sY = offY;
-         break;
-      default:
-         sX = 0.5*screenw;
-         sY = 0.5*screenh;
-         break;
-   }
-
-   glTranslatef(sX, sY, 0);
-
-   glLineWidth(2.);
-   glColor3d(1., 1., 1.);
-
-   Double_t mH = 2;
-
-   glBegin(GL_LINES);
-   // horizontal static
-   glVertex3d(0, 0.,0.);
-   glVertex3d(ms->Barsize()*screenw, 0., 0.);
-   // corner bars
-   glVertex3d(ms->Barsize()*screenw,  mH, 0.);
-   glVertex3d(ms->Barsize()*screenw, -mH, 0.);
-   // marker cormer bar
-   glColor3d(1., 0., 0.);
-   glVertex3d(0.,  mH, 0.);
-   glVertex3d(0., -mH, 0.);
-   // marker pointer
-   glVertex3d(screenw*wproc, 0., 0.);
-   glVertex3d(screenw*wproc, mH, 0.);
-   //marker line
-   glVertex3d(0, 0.,0.);
-   glVertex3d(screenw*wproc, 0., 0.);
-   glEnd();
-
-   glTranslated(-sX, -sY, 0);
-
-   TString str = Form("%.*f", (exp < 0) ? -exp : 0, barw);
-   TGLUtil::DrawNumber(str, TGLVertex3(sX + txtOffX, sY + txtOffY, -1));
-}
diff --git a/gl/src/TGLPerspectiveCamera.cxx b/gl/src/TGLPerspectiveCamera.cxx
index 5c8d9d2b58d..b525f79c6af 100644
--- a/gl/src/TGLPerspectiveCamera.cxx
+++ b/gl/src/TGLPerspectiveCamera.cxx
@@ -16,9 +16,6 @@
 #include "TMath.h"
 #include "TError.h"
 
-// TODO: Find somewhere else
-#define PI 3.141592654
-
 //////////////////////////////////////////////////////////////////////////
 //                                                                      //
 // TGLPerspectiveCamera                                                 //
@@ -37,20 +34,16 @@ ClassImp(TGLPerspectiveCamera)
 Double_t TGLPerspectiveCamera::fgFOVMin = 0.01;
 Double_t TGLPerspectiveCamera::fgFOVDefault = 30;
 Double_t TGLPerspectiveCamera::fgFOVMax = 120.0;
-
-UInt_t   TGLPerspectiveCamera::fgDollyDeltaSens = 500;
 UInt_t   TGLPerspectiveCamera::fgFOVDeltaSens = 500;
 
 //______________________________________________________________________________
-TGLPerspectiveCamera::TGLPerspectiveCamera(const TGLVector3 & hAxis, const TGLVector3 & vAxis) :
-   fHAxis(hAxis), fVAxis(vAxis),
-   fDollyMin(1.0), fDollyDefault(10.0), fDollyMax(100.0),
-   fFOV(fgFOVDefault), fDolly(fDollyDefault),
-   fVRotate(-90.0), fHRotate(90.0),
-   fCenter(0.0, 0.0, 0.0), fTruck(0.0, 0.0, 0.0)
+TGLPerspectiveCamera::TGLPerspectiveCamera(const TGLVector3 & hAxes, const TGLVector3 & vAxes) :
+   TGLCamera(hAxes, vAxes),
+   fFOV(fgFOVDefault)
 {
    // Construct perspective camera
    Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
+   fCamTrans.MoveLF(1, fDollyDefault);
 }
 
 //______________________________________________________________________________
@@ -65,23 +58,23 @@ void TGLPerspectiveCamera::Setup(const TGLBoundingBox & box, Bool_t reset)
    // Setup camera limits suitible to view the world volume defined by 'box'
    // and call Reset() to initialise camera.
 
-   fCenter = box.Center();
+   if (fExternalCenter == kFALSE)
+   {
+      TGLVertex3 center = box.Center();
+      SetCenterVec(center.X(), center.Y(), center.Z());
+   }
 
    // At default FOV, the maximum dolly should just encapsulate the longest side of box with
    // offset for next longetst side
-
-   // Find two longest sides
    TGLVector3 extents = box.Extents();
    Int_t sortInd[3];
    TMath::Sort(3, extents.CArr(), sortInd);
    Double_t longest = extents[sortInd[0]];
    Double_t nextLongest = extents[sortInd[1]];
 
-   fDollyDefault = longest/(2.0*tan(fFOV*PI/360.0));
+   fDollyDefault  = longest/(2.0*tan(fgFOVDefault*TMath::Pi()/360));
    fDollyDefault += nextLongest/2.0;
-   fDollyMin = -fDollyDefault;
-   fDollyDefault *= 1.2;
-   fDollyMax = fDollyDefault * 7.0;
+   fDollyDistance = 0.002 * fDollyDefault;
 
    if (reset)
       Reset();
@@ -92,30 +85,13 @@ void TGLPerspectiveCamera::Reset()
 {
    // Reset the camera to defaults - reframe the world volume established in Setup()
    // in default state. Note: limits defined in Setup() are not adjusted.
+
    fFOV = fgFOVDefault;
-   fHRotate = 90.0;
-   fVRotate = 0.0;
-   fTruck.Set(-fCenter.X(), -fCenter.Y(), -fCenter.Z());
-   fDolly = fDollyDefault;
-   IncTimeStamp();
-}
 
-//______________________________________________________________________________
-Bool_t TGLPerspectiveCamera::Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
-{
-  // Dolly the camera - 'move camera along eye line, retaining lens focal length'.
-   // Arguments are:
-   //
-   // 'delta' - mouse viewport delta (pixels) - +ive dolly in, -ive dolly out
-   // 'mod1' / 'mod2' - sensitivity modifiers - see TGLCamera::AdjustAndClampVal()
-   //
-   // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
-   if (AdjustAndClampVal(fDolly, fDollyMin, fDollyMax, delta, fgDollyDeltaSens, mod1, mod2)) {
-      IncTimeStamp();
-      return kTRUE;
-   } else {
-      return kFALSE;
-   }
+   fCamTrans.SetIdentity();
+   fCamTrans.MoveLF(1, fDollyDefault);
+
+   IncTimeStamp();
 }
 
 //______________________________________________________________________________
@@ -139,60 +115,6 @@ Bool_t TGLPerspectiveCamera::Zoom(Int_t delta, Bool_t mod1, Bool_t mod2)
    }
 }
 
-//______________________________________________________________________________
-Bool_t TGLPerspectiveCamera::Truck(Int_t x, Int_t y, Int_t xDelta, Int_t yDelta)
-{
-   // Truck the camera - 'move camera parallel to film plane'. The film
-   // plane is defined by the EyePoint() / EyeDirection() pair. Define motion
-   // using center point (x/y) and delta (xDelta/yDelta) - the mouse motion.
-   // For an orthographic projection this means all objects (regardless of
-   // camera distance) track the mouse motion.
-   //
-   // Returns kTRUE is redraw required (camera change), kFALSE otherwise.
-   //
-   // Note: Trucking is often mistakenly refered to as 'pan' or 'panning'.
-   // Panning is swivelling the camera on it's own axis - the eye point.
-
-   TGLVertex3 start, end;
-
-   gluUnProject(x, y, 1.0, fModVM.CArr(), fProjM.CArr(),
-                fViewport.CArr(), &start.X(), &start.Y(), &start.Z());
-   gluUnProject(x + xDelta, y + yDelta, 1.0, fModVM.CArr(), fProjM.CArr(),
-                fViewport.CArr(), &end.X(), &end.Y(), &end.Z());
-   TGLVector3 truckDelta = end - start;
-   fTruck = fTruck + truckDelta/2.0;
-   IncTimeStamp();
-   return kTRUE;
-}
-
-//______________________________________________________________________________
-Bool_t TGLPerspectiveCamera::Rotate(Int_t xDelta, Int_t yDelta)
-{
-   // Rotate the camera round view volume center established in Setup().
-   // Arguments are:
-   //
-   // xDelta - horizontal delta (pixels)
-   // YDelta - vertical delta (pixels)
-   //
-   // Deltas are divided by equivalent viewport dimension and scaled
-   // by full rotation - i.e. translates fraction of viewport to
-   // fractional rotation.
-   //
-   // TODO: Rotation center should be changeable from outside.
-
-   fHRotate += static_cast<float>(xDelta)/fViewport.Width() * 360.0;
-   fVRotate -= static_cast<float>(yDelta)/fViewport.Height() * 180.0;
-   if ( fVRotate > 90.0 ) {
-      fVRotate = 90.0;
-   }
-   if ( fVRotate < -90.0 ) {
-      fVRotate = -90.0;
-   }
-
-   IncTimeStamp();
-   return kTRUE;
-}
-
 //______________________________________________________________________________
 void TGLPerspectiveCamera::Apply(const TGLBoundingBox & sceneBox,
                                  const TGLRect        * pickRect) const
@@ -214,38 +136,42 @@ void TGLPerspectiveCamera::Apply(const TGLBoundingBox & sceneBox,
    // plane intersection.
    // Besides, this would give as a proper control over camera transforamtion
    // matrix.
+   //
+   // Much better since Oct 2007, the clipping planes stuff still
+   // needs to be cleaned.
 
    glViewport(fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height());
 
-   glMatrixMode(GL_PROJECTION);
-   glLoadIdentity();
-
-   if(fViewport.Width() == 0 || fViewport.Height() == 0) {
+   if(fViewport.Width() == 0 || fViewport.Height() == 0)
+   {
+      glMatrixMode(GL_PROJECTION);
+      glLoadIdentity();
       glMatrixMode(GL_MODELVIEW);
       glLoadIdentity();
       return;
    }
 
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+
    // To find decent near/far clip plane distances we construct the
    // frustum thus:
    // i) first setup perspective with arbitary near/far planes
    gluPerspective(fFOV, fViewport.Aspect(), 1.0, 1000.0);
+   //   printf("FIRST STEP FOV %f, aspect %f, nearClip %f, farClip %f \n", fFOV, fViewport.Aspect(), 1., 1000.);
 
    // ii) setup modelview
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
+   TGLMatrix  mx     = fCamBase*fCamTrans;
+   TGLVector3 pos    = mx.GetTranslation();
+   TGLVector3 fwd    = mx.GetBaseVec(1);
+   TGLVector3 center = pos - fwd;
+   TGLVector3 up     = fCamBase.GetBaseVec(3);
 
-   glTranslated(0, 0, -fDolly);
-
-   glRotated(fVRotate, 1.0, 0.0, 0.0);
-   glRotated(fHRotate, 0.0, 1.0, 0.0);
-
-   // Rotate so vertical axis is just that....
-   TGLVector3 zAxis = Cross(fHAxis, fVAxis);
-   TGLMatrix vertMatrix(TGLVertex3(0.0, 0.0, 0.0), zAxis, &fHAxis);
-   glMultMatrixd(vertMatrix.CArr());
-
-   glTranslated(fTruck[0], fTruck[1], fTruck[2]);
+   gluLookAt(pos[0],    pos[1],    pos[2],
+             center[0], center[1], center[2],
+             up[0],     up[1],     up[2]);
 
    // iii) update the cached frustum planes so we can get eye point/direction
    Bool_t modifiedCache = kFALSE;
@@ -261,33 +187,29 @@ void TGLPerspectiveCamera::Apply(const TGLBoundingBox & sceneBox,
    // v) find the near/far distance which just encapsulate the passed bounding box vertexes
    //    not ideal - should really find the nearest/further points on box surface
    //    which intersect frustum - however this much more complicated
-   Double_t currentDist, nearClipDist=0, farClipDist=0;
+   Double_t currentDist;
    for (UInt_t i=0; i<8; i++) {
       currentDist = clipPlane.DistanceTo(sceneBox[i]);
-      if (i==0) {
-         nearClipDist = currentDist;
-         farClipDist = nearClipDist;
-      }
-      if (currentDist < nearClipDist) {
-         nearClipDist = currentDist;
-      }
-      if (currentDist > farClipDist) {
-         farClipDist = currentDist;
+      if (i==0)
+      {
+         fNearClip = currentDist;
+         fFarClip  = fNearClip;
       }
+      if (currentDist < fNearClip)
+         fNearClip = currentDist;
+      if (currentDist > fFarClip)
+         fFarClip = currentDist;
    }
    // Add 1% each way to avoid any rounding conflicts with drawn objects
-   nearClipDist *= .49; //0.99; TODO Look at - avoid removing clipping + manip objs
-   farClipDist *= 2.01; // 1.01
-   if (farClipDist < 2.0) {
-      farClipDist = 2.0;
-   }
-   if (nearClipDist < farClipDist/1000.0) {
-      nearClipDist = farClipDist/1000.0;
-   }
+   fNearClip *= 0.49; // 0.99; TODO Look at - avoid removing clipping + manip objs
+   fFarClip  *= 2.01; // 1.01;
+   if (fFarClip < 2.0)
+      fFarClip = 2.0;
+   if (fNearClip < fFarClip/1000.0)
+      fNearClip = fFarClip/1000.0;
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
-
    // Load up any picking rect
    if (pickRect)
    {
@@ -298,19 +220,11 @@ void TGLPerspectiveCamera::Apply(const TGLBoundingBox & sceneBox,
    }
    // vi) reset the perspective using the correct near/far clips distances
    // and restore modelview mode
-   gluPerspective(fFOV, fViewport.Aspect(), nearClipDist, farClipDist);
-   glMatrixMode(GL_MODELVIEW);
+   gluPerspective(fFOV, fViewport.Aspect(), fNearClip, fFarClip);
 
-   if (fCacheDirty) {
-      UpdateCache();
+   glMatrixMode(GL_MODELVIEW);
 
-      // Tracing - only show if camera changed
-      if (gDebug>3) {
-         Info("TGLPerspectiveCamera::Apply", "FOV %f Dolly %f fVRot %f fHRot", fFOV, fDolly, fVRotate, fHRotate);
-         Info("TGLPerspectiveCamera::Apply", "fTruck (%f,%f,%f)", fTruck[0], fTruck[1], fTruck[2]);
-         Info("TGLPerspectiveCamera::Apply", "Near %f Far %f", nearClipDist, farClipDist);
-      }
-   }
+   if (fCacheDirty) UpdateCache();
 }
 
 //______________________________________________________________________________
@@ -318,26 +232,21 @@ void TGLPerspectiveCamera::Configure(Double_t fov, Double_t dolly, Double_t cent
                                      Double_t hRotate, Double_t vRotate)
 {
    // Configure the camera state
-
    fFOV = fov;
-   fDolly = dolly;
-   fCenter.Set(center[0], center[1], center[2]);
-   fHRotate = hRotate;
-   fVRotate = vRotate;
 
    // Don't generally constrain external configuration
    // However exceeding the vRotate limits or silly FOV values will
    // cause very weird behaviour or projections so fix these
-   if (fVRotate > 90.0) {
-      fVRotate = 90.0;
-   }
-   if (fVRotate < -90.0) {
-      fVRotate = -90.0;
-   }
+
    if (fFOV > 170.0) {
       fFOV = 170.0;
    } else if (fFOV < 0.1) {
       fFOV = 0.1;
    }
+
+   SetCenterVec(center[0], center[1], center[2]);
+   fCamTrans.MoveLF(1, dolly);
+   RotateRad(hRotate, vRotate);
+
    IncTimeStamp();
 }
diff --git a/gl/src/TGLScenePad.cxx b/gl/src/TGLScenePad.cxx
index 412e45b6e65..c1cef8efc9d 100644
--- a/gl/src/TGLScenePad.cxx
+++ b/gl/src/TGLScenePad.cxx
@@ -115,51 +115,7 @@ void TGLScenePad::SubPadPaint(TVirtualPad* pad)
    TObjOptLink *lnk   = (prims) ? (TObjOptLink*)prims->FirstLink() : 0;
    while (lnk)
    {
-      TObject *obj = lnk->GetObject();
-      if (obj->InheritsFrom(TAtt3D::Class()))
-      {
-         //printf("normal-painting %s / %s\n", obj->GetName(), obj->ClassName());
-         obj->Paint(lnk->GetOption());
-      }
-      else if (obj->InheritsFrom(TH2::Class()))
-      {
-         // printf("histo 2d\n");
-         TGLObject* log = new TH2GL();
-         log->SetModel(obj, lnk->GetOption());
-         log->SetBBox();
-         AdoptLogical(*log);
-         AddHistoPhysical(log);
-      }
-      else if (obj->InheritsFrom(TF2::Class()))
-      {
-         // printf("func 2d\n");
-         TGLObject* log = new TF2GL();
-         log->SetModel(obj, lnk->GetOption());
-         log->SetBBox();
-         AdoptLogical(*log);
-         AddHistoPhysical(log);
-      }
-      else if (obj->InheritsFrom(TGLParametricEquation::Class()))
-      {
-         // printf("parametric\n");
-         TGLObject* log = new TGLParametricEquationGL();
-         log->SetModel(obj, lnk->GetOption());
-         log->SetBBox();
-         AdoptLogical(*log);
-         AddHistoPhysical(log);
-      }
-
-      else if (obj->InheritsFrom(TVirtualPad::Class()))
-      {
-         SubPadPaint(dynamic_cast<TVirtualPad*>(obj));
-      }
-      else
-      {
-         // Handle 2D primitives here.
-         // printf("TGLScenePad::PadPaint skipping %p, %s, %s.\n",
-         //        obj, obj->GetName(), obj->ClassName());
-         obj->Paint(lnk->GetOption());
-      }
+      ObjectPaint(lnk->GetObject(), lnk->GetOption());
       lnk = (TObjOptLink*)lnk->Next();
    }
 
@@ -167,6 +123,58 @@ void TGLScenePad::SubPadPaint(TVirtualPad* pad)
    gPad = padsav;
 }
 
+//______________________________________________________________________________
+void TGLScenePad::ObjectPaint(TObject* obj, Option_t* opt)
+{
+   // Override of virtual TVirtualViewer3D::ObjectPaint().
+   // Special handling of 2D/3D histograms to activate Timur's
+   // histo-painters.
+
+   if (obj->InheritsFrom(TAtt3D::Class()))
+   {
+      //printf("normal-painting %s / %s\n", obj->GetName(), obj->ClassName());
+      obj->Paint(opt);
+   }
+   else if (obj->InheritsFrom(TH2::Class()))
+   {
+      // printf("histo 2d\n");
+      TGLObject* log = new TH2GL();
+      log->SetModel(obj, opt);
+      log->SetBBox();
+      AdoptLogical(*log);
+      AddHistoPhysical(log);
+   }
+   else if (obj->InheritsFrom(TF2::Class()))
+   {
+      // printf("func 2d\n");
+      TGLObject* log = new TF2GL();
+      log->SetModel(obj, opt);
+      log->SetBBox();
+      AdoptLogical(*log);
+      AddHistoPhysical(log);
+   }
+   else if (obj->InheritsFrom(TGLParametricEquation::Class()))
+   {
+      // printf("parametric\n");
+      TGLObject* log = new TGLParametricEquationGL();
+      log->SetModel(obj, opt);
+      log->SetBBox();
+      AdoptLogical(*log);
+      AddHistoPhysical(log);
+   }
+   else if (obj->InheritsFrom(TVirtualPad::Class()))
+   {
+      SubPadPaint(dynamic_cast<TVirtualPad*>(obj));
+   }
+   else
+   {
+      // Handle 2D primitives here.
+      // printf("TGLScenePad::PadPaint skipping %p, %s, %s.\n",
+      //        obj, obj->GetName(), obj->ClassName());
+      obj->Paint(opt);
+   }
+}
+
 //______________________________________________________________________________
 void TGLScenePad::PadPaintFromViewer(TGLViewer* viewer)
 {
diff --git a/gl/src/TGLUtil.cxx b/gl/src/TGLUtil.cxx
index 03db0904d6c..46aebc6d45a 100644
--- a/gl/src/TGLUtil.cxx
+++ b/gl/src/TGLUtil.cxx
@@ -63,6 +63,13 @@ TGLVertex3::TGLVertex3(Double_t x, Double_t y, Double_t z)
    Set(x,y,z);
 }
 
+//______________________________________________________________________________
+TGLVertex3::TGLVertex3(Double_t* v)
+{
+   // Construct a vertex with components (v[0], v[1], v[2])
+   Set(v[0], v[1], v[2]);
+}
+
 //______________________________________________________________________________
 TGLVertex3::TGLVertex3(const TGLVertex3 & other)
 {
@@ -201,6 +208,7 @@ TGLLine3::~TGLLine3()
 void TGLLine3::Set(const TGLVertex3 & start, const TGLVertex3 & end)
 {
    // Set 3D line running from 'start' to 'end'
+
    fVertex = start;
    fVector = end - start;
 }
@@ -486,7 +494,30 @@ TGLMatrix::TGLMatrix(const TGLVertex3 & translation)
 }
 
 //______________________________________________________________________________
-TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 * xAxis)
+TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis)
+{
+   // Construct matrix which when applied puts local origin at
+   // 'origin' and the local Z axis in direction 'z'. Both
+   // 'origin' and 'zAxisVec' are expressed in the parent frame
+   SetIdentity();
+
+   TGLVector3 zAxisInt(zAxis);
+   zAxisInt.Normalise();
+   TGLVector3 arbAxis;
+
+   if (TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Y()) && TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Z())) {
+      arbAxis.Set(1.0, 0.0, 0.0);
+   } else if (TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.X()) && TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.Z())) {
+      arbAxis.Set(0.0, 1.0, 0.0);
+   } else {
+      arbAxis.Set(0.0, 0.0, 1.0);
+   }
+
+   Set(origin, zAxis, Cross(zAxisInt, arbAxis));
+}
+
+//______________________________________________________________________________
+TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis)
 {
    // Construct matrix which when applied puts local origin at
    // 'origin' and the local Z axis in direction 'z'. Both
@@ -550,7 +581,7 @@ void TGLMatrix::MultLeft (const TGLMatrix & lhs)
 }
 
 //______________________________________________________________________________
-void TGLMatrix::Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 * xAxis)
+void TGLMatrix::Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis)
 {
    // Set matrix which when applied puts local origin at
    // 'origin' and the local Z axis in direction 'z'. Both
@@ -558,21 +589,7 @@ void TGLMatrix::Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const T
    TGLVector3 zAxisInt(zAxis);
    zAxisInt.Normalise();
 
-   TGLVector3 xAxisInt;
-   if (xAxis) {
-      xAxisInt = *xAxis;
-   } else {
-      TGLVector3 arbAxis;
-      if (TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Y()) && TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Z())) {
-         arbAxis.Set(1.0, 0.0, 0.0);
-      } else if (TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.X()) && TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.Z())) {
-         arbAxis.Set(0.0, 1.0, 0.0);
-      } else {
-         arbAxis.Set(0.0, 0.0, 1.0);
-      }
-      xAxisInt = Cross(zAxisInt, arbAxis);
-   }
-
+   TGLVector3 xAxisInt(xAxis);
    xAxisInt.Normalise();
    TGLVector3 yAxisInt = Cross(zAxisInt, xAxisInt);
 
@@ -639,7 +656,7 @@ void TGLMatrix::SetTranslation(const TGLVertex3 & translation)
 }
 
 //______________________________________________________________________________
-TGLVertex3 TGLMatrix::GetTranslation() const
+TGLVector3 TGLMatrix::GetTranslation() const
 {
    // Return the translation component of matrix
    //
@@ -648,7 +665,7 @@ TGLVertex3 TGLMatrix::GetTranslation() const
    // . . . Z()
    // . . . .
 
-   return TGLVertex3(fVals[12], fVals[13], fVals[14]);
+   return TGLVector3(fVals[12], fVals[13], fVals[14]);
 }
 
 //______________________________________________________________________________
@@ -667,6 +684,16 @@ void TGLMatrix::Translate(const TGLVector3 & vect)
    fVals[14] += vect[2];
 }
 
+//______________________________________________________________________________
+void TGLMatrix::MoveLF(Int_t ai, Double_t amount)
+{
+   // Translate in local frame.
+   // i1, i2 are axes indices: 1 ~ x, 2 ~ y, 3 ~ z.
+
+   const Double_t *C = fVals + 4*--ai;
+   fVals[12] += amount*C[0]; fVals[13] += amount*C[1]; fVals[14] += amount*C[2];
+}
+
 //______________________________________________________________________________
 void TGLMatrix::Scale(const TGLVector3 & scale)
 {
@@ -747,6 +774,25 @@ void TGLMatrix::RotateLF(Int_t i1, Int_t i2, Double_t amount)
    }
 }
 
+//______________________________________________________________________________
+void TGLMatrix::RotatePF(Int_t i1, Int_t i2, Double_t amount)
+{
+   // Rotate in parent frame. Does optimised version of MultLeft.
+
+   if(i1 == i2) return;
+
+   // Optimized version:
+   const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
+   Double_t  b1, b2;
+   Double_t* C = fVals;
+   --i1; --i2;
+   for(int c=0; c<4; ++c, C+=4) {
+      b1 = cos*C[i1] - sin*C[i2];
+      b2 = cos*C[i2] + sin*C[i1];
+      C[i1] = b1; C[i2] = b2;
+   }
+}
+
 //______________________________________________________________________________
 void TGLMatrix::TransformVertex(TGLVertex3 & vertex) const
 {
@@ -783,6 +829,107 @@ void TGLMatrix::Transpose3x3()
    fVals[6] = temp;
 }
 
+//______________________________________________________________________________
+Double_t TGLMatrix::Invert()
+{
+   // Invert the matrix, returns determinant.
+   // Copied from TMatrixFCramerInv.
+
+   Double_t* M = fVals;
+
+   const Double_t det2_12_01 = M[1]*M[6]  - M[5]*M[2];
+   const Double_t det2_12_02 = M[1]*M[10] - M[9]*M[2];
+   const Double_t det2_12_03 = M[1]*M[14] - M[13]*M[2];
+   const Double_t det2_12_13 = M[5]*M[14] - M[13]*M[6];
+   const Double_t det2_12_23 = M[9]*M[14] - M[13]*M[10];
+   const Double_t det2_12_12 = M[5]*M[10] - M[9]*M[6];
+   const Double_t det2_13_01 = M[1]*M[7]  - M[5]*M[3];
+   const Double_t det2_13_02 = M[1]*M[11] - M[9]*M[3];
+   const Double_t det2_13_03 = M[1]*M[15] - M[13]*M[3];
+   const Double_t det2_13_12 = M[5]*M[11] - M[9]*M[7];
+   const Double_t det2_13_13 = M[5]*M[15] - M[13]*M[7];
+   const Double_t det2_13_23 = M[9]*M[15] - M[13]*M[11];
+   const Double_t det2_23_01 = M[2]*M[7]  - M[6]*M[3];
+   const Double_t det2_23_02 = M[2]*M[11] - M[10]*M[3];
+   const Double_t det2_23_03 = M[2]*M[15] - M[14]*M[3];
+   const Double_t det2_23_12 = M[6]*M[11] - M[10]*M[7];
+   const Double_t det2_23_13 = M[6]*M[15] - M[14]*M[7];
+   const Double_t det2_23_23 = M[10]*M[15] - M[14]*M[11];
+
+
+   const Double_t det3_012_012 = M[0]*det2_12_12 - M[4]*det2_12_02 + M[8]*det2_12_01;
+   const Double_t det3_012_013 = M[0]*det2_12_13 - M[4]*det2_12_03 + M[12]*det2_12_01;
+   const Double_t det3_012_023 = M[0]*det2_12_23 - M[8]*det2_12_03 + M[12]*det2_12_02;
+   const Double_t det3_012_123 = M[4]*det2_12_23 - M[8]*det2_12_13 + M[12]*det2_12_12;
+   const Double_t det3_013_012 = M[0]*det2_13_12 - M[4]*det2_13_02 + M[8]*det2_13_01;
+   const Double_t det3_013_013 = M[0]*det2_13_13 - M[4]*det2_13_03 + M[12]*det2_13_01;
+   const Double_t det3_013_023 = M[0]*det2_13_23 - M[8]*det2_13_03 + M[12]*det2_13_02;
+   const Double_t det3_013_123 = M[4]*det2_13_23 - M[8]*det2_13_13 + M[12]*det2_13_12;
+   const Double_t det3_023_012 = M[0]*det2_23_12 - M[4]*det2_23_02 + M[8]*det2_23_01;
+   const Double_t det3_023_013 = M[0]*det2_23_13 - M[4]*det2_23_03 + M[12]*det2_23_01;
+   const Double_t det3_023_023 = M[0]*det2_23_23 - M[8]*det2_23_03 + M[12]*det2_23_02;
+   const Double_t det3_023_123 = M[4]*det2_23_23 - M[8]*det2_23_13 + M[12]*det2_23_12;
+   const Double_t det3_123_012 = M[1]*det2_23_12 - M[5]*det2_23_02 + M[9]*det2_23_01;
+   const Double_t det3_123_013 = M[1]*det2_23_13 - M[5]*det2_23_03 + M[13]*det2_23_01;
+   const Double_t det3_123_023 = M[1]*det2_23_23 - M[9]*det2_23_03 + M[13]*det2_23_02;
+   const Double_t det3_123_123 = M[5]*det2_23_23 - M[9]*det2_23_13 + M[13]*det2_23_12;
+
+   const Double_t det = M[0]*det3_123_123 - M[4]*det3_123_023 +
+      M[8]*det3_123_013 - M[12]*det3_123_012;
+
+   if(det == 0) {
+      Warning("TGLMatrix::Invert", "matrix is singular.");
+      return 0;
+   }
+
+   const Double_t oneOverDet = 1.0/det;
+   const Double_t mn1OverDet = - oneOverDet;
+
+   M[0]  = det3_123_123 * oneOverDet;
+   M[4]  = det3_023_123 * mn1OverDet;
+   M[8]  = det3_013_123 * oneOverDet;
+   M[12] = det3_012_123 * mn1OverDet;
+
+   M[1]  = det3_123_023 * mn1OverDet;
+   M[5]  = det3_023_023 * oneOverDet;
+   M[9]  = det3_013_023 * mn1OverDet;
+   M[13] = det3_012_023 * oneOverDet;
+
+   M[2]  = det3_123_013 * oneOverDet;
+   M[6]  = det3_023_013 * mn1OverDet;
+   M[10] = det3_013_013 * oneOverDet;
+   M[14] = det3_012_013 * mn1OverDet;
+
+   M[3]  = det3_123_012 * mn1OverDet;
+   M[7]  = det3_023_012 * oneOverDet;
+   M[11] = det3_013_012 * mn1OverDet;
+   M[15] = det3_012_012 * oneOverDet;
+
+   return det;
+}
+
+//______________________________________________________________________________
+void TGLMatrix::MultiplyIP(TGLVector3& v, Double_t w) const
+{
+   // Multiply vector in-place.
+   const Double_t* M = fVals;
+   Double_t r[3] = { v[0], v[1], v[2] };
+   v.X() = M[0]*r[0] + M[4]*r[1] +  M[8]*r[2] + M[12]*w;
+   v.Y() = M[1]*r[0] + M[5]*r[1] +  M[9]*r[2] + M[13]*w;
+   v.Z() = M[2]*r[0] + M[6]*r[1] + M[10]*r[2] + M[14]*w;
+}
+
+//______________________________________________________________________________
+void TGLMatrix::RotateIP(TGLVector3& v) const
+{
+   // Rotate vector in-place. Translation is not applied.
+   const Double_t* M = fVals;
+   Double_t r[3] = { v[0], v[1], v[2] };
+   v.X() = M[0]*r[0] + M[4]*r[1] +  M[8]*r[2];
+   v.Y() = M[1]*r[0] + M[5]*r[1] +  M[9]*r[2];
+   v.Z() = M[2]*r[0] + M[6]*r[1] + M[10]*r[2];
+}
+
 //______________________________________________________________________________
 TGLVector3 TGLMatrix::GetScale() const
 {
@@ -824,7 +971,8 @@ void TGLMatrix::Dump() const
 
 ClassImp(TGLUtil)
 
-UInt_t TGLUtil::fgDrawQuality = 60;
+UInt_t TGLUtil::fgDefaultDrawQuality = 60;
+UInt_t TGLUtil::fgDrawQuality        = fgDefaultDrawQuality;
 
 //______________________________________________________________________________
 void TGLUtil::CheckError(const char * loc)
diff --git a/gl/src/TGLViewer.cxx b/gl/src/TGLViewer.cxx
index 28b4c23d5ce..9e8fab0452f 100644
--- a/gl/src/TGLViewer.cxx
+++ b/gl/src/TGLViewer.cxx
@@ -82,12 +82,12 @@ TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
                      Int_t width, Int_t height) :
    fPad(pad),
    fContextMenu(0),
-   fPerspectiveCameraXOZ(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // XOZ floor
-   fPerspectiveCameraYOZ(TGLVector3(0.0, 1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)), // YOZ floor
-   fPerspectiveCameraXOY(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 0.0,-1.0)), // XOY floor
-   fOrthoXOYCamera(TGLOrthoCamera::kXOY),
-   fOrthoXOZCamera(TGLOrthoCamera::kXOZ),
-   fOrthoZOYCamera(TGLOrthoCamera::kZOY),
+   fPerspectiveCameraXOZ(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // XOZ floor
+   fPerspectiveCameraYOZ(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)), // YOZ floor
+   fPerspectiveCameraXOY(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // XOY floor
+   fOrthoXOYCamera(TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down Z axis, X horz, Y vert
+   fOrthoXOZCamera(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // Looking down Y axis, X horz, Z vert
+   fOrthoZOYCamera(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down X axis, Z horz, Y vert
    fCurrentCamera(&fPerspectiveCameraXOZ),
 
    fLightSet          (0),
@@ -95,12 +95,15 @@ TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
    fSelectedPShapeRef (0),
    fCurrentOvlElm     (0),
 
-   fAction(kDragNone), fLastPos(0,0), fActiveButtonID(0),
+   fPushAction(kPushStd), fAction(kDragNone), fLastPos(0,0), fActiveButtonID(0),
    fRedrawTimer(0),
    fClearColor(1),
    fAxesType(TGLUtil::kAxesNone),
+   fAxesDepthTest(kTRUE),
    fReferenceOn(kFALSE),
    fReferencePos(0.0, 0.0, 0.0),
+   fDrawCameraCenter(kFALSE),
+   fCameraMarkup(0),
    fInitGL(kFALSE),
    fSmartRefresh(kFALSE),
    fDebugMode(kFALSE),
@@ -127,12 +130,12 @@ TGLViewer::TGLViewer(TVirtualPad * pad, Int_t x, Int_t y,
 TGLViewer::TGLViewer(TVirtualPad * pad) :
    fPad(pad),
    fContextMenu(0),
-   fPerspectiveCameraXOZ(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // XOZ floor
-   fPerspectiveCameraYOZ(TGLVector3(0.0, 1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)), // YOZ floor
-   fPerspectiveCameraXOY(TGLVector3(1.0, 0.0, 0.0), TGLVector3(0.0, 0.0,-1.0)), // XOY floor
-   fOrthoXOYCamera(TGLOrthoCamera::kXOY),
-   fOrthoXOZCamera(TGLOrthoCamera::kXOZ),
-   fOrthoZOYCamera(TGLOrthoCamera::kZOY),
+   fPerspectiveCameraXOZ(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // XOZ floor
+   fPerspectiveCameraYOZ(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(1.0, 0.0, 0.0)), // YOZ floor
+   fPerspectiveCameraXOY(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // XOY floor
+   fOrthoXOYCamera(TGLVector3( 0.0, 0.0, 1.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down Z axis, X horz, Y vert
+   fOrthoXOZCamera(TGLVector3( 0.0,-1.0, 0.0), TGLVector3(0.0, 0.0, 1.0)), // Looking down Y axis, X horz, Z vert
+   fOrthoZOYCamera(TGLVector3(-1.0, 0.0, 0.0), TGLVector3(0.0, 1.0, 0.0)), // Looking down X axis, Z horz, Y vert
    fCurrentCamera(&fPerspectiveCameraXOZ),
 
    fLightSet          (0),
@@ -140,12 +143,15 @@ TGLViewer::TGLViewer(TVirtualPad * pad) :
    fSelectedPShapeRef (0),
    fCurrentOvlElm     (0),
 
-   fAction(kDragNone), fLastPos(0,0), fActiveButtonID(0),
+   fPushAction(kPushStd), fAction(kDragNone), fLastPos(0,0), fActiveButtonID(0),
    fRedrawTimer(0),
    fClearColor(1),
    fAxesType(TGLUtil::kAxesNone),
+   fAxesDepthTest(kTRUE),
    fReferenceOn(kFALSE),
    fReferencePos(0.0, 0.0, 0.0),
+   fDrawCameraCenter(kFALSE),
+   fCameraMarkup(0),
    fInitGL(kFALSE),
    fSmartRefresh(kFALSE),
    fDebugMode(kFALSE),
@@ -309,6 +315,7 @@ void TGLViewer::PostSceneBuildSetup(Bool_t resetCameras)
 
    // Set default reference to center
    fReferencePos.Set(fOverallBoundingBox.Center());
+   RefreshPadEditor(this);
 }
 
 
@@ -474,17 +481,34 @@ void TGLViewer::DrawGuides()
 {
    // Draw reference marker and coordinate axes.
 
-   glDisable(GL_DEPTH_TEST);
-
+   Bool_t disabled = kFALSE;
    if (fReferenceOn)
+   {
+      glDisable(GL_DEPTH_TEST);
       TGLUtil::DrawReferenceMarker(*fCamera, fReferencePos);
-
-   if (fAxesType != TGLUtil::kAxesOrigin)
+      disabled = kTRUE;
+   }
+   if (fDrawCameraCenter)
+   {
+      glDisable(GL_DEPTH_TEST);
+      Float_t radius = fCamera->ViewportDeltaToWorld(TGLVertex3(fCamera->GetCenterVec()), 3, 3).Mag();
+      const Float_t rgba[4] = { 0, 1, 1, 1.0 };
+      TGLUtil::DrawSphere(fCamera->GetCenterVec(), radius, rgba);
+      disabled = kTRUE;
+   }
+   if(fAxesDepthTest && disabled)
+   {
       glEnable(GL_DEPTH_TEST);
-
+      disabled = kFALSE;
+   }
+   else if (fAxesDepthTest == kFALSE && disabled == kFALSE)
+   {
+      glDisable(GL_DEPTH_TEST);
+      disabled = kTRUE;
+   }
    TGLUtil::DrawSimpleAxes(*fCamera, fOverallBoundingBox, fAxesType);
-
-   glEnable(GL_DEPTH_TEST);
+   if(disabled)
+      glEnable(GL_DEPTH_TEST);
 }
 
 //______________________________________________________________________________
@@ -932,8 +956,9 @@ void TGLViewer::SetCurrentCamera(ECameraType cameraType)
 
 //______________________________________________________________________________
 void TGLViewer::SetOrthoCamera(ECameraType camera,
-                               Double_t left, Double_t right,
-                               Double_t top,  Double_t bottom)
+                                     Double_t zoom, Double_t dolly,
+                                     Double_t center[3],
+                                     Double_t hRotate, Double_t vRotate)
 {
    // Set an orthographic camera to supplied configuration - note this
    // does not need to be the current camera - though you will not see
@@ -951,21 +976,21 @@ void TGLViewer::SetOrthoCamera(ECameraType camera,
    // TODO: Move these into a vector!
    switch(camera) {
       case(kCameraOrthoXOY): {
-         fOrthoXOYCamera.Configure(left, right, top, bottom);
+         fOrthoXOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
          if (fCurrentCamera == &fOrthoXOYCamera) {
             RequestDraw(TGLRnrCtx::kLODHigh);
          }
          break;
       }
       case(kCameraOrthoXOZ): {
-         fOrthoXOZCamera.Configure(left, right, top, bottom);
+         fOrthoXOZCamera.Configure(zoom, dolly, center, hRotate, vRotate);
          if (fCurrentCamera == &fOrthoXOZCamera) {
             RequestDraw(TGLRnrCtx::kLODHigh);
          }
          break;
       }
       case(kCameraOrthoZOY): {
-         fOrthoZOYCamera.Configure(left, right, top, bottom);
+         fOrthoZOYCamera.Configure(zoom, dolly, center, hRotate, vRotate);
          if (fCurrentCamera == &fOrthoZOYCamera) {
             RequestDraw(TGLRnrCtx::kLODHigh);
          }
@@ -1032,11 +1057,13 @@ void TGLViewer::SetPerspectiveCamera(ECameraType camera,
 /**************************************************************************/
 
 //______________________________________________________________________________
-void TGLViewer::GetGuideState(Int_t & axesType, Bool_t & referenceOn, Double_t referencePos[3]) const
+void TGLViewer::GetGuideState(Int_t & axesType, Bool_t & axesDepthTest, Bool_t & referenceOn, Double_t referencePos[3]) const
 {
-   // Fetch the state of guides (axes & reference markers) into arguments.
+   // Fetch the state of guides (axes & reference markers) into arguments
+
+   axesType = fAxesType;
+   axesDepthTest = fAxesDepthTest;
 
-   axesType    = fAxesType;
    referenceOn = fReferenceOn;
    referencePos[0] = fReferencePos.X();
    referencePos[1] = fReferencePos.Y();
@@ -1044,11 +1071,12 @@ void TGLViewer::GetGuideState(Int_t & axesType, Bool_t & referenceOn, Double_t r
 }
 
 //______________________________________________________________________________
-void TGLViewer::SetGuideState(Int_t axesType, Bool_t referenceOn, const Double_t referencePos[3])
+void TGLViewer::SetGuideState(Int_t axesType, Bool_t axesDepthTest, Bool_t referenceOn, const Double_t referencePos[3])
 {
    // Set the state of guides (axes & reference markers) from arguments.
 
    fAxesType    = axesType;
+   fAxesDepthTest = axesDepthTest;
    fReferenceOn = referenceOn;
    fReferencePos.Set(referencePos[0], referencePos[1], referencePos[2]);
    if (fGLDevice != -1)
@@ -1056,6 +1084,14 @@ void TGLViewer::SetGuideState(Int_t axesType, Bool_t referenceOn, const Double_t
    RequestDraw();
 }
 
+//______________________________________________________________________________
+void TGLViewer::SetDrawCameraCenter(Bool_t x)
+{
+   // Draw camera look at and rotation point.
+
+   fDrawCameraCenter = x;
+   RequestDraw();
+}
 
 // Selected physical
 //______________________________________________________________________________
@@ -1085,10 +1121,8 @@ void TGLViewer::OverlayDragFinished()
    Emit("OverlayDragFinished()");
 }
 
-
 /**************************************************************************/
 /**************************************************************************/
-
 //______________________________________________________________________________
 Int_t TGLViewer::DistancetoPrimitive(Int_t /*px*/, Int_t /*py*/)
 {
@@ -1269,6 +1303,23 @@ Bool_t TGLViewer::HandleButton(Event_t * event)
       if (fAction != kNone)
          return kFALSE;
 
+      if (fPushAction == kPushCamCenter)
+      {
+         fPushAction = kPushStd;
+         RequestSelect(event->fX, event->fY);
+         if (fSelRec.GetN() > 0)
+         {
+            TGLVector3 v(event->fX, event->fY, 0.5*fSelRec.GetMinZ());
+            fCurrentCamera->WindowToViewport(v);
+            v = fCurrentCamera->ViewportToWorld(v);
+            fCurrentCamera->SetExternalCenter(kTRUE);
+            fCurrentCamera->SetCenterVec(v.X(), v.Y(), v.Z());
+            RequestDraw();
+         }
+         RefreshPadEditor(this);
+         return kTRUE;
+      }
+
       Bool_t grabPointer = kFALSE;
       Bool_t handled     = kFALSE;
 
@@ -1295,6 +1346,7 @@ Bool_t TGLViewer::HandleButton(Event_t * event)
                if (event->fState & kKeyShiftMask) {
                   if (RequestSelect(event->fX, event->fY)) {
                      ApplySelection();
+                     handled = kTRUE;
                   } else {
                      SelectionChanged(); // Just notify clients.
                   }
@@ -1304,8 +1356,10 @@ Bool_t TGLViewer::HandleButton(Event_t * event)
                      TGLLogicalShape& lshape = const_cast<TGLLogicalShape&>
                         (*fSecSelRec.GetPhysShape()->GetLogical());
                      lshape.ProcessSelection(*fRnrCtx, fSecSelRec);
+                     handled = kTRUE;
                   }
-               } else {
+               }
+               if ( ! handled) {
                   fAction = kDragCameraRotate;
                   grabPointer = kTRUE;
                }
@@ -1558,8 +1612,10 @@ Bool_t TGLViewer::HandleMotion(Event_t * event)
    Short_t lod = TGLRnrCtx::kLODMed;
 
    // Camera interface requires GL coords - Y inverted
-   Int_t xDelta = event->fX - fLastPos.fX;
-   Int_t yDelta = event->fY - fLastPos.fY;
+   Int_t  xDelta = event->fX - fLastPos.fX;
+   Int_t  yDelta = event->fY - fLastPos.fY;
+   Bool_t mod1   = event->fState & kKeyControlMask;
+   Bool_t mod2   = event->fState & kKeyShiftMask;
 
    if (fAction == kDragNone)
    {
@@ -1568,13 +1624,11 @@ Bool_t TGLViewer::HandleMotion(Event_t * event)
          processed = fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event);
       lod = TGLRnrCtx::kLODHigh;
    } else if (fAction == kDragCameraRotate) {
-      processed = CurrentCamera().Rotate(xDelta, -yDelta);
+      processed = CurrentCamera().Rotate(xDelta, -yDelta, mod1, mod2);
    } else if (fAction == kDragCameraTruck) {
-      processed = CurrentCamera().Truck(event->fX, fViewport.Y() - event->fY,
-                                        xDelta, -yDelta);
+      processed = CurrentCamera().Truck(xDelta, -yDelta, mod1, mod2);
    } else if (fAction == kDragCameraDolly) {
-      processed = CurrentCamera().Dolly(xDelta, event->fState & kKeyControlMask,
-                                        event->fState & kKeyShiftMask);
+      processed = CurrentCamera().Dolly(xDelta, mod1, mod2);
    } else if (fAction == kDragOverlay) {
       processed = fCurrentOvlElm->Handle(*fRnrCtx, fOvlSelRec, event);
    }
diff --git a/gl/src/TGLViewerEditor.cxx b/gl/src/TGLViewerEditor.cxx
index 683298563df..da4e131af8b 100644
--- a/gl/src/TGLViewerEditor.cxx
+++ b/gl/src/TGLViewerEditor.cxx
@@ -37,10 +37,17 @@ TGLViewerEditor::TGLViewerEditor(const TGWindow *p,  Int_t width, Int_t height,
    fResetCameraOnDoubleClick(0),
    fUpdateScene(0),
    fCameraHome(0),
+   fCameraCenterExt(0),
+   fCaptureCenter(0),
+   fCameraCenterX(0),
+   fCameraCenterY(0),
+   fCameraCenterZ(0),
+   fAxesType(0),
    fAxesContainer(0),
    fAxesNone(0),
    fAxesEdge(0),
    fAxesOrigin(0),
+   fAxesDepthTest(0),
    fRefContainer(0),
    fReferenceOn(0),
    fReferencePosX(0),
@@ -78,12 +85,19 @@ void TGLViewerEditor::ConnectSignals2Slots()
    fResetCameraOnDoubleClick->Connect("Toggled(Bool_t)", "TGLViewerEditor", this, "DoResetCameraOnDoubleClick()");
    fUpdateScene->Connect("Pressed()", "TGLViewerEditor", this, "DoUpdateScene()");
    fCameraHome->Connect("Pressed()", "TGLViewerEditor", this, "DoCameraHome()");
+   fCameraCenterExt->Connect("Clicked()", "TGLViewerEditor", this, "DoCameraCenterExt()");
+   fCaptureCenter->Connect("Clicked()", "TGLViewerEditor", this, "DoCaptureCenter()");
+   fDrawCameraCenter->Connect("Clicked()", "TGLViewerEditor", this, "DoDrawCameraCenter()");
+   fCameraCenterX->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateCameraCenter()");
+   fCameraCenterY->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateCameraCenter()");
+   fCameraCenterZ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateCameraCenter()");
 
-   fAxesContainer->Connect("Clicked(Int_t)", "TGLViewerEditor", this, "UpdateViewerGuides()");
-   fReferenceOn->Connect("Clicked()", "TGLViewerEditor", this, "UpdateViewerGuides()");
-   fReferencePosX->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerGuides()");
-   fReferencePosY->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerGuides()");
-   fReferencePosZ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerGuides()");
+   fAxesContainer->Connect("Clicked(Int_t)", "TGLViewerEditor", this, "UpdateViewerAxes(Int_t)");
+
+   fReferenceOn->Connect("Clicked()", "TGLViewerEditor", this, "UpdateViewerReference()");
+   fReferencePosX->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerReference()");
+   fReferencePosY->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerReference()");
+   fReferencePosZ->Connect("ValueSet(Long_t)", "TGLViewerEditor", this, "UpdateViewerReference()");
 
    fCamMode->Connect("Selected(Int_t)", "TGLViewerEditor", this, "DoCameraMarkup()");
    fCamMarkupOn->Connect("Clicked()", "TGLViewerEditor", this, "DoCameraMarkup()");
@@ -119,10 +133,26 @@ void TGLViewerEditor::SetModel(TObject* obj)
    fLightSet->SetModel(fViewer->GetLightSet());
    fClipSet->SetModel(fViewer->GetClipSet());
 
+   // style tab
    fClearColor->SetColor(TColor::Number2Pixel(fViewer->GetClearColor()), kFALSE);
    fIgnoreSizesOnUpdate->SetState(fViewer->GetIgnoreSizesOnUpdate() ? kButtonDown : kButtonUp);
    fResetCamerasOnUpdate->SetState(fViewer->GetResetCamerasOnUpdate() ? kButtonDown : kButtonUp);
    fResetCameraOnDoubleClick->SetState(fViewer->GetResetCameraOnDoubleClick() ? kButtonDown : kButtonUp);
+   //camera look at
+   TGLCamera & cam = fViewer->CurrentCamera();
+   fCameraCenterExt->SetDown(cam.GetExternalCenter());
+   fDrawCameraCenter->SetDown(fViewer->GetDrawCameraCenter());
+   Double_t* la = cam.GetCenterVec();
+   fCameraCenterX->SetNumber(la[0]);
+   fCameraCenterY->SetNumber(la[1]);
+   fCameraCenterZ->SetNumber(la[2]);
+   fCameraCenterX->SetState(fCameraCenterExt->IsDown());
+   fCameraCenterY->SetState(fCameraCenterExt->IsDown());
+   fCameraCenterZ->SetState(fCameraCenterExt->IsDown());
+   if (fViewer->GetPushAction() == TGLViewer::kPushCamCenter)
+      fCaptureCenter->SetTextColor(0xa03060);
+   else
+      fCaptureCenter->SetTextColor(0x000000);
 }
 
 //______________________________________________________________________________
@@ -191,42 +221,101 @@ void TGLViewerEditor::DoCameraMarkup()
 }
 
 //______________________________________________________________________________
-void TGLViewerEditor::UpdateViewerGuides()
+void TGLViewerEditor::DoCameraCenterExt()
+{
+   // Set external camera center.
+
+   TGLCamera& cam = fViewer->CurrentCamera();
+   cam.SetExternalCenter(fCameraCenterExt->GetState());
+
+   fCameraCenterX->SetState(fCameraCenterExt->IsDown());
+   fCameraCenterY->SetState(fCameraCenterExt->IsDown());
+   fCameraCenterZ->SetState(fCameraCenterExt->IsDown());
+
+   ViewerRedraw();
+}
+
+//______________________________________________________________________________
+void TGLViewerEditor::DoCaptureCenter()
+{
+   // Capture camera-center via picking.
+
+   fViewer->PickCameraCenter();
+}
+
+//______________________________________________________________________________
+void TGLViewerEditor::DoDrawCameraCenter()
+{
+   // Draw camera center.
+
+   fViewer->SetDrawCameraCenter(fDrawCameraCenter->IsDown());
+   ViewerRedraw();
+}
+
+//______________________________________________________________________________
+void TGLViewerEditor::UpdateCameraCenter()
+{
+   // Update current camera with GUI state.
+
+   TGLCamera& cam = fViewer->CurrentCamera();
+   cam.SetCenterVec(fCameraCenterX->GetNumber(), fCameraCenterY->GetNumber(), fCameraCenterZ->GetNumber());
+   ViewerRedraw();
+}
+
+//______________________________________________________________________________
+void TGLViewerEditor::UpdateViewerAxes(Int_t id)
 {
    // Update viewer with GUI state.
 
-   Int_t axesType = TGLUtil::kAxesNone;
-   for (Int_t i = 1; i < 4; i++) {
-      TGButton * button = fAxesContainer->GetButton(i);
-      if (button && button->IsDown()) {
-         axesType = i-1;
-         break;
+   if(id < 4)
+   {
+      fAxesType = id -1;
+      for (Int_t i = 1; i < 4; i++) {
+         TGButton * button = fAxesContainer->GetButton(i);
+         if (i == id)
+            button->SetDown(kTRUE);
+         else
+            button->SetDown(kFALSE);
       }
    }
+   Bool_t axdt = fAxesContainer->GetButton(4)->IsDown();
+   const Double_t refPos[] = {fReferencePosX->GetNumber(), fReferencePosY->GetNumber(), fReferencePosZ->GetNumber()};
+   fViewer->SetGuideState(fAxesType, axdt, fReferenceOn->IsDown(), refPos);
+   UpdateReferencePosState();
+}
+
+//______________________________________________________________________________
+void TGLViewerEditor::UpdateViewerReference()
+{
+   // Update viewer with GUI state.
 
    const Double_t refPos[] = {fReferencePosX->GetNumber(), fReferencePosY->GetNumber(), fReferencePosZ->GetNumber()};
-   fViewer->SetGuideState(axesType, fReferenceOn->IsDown(), refPos);
-   UpdateReferencePos();
+   fViewer->SetGuideState(fAxesType,  fAxesContainer->GetButton(4)->IsDown(), fReferenceOn->IsDown(), refPos);
+   UpdateReferencePosState();
 }
 
 //______________________________________________________________________________
-void TGLViewerEditor::CreateStyleTab()
+TGNumberEntry*  TGLViewerEditor::MakeLabeledNEntry(TGCompositeFrame* p, const char* name, Int_t labelw,Int_t nd, Int_t style)
 {
-   // Creates "Style" tab.
+   // Helper function to create fixed width TGLabel and TGNumberEntry in same row.
 
-   // LightSet
-   fLightSet = new TGLLightSetSubEditor(this);
-   fLightSet->Connect("Changed", "TGLViewerEditor", this, "ViewerRedraw()");
-   AddFrame(fLightSet, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 0, 0, 0));
+   TGHorizontalFrame *rfr   = new TGHorizontalFrame(p);
+   TGHorizontalFrame *labfr = new TGHorizontalFrame(rfr, labelw, 20, kFixedSize);
+   TGLabel* lab =   new TGLabel(rfr,name);
+   labfr->AddFrame(lab, new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 0) );
+   rfr->AddFrame(labfr, new TGLayoutHints(kLHintsLeft | kLHintsBottom, 0, 0, 0));
 
-   {
-      TGHorizontalFrame* hf = new TGHorizontalFrame(this);
-      TGLabel* lab = new TGLabel(hf, "Clear color");
-      hf->AddFrame(lab, new TGLayoutHints(kLHintsLeft|kLHintsBottom, 1, 12, 1, 3));
-      fClearColor = new TGColorSelect(hf, 0, -1);
-      hf->AddFrame(fClearColor, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
-      AddFrame(hf, new TGLayoutHints(kLHintsLeft, 2, 1, 1, 1));
-   }
+   TGNumberEntry* ne = new TGNumberEntry(rfr, 0.0f, nd, -1, (TGNumberFormat::EStyle)style);
+   rfr->AddFrame( ne, new TGLayoutHints(kLHintsLeft | kLHintsExpandX | kLHintsBottom, 2, 0, 0));
+
+   p->AddFrame(rfr, new TGLayoutHints(kLHintsLeft, 0, 0, 1, 0));
+   return ne;
+}
+
+//______________________________________________________________________________
+void TGLViewerEditor::CreateStyleTab()
+{
+   // Creates "Style" tab.
 
    MakeTitle("Update behaviour");
    fIgnoreSizesOnUpdate  = new TGCheckButton(this, "Ignore sizes");
@@ -238,10 +327,24 @@ void TGLViewerEditor::CreateStyleTab()
    fResetCameraOnDoubleClick = new TGCheckButton(this, "Reset on dbl-click");
    fResetCameraOnDoubleClick->SetToolTipText("Reset cameras on double-click");
    AddFrame(fResetCameraOnDoubleClick, new TGLayoutHints(kLHintsLeft, 4, 1, 1, 1));
-   fUpdateScene = new TGTextButton(this, "Update Scene");
-   AddFrame(fUpdateScene, new TGLayoutHints(kLHintsLeft|kLHintsExpandX, 4, 1, 1, 1));
-   fCameraHome = new TGTextButton(this, "Camera Home");
-   AddFrame(fCameraHome, new TGLayoutHints(kLHintsLeft|kLHintsExpandX, 4, 1, 1, 1));
+
+   TGCompositeFrame* af = this;
+   fUpdateScene = new TGTextButton(af, "Update Scene", 130);
+   af->AddFrame(fUpdateScene, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 1, 1, 8, 1));
+   fCameraHome = new TGTextButton(af, "Camera Home", 130);
+   af->AddFrame(fCameraHome, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 1, 1, 1, 1));
+
+   TGHorizontalFrame* hf = new TGHorizontalFrame(this);
+   TGLabel* lab = new TGLabel(hf, "Clear Color");
+   hf->AddFrame(lab, new TGLayoutHints(kLHintsLeft|kLHintsBottom, 1, 4, 8, 3));
+   fClearColor = new TGColorSelect(hf, 0, -1);
+   hf->AddFrame(fClearColor, new TGLayoutHints(kLHintsLeft, 1, 1, 8, 1));
+   AddFrame(hf, new TGLayoutHints(kLHintsLeft, 2, 1, 1, 1));
+
+   // LightSet
+   fLightSet = new TGLLightSetSubEditor(this);
+   fLightSet->Connect("Changed", "TGLViewerEditor", this, "ViewerRedraw()");
+   AddFrame(fLightSet, new TGLayoutHints(kLHintsTop | kLHintsExpandX, 2, 0, 0, 0));
 }
 
 //______________________________________________________________________________
@@ -250,45 +353,43 @@ void TGLViewerEditor::CreateGuidesTab()
    // Create "Guides" tab.
    fGuidesFrame = CreateEditorTabSubFrame("Guides");
 
-   // axes
-   fAxesContainer = new TGButtonGroup(fGuidesFrame, "Axes");
-   fAxesNone = new TGRadioButton(fAxesContainer, "None");
-   fAxesEdge = new TGRadioButton(fAxesContainer, "Edge");
-   fAxesOrigin = new TGRadioButton(fAxesContainer, "Origin");
-   fGuidesFrame->AddFrame(fAxesContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-
-   //Reference container
-   fRefContainer = new TGGroupFrame(fGuidesFrame, "Reference Marker");
-   fGuidesFrame->AddFrame(fRefContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-
-   //Reference options
+   // external camera look at point
+   TGGroupFrame* grf = new TGGroupFrame(fGuidesFrame, "Camera center:", kVerticalFrame);
+   fDrawCameraCenter = new TGCheckButton(grf, "Show", 50);
+   grf->AddFrame(fDrawCameraCenter, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 1, 1));
+   fCameraCenterExt = new TGCheckButton(grf, "External", 50);
+   grf->AddFrame(fCameraCenterExt, new TGLayoutHints(kLHintsLeft, 0, 0, 1, 0));
+   fGuidesFrame->AddFrame(grf, new TGLayoutHints(kLHintsTop| kLHintsLeft | kLHintsExpandX, 2, 3, 3, 0));
+   Int_t labw = 20;
+   fCameraCenterX = MakeLabeledNEntry(grf, "X:", labw, 8, TGNumberFormat::kNESRealThree);
+   fCameraCenterY = MakeLabeledNEntry(grf, "Y:", labw, 8, TGNumberFormat::kNESRealThree);
+   fCameraCenterZ = MakeLabeledNEntry(grf, "Z:", labw, 8, TGNumberFormat::kNESRealThree);
+   fCaptureCenter = new TGTextButton(grf, " Pick center ");
+   grf->AddFrame(fCaptureCenter, new TGLayoutHints(kLHintsNormal, labw + 2, 0, 2, 0));
+
+   // reference container
+   fRefContainer = new TGGroupFrame(fGuidesFrame, "Reference marker");
+   fGuidesFrame->AddFrame(fRefContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
    fReferenceOn = new TGCheckButton(fRefContainer, "Show");
-   fRefContainer->AddFrame(fReferenceOn, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-
-   TGLabel *label = new TGLabel(fRefContainer, "X");
-   fRefContainer->AddFrame(label, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 3, 3));
-   fReferencePosX = new TGNumberEntry(fRefContainer, 0.0, 8);
-   fRefContainer->AddFrame(fReferencePosX, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   fRefContainer->AddFrame(fReferenceOn, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX));
+   fReferencePosX = MakeLabeledNEntry(fRefContainer, "X:", labw, 8, TGNumberFormat::kNESRealThree );
+   fReferencePosY = MakeLabeledNEntry(fRefContainer, "Y:", labw, 8, TGNumberFormat::kNESRealThree );
+   fReferencePosZ = MakeLabeledNEntry(fRefContainer, "Z:", labw, 8, TGNumberFormat::kNESRealThree );
 
-   label = new TGLabel(fRefContainer, "Y");
-   fRefContainer->AddFrame(label, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 3, 3));
-   fReferencePosY = new TGNumberEntry(fRefContainer, 0.0, 8);
-   fRefContainer->AddFrame(fReferencePosY, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-
-   label = new TGLabel(fRefContainer, "Z");
-   fRefContainer->AddFrame(label, new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 0, 3, 3));
-   fReferencePosZ = new TGNumberEntry(fRefContainer, 0.0, 8);
-   fRefContainer->AddFrame(fReferencePosZ, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
+   // axes
+   fAxesContainer = new TGButtonGroup(fGuidesFrame, "Axes");
+   fAxesNone = new TGRadioButton(fAxesContainer, "None", 1);
+   fAxesEdge = new TGRadioButton(fAxesContainer, "Edge", 2);
+   fAxesOrigin = new TGRadioButton(fAxesContainer, "Origin", 3);
+   fAxesDepthTest = new TGCheckButton(fAxesContainer, "DepthTest",4);
+   fGuidesFrame->AddFrame(fAxesContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
 
    // camera markup
-   fCamContainer = new TGGroupFrame(fGuidesFrame, "Camera Markup");
-   fGuidesFrame->AddFrame(fCamContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-
+   fCamContainer = new TGGroupFrame(fGuidesFrame, "Camera markup");
+   fGuidesFrame->AddFrame(fCamContainer, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 2, 3, 0, 0));
    fCamMarkupOn = new TGCheckButton(fCamContainer, "Show");
    fCamMarkupOn->SetToolTipText("Implemented for orthographic mode");
-
-   fCamContainer->AddFrame(fCamMarkupOn, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 3, 3, 3, 3));
-
+   fCamContainer->AddFrame(fCamMarkupOn, new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX));
    TGHorizontalFrame* chf = new TGHorizontalFrame(fCamContainer);
    TGLabel* lab = new TGLabel(chf, "Mode");
    chf->AddFrame(lab, new TGLayoutHints(kLHintsLeft|kLHintsBottom, 1, 4, 1, 2));
@@ -317,7 +418,7 @@ void TGLViewerEditor::CreateClippingTab()
 }
 
 //______________________________________________________________________________
-void TGLViewerEditor::UpdateReferencePos()
+void TGLViewerEditor::UpdateReferencePosState()
 {
    // Enable/disable reference position (x/y/z) number edits based on
    // reference check box.
@@ -330,22 +431,27 @@ void TGLViewerEditor::UpdateReferencePos()
 //______________________________________________________________________________
 void TGLViewerEditor::SetGuides()
 {
-   // Set cintriks in "Guides" tab.
+   // Configuration of guides GUI called from SetModel().
 
-   Int_t axesType = TGLUtil::kAxesNone;
+   Bool_t axesDepthTest = kFALSE;
    Bool_t referenceOn = kFALSE;
    Double_t referencePos[3] = {0.};
-   fViewer->GetGuideState(axesType, referenceOn, referencePos);
+   fViewer->GetGuideState(fAxesType, axesDepthTest, referenceOn, referencePos);
 
-   // Button ids run from 1
-   if (TGButton *btn = fAxesContainer->GetButton(axesType+1))
-      btn->SetDown();
+   for (Int_t i = 1; i < 4; i++) {
+      TGButton * btn = fAxesContainer->GetButton(i);
+      if (fAxesType+1 == i)
+          btn->SetDown(kTRUE);
+      else
+          btn->SetDown(kFALSE);
+   }
+   fAxesContainer->GetButton(4)->SetOn(axesDepthTest, kFALSE);
 
    fReferenceOn->SetDown(referenceOn);
    fReferencePosX->SetNumber(referencePos[0]);
    fReferencePosY->SetNumber(referencePos[1]);
    fReferencePosZ->SetNumber(referencePos[2]);
-   UpdateReferencePos();
+   UpdateReferencePosState();
 
    if (fViewer->CurrentCamera().IsA()->InheritsFrom("TGLOrthoCamera")) {
       fGuidesFrame->ShowFrame(fCamContainer);
diff --git a/tutorials/gl/glViewerExercise.C b/tutorials/gl/glViewerExercise.C
index 6edae7827af..3f2d43a5f8d 100644
--- a/tutorials/gl/glViewerExercise.C
+++ b/tutorials/gl/glViewerExercise.C
@@ -2,148 +2,121 @@
 //Author: Richard maunder
 
 #include "TGLViewer.h"
+#include "TGLPerspectiveCamera.h"
 #include "TTimer.h"
 #include "TRandom.h"
 #include "TVirtualPad.h"
 
 TGLViewer::ECameraType camera;
-TTimer timer(50);
+TTimer timer(25);
 TRandom randGen(0);
 
-void AnimatePerspectiveCamera()
+Int_t moveCount = 0;
+
+void AnimateCamera()
 {
-   static Double_t fov = 50.0;
+   // initialization
+   static Double_t fov = 30;
+   static Double_t zoom = 0.78;
    static Double_t dolly = 1500.0;
    static Double_t center[3] = {-164.0, -164.0, -180.0};
    static Double_t hRotate = 0.0;
    static Double_t vRotate = 0.0;
-
-   static Double_t fovStep = randGen.Rndm()*5.0 - 2.5;
-   static Double_t dollyStep = randGen.Rndm()*10.0 - 5.0;
-   static Double_t centerStep[3] = {randGen.Rndm()*20.0 - 10.0, 
-                                    randGen.Rndm()*20.0 - 10.0, 
-                                    randGen.Rndm()*20.0 - 10.0};
-   static Double_t hRotateStep = randGen.Rndm()*10.0 - 5.0;
-   static Double_t vRotateStep = randGen.Rndm()*10.0 - 5.0;
-
-   fov += fovStep;
-   dolly += dollyStep;
+   // steps
+   static Double_t fovStep = randGen.Rndm()*3.0 - 0.5;
+   static Double_t zoomStep = (20 - randGen.Rndm())/1000.;
+   static Double_t dollyStep = randGen.Rndm()*5.0 - 1.0;
+   static Double_t centerStep[3] = {randGen.Rndm()*4, randGen.Rndm()*4, randGen.Rndm()*4 };
+   static Double_t hRotateStep = randGen.Rndm()*0.025;
+   static Double_t vRotateStep = randGen.Rndm()*0.05;
+
+   // move center
    center[0] += centerStep[0];
    center[1] += centerStep[1];
    center[2] += centerStep[2];
+   Double_t mag = TMath::Sqrt(center[0]*center[0] + center[1]*center[1] + center[2]*center[2]);
+   if(mag > 500)
+   {
+      centerStep[0] = -centerStep[0];
+      centerStep[1] = -centerStep[1];
+      centerStep[2] = -centerStep[2];
+   }
+
+   // rotate
    hRotate += hRotateStep;
    vRotate += vRotateStep;
+   if (vRotate >= TMath::TwoPi() || vRotate <= 0.0)
+      vRotateStep = -vRotateStep;
 
-   if (vRotate >= 90.0 || vRotate <= -90.0) 
-   {
-   	vRotateStep = -vRotateStep;
-   }
-   if (dolly >= 2000.0 || dolly <= 1000.0) {
-   	dollyStep = -dollyStep;
-   }
-   if (fov > 170.0 || fov < 1.0) {
-      fovStep = - fovStep;
-   }
-   TGLViewer * v = (TGLViewer *)gPad->GetViewer3D();
+   if (hRotate >= (TMath::PiOver2()- 0.02f)|| hRotate <= (0.07f -TMath::PiOver2()))
+      hRotateStep = -hRotateStep;
 
-   /*
-   void  SetPerspectiveCamera(ECameraType camera, Double_t fov, Double_t dolly, 
-                              Double_t center[3], Double_t hRotate, Double_t vRotate);*/
-   v->SetPerspectiveCamera(camera, fov, dolly, center, hRotate, vRotate);
-}
+   // dolly
+   dolly += dollyStep;
+   if (dolly >= 2000.0 || dolly <= 1500.0)
+      dollyStep = -dollyStep;
 
-void AnimateOrthographicCamera()
-{
-   static Double_t left  = -100.0;
-   static Double_t right = 100.0;
-   static Double_t top   = 100.0;
-   static Double_t bottom = -100.0;
-
-   static Double_t leftStep  = randGen.Rndm()*40.0 - 10.0;
-   static Double_t rightStep = randGen.Rndm()*20.0 - 10.0;
-   static Double_t topStep   = randGen.Rndm()*40.0 - 10.0;
-   static Double_t bottomStep = randGen.Rndm()*20.0 -10.0;
-
-   left += leftStep;
-   right += rightStep;
-   top += topStep;
-   bottom += bottomStep;
-
-   if (left >= 0.0 || left <= -500.0) {
-   	leftStep = -leftStep;
-   }
-   if (right >= 500.0 || right <= 0.0) {
-   	rightStep = -rightStep;
-   }
-   if (top >= 500.0 || top <= 0.0) {
-   	topStep = -topStep;
-   }
-   if (bottom >= 0.0 || bottom <= -500.0) {
-   	bottomStep = -bottomStep;
+   // modify frustum
+   TGLViewer * v = (TGLViewer *)gPad->GetViewer3D();
+   if(camera < 3)
+   {
+      fov += fovStep;
+      if (fov > 130.0 || fov < 5.0)
+         fovStep = - fovStep; }
+   else
+   {
+      zoom += zoomStep;
+      if (zoom > 4.0 || zoom < 0.25)
+         zoomStep = - zoomStep;
    }
 
-   TGLViewer * v = (TGLViewer *)gPad->GetViewer3D();
+   // apply
+   if(camera < 3)
+      v->SetPerspectiveCamera(camera, fov, dollyStep, center, hRotateStep, vRotateStep);
+   else
+      v->SetOrthoCamera(camera, zoom, dollyStep, center, hRotateStep, vRotateStep);
 
-   /*
-   void  SetOrthoCamera(ECameraType camera, Double_t left, Double_t right, Double_t top, Double_t bottom); */
-   v->SetOrthoCamera(camera, left, right, top, bottom);
+   if (++moveCount % 10 == 0)
+      v->RefreshPadEditor(v);
 }
 
 void glViewerExercise()
 {
    gROOT->ProcessLine(".x nucleus.C");
    TGLViewer * v = (TGLViewer *)gPad->GetViewer3D();
-   
-   // Random draw style 
+
+   // Random draw style
    Int_t style = randGen.Integer(3);
-   switch (style) {
+   switch (style)
+   {
       case 0: v->SetStyle(TGLRnrCtx::kFill); break;
       case 1: v->SetStyle(TGLRnrCtx::kOutline); break;
       case 2: v->SetStyle(TGLRnrCtx::kWireFrame); break;
-   }   
-
-   // Clipping setup - something like this:
-   /*
-   Double_t planeEq[4] = { 0.5, 1.0, -1.0, 2.0 };
-   v->SetClipState(TGLViewer::kClipPlane, planeEq);
-   v->SetCurrentClip(TGLViewer::kClipPlane, kTRUE);
-   */
-
-   // Guides - something like this:
-   /*
-   Double_t refPos[3] = { 50.0, 60.0, 100.0 };
-   v->SetGuideState(TGLViewer::kAxesEdge, kTRUE, refPos); 
-   */
+   }
 
    // Lights - turn some off randomly
    TGLLightSet* ls = v->GetLightSet();
-   if (randGen.Integer(2) == 0) {
+   if (randGen.Integer(2) == 0)
       ls->SetLight(TGLLightSet::kLightLeft, kFALSE);
-   }
-   if (randGen.Integer(2) == 0) {
+   if (randGen.Integer(2) == 0)
       ls->SetLight(TGLLightSet::kLightRight, kFALSE);
-   }
-   if (randGen.Integer(2) == 0) {
+   if (randGen.Integer(2) == 0)
       ls->SetLight(TGLLightSet::kLightTop, kFALSE);
-   }
-   if (randGen.Integer(2) == 0) {
+   if (randGen.Integer(2) == 0)
       ls->SetLight(TGLLightSet::kLightBottom, kFALSE);
-   }
 
    // Random camera type
-   /*
-   enum ECameraType { kCameraPerspXOZ, kCameraPerspYOZ, kCameraPerspXOY,
-                      kCameraOrthoXOY, kCameraOrthoXOZ, kCameraOrthoZOY };*/
-   Int_t cam = randGen.Integer(6);
-   camera = (TGLViewer::ECameraType)cam;
+   Int_t id = randGen.Integer(6);
+   camera = (TGLViewer::ECameraType)id;
    v->SetCurrentCamera(camera);
+   v->CurrentCamera().SetExternalCenter(kTRUE);
+   if (id > 2) {
+      TGLOrthoCamera& o = v->CurrentCamera();
+      o.SetEnableRotate(kTRUE);
+   }
 
    // Now animate the camera
-   if (camera <3) {
-      timer.SetCommand("AnimatePerspectiveCamera()");
-   } else {
-      timer.SetCommand("AnimateOrthographicCamera()");
-   }
+   timer.SetCommand("AnimateCamera()");
    timer.TurnOn();
 }
 
diff --git a/tutorials/gl/glViewerLOD.C b/tutorials/gl/glViewerLOD.C
index dc534fb42de..b7e12e7304a 100644
--- a/tutorials/gl/glViewerLOD.C
+++ b/tutorials/gl/glViewerLOD.C
@@ -1,10 +1,10 @@
 //To set the Level Of Details when rendering geometry shapes
 //Author: Richard Maunder
-   
-void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE, Bool_t reqSpheres = kTRUE, Bool_t reqTubes = kTRUE) 
+
+void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE, Bool_t reqSpheres = kTRUE, Bool_t reqTubes = kTRUE)
 {
    TGeoManager * geom = new TGeoManager("LODTest", "GL viewer LOD test");
-   geom->SetNsegments(4); // Doesn't matter keep low  
+   geom->SetNsegments(4); // Doesn't matter keep low
    TGeoMaterial *matEmptySpace = new TGeoMaterial("EmptySpace", 0, 0, 0);
    TGeoMaterial *matSolid      = new TGeoMaterial("Solid"    , .938, 1., 10000.);
 
@@ -18,10 +18,10 @@ void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE, Bool_t reqSph
    } else {
       worldRadius = pow(reqNodes,.3)*sizeBase;
    }
- 
-   TGeoVolume *top = geom->MakeBox("WORLD", medEmptySpace, worldRadius, worldRadius, worldRadius); 
+
+   TGeoVolume *top = geom->MakeBox("WORLD", medEmptySpace, worldRadius, worldRadius, worldRadius);
    geom->SetTopVolume(top);
-   
+
    gRandom->SetSeed();
 
    // Create random number of unique sphere shapes - up to 25% of total placed sphere requested
@@ -36,13 +36,21 @@ void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE, Bool_t reqSph
       sprintf(name, "Volume_%d", i);
 
       // Random volume shape
-      UInt_t type = gRandom->Integer((reqSpheres+reqTubes)*3);
-      if (!reqSpheres) type += 3;
+      Int_t type = -1;
+      if (reqSpheres && reqTubes) {
+         type = gRandom->Integer(2);
+         if (type == 1)
+            type += gRandom->Integer(3);
+      }
+      else if(reqSpheres)
+         type = 0;
+      else if(reqTubes)
+         type = 1 + gRandom->Integer(3);
 
       // Random dimensions
       Double_t rMin = gRandom->Rndm() * sizeBase;
       Double_t rMax = rMin + gRandom->Rndm() * sizeBase * 2.0;
-      Double_t dz = pow(gRandom->Rndm(),2.0) * sizeBase * 15.0;
+      Double_t dz   = pow(gRandom->Rndm(),2.0) * sizeBase * 15.0;
       Double_t phi1 = gRandom->Rndm() * 90.0;
       Double_t phi2 = phi1 + gRandom->Rndm() * 270.0;
 
@@ -51,32 +59,30 @@ void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE, Bool_t reqSph
       if (color == kBlack) color += 1;
 
       switch (type) {
-         case 0:
-         case 1:
-         case 2: {
+        case (0): {
             // GL viewer only supports solid spheres (0. inner radius)
-            volumes[i] = geom->MakeSphere(name,  medSolid,  0., rMax); 
+            volumes[i] = geom->MakeSphere(name,  medSolid,  0., rMax);
             printf("Volume %d : Color %d, Sphere, Radius %f\n", i, color, rMax);
             break;
          }
-         case 3: {
-            volumes[i] = geom->MakeTube(name,  medSolid,  rMin, rMax, dz); 
+         case 1: {
+            volumes[i] = geom->MakeTube(name,  medSolid,  rMin, rMax, dz);
             printf("Volume %d : Color %d, Tube, Inner Radius %f, Outer Radius %f, Length %f\n", i, color, rMin, rMax, dz);
             break;
          }
-         case 4: {
-            volumes[i] = geom->MakeTubs(name,  medSolid,  rMin, rMax, dz, phi1, phi2); 
-            printf("Volume %d : Color %d, Tube Seg, Inner Radius %f, Outer Radius %f, Length %f, Phi1 %f, Phi2 %f\n", 
+         case 2: {
+            volumes[i] = geom->MakeTubs(name,  medSolid,  rMin, rMax, dz, phi1, phi2);
+            printf("Volume %d : Color %d, Tube Seg, Inner Radius %f, Outer Radius %f, Length %f, Phi1 %f, Phi2 %f\n",
                    i, color, rMin, rMax, dz, phi1, phi2);
             break;
          }
-         case 5: {
+         case 3: {
             Double_t n1[3], n2[3];
-            n1[0] = gRandom->Rndm()*.5; n1[1] = gRandom->Rndm()*.5; n1[2] = -1.0 + gRandom->Rndm()*.5; 
-            n2[0] = gRandom->Rndm()*.5; n2[1] = gRandom->Rndm()*.5; n2[2] = 1.0 - gRandom->Rndm()*.5; 
+            n1[0] = gRandom->Rndm()*.5; n1[1] = gRandom->Rndm()*.5; n1[2] = -1.0 + gRandom->Rndm()*.5;
+            n2[0] = gRandom->Rndm()*.5; n2[1] = gRandom->Rndm()*.5; n2[2] =  1.0 - gRandom->Rndm()*.5;
 
-            volumes[i] = geom->MakeCtub(name,  medSolid,  rMin, rMax, dz, phi1, phi2, n1[0], n1[1], n1[2], n2[0], n2[1], n2[2]); 
-            printf("Volume %d : Color %d, Cut Tube, Inner Radius %f, Outer Radius %f, Length %f, Phi1 %f, Phi2 %f, n1 (%f,%f,%f), n2 (%f,%f,%f)\n", 
+            volumes[i] = geom->MakeCtub(name,  medSolid,  rMin, rMax, dz, phi1, phi2, n1[0], n1[1], n1[2], n2[0], n2[1], n2[2]);
+            printf("Volume %d : Color %d, Cut Tube, Inner Radius %f, Outer Radius %f, Length %f, Phi1 %f, Phi2 %f, n1 (%f,%f,%f), n2 (%f,%f,%f)\n",
                    i, color, rMin, rMax, dz, phi1, phi2, n1[0], n1[1], n1[2], n2[0], n2[1], n2[2]);
             break;
          }
@@ -93,7 +99,7 @@ void glViewerLOD(Int_t reqNodes = 1000, Bool_t randomDist = kTRUE, Bool_t reqSph
    // Scatter reqSpheres placed sphere randomly in space
    Double_t x, y, z;
    for (i = 0; i < reqNodes; i++) {
-      // Pick random volume 
+      // Pick random volume
       UInt_t useVolume = gRandom->Integer(volumeCount);
 
       TGeoTranslation * trans;
-- 
GitLab