]>
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 | ||
cb4245bb | 12 | #include <EveDet/AliEveTPCData.h> |
915dabe1 | 13 | |
19208112 | 14 | #include <TGLRnrCtx.h> |
15 | #include <TGLSelectRecord.h> | |
16 | #include <TGLIncludes.h> | |
d810d0de | 17 | |
57ffa5fb | 18 | //______________________________________________________________________________ |
68084553 | 19 | // |
a97abca8 | 20 | // GL renderer for TPCSector2D. |
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 | ||
50 | if (fImage) delete fImage; | |
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); | |
109 | glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); | |
110 | glEnable(GL_COLOR_MATERIAL); | |
111 | glDisable(GL_CULL_FACE); | |
112 | ||
113 | // Display digits | |
114 | if(fSectorData != 0) { | |
115 | ||
d810d0de | 116 | const AliEveTPCSectorData::SegmentInfo& iSeg = AliEveTPCSectorData::GetInnSeg(); |
117 | const AliEveTPCSectorData::SegmentInfo& o1Seg = AliEveTPCSectorData::GetOut1Seg(); | |
118 | const AliEveTPCSectorData::SegmentInfo& o2Seg = AliEveTPCSectorData::GetOut2Seg(); | |
915dabe1 | 119 | |
19208112 | 120 | if(rnrCtx.SecSelection()) { |
426530cc | 121 | |
122 | if(fSector->fRnrInn) DisplayNamedQuads(iSeg, 0, 0); | |
123 | if(fSector->fRnrOut1) DisplayNamedQuads(o1Seg, iSeg.GetNMaxPads(), 0); | |
124 | if(fSector->fRnrOut2) DisplayNamedQuads(o2Seg, 0, o1Seg.GetNRows()); | |
125 | ||
b56d8877 | 126 | } else { |
426530cc | 127 | |
128 | if(fSector->fUseTexture) { | |
129 | //texture | |
130 | glEnable(GL_BLEND); | |
131 | glDepthMask(GL_FALSE); | |
132 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
133 | ||
134 | glPolygonOffset(2,2); | |
135 | glEnable(GL_POLYGON_OFFSET_FILL); | |
136 | ||
137 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | |
138 | glBindTexture(GL_TEXTURE_2D, fTexture); | |
139 | glEnable(GL_TEXTURE_2D); | |
140 | ||
141 | if(fSector->fRnrInn) DisplayTexture(iSeg, 0, 0); | |
142 | if(fSector->fRnrOut1) DisplayTexture(o1Seg, iSeg.GetNMaxPads(), 0); | |
143 | if(fSector->fRnrOut2) DisplayTexture(o2Seg, 0, o1Seg.GetNRows()); | |
144 | ||
145 | glDisable(GL_TEXTURE_2D); | |
146 | } else { | |
147 | if(fSector->fRnrInn) DisplayQuads(iSeg, 0, 0); | |
148 | if(fSector->fRnrOut1) DisplayQuads(o1Seg, iSeg.GetNMaxPads(), 0); | |
149 | if(fSector->fRnrOut2) DisplayQuads(o2Seg, 0, o1Seg.GetNRows()); | |
150 | } | |
151 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | |
152 | DisplayFrame(); | |
915dabe1 | 153 | } |
915dabe1 | 154 | |
426530cc | 155 | } |
915dabe1 | 156 | |
157 | glPopAttrib(); | |
158 | } | |
159 | ||
57ffa5fb | 160 | /******************************************************************************/ |
915dabe1 | 161 | // Data import |
57ffa5fb | 162 | /******************************************************************************/ |
915dabe1 | 163 | |
d810d0de | 164 | void AliEveTPCSector2DGL::LoadPadrow(AliEveTPCSectorData::RowIterator& iter, |
a97abca8 | 165 | Int_t row, Int_t col_off) const |
915dabe1 | 166 | { |
a97abca8 | 167 | // Load data for one pad-row into the texture. |
168 | ||
b56d8877 | 169 | Int_t padVal; |
51346b82 | 170 | Int_t time, val; |
915dabe1 | 171 | |
b56d8877 | 172 | Int_t minTime = fSector->fMinTime; |
173 | Int_t maxTime = fSector->fMaxTime; | |
174 | Bool_t halfBorderTime = ((maxTime - minTime) % 2 == 0); | |
915dabe1 | 175 | |
176 | UChar_t* img_pos = GetRowCol(row, col_off); | |
177 | while (iter.NextPad()) { | |
51346b82 | 178 | padVal = 0; |
915dabe1 | 179 | |
180 | while (iter.Next()) { | |
181 | time = iter.Time(); | |
182 | val = iter.Signal(); | |
183 | ||
b56d8877 | 184 | if(time < minTime || time > maxTime) |
185 | continue; | |
186 | ||
915dabe1 | 187 | if(fSector->fShowMax) { |
b56d8877 | 188 | if(val > padVal) { |
189 | padVal = val; | |
915dabe1 | 190 | } |
191 | } else { | |
b56d8877 | 192 | if(halfBorderTime && (time == minTime || time == maxTime)) |
193 | padVal += val/2; | |
194 | else | |
195 | padVal += val; | |
915dabe1 | 196 | } |
197 | } | |
198 | ||
b56d8877 | 199 | if(fSector->fShowMax == kFALSE && fSector->fAverage) { |
200 | padVal = (Int_t)((Float_t)padVal / (maxTime - minTime)); | |
201 | } | |
202 | padVal = TMath::Min(padVal, fSector->fMaxVal); | |
203 | if(padVal > fSector->fThreshold) | |
891e4bb4 | 204 | fSector->ColorFromArray(padVal, img_pos); |
915dabe1 | 205 | img_pos += 4; |
206 | } | |
207 | } | |
208 | ||
57ffa5fb | 209 | /******************************************************************************/ |
915dabe1 | 210 | |
d810d0de | 211 | void AliEveTPCSector2DGL::CreateTexture() const |
915dabe1 | 212 | { |
a97abca8 | 213 | // Create texture that holds pad data. |
214 | ||
915dabe1 | 215 | if (fImage == 0 ) { |
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 |
234 | for (Int_t sId = 0; sId <= 2; ++sId) { | |
b56d8877 | 235 | if(isOn[sId] == kFALSE) |
236 | continue; | |
d810d0de | 237 | const AliEveTPCSectorData::SegmentInfo& sInfo = AliEveTPCSectorData::GetSeg(sId); |
915dabe1 | 238 | for (Int_t row=sInfo.GetFirstRow(); row<=sInfo.GetLastRow(); ++row) { |
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 | ||
915dabe1 | 289 | Float_t y_d, y_u; |
290 | Float_t x_off, x; | |
426530cc | 291 | Float_t padW = seg.GetPadWidth(); |
292 | Float_t padH = seg.GetPadHeight(); | |
915dabe1 | 293 | |
294 | glBegin(GL_QUADS); | |
426530cc | 295 | for (Int_t row=0; row<seg.GetNRows(); row++) { |
296 | y_d = seg.GetRLow() + row*padH; | |
915dabe1 | 297 | y_u = y_d + padH; |
426530cc | 298 | x_off = -seg.GetNMaxPads()*padW/2; |
299 | Int_t tpcRow = row + seg.GetFirstRow(); | |
d810d0de | 300 | Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2; |
426530cc | 301 | Int_t maxPad = seg.GetNMaxPads() - deltaPad; |
302 | UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad); | |
303 | for (Int_t pad=deltaPad; pad<maxPad; pad++, pix+=4) { | |
915dabe1 | 304 | x = x_off + pad*padW; |
305 | if (pix[3] != 0) { | |
306 | glColor4ubv(pix); | |
307 | glVertex2f(x+padW, y_d); | |
308 | glVertex2f(x, y_d); | |
309 | glVertex2f(x, y_u); | |
310 | glVertex2f(x+padW, y_u); | |
311 | } | |
312 | } | |
313 | } | |
314 | glEnd(); | |
315 | } | |
316 | ||
d810d0de | 317 | void AliEveTPCSector2DGL::DisplayNamedQuads(const AliEveTPCSectorData::SegmentInfo& seg, |
a97abca8 | 318 | Int_t startCol, Int_t startRow) const |
426530cc | 319 | { |
a97abca8 | 320 | // Display segmen data as one quad per pad. |
321 | // Tag the rows and pads for selection. | |
322 | ||
426530cc | 323 | Float_t y_d, y_u; |
324 | Float_t x_off, x; | |
325 | Float_t padW = seg.GetPadWidth(); | |
326 | Float_t padH = seg.GetPadHeight(); | |
327 | ||
328 | glPushName(0); | |
329 | for (Int_t row=0; row<seg.GetNRows(); row++) { | |
330 | y_d = seg.GetRLow() + row*padH; | |
331 | y_u = y_d + padH; | |
332 | x_off = -seg.GetNMaxPads()*padW/2; | |
333 | Int_t tpcRow = row + seg.GetFirstRow(); | |
334 | glLoadName(tpcRow); | |
d810d0de | 335 | Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2; |
426530cc | 336 | Int_t maxPad = seg.GetNMaxPads() - deltaPad; |
337 | UChar_t *pix = GetRowCol(row + startRow, startCol + deltaPad); | |
338 | glPushName(0); | |
339 | for (Int_t pad=deltaPad; pad<maxPad; pad++, pix+=4) { | |
340 | x = x_off + pad*padW; | |
a8600b56 | 341 | if (pix[3] != 0 || fSector->fPickEmpty) { |
426530cc | 342 | glLoadName(pad - deltaPad); |
343 | glBegin(GL_QUADS); | |
344 | glVertex2f(x+padW, y_d); | |
345 | glVertex2f(x, y_d); | |
346 | glVertex2f(x, y_u); | |
347 | glVertex2f(x+padW, y_u); | |
348 | glEnd(); | |
349 | } | |
350 | } | |
351 | glPopName(); | |
352 | } | |
353 | glPopName(); | |
354 | } | |
355 | ||
57ffa5fb | 356 | /******************************************************************************/ |
915dabe1 | 357 | // Frame drawing |
57ffa5fb | 358 | /******************************************************************************/ |
915dabe1 | 359 | |
d810d0de | 360 | void AliEveTPCSector2DGL::TraceStepsUp(const AliEveTPCSectorData::SegmentInfo& s) |
915dabe1 | 361 | { |
a97abca8 | 362 | // Trace border of segment upwards. |
363 | ||
915dabe1 | 364 | Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth(); |
365 | Float_t y = s.GetRLow(); | |
366 | glVertex2f(x, y); | |
367 | for (Int_t i=0; i<s.GetNYSteps(); ++i) { | |
368 | y = s.GetYStep(i); | |
369 | glVertex2f(x, y); | |
370 | x -= s.GetPadWidth(); | |
371 | glVertex2f(x, y); | |
372 | } | |
373 | y = s.GetRLow() + s.GetNRows()*s.GetPadHeight(); | |
374 | glVertex2f(-s.GetNMaxPads()*s.GetPadWidth()/2, y); | |
375 | } | |
376 | ||
51346b82 | 377 | void AliEveTPCSector2DGL::TraceStepsDown(const AliEveTPCSectorData::SegmentInfo& s) |
915dabe1 | 378 | { |
a97abca8 | 379 | // Trace border of segment downwards. |
380 | ||
915dabe1 | 381 | Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2; |
382 | Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight(); | |
383 | glVertex2f(x, y); | |
384 | for (Int_t i=s.GetNYSteps() - 1; i>=0; --i) { | |
385 | y = s.GetYStep(i); | |
386 | glVertex2f(x, y); | |
387 | x -= s.GetPadWidth(); | |
388 | glVertex2f(x, y); | |
389 | } | |
390 | y = s.GetRLow(); | |
391 | glVertex2f((0.5*s.GetNMaxPads() - s.GetNYSteps())*s.GetPadWidth(), y); | |
392 | } | |
393 | ||
d810d0de | 394 | void AliEveTPCSector2DGL::DisplayFrame() const |
915dabe1 | 395 | { |
a97abca8 | 396 | // Display frame of the sector. |
397 | // Each segment's frame is drawn only if its data is drawn, too. | |
398 | ||
092578a7 | 399 | UChar_t col[4]; |
d810d0de | 400 | TEveUtil::TEveUtil::ColorFromIdx(fSector->fFrameColor, col); |
092578a7 | 401 | glColor4ubv(col); |
915dabe1 | 402 | |
b56d8877 | 403 | if(fSector->fRnrInn) { |
404 | glBegin(GL_POLYGON); | |
d810d0de | 405 | TraceStepsUp (AliEveTPCSectorData::GetInnSeg()); |
406 | TraceStepsDown(AliEveTPCSectorData::GetInnSeg()); | |
b56d8877 | 407 | glEnd(); |
408 | } | |
409 | if(fSector->fRnrOut1) { | |
410 | glBegin(GL_POLYGON); | |
d810d0de | 411 | TraceStepsUp (AliEveTPCSectorData::GetOut1Seg()); |
412 | TraceStepsDown(AliEveTPCSectorData::GetOut1Seg()); | |
b56d8877 | 413 | glEnd(); |
414 | } | |
415 | if(fSector->fRnrOut2) { | |
416 | glBegin(GL_POLYGON); | |
d810d0de | 417 | TraceStepsUp (AliEveTPCSectorData::GetOut2Seg()); |
418 | TraceStepsDown(AliEveTPCSectorData::GetOut2Seg()); | |
b56d8877 | 419 | glEnd(); |
420 | } | |
915dabe1 | 421 | } |