]>
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 | |
68ca2fe7 | 100 | if (fRTS < fSector->fRTS && fSectorData != 0) { |
915dabe1 | 101 | CreateTexture(); |
102 | fRTS = fSector->fRTS; | |
103 | } | |
104 | ||
68ca2fe7 | 105 | glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_POLYGON_BIT | GL_ENABLE_BIT); |
915dabe1 | 106 | |
107 | glDisable(GL_LIGHTING); | |
915dabe1 | 108 | glDisable(GL_CULL_FACE); |
109 | ||
110 | // Display digits | |
68ca2fe7 | 111 | if (fSectorData != 0) |
112 | { | |
d810d0de | 113 | const AliEveTPCSectorData::SegmentInfo& iSeg = AliEveTPCSectorData::GetInnSeg(); |
114 | const AliEveTPCSectorData::SegmentInfo& o1Seg = AliEveTPCSectorData::GetOut1Seg(); | |
115 | const AliEveTPCSectorData::SegmentInfo& o2Seg = AliEveTPCSectorData::GetOut2Seg(); | |
915dabe1 | 116 | |
68ca2fe7 | 117 | if (rnrCtx.SecSelection()) |
118 | { | |
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()); | |
68ca2fe7 | 123 | } |
124 | else | |
125 | { | |
126 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | |
127 | if (fSector->fUseTexture) | |
128 | { | |
426530cc | 129 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
68ca2fe7 | 130 | glEnable(GL_BLEND); |
426530cc | 131 | |
68ca2fe7 | 132 | glAlphaFunc(GL_GREATER, 0.2); |
133 | glEnable(GL_ALPHA_TEST); | |
426530cc | 134 | |
426530cc | 135 | glBindTexture(GL_TEXTURE_2D, fTexture); |
136 | glEnable(GL_TEXTURE_2D); | |
137 | ||
138 | if(fSector->fRnrInn) DisplayTexture(iSeg, 0, 0); | |
139 | if(fSector->fRnrOut1) DisplayTexture(o1Seg, iSeg.GetNMaxPads(), 0); | |
140 | if(fSector->fRnrOut2) DisplayTexture(o2Seg, 0, o1Seg.GetNRows()); | |
141 | ||
142 | glDisable(GL_TEXTURE_2D); | |
68ca2fe7 | 143 | } |
144 | else | |
145 | { | |
426530cc | 146 | if(fSector->fRnrInn) DisplayQuads(iSeg, 0, 0); |
147 | if(fSector->fRnrOut1) DisplayQuads(o1Seg, iSeg.GetNMaxPads(), 0); | |
148 | if(fSector->fRnrOut2) DisplayQuads(o2Seg, 0, o1Seg.GetNRows()); | |
149 | } | |
150 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | |
151 | DisplayFrame(); | |
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 | ||
68ca2fe7 | 197 | if (fSector->fShowMax == kFALSE && fSector->fAverage) { |
b56d8877 | 198 | padVal = (Int_t)((Float_t)padVal / (maxTime - minTime)); |
199 | } | |
200 | padVal = TMath::Min(padVal, fSector->fMaxVal); | |
68ca2fe7 | 201 | if (padVal > fSector->fThreshold) { |
a15e6d7d | 202 | fSector->ColorFromArray(padVal, imgPos); |
68ca2fe7 | 203 | } |
a15e6d7d | 204 | imgPos += 4; |
915dabe1 | 205 | } |
206 | } | |
207 | ||
57ffa5fb | 208 | /******************************************************************************/ |
915dabe1 | 209 | |
d810d0de | 210 | void AliEveTPCSector2DGL::CreateTexture() const |
915dabe1 | 211 | { |
a97abca8 | 212 | // Create texture that holds pad data. |
213 | ||
68ca2fe7 | 214 | if (fImage == 0) |
215 | { | |
915dabe1 | 216 | fImage = new UChar_t[fgkTextureByteSize]; |
217 | glGenTextures(1, &fTexture); | |
218 | } | |
219 | memset(fImage, 0, fgkTextureByteSize); | |
220 | ||
221 | Int_t rowOff[3], colOff[3]; | |
b56d8877 | 222 | Bool_t isOn[3]; |
223 | rowOff[0] = 0; | |
d810d0de | 224 | rowOff[1] = rowOff[2] = -AliEveTPCSectorData::GetSeg(1).GetFirstRow(); |
b56d8877 | 225 | colOff[0] = colOff[2] = 0; |
d810d0de | 226 | colOff[1] = AliEveTPCSectorData::GetSeg(0).GetNMaxPads(); |
b56d8877 | 227 | isOn[0] = fSector->fRnrInn; |
228 | isOn[1] = fSector->fRnrOut1; | |
229 | isOn[2] = fSector->fRnrOut2; | |
915dabe1 | 230 | |
891e4bb4 | 231 | fSector->SetupColorArray(); |
232 | ||
915dabe1 | 233 | // Loop over 3 main segments |
a15e6d7d | 234 | for (Int_t sId = 0; sId <= 2; ++sId) |
235 | { | |
236 | if (isOn[sId] == kFALSE) | |
b56d8877 | 237 | continue; |
d810d0de | 238 | const AliEveTPCSectorData::SegmentInfo& sInfo = AliEveTPCSectorData::GetSeg(sId); |
a15e6d7d | 239 | for (Int_t row = sInfo.GetFirstRow(); row <= sInfo.GetLastRow(); ++row) |
240 | { | |
d810d0de | 241 | AliEveTPCSectorData::RowIterator i = fSectorData->MakeRowIterator(row); |
242 | Int_t offset = (sInfo.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(row))/2; | |
915dabe1 | 243 | LoadPadrow(i, row + rowOff[sId], offset + colOff[sId]); |
244 | } | |
245 | } | |
246 | ||
247 | glBindTexture (GL_TEXTURE_2D, fTexture); | |
248 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT); | |
249 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT); | |
250 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
251 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
426530cc | 252 | glTexEnvf (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE); |
915dabe1 | 253 | glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, fgkTextureWidth, fgkTextureHeight, |
254 | 0, GL_RGBA, GL_UNSIGNED_BYTE, fImage); | |
255 | ||
256 | } | |
257 | ||
57ffa5fb | 258 | /******************************************************************************/ |
915dabe1 | 259 | // Data display |
57ffa5fb | 260 | /******************************************************************************/ |
915dabe1 | 261 | |
d810d0de | 262 | void AliEveTPCSector2DGL::DisplayTexture(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 263 | Int_t startCol, Int_t startRow) const |
915dabe1 | 264 | { |
a97abca8 | 265 | // Display segment data via one textured rectangle. |
266 | ||
426530cc | 267 | Float_t w = seg.GetNMaxPads()*seg.GetPadWidth()/2; |
268 | Float_t y1 = seg.GetRLow(); | |
269 | Float_t y2 = y1 + seg.GetNRows()*seg.GetPadHeight(); | |
270 | ||
915dabe1 | 271 | Float_t u1 = (Float_t) startCol / fgkTextureWidth; |
272 | Float_t v1 = (Float_t) startRow / fgkTextureHeight; | |
426530cc | 273 | Float_t u2 = u1 + (Float_t) seg.GetNMaxPads() / fgkTextureWidth; |
274 | Float_t v2 = v1 + (Float_t) seg.GetNRows() / fgkTextureHeight; | |
915dabe1 | 275 | |
51346b82 | 276 | glBegin(GL_QUADS); |
426530cc | 277 | glTexCoord2f(u1, v1); glVertex2f(-w, y1); |
278 | glTexCoord2f(u1, v2); glVertex2f(-w, y2); | |
279 | glTexCoord2f(u2, v2); glVertex2f( w, y2); | |
280 | glTexCoord2f(u2, v1); glVertex2f( w, y1); | |
915dabe1 | 281 | glEnd(); |
282 | } | |
283 | ||
57ffa5fb | 284 | /******************************************************************************/ |
915dabe1 | 285 | |
d810d0de | 286 | void AliEveTPCSector2DGL::DisplayQuads(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 287 | Int_t startCol, Int_t startRow) const |
915dabe1 | 288 | { |
a97abca8 | 289 | // Display segment data by rendering one quad per pad. |
290 | ||
a15e6d7d | 291 | Float_t yD, yU; |
292 | Float_t xOff, x; | |
426530cc | 293 | Float_t padW = seg.GetPadWidth(); |
294 | Float_t padH = seg.GetPadHeight(); | |
915dabe1 | 295 | |
296 | glBegin(GL_QUADS); | |
a15e6d7d | 297 | for (Int_t row = 0; row < seg.GetNRows(); row++) |
298 | { | |
299 | yD = seg.GetRLow() + row*padH; | |
300 | yU = yD + padH; | |
301 | xOff = -seg.GetNMaxPads()*padW/2; | |
426530cc | 302 | Int_t tpcRow = row + seg.GetFirstRow(); |
d810d0de | 303 | Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2; |
426530cc | 304 | Int_t maxPad = seg.GetNMaxPads() - deltaPad; |
305 | UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad); | |
a15e6d7d | 306 | for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4) |
307 | { | |
308 | x = xOff + pad*padW; | |
309 | if (pix[3] != 0) | |
310 | { | |
311 | TGLUtil::Color4ubv(pix); | |
312 | glVertex2f(x+padW, yD); | |
313 | glVertex2f(x, yD); | |
314 | glVertex2f(x, yU); | |
315 | glVertex2f(x+padW, yU); | |
915dabe1 | 316 | } |
317 | } | |
318 | } | |
319 | glEnd(); | |
320 | } | |
321 | ||
d810d0de | 322 | void AliEveTPCSector2DGL::DisplayNamedQuads(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 323 | Int_t startCol, Int_t startRow) const |
426530cc | 324 | { |
a97abca8 | 325 | // Display segmen data as one quad per pad. |
326 | // Tag the rows and pads for selection. | |
327 | ||
a15e6d7d | 328 | Float_t yD, yU; |
329 | Float_t xOff, x; | |
426530cc | 330 | Float_t padW = seg.GetPadWidth(); |
331 | Float_t padH = seg.GetPadHeight(); | |
332 | ||
333 | glPushName(0); | |
a15e6d7d | 334 | for (Int_t row = 0; row < seg.GetNRows(); row++) |
335 | { | |
336 | yD = seg.GetRLow() + row*padH; | |
337 | yU = yD + padH; | |
338 | xOff = -seg.GetNMaxPads()*padW/2; | |
426530cc | 339 | Int_t tpcRow = row + seg.GetFirstRow(); |
340 | glLoadName(tpcRow); | |
d810d0de | 341 | Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2; |
426530cc | 342 | Int_t maxPad = seg.GetNMaxPads() - deltaPad; |
343 | UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad); | |
344 | glPushName(0); | |
a15e6d7d | 345 | for (Int_t pad = deltaPad; pad < maxPad; pad++, pix+=4) |
346 | { | |
347 | x = xOff + pad*padW; | |
348 | if (pix[3] != 0 || fSector->fPickEmpty) | |
349 | { | |
426530cc | 350 | glLoadName(pad - deltaPad); |
351 | glBegin(GL_QUADS); | |
a15e6d7d | 352 | glVertex2f(x+padW, yD); |
353 | glVertex2f(x, yD); | |
354 | glVertex2f(x, yU); | |
355 | glVertex2f(x+padW, yU); | |
426530cc | 356 | glEnd(); |
357 | } | |
358 | } | |
359 | glPopName(); | |
360 | } | |
361 | glPopName(); | |
362 | } | |
363 | ||
57ffa5fb | 364 | /******************************************************************************/ |
915dabe1 | 365 | // Frame drawing |
57ffa5fb | 366 | /******************************************************************************/ |
915dabe1 | 367 | |
d810d0de | 368 | void AliEveTPCSector2DGL::TraceStepsUp(const AliEveTPCSectorData::SegmentInfo& s) |
915dabe1 | 369 | { |
a97abca8 | 370 | // Trace border of segment upwards. |
371 | ||
915dabe1 | 372 | Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth(); |
373 | Float_t y = s.GetRLow(); | |
374 | glVertex2f(x, y); | |
a15e6d7d | 375 | for (Int_t i = 0; i < s.GetNYSteps(); ++i) |
376 | { | |
915dabe1 | 377 | y = s.GetYStep(i); |
378 | glVertex2f(x, y); | |
379 | x -= s.GetPadWidth(); | |
380 | glVertex2f(x, y); | |
381 | } | |
382 | y = s.GetRLow() + s.GetNRows()*s.GetPadHeight(); | |
383 | glVertex2f(-s.GetNMaxPads()*s.GetPadWidth()/2, y); | |
384 | } | |
385 | ||
51346b82 | 386 | void AliEveTPCSector2DGL::TraceStepsDown(const AliEveTPCSectorData::SegmentInfo& s) |
915dabe1 | 387 | { |
a97abca8 | 388 | // Trace border of segment downwards. |
389 | ||
915dabe1 | 390 | Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2; |
391 | Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight(); | |
392 | glVertex2f(x, y); | |
a15e6d7d | 393 | for (Int_t i = s.GetNYSteps() - 1; i >= 0; --i) |
394 | { | |
915dabe1 | 395 | y = s.GetYStep(i); |
396 | glVertex2f(x, y); | |
397 | x -= s.GetPadWidth(); | |
398 | glVertex2f(x, y); | |
399 | } | |
400 | y = s.GetRLow(); | |
401 | glVertex2f((0.5*s.GetNMaxPads() - s.GetNYSteps())*s.GetPadWidth(), y); | |
402 | } | |
403 | ||
d810d0de | 404 | void AliEveTPCSector2DGL::DisplayFrame() const |
915dabe1 | 405 | { |
a97abca8 | 406 | // Display frame of the sector. |
407 | // Each segment's frame is drawn only if its data is drawn, too. | |
408 | ||
a15e6d7d | 409 | TGLUtil::Color(fSector->fFrameColor); |
915dabe1 | 410 | |
a15e6d7d | 411 | if(fSector->fRnrInn) |
412 | { | |
b56d8877 | 413 | glBegin(GL_POLYGON); |
d810d0de | 414 | TraceStepsUp (AliEveTPCSectorData::GetInnSeg()); |
415 | TraceStepsDown(AliEveTPCSectorData::GetInnSeg()); | |
b56d8877 | 416 | glEnd(); |
417 | } | |
a15e6d7d | 418 | if(fSector->fRnrOut1) |
419 | { | |
b56d8877 | 420 | glBegin(GL_POLYGON); |
d810d0de | 421 | TraceStepsUp (AliEveTPCSectorData::GetOut1Seg()); |
422 | TraceStepsDown(AliEveTPCSectorData::GetOut1Seg()); | |
b56d8877 | 423 | glEnd(); |
424 | } | |
a15e6d7d | 425 | if(fSector->fRnrOut2) |
426 | { | |
b56d8877 | 427 | glBegin(GL_POLYGON); |
d810d0de | 428 | TraceStepsUp (AliEveTPCSectorData::GetOut2Seg()); |
429 | TraceStepsDown(AliEveTPCSectorData::GetOut2Seg()); | |
b56d8877 | 430 | glEnd(); |
431 | } | |
915dabe1 | 432 | } |