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