Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveLegoEventHandler.cxx
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
3  * All rights reserved. *
4  * *
5  * For the licensing terms see $ROOTSYS/LICENSE. *
6  * For the list of contributors see $ROOTSYS/README/CREDITS. *
7  *************************************************************************/
8 
9 
10 #include "TEveLegoEventHandler.h"
11 #include "TEveCaloLegoGL.h"
12 
13 #include "TGLViewer.h"
14 #include "TGLWidget.h"
15 #include "TGLOverlay.h"
16 #include "TGLLogicalShape.h"
17 #include "TGLPhysicalShape.h"
18 #include "TGLCamera.h"
19 #include "TGLPerspectiveCamera.h"
20 #include "TGLOrthoCamera.h"
21 #include "KeySymbols.h"
22 
23 #include "TMath.h"
24 #include "TGLUtil.h"
25 #include "TEveTrans.h"
26 
27 #include "TEveCalo.h"
28 
29 /** \class TEveLegoEventHandler
30 \ingroup TEve
31 A base class of TGLEventHandler. Switches current camera from perspective
32 to orthographic bird-view, if camera theta is less than given threshold. It sets back
33 perspective camera when accumulated angle is more than transition theta.
34 */
35 
36 ClassImp(TEveLegoEventHandler);
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Constructor.
40 
41 TEveLegoEventHandler::TEveLegoEventHandler(TGWindow *w, TObject *obj, TEveCaloLego *lego):
42  TGLEventHandler(w, obj),
43 
44  fMode(kFree),
45  fTransTheta(0.5f),
46  fTheta(0.f),
47 
48  fLego(lego)
49 {
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Virtual from TGLEventHandler.
54 /// Free the camera when home is pressed.
55 
56 Bool_t TEveLegoEventHandler::HandleKey(Event_t *event)
57 {
58  if (event->fCode == kKey_Home)
59  fMode = kFree;
60 
61  return TGLEventHandler::HandleKey(event);
62 }
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Method to handle action TGLViewer::kDragCameraRotate. It switches from standard perspective
66 /// view to bird-view bellow angle fTransTheta and restores view when accumulated theta is larger
67 /// than transition angle.
68 
69 Bool_t TEveLegoEventHandler::Rotate(Int_t xDelta, Int_t yDelta, Bool_t mod1, Bool_t mod2)
70 {
71  if ( !fLego ) return TGLEventHandler::Rotate(xDelta, yDelta, mod1, mod2);
72 
73  TGLCamera &cam = fGLViewer->GetRnrCtx()->RefCamera();
74  Double_t hRotate = cam.AdjustDelta(-yDelta, TMath::Pi()/cam.RefViewport().Height(), mod1, mod2);
75 
76  // get lego bounding box
77  Float_t *bb = fLego->AssertBBox();
78  TGLBoundingBox box;
79  box.SetAligned(TGLVertex3(bb[0], bb[2], bb[4]), TGLVertex3(bb[1], bb[3], bb[5]));
80  box.Transform(fLego->RefMainTrans().Array());
81 
82  Bool_t camChanged = kFALSE;
83 
84  if (cam.IsOrthographic())
85  {
86  fTheta += hRotate;
87  if (fTheta < 0) fTheta = 0;
88  if (fTheta > fTransTheta)
89  {
90  TGLCamera* ortho = &cam;
91  Double_t l = -ortho->FrustumPlane(TGLCamera::kLeft).D();
92  Double_t r = ortho->FrustumPlane(TGLCamera::kRight).D();
93  Double_t t = ortho->FrustumPlane(TGLCamera::kTop).D();
94  Double_t b = -ortho->FrustumPlane(TGLCamera::kBottom).D();
95 
96  fGLViewer->SetCurrentCamera(TGLViewer::kCameraPerspXOY);
97  TGLPerspectiveCamera* persp = dynamic_cast<TGLPerspectiveCamera*>(&fGLViewer->GetRnrCtx()->RefCamera());
98  persp->Setup(box, kTRUE);
99 
100  TGLVector3 extents = box.Extents();
101  Int_t sortInd[3];
102  TMath::Sort(3, extents.CArr(), sortInd);
103  Double_t size = TMath::Hypot(extents[sortInd[0]], extents[sortInd[1]]);
104  Double_t dolly = size / (2.0*TMath::Tan(30*TMath::Pi()/360));
105  Double_t fov = TMath::ATan(TMath::Hypot(t-b, r-l)/(2*dolly));
106 
107  persp->SetCenterVecWarp(0.5*(l+r), 0.5*(t+b), 0);
108 
109  Double_t vR = -0.5 * TMath::Pi(); // switch XY
110  Double_t hR = -0.5 * TMath::Pi() + fTransTheta; // fix top view angle
111  persp->Configure(fov*TMath::RadToDeg(), 0, 0, hR, vR);
112 
113  fMode = kFree;
114  camChanged = kTRUE;
115  }
116  }
117  else
118  {
119  Double_t theta = cam.GetTheta();
120  Double_t thetaN = theta + hRotate;
121  if (thetaN > TMath::Pi() - cam.GetVAxisMinAngle()) thetaN = TMath::Pi() - cam.GetVAxisMinAngle();
122  else if (thetaN < cam.GetVAxisMinAngle()) thetaN = cam.GetVAxisMinAngle();
123 
124  fTheta = thetaN;
125 
126  if (thetaN < fTransTheta)
127  {
128  TGLPerspectiveCamera* persp = (TGLPerspectiveCamera*)(&cam);
129  fGLViewer->SetCurrentCamera(TGLViewer::kCameraOrthoXOY);
130  TGLOrthoCamera* ortho = dynamic_cast<TGLOrthoCamera*>(& fGLViewer->GetRnrCtx()->RefCamera());
131  ortho->Setup(box, kTRUE);
132 
133  // translation to the plane intersect
134  const TGLMatrix& mx = cam.GetCamBase() * cam.GetCamTrans();
135  TGLVertex3 d = mx.GetTranslation();
136  TGLVertex3 p = d + mx.GetBaseVec(1);
137  TGLLine3 line(d, p);
138  const TGLPlane rp = TGLPlane(cam.GetCamBase().GetBaseVec(3), TGLVertex3());
139  std::pair<Bool_t, TGLVertex3> intersection;
140  intersection = Intersection(rp, line, kTRUE);
141  TGLVertex3 v = intersection.second;
142  ortho->Truck( v.X() - box.Center().X(), v.Y() - box.Center().Y());
143 
144  // zoom
145  Double_t t = persp->FrustumPlane(TGLCamera::kTop).D();
146  Double_t b = -persp->FrustumPlane(TGLCamera::kBottom).D();
147  Double_t zoom = box.Extents().Y()/(t-b);
148  ortho->Configure(zoom, 0, 0, 0, 0);
149 
150  fMode = kLocked;
151  camChanged = kTRUE;
152  }
153  else
154  {
155  camChanged = fGLViewer->CurrentCamera().Rotate(xDelta, -yDelta, mod1, mod2);
156  }
157  }
158  return camChanged;
159 }