41 ClassImp(TGLSurfacePainter);
43 TRandom *TGLSurfacePainter::fgRandom =
new TRandom(0);
48 void TGLSurfacePainter::Projection_t::Swap(Projection_t &rhs)
50 fRGBA[0] = rhs.fRGBA[0], fRGBA[1] = rhs.fRGBA[1], fRGBA[2] = rhs.fRGBA[2], fRGBA[3] = rhs.fRGBA[3];
51 fVertices.swap(rhs.fVertices);
57 TGLSurfacePainter::TGLSurfacePainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
58 : TGLPlotPainter(hist, camera, coord, kTRUE, kTRUE, kTRUE),
68 char *TGLSurfacePainter::GetPlotInfo(Int_t px, Int_t py)
70 static char null[] = {
"" };
73 return fSelectedPart < fSelectionBase ? (
char *)
"TF2" : (
char *)
"Switch to true-color mode to obtain correct info";
74 return fSelectedPart < fSelectionBase ? (
char *)
"TF2" : WindowPointTo3DPoint(px, py);
82 Bool_t TGLSurfacePainter::InitGeometry()
85 switch (fCoord->GetCoordType()) {
87 ret = InitGeometryCartesian();
break;
89 ret = InitGeometryPolar();
break;
91 ret = InitGeometryCylindrical();
break;
93 ret = InitGeometrySpherical();
break;
97 if (ret && fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
104 void TGLSurfacePainter::StartPan(Int_t px, Int_t py)
106 fMousePosition.fX = px;
107 fMousePosition.fY = fCamera->GetHeight() - py;
108 fCamera->StartPan(px, py);
109 fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
116 void TGLSurfacePainter::Pan(Int_t px, Int_t py)
118 if (fSelectedPart >= fSelectionBase) {
119 SaveModelviewMatrix();
120 SaveProjectionMatrix();
122 fCamera->SetCamera();
123 fCamera->Apply(fPadPhi, fPadTheta);
124 fCamera->Pan(px, py);
126 RestoreProjectionMatrix();
127 RestoreModelviewMatrix();
128 }
else if (fSelectedPart > 0) {
130 py = fCamera->GetHeight() - py;
132 SaveModelviewMatrix();
133 SaveProjectionMatrix();
135 fCamera->SetCamera();
136 fCamera->Apply(fPadPhi, fPadTheta);
140 if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
141 fBoxCut.MoveBox(px, py, fSelectedPart);
148 RestoreProjectionMatrix();
149 RestoreModelviewMatrix();
152 fMousePosition.fX = px, fMousePosition.fY = py;
153 fUpdateSelection = kTRUE;
159 void TGLSurfacePainter::AddOption(
const TString &option)
162 const Ssiz_t surfPos = option.Index(
"surf");
163 if (surfPos + 4 < option.Length() && isdigit(option[surfPos + 4])) {
164 switch (option[surfPos + 4] -
'0') {
173 fCoord->SetCoordType(kGLCartesian);
179 if (fCoord->GetCoordType() != kGLSpherical && fCoord->GetCoordType() != kGLCylindrical)
190 option.Index(
"z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
196 void TGLSurfacePainter::ProcessEvent(Int_t event, Int_t , Int_t py)
198 const TGLVertex3 *frame = fBackBox.Get3DBox();
199 if (py == kKey_P || py == kKey_p) {
202 fSectionPass = kTRUE;
206 fXOZSectionPos = frame[0].Y();
207 fYOZSectionPos = frame[0].X();
208 fXOYSectionPos = frame[0].Z();
209 fSectionPass = kFALSE;
211 }
else if (event == kButton1Double && (HasSections() || HasProjections() || fBoxCut.IsActive())) {
212 fXOZSectionPos = frame[0].Y();
213 fYOZSectionPos = frame[0].X();
214 fXOYSectionPos = frame[0].Z();
218 if (fBoxCut.IsActive())
220 if (!gVirtualX->IsCmdThread())
221 gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
224 }
else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
226 Info(
"ProcessEvent",
"Switch to true color to use box cut");
229 fUpdateSelection = kTRUE;
237 void TGLSurfacePainter::InitGL()
const
239 glEnable(GL_LIGHTING);
241 glEnable(GL_DEPTH_TEST);
242 glDisable(GL_CULL_FACE);
243 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
249 void TGLSurfacePainter::DeInitGL()
const
251 glDisable(GL_LIGHTING);
252 glDisable(GL_LIGHT0);
253 glDisable(GL_DEPTH_TEST);
254 glDisable(GL_CULL_FACE);
255 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
264 void TGLSurfacePainter::SetNormals()
266 const Int_t nX = fCoord->GetNXBins();
267 const Int_t nY = fCoord->GetNYBins();
269 fFaceNormals.resize((nX + 1) * (nY + 1));
270 fFaceNormals.assign(fFaceNormals.size(), std::pair<TGLVector3, TGLVector3>());
271 fFaceNormals.SetRowLen(nY + 1);
275 for (Int_t i = 0; i < nX - 1; ++i) {
276 for (Int_t j = 0; j < nY - 1; ++j) {
278 TMath::Normal2Plane(fMesh[i][j + 1].CArr(), fMesh[i][j].CArr(), fMesh[i + 1][j].CArr(),
279 fFaceNormals[i + 1][j + 1].first.Arr());
281 TMath::Normal2Plane(fMesh[i + 1][j].CArr(), fMesh[i + 1][j + 1].CArr(), fMesh[i][j + 1].CArr(),
282 fFaceNormals[i + 1][j + 1].second.Arr());
286 fAverageNormals.resize(nX * nY);
287 fAverageNormals.SetRowLen(nY);
289 fAverageNormals.assign(fAverageNormals.size(), TGLVector3());
291 for (Int_t i = 0; i < nX; ++i) {
292 for (Int_t j = 0; j < nY; ++j) {
293 TGLVector3 &norm = fAverageNormals[i][j];
295 norm += fFaceNormals[i][j].second;
296 norm += fFaceNormals[i][j + 1].first;
297 norm += fFaceNormals[i][j + 1].second;
298 norm += fFaceNormals[i + 1][j].first;
299 norm += fFaceNormals[i + 1][j].second;
300 norm += fFaceNormals[i + 1][j + 1].first;
302 if (!norm.X() && !norm.Y() && !norm.Z())
313 void TGLSurfacePainter::SetSurfaceColor()
const
315 Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.35f};
317 if (fHist->GetFillColor() != kWhite && fType != kSurf1 && fType != kSurf2 && fType != kSurf5)
318 if (
const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
319 c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
321 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
322 const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
323 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
324 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
330 void TGLSurfacePainter::DrawPlot()
const
333 const Rgl::PlotTranslation trGuard(
this);
335 if (fCoord->GetCoordType() == kGLCartesian) {
336 fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
342 if (!fSelectionPass) {
344 glEnable(GL_POLYGON_OFFSET_FILL);
345 glPolygonOffset(1.f, 1.f);
347 if (HasSections() || HasProjections())
351 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
356 if (Textured() && !fSelectionPass) {
357 if (!PreparePalette()) {
359 fDrawPalette = kFALSE;
361 else if (fType != kSurf3)
362 fPalette.EnableTexture(GL_MODULATE);
365 const Int_t nX = fCoord->GetNXBins();
366 const Int_t nY = fCoord->GetNYBins();
367 const Int_t frontPoint = fBackBox.GetFrontPoint();
368 Int_t i = 0, firstJ = 0;
369 const Int_t addI = frontPoint == 2 || frontPoint == 1 ? i = 0, 1 : (i = nX - 2, -1);
370 const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? firstJ = 0, 1 : (firstJ = nY - 2, -1);
372 if (fHighColor && fSelectionPass)
373 Rgl::ObjectIDToColor(fSelectionBase, kTRUE);
375 for (; addI > 0 ? i < nX - 1 : i >= 0; i += addI) {
376 for (Int_t j = firstJ; addJ > 0 ? j < nY - 1 : j >= 0; j += addJ) {
377 Int_t triNumber = 2 * i * (nY - 1) + j * 2 + fSelectionBase;
379 Double_t xMin = TMath::Min(TMath::Min(fMesh[i][j + 1].X(), fMesh[i][j].X()), fMesh[i + 1][j].X());
380 Double_t xMax = TMath::Max(TMath::Max(fMesh[i][j + 1].X(), fMesh[i][j].X()), fMesh[i + 1][j].X());
381 Double_t yMin = TMath::Min(TMath::Min(fMesh[i][j + 1].Y(), fMesh[i][j].Y()), fMesh[i + 1][j].Y());
382 Double_t yMax = TMath::Max(TMath::Max(fMesh[i][j + 1].Y(), fMesh[i][j].Y()), fMesh[i + 1][j].Y());
383 Double_t zMin = TMath::Min(TMath::Min(fMesh[i][j + 1].Z(), fMesh[i][j].Z()), fMesh[i + 1][j].Z());
384 Double_t zMax = TMath::Max(TMath::Max(fMesh[i][j + 1].Z(), fMesh[i][j].Z()), fMesh[i + 1][j].Z());
386 if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
389 if (fSelectionPass && !fHighColor)
390 Rgl::ObjectIDToColor(triNumber, kFALSE);
392 if ((fType == kSurf1 || fType == kSurf2 || fType == kSurf5) && !fSelectionPass)
393 Rgl::DrawFaceTextured(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
394 fTexMap[i][j + 1], fTexMap[i][j], fTexMap[i + 1][j],
395 fAverageNormals[i][j + 1], fAverageNormals[i][j],
396 fAverageNormals[i + 1][j]);
398 Rgl::DrawSmoothFace(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
399 fAverageNormals[i][j + 1], fAverageNormals[i][j],
400 fAverageNormals[i + 1][j]);
404 if (fSelectionPass && !fHighColor)
405 Rgl::ObjectIDToColor(triNumber, kFALSE);
407 if ((fType == kSurf1 || fType == kSurf2 || fType == kSurf5) && !fSelectionPass)
408 Rgl::DrawFaceTextured(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
409 fTexMap[i + 1][j], fTexMap[i + 1][j + 1], fTexMap[i][j + 1],
410 fAverageNormals[i + 1][j], fAverageNormals[i + 1][j + 1],
411 fAverageNormals[i][j + 1]);
413 Rgl::DrawSmoothFace(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
414 fAverageNormals[i + 1][j], fAverageNormals[i + 1][j + 1],
415 fAverageNormals[i][j + 1]);
420 glDisable(GL_POLYGON_OFFSET_FILL);
422 if (fBoxCut.IsActive())
423 fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
425 if (fType != kSurf3 && Textured() && !fSelectionPass)
426 fPalette.DisableTexture();
429 if (!fSelectionPass) {
430 const TGLEnableGuard blendGuard(GL_BLEND);
432 if (fType == kSurf || fType == kSurf1 || fType == kSurf3) {
433 const TGLDisableGuard lightGuard(GL_LIGHTING);
434 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
436 glDepthMask(GL_FALSE);
438 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
439 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
441 glColor4d(0., 0., 0., 0.5);
443 for (i = 0; i < nX - 1; ++i) {
444 for (Int_t j = 0; j < nY - 1; ++j) {
445 Rgl::DrawQuadOutline(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j], fMesh[i + 1][j + 1]);
449 glDepthMask(GL_TRUE);
453 if (fType == kSurf3 && !fSelectionPass) {
454 fPalette.EnableTexture(GL_MODULATE);
455 const TGLEnableGuard blend(GL_BLEND);
456 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
457 DrawContoursProjection();
458 fPalette.DisableTexture();
461 if (!fSelectionPass && fSelectedPart > 6) {
463 const TGLDisableGuard lightGuard(GL_LIGHTING);
464 const TGLEnableGuard blendGuard(GL_BLEND);
465 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
466 const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
467 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
470 glColor4d(1.f, 0.f, 0.4f, 0.6f);
471 glBegin(GL_LINE_STRIP);
472 for (i = 0; i < nX; ++i)
473 glVertex3dv(fMesh[i][0].CArr());
474 for (Int_t j = 0; j < nY; ++j)
475 glVertex3dv(fMesh[nX - 1][j].CArr());
476 for (i = nX - 1; i >= 0; --i)
477 glVertex3dv(fMesh[i][nY - 1].CArr());
478 for (Int_t j = nY - 1; j >= 0; --j)
479 glVertex3dv(fMesh[0][j].CArr());
484 if (!fSelectionPass && fDrawPalette)
495 Bool_t TGLSurfacePainter::InitGeometryCartesian()
497 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
500 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
504 const Int_t nX = fCoord->GetNXBins();
505 const Int_t nY = fCoord->GetNYBins();
507 fMesh.resize(nX * nY);
510 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
511 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
512 fCoord->GetXLog() ? fMesh[i][j].X() = TMath::Log10(fXAxis->GetBinCenter(ir)) * fCoord->GetXScale()
513 : fMesh[i][j].X() = fXAxis->GetBinCenter(ir) * fCoord->GetXScale();
514 fCoord->GetYLog() ? fMesh[i][j].Y() = TMath::Log10(fYAxis->GetBinCenter(jr)) * fCoord->GetYScale()
515 : fMesh[i][j].Y() = fYAxis->GetBinCenter(jr) * fCoord->GetYScale();
517 Double_t z = fHist->GetBinContent(ir, jr);
524 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
525 fMinMaxVal.second = fMinMaxVal.first;
527 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
528 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
529 const Double_t val = fHist->GetBinContent(i, j);
530 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
531 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
535 ClampZ(fMinMaxVal.first);
536 ClampZ(fMinMaxVal.second);
538 fUpdateTexMap = kTRUE;
543 if (fCoord->Modified()) {
544 fUpdateSelection = kTRUE;
545 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
546 fXOZSectionPos = vertex.Y();
547 fYOZSectionPos = vertex.X();
548 fXOYSectionPos = vertex.Z();
549 fCoord->ResetModified();
550 Rgl::SetZLevels(fZAxis, fCoord->GetZRange().first, fCoord->GetZRange().second, fCoord->GetZScale(), fZLevels);
563 Bool_t TGLSurfacePainter::InitGeometryPolar()
565 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
568 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
570 if (fCoord->Modified()) {
571 fUpdateSelection = kTRUE;
572 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
573 fXOZSectionPos = vertex.Y();
574 fYOZSectionPos = vertex.X();
575 fXOYSectionPos = vertex.Z();
576 fCoord->ResetModified();
579 const Int_t nY = fCoord->GetNYBins();
580 const Int_t nX = fCoord->GetNXBins();
582 fMesh.resize(nX * nY);
585 const Double_t fullAngle = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
586 const Double_t phiLow = fXAxis->GetBinCenter(1);
587 const Double_t rRange = fYAxis->GetBinCenter(fYAxis->GetNbins()) - fYAxis->GetBinCenter(1);
589 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
590 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
591 const Double_t angle = (fXAxis->GetBinCenter(ir) - phiLow) / fullAngle * TMath::TwoPi();
592 const Double_t radius = ((fYAxis->GetBinCenter(jr)) - fYAxis->GetBinCenter(1)) /
593 rRange * fCoord->GetYScale();
594 fMesh[i][j].X() = radius * TMath::Cos(angle);
595 fMesh[i][j].Y() = radius * TMath::Sin(angle);
596 Double_t z = fHist->GetBinContent(ir, jr);
605 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
606 fMinMaxVal.second = fMinMaxVal.first;
608 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
609 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
610 const Double_t val = fHist->GetBinContent(i, j);
611 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
612 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
616 fUpdateTexMap = kTRUE;
630 Bool_t TGLSurfacePainter::InitGeometryCylindrical()
632 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
635 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
637 if (fCoord->Modified()) {
638 fUpdateSelection = kTRUE;
639 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
640 fXOZSectionPos = vertex.Y();
641 fYOZSectionPos = vertex.X();
642 fXOYSectionPos = vertex.Z();
643 fCoord->ResetModified();
646 const Int_t nY = fCoord->GetNYBins();
647 const Int_t nX = fCoord->GetNXBins();
648 fMesh.resize(nX * nY);
651 Double_t legoR = gStyle->GetLegoInnerR();
652 if (legoR > 1. || legoR < 0.)
654 const Double_t rRange = fCoord->GetZLength();
655 const Double_t sc = (1 - legoR) * fCoord->GetXScale();
656 legoR *= fCoord->GetXScale();
658 const Double_t fullAngle = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
659 const Double_t phiLow = fXAxis->GetBinCenter(1);
662 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
663 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
664 angle = (fXAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
665 Double_t r = fType != kSurf5 ? legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc : legoR;
666 fMesh[i][j].X() = r * TMath::Cos(angle);
667 fMesh[i][j].Y() = fCoord->GetYLog() ?
668 TMath::Log10(fYAxis->GetBinCenter(jr)) * fCoord->GetYScale()
670 fYAxis->GetBinCenter(jr) * fCoord->GetYScale();
671 fMesh[i][j].Z() = r * TMath::Sin(angle);
676 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
677 fMinMaxVal.second = fMinMaxVal.first;
679 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
680 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
681 const Double_t val = fHist->GetBinContent(i, j);
682 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
683 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
687 fUpdateTexMap = kTRUE;
703 Bool_t TGLSurfacePainter::InitGeometrySpherical()
705 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
708 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
710 if (fCoord->Modified()) {
711 fUpdateSelection = kTRUE;
712 const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
713 fXOZSectionPos = vertex.Y();
714 fYOZSectionPos = vertex.X();
715 fXOYSectionPos = vertex.Z();
716 fCoord->ResetModified();
719 const Int_t nY = fCoord->GetNYBins();
720 const Int_t nX = fCoord->GetNXBins();
721 fMesh.resize(nX * nY);
724 Double_t legoR = gStyle->GetLegoInnerR();
725 if (legoR > 1. || legoR < 0.)
727 const Double_t rRange = fCoord->GetZLength();
728 const Double_t sc = (1 - legoR) * fCoord->GetXScale();
729 legoR *= fCoord->GetXScale();
732 const Double_t fullTheta = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
733 const Double_t thetaLow = fXAxis->GetBinCenter(1);
735 const Double_t fullPhi = fYAxis->GetBinCenter(fYAxis->GetNbins()) - fYAxis->GetBinCenter(1);
736 const Double_t phiLow = fYAxis->GetBinCenter(1);
738 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
740 const Double_t theta = (fXAxis->GetBinCenter(ir) - thetaLow) / fullTheta * TMath::TwoPi();
742 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
744 const Double_t phi = (fYAxis->GetBinCenter(jr) - phiLow) / fullPhi * TMath::Pi();
745 const Double_t r = fType != kSurf5 ? legoR + (fHist->GetBinContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc
748 fMesh[i][j].X() = r * TMath::Sin(phi) * TMath::Cos(theta);
749 fMesh[i][j].Y() = r * TMath::Sin(phi) * TMath::Sin(theta);
750 fMesh[i][j].Z() = r * TMath::Cos(phi);
755 fMinMaxVal.first = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
756 fMinMaxVal.second = fMinMaxVal.first;
758 for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
759 for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
760 const Double_t val = fHist->GetBinContent(i, j);
761 fMinMaxVal.first = TMath::Min(fMinMaxVal.first, val);
762 fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
766 fUpdateTexMap = kTRUE;
778 void TGLSurfacePainter::DrawProjections()
const
780 const TGLDisableGuard lightGuard(GL_LIGHTING);
781 const TGLEnableGuard blendGuard(GL_BLEND);
782 const TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
783 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
784 glDepthMask(GL_FALSE);
787 typedef std::list<Projection_t>::const_iterator CLI_t;
788 for (CLI_t begin = fXOZProj.begin(), end = fXOZProj.end(); begin != end; ++begin) {
789 const Projection_t &proj = *begin;
790 glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
792 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
793 glBegin(GL_LINE_STRIP);
794 glVertex3dv(proj.fVertices[i * 3].CArr());
795 glVertex3dv(proj.fVertices[i * 3 + 1].CArr());
796 glVertex3dv(proj.fVertices[i * 3 + 2].CArr());
799 const Double_t y = fBackBox.GetFrontPoint() == 2 || fBackBox.GetFrontPoint() == 3 ? fBackBox.Get3DBox()[0].Y() : fBackBox.Get3DBox()[2].Y();
800 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
801 glBegin(GL_LINE_STRIP);
802 const TGLVertex3 &v1 = proj.fVertices[i * 3];
803 glVertex3d(v1.X(), y, v1.Z());
804 const TGLVertex3 &v2 = proj.fVertices[i * 3 + 1];
805 glVertex3d(v2.X(), y, v2.Z());
806 const TGLVertex3 &v3 = proj.fVertices[i * 3 + 2];
807 glVertex3d(v3.X(), y, v3.Z());
812 for (CLI_t begin = fYOZProj.begin(), end = fYOZProj.end(); begin != end; ++begin) {
813 const Projection_t &proj = *begin;
814 glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
816 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
817 glBegin(GL_LINE_STRIP);
818 glVertex3dv(proj.fVertices[i * 3].CArr());
819 glVertex3dv(proj.fVertices[i * 3 + 1].CArr());
820 glVertex3dv(proj.fVertices[i * 3 + 2].CArr());
824 const Double_t x = fBackBox.GetFrontPoint() == 2 || fBackBox.GetFrontPoint() == 1 ? fBackBox.Get3DBox()[0].X() : fBackBox.Get3DBox()[2].X();
825 for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
826 glBegin(GL_LINE_STRIP);
827 const TGLVertex3 &v1 = proj.fVertices[i * 3];
828 glVertex3d(x, v1.Y(), v1.Z());
829 const TGLVertex3 &v2 = proj.fVertices[i * 3 + 1];
830 glVertex3d(x, v2.Y(), v2.Z());
831 const TGLVertex3 &v3 = proj.fVertices[i * 3 + 2];
832 glVertex3d(x, v3.Y(), v3.Z());
837 for (CLI_t begin = fXOYProj.begin(), end = fXOYProj.end(); begin != end; ++begin) {
838 const Projection_t &proj = *begin;
839 glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
841 for(UInt_t i = 0, e = proj.fVertices.size() / 2; i < e; ++i) {
843 glVertex3dv(proj.fVertices[i * 2].CArr());
844 glVertex3dv(proj.fVertices[i * 2 + 1].CArr());
849 for(UInt_t i = 0, e = proj.fVertices.size() / 2; i < e; ++i) {
851 const TGLVertex3 &v1 = proj.fVertices[i * 2];
852 glVertex3d(v1.X(), v1.Y(), fBackBox.Get3DBox()[0].Z());
853 const TGLVertex3 &v2 = proj.fVertices[i * 2 + 1];
854 glVertex3d(v2.X(), v2.Y(), fBackBox.Get3DBox()[0].Z());
860 glDepthMask(GL_TRUE);
867 void TGLSurfacePainter::DrawSectionXOZ()
const
872 for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
873 if (fMesh[0][j].Y() <= fXOZSectionPos && fXOZSectionPos <= fMesh[0][j + 1].Y()) {
881 const TGLPlane profilePlane(0., 1., 0., -fXOZSectionPos);
884 glColor3d(1., 0., 0.);
887 for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
888 glBegin(GL_LINE_STRIP);
889 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i + 1][binY + 1]), kFALSE).second.CArr());
890 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i][binY + 1]), kFALSE).second.CArr());
891 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i][binY], fMesh[i][binY + 1]), kFALSE).second.CArr());
896 fProj.fVertices.clear();
897 for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
898 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i + 1][binY + 1]), kFALSE).second);
899 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i][binY + 1]), kFALSE).second);
900 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i][binY], fMesh[i][binY + 1]), kFALSE).second);
902 if (fProj.fVertices.size()) {
903 fProj.fRGBA[0] = (UChar_t) (50 + fgRandom->Integer(206));
904 fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
905 fProj.fRGBA[2] = (UChar_t) fgRandom->Integer(150);
906 fProj.fRGBA[3] = 150;
907 static Projection_t dummy;
908 fXOZProj.push_back(dummy);
909 fXOZProj.back().Swap(fProj);
918 void TGLSurfacePainter::DrawSectionYOZ()
const
923 for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
924 if (fMesh[i][0].X() <= fYOZSectionPos && fYOZSectionPos <= fMesh[i + 1][0].X()) {
932 const TGLPlane profilePlane(1., 0., 0., -fYOZSectionPos);
935 glColor3d(1., 0., 0.);
937 for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
938 glBegin(GL_LINE_STRIP);
939 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j + 1]), kFALSE).second.CArr());
940 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j]), kFALSE).second.CArr());
941 glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j], fMesh[binX + 1][j]), kFALSE).second.CArr());
946 fProj.fVertices.clear();
947 for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
948 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j + 1]), kFALSE).second);
949 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j]), kFALSE).second);
950 fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j], fMesh[binX + 1][j]), kFALSE).second);
952 if (fProj.fVertices.size()) {
953 fProj.fRGBA[0] = (UChar_t) (50 + fgRandom->Integer(206));
954 fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
955 fProj.fRGBA[2] = (UChar_t) fgRandom->Integer(150);
956 fProj.fRGBA[3] = 150;
957 static Projection_t dummy;
958 fYOZProj.push_back(dummy);
959 fYOZProj.back().Swap(fProj);
969 void TGLSurfacePainter::DrawSectionXOY()
const
973 const Int_t nX = fCoord->GetNXBins();
974 const Int_t nY = fCoord->GetNYBins();
975 const TGLPlane profilePlane(0., 0., 1., -fXOYSectionPos);
976 TGLVertex3 intersection[2];
980 fProj.fVertices.clear();
982 glColor3d(1., 0., 0.);
986 for (Int_t i = 0; i < nX - 1; ++i) {
987 for (Int_t j = 0; j < nY - 1; ++j) {
988 const TGLVertex3 &v1 = fMesh[i + 1][j], &v2 = fMesh[i][j], &v3 = fMesh[i][j + 1], &v4 = fMesh[i + 1][j + 1];
989 Double_t zMin = TMath::Min(TMath::Min(v1.Z(), v2.Z()), v3.Z());
990 Double_t zMax = TMath::Max(TMath::Max(v1.Z(), v2.Z()), v3.Z());
992 if (zMin < fXOYSectionPos && zMax > fXOYSectionPos) {
994 if ((v1.Z() > fXOYSectionPos && v2.Z() < fXOYSectionPos) || (v2.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos)) {
995 TGLLine3 line(v1, v2);
996 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
998 if ((v2.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos) || (v3.Z() > fXOYSectionPos && v2.Z() < fXOYSectionPos)) {
999 TGLLine3 line(v2, v3);
1000 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1002 if ((np < 2 && v1.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos) || (v3.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos)) {
1003 TGLLine3 line(v1, v3);
1004 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1007 if (!fSectionPass) {
1009 glVertex3dv(intersection[0].CArr());
1010 glVertex3dv(intersection[1].CArr());
1013 fProj.fVertices.push_back(intersection[0]);
1014 fProj.fVertices.push_back(intersection[1]);
1018 zMin = TMath::Min(v4.Z(), zMin);
1019 zMax = TMath::Max(v4.Z(), zMax);
1020 if (zMin < fXOYSectionPos && zMax > fXOYSectionPos) {
1022 if ((v3.Z() > fXOYSectionPos && v4.Z() < fXOYSectionPos) || (v4.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos)) {
1023 TGLLine3 line(v3, v4);
1024 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1026 if ((v4.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos) || (v1.Z() > fXOYSectionPos && v4.Z() < fXOYSectionPos)) {
1027 TGLLine3 line(v4, v1);
1028 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1030 if ((np < 2 && v3.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos) || (v1.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos)) {
1031 TGLLine3 line(v3, v1);
1032 intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
1035 if (!fSectionPass) {
1037 glVertex3dv(intersection[0].CArr());
1038 glVertex3dv(intersection[1].CArr());
1041 fProj.fVertices.push_back(intersection[0]);
1042 fProj.fVertices.push_back(intersection[1]);
1049 if (fSectionPass && fProj.fVertices.size()) {
1050 fProj.fRGBA[0] = (UChar_t) fgRandom->Integer(150);
1051 fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
1052 fProj.fRGBA[2] = (UChar_t) (50 + fgRandom->Integer(206));
1053 fProj.fRGBA[3] = 150;
1054 static Projection_t dummy;
1055 fXOYProj.push_back(dummy);
1056 fXOYProj.back().Swap(fProj);
1066 void TGLSurfacePainter::ClampZ(Double_t &zVal)
const
1068 const TGLVertex3 *frame = fBackBox.Get3DBox();
1070 if (fCoord->GetZLog())
1072 zVal = frame[0].Z();
1074 zVal = TMath::Log10(zVal) * fCoord->GetZScale();
1076 zVal *= fCoord->GetZScale();
1078 if (zVal > frame[4].Z())
1079 zVal = frame[4].Z();
1080 else if (zVal < frame[0].Z())
1081 zVal = frame[0].Z();
1087 char *TGLSurfacePainter::WindowPointTo3DPoint(Int_t px, Int_t py)
const
1089 py = fCamera->GetHeight() - py;
1091 const Int_t nY = fCoord->GetNYBins() - 1;
1092 Int_t selected = fSelectedPart - (fSelectionBase - 1);
1093 Int_t k = selected / 2;
1097 const Bool_t odd = selected & 1;
1098 const TGLVertex3 &v1 = odd ? fMesh[i][j + 1] : fMesh[i + 1][j];
1099 const TGLVertex3 &v2 = odd ? fMesh[i + 1][j + 1] : fMesh[i][j];
1100 const TGLVertex3 &v3 = odd ? fMesh[i + 1][j] : fMesh[i][j + 1];
1102 TGLVertex3 winV1, winV2, winV3;
1104 Double_t mvMatrix[16] = {0.};
1105 glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix);
1106 Double_t prMatrix[16] = {0.};
1107 glGetDoublev(GL_PROJECTION_MATRIX, prMatrix);
1108 Int_t viewport[4] = {0};
1109 glGetIntegerv(GL_VIEWPORT, viewport);
1111 gluProject(v1.X(), v1.Y(), v1.Z(), mvMatrix, prMatrix, viewport, &winV1.X(), &winV1.Y(), &winV1.Z());
1112 gluProject(v2.X(), v2.Y(), v2.Z(), mvMatrix, prMatrix, viewport, &winV2.X(), &winV2.Y(), &winV2.Z());
1113 gluProject(v3.X(), v3.Y(), v3.Z(), mvMatrix, prMatrix, viewport, &winV3.X(), &winV3.Y(), &winV3.Z());
1115 Double_t planeABCD[4] = {0.};
1116 TMath::Normal2Plane(winV1.CArr(), winV2.CArr(), winV3.CArr(), planeABCD);
1117 planeABCD[3] = - winV1.X() * planeABCD[0] - winV1.Y() * planeABCD[1] - winV1.Z() * planeABCD[2];
1118 Double_t pz = (-planeABCD[3] - planeABCD[0] * px - planeABCD[1] * py) / planeABCD[2];
1119 Double_t rez[3] = {0.};
1121 gluUnProject(px, py, pz, mvMatrix, prMatrix, viewport, rez, rez + 1, rez + 2);
1123 fObjectInfo.Form(
"(x == %f, y == %f, z == %f)",
1124 rez[0] / fCoord->GetXScale(),
1125 rez[1] / fCoord->GetYScale(),
1126 rez[2] / fCoord->GetZScale());
1128 return (
char *)fObjectInfo.Data();
1134 Bool_t TGLSurfacePainter::PreparePalette()
const
1139 if(fMinMaxVal.first == fMinMaxVal.second)
1143 if (fHist->TestBit(TH1::kUserContour))
1144 fHist->ResetBit(TH1::kUserContour);
1146 UInt_t paletteSize = gStyle->GetNumberContours();
1150 Bool_t rez = fPalette.GeneratePalette(paletteSize, fMinMaxVal);
1152 if (rez && fUpdateTexMap) {
1154 fUpdateTexMap = kFALSE;
1163 void TGLSurfacePainter::GenTexMap()
const
1165 const Int_t nX = fCoord->GetNXBins();
1166 const Int_t nY = fCoord->GetNYBins();
1168 fTexMap.resize(nX * nY);
1169 fTexMap.SetRowLen(nY);
1171 for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
1172 for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
1173 Double_t z = fHist->GetBinContent(ir, jr);
1174 if (fCoord->GetCoordType() == kGLCartesian)
1176 fTexMap[i][j] = fPalette.GetTexCoord(z);
1184 void TGLSurfacePainter::DrawContoursProjection()
const
1186 static const Float_t whiteDiffuse[] = {0.8f, 0.8f, 0.8f, 0.65f};
1187 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, whiteDiffuse);
1188 for (Int_t i = 0, ei = fCoord->GetNXBins() - 1; i < ei; ++i) {
1189 for (Int_t j = 0, ej = fCoord->GetNYBins() - 1; j < ej; ++j) {
1190 Rgl::DrawFaceTextured(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
1191 fTexMap[i][j + 1], fTexMap[i][j], fTexMap[i + 1][j],
1192 fBackBox.Get3DBox()[4].Z(), TGLVector3(0., 0., 1.));
1193 Rgl::DrawFaceTextured(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
1194 fTexMap[i + 1][j], fTexMap[i + 1][j + 1], fTexMap[i][j + 1],
1195 fBackBox.Get3DBox()[4].Z(), TGLVector3(0., 0., 1.));
1203 Bool_t TGLSurfacePainter::Textured()
const
1220 Bool_t TGLSurfacePainter::HasSections()
const
1222 return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos > fBackBox.Get3DBox()[0].X() ||
1223 fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
1229 Bool_t TGLSurfacePainter::HasProjections()
const
1231 return fXOZProj.size() || fYOZProj.size() || fXOYProj.size();
1239 void TGLSurfacePainter::DrawPalette()
const
1246 Rgl::DrawPalette(fCamera, fPalette);
1250 fCamera->SetCamera();
1251 fCamera->Apply(fPadPhi, fPadTheta);
1257 void TGLSurfacePainter::DrawPaletteAxis()
const
1259 gVirtualX->SetDrawMode(TVirtualX::kCopy);
1260 Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);