Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLTF3Painter.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 
12 #include <typeinfo>
13 
14 #include "TVirtualGL.h"
15 #include "KeySymbols.h"
16 #include "TVirtualX.h"
17 #include "Buttons.h"
18 #include "TString.h"
19 #include "TROOT.h"
20 #include "TColor.h"
21 #include "TMath.h"
22 #include "TH3.h"
23 #include "TF3.h"
24 
25 #include "TGLMarchingCubes.h"
26 #include "TGLPlotCamera.h"
27 #include "TGLTF3Painter.h"
28 #include "TGLIncludes.h"
29 
30 /** \class TGLTF3Painter
31 \ingroup opengl
32 Plot-painter for TF3 functions.
33 */
34 
35 ClassImp(TGLTF3Painter);
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Constructor.
39 
40 TGLTF3Painter::TGLTF3Painter(TF3 *fun, TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
41  : TGLPlotPainter(hist, camera, coord, kFALSE, kFALSE, kFALSE),
42  fStyle(kDefault),
43  fF3(fun),
44  fXOZSlice("XOZ", (TH3 *)hist, fun, coord, &fBackBox, TGLTH3Slice::kXOZ),
45  fYOZSlice("YOZ", (TH3 *)hist, fun, coord, &fBackBox, TGLTH3Slice::kYOZ),
46  fXOYSlice("XOY", (TH3 *)hist, fun, coord, &fBackBox, TGLTH3Slice::kXOY)
47 {
48 }
49 
50 ////////////////////////////////////////////////////////////////////////////////
51 ///Coords for point on surface under cursor.
52 
53 char *TGLTF3Painter::GetPlotInfo(Int_t /*px*/, Int_t /*py*/)
54 {
55  static char mess[] = { "fun3" };
56  return mess;
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 ///Create mesh.
61 
62 Bool_t TGLTF3Painter::InitGeometry()
63 {
64  fCoord->SetCoordType(kGLCartesian);
65 
66  if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))
67  return kFALSE;
68 
69  fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
70  if (fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
71 
72  //Build mesh for TF3 surface
73  fMesh.ClearMesh();
74 
75  Rgl::Mc::TMeshBuilder<TF3, Double_t> builder(kFALSE);//no averaged normals.
76  //Set grid parameters.
77  Rgl::Mc::TGridGeometry<Double_t> geom(fXAxis, fYAxis, fZAxis, fCoord->GetXScale(),
78  fCoord->GetYScale(), fCoord->GetZScale(),
79  Rgl::Mc::TGridGeometry<Double_t>::kBinEdge);
80 
81  builder.BuildMesh(fF3, geom, &fMesh, 0.);
82 
83  if (fCoord->Modified()) {
84  fUpdateSelection = kTRUE;
85  const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
86  fXOZSectionPos = vertex.Y();
87  fYOZSectionPos = vertex.X();
88  fXOYSectionPos = vertex.Z();
89  fCoord->ResetModified();
90  }
91 
92  return kTRUE;
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 ///User clicks right mouse button (in a pad).
97 
98 void TGLTF3Painter::StartPan(Int_t px, Int_t py)
99 {
100  fMousePosition.fX = px;
101  fMousePosition.fY = fCamera->GetHeight() - py;
102  fCamera->StartPan(px, py);
103  fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 ///User's moving mouse cursor, with middle mouse button pressed (for pad).
108 ///Calculate 3d shift related to 2d mouse movement.
109 ///Slicing is disabled (since somebody has broken it).
110 
111 void TGLTF3Painter::Pan(Int_t px, Int_t py)
112 {
113  if (fSelectedPart >= fSelectionBase) {//Pan camera.
114  SaveModelviewMatrix();
115  SaveProjectionMatrix();
116 
117  fCamera->SetCamera();
118  fCamera->Apply(fPadPhi, fPadTheta);
119  fCamera->Pan(px, py);
120 
121  RestoreProjectionMatrix();
122  RestoreModelviewMatrix();
123  } else if (fSelectedPart > 0) {
124  //Convert py into bottom-top orientation.
125  //Possibly, move box here
126  py = fCamera->GetHeight() - py;
127 
128  SaveModelviewMatrix();
129  SaveProjectionMatrix();
130 
131  fCamera->SetCamera();
132  fCamera->Apply(fPadPhi, fPadTheta);
133 
134  if (!fHighColor) {
135  if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis)) {
136  fBoxCut.MoveBox(px, py, fSelectedPart);
137  } else {
138  //MoveSection(px, py);
139  }
140  } else {
141  //MoveSection(px, py);
142  }
143 
144  RestoreProjectionMatrix();
145  RestoreModelviewMatrix();
146  }
147 
148  fMousePosition.fX = px, fMousePosition.fY = py;
149  fUpdateSelection = kTRUE;
150 }
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 ///No options for tf3
154 
155 void TGLTF3Painter::AddOption(const TString &/*option*/)
156 {
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 ///Change color scheme.
161 
162 void TGLTF3Painter::ProcessEvent(Int_t event, Int_t /*px*/, Int_t py)
163 {
164  if (event == kKeyPress) {
165  if (py == kKey_s || py == kKey_S) {
166  fStyle < kMaple2 ? fStyle = ETF3Style(fStyle + 1) : fStyle = kDefault;
167  } else if (py == kKey_c || py == kKey_C) {
168  if (fHighColor)
169  Info("ProcessEvent", "Cut box does not work in high color, please, switch to true color");
170  else {
171  fBoxCut.TurnOnOff();
172  fUpdateSelection = kTRUE;
173  }
174  }
175  } else if (event == kButton1Double && (fBoxCut.IsActive() || HasSections())) {
176  if (fBoxCut.IsActive())
177  fBoxCut.TurnOnOff();
178  const TGLVertex3 *frame = fBackBox.Get3DBox();
179  fXOZSectionPos = frame[0].Y();
180  fYOZSectionPos = frame[0].X();
181  fXOYSectionPos = frame[0].Z();
182 
183  if (!gVirtualX->IsCmdThread())
184  gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
185  else
186  Paint();
187  }
188 }
189 
190 ////////////////////////////////////////////////////////////////////////////////
191 ///Initialize OpenGL state variables.
192 
193 void TGLTF3Painter::InitGL() const
194 {
195  glEnable(GL_LIGHTING);
196  glEnable(GL_LIGHT0);
197  glEnable(GL_DEPTH_TEST);
198  glDisable(GL_CULL_FACE);
199  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 ///Initialize OpenGL state variables.
204 
205 void TGLTF3Painter::DeInitGL() const
206 {
207  glDisable(GL_LIGHTING);
208  glDisable(GL_LIGHT0);
209  glDisable(GL_DEPTH_TEST);
210  glDisable(GL_CULL_FACE);
211  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 ///Draw triangles, no normals, no lighting.
216 
217 void TGLTF3Painter::DrawToSelectionBuffer() const
218 {
219  Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
220 
221  if (!fBoxCut.IsActive())
222  Rgl::DrawMesh(fMesh.fVerts, fMesh.fTris);
223  else
224  Rgl::DrawMesh(fMesh.fVerts, fMesh.fTris, fBoxCut);
225 }
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 ///Surface with material properties and lighting.
229 
230 void TGLTF3Painter::DrawDefaultPlot() const
231 {
232  if (HasSections()) {
233  glEnable(GL_BLEND);
234  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
235  glDepthMask(GL_FALSE);
236  }
237 
238  SetSurfaceColor();
239 
240  if (!fBoxCut.IsActive()) {
241  Rgl::DrawMesh(fMesh.fVerts, fMesh.fNorms, fMesh.fTris);
242  } else {
243  Rgl::DrawMesh(fMesh.fVerts, fMesh.fNorms, fMesh.fTris, fBoxCut);
244  }
245 
246  if (HasSections()) {
247  glDisable(GL_BLEND);
248  glDepthMask(GL_TRUE);
249  }
250 }
251 
252 ////////////////////////////////////////////////////////////////////////////////
253 ///Colored surface, without lighting and
254 ///material properties.
255 
256 void TGLTF3Painter::DrawMaplePlot() const
257 {
258  const TGLDisableGuard lightGuard(GL_LIGHTING);
259 
260  if (HasSections() && fStyle < kMaple2) {
261  glEnable(GL_BLEND);
262  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
263  glDepthMask(GL_FALSE);
264  }
265 
266  if (fStyle == kMaple1) {//Shaded polygons and outlines.
267  glEnable(GL_POLYGON_OFFSET_FILL);//[1
268  glPolygonOffset(1.f, 1.f);
269  } else if (fStyle == kMaple2)//Colored outlines only.
270  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//[2
271 
272  if(!fBoxCut.IsActive())
273  Rgl::DrawMapleMesh(fMesh.fVerts, fMesh.fNorms, fMesh.fTris);
274  else
275  Rgl::DrawMapleMesh(fMesh.fVerts, fMesh.fNorms, fMesh.fTris, fBoxCut);
276 
277  if (fStyle == kMaple1) {
278  //Draw outlines.
279  glDisable(GL_POLYGON_OFFSET_FILL);//1]
280  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//[3
281  glColor4d(0., 0., 0., 0.25);
282 
283  if(!fBoxCut.IsActive())
284  Rgl::DrawMesh(fMesh.fVerts, fMesh.fTris);
285  else
286  Rgl::DrawMesh(fMesh.fVerts, fMesh.fTris, fBoxCut);
287 
288  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);//[3
289  } else if (fStyle == kMaple2)
290  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
291 
292  if (HasSections() && fStyle < kMaple2) {
293  glDisable(GL_BLEND);
294  glDepthMask(GL_TRUE);
295  }
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 ///Draw mesh.
300 
301 void TGLTF3Painter::DrawPlot() const
302 {
303  //Shift plot to point of origin.
304  const Rgl::PlotTranslation trGuard(this);
305 
306  fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
307  DrawSections();
308 
309  if (fSelectionPass) {
310  DrawToSelectionBuffer();
311  } else if (fStyle == kDefault) {
312  DrawDefaultPlot();
313  } else {
314  DrawMaplePlot();
315  }
316 
317  if (fBoxCut.IsActive())
318  fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 ///Set color for surface.
323 
324 void TGLTF3Painter::SetSurfaceColor() const
325 {
326  Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.15f};
327 
328  if (fF3->GetFillColor() != kWhite)
329  if (const TColor *c = gROOT->GetColor(fF3->GetFillColor()))
330  c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
331 
332  glMaterialfv(GL_BACK, GL_DIFFUSE, diffColor);
333  diffColor[0] /= 2, diffColor[1] /= 2, diffColor[2] /= 2;
334  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffColor);
335  const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
336  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
337  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 ///Any section exists.
342 
343 Bool_t TGLTF3Painter::HasSections() const
344 {
345  return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() ||
346  fYOZSectionPos > fBackBox.Get3DBox()[0].X() ||
347  fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
348 }
349 
350 ////////////////////////////////////////////////////////////////////////////////
351 /// Draw XOZ parallel section.
352 
353 void TGLTF3Painter::DrawSectionXOZ() const
354 {
355  if (fSelectionPass)
356  return;
357  fXOZSlice.DrawSlice(fXOZSectionPos / fCoord->GetYScale());
358 }
359 
360 ////////////////////////////////////////////////////////////////////////////////
361 /// Draw YOZ parallel section.
362 
363 void TGLTF3Painter::DrawSectionYOZ() const
364 {
365  if (fSelectionPass)
366  return;
367  fYOZSlice.DrawSlice(fYOZSectionPos / fCoord->GetXScale());
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Draw XOY parallel section.
372 
373 void TGLTF3Painter::DrawSectionXOY() const
374 {
375  if (fSelectionPass)
376  return;
377  fXOYSlice.DrawSlice(fXOYSectionPos / fCoord->GetZScale());
378 }
379 
380 
381 /** \class TGLIsoPainter
382 \ingroup opengl
383 "gliso" option for TH3.
384 */
385 
386 ClassImp(TGLIsoPainter);
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 ///Constructor.
390 
391 TGLIsoPainter::TGLIsoPainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
392  : TGLPlotPainter(hist, camera, coord, kFALSE, kFALSE, kFALSE),
393  fXOZSlice("XOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOZ),
394  fYOZSlice("YOZ", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kYOZ),
395  fXOYSlice("XOY", (TH3 *)hist, coord, &fBackBox, TGLTH3Slice::kXOY),
396  fInit(kFALSE)
397 {
398  if (hist->GetDimension() < 3)
399  Error("TGLIsoPainter::TGLIsoPainter", "Wrong type of histogramm, must have 3 dimensions");
400 }
401 
402 ////////////////////////////////////////////////////////////////////////////////
403 ///Return info for plot part under cursor.
404 
405 char *TGLIsoPainter::GetPlotInfo(Int_t /*px*/, Int_t /*py*/)
406 {
407  static char mess[] = { "iso" };
408  return mess;
409 }
410 
411 ////////////////////////////////////////////////////////////////////////////////
412 ///Initializes meshes for 3d iso contours.
413 
414 Bool_t TGLIsoPainter::InitGeometry()
415 {
416  if (fHist->GetDimension() < 3) {
417  Error("TGLIsoPainter::TGLIsoPainter", "Wrong type of histogramm, must have 3 dimensions");
418  return kFALSE;
419  }
420 
421  //Create mesh.
422  if (fInit)
423  return kTRUE;
424 
425  //Only in cartesian.
426  fCoord->SetCoordType(kGLCartesian);
427  if (!fCoord->SetRanges(fHist, kFALSE, kTRUE))
428  return kFALSE;
429 
430  fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
431  if (fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
432 
433  //Move old meshes into the cache.
434  if (!fIsos.empty())
435  fCache.splice(fCache.begin(), fIsos);
436  //Number of contours == number of iso surfaces.
437  UInt_t nContours = fHist->GetContour();
438 
439  if (nContours > 1) {
440  fColorLevels.resize(nContours);
441  FindMinMax();
442 
443  if (fHist->TestBit(TH1::kUserContour)) {
444  //There are user defined contours (iso-levels).
445  for (UInt_t i = 0; i < nContours; ++i)
446  fColorLevels[i] = fHist->GetContourLevelPad(i);
447  } else {
448  //Equidistant iso-surfaces.
449  const Double_t isoStep = (fMinMax.second - fMinMax.first) / nContours;
450  for (UInt_t i = 0; i < nContours; ++i)
451  fColorLevels[i] = fMinMax.first + i * isoStep;
452  }
453 
454  fPalette.GeneratePalette(nContours, fMinMax, kFALSE);
455  } else {
456  //Only one iso (ROOT's standard).
457  fColorLevels.resize(nContours = 1);
458  fColorLevels[0] = fHist->GetSumOfWeights() / (fHist->GetNbinsX() * fHist->GetNbinsY() * fHist->GetNbinsZ());
459  }
460 
461  MeshIter_t firstMesh = fCache.begin();
462  //Initialize meshes, trying to reuse mesh from
463  //mesh cache.
464  for (UInt_t i = 0; i < nContours; ++i) {
465  if (firstMesh != fCache.end()) {
466  //There is a mesh in a cache.
467  SetMesh(*firstMesh, fColorLevels[i]);
468  MeshIter_t next = firstMesh;
469  ++next;
470  fIsos.splice(fIsos.begin(), fCache, firstMesh);
471  firstMesh = next;
472  } else {
473  //No meshes in a cache.
474  //Create new one and _swap_ data (look at Mesh_t::Swap in a header)
475  //between empty mesh in a list and this mesh
476  //to avoid real copying.
477  Mesh_t newMesh;
478  SetMesh(newMesh, fColorLevels[i]);
479  fIsos.push_back(fDummyMesh);
480  fIsos.back().Swap(newMesh);
481  }
482  }
483 
484  if (fCoord->Modified()) {
485  fUpdateSelection = kTRUE;
486  fXOZSectionPos = fBackBox.Get3DBox()[0].Y();
487  fYOZSectionPos = fBackBox.Get3DBox()[0].X();
488  fXOYSectionPos = fBackBox.Get3DBox()[0].Z();
489  fCoord->ResetModified();
490  }
491 
492  //Avoid rebuilding the mesh.
493  fInit = kTRUE;
494 
495  return kTRUE;
496 
497 }
498 
499 ////////////////////////////////////////////////////////////////////////////////
500 ///User clicks right mouse button (in a pad).
501 
502 void TGLIsoPainter::StartPan(Int_t px, Int_t py)
503 {
504  fMousePosition.fX = px;
505  fMousePosition.fY = fCamera->GetHeight() - py;
506  fCamera->StartPan(px, py);
507  fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
508 }
509 
510 ////////////////////////////////////////////////////////////////////////////////
511 ///User's moving mouse cursor, with middle mouse button pressed (for pad).
512 ///Calculate 3d shift related to 2d mouse movement.
513 ///User's moving mouse cursor, with middle mouse button pressed (for pad).
514 ///Calculate 3d shift related to 2d mouse movement.
515 
516 void TGLIsoPainter::Pan(Int_t px, Int_t py)
517 {
518  if (fSelectedPart >= fSelectionBase) {//Pan camera.
519  SaveModelviewMatrix();
520  SaveProjectionMatrix();
521 
522  fCamera->SetCamera();
523  fCamera->Apply(fPadPhi, fPadTheta);
524  fCamera->Pan(px, py);
525 
526  RestoreProjectionMatrix();
527  RestoreModelviewMatrix();
528  } else if (fSelectedPart > 0) {
529  //Convert py into bottom-top orientation.
530  //Possibly, move box here
531  py = fCamera->GetHeight() - py;
532 
533  SaveModelviewMatrix();
534  SaveProjectionMatrix();
535 
536  fCamera->SetCamera();
537  fCamera->Apply(fPadPhi, fPadTheta);
538 
539  if (!fHighColor) {
540  if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis)) {
541  fBoxCut.MoveBox(px, py, fSelectedPart);
542  } else {
543  //MoveSection(px, py);
544  }
545  } else {
546  //MoveSection(px, py);
547  }
548 
549  RestoreProjectionMatrix();
550  RestoreModelviewMatrix();
551 
552  }
553 
554  fMousePosition.fX = px, fMousePosition.fY = py;
555  fUpdateSelection = kTRUE;
556 }
557 
558 ////////////////////////////////////////////////////////////////////////////////
559 ///No additional options for TGLIsoPainter.
560 
561 void TGLIsoPainter::AddOption(const TString &/*option*/)
562 {
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 ///Change color scheme.
567 
568 void TGLIsoPainter::ProcessEvent(Int_t event, Int_t /*px*/, Int_t py)
569 {
570  if (event == kKeyPress) {
571  if (py == kKey_c || py == kKey_C) {
572  if (fHighColor)
573  Info("ProcessEvent", "Cut box does not work in high color, please, switch to true color");
574  else {
575  fBoxCut.TurnOnOff();
576  fUpdateSelection = kTRUE;
577  }
578  }
579  } else if (event == kButton1Double && (fBoxCut.IsActive() || HasSections())) {
580  if (fBoxCut.IsActive())
581  fBoxCut.TurnOnOff();
582  const TGLVertex3 *frame = fBackBox.Get3DBox();
583  fXOZSectionPos = frame[0].Y();
584  fYOZSectionPos = frame[0].X();
585  fXOYSectionPos = frame[0].Z();
586 
587  if (!gVirtualX->IsCmdThread())
588  gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
589  else
590  Paint();
591  }
592 }
593 
594 ////////////////////////////////////////////////////////////////////////////////
595 ///Initialize OpenGL state variables.
596 
597 void TGLIsoPainter::InitGL() const
598 {
599  glEnable(GL_LIGHTING);
600  glEnable(GL_LIGHT0);
601  glEnable(GL_DEPTH_TEST);
602  glDisable(GL_CULL_FACE);
603  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
604 }
605 
606 ////////////////////////////////////////////////////////////////////////////////
607 ///Initialize OpenGL state variables.
608 
609 void TGLIsoPainter::DeInitGL() const
610 {
611  glDisable(GL_LIGHTING);
612  glDisable(GL_LIGHT0);
613  glDisable(GL_DEPTH_TEST);
614  glDisable(GL_CULL_FACE);
615  glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
616 }
617 
618 ////////////////////////////////////////////////////////////////////////////////
619 ///Draw mesh.
620 
621 void TGLIsoPainter::DrawPlot() const
622 {
623  //Shift plot to point of origin.
624  const Rgl::PlotTranslation trGuard(this);
625 
626 
627  fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
628  DrawSections();
629 
630  if (fIsos.size() != fColorLevels.size()) {
631  Error("TGLIsoPainter::DrawPlot", "Non-equal number of levels and isos");
632  return;
633  }
634 
635  if (!fSelectionPass && HasSections()) {
636  //Surface is semi-transparent during dynamic profiling.
637  //Having several complex nested surfaces, it's not easy
638  //(possible?) to implement correct and _efficient_ transparency
639  //drawing. So, artefacts are possbile.
640  glEnable(GL_BLEND);
641  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
642  glDepthMask(GL_FALSE);
643  }
644 
645  UInt_t colorInd = 0;
646  ConstMeshIter_t iso = fIsos.begin();
647 
648  for (; iso != fIsos.end(); ++iso, ++colorInd)
649  DrawMesh(*iso, colorInd);
650 
651  if (!fSelectionPass && HasSections()) {
652  glDisable(GL_BLEND);
653  glDepthMask(GL_TRUE);
654  }
655 
656  if (fBoxCut.IsActive())
657  fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
658 }
659 
660 ////////////////////////////////////////////////////////////////////////////////
661 /// Draw XOZ parallel section.
662 
663 void TGLIsoPainter::DrawSectionXOZ() const
664 {
665  if (fSelectionPass)
666  return;
667  fXOZSlice.DrawSlice(fXOZSectionPos / fCoord->GetYScale());
668 }
669 
670 ////////////////////////////////////////////////////////////////////////////////
671 /// Draw YOZ parallel section.
672 
673 void TGLIsoPainter::DrawSectionYOZ() const
674 {
675  if (fSelectionPass)
676  return;
677  fYOZSlice.DrawSlice(fYOZSectionPos / fCoord->GetXScale());
678 }
679 
680 ////////////////////////////////////////////////////////////////////////////////
681 /// Draw XOY parallel section.
682 
683 void TGLIsoPainter::DrawSectionXOY() const
684 {
685  if (fSelectionPass)
686  return;
687  fXOYSlice.DrawSlice(fXOYSectionPos / fCoord->GetZScale());
688 }
689 
690 ////////////////////////////////////////////////////////////////////////////////
691 ///Any section exists.
692 
693 Bool_t TGLIsoPainter::HasSections() const
694 {
695  return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos > fBackBox.Get3DBox()[0].X() ||
696  fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
697 }
698 
699 ////////////////////////////////////////////////////////////////////////////////
700 ///Set color for surface.
701 
702 void TGLIsoPainter::SetSurfaceColor(Int_t ind) const
703 {
704  Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.25f};
705 
706  if (fColorLevels.size() == 1) {
707  if (fHist->GetFillColor() != kWhite)
708  if (const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
709  c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
710  } else {
711  const UChar_t *color = fPalette.GetColour(ind);
712  diffColor[0] = color[0] / 255.;
713  diffColor[1] = color[1] / 255.;
714  diffColor[2] = color[2] / 255.;
715  }
716 
717  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
718  const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
719  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
720  diffColor[0] /= 3.5, diffColor[1] /= 3.5, diffColor[2] /= 3.5;
721  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, diffColor);
722  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 30.f);
723 }
724 
725 ////////////////////////////////////////////////////////////////////////////////
726 ///Grid geometry.
727 
728 void TGLIsoPainter::SetMesh(Mesh_t &m, Double_t isoValue)
729 {
730  Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis, fCoord->GetXScale(),
731  fCoord->GetYScale(), fCoord->GetZScale());
732  //Clear mesh if it was from cache.
733  m.ClearMesh();
734  //Select correct TMeshBuilder type.
735  if (typeid(*fHist) == typeid(TH3C)) {
736  Rgl::Mc::TMeshBuilder<TH3C, Float_t> builder(kTRUE);
737  builder.BuildMesh(static_cast<TH3C *>(fHist), geom, &m, isoValue);
738  } else if (typeid(*fHist) == typeid(TH3S)) {
739  Rgl::Mc::TMeshBuilder<TH3S, Float_t> builder(kTRUE);
740  builder.BuildMesh(static_cast<TH3S *>(fHist), geom, &m, isoValue);
741  } else if (typeid(*fHist) == typeid(TH3I)) {
742  Rgl::Mc::TMeshBuilder<TH3I, Float_t> builder(kTRUE);
743  builder.BuildMesh(static_cast<TH3I *>(fHist), geom, &m, isoValue);
744  } else if (typeid(*fHist) == typeid(TH3F)) {
745  Rgl::Mc::TMeshBuilder<TH3F, Float_t> builder(kTRUE);
746  builder.BuildMesh(static_cast<TH3F *>(fHist), geom, &m, isoValue);
747  } else if (typeid(*fHist) == typeid(TH3D)) {
748  Rgl::Mc::TMeshBuilder<TH3D, Float_t> builder(kTRUE);
749  builder.BuildMesh(static_cast<TH3D *>(fHist), geom, &m, isoValue);
750  }
751 }
752 
753 ////////////////////////////////////////////////////////////////////////////////
754 ///Draw TF3 surface
755 
756 void TGLIsoPainter::DrawMesh(const Mesh_t &m, Int_t level) const
757 {
758  if (!fSelectionPass)
759  SetSurfaceColor(level);
760 
761  if (!fBoxCut.IsActive()) {
762  if (!fSelectionPass)
763  Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris);
764  else {
765  Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
766  Rgl::DrawMesh(m.fVerts, m.fTris);
767  }
768  } else {
769  if (!fSelectionPass)
770  Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris, fBoxCut);
771  else {
772  Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
773  Rgl::DrawMesh(m.fVerts, m.fTris, fBoxCut);
774  }
775  }
776 }
777 
778 ////////////////////////////////////////////////////////////////////////////////
779 ///Find max/min bin contents for TH3.
780 
781 void TGLIsoPainter::FindMinMax()
782 {
783  fMinMax.first = fHist->GetBinContent(fXAxis->GetFirst(), fYAxis->GetFirst(), fZAxis->GetFirst());
784  fMinMax.second = fMinMax.first;
785 
786  for (Int_t i = fXAxis->GetFirst(), ei = fXAxis->GetLast(); i <= ei; ++i) {
787  for (Int_t j = fYAxis->GetFirst(), ej = fYAxis->GetLast(); j <= ej; ++j) {
788  for (Int_t k = fZAxis->GetFirst(), ek = fZAxis->GetLast(); k <= ek; ++k) {
789  const Double_t binContent = fHist->GetBinContent(i, j, k);
790  fMinMax.first = TMath::Min(binContent, fMinMax.first);
791  fMinMax.second = TMath::Max(binContent, fMinMax.second);
792  }
793  }
794  }
795 }