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