// @(#)root/gl:$Name: $:$Id: TGLOrthoCamera.cxx,v 1.13 2006/01/26 11:59:41 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. *
*************************************************************************/
#include "Riostream.h"
#include "TGLOrthoCamera.h"
#include "TGLUtil.h"
#include "TGLIncludes.h"
#include "TMath.h"
//////////////////////////////////////////////////////////////////////////
// //
// TGLOrthoCamera //
// //
// Orthographic projection camera. Currently limited to three types //
// defined at construction time - kXOY, kXOZ, kZOY - where this refers //
// to the viewport plane axis - e.g. kXOY has X axis horizontal, Y //
// vertical - i.e. looking down Z axis with Y vertical. //
//
// The plane types restriction could easily be removed to supported //
// arbitary ortho projections along any axis/orientation with free //
// rotations about them. //
// //
//////////////////////////////////////////////////////////////////////////
ClassImp(TGLOrthoCamera)
UInt_t TGLOrthoCamera::fgZoomDeltaSens = 500;
//______________________________________________________________________________
TGLOrthoCamera::TGLOrthoCamera(EType type) :
fType(type), 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), fMatrix()
{
// 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)
//
Setup(TGLBoundingBox(TGLVertex3(-100,-100,-100), TGLVertex3(100,100,100)));
}
//______________________________________________________________________________
TGLOrthoCamera::~TGLOrthoCamera()
{
// Destroy orthographic camera
}
//______________________________________________________________________________
void TGLOrthoCamera::Setup(const TGLBoundingBox & box)
{
// 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. };
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;
}
}
Reset();
}
//______________________________________________________________________________
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;
fCacheDirty = kTRUE;
}
//______________________________________________________________________________
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.
// TODO: Bring all mouse handling into camera classes - would simplify interface and
// remove these non-generic cases.
return Zoom(delta, mod1, mod2);
}
//______________________________________________________________________________
Bool_t TGLOrthoCamera::Zoom (Int_t delta, Bool_t mod1, Bool_t mod2)
{
// Zoom the camera - 'adjust lens focal length, retaining camera position'.
// Arguments are:
//
// 'delta' - mouse viewport delta (pixels) - +ive zoom in, -ive zoom 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.
// 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))
{
fCacheDirty = kTRUE;
return kTRUE;
}
else
{
return kFALSE;
}
}
//______________________________________________________________________________
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);
fCacheDirty = kTRUE;
return kTRUE;
}
//______________________________________________________________________________
Bool_t TGLOrthoCamera::Rotate(Int_t /*xDelta*/, Int_t /*yDelta*/)
{
// 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;
}
//______________________________________________________________________________
void TGLOrthoCamera::Apply(const TGLBoundingBox & /*box*/, const TGLRect * pickRect) const
{
// Apply the camera to the current GL context, setting the viewport, projection
// and modelview matricies. After this verticies etc can be directly entered
// in the world frame. This also updates the cached frustum values, enabling
// all the projection, overlap tests etc defined in TGLCamera to be used.
//
// Arguments are:
// 'box' - view volume box - ignored for ortho camera. Assumed to be same
// 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());
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();
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;
} else {
halfRange = height / 2.0;
}
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);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScaled(1.0 / fViewport.Aspect(), 1.0, 1.0);
// Debug aid - show current volume
/*glDisable(GL_LIGHTING);
glColor3d(0.0, 0.0, 1.0);
fVolume.Draw();
glEnable(GL_LIGHTING);*/
glMultMatrixd(fMatrix.CArr());
glTranslated(fTruck.X(), fTruck.Y(), fTruck.Z());
if (fCacheDirty) {
UpdateCache();
}
}
//______________________________________________________________________________
void TGLOrthoCamera::Configure(Double_t left, Double_t right,
Double_t top, Double_t bottom)
{
// 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;
}
fCacheDirty = kTRUE;
}
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.