Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLBoxPainter.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Timur Pocheptsov 31/08/2006
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 #include <cctype>
12 
13 #include "KeySymbols.h"
14 #include "TVirtualX.h"
15 #include "Buttons.h"
16 #include "TString.h"
17 #include "TROOT.h"
18 #include "TMath.h"
19 #include "TClass.h"
20 #include "TColor.h"
21 #include "TStyle.h"
22 #include "TH3.h"
23 #include "TVirtualMutex.h"
24 
25 #include "TPolyMarker3D.h"
26 #include "TGLPlotCamera.h"
27 #include "TGLBoxPainter.h"
28 #include "TGLIncludes.h"
29 
30 /** \class TGLBoxPainter
31 \ingroup opengl
32 Paints TH3 histograms by rendering variable-sized boxes matching the
33 bin contents.
34 */
35 
36 ClassImp(TGLBoxPainter);
37 
38 ////////////////////////////////////////////////////////////////////////////////
39 /// Normal constructor.
40 
41 TGLBoxPainter::TGLBoxPainter(TH1 *hist, TGLPlotCamera *cam, TGLPlotCoordinates *coord)
42  : TGLPlotPainter(hist, cam, coord, kTRUE, kTRUE, kTRUE),
43  fXOZSlice("XOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOZ),
44  fYOZSlice("YOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kYOZ),
45  fXOYSlice("XOY", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOY),
46  fType(kBox),
47  fPolymarker(0)
48 {
49 }
50 
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Normal constructor.
54 
55 TGLBoxPainter::TGLBoxPainter(TH1 *hist, TPolyMarker3D * pm,
56  TGLPlotCamera *cam, TGLPlotCoordinates *coord)
57  : TGLPlotPainter(hist, cam, coord, kFALSE, kFALSE, kFALSE),
58  fXOZSlice("XOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOZ),
59  fYOZSlice("YOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kYOZ),
60  fXOYSlice("XOY", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOY),
61  fType(kBox),
62  fPolymarker(pm)
63 {
64 }
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 ///Show box info (i, j, k, binContent).
68 
69 char *TGLBoxPainter::GetPlotInfo(Int_t, Int_t)
70 {
71  fPlotInfo = "";
72 
73  if (fSelectedPart) {
74  if (fSelectedPart < fSelectionBase) {
75  if (fHist->Class())
76  fPlotInfo += fHist->Class()->GetName();
77  fPlotInfo += "::";
78  fPlotInfo += fHist->GetName();
79  } else if (!fHighColor){
80  const Int_t arr2Dsize = fCoord->GetNYBins() * fCoord->GetNZBins();
81  const Int_t binI = (fSelectedPart - fSelectionBase) / arr2Dsize + fCoord->GetFirstXBin();
82  const Int_t binJ = (fSelectedPart - fSelectionBase) % arr2Dsize / fCoord->GetNZBins() + fCoord->GetFirstYBin();
83  const Int_t binK = (fSelectedPart - fSelectionBase) % arr2Dsize % fCoord->GetNZBins() + fCoord->GetFirstZBin();
84 
85  fPlotInfo.Form("(binx = %d; biny = %d; binz = %d; binc = %f)", binI, binJ, binK,
86  fHist->GetBinContent(binI, binJ, binK));
87  } else
88  fPlotInfo = "Switch to true color mode to get correct info";
89  }
90 
91  return (Char_t *)fPlotInfo.Data();
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 ///Set ranges, find min and max bin content.
96 
97 Bool_t TGLBoxPainter::InitGeometry()
98 {
99  fCoord->SetZLog(kFALSE);
100  fCoord->SetYLog(kFALSE);
101  fCoord->SetXLog(kFALSE);
102 
103  if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))//kFALSE == drawErrors, kTRUE == zAsBins
104  return kFALSE;
105 
106  fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
107  if(fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
108 
109  fMinMaxVal.second = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin(), fCoord->GetFirstZBin());
110  fMinMaxVal.first = fMinMaxVal.second;
111  //Bad. You can up-date some bin value and get wrong picture.
112  for (Int_t ir = fCoord->GetFirstXBin(); ir <= fCoord->GetLastXBin(); ++ir) {
113  for (Int_t jr = fCoord->GetFirstYBin(); jr <= fCoord->GetLastYBin(); ++jr) {
114  for (Int_t kr = fCoord->GetFirstZBin(); kr <= fCoord->GetLastZBin(); ++kr) {
115  fMinMaxVal.second = TMath::Max(fMinMaxVal.second, fHist->GetBinContent(ir, jr, kr));
116  fMinMaxVal.first = TMath::Min(fMinMaxVal.first, fHist->GetBinContent(ir, jr, kr));
117  }
118  }
119  }
120 
121  fXOYSlice.SetMinMax(fMinMaxVal);
122  fXOZSlice.SetMinMax(fMinMaxVal);
123  fYOZSlice.SetMinMax(fMinMaxVal);
124 
125  if (fPolymarker) {
126  const Double_t xScale = fCoord->GetXScale();
127  const Double_t yScale = fCoord->GetYScale();
128  const Double_t zScale = fCoord->GetZScale();
129 
130  fPMPoints.assign(fPolymarker->GetP(), fPolymarker->GetP() + fPolymarker->GetN() * 3);
131  for (unsigned i = 0; i < fPMPoints.size(); i += 3) {
132  fPMPoints[i] *= xScale;
133  fPMPoints[i + 1] *= yScale;
134  fPMPoints[i + 2] *= zScale;
135  }
136  }
137 
138  if (fCoord->Modified()) {
139  fUpdateSelection = kTRUE;
140  fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
141  fYOZSectionPos = fBackBox.Get3DBox()[0].X();
142  fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
143  fCoord->ResetModified();
144  }
145 
146  return kTRUE;
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// User clicks right mouse button (in a pad).
151 
152 void TGLBoxPainter::StartPan(Int_t px, Int_t py)
153 {
154  fMousePosition.fX = px;
155  fMousePosition.fY = fCamera->GetHeight() - py;
156  fCamera->StartPan(px, py);
157  fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// User's moving mouse cursor, with middle mouse button pressed (for pad).
162 /// Calculate 3d shift related to 2d mouse movement.
163 
164 void TGLBoxPainter::Pan(Int_t px, Int_t py)
165 {
166  if (fSelectedPart >= fSelectionBase) {//Pan camera.
167  SaveModelviewMatrix();
168  SaveProjectionMatrix();
169 
170  fCamera->SetCamera();
171  fCamera->Apply(fPadPhi, fPadTheta);
172  fCamera->Pan(px, py);
173 
174  RestoreProjectionMatrix();
175  RestoreModelviewMatrix();
176  } else if (fSelectedPart > 0) {
177  //Convert py into bottom-top orientation.
178  //Possibly, move box here
179  py = fCamera->GetHeight() - py;
180  SaveModelviewMatrix();
181  SaveProjectionMatrix();
182 
183  fCamera->SetCamera();
184  fCamera->Apply(fPadPhi, fPadTheta);
185 
186 
187  if (!fHighColor) {
188  if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
189  fBoxCut.MoveBox(px, py, fSelectedPart);
190  else
191  MoveSection(px, py);
192  } else {
193  MoveSection(px, py);
194  }
195 
196  RestoreProjectionMatrix();
197  RestoreModelviewMatrix();
198  }
199 
200  fMousePosition.fX = px, fMousePosition.fY = py;
201  fUpdateSelection = kTRUE;
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Box1 == spheres.
206 
207 void TGLBoxPainter::AddOption(const TString &option)
208 {
209  using namespace std;//isdigit must be in std. But ...
210 
211  const Ssiz_t boxPos = option.Index("box");//"box" _already_ _exists_ in a string.
212  if (boxPos + 3 < option.Length() && isdigit(option[boxPos + 3]))
213  option[boxPos + 3] - '0' == 1 ? fType = kBox1 : fType = kBox;
214  else
215  fType = kBox;
216  option.Index("z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Remove sections.
221 
222 void TGLBoxPainter::ProcessEvent(Int_t event, Int_t /*px*/, Int_t py)
223 {
224  if (event == kButton1Double && (HasSections() || fBoxCut.IsActive())) {
225  fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
226  fYOZSectionPos = fBackBox.Get3DBox()[0].X();
227  fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
228  if (fBoxCut.IsActive())
229  fBoxCut.TurnOnOff();
230  if (!gVirtualX->IsCmdThread())
231  gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
232  else
233  Paint();
234  } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
235  if (fHighColor)
236  Info("ProcessEvent", "Switch to true color mode to use box cut");
237  else {
238  fBoxCut.TurnOnOff();
239  fUpdateSelection = kTRUE;
240  }
241  }
242 }
243 
244 ////////////////////////////////////////////////////////////////////////////////
245 /// Initialize some gl state variables.
246 
247 void TGLBoxPainter::InitGL()const
248 {
249  glEnable(GL_DEPTH_TEST);
250  glEnable(GL_LIGHTING);
251  glEnable(GL_LIGHT0);
252  //For box option back polygons are culled (but not for dynamic profiles).
253  glEnable(GL_CULL_FACE);
254  glCullFace(GL_BACK);
255 
256  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 ///Return back some gl state variables.
261 
262 void TGLBoxPainter::DeInitGL()const
263 {
264  glDisable(GL_DEPTH_TEST);
265  glDisable(GL_LIGHTING);
266  glDisable(GL_LIGHT0);
267  glDisable(GL_CULL_FACE);
268  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
269 }
270 
271 namespace {
272 
273  /////////////////////////////////////////////////////////////////////////////
274  ///
275 
276  void DrawMinusSigns(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax,
277  Double_t zMin, Double_t zMax, Int_t fp, Bool_t onSphere, Bool_t transp)
278  {
279  const TGLDisableGuard depthTest(GL_DEPTH_TEST);
280  const TGLDisableGuard cullFace(GL_CULL_FACE);
281 
282  const Double_t ratio = onSphere ? 0.4 : 0.15;
283  const Double_t leftX = xMin + ratio * (xMax - xMin), rightX = xMax - ratio * (xMax - xMin);
284  const Double_t leftY = yMin + ratio * (yMax - yMin), rightY = yMax - ratio * (yMax - yMin);
285  const Double_t lowZ = zMin / 2. + zMax / 2. - 0.1 * (zMax - zMin);
286  const Double_t upZ = zMin / 2. + zMax / 2. + 0.1 * (zMax - zMin);
287 
288 
289  const Double_t minusVerts[][3] = {{xMin, leftY, lowZ}, {xMin, leftY, upZ}, {xMin, rightY, upZ}, {xMin, rightY, lowZ},
290  {leftX, yMin, lowZ}, {rightX, yMin, lowZ}, {rightX, yMin, upZ}, {leftX, yMin, upZ},
291  {xMax, leftY, lowZ}, {xMax, rightY, lowZ}, {xMax, rightY, upZ}, {xMax, leftY, upZ},
292  {rightX, yMax, lowZ}, {leftX, yMax, lowZ}, {leftX, yMax, upZ}, {rightX, yMax, upZ}};
293  const Int_t minusQuads[][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}};
294 
295 
296  TGLDisableGuard light(GL_LIGHTING);
297  glColor3d(1., 0., 0.);
298 
299  const Int_t frontPlanes[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};//Code duplication again :(
300  const Int_t *verts = minusQuads[frontPlanes[fp][0]];
301 
302  glBegin(GL_POLYGON);
303  glVertex3dv(minusVerts[verts[0]]);
304  glVertex3dv(minusVerts[verts[1]]);
305  glVertex3dv(minusVerts[verts[2]]);
306  glVertex3dv(minusVerts[verts[3]]);
307  glEnd();
308 
309  verts = minusQuads[frontPlanes[fp][1]];
310 
311  glBegin(GL_POLYGON);
312  glVertex3dv(minusVerts[verts[0]]);
313  glVertex3dv(minusVerts[verts[1]]);
314  glVertex3dv(minusVerts[verts[2]]);
315  glVertex3dv(minusVerts[verts[3]]);
316  glEnd();
317 
318  const Float_t nullEmission[] = {0.f, 0.f, 0.f, 1.f};
319  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, nullEmission);
320  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, nullEmission);
321 
322  glColor4d(0., 0., 0., 0.25);
323  glPolygonMode(GL_FRONT, GL_LINE);
324 
325  if (!transp) {
326  glEnable(GL_BLEND);
327  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
328  }
329 
330  glEnable(GL_LINE_SMOOTH);
331  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
332 
333  verts = minusQuads[frontPlanes[fp][0]];
334 
335  glBegin(GL_POLYGON);
336  glVertex3dv(minusVerts[verts[0]]);
337  glVertex3dv(minusVerts[verts[1]]);
338  glVertex3dv(minusVerts[verts[2]]);
339  glVertex3dv(minusVerts[verts[3]]);
340  glEnd();
341 
342  verts = minusQuads[frontPlanes[fp][1]];
343 
344  glBegin(GL_POLYGON);
345  glVertex3dv(minusVerts[verts[0]]);
346  glVertex3dv(minusVerts[verts[1]]);
347  glVertex3dv(minusVerts[verts[2]]);
348  glVertex3dv(minusVerts[verts[3]]);
349  glEnd();
350 
351  glPolygonMode(GL_FRONT, GL_FILL);
352 
353  if (!transp)
354  glDisable(GL_BLEND);
355  }
356 
357 }
358 
359 ////////////////////////////////////////////////////////////////////////////////
360 
361 void TGLBoxPainter::DrawPlot()const
362 {
363  if (fPolymarker)
364  return DrawCloud();
365 
366  // Draw set of boxes (spheres)
367 
368  //Shift plot to point of origin.
369  const Rgl::PlotTranslation trGuard(this);
370 
371  fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
372  glDisable(GL_CULL_FACE);
373  DrawSections();
374  glEnable(GL_CULL_FACE);
375 
376  if (!fSelectionPass) {
377  glEnable(GL_POLYGON_OFFSET_FILL);//[0
378  glPolygonOffset(1.f, 1.f);
379  SetPlotColor();
380  if (HasSections()) {
381  //Boxes are semi-transparent if we have any sections.
382  glEnable(GL_BLEND);//[1
383  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
384  }
385  }
386 
387  //Using front point, find the correct order to draw boxes from
388  //back to front/from bottom to top (it's important only for semi-transparent boxes).
389  const Int_t frontPoint = fBackBox.GetFrontPoint();
390  Int_t irInit = fCoord->GetFirstXBin(), iInit = 0;
391  const Int_t nX = fCoord->GetNXBins();
392  Int_t jrInit = fCoord->GetFirstYBin(), jInit = 0;
393  const Int_t nY = fCoord->GetNYBins();
394  Int_t krInit = fCoord->GetFirstZBin(), kInit = 0;
395  const Int_t nZ = fCoord->GetNZBins();
396 
397  const Int_t addI = frontPoint == 2 || frontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fCoord->GetLastXBin(), -1);
398  const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fCoord->GetLastYBin(), -1);
399  const Int_t addK = fBackBox.Get2DBox()[frontPoint + 4].Y() < fBackBox.Get2DBox()[frontPoint].Y() ? 1
400  : (kInit = nZ - 1, krInit = fCoord->GetLastZBin(),-1);
401  const Double_t xScale = fCoord->GetXScale();
402  const Double_t yScale = fCoord->GetYScale();
403  const Double_t zScale = fCoord->GetZScale();
404  const TAxis *xA = fXAxis;
405  const TAxis *yA = fYAxis;
406  const TAxis *zA = fZAxis;
407 
408  if (fSelectionPass && fHighColor)
409  Rgl::ObjectIDToColor(fSelectionBase, fHighColor);//base + 1 == 7
410 
411  Double_t maxContent = TMath::Max(TMath::Abs(fMinMaxVal.first), TMath::Abs(fMinMaxVal.second));
412  if(!maxContent)//bad, find better way to check zero.
413  maxContent = 1.;
414 
415  for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
416  for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
417  for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
418  const Double_t binContent = fHist->GetBinContent(ir, jr, kr);
419  const Double_t w = TMath::Power(TMath::Abs(binContent) / maxContent,1./3.);
420  if (!w)
421  continue;
422 
423  const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
424  const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
425  const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
426  const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
427  const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
428  const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
429 
430  if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
431  continue;
432 
433  const Int_t binID = fSelectionBase + i * fCoord->GetNZBins() * fCoord->GetNYBins() + j * fCoord->GetNZBins() + k;
434 
435  if (fSelectionPass && !fHighColor)
436  Rgl::ObjectIDToColor(binID, fHighColor);
437  else if(!fHighColor && fSelectedPart == binID)
438  glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gOrangeEmission);
439 
440  if (fType == kBox) {
441  Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
442  } else {
443  Rgl::DrawSphere(&fQuadric, xMin, xMax, yMin, yMax, zMin, zMax);
444  }
445 
446  if (binContent < 0. && !fSelectionPass)
447  DrawMinusSigns(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint, fType != kBox, HasSections());
448 
449  if (!fSelectionPass && !fHighColor && fSelectedPart == binID)
450  glMaterialfv(GL_FRONT, GL_EMISSION, Rgl::gNullEmission);
451  }
452  }
453  }
454 
455  if (fBoxCut.IsActive())
456  fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
457 
458  if (!fSelectionPass && fType != kBox1) {
459  glDisable(GL_POLYGON_OFFSET_FILL);//0]
460  TGLDisableGuard lightGuard(GL_LIGHTING);//[2 - 2]
461  glColor4d(0., 0., 0., 0.25);
462  glPolygonMode(GL_FRONT, GL_LINE);//[3
463 
464  const TGLEnableGuard blendGuard(GL_BLEND);//[4-4] + 1]
465  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
466  const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);//[5-5]
467  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
468 
469  for(Int_t ir = irInit, i = iInit; addI > 0 ? i < nX : i >= 0; ir += addI, i += addI) {
470  for(Int_t jr = jrInit, j = jInit; addJ > 0 ? j < nY : j >= 0; jr += addJ, j += addJ) {
471  for(Int_t kr = krInit, k = kInit; addK > 0 ? k < nZ : k >= 0; kr += addK, k += addK) {
472  const Double_t w = TMath::Power(TMath::Abs(fHist->GetBinContent(ir, jr, kr)) / maxContent,1./3.);
473 
474  if (!w)
475  continue;
476 
477  const Double_t xMin = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 - w * xA->GetBinWidth(ir) / 2);
478  const Double_t xMax = xScale * (xA->GetBinLowEdge(ir) / 2 + xA->GetBinUpEdge(ir) / 2 + w * xA->GetBinWidth(ir) / 2);
479  const Double_t yMin = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 - w * yA->GetBinWidth(jr) / 2);
480  const Double_t yMax = yScale * (yA->GetBinLowEdge(jr) / 2 + yA->GetBinUpEdge(jr) / 2 + w * yA->GetBinWidth(jr) / 2);
481  const Double_t zMin = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 - w * zA->GetBinWidth(kr) / 2);
482  const Double_t zMax = zScale * (zA->GetBinLowEdge(kr) / 2 + zA->GetBinUpEdge(kr) / 2 + w * zA->GetBinWidth(kr) / 2);
483 
484  if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
485  continue;
486 
487  Rgl::DrawBoxFront(xMin, xMax, yMin, yMax, zMin, zMax, frontPoint);
488  }
489  }
490  }
491 
492  glPolygonMode(GL_FRONT, GL_FILL);//3]
493  }
494 
495  if (!fSelectionPass && fDrawPalette && HasSections())
496  DrawPalette();
497 }
498 
499 ////////////////////////////////////////////////////////////////////////////////
500 ///Draw a frame and a polymarker inside.
501 
502 void TGLBoxPainter::DrawCloud()const
503 {
504  //Shift plot to the point of origin.
505  const Rgl::PlotTranslation trGuard(this);
506 
507  //Frame.
508  fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
509 
510  if (fPhysicalShapeColor)
511  glColor3fv(fPhysicalShapeColor);
512 
513  glDisable(GL_LIGHTING);
514 
515  const TGLVertex3 *bb = fBackBox.Get3DBox();
516  const Double_t dX = (bb[1].X() - bb[0].X()) / 40.;
517  const Double_t dY = (bb[3].Y() - bb[0].Y()) / 40.;
518  const Double_t dZ = (bb[4].Z() - bb[0].Z()) / 40.;
519  //Now, draw the cloud of points (polymarker) inside the frame.
520  TGLUtil::RenderPolyMarkers(*fPolymarker, fPMPoints, dX, dY, dZ);
521 
522  glEnable(GL_LIGHTING);
523 }
524 
525 ////////////////////////////////////////////////////////////////////////////////
526 /// Set boxes color.
527 
528 void TGLBoxPainter::SetPlotColor()const
529 {
530  Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.05f};
531 
532  if (fPhysicalShapeColor) {
533  diffColor[0] = fPhysicalShapeColor[0];
534  diffColor[1] = fPhysicalShapeColor[1];
535  diffColor[2] = fPhysicalShapeColor[2];
536  } else {
537  if (fHist->GetFillColor() != kWhite)
538  if (const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
539  c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
540  }
541 
542  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
543  const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
544  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
545  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Draw XOZ parallel section.
550 
551 void TGLBoxPainter::DrawSectionXOZ()const
552 {
553  if (fSelectionPass)
554  return;
555  fXOZSlice.DrawSlice(fXOZSectionPos / fCoord->GetYScale());
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 /// Draw YOZ parallel section.
560 
561 void TGLBoxPainter::DrawSectionYOZ()const
562 {
563  if (fSelectionPass)
564  return;
565  fYOZSlice.DrawSlice(fYOZSectionPos / fCoord->GetXScale());
566 }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Draw XOY parallel section.
570 
571 void TGLBoxPainter::DrawSectionXOY()const
572 {
573  if (fSelectionPass)
574  return;
575  fXOYSlice.DrawSlice(fXOYSectionPos / fCoord->GetZScale());
576 }
577 
578 ////////////////////////////////////////////////////////////////////////////////
579 /// Check, if any section exists.
580 
581 Bool_t TGLBoxPainter::HasSections()const
582 {
583  return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos> fBackBox.Get3DBox()[0].X() ||
584  fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
585 }
586 
587 ////////////////////////////////////////////////////////////////////////////////
588 ///Draw. Palette.
589 ///Originally, fCamera was never null.
590 ///It can be a null now because of gl-viewer.
591 
592 void TGLBoxPainter::DrawPalette()const
593 {
594  if (!fCamera) {
595  //Thank you, gl-viewer!
596  return;
597  }
598 
599  const TGLLevelPalette * palette = 0;
600  const TGLVertex3 *frame = fBackBox.Get3DBox();
601 
602  if (fXOZSectionPos > frame[0].Y())
603  palette = &fXOZSlice.GetPalette();
604  else if (fYOZSectionPos > frame[0].X())
605  palette = &fYOZSlice.GetPalette();
606  else if (fXOYSectionPos > frame[0].Z())
607  palette = &fXOYSlice.GetPalette();
608 
609  if (!palette || !palette->GetPaletteSize()) {
610  return;
611  }
612 
613  Rgl::DrawPalette(fCamera, *palette);
614 
615  glFinish();
616 
617  fCamera->SetCamera();
618  fCamera->Apply(fPadPhi, fPadTheta);
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 ///Draw. Palette. Axis.
623 
624 void TGLBoxPainter::DrawPaletteAxis()const
625 {
626  if (HasSections()) {
627  gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
628  Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);
629  }
630 }