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