CMake: removing qpythia from the depedencies
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveTPCSector2DGL.cxx
1 // $Id$
2 // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3
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  **************************************************************************/
9
10 #include "AliEveTPCSector2DGL.h"
11
12 #include <AliEveTPCSector2D.h>
13
14 #include <TGLRnrCtx.h>
15 #include <TGLSelectRecord.h>
16 #include <TGLIncludes.h>
17
18 //______________________________________________________________________________
19 //
20 // GL renderer for AliEveTPCSector2D.
21
22 ClassImp(AliEveTPCSector2DGL)
23
24 // This can be optimized to non-pow-2 values once everybody has GL 1.4.
25
26 const Int_t AliEveTPCSector2DGL::fgkTextureWidth    = 256;
27 const Int_t AliEveTPCSector2DGL::fgkTextureHeight   = 128;
28 const Int_t AliEveTPCSector2DGL::fgkTextureByteSize = 4*256*128;
29
30 /******************************************************************************/
31
32 AliEveTPCSector2DGL::AliEveTPCSector2DGL() :
33   TGLObject(),
34
35   fSector     (0),
36   fSectorData (0),
37
38   fImage   (0),
39   fTexture (0),
40   fRTS     (0)
41 {
42   // Constructor.
43 }
44
45 AliEveTPCSector2DGL::~AliEveTPCSector2DGL()
46 {
47   // Destructor.
48   // !!!! Should unregister texture via ContextIdentity!
49
50   if (fImage)   delete [] fImage;
51   if (fTexture) glDeleteTextures(1, &fTexture);
52 }
53
54 /******************************************************************************/
55
56 Bool_t AliEveTPCSector2DGL::SetModel(TObject* obj, const Option_t* /*opt*/)
57 {
58   // Set model object.
59
60   if (SetModelCheckClass(obj, AliEveTPCSector2D::Class())) {
61     fSector = (AliEveTPCSector2D*) fExternalObj;
62     return kTRUE;
63   }
64   return kFALSE;
65 }
66
67 void AliEveTPCSector2DGL::SetBBox()
68 {
69   // Set bounding-box.
70
71   SetAxisAlignedBBox(((AliEveTPCSector2D*)fExternalObj)->AssertBBox());
72 }
73
74 /******************************************************************************/
75
76 void AliEveTPCSector2DGL::ProcessSelection(TGLRnrCtx       & /*rnrCtx*/,
77                                            TGLSelectRecord & rec)
78 {
79   // Process selection record.
80   // Determine row and pad, call PadSelected() in model object.
81
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);
88 }
89
90 /******************************************************************************/
91
92 void AliEveTPCSector2DGL::DirectDraw(TGLRnrCtx& rnrCtx) const
93 {
94   // Actual GL drawing.
95
96   // printf("AliEveTPCSector2DGL::DirectDraw \n");
97
98   fSectorData = fSector->GetSectorData();
99
100   if (fRTS < fSector->fRTS && fSectorData != 0) {
101     CreateTexture();
102     fRTS = fSector->fRTS;
103   }
104
105   glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_POLYGON_BIT | GL_ENABLE_BIT);
106
107   glDisable(GL_LIGHTING);
108   glDisable(GL_CULL_FACE);
109
110   // Display digits
111   if (fSectorData != 0)
112   {
113     const AliEveTPCSectorData::SegmentInfo&  iSeg = AliEveTPCSectorData::GetInnSeg();
114     const AliEveTPCSectorData::SegmentInfo& o1Seg = AliEveTPCSectorData::GetOut1Seg();
115     const AliEveTPCSectorData::SegmentInfo& o2Seg = AliEveTPCSectorData::GetOut2Seg();
116
117     if (rnrCtx.SecSelection())
118     {
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     }
124     else
125     {
126       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
127       if (fSector->fUseTexture)
128       {
129         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
130         glEnable(GL_BLEND);
131
132         glAlphaFunc(GL_GREATER, 0.2);
133         glEnable(GL_ALPHA_TEST);
134
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);
143       }
144       else
145       {
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();
152     }
153   }
154
155   glPopAttrib();
156 }
157
158 /******************************************************************************/
159 // Data import
160 /******************************************************************************/
161
162 void AliEveTPCSector2DGL::LoadPadrow(AliEveTPCSectorData::RowIterator& iter,
163                                      Int_t row, Int_t colOff) const
164 {
165   // Load data for one pad-row into the texture.
166
167   Int_t    padVal;
168   Int_t    time, val;
169
170   Int_t    minTime = fSector->fMinTime;
171   Int_t    maxTime = fSector->fMaxTime;
172   Bool_t   halfBorderTime = ((maxTime - minTime) % 2 == 0);
173
174   UChar_t* imgPos = GetRowCol(row, colOff);
175   while (iter.NextPad()) {
176     padVal = 0;
177
178     while (iter.Next()) {
179       time = iter.Time();
180       val  = iter.Signal();
181
182       if(time < minTime || time > maxTime)
183         continue;
184
185       if(fSector->fShowMax) {
186         if(val > padVal) {
187           padVal = val;
188         }
189       } else {
190         if(halfBorderTime && (time == minTime || time == maxTime))
191           padVal += val/2;
192         else
193           padVal += val;
194       }
195     }
196
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) {
202       fSector->ColorFromArray(padVal, imgPos);
203     }
204     imgPos += 4;
205   }
206 }
207
208 /******************************************************************************/
209
210 void AliEveTPCSector2DGL::CreateTexture() const
211 {
212   // Create texture that holds pad data.
213
214   if (fImage == 0)
215   {
216     fImage = new UChar_t[fgkTextureByteSize];
217     glGenTextures(1, &fTexture);
218   }
219   memset(fImage, 0, fgkTextureByteSize);
220
221   Int_t rowOff[3], colOff[3];
222   Bool_t isOn[3];
223   rowOff[0] = 0;
224   rowOff[1] = rowOff[2] = -AliEveTPCSectorData::GetSeg(1).GetFirstRow();
225   colOff[0] = colOff[2] = 0;
226   colOff[1] = AliEveTPCSectorData::GetSeg(0).GetNMaxPads();
227   isOn[0] = fSector->fRnrInn;
228   isOn[1] = fSector->fRnrOut1;
229   isOn[2] = fSector->fRnrOut2;
230
231   fSector->SetupColorArray();
232
233   // Loop over 3 main segments
234   for (Int_t sId = 0; sId <= 2; ++sId)
235   {
236     if (isOn[sId] == kFALSE)
237       continue;
238     const AliEveTPCSectorData::SegmentInfo& sInfo = AliEveTPCSectorData::GetSeg(sId);
239     for (Int_t row = sInfo.GetFirstRow(); row <= sInfo.GetLastRow(); ++row)
240     {
241       AliEveTPCSectorData::RowIterator i = fSectorData->MakeRowIterator(row);
242       Int_t offset = (sInfo.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(row))/2;
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);
252   glTexEnvf      (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,   GL_REPLACE);
253   glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, fgkTextureWidth, fgkTextureHeight,
254                   0, GL_RGBA, GL_UNSIGNED_BYTE, fImage);
255
256 }
257
258 /******************************************************************************/
259 // Data display
260 /******************************************************************************/
261
262 void AliEveTPCSector2DGL::DisplayTexture(const AliEveTPCSectorData::SegmentInfo& seg,
263                                          Int_t startCol, Int_t startRow) const
264 {
265   // Display segment data via one textured rectangle.
266
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
271   Float_t u1 = (Float_t) startCol / fgkTextureWidth;
272   Float_t v1 = (Float_t) startRow / fgkTextureHeight;
273   Float_t u2 = u1 + (Float_t) seg.GetNMaxPads() / fgkTextureWidth;
274   Float_t v2 = v1 + (Float_t) seg.GetNRows()    / fgkTextureHeight;
275
276   glBegin(GL_QUADS);
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);
281   glEnd();
282 }
283
284 /******************************************************************************/
285
286 void AliEveTPCSector2DGL::DisplayQuads(const AliEveTPCSectorData::SegmentInfo& seg,
287                                        Int_t startCol, Int_t startRow) const
288 {
289   // Display segment data by rendering one quad per pad.
290
291   Float_t yD, yU;
292   Float_t xOff, x;
293   Float_t padW = seg.GetPadWidth();
294   Float_t padH = seg.GetPadHeight();
295
296   glBegin(GL_QUADS);
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;
302     Int_t tpcRow = row + seg.GetFirstRow();
303     Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2;
304     Int_t   maxPad = seg.GetNMaxPads() - deltaPad;
305     UChar_t   *pix = GetRowCol(row + startRow, startCol + deltaPad);
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);
316       }
317     }
318   }
319   glEnd();
320 }
321
322 void AliEveTPCSector2DGL::DisplayNamedQuads(const AliEveTPCSectorData::SegmentInfo& seg,
323                                             Int_t startCol, Int_t startRow) const
324 {
325   // Display segmen data as one quad per pad.
326   // Tag the rows and pads for selection.
327
328   Float_t yD, yU;
329   Float_t xOff, x;
330   Float_t padW = seg.GetPadWidth();
331   Float_t padH = seg.GetPadHeight();
332
333   glPushName(0);
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;
339     Int_t tpcRow = row + seg.GetFirstRow();
340     glLoadName(tpcRow);
341     Int_t deltaPad = (seg.GetNMaxPads() - AliEveTPCSectorData::GetNPadsInRow(tpcRow))/2;
342     Int_t   maxPad = seg.GetNMaxPads() - deltaPad;
343     UChar_t   *pix = GetRowCol(row + startRow, startCol + deltaPad);
344     glPushName(0);
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       {
350         glLoadName(pad - deltaPad);
351         glBegin(GL_QUADS);
352         glVertex2f(x+padW, yD);
353         glVertex2f(x,      yD);
354         glVertex2f(x,      yU);
355         glVertex2f(x+padW, yU);
356         glEnd();
357       }
358     }
359     glPopName();
360   }
361   glPopName();
362 }
363
364 /******************************************************************************/
365 // Frame drawing
366 /******************************************************************************/
367
368 void AliEveTPCSector2DGL::TraceStepsUp(const AliEveTPCSectorData::SegmentInfo& s)
369 {
370   // Trace border of segment upwards.
371
372   Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth();
373   Float_t y  = s.GetRLow();
374   glVertex2f(x, y);
375   for (Int_t i = 0; i < s.GetNYSteps(); ++i)
376   {
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
386 void AliEveTPCSector2DGL::TraceStepsDown(const AliEveTPCSectorData::SegmentInfo& s)
387 {
388   // Trace border of segment downwards.
389
390   Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2;
391   Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight();
392   glVertex2f(x, y);
393   for (Int_t i = s.GetNYSteps() - 1; i >= 0; --i)
394   {
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
404 void AliEveTPCSector2DGL::DisplayFrame() const
405 {
406   // Display frame of the sector.
407   // Each segment's frame is drawn only if its data is drawn, too.
408
409   TGLUtil::Color(fSector->fFrameColor);
410
411   if(fSector->fRnrInn)
412   {
413     glBegin(GL_POLYGON);
414     TraceStepsUp  (AliEveTPCSectorData::GetInnSeg());
415     TraceStepsDown(AliEveTPCSectorData::GetInnSeg());
416     glEnd();
417   }
418   if(fSector->fRnrOut1)
419   {
420     glBegin(GL_POLYGON);
421     TraceStepsUp  (AliEveTPCSectorData::GetOut1Seg());
422     TraceStepsDown(AliEveTPCSectorData::GetOut1Seg());
423     glEnd();
424   }
425   if(fSector->fRnrOut2)
426   {
427     glBegin(GL_POLYGON);
428     TraceStepsUp  (AliEveTPCSectorData::GetOut2Seg());
429     TraceStepsDown(AliEveTPCSectorData::GetOut2Seg());
430     glEnd();
431   }
432 }