00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
00069
00070 delete fAxisPainter;
00071 delete fAxis;
00072 }
00073
00074
00075 TAttAxis* TGLCameraOverlay::GetAttAxis()
00076 {
00077
00078
00079 return dynamic_cast<TAttAxis*>(fAxis);
00080 }
00081
00082
00083 void TGLCameraOverlay::SetFrustum(TGLCamera& cam)
00084 {
00085
00086
00087 TGLVector3 absRef(1., 1., 1.);
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
00103
00104 TGLCamera &cam = rnrCtx.RefCamera();
00105
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
00111 const TGLPlane rp = (fUseExternalRefPlane) ? fExternalRefPlane :
00112 TGLPlane(cam.GetCamBase().GetBaseVec(3), TGLVertex3());
00113
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
00138 TGLUtil::Color(kRed);
00139 Float_t w = 0.02;
00140 Float_t ce = 0.15;
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
00167
00168 fAxisPainter->SetAttAxis(fAxis);
00169 fAxisPainter->SetUseAxisColors(fUseAxisColors);
00170
00171 Color_t lineColor = fUseAxisColors ? fAxis->GetAxisColor() : rnrCtx.ColorSet().Markup().GetColorIndex();
00172
00173
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
00178 Float_t tlY = 0.015*rl/(vp[2]-vp[0]);
00179 Float_t tlX = 0.015*rl/(vp[3]-vp[1]);
00180
00181 Float_t minX, maxX;
00182 TGLVector3 xdir = rnrCtx.RefCamera().GetCamBase().GetBaseVec(2); xdir.Normalise();
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();
00195 TGLVector3 vy1 = ydir * fFrustum[1];
00196 TGLVector3 vy2 = ydir * fFrustum[3];
00197
00198 TGLVector3 vx1 = xdir * minX;
00199 TGLVector3 vx2 = xdir * maxX;
00200
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
00210 Char_t alpha = 80;
00211 Char_t alpha2 = 90;
00212 Int_t secSteps = fAxis->GetNdivisions() % 100;
00213 GLushort stipple = 0x5555;
00214
00215
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
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
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
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
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 }
00294
00295
00296
00297
00298
00299 fAxis->SetTickLength(tlY);
00300 fAxisPainter->RefDir() = ydir;
00301 fAxis->SetLimits(minY, maxY);
00302 fAxisPainter->RefTMOff(0) = xdir*rngX;
00303
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
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
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
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 }
00373 }
00374
00375
00376 void TGLCameraOverlay::RenderBar(TGLRnrCtx& rnrCtx)
00377 {
00378
00379
00380
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);
00400 TGLVector3 ydir = rnrCtx.RefCamera().GetCamBase().GetBaseVec(3);
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
00430 v = red*xdir;
00431 glVertex3dv(v.Arr());
00432 v = barsize*xdir;
00433 glVertex3dv(v.Arr());
00434
00435 v = xdir*barsize + ydir*mH;
00436 glVertex3dv(v.Arr());
00437 v = xdir*barsize - ydir*mH;
00438 glVertex3dv(v.Arr());
00439
00440 TGLUtil::Color(kRed);
00441 v = ydir*mH;
00442 glVertex3dv(v.Arr());
00443 v.Negate();
00444 glVertex3dv(v.Arr());
00445
00446 v = red*ydir;
00447 glVertex3dv(v.Arr());
00448 v += ydir*mH;
00449 glVertex3dv(v.Arr());
00450
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
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 }