00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TEveCalo3DGL.h"
00013 #include "TEveCalo.h"
00014
00015 #include "TMath.h"
00016 #include "TAxis.h"
00017
00018 #include "TGLRnrCtx.h"
00019 #include "TGLSelectRecord.h"
00020 #include "TGLPhysicalShape.h"
00021 #include "TGLIncludes.h"
00022 #include "TGLUtil.h"
00023 #include "TEveRGBAPalette.h"
00024 #include "TEveUtil.h"
00025
00026
00027
00028
00029
00030 ClassImp(TEveCalo3DGL);
00031
00032
00033 TEveCalo3DGL::TEveCalo3DGL() :
00034 TGLObject(), fM(0)
00035 {
00036
00037
00038 fMultiColor = kTRUE;
00039 }
00040
00041
00042 Bool_t TEveCalo3DGL::SetModel(TObject* obj, const Option_t* )
00043 {
00044
00045
00046 fM = SetModelDynCast<TEveCalo3D>(obj);
00047 return kTRUE;
00048 }
00049
00050
00051 void TEveCalo3DGL::SetBBox()
00052 {
00053
00054
00055
00056 SetAxisAlignedBBox(((TEveCalo3D*)fExternalObj)->AssertBBox());
00057 }
00058
00059
00060 Bool_t TEveCalo3DGL::ShouldDLCache(const TGLRnrCtx& rnrCtx) const
00061 {
00062
00063
00064
00065
00066 if (rnrCtx.Highlight() || rnrCtx.Selection()) return kFALSE;
00067 return TGLObject::ShouldDLCache(rnrCtx);
00068 }
00069
00070
00071 inline void TEveCalo3DGL::CrossProduct(const Float_t a[3], const Float_t b[3],
00072 const Float_t c[3], Float_t out[3]) const
00073 {
00074
00075
00076 const Float_t v1[3] = { a[0] - c[0], a[1] - c[1], a[2] - c[2] };
00077 const Float_t v2[3] = { b[0] - c[0], b[1] - c[1], b[2] - c[2] };
00078
00079 out[0] = v1[1] * v2[2] - v1[2] * v2[1];
00080 out[1] = v1[2] * v2[0] - v1[0] * v2[2];
00081 out[2] = v1[0] * v2[1] - v1[1] * v2[0];
00082 }
00083
00084
00085 void TEveCalo3DGL::RenderGridEndCap() const
00086 {
00087
00088
00089 using namespace TMath;
00090
00091 Float_t rB = fM->GetBarrelRadius();
00092 Double_t zE = fM->GetEndCapPos();
00093
00094 Float_t etaMin = fM->GetEtaMin();
00095 Float_t etaMax = fM->GetEtaMax();
00096 Float_t trans = fM->GetTransitionEta();
00097 Float_t phiMin = fM->GetPhiMin();
00098 Float_t phiMax = fM->GetPhiMax();
00099
00100 TAxis *ax = fM->GetData()->GetEtaBins();
00101 Int_t nx = ax->GetNbins();
00102 TAxis *ay = fM->GetData()->GetPhiBins();
00103 Int_t ny = ay->GetNbins();
00104
00105
00106 Float_t r, z, theta, phiU, phiL, eta;
00107
00108
00109 for (Int_t i=0; i<=nx; ++i)
00110 {
00111 eta = ax->GetBinUpEdge(i);
00112 if (Abs(eta) >= trans && (eta > etaMin && eta < etaMax))
00113 {
00114 theta = TEveCaloData::EtaToTheta(eta);
00115 r = Abs(zE*Tan(theta));
00116 z = Sign(zE, ax->GetBinLowEdge(i));
00117 for (Int_t j=1; j<=ny; ++j)
00118 {
00119 phiL = ay->GetBinLowEdge(j);
00120 phiU = ay->GetBinUpEdge(j);
00121 if (TEveUtil::IsU1IntervalContainedByMinMax(phiMin, phiMax, phiL, phiU))
00122 {
00123 glVertex3f(r*Cos(phiL), r*Sin(phiL), z);
00124 glVertex3f(r*Cos(phiU), r*Sin(phiU), z);
00125 }
00126 }
00127 }
00128 }
00129
00130 Float_t r1, r2;
00131
00132 if (etaMax > trans)
00133 {
00134 r1 = zE*Tan(TEveCaloData::EtaToTheta(etaMax));
00135 if (etaMin < trans)
00136 r2 = rB;
00137 else
00138 r2 = zE*Tan(TEveCaloData::EtaToTheta(etaMin));
00139
00140 for (Int_t j=1; j<=ny; ++j)
00141 {
00142 phiL = ay->GetBinLowEdge(j);
00143 phiU = ay->GetBinUpEdge(j);
00144 if (TEveUtil::IsU1IntervalContainedByMinMax(phiMin, phiMax, phiL, phiU))
00145 {
00146 glVertex3f( r1*Cos(phiU), r1*Sin(phiU), zE);
00147 glVertex3f( r2*Cos(phiU), r2*Sin(phiU), zE);
00148 glVertex3f( r1*Cos(phiL), r1*Sin(phiL), zE);
00149 glVertex3f( r2*Cos(phiL), r2*Sin(phiL), zE);
00150 }
00151 }
00152 }
00153
00154
00155 if (etaMin < -trans)
00156 {
00157 r1 = zE*Tan(TEveCaloData::EtaToTheta(etaMin));
00158 if (etaMax > -trans)
00159 r2 = rB;
00160 else
00161 r2 = zE*Tan(TEveCaloData::EtaToTheta(etaMax));
00162
00163 r1 = Abs(r1);
00164 r2 = Abs(r2);
00165 for (Int_t j=1; j<=ny; ++j)
00166 {
00167 phiL = ay->GetBinLowEdge(j);
00168 phiU = ay->GetBinUpEdge(j);
00169 if (TEveUtil::IsU1IntervalContainedByMinMax(phiMin, phiMax, phiL, phiU))
00170 {
00171 glVertex3f(r1*Cos(phiU), r1*Sin(phiU), -zE);
00172 glVertex3f(r2*Cos(phiU), r2*Sin(phiU), -zE);
00173 glVertex3f(r1*Cos(phiL), r1*Sin(phiL), -zE);
00174 glVertex3f(r2*Cos(phiL), r2*Sin(phiL), -zE);
00175 }
00176 }
00177 }
00178 }
00179
00180
00181 void TEveCalo3DGL::RenderGridBarrel() const
00182 {
00183
00184
00185 using namespace TMath;
00186
00187 Float_t etaMin = fM->GetEtaMin();
00188 Float_t etaMax = fM->GetEtaMax();
00189 Float_t trans = fM->GetTransitionEta();
00190 Float_t phiMin = fM->GetPhiMin();
00191 Float_t phiMax = fM->GetPhiMax();
00192
00193 Float_t rB = fM->GetBarrelRadius();
00194 TAxis *ax = fM->GetData()->GetEtaBins();
00195 Int_t nx = ax->GetNbins();
00196 TAxis *ay = fM->GetData()->GetPhiBins();
00197 Int_t ny = ay->GetNbins();
00198
00199 Float_t z, theta, phiL, phiU, eta, x, y;
00200
00201
00202 for(Int_t i=0; i<=nx; i++)
00203 {
00204 eta = ax->GetBinUpEdge(i);
00205 if ((Abs(eta)<=trans) && (etaMin < eta && eta < etaMax))
00206 {
00207 theta = TEveCaloData::EtaToTheta(eta);
00208 z = rB/Tan(theta);
00209 for (Int_t j=1; j<=ny; j++)
00210 {
00211 phiU = ay->GetBinUpEdge(j);
00212 phiL = ay->GetBinLowEdge(j);
00213 if (TEveUtil::IsU1IntervalContainedByMinMax(phiMin, phiMax, phiL, phiU))
00214 {
00215 glVertex3f(rB*Cos(phiL), rB*Sin(phiL), z);
00216 glVertex3f(rB*Cos(phiU), rB*Sin(phiU), z);
00217 }
00218 }
00219 }
00220 }
00221
00222
00223 Float_t zF, zB;
00224
00225 if (etaMin > -trans)
00226 zB = rB/Tan(TEveCaloData::EtaToTheta(etaMin));
00227 else
00228 zB = -fM->GetEndCapPos();
00229
00230
00231 if (etaMax < trans)
00232 zF = rB/Tan(TEveCaloData::EtaToTheta(etaMax));
00233 else
00234 zF = fM->GetEndCapPos();
00235
00236 for (Int_t j=1; j<=ny; j++)
00237 {
00238 phiU = ay->GetBinUpEdge(j);
00239 phiL = ay->GetBinLowEdge(j);
00240 if (TEveUtil::IsU1IntervalContainedByMinMax(phiMin, phiMax, phiL, phiU))
00241 {
00242 x = rB * Cos(phiL);
00243 y = rB * Sin(phiL);
00244 glVertex3f(x, y, zB);
00245 glVertex3f(x, y, zF);
00246 x = rB * Cos(phiU);
00247 y = rB * Sin(phiU);
00248 glVertex3f(x, y, zB);
00249 glVertex3f(x, y, zF);
00250 }
00251 }
00252 }
00253
00254
00255 void TEveCalo3DGL::RenderGrid(TGLRnrCtx & rnrCtx) const
00256 {
00257
00258
00259 if (rnrCtx.Highlight() || rnrCtx.Selection() || rnrCtx.IsDrawPassOutlineLine()) return;
00260
00261 Bool_t transparent_p = fM->fFrameTransparency > 0;
00262
00263 if (transparent_p)
00264 {
00265 glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
00266
00267 glDepthMask(GL_FALSE);
00268 glEnable(GL_BLEND);
00269 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00270
00271 TGLUtil::ColorTransparency(fM->fFrameColor, fM->fFrameTransparency);
00272 }
00273
00274 TGLCapabilitySwitch lights_off(GL_LIGHTING, kFALSE);
00275
00276 TGLUtil::LineWidth(fM->GetFrameWidth());
00277 glBegin(GL_LINES);
00278
00279 Float_t etaMin = fM->GetEtaMin();
00280 Float_t etaMax = fM->GetEtaMax();
00281
00282 Float_t trans = fM->GetTransitionEta();
00283 if (fM->GetRnrBarrelFrame() && (etaMin < trans && etaMax > -trans))
00284 {
00285 RenderGridBarrel();
00286 }
00287
00288 if (fM->GetRnrEndCapFrame() && (etaMax > trans || etaMin < -trans))
00289 {
00290 RenderGridEndCap();
00291 }
00292
00293 glEnd();
00294
00295 if (transparent_p)
00296 {
00297 glPopAttrib();
00298 }
00299 }
00300
00301
00302 void TEveCalo3DGL::RenderBox(const Float_t pnts[8]) const
00303 {
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 const Float_t *p = pnts;
00319 Float_t cross[3];
00320
00321
00322 glBegin(GL_POLYGON);
00323 CrossProduct(p+3, p+9, p, cross);
00324 glNormal3fv(cross);
00325 glVertex3fv(p);
00326 glVertex3fv(p+3);
00327 glVertex3fv(p+6);
00328 glVertex3fv(p+9);
00329 glEnd();
00330
00331 glBegin(GL_POLYGON);
00332 CrossProduct(p+21, p+15, p+12, cross);
00333 glNormal3fv(cross);
00334 glVertex3fv(p+21);
00335 glVertex3fv(p+18);
00336 glVertex3fv(p+15);
00337 glVertex3fv(p+12);
00338 glEnd();
00339
00340 glBegin(GL_POLYGON);
00341 CrossProduct(p+12, p+3, p, cross);
00342 glNormal3fv(cross);
00343 glVertex3fv(p);
00344 glVertex3fv(p+12);
00345 glVertex3fv(p+15);
00346 glVertex3fv(p+3);
00347 glEnd();
00348
00349 glBegin(GL_POLYGON);
00350 CrossProduct(p+6, p+21, p+9, cross);
00351 glNormal3fv(cross);
00352 glVertex3fv(p+9);
00353 glVertex3fv(p+6);
00354 glVertex3fv(p+18);
00355 glVertex3fv(p+21);
00356 glEnd();
00357
00358 glBegin(GL_POLYGON);
00359 CrossProduct(p+21, p, p+9, cross);
00360 glNormal3fv(cross);
00361 glVertex3fv(p);
00362 glVertex3fv(p+9);
00363 glVertex3fv(p+21);
00364 glVertex3fv(p+12);
00365 glEnd();
00366
00367 glBegin(GL_POLYGON);
00368 CrossProduct(p+15, p+6, p+3, cross);
00369 glNormal3fv(cross);
00370 glVertex3fv(p+3);
00371 glVertex3fv(p+15);
00372 glVertex3fv(p+18);
00373 glVertex3fv(p+6);
00374 glEnd();
00375 }
00376
00377
00378 void TEveCalo3DGL::RenderBarrelCell(const TEveCaloData::CellGeom_t &cellData, Float_t towerH, Float_t& offset ) const
00379 {
00380
00381
00382 using namespace TMath;
00383
00384 Float_t r1 = fM->GetBarrelRadius() + offset;
00385 Float_t r2 = r1 + towerH*Sin(cellData.ThetaMin());
00386 Float_t z1In, z1Out, z2In, z2Out;
00387
00388 z1In = r1/Tan(cellData.ThetaMax());
00389 z1Out = r2/Tan(cellData.ThetaMax());
00390 z2In = r1/Tan(cellData.ThetaMin());
00391 z2Out = r2/Tan(cellData.ThetaMin());
00392
00393 Float_t cos1 = Cos(cellData.PhiMin());
00394 Float_t sin1 = Sin(cellData.PhiMin());
00395 Float_t cos2 = Cos(cellData.PhiMax());
00396 Float_t sin2 = Sin(cellData.PhiMax());
00397
00398 Float_t box[24];
00399 Float_t* pnts = box;
00400
00401 pnts[0] = r1*cos2;
00402 pnts[1] = r1*sin2;
00403 pnts[2] = z1In;
00404 pnts += 3;
00405
00406 pnts[0] = r1*cos1;
00407 pnts[1] = r1*sin1;
00408 pnts[2] = z1In;
00409 pnts += 3;
00410
00411 pnts[0] = r1*cos1;
00412 pnts[1] = r1*sin1;
00413 pnts[2] = z2In;
00414 pnts += 3;
00415
00416 pnts[0] = r1*cos2;
00417 pnts[1] = r1*sin2;
00418 pnts[2] = z2In;
00419 pnts += 3;
00420
00421
00422 pnts[0] = r2*cos2;
00423 pnts[1] = r2*sin2;
00424 pnts[2] = z1Out;
00425 pnts += 3;
00426
00427 pnts[0] = r2*cos1;
00428 pnts[1] = r2*sin1;
00429 pnts[2] = z1Out;
00430 pnts += 3;
00431
00432 pnts[0] = r2*cos1;
00433 pnts[1] = r2*sin1;
00434 pnts[2] = z2Out;
00435 pnts += 3;
00436
00437 pnts[0] = r2*cos2;
00438 pnts[1] = r2*sin2;
00439 pnts[2] = z2Out;
00440
00441 RenderBox(box);
00442
00443 offset += towerH*Sin(cellData.ThetaMin());
00444
00445 }
00446
00447
00448 void TEveCalo3DGL::RenderEndCapCell(const TEveCaloData::CellGeom_t &cellData, Float_t towerH, Float_t& offset ) const
00449 {
00450
00451
00452 using namespace TMath;
00453 Float_t z1, r1In, r1Out, z2, r2In, r2Out;
00454
00455 z1 = TMath::Sign(fM->fEndCapPos + offset, cellData.EtaMin());
00456 z2 = z1 + TMath::Sign(towerH, cellData.EtaMin());
00457
00458 r1In = z1*Tan(cellData.ThetaMin());
00459 r2In = z2*Tan(cellData.ThetaMin());
00460 r1Out = z1*Tan(cellData.ThetaMax());
00461 r2Out = z2*Tan(cellData.ThetaMax());
00462
00463 Float_t cos2 = Cos(cellData.PhiMin());
00464 Float_t sin2 = Sin(cellData.PhiMin());
00465 Float_t cos1 = Cos(cellData.PhiMax());
00466 Float_t sin1 = Sin(cellData.PhiMax());
00467
00468 Float_t box[24];
00469 Float_t* pnts = box;
00470
00471 pnts[0] = r1In*cos1;
00472 pnts[1] = r1In*sin1;
00473 pnts[2] = z1;
00474 pnts += 3;
00475
00476 pnts[0] = r1In*cos2;
00477 pnts[1] = r1In*sin2;
00478 pnts[2] = z1;
00479 pnts += 3;
00480
00481 pnts[0] = r2In*cos2;
00482 pnts[1] = r2In*sin2;
00483 pnts[2] = z2;
00484 pnts += 3;
00485
00486 pnts[0] = r2In*cos1;
00487 pnts[1] = r2In*sin1;
00488 pnts[2] = z2;
00489 pnts += 3;
00490
00491
00492 pnts[0] = r1Out*cos1;
00493 pnts[1] = r1Out*sin1;
00494 pnts[2] = z1;
00495 pnts += 3;
00496
00497 pnts[0] = r1Out*cos2;
00498 pnts[1] = r1Out*sin2;
00499 pnts[2] = z1;
00500 pnts += 3;
00501
00502 pnts[0] = r2Out*cos2;
00503 pnts[1] = r2Out*sin2;
00504 pnts[2] = z2;
00505 pnts += 3;
00506
00507 pnts[0] = r2Out*cos1;
00508 pnts[1] = r2Out*sin1;
00509 pnts[2] = z2;
00510
00511 RenderBox(box);
00512
00513 if (z1 > 0)
00514 offset += towerH * Cos(cellData.ThetaMin());
00515 else
00516 offset -= towerH * Cos(cellData.ThetaMin());
00517
00518 }
00519
00520
00521
00522 void TEveCalo3DGL::DirectDraw(TGLRnrCtx &rnrCtx) const
00523 {
00524
00525
00526 if ( fM->GetValueIsColor()) fM->AssertPalette();
00527
00528
00529 if (fM->fCellIdCacheOK == kFALSE)
00530 fM->BuildCellIdCache();
00531
00532 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
00533 glEnable(GL_LIGHTING);
00534 glEnable(GL_NORMALIZE);
00535 glEnable(GL_BLEND);
00536 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00537
00538 TEveCaloData::CellData_t cellData;
00539 Float_t towerH = 0;
00540 Int_t tower = 0;
00541 Int_t prevTower = -1;
00542 Float_t offset = 0;
00543 Int_t cellID = 0;
00544
00545 if (rnrCtx.SecSelection()) glPushName(0);
00546
00547 fOffset.assign(fM->fCellList.size(), 0);
00548 for (TEveCaloData::vCellId_i i = fM->fCellList.begin(); i != fM->fCellList.end(); ++i)
00549 {
00550 fM->fData->GetCellData((*i), cellData);
00551 tower = i->fTower;
00552 if (tower != prevTower)
00553 {
00554 offset = 0;
00555 prevTower = tower;
00556 }
00557 fOffset[cellID] = offset;
00558 fM->SetupColorHeight(cellData.Value(fM->fPlotEt), (*i).fSlice, towerH);
00559
00560 if (rnrCtx.SecSelection()) glLoadName(cellID);
00561
00562 if ((cellData.Eta() > 0 && cellData.Eta() < fM->GetTransitionEta()) ||
00563 (cellData.Eta() < 0 && cellData.Eta() > -fM->GetTransitionEta()))
00564 {
00565 RenderBarrelCell(cellData, towerH, offset);
00566 }
00567 else
00568 {
00569 RenderEndCapCell(cellData, towerH, offset);
00570 }
00571 ++cellID;
00572 }
00573
00574 if (rnrCtx.SecSelection()) glPopName();
00575
00576 RenderGrid(rnrCtx);
00577
00578 glPopAttrib();
00579 }
00580
00581
00582 void TEveCalo3DGL::DrawHighlight(TGLRnrCtx & rnrCtx, const TGLPhysicalShape* , Int_t ) const
00583 {
00584
00585
00586 if (fM->fData->GetCellsSelected().empty() && fM->fData->GetCellsHighlighted().empty())
00587 {
00588 return;
00589 }
00590
00591 glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT | GL_POLYGON_BIT);
00592 glDisable(GL_LIGHTING);
00593 glDisable(GL_CULL_FACE);
00594 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00595
00596 TGLUtil::LineWidth(2);
00597 TGLUtil::LockColor();
00598
00599 if (!fM->fData->GetCellsHighlighted().empty())
00600 {
00601 glColor4ubv(rnrCtx.ColorSet().Selection(3).CArr());
00602 DrawSelectedCells(fM->fData->GetCellsHighlighted());
00603 }
00604 if (!fM->fData->GetCellsSelected().empty())
00605 {
00606 Float_t dr[2];
00607 glGetFloatv(GL_DEPTH_RANGE,dr);
00608 glColor4ubv(rnrCtx.ColorSet().Selection(1).CArr());
00609 glDepthRange(dr[0], 0.8*dr[1]);
00610 DrawSelectedCells(fM->fData->GetCellsSelected());
00611 glDepthRange(dr[0], dr[1]);
00612 }
00613 TGLUtil::UnlockColor();
00614 glPopAttrib();
00615 }
00616
00617
00618 void TEveCalo3DGL::DrawSelectedCells(TEveCaloData::vCellId_t cells) const
00619 {
00620 TEveCaloData::CellData_t cellData;
00621 Float_t towerH = 0;
00622
00623 for (TEveCaloData::vCellId_i i = cells.begin(); i != cells.end(); i++)
00624 {
00625 fM->fData->GetCellData(*i, cellData);
00626 fM->SetupColorHeight(cellData.Value(fM->fPlotEt), (*i).fSlice, towerH);
00627
00628
00629 Float_t offset = 0;
00630 for (Int_t j = 0; j < (Int_t) fM->fCellList.size(); ++j)
00631 {
00632 if (fM->fCellList[j].fTower == i->fTower && fM->fCellList[j].fSlice == i->fSlice )
00633 {
00634 offset = fOffset[j];
00635 break;
00636 }
00637 }
00638
00639 if (fM->CellInEtaPhiRng(cellData))
00640 {
00641 if (TMath::Abs(cellData.Eta()) < fM->GetTransitionEta())
00642 RenderBarrelCell(cellData, towerH, offset);
00643 else
00644 RenderEndCapCell(cellData, towerH, offset);
00645 }
00646 }
00647 }
00648
00649
00650 void TEveCalo3DGL::ProcessSelection(TGLRnrCtx& , TGLSelectRecord& rec)
00651 {
00652
00653
00654
00655 TEveCaloData::vCellId_t sel;
00656 if (rec.GetN() > 1)
00657 {
00658 sel.push_back(fM->fCellList[rec.GetItem(1)]);
00659 }
00660 fM->fData->ProcessSelection(sel, rec);
00661 }