00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TGLRotateManip.h"
00013 #include "TGLPhysicalShape.h"
00014 #include "TGLCamera.h"
00015 #include "TGLIncludes.h"
00016 #include "TMath.h"
00017 #include "TError.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 ClassImp(TGLRotateManip);
00028
00029
00030 Double_t TGLRotateManip::Angle(const TGLVector3& v1, const TGLVector3& v2)
00031 {
00032
00033 return TMath::ACos(Dot(v1, v2) / (v1.Mag() * v2.Mag()));
00034 }
00035
00036
00037 Double_t TGLRotateManip::Angle(const TGLVector3& v1, const TGLVector3& v2,
00038 const TGLVector3& ref)
00039 {
00040
00041
00042
00043 TGLVector3 cross = Cross(v1, v2);
00044 if (Dot(cross,ref) > 0.0) {
00045 return Angle(v1, v2);
00046 } else {
00047 return -Angle(v1, v2);
00048 }
00049 }
00050
00051
00052 TGLRotateManip::TGLRotateManip() :
00053 fShallowRing(kFALSE), fShallowFront(kTRUE),
00054 fActiveRingPlane(TGLVector3(1.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
00055 fActiveRingCenter(TGLVertex3(0.0, 0.0, 0.0)),
00056 fRingLine(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
00057 fRingLineOld(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0))
00058 {
00059
00060 }
00061
00062
00063 TGLRotateManip::TGLRotateManip(TGLPhysicalShape* shape) :
00064 TGLManip(shape),
00065 fShallowRing(kFALSE), fShallowFront(kTRUE),
00066 fActiveRingPlane(TGLVector3(1.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
00067 fActiveRingCenter(TGLVertex3(0.0, 0.0, 0.0)),
00068 fRingLine(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0)),
00069 fRingLineOld(TGLVertex3(0.0, 0.0, 0.0), TGLVertex3(0.0, 0.0, 0.0))
00070 {
00071
00072 }
00073
00074
00075 TGLRotateManip::~TGLRotateManip()
00076 {
00077
00078 }
00079
00080
00081 void TGLRotateManip::Draw(const TGLCamera& camera) const
00082 {
00083
00084
00085
00086
00087
00088 if (!fShape) {
00089 return;
00090 }
00091
00092
00093 const TGLBoundingBox& box = fShape->BoundingBox();
00094 Double_t baseScale;
00095 TGLVector3 axisScale[3];
00096 CalcDrawScale(box, camera, baseScale, axisScale);
00097 Double_t ringRadius = baseScale*10.0;
00098
00099
00100 TGLPhysicalShape::EManip manip = fShape->GetManip();
00101
00102 glEnable(GL_BLEND);
00103 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00104 glDisable(GL_CULL_FACE);
00105
00106 TGLUtil::TDrawQualityScaler hiRes(3);
00107
00108
00109
00110
00111 if (manip & TGLPhysicalShape::kRotateX) {
00112 glPushName(1);
00113 TGLUtil::DrawRing(box.Center(), box.Axis(0, kTRUE), ringRadius*1.004, ColorFor(1));
00114 glPopName();
00115 } else {
00116 TGLUtil::DrawRing(box.Center(), box.Axis(0, kTRUE), ringRadius*1.004, TGLUtil::fgGrey);
00117 }
00118 if (manip & TGLPhysicalShape::kRotateY) {
00119 glPushName(2);
00120 TGLUtil::DrawRing(box.Center(), box.Axis(1, kTRUE), ringRadius*1.002, ColorFor(2));
00121 glPopName();
00122 } else {
00123 TGLUtil::DrawRing(box.Center(), box.Axis(1, kTRUE), ringRadius*1.002, TGLUtil::fgGrey);
00124 }
00125 if (manip & TGLPhysicalShape::kRotateZ) {
00126 glPushName(3);
00127 TGLUtil::DrawRing(box.Center(), box.Axis(2, kTRUE), ringRadius, ColorFor(3));
00128 glPopName();
00129 } else {
00130 TGLUtil::DrawRing(box.Center(), box.Axis(2, kTRUE), ringRadius, TGLUtil::fgGrey);
00131 }
00132
00133 TGLUtil::DrawSphere(box.Center(), ringRadius/20.0, TGLUtil::fgWhite);
00134
00135
00136
00137 if (fActive) {
00138 if (fShallowRing) {
00139 TGLVertex3 eyeOnRing;
00140 if (fShallowFront) {
00141 eyeOnRing = fActiveRingCenter - (camera.EyeDirection()*ringRadius);
00142 } else {
00143 eyeOnRing = fActiveRingCenter + (camera.EyeDirection()*ringRadius);
00144 }
00145
00146 eyeOnRing = fActiveRingPlane.NearestOn(eyeOnRing);
00147 TGLVector3 arrowDir = Cross(fActiveRingPlane.Norm(), eyeOnRing - fActiveRingCenter);
00148 arrowDir.Normalise();
00149 TGLUtil::DrawLine(eyeOnRing, arrowDir*ringRadius*1.3, TGLUtil::kLineHeadArrow, baseScale, TGLUtil::fgYellow);
00150 TGLUtil::DrawLine(eyeOnRing, -arrowDir*ringRadius*1.3, TGLUtil::kLineHeadArrow, baseScale, TGLUtil::fgYellow);
00151 } else {
00152 TGLVector3 activeVector = fRingLine.Vector();
00153 activeVector.Normalise();
00154 activeVector *= ringRadius;
00155 TGLUtil::DrawLine(fRingLine.Start(), activeVector,
00156 TGLUtil::kLineHeadNone, baseScale, TGLUtil::fgYellow);
00157 }
00158 }
00159
00160 glEnable(GL_CULL_FACE);
00161 glDisable(GL_BLEND);
00162 }
00163
00164
00165 Bool_t TGLRotateManip::HandleButton(const Event_t& event, const TGLCamera& camera)
00166 {
00167
00168
00169
00170 Bool_t captured = TGLManip::HandleButton(event, camera);
00171
00172 if (captured) {
00173
00174 UInt_t axisIndex = fSelectedWidget - 1;
00175 TGLVector3 widgetAxis = fShape->BoundingBox().Axis(axisIndex, kTRUE);
00176
00177
00178 fActiveRingPlane.Set(widgetAxis, fShape->BoundingBox().Center());
00179 fActiveRingCenter.Set(fShape->BoundingBox().Center());
00180
00181 fRingLineOld = fRingLine = CalculateRingLine(fLastMouse, camera);
00182
00183
00184
00185 Double_t planeEyeAngle = Angle(fActiveRingPlane.Norm(), camera.EyeDirection()) - TMath::ASin(1.0);
00186 Double_t shallowDelta = 0.15;
00187 if ((planeEyeAngle > -shallowDelta) && (planeEyeAngle < shallowDelta)) {
00188 fShallowRing = kTRUE;
00189
00190
00191
00192
00193
00194 fShallowFront = kTRUE;
00195
00196
00197
00198
00199
00200
00201
00202 } else {
00203 fShallowRing = kFALSE;
00204 }
00205 }
00206
00207 return captured;
00208 }
00209
00210
00211 Bool_t TGLRotateManip::HandleMotion(const Event_t& event, const TGLCamera& camera)
00212 {
00213
00214
00215
00216
00217 if (fActive) {
00218 TPoint newMouse(event.fX, event.fY);
00219
00220
00221 Double_t angle = CalculateAngleDelta(newMouse, camera);
00222 fShape->Rotate(fActiveRingCenter, fActiveRingPlane.Norm(), angle);
00223 fLastMouse = newMouse;
00224 return kTRUE;
00225 }
00226 return kFALSE;
00227 }
00228
00229
00230 Double_t TGLRotateManip::CalculateAngleDelta(const TPoint& mouse, const TGLCamera& camera)
00231 {
00232
00233
00234 if (fShallowRing) {
00235 std::pair<Bool_t, TGLLine3> nearLineIntersection = Intersection(fActiveRingPlane,
00236 camera.FrustumPlane(TGLCamera::kNear));
00237 if (!nearLineIntersection.first) {
00238 Error("TGLRotateManip::CalculateAngleDelta", "active ring plane parallel to near clip?");
00239 return 1.0;
00240 }
00241 TGLLine3 nearLine = nearLineIntersection.second;
00242 TGLVector3 activePlaneNear = camera.WorldDeltaToViewport(nearLine.Start(), nearLine.Vector());
00243 activePlaneNear.Normalise();
00244 TGLVector3 mouseDelta(mouse.GetX() - fLastMouse.GetX(),
00245 -(mouse.GetY() - fLastMouse.GetY()),
00246 0.0);
00247
00248 Double_t angle = Dot(activePlaneNear, mouseDelta) / 150.0;
00249 if (fShallowFront) {
00250 return -angle;
00251 } else {
00252 return angle;
00253 }
00254 } else {
00255 fRingLineOld = fRingLine;
00256 fRingLine = CalculateRingLine(fLastMouse, camera);
00257 return Angle(fRingLineOld.Vector(), fRingLine.Vector(), fActiveRingPlane.Norm());
00258 }
00259 }
00260
00261
00262 TGLLine3 TGLRotateManip::CalculateRingLine(const TPoint& mouse, const TGLCamera& camera) const
00263 {
00264
00265
00266
00267
00268
00269 TPoint mouseViewport(mouse);
00270 camera.WindowToViewport(mouseViewport);
00271
00272
00273 TGLLine3 viewportProjection = camera.ViewportToWorld(mouseViewport);
00274
00275
00276 std::pair<Bool_t, TGLVertex3> ringPlaneInter = Intersection(fActiveRingPlane, viewportProjection, kTRUE);
00277
00278
00279
00280 if (!ringPlaneInter.first) {
00281 return TGLLine3(fActiveRingCenter, -camera.EyeDirection());
00282 }
00283 return TGLLine3(fActiveRingCenter, ringPlaneInter.second);
00284 }
00285