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);