2 // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
4 /**************************************************************************
5 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
6 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for *
7 * full copyright notice. *
8 **************************************************************************/
10 #include "AliEveTPCSector2DGL.h"
12 #include <EveDet/AliEveTPCSector2D.h>
14 #include <TGLRnrCtx.h>
15 #include <TGLSelectRecord.h>
16 #include <TGLIncludes.h>
18 //______________________________________________________________________________
20 // GL renderer for AliEveTPCSector2D.
22 ClassImp(AliEveTPCSector2DGL)
24 // This can be optimized to non-pow-2 values once everybody has GL 1.4.
26 const Int_t AliEveTPCSector2DGL::fgkTextureWidth = 256;
27 const Int_t AliEveTPCSector2DGL::fgkTextureHeight = 128;
28 const Int_t AliEveTPCSector2DGL::fgkTextureByteSize = 4*256*128;
30 /******************************************************************************/
32 AliEveTPCSector2DGL::AliEveTPCSector2DGL() :
45 AliEveTPCSector2DGL::~AliEveTPCSector2DGL()
48 // !!!! Should unregister texture via ContextIdentity!
50 if (fImage) delete [] fImage;
51 if (fTexture) glDeleteTextures(1, &fTexture);
54 /******************************************************************************/
56 Bool_t AliEveTPCSector2DGL::SetModel(TObject* obj, const Option_t* /*opt*/)
60 if (SetModelCheckClass(obj, AliEveTPCSector2D::Class())) {
61 fSector = (AliEveTPCSector2D*) fExternalObj;
67 void AliEveTPCSector2DGL::SetBBox()
71 SetAxisAlignedBBox(((AliEveTPCSector2D*)fExternalObj)->AssertBBox());
74 /******************************************************************************/
76 void AliEveTPCSector2DGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/,
77 TGLSelectRecord & rec)
79 // Process selection record.
80 // Determine row and pad, call PadSelected() in model object.
82 if (rec.GetN() != 3) return;
83 Int_t row = rec.GetItem(1);
84 Int_t pad = rec.GetItem(2);
85 if (row < 0 || row >= AliEveTPCSectorData::GetNAllRows()) return;
86 if (pad < 0 || pad >= AliEveTPCSectorData::GetNPadsInRow(row)) return;
87 fSector->PadSelected(row, pad);
90 /******************************************************************************/
92 void AliEveTPCSector2DGL::DirectDraw(TGLRnrCtx& rnrCtx) const
96 // printf("AliEveTPCSector2DGL::DirectDraw \n");
98 fSectorData = fSector->GetSectorData();
100 if(fRTS < fSector->fRTS && fSectorData != 0) {
102 fRTS = fSector->fRTS;
105 glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT |
106 GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT);
108 glDisable(GL_LIGHTING);
109 glDisable(GL_CULL_FACE);
112 if(fSectorData != 0) {
114 const AliEveTPCSectorData::SegmentInfo& iSeg = AliEveTPCSectorData::GetInnSeg();
115 const AliEveTPCSectorData::SegmentInfo& o1Seg = AliEveTPCSectorData::GetOut1Seg();
116 const AliEveTPCSectorData::SegmentInfo& o2Seg = AliEveTPCSectorData::GetOut2Seg();
118 if(rnrCtx.SecSelection()) {
120 if(fSector->fRnrInn) DisplayNamedQuads(iSeg, 0, 0);
121 if(fSector->fRnrOut1) DisplayNamedQuads(o1Seg, iSeg.GetNMaxPads(), 0);
122 if(fSector->fRnrOut2) DisplayNamedQuads(o2Seg, 0, o1Seg.GetNRows());
126 if(fSector->fUseTexture) {
129 glDepthMask(GL_FALSE);
130 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
132 glPolygonOffset(2,2);
133 glEnable(GL_POLYGON_OFFSET_FILL);
135 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
136 glBindTexture(GL_TEXTURE_2D, fTexture);
137 glEnable(GL_TEXTURE_2D);
139 if(fSector->fRnrInn) DisplayTexture(iSeg, 0, 0);
140 if(fSector->fRnrOut1) DisplayTexture(o1Seg, iSeg.GetNMaxPads(), 0);
141 if(fSector->fRnrOut2) DisplayTexture(o2Seg, 0, o1Seg.GetNRows());
143 glDisable(GL_TEXTURE_2D);
145 if(fSector->fRnrInn) DisplayQuads(iSeg, 0, 0);
146 if(fSector->fRnrOut1) DisplayQuads(o1Seg, iSeg.GetNMaxPads(), 0);
147 if(fSector->fRnrOut2) DisplayQuads(o2Seg, 0, o1Seg.GetNRows());
149 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
158 /******************************************************************************/
160 /******************************************************************************/
162 void AliEveTPCSector2DGL::LoadPadrow(AliEveTPCSectorData::RowIterator& iter,
163 Int_t row, Int_t colOff) const
165 // Load data for one pad-row into the texture.
170 Int_t minTime = fSector->fMinTime;
171 Int_t maxTime = fSector->fMaxTime;
172 Bool_t halfBorderTime = ((maxTime - minTime) % 2 == 0);
174 UChar_t* imgPos = GetRowCol(row, colOff);
175 while (iter.NextPad()) {
178 while (iter.Next()) {
182 if(time < minTime || time > maxTime)
185 if(fSector->fShowMax) {
190 if(halfBorderTime && (time == minTime || time == maxTime))
197 if(fSector->fShowMax == kFALSE && fSector->fAverage) {
198 padVal = (Int_t)((Float_t)padVal / (maxTime - minTime));
200 padVal = TMath::Min(padVal, fSector->fMaxVal);
201 if(padVal > fSector->fThreshold)
202 fSector->ColorFromArray(padVal, imgPos);
207 /******************************************************************************/
209 void AliEveTPCSector2DGL::CreateTexture() const
211 // Create texture that holds pad data.
214 fImage = new UChar_t[fgkTextureByteSize];
215 glGenTextures(1, &fTexture);
217 memset(fImage, 0, fgkTextureByteSize);
219 Int_t rowOff[3], colOff[3];
222 rowOff[1] = rowOff[2] = -AliEveTPCSectorData::GetSeg(1).GetFirstRow();
223 colOff[0] = colOff[2] = 0;
224 colOff[1] = AliEveTPCSectorData::GetSeg(0).GetNMaxPads();
225 isOn[0] = fSector->fRnrInn;
226 isOn[1] = fSector->fRnrOut1;
227 isOn[2] = fSector->fRnrOut2;
229 fSector->SetupColorArray();
231 // Loop over 3 main segments
232 for (Int_t sId = 0; sId <= 2; ++sId)
234 if (isOn[sId] == kFALSE)
236 const AliEveTPCSectorData::SegmentInfo& sInfo = AliEveTPCSectorData::GetSeg(sId);
237 for (Int_t row = sInfo.GetFirstRow(); row <= sInfo.GetLastRow(); ++row)
239 AliEveTPCSectorData::RowIterator i = fSectorData->MakeRowIterator(row);
240 Int_t offset = (sInfo.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(row))/2;
241 LoadPadrow(i, row + rowOff[sId], offset + colOff[sId]);
245 glBindTexture (GL_TEXTURE_2D, fTexture);
246 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT);
247 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
248 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
249 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
250 glTexEnvf (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);
251 glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, fgkTextureWidth, fgkTextureHeight,
252 0, GL_RGBA, GL_UNSIGNED_BYTE, fImage);
256 /******************************************************************************/
258 /******************************************************************************/
260 void AliEveTPCSector2DGL::DisplayTexture(const AliEveTPCSectorData::SegmentInfo& seg,
261 Int_t startCol, Int_t startRow) const
263 // Display segment data via one textured rectangle.
265 Float_t w = seg.GetNMaxPads()*seg.GetPadWidth()/2;
266 Float_t y1 = seg.GetRLow();
267 Float_t y2 = y1 + seg.GetNRows()*seg.GetPadHeight();
269 Float_t u1 = (Float_t) startCol / fgkTextureWidth;
270 Float_t v1 = (Float_t) startRow / fgkTextureHeight;
271 Float_t u2 = u1 + (Float_t) seg.GetNMaxPads() / fgkTextureWidth;
272 Float_t v2 = v1 + (Float_t) seg.GetNRows() / fgkTextureHeight;
275 glTexCoord2f(u1, v1); glVertex2f(-w, y1);
276 glTexCoord2f(u1, v2); glVertex2f(-w, y2);
277 glTexCoord2f(u2, v2); glVertex2f( w, y2);
278 glTexCoord2f(u2, v1); glVertex2f( w, y1);
282 /******************************************************************************/
284 void AliEveTPCSector2DGL::DisplayQuads(const AliEveTPCSectorData::SegmentInfo& seg,
285 Int_t startCol, Int_t startRow) const
287 // Display segment data by rendering one quad per pad.
291 Float_t padW = seg.GetPadWidth();
292 Float_t padH = seg.GetPadHeight();
295 for (Int_t row = 0; row < seg.GetNRows(); row++)
297 yD = seg.GetRLow() + row*padH;
299 xOff = -seg.GetNMaxPads()*padW/2;
300 Int_t tpcRow = row + seg.GetFirstRow();
301 Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2;
302 Int_t maxPad = seg.GetNMaxPads() - deltaPad;
303 UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad);
304 for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4)
309 TGLUtil::Color4ubv(pix);
310 glVertex2f(x+padW, yD);
313 glVertex2f(x+padW, yU);
320 void AliEveTPCSector2DGL::DisplayNamedQuads(const AliEveTPCSectorData::SegmentInfo& seg,
321 Int_t startCol, Int_t startRow) const
323 // Display segmen data as one quad per pad.
324 // Tag the rows and pads for selection.
328 Float_t padW = seg.GetPadWidth();
329 Float_t padH = seg.GetPadHeight();
332 for (Int_t row = 0; row < seg.GetNRows(); row++)
334 yD = seg.GetRLow() + row*padH;
336 xOff = -seg.GetNMaxPads()*padW/2;
337 Int_t tpcRow = row + seg.GetFirstRow();
339 Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2;
340 Int_t maxPad = seg.GetNMaxPads() - deltaPad;
341 UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad);
343 for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4)
346 if (pix[3] != 0 || fSector->fPickEmpty)
348 glLoadName(pad - deltaPad);
350 glVertex2f(x+padW, yD);
353 glVertex2f(x+padW, yU);
362 /******************************************************************************/
364 /******************************************************************************/
366 void AliEveTPCSector2DGL::TraceStepsUp(const AliEveTPCSectorData::SegmentInfo& s)
368 // Trace border of segment upwards.
370 Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth();
371 Float_t y = s.GetRLow();
373 for (Int_t i = 0; i < s.GetNYSteps(); ++i)
377 x -= s.GetPadWidth();
380 y = s.GetRLow() + s.GetNRows()*s.GetPadHeight();
381 glVertex2f(-s.GetNMaxPads()*s.GetPadWidth()/2, y);
384 void AliEveTPCSector2DGL::TraceStepsDown(const AliEveTPCSectorData::SegmentInfo& s)
386 // Trace border of segment downwards.
388 Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2;
389 Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight();
391 for (Int_t i = s.GetNYSteps() - 1; i >= 0; --i)
395 x -= s.GetPadWidth();
399 glVertex2f((0.5*s.GetNMaxPads() - s.GetNYSteps())*s.GetPadWidth(), y);
402 void AliEveTPCSector2DGL::DisplayFrame() const
404 // Display frame of the sector.
405 // Each segment's frame is drawn only if its data is drawn, too.
407 TGLUtil::Color(fSector->fFrameColor);
412 TraceStepsUp (AliEveTPCSectorData::GetInnSeg());
413 TraceStepsDown(AliEveTPCSectorData::GetInnSeg());
416 if(fSector->fRnrOut1)
419 TraceStepsUp (AliEveTPCSectorData::GetOut1Seg());
420 TraceStepsDown(AliEveTPCSectorData::GetOut1Seg());
423 if(fSector->fRnrOut2)
426 TraceStepsUp (AliEveTPCSectorData::GetOut2Seg());
427 TraceStepsDown(AliEveTPCSectorData::GetOut2Seg());