// @(#)root/gl:$Id$
// Author:  Richard Maunder  25/05/2005

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TGLCamera
#define ROOT_TGLCamera

#include "TGLUtil.h"
#include "TGLBoundingBox.h"
#include "TPoint.h"
#include "TObject.h"

#include <cassert>
#include <cmath>

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGLCamera                                                            //
//                                                                      //
// Abstract base camera class - concrete classes for orthographic and   //
// persepctive cameras derive from it. This class maintains values for  //
// the current:                                                         //
// i)   Viewport                                                        //
// ii)  Projection, modelview and clip matricies - extracted from GL    //
// iii) The 6 frustum planes                                            //
// iv)  Expanded frustum interest box                                   //
//                                                                      //
// It provides methods for various projection, overlap and intersection //
// tests for viewport and world locations, against the true frustum and //
// expanded interest box, and for extracting eye position and direction.//
//                                                                      //
// It also defines the pure virtual manipulation interface methods the  //
// concrete ortho and prespective classes must implement.               //
//////////////////////////////////////////////////////////////////////////

class TGLCamera : public TObject
{
public:
   enum EFrustumPlane
   {
      kNear             = 0,
      kLeft             = 1,
      kRight            = 2,
      kTop              = 3,
      kBottom           = 4,
      kFar              = 5,
      kPlanesPerFrustum = 6
   };

private:
   // Fields

   // Debuging visual aids
   TGLBoundingBox   fPreviousInterestBox;  //! previous interest box (DEBUG)
   TGLBoundingBox   fInterestFrustum;      //! frustum basis of current interest box - NOT a true BB! (DEBUG)
   TGLBoundingBox   fInterestFrustumAsBox; //! frustum basis (as box) of current interest box (DEBUG)

   static const Double_t fgInterestBoxExpansion; //! expansion c.f. aligned current frustum box

   // Methods
   TGLBoundingBox Frustum(Bool_t asBox = kTRUE) const; // current frustum

   // Non-copyable class
   TGLCamera(const TGLCamera &);
   TGLCamera & operator=(const TGLCamera &);

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
    Bool_t      fFixDefCenter;    //  use fixed default center
    Bool_t      fWasArcBalled;    //  set when arc-ball rotation is used
    TGLVector3  fExtCenter;       //  external camera center
    TGLVector3  fDefCenter;       //  default camera center
    TGLVector3  fFDCenter;        //  fixed default 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?
   mutable UInt_t    fTimeStamp;                       //! timestamp
   mutable TGLMatrix fLastNoPickProjM;                 //! no-pick projection matrix (cached)
   mutable TGLMatrix fProjM;                           //! projection matrix        (cached)
   mutable TGLMatrix fModVM;                           //! modelView matrix         (cached)
   mutable TGLMatrix fClipM;                           //! object space clip matrix (cached)
   mutable TGLPlane fFrustumPlanes[kPlanesPerFrustum]; //! frustum planes           (cached)

   TGLRect   fViewport;    //! viewport (GL coords - origin bottom left)

   TGLBoundingBox   fInterestBox;          //! the interest box - created in UpdateInterest()
   mutable Double_t fLargestSeen;          //! largest box diagonal seen in OfInterest() - used when
                                           //! bootstrapping interest box

   // 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();

   virtual Bool_t IsOrthographic() const {  return kFALSE; }
   virtual Bool_t IsPerspective() const { return kFALSE; }

   const TGLMatrix& RefModelViewMatrix() const { return fModVM; }

   Bool_t IsCacheDirty() const { return fCacheDirty; }
   void   IncTimeStamp()       { fCacheDirty = kTRUE; ++fTimeStamp; }
   UInt_t TimeStamp()    const { return fTimeStamp; }

   void           SetViewport(const TGLRect & viewport);
   TGLRect&       RefViewport()       { return fViewport; }
   const TGLRect& RefViewport() const { return fViewport; }

   // Camera manipulation interface (GL coord - origin bottom left)
   virtual void   Setup(const TGLBoundingBox & box, Bool_t reset=kTRUE) = 0;
   virtual void   Reset() = 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(Double_t xDelta, Double_t yDelta);
   virtual Bool_t Truck(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2) = 0;
   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 Bool_t RotateArcBall(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2);
   virtual Bool_t RotateArcBallRad(Double_t hRotate, Double_t vRotate);

   virtual void   Apply(const TGLBoundingBox & sceneBox, const TGLRect * pickRect = 0) const = 0;

   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(Double_t screenShift, Double_t deltaFactor,
                          Bool_t mod1, Bool_t mod2) const;

   void    SetExternalCenter(Bool_t x);
   Bool_t  GetExternalCenter(){ return fExternalCenter; }

   void    SetCenterVec(Double_t x, Double_t y, Double_t z);
   void    SetCenterVecWarp(Double_t x, Double_t y, Double_t z);
   Double_t* GetCenterVec() { return fCenter->Arr(); }

   void    SetFixDefCenter(Bool_t x) { fFixDefCenter = x; }
   void    SetFixDefCenterVec(Double_t x, Double_t y, Double_t z) { fFDCenter.Set(x, y, z); }
   Double_t* GetFixDefCenterVec() { return fFDCenter.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; }
   // If you manipulate camera ... also call IncTimeStamp() before redraw.
   TGLMatrix& RefCamBase()  { return fCamBase;  }
   TGLMatrix& RefCamTrans() { return fCamTrans; }

   Double_t GetTheta() const;

   TGLMatrix& RefLastNoPickProjM() const { return fLastNoPickProjM; }

   // Current orientation and frustum
   TGLVertex3 EyePoint() const;
   TGLVector3 EyeDirection() const;
   TGLVertex3 FrustumCenter() const;
   const TGLPlane & FrustumPlane(EFrustumPlane plane) const;

   // Overlap / projection / intersection tests
   // Viewport is GL coorinate system - origin bottom/left
   Rgl::EOverlap FrustumOverlap (const TGLBoundingBox & box) const; // box/frustum overlap test
   Rgl::EOverlap ViewportOverlap(const TGLBoundingBox & box) const; // box/viewport overlap test
   TGLRect    ViewportRect   (const TGLBoundingBox & box, TGLBoundingBox::EFace face) const;
   TGLRect    ViewportRect   (const TGLBoundingBox & box, const TGLBoundingBox::EFace * face = 0) const;
   TGLVertex3 WorldToViewport(const TGLVertex3 & worldVertex, TGLMatrix* modviewMat=0) const;
   TGLVector3 WorldDeltaToViewport(const TGLVertex3 & worldRef, const TGLVector3 & worldDelta) const;
   TGLVertex3 ViewportToWorld(const TGLVertex3 & viewportVertex, TGLMatrix* modviewMat=0) const;
   TGLLine3   ViewportToWorld(Double_t viewportX, Double_t viewportY) const;
   TGLLine3   ViewportToWorld(const TPoint & viewport) const;
   TGLVector3 ViewportDeltaToWorld(const TGLVertex3 & worldRef, Double_t viewportXDelta, Double_t viewportYDelta, TGLMatrix* modviewMat=0) const;
   std::pair<Bool_t, TGLVertex3> ViewportPlaneIntersection(Double_t viewportX, Double_t viewportY, const TGLPlane & worldPlane) const;
   std::pair<Bool_t, TGLVertex3> ViewportPlaneIntersection(const TPoint & viewport, const TGLPlane & worldPlane) const;

   // Window to GL viewport conversion - invert Y
   void WindowToViewport(Int_t & /* x */, Int_t & y) const { y = fViewport.Height() - y; }
   void WindowToViewport(TPoint & point)             const { point.SetY(fViewport.Height() - point.GetY()); }
   void WindowToViewport(TGLRect & rect)             const { rect.Y() = fViewport.Height() - rect.Y(); }
   void WindowToViewport(TGLVertex3 & vertex)        const { vertex.Y() = fViewport.Height() - vertex.Y(); }

   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);
   void   ResetInterest();

   // Debuging - draw frustum and interest boxes
   void  DrawDebugAids() const;

   ClassDef(TGLCamera,1); // Camera abstract base class.
};

inline const TGLPlane & TGLCamera::FrustumPlane(EFrustumPlane plane) const
{
   // Return one of the planes forming the camera frustum
   if (fCacheDirty) {
      Error("TGLCamera::FrustumBox()", "cache dirty");
   }
   return fFrustumPlanes[plane];
}


#endif // ROOT_TGLCamera
 TGLCamera.h:1
 TGLCamera.h:2
 TGLCamera.h:3
 TGLCamera.h:4
 TGLCamera.h:5
 TGLCamera.h:6
 TGLCamera.h:7
 TGLCamera.h:8
 TGLCamera.h:9
 TGLCamera.h:10
 TGLCamera.h:11
 TGLCamera.h:12
 TGLCamera.h:13
 TGLCamera.h:14
 TGLCamera.h:15
 TGLCamera.h:16
 TGLCamera.h:17
 TGLCamera.h:18
 TGLCamera.h:19
 TGLCamera.h:20
 TGLCamera.h:21
 TGLCamera.h:22
 TGLCamera.h:23
 TGLCamera.h:24
 TGLCamera.h:25
 TGLCamera.h:26
 TGLCamera.h:27
 TGLCamera.h:28
 TGLCamera.h:29
 TGLCamera.h:30
 TGLCamera.h:31
 TGLCamera.h:32
 TGLCamera.h:33
 TGLCamera.h:34
 TGLCamera.h:35
 TGLCamera.h:36
 TGLCamera.h:37
 TGLCamera.h:38
 TGLCamera.h:39
 TGLCamera.h:40
 TGLCamera.h:41
 TGLCamera.h:42
 TGLCamera.h:43
 TGLCamera.h:44
 TGLCamera.h:45
 TGLCamera.h:46
 TGLCamera.h:47
 TGLCamera.h:48
 TGLCamera.h:49
 TGLCamera.h:50
 TGLCamera.h:51
 TGLCamera.h:52
 TGLCamera.h:53
 TGLCamera.h:54
 TGLCamera.h:55
 TGLCamera.h:56
 TGLCamera.h:57
 TGLCamera.h:58
 TGLCamera.h:59
 TGLCamera.h:60
 TGLCamera.h:61
 TGLCamera.h:62
 TGLCamera.h:63
 TGLCamera.h:64
 TGLCamera.h:65
 TGLCamera.h:66
 TGLCamera.h:67
 TGLCamera.h:68
 TGLCamera.h:69
 TGLCamera.h:70
 TGLCamera.h:71
 TGLCamera.h:72
 TGLCamera.h:73
 TGLCamera.h:74
 TGLCamera.h:75
 TGLCamera.h:76
 TGLCamera.h:77
 TGLCamera.h:78
 TGLCamera.h:79
 TGLCamera.h:80
 TGLCamera.h:81
 TGLCamera.h:82
 TGLCamera.h:83
 TGLCamera.h:84
 TGLCamera.h:85
 TGLCamera.h:86
 TGLCamera.h:87
 TGLCamera.h:88
 TGLCamera.h:89
 TGLCamera.h:90
 TGLCamera.h:91
 TGLCamera.h:92
 TGLCamera.h:93
 TGLCamera.h:94
 TGLCamera.h:95
 TGLCamera.h:96
 TGLCamera.h:97
 TGLCamera.h:98
 TGLCamera.h:99
 TGLCamera.h:100
 TGLCamera.h:101
 TGLCamera.h:102
 TGLCamera.h:103
 TGLCamera.h:104
 TGLCamera.h:105
 TGLCamera.h:106
 TGLCamera.h:107
 TGLCamera.h:108
 TGLCamera.h:109
 TGLCamera.h:110
 TGLCamera.h:111
 TGLCamera.h:112
 TGLCamera.h:113
 TGLCamera.h:114
 TGLCamera.h:115
 TGLCamera.h:116
 TGLCamera.h:117
 TGLCamera.h:118
 TGLCamera.h:119
 TGLCamera.h:120
 TGLCamera.h:121
 TGLCamera.h:122
 TGLCamera.h:123
 TGLCamera.h:124
 TGLCamera.h:125
 TGLCamera.h:126
 TGLCamera.h:127
 TGLCamera.h:128
 TGLCamera.h:129
 TGLCamera.h:130
 TGLCamera.h:131
 TGLCamera.h:132
 TGLCamera.h:133
 TGLCamera.h:134
 TGLCamera.h:135
 TGLCamera.h:136
 TGLCamera.h:137
 TGLCamera.h:138
 TGLCamera.h:139
 TGLCamera.h:140
 TGLCamera.h:141
 TGLCamera.h:142
 TGLCamera.h:143
 TGLCamera.h:144
 TGLCamera.h:145
 TGLCamera.h:146
 TGLCamera.h:147
 TGLCamera.h:148
 TGLCamera.h:149
 TGLCamera.h:150
 TGLCamera.h:151
 TGLCamera.h:152
 TGLCamera.h:153
 TGLCamera.h:154
 TGLCamera.h:155
 TGLCamera.h:156
 TGLCamera.h:157
 TGLCamera.h:158
 TGLCamera.h:159
 TGLCamera.h:160
 TGLCamera.h:161
 TGLCamera.h:162
 TGLCamera.h:163
 TGLCamera.h:164
 TGLCamera.h:165
 TGLCamera.h:166
 TGLCamera.h:167
 TGLCamera.h:168
 TGLCamera.h:169
 TGLCamera.h:170
 TGLCamera.h:171
 TGLCamera.h:172
 TGLCamera.h:173
 TGLCamera.h:174
 TGLCamera.h:175
 TGLCamera.h:176
 TGLCamera.h:177
 TGLCamera.h:178
 TGLCamera.h:179
 TGLCamera.h:180
 TGLCamera.h:181
 TGLCamera.h:182
 TGLCamera.h:183
 TGLCamera.h:184
 TGLCamera.h:185
 TGLCamera.h:186
 TGLCamera.h:187
 TGLCamera.h:188
 TGLCamera.h:189
 TGLCamera.h:190
 TGLCamera.h:191
 TGLCamera.h:192
 TGLCamera.h:193
 TGLCamera.h:194
 TGLCamera.h:195
 TGLCamera.h:196
 TGLCamera.h:197
 TGLCamera.h:198
 TGLCamera.h:199
 TGLCamera.h:200
 TGLCamera.h:201
 TGLCamera.h:202
 TGLCamera.h:203
 TGLCamera.h:204
 TGLCamera.h:205
 TGLCamera.h:206
 TGLCamera.h:207
 TGLCamera.h:208
 TGLCamera.h:209
 TGLCamera.h:210
 TGLCamera.h:211
 TGLCamera.h:212
 TGLCamera.h:213
 TGLCamera.h:214
 TGLCamera.h:215
 TGLCamera.h:216
 TGLCamera.h:217
 TGLCamera.h:218
 TGLCamera.h:219
 TGLCamera.h:220
 TGLCamera.h:221
 TGLCamera.h:222
 TGLCamera.h:223
 TGLCamera.h:224
 TGLCamera.h:225
 TGLCamera.h:226
 TGLCamera.h:227
 TGLCamera.h:228
 TGLCamera.h:229