28 ClassImp(TGLRotateManip);
33 Double_t TGLRotateManip::Angle(
const TGLVector3& v1,
const TGLVector3& v2)
35 return TMath::ACos(Dot(v1, v2) / (v1.Mag() * v2.Mag()));
43 Double_t TGLRotateManip::Angle(
const TGLVector3& v1,
const TGLVector3& v2,
44 const TGLVector3& ref)
46 TGLVector3 cross = Cross(v1, v2);
47 if (Dot(cross,ref) > 0.0) {
50 return -Angle(v1, v2);
57 TGLRotateManip::TGLRotateManip() :
58 fShallowRing(kFALSE), fShallowFront(kTRUE),
59 fActiveRingPlane(TGLVector3(1.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
60 fActiveRingCenter(TGLVertex3(0.0, 0.0, 0.0)),
61 fRingLine(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
62 fRingLineOld(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0))
69 TGLRotateManip::TGLRotateManip(TGLPhysicalShape* shape) :
71 fShallowRing(kFALSE), fShallowFront(kTRUE),
72 fActiveRingPlane(TGLVector3(1.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
73 fActiveRingCenter(TGLVertex3(0.0, 0.0, 0.0)),
74 fRingLine(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
75 fRingLineOld(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0))
82 TGLRotateManip::~TGLRotateManip()
92 void TGLRotateManip::Draw(
const TGLCamera& camera)
const
99 const TGLBoundingBox& box = fShape->BoundingBox();
101 TGLVector3 axisScale[3];
102 CalcDrawScale(box, camera, baseScale, axisScale);
103 Double_t ringRadius = baseScale*10.0;
106 TGLPhysicalShape::EManip manip = fShape->GetManip();
109 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
110 glDisable(GL_CULL_FACE);
112 TGLUtil::TDrawQualityScaler hiRes(3);
117 if (manip & TGLPhysicalShape::kRotateX) {
119 TGLUtil::DrawRing(box.Center(), box.Axis(0, kTRUE), ringRadius*1.004, ColorFor(1));
122 TGLUtil::DrawRing(box.Center(), box.Axis(0, kTRUE), ringRadius*1.004, TGLUtil::fgGrey);
124 if (manip & TGLPhysicalShape::kRotateY) {
126 TGLUtil::DrawRing(box.Center(), box.Axis(1, kTRUE), ringRadius*1.002, ColorFor(2));
129 TGLUtil::DrawRing(box.Center(), box.Axis(1, kTRUE), ringRadius*1.002, TGLUtil::fgGrey);
131 if (manip & TGLPhysicalShape::kRotateZ) {
133 TGLUtil::DrawRing(box.Center(), box.Axis(2, kTRUE), ringRadius, ColorFor(3));
136 TGLUtil::DrawRing(box.Center(), box.Axis(2, kTRUE), ringRadius, TGLUtil::fgGrey);
139 TGLUtil::DrawSphere(box.Center(), ringRadius/20.0, TGLUtil::fgWhite);
145 TGLVertex3 eyeOnRing;
147 eyeOnRing = fActiveRingCenter - (camera.EyeDirection()*ringRadius);
149 eyeOnRing = fActiveRingCenter + (camera.EyeDirection()*ringRadius);
152 eyeOnRing = fActiveRingPlane.NearestOn(eyeOnRing);
153 TGLVector3 arrowDir = Cross(fActiveRingPlane.Norm(), eyeOnRing - fActiveRingCenter);
154 arrowDir.Normalise();
155 TGLUtil::DrawLine(eyeOnRing, arrowDir*ringRadius*1.3, TGLUtil::kLineHeadArrow, baseScale, TGLUtil::fgYellow);
156 TGLUtil::DrawLine(eyeOnRing, -arrowDir*ringRadius*1.3, TGLUtil::kLineHeadArrow, baseScale, TGLUtil::fgYellow);
158 TGLVector3 activeVector = fRingLine.Vector();
159 activeVector.Normalise();
160 activeVector *= ringRadius;
161 TGLUtil::DrawLine(fRingLine.Start(), activeVector,
162 TGLUtil::kLineHeadNone, baseScale, TGLUtil::fgYellow);
166 glEnable(GL_CULL_FACE);
174 Bool_t TGLRotateManip::HandleButton(
const Event_t& event,
const TGLCamera& camera)
176 Bool_t captured = TGLManip::HandleButton(event, camera);
180 UInt_t axisIndex = fSelectedWidget - 1;
181 TGLVector3 widgetAxis = fShape->BoundingBox().Axis(axisIndex, kTRUE);
184 fActiveRingPlane.Set(widgetAxis, fShape->BoundingBox().Center());
185 fActiveRingCenter.Set(fShape->BoundingBox().Center());
187 fRingLineOld = fRingLine = CalculateRingLine(fLastMouse, camera);
191 Double_t planeEyeAngle = Angle(fActiveRingPlane.Norm(), camera.EyeDirection()) - TMath::ASin(1.0);
192 Double_t shallowDelta = 0.15;
193 if ((planeEyeAngle > -shallowDelta) && (planeEyeAngle < shallowDelta)) {
194 fShallowRing = kTRUE;
200 fShallowFront = kTRUE;
209 fShallowRing = kFALSE;
221 Bool_t TGLRotateManip::HandleMotion(
const Event_t& event,
const TGLCamera& camera)
224 TPoint newMouse(event.fX, event.fY);
227 Double_t angle = CalculateAngleDelta(newMouse, camera);
228 fShape->Rotate(fActiveRingCenter, fActiveRingPlane.Norm(), angle);
229 fLastMouse = newMouse;
238 Double_t TGLRotateManip::CalculateAngleDelta(
const TPoint& mouse,
const TGLCamera& camera)
241 std::pair<Bool_t, TGLLine3> nearLineIntersection = Intersection(fActiveRingPlane,
242 camera.FrustumPlane(TGLCamera::kNear));
243 if (!nearLineIntersection.first) {
244 Error(
"TGLRotateManip::CalculateAngleDelta",
"active ring plane parallel to near clip?");
247 TGLLine3 nearLine = nearLineIntersection.second;
248 TGLVector3 activePlaneNear = camera.WorldDeltaToViewport(nearLine.Start(), nearLine.Vector());
249 activePlaneNear.Normalise();
250 TGLVector3 mouseDelta(mouse.GetX() - fLastMouse.GetX(),
251 -(mouse.GetY() - fLastMouse.GetY()),
254 Double_t angle = Dot(activePlaneNear, mouseDelta) / 150.0;
261 fRingLineOld = fRingLine;
262 fRingLine = CalculateRingLine(fLastMouse, camera);
263 return Angle(fRingLineOld.Vector(), fRingLine.Vector(), fActiveRingPlane.Norm());
272 TGLLine3 TGLRotateManip::CalculateRingLine(
const TPoint& mouse,
const TGLCamera& camera)
const
275 TPoint mouseViewport(mouse);
276 camera.WindowToViewport(mouseViewport);
279 TGLLine3 viewportProjection = camera.ViewportToWorld(mouseViewport);
282 std::pair<Bool_t, TGLVertex3> ringPlaneInter = Intersection(fActiveRingPlane, viewportProjection, kTRUE);
286 if (!ringPlaneInter.first) {
287 return TGLLine3(fActiveRingCenter, -camera.EyeDirection());
289 return TGLLine3(fActiveRingCenter, ringPlaneInter.second);