#include "TVirtualGL.h"
#include "TMath.h"
#include "TGLOrthoCamera.h"
#include "TGLIncludes.h"
#include "TGLUtil.h"
ClassImp(TGLOrthoCamera)
UInt_t   TGLOrthoCamera::fgZoomDeltaSens = 500;
TGLOrthoCamera::TGLOrthoCamera(EType type, const TGLVector3 & hAxis, const TGLVector3 & vAxis) :
   TGLCamera(hAxis, vAxis),
   fType(type),
   fEnableRotate(kFALSE), fDollyToZoom(kTRUE),
   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)
{
   
   Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
}
TGLOrthoCamera::~TGLOrthoCamera()
{
   
}
void TGLOrthoCamera::Setup(const TGLBoundingBox & box, Bool_t reset)
{
   
   
   fVolume = box;
   if (fExternalCenter == kFALSE)
   {
      TGLVertex3 center = box.Center();
      SetCenterVec(center.X(), center.Y(), center.Z());
   }
   if (reset)
      Reset();
}
void TGLOrthoCamera::Reset()
{
   
   
   TGLVector3 e = fVolume.Extents();
   switch (fType) {
      case kXOY: 
      case kXnOY:
      {
         
         fDefXSize = e.X(); fDefYSize = e.Y();
         break;
      }
      case kXOZ:
      case kXnOZ:
      {
         
         fDefXSize = e.X(); fDefYSize = e.Z();
         break;
      }
      case kZOY:
      case kZnOY:
      {
         
         fDefXSize = e.Z(); fDefYSize = e.Y();
         break;
      }
   }
   fDollyDefault  = 1.25*0.5*TMath::Sqrt(3)*fVolume.Extents().Mag();
   fDollyDistance = 0.002 * fDollyDefault;
   fZoom   = fZoomDefault;
   fCamTrans.SetIdentity();
   fCamTrans.MoveLF(1, fDollyDefault);
   IncTimeStamp();
}
Bool_t TGLOrthoCamera::Dolly(Int_t delta, Bool_t mod1, Bool_t mod2)
{
   
   
   
   if (fDollyToZoom) {
      return Zoom(delta, mod1, mod2);
   } else {
      return TGLCamera::Dolly(delta, mod1, mod2);
   }
}
Bool_t TGLOrthoCamera::Zoom(Int_t delta, Bool_t mod1, Bool_t mod2)
{
   
   
   
   
   
   
   
   
   
   
   
   if (AdjustAndClampVal(fZoom, fZoomMin, fZoomMax, -delta*2, fgZoomDeltaSens, mod1, mod2))
   {
      IncTimeStamp();
      return kTRUE;
   }
   else
   {
      return kFALSE;
   }
}
Bool_t TGLOrthoCamera::Truck(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
{
   
   
   Double_t xstep = 2.0 * xDelta / fProjM[0] / fViewport.Width();
   Double_t ystep = 2.0 * yDelta / fProjM[5] / fViewport.Height();
   xstep = AdjustDelta(xstep, 1.0, mod1, mod2);
   ystep = AdjustDelta(ystep, 1.0, mod1, mod2);
   fCamTrans.MoveLF(2, -xstep);
   fCamTrans.MoveLF(3, -ystep);
   IncTimeStamp();
   return kTRUE;
}
Bool_t TGLOrthoCamera::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
{
   
   
   if (fEnableRotate)
      return TGLCamera::Rotate(xDelta, yDelta, mod1, mod2);
   else
      return kFALSE;
}
void TGLOrthoCamera::Apply(const TGLBoundingBox & ,
                           const TGLRect        * pickRect) const
{
   
   
   
   
   
   
   
   
   
   
   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();
   
   if (pickRect)
   {
      TGLRect rect(*pickRect);
      WindowToViewport(rect);
      gluPickMatrix(rect.X(), rect.Y(), rect.Width(), rect.Height(),
                    (Int_t*) fViewport.CArr());
   }
   Double_t halfRangeX, halfRangeY;
   if (fDefYSize*fViewport.Width()/fDefXSize > fViewport.Height()) {
      halfRangeY = 0.5 *fDefYSize;
      halfRangeX = halfRangeY*fViewport.Width()/fViewport.Height();
   } else {
      halfRangeX = 0.5 *fDefXSize;
      halfRangeY = halfRangeX*fViewport.Height()/fViewport.Width();
   }
   halfRangeX /= fZoom;
   halfRangeY /= fZoom;
   fNearClip = 0.05*fDollyDefault;
   fFarClip  = 2.0*fDollyDefault;
   glOrtho(-halfRangeX, halfRangeX,
           -halfRangeY, halfRangeY,
            fNearClip,  fFarClip);
   if (!pickRect) glGetDoublev(GL_PROJECTION_MATRIX, fLastNoPickProjM.Arr());
   
   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);
   gluLookAt(pos[0],    pos[1],    pos[2],
             center[0], center[1], center[2],
             up[0],     up[1],     up[2]);
   if (fCacheDirty) UpdateCache();
}
void TGLOrthoCamera::Configure(Double_t zoom, Double_t dolly, Double_t center[3],
                                     Double_t hRotate, Double_t vRotate)
{
   
   fZoom = zoom;
   SetCenterVec(center[0], center[1], center[2]);
   fCamTrans.MoveLF(1, dolly);
   RotateRad(hRotate, vRotate);
   IncTimeStamp();
}
void TGLOrthoCamera::Markup(TGLCameraMarkupStyle* ms) const
{
   
   Double_t width     = fFrustumPlanes[kLeft].D() + fFrustumPlanes[kRight].D();
   Double_t maxbarw0  = ms->Barsize()*width;
   
   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);
   
   glVertex3d(0, 0.,0.);
   glVertex3d(ms->Barsize()*screenw, 0., 0.);
   
   glVertex3d(ms->Barsize()*screenw,  mH, 0.);
   glVertex3d(ms->Barsize()*screenw, -mH, 0.);
   
   glColor3d(1., 0., 0.);
   glVertex3d(0.,  mH, 0.);
   glVertex3d(0., -mH, 0.);
   
   glVertex3d(screenw*wproc, 0., 0.);
   glVertex3d(screenw*wproc, mH, 0.);
   
   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));
}
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)
{
   
   fOrthoBox[0] = 1.;
   fOrthoBox[1] = 1.;
   fOrthoBox[2] = -1.;
   fOrthoBox[3] = 1.;
}
void TGLOrthoCamera::SetViewport(TGLPaintDevice *dev)
{
   
   Int_t vp[4] = {0};
   dev->ExtractViewport(vp);
   if (vp[2] != Int_t(fViewport.Width()) || vp[3] != Int_t(fViewport.Height()) ||
       vp[0] != fViewport.X() || vp[1] != fViewport.Y())
   {
      fVpChanged = kTRUE;
      fArcBall.SetBounds(vp[2], vp[3]);
      fViewport.Set(vp[0], vp[1], vp[2], vp[3]);
   } else
      fVpChanged = kFALSE;
}
void TGLOrthoCamera::SetViewVolume(const TGLVertex3 *box)
{
   
   fCenter[0] = (box[0].X() + box[1].X()) / 2;
   fCenter[1] = (box[0].Y() + box[2].Y()) / 2;
   fCenter[2] = (box[0].Z() + box[4].Z()) / 2;
   const Double_t maxDim = box[1].X() - box[0].X();
   fOrthoBox[0] = maxDim;
   fOrthoBox[1] = maxDim;
   fOrthoBox[2] = -100 * maxDim;
   fOrthoBox[3] = 100 * maxDim;
   fShift = maxDim * 1.5;
}
void TGLOrthoCamera::StartRotation(Int_t px, Int_t py)
{
   
   fArcBall.Click(TPoint(px, py));
}
void TGLOrthoCamera::RotateCamera(Int_t px, Int_t py)
{
   
   fArcBall.Drag(TPoint(px, py));
}
void TGLOrthoCamera::StartPan(Int_t px, Int_t py)
{
   
   fMousePos.fX = px;
   fMousePos.fY = fViewport.Height() - py;
}
void TGLOrthoCamera::Pan(Int_t px, Int_t py)
{
   
   py = fViewport.Height() - py;
   
   Double_t mv[16] = {0.};
   glGetDoublev(GL_MODELVIEW_MATRIX, mv);
   Double_t pr[16] = {0.};
   glGetDoublev(GL_PROJECTION_MATRIX, pr);
   Int_t vp[] = {0, 0, fViewport.Width(), fViewport.Height()};
   
   TGLVertex3 start, end;
   gluUnProject(fMousePos.fX, fMousePos.fY, 1., mv, pr, vp, &start.X(), &start.Y(), &start.Z());
   gluUnProject(px, py, 1., mv, pr, vp, &end.X(), &end.Y(), &end.Z());
   fTruck += (start - end) /= 2.;
   fMousePos.fX = px;
   fMousePos.fY = py;
}
void TGLOrthoCamera::SetCamera()const
{
   
   glViewport(0, 0, fViewport.Width(), fViewport.Height());
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(
           -fOrthoBox[0] * fZoom,
            fOrthoBox[0] * fZoom,
           -fOrthoBox[1] * fZoom,
            fOrthoBox[1] * fZoom,
            fOrthoBox[2],
            fOrthoBox[3]
          );
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}
void TGLOrthoCamera::Apply()const
{
   
   glTranslated(0., 0., -fShift);
   glMultMatrixd(fArcBall.GetRotMatrix());
   glRotated(45., 1., 0., 0.);
   glRotated(-45., 0., 1., 0.);
   glRotated(-90., 0., 1., 0.);
   glRotated(-90., 1., 0., 0.);
   glTranslated(-fTruck[0], -fTruck[1], -fTruck[2]);
   glTranslated(-fCenter[0], -fCenter[1], -fCenter[2]);
}
Int_t TGLOrthoCamera::GetX()const
{
   
   return fViewport.X();
}
Int_t TGLOrthoCamera::GetY()const
{
   
   return fViewport.Y();
}
Int_t TGLOrthoCamera::GetWidth()const
{
   
   return Int_t(fViewport.Width());
}
Int_t TGLOrthoCamera::GetHeight()const
{
   
   return Int_t(fViewport.Height());
}
void TGLOrthoCamera::ZoomIn()
{
   
   fZoom /= 1.2;
}
void TGLOrthoCamera::ZoomOut()
{
   
   fZoom *= 1.2;
}
Last change: Tue May 13 17:12:48 2008
Last generated: 2008-05-13 17:12
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.