]>
Commit | Line | Data |
---|---|---|
d810d0de | 1 | // $Id$ |
2 | // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007 | |
915dabe1 | 3 | |
d810d0de | 4 | /************************************************************************** |
5 | * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. * | |
6 | * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for * | |
51346b82 | 7 | * full copyright notice. * |
d810d0de | 8 | **************************************************************************/ |
915dabe1 | 9 | |
d810d0de | 10 | #include "AliEveTPCSector2DGL.h" |
11 | ||
a15e6d7d | 12 | #include <EveDet/AliEveTPCSector2D.h> |
915dabe1 | 13 | |
19208112 | 14 | #include <TGLRnrCtx.h> |
15 | #include <TGLSelectRecord.h> | |
16 | #include <TGLIncludes.h> | |
d810d0de | 17 | |
57ffa5fb | 18 | //______________________________________________________________________________ |
68084553 | 19 | // |
a15e6d7d | 20 | // GL renderer for AliEveTPCSector2D. |
68084553 | 21 | |
d810d0de | 22 | ClassImp(AliEveTPCSector2DGL) |
68084553 | 23 | |
24 | // This can be optimized to non-pow-2 values once everybody has GL 1.4. | |
915dabe1 | 25 | |
d810d0de | 26 | const Int_t AliEveTPCSector2DGL::fgkTextureWidth = 256; |
27 | const Int_t AliEveTPCSector2DGL::fgkTextureHeight = 128; | |
28 | const Int_t AliEveTPCSector2DGL::fgkTextureByteSize = 4*256*128; | |
915dabe1 | 29 | |
57ffa5fb | 30 | /******************************************************************************/ |
915dabe1 | 31 | |
d810d0de | 32 | AliEveTPCSector2DGL::AliEveTPCSector2DGL() : |
265ecb21 | 33 | TGLObject(), |
51346b82 | 34 | |
265ecb21 | 35 | fSector (0), |
36 | fSectorData (0), | |
37 | ||
38 | fImage (0), | |
39 | fTexture (0), | |
40 | fRTS (0) | |
a97abca8 | 41 | { |
42 | // Constructor. | |
43 | } | |
915dabe1 | 44 | |
d810d0de | 45 | AliEveTPCSector2DGL::~AliEveTPCSector2DGL() |
915dabe1 | 46 | { |
a97abca8 | 47 | // Destructor. |
48 | // !!!! Should unregister texture via ContextIdentity! | |
49 | ||
36956ab0 | 50 | if (fImage) delete [] fImage; |
a97abca8 | 51 | if (fTexture) glDeleteTextures(1, &fTexture); |
915dabe1 | 52 | } |
53 | ||
57ffa5fb | 54 | /******************************************************************************/ |
915dabe1 | 55 | |
d810d0de | 56 | Bool_t AliEveTPCSector2DGL::SetModel(TObject* obj, const Option_t* /*opt*/) |
915dabe1 | 57 | { |
a97abca8 | 58 | // Set model object. |
59 | ||
60 | if (SetModelCheckClass(obj, AliEveTPCSector2D::Class())) { | |
d810d0de | 61 | fSector = (AliEveTPCSector2D*) fExternalObj; |
891e4bb4 | 62 | return kTRUE; |
915dabe1 | 63 | } |
891e4bb4 | 64 | return kFALSE; |
915dabe1 | 65 | } |
66 | ||
d810d0de | 67 | void AliEveTPCSector2DGL::SetBBox() |
915dabe1 | 68 | { |
a97abca8 | 69 | // Set bounding-box. |
70 | ||
d810d0de | 71 | SetAxisAlignedBBox(((AliEveTPCSector2D*)fExternalObj)->AssertBBox()); |
915dabe1 | 72 | } |
73 | ||
57ffa5fb | 74 | /******************************************************************************/ |
915dabe1 | 75 | |
d810d0de | 76 | void AliEveTPCSector2DGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/, |
a97abca8 | 77 | TGLSelectRecord & rec) |
a8600b56 | 78 | { |
a97abca8 | 79 | // Process selection record. |
80 | // Determine row and pad, call PadSelected() in model object. | |
81 | ||
19208112 | 82 | if (rec.GetN() != 3) return; |
83 | Int_t row = rec.GetItem(1); | |
84 | Int_t pad = rec.GetItem(2); | |
d810d0de | 85 | if (row < 0 || row >= AliEveTPCSectorData::GetNAllRows()) return; |
86 | if (pad < 0 || pad >= AliEveTPCSectorData::GetNPadsInRow(row)) return; | |
96ff1952 | 87 | fSector->PadSelected(row, pad); |
a8600b56 | 88 | } |
89 | ||
57ffa5fb | 90 | /******************************************************************************/ |
a8600b56 | 91 | |
d810d0de | 92 | void AliEveTPCSector2DGL::DirectDraw(TGLRnrCtx& rnrCtx) const |
915dabe1 | 93 | { |
94 | // Actual GL drawing. | |
95 | ||
d810d0de | 96 | // printf("AliEveTPCSector2DGL::DirectDraw \n"); |
915dabe1 | 97 | |
fa3a3795 | 98 | fSectorData = fSector->GetSectorData(); |
915dabe1 | 99 | |
100 | if(fRTS < fSector->fRTS && fSectorData != 0) { | |
101 | CreateTexture(); | |
102 | fRTS = fSector->fRTS; | |
103 | } | |
104 | ||
105 | glPushAttrib(GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | | |
106 | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT); | |
107 | ||
108 | glDisable(GL_LIGHTING); | |
915dabe1 | 109 | glDisable(GL_CULL_FACE); |
110 | ||
111 | // Display digits | |
112 | if(fSectorData != 0) { | |
113 | ||
d810d0de | 114 | const AliEveTPCSectorData::SegmentInfo& iSeg = AliEveTPCSectorData::GetInnSeg(); |
115 | const AliEveTPCSectorData::SegmentInfo& o1Seg = AliEveTPCSectorData::GetOut1Seg(); | |
116 | const AliEveTPCSectorData::SegmentInfo& o2Seg = AliEveTPCSectorData::GetOut2Seg(); | |
915dabe1 | 117 | |
19208112 | 118 | if(rnrCtx.SecSelection()) { |
426530cc | 119 | |
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()); | |
123 | ||
b56d8877 | 124 | } else { |
426530cc | 125 | |
126 | if(fSector->fUseTexture) { | |
127 | //texture | |
128 | glEnable(GL_BLEND); | |
129 | glDepthMask(GL_FALSE); | |
130 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
131 | ||
132 | glPolygonOffset(2,2); | |
133 | glEnable(GL_POLYGON_OFFSET_FILL); | |
134 | ||
135 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | |
136 | glBindTexture(GL_TEXTURE_2D, fTexture); | |
137 | glEnable(GL_TEXTURE_2D); | |
138 | ||
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()); | |
142 | ||
143 | glDisable(GL_TEXTURE_2D); | |
144 | } else { | |
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()); | |
148 | } | |
149 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | |
150 | DisplayFrame(); | |
915dabe1 | 151 | } |
915dabe1 | 152 | |
426530cc | 153 | } |
915dabe1 | 154 | |
155 | glPopAttrib(); | |
156 | } | |
157 | ||
57ffa5fb | 158 | /******************************************************************************/ |
915dabe1 | 159 | // Data import |
57ffa5fb | 160 | /******************************************************************************/ |
915dabe1 | 161 | |
d810d0de | 162 | void AliEveTPCSector2DGL::LoadPadrow(AliEveTPCSectorData::RowIterator& iter, |
a15e6d7d | 163 | Int_t row, Int_t colOff) const |
915dabe1 | 164 | { |
a97abca8 | 165 | // Load data for one pad-row into the texture. |
166 | ||
b56d8877 | 167 | Int_t padVal; |
51346b82 | 168 | Int_t time, val; |
915dabe1 | 169 | |
b56d8877 | 170 | Int_t minTime = fSector->fMinTime; |
171 | Int_t maxTime = fSector->fMaxTime; | |
172 | Bool_t halfBorderTime = ((maxTime - minTime) % 2 == 0); | |
915dabe1 | 173 | |
a15e6d7d | 174 | UChar_t* imgPos = GetRowCol(row, colOff); |
915dabe1 | 175 | while (iter.NextPad()) { |
51346b82 | 176 | padVal = 0; |
915dabe1 | 177 | |
178 | while (iter.Next()) { | |
179 | time = iter.Time(); | |
180 | val = iter.Signal(); | |
181 | ||
b56d8877 | 182 | if(time < minTime || time > maxTime) |
183 | continue; | |
184 | ||
915dabe1 | 185 | if(fSector->fShowMax) { |
b56d8877 | 186 | if(val > padVal) { |
187 | padVal = val; | |
915dabe1 | 188 | } |
189 | } else { | |
b56d8877 | 190 | if(halfBorderTime && (time == minTime || time == maxTime)) |
191 | padVal += val/2; | |
192 | else | |
193 | padVal += val; | |
915dabe1 | 194 | } |
195 | } | |
196 | ||
b56d8877 | 197 | if(fSector->fShowMax == kFALSE && fSector->fAverage) { |
198 | padVal = (Int_t)((Float_t)padVal / (maxTime - minTime)); | |
199 | } | |
200 | padVal = TMath::Min(padVal, fSector->fMaxVal); | |
201 | if(padVal > fSector->fThreshold) | |
a15e6d7d | 202 | fSector->ColorFromArray(padVal, imgPos); |
203 | imgPos += 4; | |
915dabe1 | 204 | } |
205 | } | |
206 | ||
57ffa5fb | 207 | /******************************************************************************/ |
915dabe1 | 208 | |
d810d0de | 209 | void AliEveTPCSector2DGL::CreateTexture() const |
915dabe1 | 210 | { |
a97abca8 | 211 | // Create texture that holds pad data. |
212 | ||
36956ab0 | 213 | if (fImage == 0) { |
915dabe1 | 214 | fImage = new UChar_t[fgkTextureByteSize]; |
215 | glGenTextures(1, &fTexture); | |
216 | } | |
217 | memset(fImage, 0, fgkTextureByteSize); | |
218 | ||
219 | Int_t rowOff[3], colOff[3]; | |
b56d8877 | 220 | Bool_t isOn[3]; |
221 | rowOff[0] = 0; | |
d810d0de | 222 | rowOff[1] = rowOff[2] = -AliEveTPCSectorData::GetSeg(1).GetFirstRow(); |
b56d8877 | 223 | colOff[0] = colOff[2] = 0; |
d810d0de | 224 | colOff[1] = AliEveTPCSectorData::GetSeg(0).GetNMaxPads(); |
b56d8877 | 225 | isOn[0] = fSector->fRnrInn; |
226 | isOn[1] = fSector->fRnrOut1; | |
227 | isOn[2] = fSector->fRnrOut2; | |
915dabe1 | 228 | |
891e4bb4 | 229 | fSector->SetupColorArray(); |
230 | ||
915dabe1 | 231 | // Loop over 3 main segments |
a15e6d7d | 232 | for (Int_t sId = 0; sId <= 2; ++sId) |
233 | { | |
234 | if (isOn[sId] == kFALSE) | |
b56d8877 | 235 | continue; |
d810d0de | 236 | const AliEveTPCSectorData::SegmentInfo& sInfo = AliEveTPCSectorData::GetSeg(sId); |
a15e6d7d | 237 | for (Int_t row = sInfo.GetFirstRow(); row <= sInfo.GetLastRow(); ++row) |
238 | { | |
d810d0de | 239 | AliEveTPCSectorData::RowIterator i = fSectorData->MakeRowIterator(row); |
240 | Int_t offset = (sInfo.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(row))/2; | |
915dabe1 | 241 | LoadPadrow(i, row + rowOff[sId], offset + colOff[sId]); |
242 | } | |
243 | } | |
244 | ||
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); | |
426530cc | 250 | glTexEnvf (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); |
915dabe1 | 251 | glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, fgkTextureWidth, fgkTextureHeight, |
252 | 0, GL_RGBA, GL_UNSIGNED_BYTE, fImage); | |
253 | ||
254 | } | |
255 | ||
57ffa5fb | 256 | /******************************************************************************/ |
915dabe1 | 257 | // Data display |
57ffa5fb | 258 | /******************************************************************************/ |
915dabe1 | 259 | |
d810d0de | 260 | void AliEveTPCSector2DGL::DisplayTexture(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 261 | Int_t startCol, Int_t startRow) const |
915dabe1 | 262 | { |
a97abca8 | 263 | // Display segment data via one textured rectangle. |
264 | ||
426530cc | 265 | Float_t w = seg.GetNMaxPads()*seg.GetPadWidth()/2; |
266 | Float_t y1 = seg.GetRLow(); | |
267 | Float_t y2 = y1 + seg.GetNRows()*seg.GetPadHeight(); | |
268 | ||
915dabe1 | 269 | Float_t u1 = (Float_t) startCol / fgkTextureWidth; |
270 | Float_t v1 = (Float_t) startRow / fgkTextureHeight; | |
426530cc | 271 | Float_t u2 = u1 + (Float_t) seg.GetNMaxPads() / fgkTextureWidth; |
272 | Float_t v2 = v1 + (Float_t) seg.GetNRows() / fgkTextureHeight; | |
915dabe1 | 273 | |
51346b82 | 274 | glBegin(GL_QUADS); |
426530cc | 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); | |
915dabe1 | 279 | glEnd(); |
280 | } | |
281 | ||
57ffa5fb | 282 | /******************************************************************************/ |
915dabe1 | 283 | |
d810d0de | 284 | void AliEveTPCSector2DGL::DisplayQuads(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 285 | Int_t startCol, Int_t startRow) const |
915dabe1 | 286 | { |
a97abca8 | 287 | // Display segment data by rendering one quad per pad. |
288 | ||
a15e6d7d | 289 | Float_t yD, yU; |
290 | Float_t xOff, x; | |
426530cc | 291 | Float_t padW = seg.GetPadWidth(); |
292 | Float_t padH = seg.GetPadHeight(); | |
915dabe1 | 293 | |
294 | glBegin(GL_QUADS); | |
a15e6d7d | 295 | for (Int_t row = 0; row < seg.GetNRows(); row++) |
296 | { | |
297 | yD = seg.GetRLow() + row*padH; | |
298 | yU = yD + padH; | |
299 | xOff = -seg.GetNMaxPads()*padW/2; | |
426530cc | 300 | Int_t tpcRow = row + seg.GetFirstRow(); |
d810d0de | 301 | Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2; |
426530cc | 302 | Int_t maxPad = seg.GetNMaxPads() - deltaPad; |
303 | UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad); | |
a15e6d7d | 304 | for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4) |
305 | { | |
306 | x = xOff + pad*padW; | |
307 | if (pix[3] != 0) | |
308 | { | |
309 | TGLUtil::Color4ubv(pix); | |
310 | glVertex2f(x+padW, yD); | |
311 | glVertex2f(x, yD); | |
312 | glVertex2f(x, yU); | |
313 | glVertex2f(x+padW, yU); | |
915dabe1 | 314 | } |
315 | } | |
316 | } | |
317 | glEnd(); | |
318 | } | |
319 | ||
d810d0de | 320 | void AliEveTPCSector2DGL::DisplayNamedQuads(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 321 | Int_t startCol, Int_t startRow) const |
426530cc | 322 | { |
a97abca8 | 323 | // Display segmen data as one quad per pad. |
324 | // Tag the rows and pads for selection. | |
325 | ||
a15e6d7d | 326 | Float_t yD, yU; |
327 | Float_t xOff, x; | |
426530cc | 328 | Float_t padW = seg.GetPadWidth(); |
329 | Float_t padH = seg.GetPadHeight(); | |
330 | ||
331 | glPushName(0); | |
a15e6d7d | 332 | for (Int_t row = 0; row < seg.GetNRows(); row++) |
333 | { | |
334 | yD = seg.GetRLow() + row*padH; | |
335 | yU = yD + padH; | |
336 | xOff = -seg.GetNMaxPads()*padW/2; | |
426530cc | 337 | Int_t tpcRow = row + seg.GetFirstRow(); |
338 | glLoadName(tpcRow); | |
d810d0de | 339 | Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2; |
426530cc | 340 | Int_t maxPad = seg.GetNMaxPads() - deltaPad; |
341 | UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad); | |
342 | glPushName(0); | |
a15e6d7d | 343 | for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4) |
344 | { | |
345 | x = xOff + pad*padW; | |
346 | if (pix[3] != 0 || fSector->fPickEmpty) | |
347 | { | |
426530cc | 348 | glLoadName(pad - deltaPad); |
349 | glBegin(GL_QUADS); | |
a15e6d7d | 350 | glVertex2f(x+padW, yD); |
351 | glVertex2f(x, yD); | |
352 | glVertex2f(x, yU); | |
353 | glVertex2f(x+padW, yU); | |
426530cc | 354 | glEnd(); |
355 | } | |
356 | } | |
357 | glPopName(); | |
358 | } | |
359 | glPopName(); | |
360 | } | |
361 | ||
57ffa5fb | 362 | /******************************************************************************/ |
915dabe1 | 363 | // Frame drawing |
57ffa5fb | 364 | /******************************************************************************/ |
915dabe1 | 365 | |
d810d0de | 366 | void AliEveTPCSector2DGL::TraceStepsUp(const AliEveTPCSectorData::SegmentInfo& s) |
915dabe1 | 367 | { |
a97abca8 | 368 | // Trace border of segment upwards. |
369 | ||
915dabe1 | 370 | Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth(); |
371 | Float_t y = s.GetRLow(); | |
372 | glVertex2f(x, y); | |
a15e6d7d | 373 | for (Int_t i = 0; i < s.GetNYSteps(); ++i) |
374 | { | |
915dabe1 | 375 | y = s.GetYStep(i); |
376 | glVertex2f(x, y); | |
377 | x -= s.GetPadWidth(); | |
378 | glVertex2f(x, y); | |
379 | } | |
380 | y = s.GetRLow() + s.GetNRows()*s.GetPadHeight(); | |
381 | glVertex2f(-s.GetNMaxPads()*s.GetPadWidth()/2, y); | |
382 | } | |
383 | ||
51346b82 | 384 | void AliEveTPCSector2DGL::TraceStepsDown(const AliEveTPCSectorData::SegmentInfo& s) |
915dabe1 | 385 | { |
a97abca8 | 386 | // Trace border of segment downwards. |
387 | ||
915dabe1 | 388 | Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2; |
389 | Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight(); | |
390 | glVertex2f(x, y); | |
a15e6d7d | 391 | for (Int_t i = s.GetNYSteps() - 1; i >= 0; --i) |
392 | { | |
915dabe1 | 393 | y = s.GetYStep(i); |
394 | glVertex2f(x, y); | |
395 | x -= s.GetPadWidth(); | |
396 | glVertex2f(x, y); | |
397 | } | |
398 | y = s.GetRLow(); | |
399 | glVertex2f((0.5*s.GetNMaxPads() - s.GetNYSteps())*s.GetPadWidth(), y); | |
400 | } | |
401 | ||
d810d0de | 402 | void AliEveTPCSector2DGL::DisplayFrame() const |
915dabe1 | 403 | { |
a97abca8 | 404 | // Display frame of the sector. |
405 | // Each segment's frame is drawn only if its data is drawn, too. | |
406 | ||
a15e6d7d | 407 | TGLUtil::Color(fSector->fFrameColor); |
915dabe1 | 408 | |
a15e6d7d | 409 | if(fSector->fRnrInn) |
410 | { | |
b56d8877 | 411 | glBegin(GL_POLYGON); |
d810d0de | 412 | TraceStepsUp (AliEveTPCSectorData::GetInnSeg()); |
413 | TraceStepsDown(AliEveTPCSectorData::GetInnSeg()); | |
b56d8877 | 414 | glEnd(); |
415 | } | |
a15e6d7d | 416 | if(fSector->fRnrOut1) |
417 | { | |
b56d8877 | 418 | glBegin(GL_POLYGON); |
d810d0de | 419 | TraceStepsUp (AliEveTPCSectorData::GetOut1Seg()); |
420 | TraceStepsDown(AliEveTPCSectorData::GetOut1Seg()); | |
b56d8877 | 421 | glEnd(); |
422 | } | |
a15e6d7d | 423 | if(fSector->fRnrOut2) |
424 | { | |
b56d8877 | 425 | glBegin(GL_POLYGON); |
d810d0de | 426 | TraceStepsUp (AliEveTPCSectorData::GetOut2Seg()); |
427 | TraceStepsDown(AliEveTPCSectorData::GetOut2Seg()); | |
b56d8877 | 428 | glEnd(); |
429 | } | |
915dabe1 | 430 | } |