Merge from EVE-dev.
[u/mrichter/AliRoot.git] / EVE / Alieve / TPCSector2DGL.cxx
1 // $Header$
2
3 #include "TPCSector2DGL.h"
4
5 #include <Alieve/TPCData.h>
6
7 #include <TStopwatch.h>
8
9 #include <TGLDrawFlags.h>
10 #include <GL/gl.h>
11
12 using namespace Reve;
13 using namespace Alieve;
14 using namespace std;
15
16 //______________________________________________________________________
17 // TPCSector2DGL
18 //
19
20 ClassImp(TPCSector2DGL)
21
22 // This can be optimized to non-pow-2 values once everybody has GL 1.4.
23
24 const Int_t TPCSector2DGL::fgkTextureWidth    = 256;
25 const Int_t TPCSector2DGL::fgkTextureHeight   = 128;
26 const Int_t TPCSector2DGL::fgkTextureByteSize = 4*256*128;
27
28 /**************************************************************************/
29
30 TPCSector2DGL::TPCSector2DGL() : TGLObject()
31 {
32   fSector     = 0;
33   fSectorData = 0;
34
35   fImage   = 0;
36   fTexture = 0;
37   fRTS     = 0;
38 }
39
40 TPCSector2DGL::~TPCSector2DGL()
41 {
42   if(fImage)   delete fImage;
43   if(fTexture) glDeleteTextures(1, &fTexture);
44 }
45
46 /**************************************************************************/
47
48 Bool_t TPCSector2DGL::SetModel(TObject* obj)
49 {
50 #if ROOT_VERSION_CODE <= ROOT_VERSION(5,11,2)
51   if(set_model(obj, "Alieve::TPCSector2D")) {
52 #elif ROOT_VERSION_CODE <= ROOT_VERSION(5,13,0)
53   if(SetModelCheckClass(obj, "Alieve::TPCSector2D")) {
54 #else
55   if(SetModelCheckClass(obj, Alieve::TPCSector2D::Class())) {
56 #endif
57     fSector = (TPCSector2D*) fExternalObj;
58     return kTRUE;
59   }
60   return kFALSE;
61 }
62
63 void TPCSector2DGL::SetBBox()
64 {
65 #if ROOT_VERSION_CODE <= ROOT_VERSION(5,11,2)
66   set_axis_aligned_bbox(((TPCSector2D*)fExternalObj)->AssertBBox());
67 #else
68   SetAxisAlignedBBox(((TPCSector2D*)fExternalObj)->AssertBBox());
69 #endif
70 }
71
72 /**************************************************************************/
73
74 void TPCSector2DGL::DirectDraw(const TGLDrawFlags& flags) const
75 {
76   // Actual GL drawing.
77
78   // printf("TPCSector2DGL::DirectDraw \n");
79
80   fSectorData = fSector->GetSectorData();
81
82   if(fRTS < fSector->fRTS && fSectorData != 0) {
83     CreateTexture();
84     fRTS = fSector->fRTS;
85   }
86
87   glPushAttrib(GL_CURRENT_BIT      | GL_DEPTH_BUFFER_BIT |
88                GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT       | GL_POLYGON_BIT);
89
90   glDisable(GL_LIGHTING);
91   glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
92   glEnable(GL_COLOR_MATERIAL);
93   glDisable(GL_CULL_FACE);
94
95   // Display digits
96   if(fSectorData != 0) {
97
98     const TPCSectorData::SegmentInfo&  iSeg = TPCSectorData::GetInnSeg();
99     const TPCSectorData::SegmentInfo& o1Seg = TPCSectorData::GetOut1Seg();
100     const TPCSectorData::SegmentInfo& o2Seg = TPCSectorData::GetOut2Seg();
101
102     if(flags.SecSelection()) {
103
104       if(fSector->fRnrInn)  DisplayNamedQuads(iSeg, 0, 0);
105       if(fSector->fRnrOut1) DisplayNamedQuads(o1Seg, iSeg.GetNMaxPads(), 0);
106       if(fSector->fRnrOut2) DisplayNamedQuads(o2Seg, 0, o1Seg.GetNRows());
107
108     } else {
109
110       if(fSector->fUseTexture) {
111         //texture
112         glEnable(GL_BLEND);
113         glDepthMask(GL_FALSE);
114         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
115
116         glPolygonOffset(2,2);
117         glEnable(GL_POLYGON_OFFSET_FILL);
118
119         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
120         glBindTexture(GL_TEXTURE_2D, fTexture);
121         glEnable(GL_TEXTURE_2D);
122
123         if(fSector->fRnrInn)  DisplayTexture(iSeg, 0, 0);
124         if(fSector->fRnrOut1) DisplayTexture(o1Seg, iSeg.GetNMaxPads(), 0);
125         if(fSector->fRnrOut2) DisplayTexture(o2Seg, 0, o1Seg.GetNRows());
126
127         glDisable(GL_TEXTURE_2D);
128       } else {
129         if(fSector->fRnrInn)  DisplayQuads(iSeg, 0, 0);
130         if(fSector->fRnrOut1) DisplayQuads(o1Seg, iSeg.GetNMaxPads(), 0);
131         if(fSector->fRnrOut2) DisplayQuads(o2Seg, 0, o1Seg.GetNRows());
132       }
133       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
134       DisplayFrame();
135     }
136
137   }
138
139   glPopAttrib();
140 }
141
142 /**************************************************************************/
143 // Data import
144 /**************************************************************************/
145
146 void TPCSector2DGL::LoadPadrow(TPCSectorData::RowIterator& iter,
147                                Int_t row, Int_t col_off) const
148 {
149   Int_t    padVal;
150   Int_t    time, val;   
151
152   Int_t    minTime = fSector->fMinTime;
153   Int_t    maxTime = fSector->fMaxTime;
154   Bool_t   halfBorderTime = ((maxTime - minTime) % 2 == 0);
155
156   UChar_t* img_pos = GetRowCol(row, col_off);
157   while (iter.NextPad()) {
158     padVal = 0; 
159
160     while (iter.Next()) {
161       time = iter.Time();
162       val  = iter.Signal();
163
164       if(time < minTime || time > maxTime)
165         continue;
166
167       if(fSector->fShowMax) {
168         if(val > padVal) {
169           padVal = val;
170         }
171       } else {
172         if(halfBorderTime && (time == minTime || time == maxTime))
173           padVal += val/2;
174         else
175           padVal += val;
176       }
177     }
178
179     if(fSector->fShowMax == kFALSE && fSector->fAverage) {
180       padVal = (Int_t)((Float_t)padVal / (maxTime - minTime));
181     }
182     padVal = TMath::Min(padVal, fSector->fMaxVal);
183     if(padVal > fSector->fThreshold)
184       fSector->ColorFromArray(padVal, img_pos);
185     img_pos += 4;
186   }
187 }
188
189 /**************************************************************************/
190
191 void TPCSector2DGL::CreateTexture() const
192 {
193   if (fImage == 0 ) {
194     fImage = new UChar_t[fgkTextureByteSize];
195     glGenTextures(1, &fTexture);
196   }
197   memset(fImage, 0, fgkTextureByteSize);
198
199   Int_t rowOff[3], colOff[3];
200   Bool_t isOn[3];
201   rowOff[0] = 0;
202   rowOff[1] = rowOff[2] = -TPCSectorData::GetSeg(1).GetFirstRow();
203   colOff[0] = colOff[2] = 0;
204   colOff[1] = TPCSectorData::GetSeg(0).GetNMaxPads();
205   isOn[0] = fSector->fRnrInn;
206   isOn[1] = fSector->fRnrOut1;
207   isOn[2] = fSector->fRnrOut2;
208
209   fSector->SetupColorArray();
210
211   // Loop over 3 main segments
212   for (Int_t sId = 0; sId <= 2; ++sId) {
213     if(isOn[sId] == kFALSE)
214       continue;
215     const TPCSectorData::SegmentInfo& sInfo = TPCSectorData::GetSeg(sId);
216     for (Int_t row=sInfo.GetFirstRow(); row<=sInfo.GetLastRow(); ++row) {
217       TPCSectorData::RowIterator i = fSectorData->MakeRowIterator(row);
218       Int_t offset = (sInfo.GetNMaxPads() - TPCSectorData::GetNPadsInRow(row))/2;
219       LoadPadrow(i, row + rowOff[sId], offset + colOff[sId]);
220     }
221   }
222
223   glBindTexture  (GL_TEXTURE_2D, fTexture);
224   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT);
225   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT);
226   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
227   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
228   glTexEnvf      (GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,   GL_REPLACE);
229   glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, fgkTextureWidth, fgkTextureHeight,
230                   0, GL_RGBA, GL_UNSIGNED_BYTE, fImage);
231
232 }
233
234 /**************************************************************************/
235 // Data display
236 /**************************************************************************/
237
238 void TPCSector2DGL::DisplayTexture(const TPCSectorData::SegmentInfo& seg,
239                                    Int_t startCol, Int_t startRow) const
240 {
241   Float_t w  = seg.GetNMaxPads()*seg.GetPadWidth()/2;
242   Float_t y1 = seg.GetRLow();
243   Float_t y2 = y1 + seg.GetNRows()*seg.GetPadHeight();
244
245   Float_t u1 = (Float_t) startCol / fgkTextureWidth;
246   Float_t v1 = (Float_t) startRow / fgkTextureHeight;
247   Float_t u2 = u1 + (Float_t) seg.GetNMaxPads() / fgkTextureWidth;
248   Float_t v2 = v1 + (Float_t) seg.GetNRows()    / fgkTextureHeight;
249
250   glBegin(GL_QUADS);  
251   glTexCoord2f(u1, v1);  glVertex2f(-w, y1);
252   glTexCoord2f(u1, v2);  glVertex2f(-w, y2);
253   glTexCoord2f(u2, v2);  glVertex2f( w, y2);
254   glTexCoord2f(u2, v1);  glVertex2f( w, y1);
255   glEnd();
256 }
257
258 /**************************************************************************/
259
260 void TPCSector2DGL::DisplayQuads(const TPCSectorData::SegmentInfo& seg,
261                                  Int_t startCol, Int_t startRow) const
262 {
263   Float_t y_d, y_u;
264   Float_t x_off, x;
265   Float_t padW = seg.GetPadWidth();
266   Float_t padH = seg.GetPadHeight();
267
268   glBegin(GL_QUADS);
269   for (Int_t row=0; row<seg.GetNRows(); row++) {
270     y_d = seg.GetRLow() + row*padH;
271     y_u = y_d + padH;
272     x_off = -seg.GetNMaxPads()*padW/2;
273     Int_t tpcRow = row + seg.GetFirstRow();
274     Int_t deltaPad = (seg.GetNMaxPads() - TPCSectorData::GetNPadsInRow(tpcRow))/2;
275     Int_t   maxPad = seg.GetNMaxPads() - deltaPad;
276     UChar_t   *pix = GetRowCol(row + startRow, startCol + deltaPad);
277     for (Int_t pad=deltaPad; pad<maxPad; pad++, pix+=4) {
278       x = x_off + pad*padW;
279       if (pix[3] != 0) {
280         glColor4ubv(pix);
281         glVertex2f(x+padW, y_d);
282         glVertex2f(x,      y_d);
283         glVertex2f(x,      y_u);
284         glVertex2f(x+padW, y_u);
285       }
286     }
287   }
288   glEnd();
289 }
290
291 void TPCSector2DGL::DisplayNamedQuads(const TPCSectorData::SegmentInfo& seg,
292                                       Int_t startCol, Int_t startRow) const
293 {
294   Float_t y_d, y_u;
295   Float_t x_off, x;
296   Float_t padW = seg.GetPadWidth();
297   Float_t padH = seg.GetPadHeight();
298
299   glPushName(0);
300   for (Int_t row=0; row<seg.GetNRows(); row++) {
301     y_d = seg.GetRLow() + row*padH;
302     y_u = y_d + padH;
303     x_off = -seg.GetNMaxPads()*padW/2;
304     Int_t tpcRow = row + seg.GetFirstRow();
305     glLoadName(tpcRow);
306     Int_t deltaPad = (seg.GetNMaxPads() - TPCSectorData::GetNPadsInRow(tpcRow))/2;
307     Int_t   maxPad = seg.GetNMaxPads() - deltaPad;
308     UChar_t   *pix = GetRowCol(row + startRow, startCol + deltaPad);
309     glPushName(0);
310     for (Int_t pad=deltaPad; pad<maxPad; pad++, pix+=4) {
311       x = x_off + pad*padW;
312       // !!! Potentially replace following 'if', add an option to TPCSector2D.
313       // !!! Details depend on how data is processed during extraction.
314       if (pix[3] != 0) {
315         glLoadName(pad - deltaPad);
316         glBegin(GL_QUADS);
317         glVertex2f(x+padW, y_d);
318         glVertex2f(x,      y_d);
319         glVertex2f(x,      y_u);
320         glVertex2f(x+padW, y_u);
321         glEnd();
322       }
323     }
324     glPopName();
325   }
326   glPopName();
327 }
328
329 /**************************************************************************/
330 // Frame drawing
331 /**************************************************************************/
332
333 void TPCSector2DGL::TraceStepsUp(const TPCSectorData::SegmentInfo& s)
334 {
335   Float_t x = -(s.GetNMaxPads()*1.0/2 - s.GetNYSteps())*s.GetPadWidth();
336   Float_t y  = s.GetRLow();
337   glVertex2f(x, y);
338   for (Int_t i=0; i<s.GetNYSteps(); ++i) {
339     y = s.GetYStep(i);
340     glVertex2f(x, y);
341     x -= s.GetPadWidth();
342     glVertex2f(x, y);
343   }
344   y =  s.GetRLow() + s.GetNRows()*s.GetPadHeight();
345   glVertex2f(-s.GetNMaxPads()*s.GetPadWidth()/2, y);
346 }
347
348 void TPCSector2DGL::TraceStepsDown(const TPCSectorData::SegmentInfo& s) 
349 {
350   Float_t x = s.GetNMaxPads()*s.GetPadWidth()/2;
351   Float_t y = s.GetRLow() + s.GetNRows()*s.GetPadHeight();
352   glVertex2f(x, y);
353   for (Int_t i=s.GetNYSteps() - 1; i>=0; --i) {
354     y =  s.GetYStep(i);
355     glVertex2f(x, y);
356     x -= s.GetPadWidth();
357     glVertex2f(x, y);
358   }
359   y = s.GetRLow();
360   glVertex2f((0.5*s.GetNMaxPads() - s.GetNYSteps())*s.GetPadWidth(), y);
361 }
362
363 void TPCSector2DGL::DisplayFrame() const
364 {
365   UChar_t col[4];
366   ColorFromIdx(fSector->fFrameColor, col);
367   glColor4ubv(col);
368
369   if(fSector->fRnrInn) {
370     glBegin(GL_POLYGON);
371     TraceStepsUp  (TPCSectorData::GetInnSeg());
372     TraceStepsDown(TPCSectorData::GetInnSeg());
373     glEnd();
374   }
375   if(fSector->fRnrOut1) {
376     glBegin(GL_POLYGON);
377     TraceStepsUp  (TPCSectorData::GetOut1Seg());
378     TraceStepsDown(TPCSectorData::GetOut1Seg());
379     glEnd();
380   }
381   if(fSector->fRnrOut2) {
382     glBegin(GL_POLYGON);
383     TraceStepsUp  (TPCSectorData::GetOut2Seg());
384     TraceStepsDown(TPCSectorData::GetOut2Seg());
385     glEnd();
386   }
387 }