// @(#)root/gl:$Name:  $:$Id: TGLPerspectiveCamera.cxx,v 1.5 2005/06/21 16:54:17 brun Exp $
// Author:  Richard Maunder  25/05/2005

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

// TODO: Function descriptions
// TODO: Class def - same as header

#include "TGLPerspectiveCamera.h"
#include "TGLUtil.h"
#include "TGLIncludes.h"

#include "TMath.h"
#include "TError.h"

// TODO: Find somewhere else
#define PI 3.141592654

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() :
   fDollyMin(1.0), fDollyDefault(10.0), fDollyMax(100.0),
   fFOV(fgFOVDefault), fDolly(fDollyDefault), 
   fVRotate(0.0), fHRotate(0.0), 
   fCenter(0.0, 0.0, 0.0), fTruck(0.0, 0.0, 0.0)
{
   Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
}

//______________________________________________________________________________
 TGLPerspectiveCamera::~TGLPerspectiveCamera()
{
}

//______________________________________________________________________________
 void TGLPerspectiveCamera::Setup(const TGLBoundingBox & box)
{
   // Setup camera limits based on supplied bounding box.

   fCenter = box.Center();

   // 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 += nextLongest/2.0;
   fDollyMin = -fDollyDefault;
   fDollyDefault *= 1.5;
   fDollyMax = fDollyDefault * 3.0;

   Reset();
}

//______________________________________________________________________________
 void TGLPerspectiveCamera::Reset()
{
   fFOV = fgFOVDefault;
   fHRotate = 0.0;
   fVRotate = -90.0;
   fTruck.Set(-fCenter.X(), -fCenter.Y(), -fCenter.Z());
   fDolly = fDollyDefault;
   fCacheDirty = kTRUE;
}

//______________________________________________________________________________
 Bool_t TGLPerspectiveCamera::Zoom(Int_t shift, Bool_t mod1, Bool_t mod2)
{
   if (AdjustAndClampVal(fFOV, fgFOVMin, fgFOVMax, shift, fgFOVDeltaSens, mod1, mod2)) {
      fCacheDirty = kTRUE;
      return kTRUE;
   } else {
      return kFALSE;
   }
}

//______________________________________________________________________________
 Bool_t TGLPerspectiveCamera::Dolly(Int_t shift, Bool_t mod1, Bool_t mod2)
{
   if (AdjustAndClampVal(fDolly, fDollyMin, fDollyMax, shift, fgDollyDeltaSens, mod1, mod2)) {
      fCacheDirty = kTRUE;
      return kTRUE;
   } else {
      return kFALSE;
   }
}

//______________________________________________________________________________
 Bool_t TGLPerspectiveCamera::Truck(Int_t x, Int_t y, Int_t xDelta, Int_t yDelta)
{
   //TODO: Convert TGLRect so this not required
   GLint viewport[4] = { fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height() };
   TGLVertex3 start, end;

   gluUnProject(x, y, 1.0, fModVM.CArr(), fProjM.CArr(), viewport, &start.X(), &start.Y(), &start.Z());
   gluUnProject(x + xDelta, y + yDelta, 1.0, fModVM.CArr(), fProjM.CArr(), viewport, &end.X(), &end.Y(), &end.Z());
   TGLVector3 truckDelta = end - start;
   fTruck = fTruck + truckDelta/2.0;
   fCacheDirty = kTRUE;
   return kTRUE;
}

//______________________________________________________________________________
 Bool_t TGLPerspectiveCamera::Rotate(Int_t xShift, Int_t yShift)
{
   fHRotate += static_cast<float>(xShift)/fViewport.Width() * 360.0;
   fVRotate -= static_cast<float>(yShift)/fViewport.Height() * 180.0;
   if ( fVRotate > 0.0 ) {
      fVRotate = 0.0;
   }
   if ( fVRotate < -180.0 ) {
      fVRotate = -180.0;
   }

   fCacheDirty = kTRUE;
   return kTRUE;
}

//______________________________________________________________________________
 void TGLPerspectiveCamera::Apply(const TGLBoundingBox & box, const TGLRect * pickRect)
{
   glViewport(fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height());

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();

   // Load up any picking rect
   if (pickRect) {
      //TODO: Convert TGLRect so this not required
      GLint viewport[4] = { fViewport.X(), fViewport.Y(), fViewport.Width(), fViewport.Height() };
      gluPickMatrix(pickRect->X(), pickRect->Y(),
                    pickRect->Width(), pickRect->Height(),
                    viewport);
   }

   if(fViewport.Width() == 0 || fViewport.Height() == 0) {
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
   } else {
      Double_t boxDiag = box.Extents().Mag();
      Double_t nearClip = TMath::Abs(fDolly) - (boxDiag/2.0);
      if (nearClip < 3.0) {
         nearClip = 3.0;
      }
      Double_t farClip = nearClip + boxDiag;

      gluPerspective(fFOV, fViewport.Aspect(), nearClip, farClip);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glTranslated(0, 0, -fDolly);
      glRotated(fVRotate, 1.0, 0.0, 0.0);
      glRotated(fHRotate, 0.0, 0.0, 1.0);
      glRotated(90, 0.0, 1.0, 0.0);
      glTranslated(fTruck[0], fTruck[1], fTruck[2]);

      // Tracing
      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", nearClip, farClip);
      }
   }

   if (fCacheDirty) {
      UpdateCache();
   }
}




ROOT page - Class index - Class Hierarchy - Top of the page

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.