TGLCameraOverlay.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLCameraOverlay.cxx 35013 2010-08-25 14:28:19Z matevz $
00002 // Author: Alja Mrak-Tadel 2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TGLIncludes.h"
00013 #include "TGLCameraOverlay.h"
00014 #include "TGLViewer.h"
00015 #include "TGLCamera.h"
00016 #include "TGLSelectRecord.h"
00017 #include "TGLUtil.h"
00018 #include "TGLRnrCtx.h"
00019 #include "TGLAxisPainter.h"
00020 
00021 #include "TMath.h"
00022 #include "TAxis.h"
00023 #include "THLimitsFinder.h"
00024 
00025 //______________________________________________________________________________
00026 // A GL overlay element which displays camera furstum.
00027 //
00028 
00029 ClassImp(TGLCameraOverlay);
00030 
00031 //______________________________________________________________________________
00032 TGLCameraOverlay::TGLCameraOverlay(Bool_t showOrtho, Bool_t showPersp) :
00033    TGLOverlayElement(),
00034 
00035    fShowOrthographic(showOrtho),
00036    fShowPerspective(showPersp),
00037 
00038    fOrthographicMode(kAxis),
00039    fPerspectiveMode(kPlaneIntersect),
00040 
00041    fAxisPainter(0),
00042    fAxis(0),
00043    fAxisExtend(0.9),
00044    fUseAxisColors(kFALSE),
00045 
00046    fExternalRefPlane(),
00047    fUseExternalRefPlane(kFALSE)
00048 {
00049    // Constructor.
00050 
00051    fFrustum[0] = fFrustum[1] = fFrustum[2] = fFrustum[3] = 0;
00052 
00053    fAxis = new TAxis();
00054    fAxis->SetNdivisions(710);
00055    fAxis->SetLabelSize(0.018);
00056    fAxis->SetLabelOffset(0.01);
00057    fAxis->SetAxisColor(kGray+1);
00058    fAxis->SetLabelColor(kGray+1);
00059 
00060    fAxisPainter = new TGLAxisPainter();
00061    fAxisPainter->SetFontMode(TGLFont::kBitmap);
00062    fAxisPainter->SetUseAxisColors(kFALSE);
00063 }
00064 
00065 //______________________________________________________________________________
00066 TGLCameraOverlay::~TGLCameraOverlay()
00067 {
00068    // Destructor.
00069 
00070    delete  fAxisPainter;
00071    delete  fAxis;
00072 }
00073 
00074 //______________________________________________________________________________
00075 TAttAxis* TGLCameraOverlay::GetAttAxis()
00076 {
00077    // Get axis attributes.
00078 
00079    return dynamic_cast<TAttAxis*>(fAxis);
00080 }
00081 
00082 //______________________________________________________________________________
00083 void TGLCameraOverlay::SetFrustum(TGLCamera& cam)
00084 {
00085    // Set frustum values from given camera.
00086 
00087    TGLVector3 absRef(1., 1., 1.); // needed in case if orthographic camera is negative
00088    Float_t l = -cam.FrustumPlane(TGLCamera::kLeft).D()  * Dot(cam.GetCamBase().GetBaseVec(2), absRef);
00089    Float_t r =  cam.FrustumPlane(TGLCamera::kRight).D() * Dot(cam.GetCamBase().GetBaseVec(2), absRef);
00090    Float_t t =  cam.FrustumPlane(TGLCamera::kTop).D();
00091    Float_t b = -cam.FrustumPlane(TGLCamera::kBottom).D();
00092 
00093    fFrustum[0] = l;
00094    fFrustum[1] = b;
00095    fFrustum[2] = r;
00096    fFrustum[3] = t;
00097 }
00098 
00099 //______________________________________________________________________________
00100 void TGLCameraOverlay::RenderPlaneIntersect(TGLRnrCtx& rnrCtx)
00101 {
00102    // Draw cross section coordinates in top right corner of screen.
00103 
00104    TGLCamera &cam = rnrCtx.RefCamera();
00105    // get eye line
00106    const TGLMatrix& mx =  cam.GetCamBase() * cam.GetCamTrans();
00107    TGLVertex3 d   = mx.GetTranslation();
00108    TGLVertex3 p = d + mx.GetBaseVec(1);
00109    TGLLine3  line(d, p);
00110    // get ref plane
00111    const TGLPlane rp = (fUseExternalRefPlane) ? fExternalRefPlane :
00112       TGLPlane(cam.GetCamBase().GetBaseVec(3), TGLVertex3());
00113    // get intersection
00114    std::pair<Bool_t, TGLVertex3> intersection;
00115    intersection = Intersection(rp, line, kTRUE);
00116 
00117    if (intersection.first)
00118    {
00119       TGLVertex3 v = intersection.second;
00120 
00121       glMatrixMode(GL_PROJECTION);
00122       glPushMatrix();
00123       glLoadIdentity();
00124 
00125       glMatrixMode(GL_MODELVIEW);
00126       glPushMatrix();
00127       glLoadIdentity();
00128 
00129       TGLRect &vp = rnrCtx.GetCamera()->RefViewport();
00130       TGLFont font;
00131       Int_t fs = TMath::Nint(TMath::Sqrt(vp.Width()*vp.Width() + vp.Height()*vp.Height())*0.02);
00132       rnrCtx.RegisterFontNoScale(fs, "arial", TGLFont::kPixmap, font);
00133       const char* txt = Form("(%f, %f, %f)", v[0], v[1], v[2]);
00134       TGLUtil::Color(rnrCtx.ColorSet().Markup());
00135       font.Render(txt, 0.98, 0.98, 0, TGLFont::kRight, TGLFont::kBottom);
00136 
00137       // render cross
00138       TGLUtil::Color(kRed);
00139       Float_t w = 0.02;  // cross size
00140       Float_t ce = 0.15; // empty space
00141       glBegin(GL_LINES);
00142       glVertex2f(0 +w*ce, 0);
00143       glVertex2f(0 +w,    0);
00144 
00145       glVertex2f(0 -w*ce, 0);
00146       glVertex2f(0 -w, 0);
00147 
00148       Float_t h = w*vp.Width()/vp.Height();
00149       glVertex2f(0, 0 +h*ce);
00150       glVertex2f(0, 0 +h);
00151 
00152       glVertex2f(0, 0 -h*ce);
00153       glVertex2f(0, 0 -h);
00154       glEnd();
00155 
00156       glPopMatrix();
00157       glMatrixMode(GL_PROJECTION);
00158       glPopMatrix();
00159       glMatrixMode(GL_MODELVIEW);
00160    }
00161 }
00162 
00163 //______________________________________________________________________________
00164 void TGLCameraOverlay::RenderAxis(TGLRnrCtx& rnrCtx, Bool_t grid)
00165 {
00166    // Draw axis on four edges and a transparent grid.
00167 
00168    fAxisPainter->SetAttAxis(fAxis);
00169    fAxisPainter->SetUseAxisColors(fUseAxisColors);
00170 
00171    Color_t lineColor = fUseAxisColors ? fAxis->GetAxisColor() : rnrCtx.ColorSet().Markup().GetColorIndex();
00172 
00173    // font size calculated relative to viewport diagonal
00174    GLint   vp[4]; glGetIntegerv(GL_VIEWPORT, vp);
00175    Float_t rl = 0.5 *((vp[2]-vp[0]) + (vp[3]-vp[1]));
00176    Int_t fsizePx = (Int_t)(fAxis->GetLabelSize()*rl);
00177    // tick length
00178    Float_t tlY = 0.015*rl/(vp[2]-vp[0]);
00179    Float_t tlX = 0.015*rl/(vp[3]-vp[1]);
00180    // corner vectors
00181    Float_t minX, maxX;
00182    TGLVector3 xdir = rnrCtx.RefCamera().GetCamBase().GetBaseVec(2); xdir.Normalise(); // left
00183    if (fFrustum[2] > fFrustum[0] )
00184    {   
00185       minX =  fFrustum[0];
00186       maxX =  fFrustum[2];
00187    }
00188    else {
00189       xdir = -xdir;
00190       minX =  fFrustum[2];
00191       maxX =  fFrustum[0];
00192    }
00193 
00194    TGLVector3 ydir = rnrCtx.RefCamera().GetCamBase().GetBaseVec(3); ydir.Normalise(); // up
00195    TGLVector3 vy1 = ydir * fFrustum[1];
00196    TGLVector3 vy2 = ydir * fFrustum[3];
00197 
00198    TGLVector3 vx1 = xdir * minX;
00199    TGLVector3 vx2 = xdir * maxX;
00200    // range
00201    Double_t rngY = fFrustum[3] - fFrustum[1];
00202    Double_t rngX = maxX - minX;
00203    Double_t off =  TMath::Sqrt((rngX*rngX)+(rngY*rngY)) * 0.03;
00204    Double_t minY = fFrustum[1] + off;
00205    Double_t maxY = fFrustum[3] - off;
00206    minX += off;
00207    maxX -= off;
00208 
00209    // grid lines
00210    Char_t alpha = 80; //primary
00211    Char_t alpha2 = 90; //seconndary
00212    Int_t secSteps = fAxis->GetNdivisions() % 100;
00213    GLushort stipple =  0x5555; // 33333 more rare
00214 
00215    // horizontal X
00216    //
00217    fAxisPainter->SetLabelPixelFontSize(fsizePx);
00218    fAxis->SetTickLength(tlX);
00219    fAxisPainter->RefDir() = xdir;
00220    fAxis->SetLimits(minX, maxX);
00221    fAxisPainter->RefTMOff(0) = ydir*rngY;
00222 
00223    // bottom
00224    glPushMatrix();
00225    glTranslated(vy1.X(), vy1.Y(), vy1.Z());
00226    fAxisPainter->SetLabelAlign(TGLFont::kCenterH, TGLFont::kTop);
00227    fAxisPainter->PaintAxis(rnrCtx, fAxis);
00228    glPopMatrix();
00229 
00230    // top
00231    glPushMatrix();
00232    glTranslated(vy2.X(), vy2.Y(), vy2.Z());
00233    fAxisPainter->SetLabelAlign(TGLFont::kCenterH, TGLFont::kBottom);
00234    fAxisPainter->RefTMOff(0).Negate();
00235    fAxisPainter->RnrLabels();
00236    fAxisPainter->RnrLines();
00237    glPopMatrix();
00238 
00239    TGLUtil::LineWidth(1);
00240    if (grid)
00241    {
00242       TGLAxisPainter::LabVec_t& labs = fAxisPainter->RefLabVec();
00243       TGLVector3 tmp;
00244       // draw label vertical lines
00245       TGLUtil::ColorTransparency(lineColor, alpha);
00246       glBegin(GL_LINES);
00247       for ( TGLAxisPainter::LabVec_t::iterator i = labs.begin(); i != labs.end(); i++)
00248       {
00249          tmp = vy1 + xdir * (i->first);
00250          glVertex3dv(tmp.Arr());
00251          tmp = vy2 + xdir * (i->first);
00252          glVertex3dv(tmp.Arr());
00253       }
00254       glEnd();
00255 
00256       // secondary tick mark lines
00257       if (labs.size() > 1)
00258       {
00259          TGLUtil::ColorTransparency(lineColor, alpha2);
00260          glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
00261          glEnable(GL_LINE_STIPPLE);
00262          glLineStipple(1, stipple);
00263 
00264          glBegin(GL_LINES);
00265          Int_t ondiv;
00266          Double_t omin, omax, bw1;
00267          Double_t val =0;
00268          THLimitsFinder::Optimize(labs[0].second, labs[1].second, secSteps, omin, omax, ondiv, bw1);
00269          val =  labs[0].second;
00270          while(val < fFrustum[2])
00271          {
00272             for(Int_t k=0; k<ondiv; k++)
00273             {
00274                val += bw1;
00275                tmp = vy1 + xdir * val;
00276                glVertex3dv(tmp.Arr());
00277                tmp = vy2 + xdir * val;
00278                glVertex3dv(tmp.Arr());
00279             }
00280          }
00281          val = labs[0].second - bw1;
00282          while(val > fFrustum[0])
00283          {
00284             tmp = vy1 + xdir * val;
00285             glVertex3dv(tmp.Arr());
00286             tmp = vy2 + xdir * val;
00287             glVertex3dv(tmp.Arr());
00288             val -= bw1;
00289          }
00290          glEnd();
00291          glPopAttrib();
00292       }
00293    } // draw grid
00294 
00295    //
00296    // vertical Y axis
00297    //
00298 
00299    fAxis->SetTickLength(tlY);
00300    fAxisPainter->RefDir() = ydir;
00301    fAxis->SetLimits(minY, maxY);
00302    fAxisPainter->RefTMOff(0) = xdir*rngX;
00303    // left
00304    glPushMatrix();
00305    glTranslated(vx1.X(), vx1.Y(), vx1.Z());
00306    fAxisPainter->SetLabelAlign(TGLFont::kLeft, TGLFont::kCenterV);
00307    fAxisPainter->PaintAxis(rnrCtx, fAxis);
00308    glPopMatrix();
00309    // right
00310    glPushMatrix();
00311    glTranslated(vx2.X(), vx2.Y(), vx2.Z());
00312    fAxisPainter->SetLabelAlign(TGLFont::kRight, TGLFont::kCenterV);
00313    fAxisPainter->RefTMOff(0).Negate();
00314    fAxisPainter->RnrLabels();
00315    fAxisPainter->RnrLines();
00316    glPopMatrix();
00317 
00318    if (grid)
00319    {
00320       TGLAxisPainter::LabVec_t& labs = fAxisPainter->RefLabVec();
00321       TGLVector3 tmp;
00322       // draw label horizontal lines
00323       TGLUtil::ColorTransparency(lineColor, alpha);
00324       glBegin(GL_LINES);
00325       for ( TGLAxisPainter::LabVec_t::iterator i = labs.begin(); i != labs.end(); i++)
00326       {
00327          tmp = vx1 + ydir *(i->first);
00328          glVertex3dv(tmp.Arr());
00329          tmp = vx2 + ydir *(i->first);
00330          glVertex3dv(tmp.Arr());
00331       }
00332       glEnd();
00333 
00334       // secondary tick mark lines
00335       if (labs.size() > 1)
00336       {
00337          TGLUtil::ColorTransparency(lineColor, alpha2);
00338          glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
00339          glEnable(GL_LINE_STIPPLE);
00340          glLineStipple(1, stipple);
00341 
00342          glBegin(GL_LINES);
00343          Int_t ondiv;
00344          Double_t omin, omax, bw1;
00345          Double_t val =0;
00346          THLimitsFinder::Optimize(labs[0].second, labs[1].second, secSteps, omin, omax, ondiv, bw1);
00347          val =  labs[0].second;
00348          while(val < fFrustum[3])
00349          {
00350             for(Int_t k=0; k<ondiv; k++)
00351             {
00352                val += bw1;
00353                tmp = vx1 + ydir *val;
00354                glVertex3dv(tmp.Arr());
00355                tmp = vx2 + ydir * val;
00356                glVertex3dv(tmp.Arr());
00357             }
00358          }
00359 
00360          val = labs[0].second - bw1;
00361          while(val > fFrustum[1])
00362          {
00363             tmp = vx1 + ydir *val;
00364             glVertex3dv(tmp.Arr());
00365             tmp = vx2 + ydir * val;
00366             glVertex3dv(tmp.Arr());
00367             val -= bw1;
00368          }
00369          glEnd();
00370          glPopAttrib();
00371       }
00372    } // draw grid
00373 }
00374 
00375 //______________________________________________________________________________
00376 void TGLCameraOverlay::RenderBar(TGLRnrCtx&  rnrCtx)
00377 {
00378    // Show frustum size with fixed screen line length and printed value.
00379 
00380    // factors 10, 5 and 2 are allowed
00381    Double_t wfrust     = TMath::Abs(fFrustum[2]-fFrustum[0]);
00382    Float_t barsize= 0.14* wfrust;
00383    Int_t exp = (Int_t) TMath::Floor(TMath::Log10(barsize));
00384    Double_t fact = barsize/TMath::Power(10, exp);
00385    Double_t red;
00386    if (fact > 5)
00387    {
00388       red = 5*TMath::Power(10, exp);
00389    }
00390    else if (fact > 2)
00391    {
00392       red = 2*TMath::Power(10, exp);
00393    } else
00394    {
00395       red = TMath::Power(10, exp);
00396    }
00397 
00398    TGLVector3 v;
00399    TGLVector3 xdir = rnrCtx.RefCamera().GetCamBase().GetBaseVec(2); // left
00400    TGLVector3 ydir = rnrCtx.RefCamera().GetCamBase().GetBaseVec(3); // up
00401    xdir.Normalise();
00402    ydir.Normalise();
00403 
00404    TGLUtil::Color(rnrCtx.ColorSet().Foreground());
00405 
00406    const char* txt = Form("%.*f", (exp < 0) ? -exp : 0, red);
00407    Float_t bb[6];
00408    TGLFont font;
00409    rnrCtx.RegisterFont(12, "arial", TGLFont::kPixmap, font);
00410    font.BBox(txt, bb[0], bb[1], bb[2], bb[3], bb[4], bb[5]);
00411    TGLRect &vp = rnrCtx.GetCamera()->RefViewport();
00412    Double_t mH = (fFrustum[3]-fFrustum[1])*bb[4]/vp.Height();
00413    glPushMatrix();
00414    v = xdir*(fFrustum[2]-barsize) + ydir*(fFrustum[3] - mH*1.5);
00415    glTranslated(v.X(), v.Y(), v.Z());
00416    glRasterPos2i(0,0);
00417    font.Render(txt);
00418    glPopMatrix();
00419 
00420    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
00421    TGLUtil::LineWidth(2.);
00422    glPushMatrix();
00423    Float_t xt = fFrustum[2] - 1.1*barsize;
00424    Float_t yt = fFrustum[3] - 2.1*mH;
00425    v = xdir*xt + ydir*yt;
00426    glTranslated(v.X(), v.Y(), v.Z());
00427 
00428    glBegin(GL_LINES);
00429    // horizontal static
00430    v = red*xdir;
00431    glVertex3dv(v.Arr());
00432    v = barsize*xdir;
00433    glVertex3dv(v.Arr());
00434    // corner bars end
00435    v = xdir*barsize + ydir*mH;
00436    glVertex3dv(v.Arr());
00437    v = xdir*barsize - ydir*mH;
00438    glVertex3dv(v.Arr());
00439    // corner bar start
00440    TGLUtil::Color(kRed);
00441    v = ydir*mH;
00442    glVertex3dv(v.Arr());
00443    v.Negate();
00444    glVertex3dv(v.Arr());
00445    // marker pointer
00446    v = red*ydir;
00447    glVertex3dv(v.Arr());
00448    v += ydir*mH;
00449    glVertex3dv(v.Arr());
00450    //marker line
00451    glVertex3d(0, 0., 0.);
00452    v = red*xdir;
00453    glVertex3dv(v.Arr());
00454    glEnd();
00455    glPopAttrib();
00456    glPopMatrix();
00457 }
00458 
00459 //______________________________________________________________________________
00460 void TGLCameraOverlay::Render(TGLRnrCtx& rnrCtx)
00461 {
00462    // Display coodinates info of current frustum.
00463 
00464    TGLCamera &cam = rnrCtx.RefCamera();
00465 
00466    if (rnrCtx.Selection() ||
00467        (cam.IsPerspective()  && ! fShowPerspective) ||
00468        (cam.IsOrthographic() && ! fShowOrthographic))
00469    {
00470       return;
00471    }
00472 
00473    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
00474    glEnable(GL_BLEND);
00475    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00476 
00477    TGLUtil::Color(rnrCtx.ColorSet().Markup());
00478    TGLCapabilitySwitch lights_off(GL_LIGHTING, kFALSE);
00479    Float_t old_depth_range[2];
00480    glGetFloatv(GL_DEPTH_RANGE, old_depth_range);
00481 
00482    SetFrustum(cam);
00483 
00484    if (cam.IsOrthographic())
00485    {
00486       switch (fOrthographicMode)
00487       {
00488          case kBar:
00489             glDepthRange(0, 0.1);
00490             RenderBar(rnrCtx);
00491             break;
00492          case kAxis:
00493             glDepthRange(0, 0.1);
00494             RenderAxis(rnrCtx, kFALSE);
00495             break;
00496          case kGridFront:
00497             glDepthRange(0, 0.1);
00498             RenderAxis(rnrCtx, kTRUE);
00499             break;
00500          case kGridBack:
00501             glDepthRange(1, 0.9);
00502             RenderAxis(rnrCtx, kTRUE);
00503             break;
00504          default:
00505             break;
00506       };
00507    }
00508    else
00509    {
00510       RenderPlaneIntersect(rnrCtx);
00511    }
00512 
00513    glDepthRange(old_depth_range[0], old_depth_range[1]);
00514    glPopAttrib();
00515 }

Generated on Tue Jul 5 14:18:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1