TGLSurfacePainter.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id$
00002 // Author:  Timur Pocheptsov  31/08/2006
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include <algorithm>
00013 #include "Riostream.h"
00014 #include <cstdlib>
00015 #include <cctype>
00016 
00017 #include "TVirtualPad.h"
00018 #include "KeySymbols.h"
00019 #include "TVirtualGL.h"
00020 #include "TVirtualX.h"
00021 #include "Buttons.h"
00022 #include "TString.h"
00023 #include "TStyle.h"
00024 #include "TGaxis.h"
00025 #include "TColor.h"
00026 #include "TROOT.h"
00027 #include "TMath.h"
00028 #include "TAxis.h"
00029 #include "TH1.h"
00030 #include "TRandom.h"
00031 
00032 #include "TGLSurfacePainter.h"
00033 #include "TGLPlotCamera.h"
00034 #include "TGLIncludes.h"
00035 
00036 //______________________________________________________________________________
00037 //
00038 // Implements painting of TH2 with "SURF" option.
00039 
00040 ClassImp(TGLSurfacePainter)
00041 
00042 TRandom *TGLSurfacePainter::fgRandom = new TRandom(0);
00043 
00044 //______________________________________________________________________________
00045 void TGLSurfacePainter::Projection_t::Swap(Projection_t &rhs)
00046 {
00047    // Constructor.
00048 
00049    fRGBA[0] = rhs.fRGBA[0], fRGBA[1] = rhs.fRGBA[1], fRGBA[2] = rhs.fRGBA[2], fRGBA[3] = rhs.fRGBA[3];
00050    fVertices.swap(rhs.fVertices);
00051 }
00052 
00053 //______________________________________________________________________________
00054 TGLSurfacePainter::TGLSurfacePainter(TH1 *hist, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
00055                                      : TGLPlotPainter(hist, camera, coord, kTRUE, kTRUE, kTRUE),
00056                                        fType(kSurf),
00057                                        fSectionPass(kFALSE),
00058                                        fUpdateTexMap(kTRUE)
00059 {
00060    // Constructor.
00061 }
00062 
00063 //______________________________________________________________________________
00064 char *TGLSurfacePainter::GetPlotInfo(Int_t px, Int_t py)
00065 {
00066    //Coords for point on surface under cursor.
00067 
00068    static char null[] = { "" };
00069    if (fSelectedPart) {
00070       if (fHighColor)
00071          return fSelectedPart < fSelectionBase ? (char *)"TF2" : (char *)"Switch to true-color mode to obtain correct info";
00072       return fSelectedPart < fSelectionBase ? (char *)"TF2" : WindowPointTo3DPoint(px, py);
00073    }
00074    return null;
00075 }
00076 
00077 //______________________________________________________________________________
00078 Bool_t TGLSurfacePainter::InitGeometry()
00079 {
00080    //Set mesh, normals.
00081    Bool_t ret = kFALSE;
00082    switch (fCoord->GetCoordType()) {
00083    case kGLCartesian:
00084       ret = InitGeometryCartesian(); break;
00085    case kGLPolar:
00086       ret = InitGeometryPolar(); break;
00087    case kGLCylindrical:
00088       ret = InitGeometryCylindrical(); break;
00089    case kGLSpherical:
00090       ret = InitGeometrySpherical(); break;
00091    default:
00092       return kFALSE;
00093    }
00094    if (ret && fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
00095    return ret;
00096 }
00097 
00098 //______________________________________________________________________________
00099 void TGLSurfacePainter::StartPan(Int_t px, Int_t py)
00100 {
00101    //User clicks right mouse button (in a pad).
00102    fMousePosition.fX = px;
00103    fMousePosition.fY = fCamera->GetHeight() - py;
00104    fCamera->StartPan(px, py);
00105    fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
00106 }
00107 
00108 //______________________________________________________________________________
00109 void TGLSurfacePainter::Pan(Int_t px, Int_t py)
00110 {
00111    //User's moving mouse cursor, with middle mouse button pressed (for pad).
00112    //Calculate 3d shift related to 2d mouse movement.
00113    if (fSelectedPart >= fSelectionBase) {//Pan camera.
00114       SaveModelviewMatrix();
00115       SaveProjectionMatrix();
00116 
00117       fCamera->SetCamera();
00118       fCamera->Apply(fPadPhi, fPadTheta);
00119       fCamera->Pan(px, py);
00120 
00121       RestoreProjectionMatrix();
00122       RestoreModelviewMatrix();
00123    } else if (fSelectedPart > 0) {
00124       //Convert py into bottom-top orientation.
00125       py = fCamera->GetHeight() - py;
00126 
00127       SaveModelviewMatrix();
00128       SaveProjectionMatrix();
00129 
00130       fCamera->SetCamera();
00131       fCamera->Apply(fPadPhi, fPadTheta);
00132 
00133 
00134       if (!fHighColor) {
00135          if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
00136             fBoxCut.MoveBox(px, py, fSelectedPart);
00137          else
00138             MoveSection(px, py);
00139       }
00140       else
00141          MoveSection(px, py);
00142 
00143       RestoreProjectionMatrix();
00144       RestoreModelviewMatrix();
00145    }
00146 
00147    fMousePosition.fX = px, fMousePosition.fY = py;
00148    fUpdateSelection = kTRUE;
00149 }
00150 
00151 //______________________________________________________________________________
00152 void TGLSurfacePainter::AddOption(const TString &option)
00153 {
00154    //Additional options for surfaces.
00155    using namespace std;
00156    const Ssiz_t surfPos = option.Index("surf");//"surf" _already_ _exists_ in a string.
00157    if (surfPos + 4 < option.Length() && isdigit(option[surfPos + 4])) {
00158       switch (option[surfPos + 4] - '0') {
00159       case 1:
00160          fType = kSurf1;
00161          break;
00162       case 2:
00163          fType = kSurf2;
00164          break;
00165       case 3:
00166          fType = kSurf3;
00167          fCoord->SetCoordType(kGLCartesian);
00168          break;
00169       case 4:
00170          fType = kSurf4;
00171          break;
00172       case 5:
00173          if (fCoord->GetCoordType() != kGLSpherical && fCoord->GetCoordType() != kGLCylindrical)
00174             fType = kSurf3;
00175          else
00176             fType = kSurf5;
00177          break;
00178       default:
00179          fType = kSurf;
00180       }
00181    } else
00182       fType = kSurf;
00183 
00184    option.Index("z") == kNPOS ? fDrawPalette = kFALSE : fDrawPalette = kTRUE;
00185 }
00186 
00187 //______________________________________________________________________________
00188 void TGLSurfacePainter::ProcessEvent(Int_t event, Int_t /*px*/, Int_t py)
00189 {
00190    //Remove all profiles/sections.
00191    const TGLVertex3 *frame = fBackBox.Get3DBox();
00192    if (py == kKey_P || py == kKey_p) {
00193 
00194       if (HasSections()) {
00195          fSectionPass = kTRUE;
00196          DrawSectionXOZ();
00197          DrawSectionYOZ();
00198          DrawSectionXOY();
00199          fXOZSectionPos = frame[0].Y();
00200          fYOZSectionPos = frame[0].X();
00201          fXOYSectionPos = frame[0].Z();
00202          fSectionPass = kFALSE;
00203       }
00204    } else if (event == kButton1Double && (HasSections() || HasProjections() || fBoxCut.IsActive())) {
00205       fXOZSectionPos = frame[0].Y();
00206       fYOZSectionPos = frame[0].X();
00207       fXOYSectionPos = frame[0].Z();
00208       fXOZProj.clear();
00209       fYOZProj.clear();
00210       fXOYProj.clear();
00211       if (fBoxCut.IsActive())
00212          fBoxCut.TurnOnOff();
00213       if (!gVirtualX->IsCmdThread())
00214          gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)this));
00215       else
00216          Paint();
00217    } else if (event == kKeyPress && (py == kKey_c || py == kKey_C)) {
00218       if (fHighColor)
00219          Info("ProcessEvent", "Switch to true color to use box cut");
00220       else {
00221          fBoxCut.TurnOnOff();
00222          fUpdateSelection = kTRUE;
00223       }
00224    }
00225 }
00226 
00227 //______________________________________________________________________________
00228 void TGLSurfacePainter::InitGL()const
00229 {
00230    //Initialize some OpenGL state variables.
00231    glEnable(GL_LIGHTING);
00232    glEnable(GL_LIGHT0);
00233    glEnable(GL_DEPTH_TEST);
00234    glDisable(GL_CULL_FACE);
00235    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
00236 }
00237 
00238 //______________________________________________________________________________
00239 void TGLSurfacePainter::DeInitGL()const
00240 {
00241    //Initialize some OpenGL state variables.
00242    glDisable(GL_LIGHTING);
00243    glDisable(GL_LIGHT0);
00244    glDisable(GL_DEPTH_TEST);
00245    glDisable(GL_CULL_FACE);
00246    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
00247 }
00248 
00249 
00250 //______________________________________________________________________________
00251 void TGLSurfacePainter::SetNormals()
00252 {
00253    //One normal per vertex;
00254    //this normal is average of
00255    //neighbouring triangles normals.
00256    const Int_t nX = fCoord->GetNXBins();
00257    const Int_t nY = fCoord->GetNYBins();
00258 
00259    fFaceNormals.resize((nX + 1) * (nY + 1));
00260    fFaceNormals.assign(fFaceNormals.size(), std::pair<TGLVector3, TGLVector3>());
00261    fFaceNormals.SetRowLen(nY + 1);
00262 
00263 
00264    //first, calculate normal for each triangle face
00265    for (Int_t i = 0; i < nX - 1; ++i) {
00266       for (Int_t j = 0; j < nY - 1; ++j) {
00267          //first "bottom-left" triangle
00268          TMath::Normal2Plane(fMesh[i][j + 1].CArr(), fMesh[i][j].CArr(), fMesh[i + 1][j].CArr(),
00269                              fFaceNormals[i + 1][j + 1].first.Arr());
00270          //second "top-right" triangle
00271          TMath::Normal2Plane(fMesh[i + 1][j].CArr(), fMesh[i + 1][j + 1].CArr(), fMesh[i][j + 1].CArr(),
00272                              fFaceNormals[i + 1][j + 1].second.Arr());
00273       }
00274    }
00275 
00276    fAverageNormals.resize(nX * nY);
00277    fAverageNormals.SetRowLen(nY);
00278 
00279    fAverageNormals.assign(fAverageNormals.size(), TGLVector3());
00280    //second, calculate average normal for each vertex
00281    for (Int_t i = 0; i < nX; ++i) {
00282       for (Int_t j = 0; j < nY; ++j) {
00283          TGLVector3 &norm = fAverageNormals[i][j];
00284 
00285          norm += fFaceNormals[i][j].second;
00286          norm += fFaceNormals[i][j + 1].first;
00287          norm += fFaceNormals[i][j + 1].second;
00288          norm += fFaceNormals[i + 1][j].first;
00289          norm += fFaceNormals[i + 1][j].second;
00290          norm += fFaceNormals[i + 1][j + 1].first;
00291 
00292          if (!norm.X() && !norm.Y() && !norm.Z())
00293             continue;
00294 
00295          norm.Normalise();
00296       }
00297    }
00298 }
00299 
00300 //______________________________________________________________________________
00301 void TGLSurfacePainter::SetSurfaceColor()const
00302 {
00303    //Set color for surface.
00304    Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.35f};
00305 
00306    if (fHist->GetFillColor() != kWhite && fType != kSurf1 && fType != kSurf2 && fType != kSurf5)
00307       if (const TColor *c = gROOT->GetColor(fHist->GetFillColor()))
00308          c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
00309 
00310    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffColor);
00311    const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
00312    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
00313    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
00314 }
00315 
00316 //______________________________________________________________________________
00317 void TGLSurfacePainter::DrawPlot()const
00318 {
00319    //Draw surf/surf1/surf2/surf4
00320 
00321    //Shift plot to point of origin.
00322    const Rgl::PlotTranslation trGuard(this);
00323 
00324    if (fCoord->GetCoordType() == kGLCartesian) {
00325       fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
00326       DrawSections();
00327       if (!fSelectionPass)
00328          DrawProjections();
00329    }
00330 
00331    if (!fSelectionPass) {
00332       SetSurfaceColor();
00333       glEnable(GL_POLYGON_OFFSET_FILL);
00334       glPolygonOffset(1.f, 1.f);
00335 
00336       if (HasSections() || HasProjections())
00337       {
00338          //Surface is semi-transparent during dynamic profiling
00339          glEnable(GL_BLEND);
00340          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00341       }
00342 
00343    }
00344 
00345    if (Textured() && !fSelectionPass) {
00346       if (!PreparePalette()) {
00347          fType = kSurf;
00348          fDrawPalette = kFALSE;
00349       }
00350       else if (fType != kSurf3)
00351          fPalette.EnableTexture(GL_MODULATE);
00352    }
00353 
00354    const Int_t nX = fCoord->GetNXBins();
00355    const Int_t nY = fCoord->GetNYBins();
00356    const Int_t frontPoint = fBackBox.GetFrontPoint();
00357    Int_t i = 0, firstJ = 0;
00358    const Int_t addI = frontPoint == 2 || frontPoint == 1 ? i = 0, 1 : (i = nX - 2, -1);
00359    const Int_t addJ = frontPoint == 2 || frontPoint == 3 ? firstJ = 0, 1 : (firstJ = nY - 2, -1);
00360 
00361    if (fHighColor && fSelectionPass)
00362       Rgl::ObjectIDToColor(fSelectionBase, kTRUE);
00363 
00364    for (; addI > 0 ? i < nX - 1 : i >= 0; i += addI) {
00365       for (Int_t j = firstJ; addJ > 0 ? j < nY - 1 : j >= 0; j += addJ) {
00366          Int_t triNumber = 2 * i * (nY - 1) + j * 2 + fSelectionBase;
00367 
00368          Double_t xMin = TMath::Min(TMath::Min(fMesh[i][j + 1].X(), fMesh[i][j].X()), fMesh[i + 1][j].X());
00369          Double_t xMax = TMath::Max(TMath::Max(fMesh[i][j + 1].X(), fMesh[i][j].X()), fMesh[i + 1][j].X());
00370          Double_t yMin = TMath::Min(TMath::Min(fMesh[i][j + 1].Y(), fMesh[i][j].Y()), fMesh[i + 1][j].Y());
00371          Double_t yMax = TMath::Max(TMath::Max(fMesh[i][j + 1].Y(), fMesh[i][j].Y()), fMesh[i + 1][j].Y());
00372          Double_t zMin = TMath::Min(TMath::Min(fMesh[i][j + 1].Z(), fMesh[i][j].Z()), fMesh[i + 1][j].Z());
00373          Double_t zMax = TMath::Max(TMath::Max(fMesh[i][j + 1].Z(), fMesh[i][j].Z()), fMesh[i + 1][j].Z());
00374 
00375          if (fBoxCut.IsActive() && fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
00376             continue;
00377 
00378          if (fSelectionPass && !fHighColor)
00379             Rgl::ObjectIDToColor(triNumber, kFALSE);
00380 
00381          if ((fType == kSurf1 || fType == kSurf2 || fType == kSurf5) && !fSelectionPass)
00382             Rgl::DrawFaceTextured(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
00383                                  fTexMap[i][j + 1], fTexMap[i][j], fTexMap[i + 1][j],
00384                                  fAverageNormals[i][j + 1], fAverageNormals[i][j],
00385                                  fAverageNormals[i + 1][j]);
00386          else
00387             Rgl::DrawSmoothFace(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
00388                               fAverageNormals[i][j + 1], fAverageNormals[i][j],
00389                               fAverageNormals[i + 1][j]);
00390 
00391          ++triNumber;
00392 
00393          if (fSelectionPass && !fHighColor)
00394             Rgl::ObjectIDToColor(triNumber, kFALSE);
00395 
00396          if ((fType == kSurf1 || fType == kSurf2 || fType == kSurf5) && !fSelectionPass)
00397             Rgl::DrawFaceTextured(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
00398                                  fTexMap[i + 1][j], fTexMap[i + 1][j + 1], fTexMap[i][j + 1],
00399                                  fAverageNormals[i + 1][j], fAverageNormals[i + 1][j + 1],
00400                                  fAverageNormals[i][j + 1]);
00401          else
00402             Rgl::DrawSmoothFace(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
00403                               fAverageNormals[i + 1][j], fAverageNormals[i + 1][j + 1],
00404                               fAverageNormals[i][j + 1]);
00405       }
00406    }
00407 
00408    if (!fSelectionPass)
00409       glDisable(GL_POLYGON_OFFSET_FILL);
00410 
00411    if (fBoxCut.IsActive())
00412       fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
00413 
00414    if (fType != kSurf3 && Textured() && !fSelectionPass)
00415       fPalette.DisableTexture();
00416 
00417    //Draw outlines here
00418    if (!fSelectionPass) {
00419       const TGLEnableGuard  blendGuard(GL_BLEND);
00420 
00421       if (fType == kSurf || fType == kSurf1 || fType == kSurf3) {
00422          const TGLDisableGuard lightGuard(GL_LIGHTING);
00423          const TGLEnableGuard  smoothGuard(GL_LINE_SMOOTH);
00424 
00425          glDepthMask(GL_FALSE);
00426 
00427          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00428          glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00429 
00430          glColor4d(0., 0., 0., 0.5);
00431 
00432          for (i = 0; i < nX - 1; ++i) {
00433             for (Int_t j = 0; j < nY - 1; ++j) {
00434                Rgl::DrawQuadOutline(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j], fMesh[i + 1][j + 1]);
00435             }
00436          }
00437 
00438          glDepthMask(GL_TRUE);
00439       }
00440    }
00441 
00442    if (fType == kSurf3 && !fSelectionPass) {
00443       fPalette.EnableTexture(GL_MODULATE);
00444       const TGLEnableGuard blend(GL_BLEND);
00445       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00446       DrawContoursProjection();
00447       fPalette.DisableTexture();
00448    }
00449 
00450    if (!fSelectionPass && fSelectedPart > 6) {
00451       //Draw red outline for surface.
00452       const TGLDisableGuard lightGuard(GL_LIGHTING);
00453       const TGLEnableGuard blendGuard(GL_BLEND);
00454       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00455       const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);
00456       glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00457       glLineWidth(3.f);
00458 
00459       glColor4d(1.f, 0.f, 0.4f, 0.6f);
00460       glBegin(GL_LINE_STRIP);
00461       for (i = 0; i < nX; ++i)
00462          glVertex3dv(fMesh[i][0].CArr());
00463       for (Int_t j = 0; j < nY; ++j)
00464          glVertex3dv(fMesh[nX - 1][j].CArr());
00465       for (i = nX - 1; i >= 0; --i)
00466          glVertex3dv(fMesh[i][nY - 1].CArr());
00467       for (Int_t j = nY - 1; j >= 0; --j)
00468          glVertex3dv(fMesh[0][j].CArr());
00469       glEnd();
00470       glLineWidth(1.f);
00471    }
00472 
00473    if (!fSelectionPass && fDrawPalette)
00474       DrawPalette();
00475 }
00476 
00477 //______________________________________________________________________________
00478 Bool_t TGLSurfacePainter::InitGeometryCartesian()
00479 {
00480    //Find bin ranges for X and Y axes,
00481    //axes ranges for X, Y and Z.
00482    //Function returns false, if logarithmic scale for
00483    //some axis was requested, but we cannot
00484    //find correct range.
00485 
00486    if (!fCoord->SetRanges(fHist, kFALSE, kFALSE)) //the second arg must be drawErrors, the third is always kFALSE.
00487       return kFALSE;
00488 
00489    fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
00490    //Set surface's mesh
00491    //Calculates table of X and Y for lego (Z is obtained during drawing) or
00492    //calculate mesh of triangles with vertices in the centres of bins
00493    const Int_t nX = fCoord->GetNXBins();
00494    const Int_t nY = fCoord->GetNYBins();
00495 
00496    fMesh.resize(nX * nY);
00497    fMesh.SetRowLen(nY);
00498 
00499    for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
00500       for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
00501          fCoord->GetXLog() ? fMesh[i][j].X() = TMath::Log10(fXAxis->GetBinCenter(ir)) * fCoord->GetXScale()
00502                            : fMesh[i][j].X() = fXAxis->GetBinCenter(ir) * fCoord->GetXScale();
00503          fCoord->GetYLog() ? fMesh[i][j].Y() = TMath::Log10(fYAxis->GetBinCenter(jr)) * fCoord->GetYScale()
00504                            : fMesh[i][j].Y() = fYAxis->GetBinCenter(jr) * fCoord->GetYScale();
00505 
00506          Double_t z = fHist->GetCellContent(ir, jr);
00507          ClampZ(z);
00508          fMesh[i][j].Z() = z;
00509       }
00510    }
00511 
00512    if (Textured()) {
00513       fMinMaxVal.first  = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
00514       fMinMaxVal.second = fMinMaxVal.first;
00515 
00516       for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
00517          for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
00518             const Double_t val = fHist->GetBinContent(i, j);
00519             fMinMaxVal.first  = TMath::Min(fMinMaxVal.first, val);
00520             fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
00521          }
00522       }
00523 
00524       ClampZ(fMinMaxVal.first);
00525       ClampZ(fMinMaxVal.second);
00526 
00527       fUpdateTexMap = kTRUE;
00528    }
00529 
00530    SetNormals();
00531 
00532    if (fCoord->Modified()) {
00533       fUpdateSelection = kTRUE;
00534       const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
00535       fXOZSectionPos = vertex.Y();
00536       fYOZSectionPos = vertex.X();
00537       fXOYSectionPos = vertex.Z();
00538       fCoord->ResetModified();
00539       Rgl::SetZLevels(fZAxis, fCoord->GetZRange().first, fCoord->GetZRange().second, fCoord->GetZScale(), fZLevels);
00540    }
00541 
00542    return kTRUE;
00543 }
00544 
00545 //______________________________________________________________________________
00546 Bool_t TGLSurfacePainter::InitGeometryPolar()
00547 {
00548    //Find bin ranges for X and Y axes,
00549    //axes ranges for X, Y and Z.
00550    //Function returns false, if logarithmic scale for
00551    //some axis was requested, but we cannot
00552    //find correct range.
00553 
00554    if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
00555       return kFALSE;
00556 
00557    fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
00558 
00559    if (fCoord->Modified()) {
00560       fUpdateSelection = kTRUE;
00561       const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
00562       fXOZSectionPos = vertex.Y();
00563       fYOZSectionPos = vertex.X();
00564       fXOYSectionPos = vertex.Z();
00565       fCoord->ResetModified();
00566    }
00567 
00568    const Int_t nY = fCoord->GetNYBins();
00569    const Int_t nX = fCoord->GetNXBins();
00570 
00571    fMesh.resize(nX * nY);
00572    fMesh.SetRowLen(nY);
00573 
00574    const Double_t fullAngle = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
00575    const Double_t phiLow    = fXAxis->GetBinCenter(1);
00576    const Double_t rRange    = fYAxis->GetBinCenter(fYAxis->GetNbins()) - fYAxis->GetBinCenter(1);
00577 
00578    for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
00579       for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
00580          const Double_t angle  = (fXAxis->GetBinCenter(ir) - phiLow) / fullAngle * TMath::TwoPi();
00581          const Double_t radius = ((fYAxis->GetBinCenter(jr)) - fYAxis->GetBinCenter(1)) /
00582                                  rRange * fCoord->GetYScale();
00583          fMesh[i][j].X() = radius * TMath::Cos(angle);
00584          fMesh[i][j].Y() = radius * TMath::Sin(angle);
00585          Double_t z = fHist->GetBinContent(ir, jr);
00586          ClampZ(z);
00587          fMesh[i][j].Z() = z;
00588       }
00589    }
00590 
00591    SetNormals();
00592 
00593    if (Textured()) {
00594       fMinMaxVal.first  = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
00595       fMinMaxVal.second = fMinMaxVal.first;
00596 
00597       for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
00598          for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
00599             const Double_t val = fHist->GetBinContent(i, j);
00600             fMinMaxVal.first  = TMath::Min(fMinMaxVal.first, val);
00601             fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
00602          }
00603       }
00604 
00605       fUpdateTexMap = kTRUE;
00606    }
00607 
00608 
00609    return kTRUE;
00610 }
00611 
00612 //______________________________________________________________________________
00613 Bool_t TGLSurfacePainter::InitGeometryCylindrical()
00614 {
00615    //Find bin ranges for X and Y axes,
00616    //axes ranges for X, Y and Z.
00617    //Function returns false, if logarithmic scale for
00618    //some axis was requested, but we cannot
00619    //find correct range.
00620 
00621    if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
00622       return kFALSE;
00623 
00624    fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
00625 
00626    if (fCoord->Modified()) {
00627       fUpdateSelection = kTRUE;
00628       const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
00629       fXOZSectionPos = vertex.Y();
00630       fYOZSectionPos = vertex.X();
00631       fXOYSectionPos = vertex.Z();
00632       fCoord->ResetModified();
00633    }
00634 
00635    const Int_t nY = fCoord->GetNYBins();
00636    const Int_t nX = fCoord->GetNXBins();
00637    fMesh.resize(nX * nY);
00638    fMesh.SetRowLen(nY);
00639 
00640    Double_t legoR = gStyle->GetLegoInnerR();
00641    if (legoR > 1. || legoR < 0.)
00642       legoR = 0.5;
00643    const Double_t rRange = fCoord->GetZLength();
00644    const Double_t sc = (1 - legoR) * fCoord->GetXScale();
00645    legoR *= fCoord->GetXScale();
00646 
00647    const Double_t fullAngle = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
00648    const Double_t phiLow    = fXAxis->GetBinCenter(1);
00649    Double_t angle = 0.;
00650 
00651    for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
00652       for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
00653          angle = (fXAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
00654          Double_t r = fType != kSurf5 ? legoR + (fHist->GetCellContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc : legoR;
00655          fMesh[i][j].X() = r * TMath::Cos(angle);
00656          fMesh[i][j].Y() = fCoord->GetYLog() ?
00657                               TMath::Log10(fYAxis->GetBinCenter(jr)) * fCoord->GetYScale()
00658                                           :
00659                               fYAxis->GetBinCenter(jr) * fCoord->GetYScale();
00660          fMesh[i][j].Z() = r * TMath::Sin(angle);
00661       }
00662    }
00663 
00664    if (Textured()) {
00665       fMinMaxVal.first  = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
00666       fMinMaxVal.second = fMinMaxVal.first;
00667 
00668       for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
00669          for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
00670             const Double_t val = fHist->GetBinContent(i, j);
00671             fMinMaxVal.first  = TMath::Min(fMinMaxVal.first, val);
00672             fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
00673          }
00674       }
00675 
00676       fUpdateTexMap = kTRUE;
00677    }
00678 
00679 
00680    SetNormals();
00681 
00682    return kTRUE;
00683 }
00684 
00685 //______________________________________________________________________________
00686 Bool_t TGLSurfacePainter::InitGeometrySpherical()
00687 {
00688    //Find bin ranges for X and Y axes,
00689    //axes ranges for X, Y and Z.
00690    //Function returns false, if logarithmic scale for
00691    //some axis was requested, but we cannot
00692    //find correct range.
00693 
00694    if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
00695       return kFALSE;
00696 
00697    fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
00698 
00699    if (fCoord->Modified()) {
00700       fUpdateSelection = kTRUE;
00701       const TGLVertex3 &vertex = fBackBox.Get3DBox()[0];
00702       fXOZSectionPos = vertex.Y();
00703       fYOZSectionPos = vertex.X();
00704       fXOYSectionPos = vertex.Z();
00705       fCoord->ResetModified();
00706    }
00707 
00708    const Int_t nY = fCoord->GetNYBins();
00709    const Int_t nX = fCoord->GetNXBins();
00710    fMesh.resize(nX * nY);
00711    fMesh.SetRowLen(nY);
00712 
00713    Double_t legoR = gStyle->GetLegoInnerR();
00714    if (legoR > 1. || legoR < 0.)
00715       legoR = 0.5;
00716    const Double_t rRange = fCoord->GetZLength();
00717    const Double_t sc = (1 - legoR) * fCoord->GetXScale();
00718    legoR *= fCoord->GetXScale();
00719 
00720    //0 <= theta <= 2 * pi
00721    const Double_t fullTheta   = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
00722    const Double_t thetaLow    = fXAxis->GetBinCenter(1);
00723    //0 <= phi <= pi
00724    const Double_t fullPhi = fYAxis->GetBinCenter(fYAxis->GetNbins()) - fYAxis->GetBinCenter(1);
00725    const Double_t phiLow  = fYAxis->GetBinCenter(1);
00726 
00727    for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
00728 
00729       const Double_t theta = (fXAxis->GetBinCenter(ir) - thetaLow) / fullTheta * TMath::TwoPi();
00730 
00731       for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
00732 
00733          const Double_t phi = (fYAxis->GetBinCenter(jr) - phiLow) / fullPhi * TMath::Pi();
00734          const Double_t r   = fType != kSurf5 ? legoR + (fHist->GetCellContent(ir, jr) - fCoord->GetZRange().first) / rRange * sc
00735                                              : legoR;
00736 
00737          fMesh[i][j].X() = r * TMath::Sin(phi) * TMath::Cos(theta);
00738          fMesh[i][j].Y() = r * TMath::Sin(phi) * TMath::Sin(theta);
00739          fMesh[i][j].Z() = r * TMath::Cos(phi);
00740       }
00741    }
00742 
00743    if (Textured()) {
00744       fMinMaxVal.first  = fHist->GetBinContent(fCoord->GetFirstXBin(), fCoord->GetFirstYBin());
00745       fMinMaxVal.second = fMinMaxVal.first;
00746 
00747       for (Int_t i = fCoord->GetFirstXBin(), e = fCoord->GetLastXBin(); i <= e; ++i) {
00748          for (Int_t j = fCoord->GetFirstYBin(), e1 = fCoord->GetLastYBin(); j <= e1; ++j) {
00749             const Double_t val = fHist->GetBinContent(i, j);
00750             fMinMaxVal.first  = TMath::Min(fMinMaxVal.first, val);
00751             fMinMaxVal.second = TMath::Max(fMinMaxVal.second, val);
00752          }
00753       }
00754 
00755       fUpdateTexMap = kTRUE;
00756    }
00757 
00758 
00759    SetNormals();
00760 
00761    return kTRUE;
00762 }
00763 
00764 //______________________________________________________________________________
00765 void TGLSurfacePainter::DrawProjections()const
00766 {
00767    // Draw projections.
00768 
00769    const TGLDisableGuard lightGuard(GL_LIGHTING);
00770    const TGLEnableGuard  blendGuard(GL_BLEND);
00771    const TGLEnableGuard  lineSmooth(GL_LINE_SMOOTH);
00772    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00773    glDepthMask(GL_FALSE);
00774    glLineWidth(3.f);
00775 
00776    typedef std::list<Projection_t>::const_iterator CLI_t;
00777    for (CLI_t begin = fXOZProj.begin(), end = fXOZProj.end(); begin != end; ++begin) {
00778       const Projection_t &proj = *begin;
00779       glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
00780 
00781       for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
00782          glBegin(GL_LINE_STRIP);
00783          glVertex3dv(proj.fVertices[i * 3].CArr());
00784          glVertex3dv(proj.fVertices[i * 3 + 1].CArr());
00785          glVertex3dv(proj.fVertices[i * 3 + 2].CArr());
00786          glEnd();
00787       }
00788       const Double_t y = fBackBox.GetFrontPoint() == 2 || fBackBox.GetFrontPoint() == 3 ? fBackBox.Get3DBox()[0].Y() : fBackBox.Get3DBox()[2].Y();
00789       for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
00790          glBegin(GL_LINE_STRIP);
00791          const TGLVertex3 &v1 = proj.fVertices[i * 3];
00792          glVertex3d(v1.X(), y, v1.Z());
00793          const TGLVertex3 &v2 = proj.fVertices[i * 3 + 1];
00794          glVertex3d(v2.X(), y, v2.Z());
00795          const TGLVertex3 &v3 = proj.fVertices[i * 3 + 2];
00796          glVertex3d(v3.X(), y, v3.Z());
00797          glEnd();
00798       }
00799    }
00800 
00801    for (CLI_t begin = fYOZProj.begin(), end = fYOZProj.end(); begin != end; ++begin) {
00802       const Projection_t &proj = *begin;
00803       glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
00804 
00805       for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
00806          glBegin(GL_LINE_STRIP);
00807          glVertex3dv(proj.fVertices[i * 3].CArr());
00808          glVertex3dv(proj.fVertices[i * 3 + 1].CArr());
00809          glVertex3dv(proj.fVertices[i * 3 + 2].CArr());
00810          glEnd();
00811       }
00812 
00813       const Double_t x = fBackBox.GetFrontPoint() == 2 || fBackBox.GetFrontPoint() == 1 ? fBackBox.Get3DBox()[0].X() : fBackBox.Get3DBox()[2].X();
00814       for(UInt_t i = 0, e = proj.fVertices.size() / 3; i < e; ++i) {
00815          glBegin(GL_LINE_STRIP);
00816          const TGLVertex3 &v1 = proj.fVertices[i * 3];
00817          glVertex3d(x, v1.Y(), v1.Z());
00818          const TGLVertex3 &v2 = proj.fVertices[i * 3 + 1];
00819          glVertex3d(x, v2.Y(), v2.Z());
00820          const TGLVertex3 &v3 = proj.fVertices[i * 3 + 2];
00821          glVertex3d(x, v3.Y(), v3.Z());
00822          glEnd();
00823       }
00824    }
00825 
00826    for (CLI_t begin = fXOYProj.begin(), end = fXOYProj.end(); begin != end; ++begin) {
00827       const Projection_t &proj = *begin;
00828       glColor4ub(proj.fRGBA[0], proj.fRGBA[1], proj.fRGBA[2], proj.fRGBA[3]);
00829 
00830       for(UInt_t i = 0, e = proj.fVertices.size() / 2; i < e; ++i) {
00831          glBegin(GL_LINES);
00832          glVertex3dv(proj.fVertices[i * 2].CArr());
00833          glVertex3dv(proj.fVertices[i * 2 + 1].CArr());
00834          glEnd();
00835       }
00836 
00837 
00838       for(UInt_t i = 0, e = proj.fVertices.size() / 2; i < e; ++i) {
00839          glBegin(GL_LINES);
00840          const TGLVertex3 &v1 = proj.fVertices[i * 2];
00841          glVertex3d(v1.X(), v1.Y(), fBackBox.Get3DBox()[0].Z());
00842          const TGLVertex3 &v2 = proj.fVertices[i * 2 + 1];
00843          glVertex3d(v2.X(), v2.Y(), fBackBox.Get3DBox()[0].Z());
00844          glEnd();
00845       }
00846 
00847    }
00848 
00849    glDepthMask(GL_TRUE);
00850    glLineWidth(1.f);
00851 }
00852 
00853 //______________________________________________________________________________
00854 void TGLSurfacePainter::DrawSectionXOZ()const
00855 {
00856    // Draw section X.
00857 
00858    using namespace std;
00859    //XOZ parallel section.
00860    Int_t binY = -1;
00861    for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
00862       if (fMesh[0][j].Y() <= fXOZSectionPos && fXOZSectionPos <= fMesh[0][j + 1].Y()) {
00863          binY = j;
00864          break;
00865       }
00866    }
00867 
00868    if (binY >= 0) {
00869       //Draw 2d curve on the profile's plane.
00870       const TGLPlane profilePlane(0., 1., 0., -fXOZSectionPos);
00871 
00872       if (!fSectionPass) {
00873          glColor3d(1., 0., 0.);
00874          glLineWidth(3.f);
00875 
00876          for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
00877             glBegin(GL_LINE_STRIP);
00878             glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i + 1][binY + 1]), kFALSE).second.CArr());
00879             glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i][binY + 1]), kFALSE).second.CArr());
00880             glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[i][binY], fMesh[i][binY + 1]), kFALSE).second.CArr());
00881             glEnd();
00882          }
00883          glLineWidth(1.f);
00884       } else {
00885          fProj.fVertices.clear();
00886          for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
00887             fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i + 1][binY + 1]), kFALSE).second);
00888             fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i + 1][binY], fMesh[i][binY + 1]), kFALSE).second);
00889             fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[i][binY], fMesh[i][binY + 1]), kFALSE).second);
00890          }
00891          if (fProj.fVertices.size()) {
00892             fProj.fRGBA[0] = (UChar_t) (50 + fgRandom->Integer(206));
00893             fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
00894             fProj.fRGBA[2] = (UChar_t) fgRandom->Integer(150);
00895             fProj.fRGBA[3] = 150;
00896             static Projection_t dummy;
00897             fXOZProj.push_back(dummy);
00898             fXOZProj.back().Swap(fProj);
00899          }
00900       }
00901    }
00902 }
00903 
00904 //______________________________________________________________________________
00905 void TGLSurfacePainter::DrawSectionYOZ()const
00906 {
00907    // Draw section Y.
00908 
00909    using namespace std;
00910    //YOZ parallel section.
00911    Int_t binX = -1;
00912    for (Int_t i = 0, e = fCoord->GetNXBins() - 1; i < e; ++i) {
00913       if (fMesh[i][0].X() <= fYOZSectionPos && fYOZSectionPos <= fMesh[i + 1][0].X()) {
00914          binX = i;
00915          break;
00916       }
00917    }
00918 
00919    if (binX >= 0) {
00920       //Draw 2d curve on the profile's plane.
00921       const TGLPlane profilePlane(1., 0., 0., -fYOZSectionPos);
00922 
00923       if (!fSectionPass) {
00924          glColor3d(1., 0., 0.);
00925          glLineWidth(3.f);
00926          for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
00927             glBegin(GL_LINE_STRIP);
00928             glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j + 1]), kFALSE).second.CArr());
00929             glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j]), kFALSE).second.CArr());
00930             glVertex3dv(Intersection(profilePlane, TGLLine3(fMesh[binX][j], fMesh[binX + 1][j]), kFALSE).second.CArr());
00931             glEnd();
00932          }
00933          glLineWidth(1.f);
00934       } else {
00935          fProj.fVertices.clear();
00936          for (Int_t j = 0, e = fCoord->GetNYBins() - 1; j < e; ++j) {
00937             fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j + 1]), kFALSE).second);
00938             fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j + 1], fMesh[binX + 1][j]), kFALSE).second);
00939             fProj.fVertices.push_back(Intersection(profilePlane, TGLLine3(fMesh[binX][j], fMesh[binX + 1][j]), kFALSE).second);
00940          }
00941          if (fProj.fVertices.size()) {
00942             fProj.fRGBA[0] = (UChar_t) (50 + fgRandom->Integer(206));
00943             fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
00944             fProj.fRGBA[2] = (UChar_t) fgRandom->Integer(150);
00945             fProj.fRGBA[3] = 150;
00946             static Projection_t dummy;
00947             fYOZProj.push_back(dummy);
00948             fYOZProj.back().Swap(fProj);
00949          }
00950       }
00951 
00952    }
00953 }
00954 
00955 //______________________________________________________________________________
00956 void TGLSurfacePainter::DrawSectionXOY()const
00957 {
00958    // Draw section Z.
00959 
00960    using namespace std;
00961    //XOY parallel section.
00962    const Int_t nX = fCoord->GetNXBins();
00963    const Int_t nY = fCoord->GetNYBins();
00964    const TGLPlane profilePlane(0., 0., 1., -fXOYSectionPos);
00965    TGLVertex3 intersection[2];
00966 
00967 
00968    if (fSectionPass)
00969       fProj.fVertices.clear();
00970    else {
00971       glColor3d(1., 0., 0.);
00972       glLineWidth(3.f);
00973    }
00974 
00975    for (Int_t i = 0; i < nX - 1; ++i) {
00976       for (Int_t j = 0; j < nY - 1; ++j) {
00977          const TGLVertex3 &v1 = fMesh[i + 1][j], &v2 = fMesh[i][j], &v3 = fMesh[i][j + 1], &v4 = fMesh[i + 1][j + 1];
00978          Double_t zMin = TMath::Min(TMath::Min(v1.Z(), v2.Z()), v3.Z());
00979          Double_t zMax = TMath::Max(TMath::Max(v1.Z(), v2.Z()), v3.Z());
00980 
00981          if (zMin < fXOYSectionPos && zMax > fXOYSectionPos) {
00982             Int_t np = 0;
00983             if ((v1.Z() > fXOYSectionPos && v2.Z() < fXOYSectionPos) || (v2.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos)) {
00984                TGLLine3 line(v1, v2);
00985                intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
00986             }
00987             if ((v2.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos) || (v3.Z() > fXOYSectionPos && v2.Z() < fXOYSectionPos)) {
00988                TGLLine3 line(v2, v3);
00989                intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
00990             }
00991             if ((np < 2 && v1.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos) || (v3.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos)) {
00992                TGLLine3 line(v1, v3);
00993                intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
00994             }
00995             if (np > 1) {
00996                if (!fSectionPass) {
00997                   glBegin(GL_LINES);
00998                   glVertex3dv(intersection[0].CArr());
00999                   glVertex3dv(intersection[1].CArr());
01000                   glEnd();
01001                } else {
01002                   fProj.fVertices.push_back(intersection[0]);
01003                   fProj.fVertices.push_back(intersection[1]);
01004                }
01005             }
01006          }
01007          zMin = TMath::Min(v4.Z(), zMin);
01008          zMax = TMath::Max(v4.Z(), zMax);
01009          if (zMin < fXOYSectionPos && zMax > fXOYSectionPos) {
01010             Int_t np = 0;
01011             if ((v3.Z() > fXOYSectionPos && v4.Z() < fXOYSectionPos) || (v4.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos)) {
01012                TGLLine3 line(v3, v4);
01013                intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
01014             }
01015             if ((v4.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos) || (v1.Z() > fXOYSectionPos && v4.Z() < fXOYSectionPos)) {
01016                TGLLine3 line(v4, v1);
01017                intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
01018             }
01019             if ((np < 2 && v3.Z() > fXOYSectionPos && v1.Z() < fXOYSectionPos) || (v1.Z() > fXOYSectionPos && v3.Z() < fXOYSectionPos)) {
01020                TGLLine3 line(v3, v1);
01021                intersection[np++] = Intersection(profilePlane, line, kFALSE).second;
01022             }
01023             if (np > 1) {
01024                if (!fSectionPass) {
01025                   glBegin(GL_LINES);
01026                   glVertex3dv(intersection[0].CArr());
01027                   glVertex3dv(intersection[1].CArr());
01028                   glEnd();
01029                } else {
01030                   fProj.fVertices.push_back(intersection[0]);
01031                   fProj.fVertices.push_back(intersection[1]);
01032                }
01033             }
01034          }
01035       }
01036    }
01037 
01038    if (fSectionPass && fProj.fVertices.size()) {
01039       fProj.fRGBA[0] = (UChar_t) fgRandom->Integer(150);
01040       fProj.fRGBA[1] = (UChar_t) fgRandom->Integer(150);
01041       fProj.fRGBA[2] = (UChar_t) (50 + fgRandom->Integer(206));
01042       fProj.fRGBA[3] = 150;
01043       static Projection_t dummy;
01044       fXOYProj.push_back(dummy);
01045       fXOYProj.back().Swap(fProj);
01046    }
01047 
01048    if (!fSectionPass)
01049       glLineWidth(1.f);
01050 }
01051 
01052 //______________________________________________________________________________
01053 void TGLSurfacePainter::ClampZ(Double_t &zVal)const
01054 {
01055    //Clamp z value.
01056    const TGLVertex3 *frame = fBackBox.Get3DBox();
01057 
01058    if (fCoord->GetZLog())
01059       if (zVal <= 0.)
01060          zVal = frame[0].Z();
01061       else
01062          zVal = TMath::Log10(zVal) * fCoord->GetZScale();
01063    else
01064       zVal *= fCoord->GetZScale();
01065 
01066    if (zVal > frame[4].Z())
01067       zVal = frame[4].Z();
01068    else if (zVal < frame[0].Z())
01069       zVal = frame[0].Z();
01070 }
01071 
01072 //______________________________________________________________________________
01073 char *TGLSurfacePainter::WindowPointTo3DPoint(Int_t px, Int_t py)const
01074 {
01075    //Find 3d coords using mouse cursor coords.
01076 /*   if (!MakeGLContextCurrent()) {
01077       static char err[] = { "Apocalipshit!" };
01078       return err;
01079    }*/
01080 
01081    py = fCamera->GetHeight() - py;
01082 
01083    const Int_t nY = fCoord->GetNYBins() - 1;
01084    Int_t selected = fSelectedPart - (fSelectionBase - 1);
01085    Int_t k = selected / 2;
01086    Int_t i = k / nY;
01087    Int_t j = k % nY;
01088 
01089    const Bool_t odd = selected & 1;
01090    const TGLVertex3 &v1 = odd ? fMesh[i][j + 1] : fMesh[i + 1][j];
01091    const TGLVertex3 &v2 = odd ? fMesh[i + 1][j + 1] : fMesh[i][j];
01092    const TGLVertex3 &v3 = odd ? fMesh[i + 1][j] : fMesh[i][j + 1];
01093 
01094    TGLVertex3 winV1, winV2, winV3;
01095 
01096    Double_t mvMatrix[16] = {0.};
01097    glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix);
01098    Double_t prMatrix[16] = {0.};
01099    glGetDoublev(GL_PROJECTION_MATRIX, prMatrix);
01100    Int_t viewport[4] = {0};
01101    glGetIntegerv(GL_VIEWPORT, viewport);
01102 
01103    gluProject(v1.X(), v1.Y(), v1.Z(), mvMatrix, prMatrix, viewport, &winV1.X(), &winV1.Y(), &winV1.Z());
01104    gluProject(v2.X(), v2.Y(), v2.Z(), mvMatrix, prMatrix, viewport, &winV2.X(), &winV2.Y(), &winV2.Z());
01105    gluProject(v3.X(), v3.Y(), v3.Z(), mvMatrix, prMatrix, viewport, &winV3.X(), &winV3.Y(), &winV3.Z());
01106 
01107    Double_t planeABCD[4] = {0.};
01108    TMath::Normal2Plane(winV1.CArr(), winV2.CArr(), winV3.CArr(), planeABCD);
01109    planeABCD[3] = - winV1.X() * planeABCD[0] - winV1.Y() * planeABCD[1] - winV1.Z() * planeABCD[2];
01110    Double_t pz = (-planeABCD[3] - planeABCD[0] * px - planeABCD[1] * py) / planeABCD[2];
01111    Double_t rez[3] = {0.};
01112 
01113    gluUnProject(px, py, pz, mvMatrix, prMatrix, viewport, rez, rez + 1, rez + 2);
01114 
01115    fObjectInfo.Form("(x == %f, y == %f, z == %f)",
01116                     rez[0] / fCoord->GetXScale(),
01117                     rez[1] / fCoord->GetYScale(),
01118                     rez[2] / fCoord->GetZScale());
01119 
01120    return (char *)fObjectInfo.Data();
01121 }
01122 
01123 //______________________________________________________________________________
01124 Bool_t TGLSurfacePainter::PreparePalette()const
01125 {
01126    //Generate palette.
01127    if (!fUpdateTexMap)
01128       return kTRUE;
01129 
01130    if(fMinMaxVal.first == fMinMaxVal.second)
01131       return kFALSE;//must be std::abs(fMinMaxVal.second - fMinMaxVal.first) < ...
01132 
01133    //User-defined contours are disabled. To be fixed.
01134    if (fHist->TestBit(TH1::kUserContour))
01135       fHist->ResetBit(TH1::kUserContour);
01136 
01137    UInt_t paletteSize = gStyle->GetNumberContours();
01138    if (!paletteSize)
01139       paletteSize = 20;
01140 
01141    Bool_t rez = fPalette.GeneratePalette(paletteSize, fMinMaxVal);
01142 
01143    if (rez && fUpdateTexMap) {
01144       GenTexMap();
01145       fUpdateTexMap = kFALSE;
01146    }
01147 
01148    return rez;
01149 }
01150 
01151 //______________________________________________________________________________
01152 void TGLSurfacePainter::GenTexMap()const
01153 {
01154    //Find texture coordinates.
01155    const Int_t nX = fCoord->GetNXBins();
01156    const Int_t nY = fCoord->GetNYBins();
01157 
01158    fTexMap.resize(nX * nY);
01159    fTexMap.SetRowLen(nY);
01160 
01161    for (Int_t i = 0, ir = fCoord->GetFirstXBin(); i < nX; ++i, ++ir) {
01162       for (Int_t j = 0, jr = fCoord->GetFirstYBin(); j < nY; ++j, ++jr) {
01163          Double_t z = fHist->GetCellContent(ir, jr);
01164          if (fCoord->GetCoordType() == kGLCartesian)
01165             ClampZ(z);
01166          fTexMap[i][j] = fPalette.GetTexCoord(z);
01167       }
01168    }
01169 }
01170 
01171 //______________________________________________________________________________
01172 void TGLSurfacePainter::DrawContoursProjection()const
01173 {
01174    //Draw flat textured surface.
01175    static const Float_t whiteDiffuse[] = {0.8f, 0.8f, 0.8f, 0.65f};
01176    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, whiteDiffuse);
01177    for (Int_t i = 0, ei = fCoord->GetNXBins() - 1; i < ei; ++i) {
01178       for (Int_t j = 0, ej = fCoord->GetNYBins() - 1; j < ej; ++j) {
01179          Rgl::DrawFaceTextured(fMesh[i][j + 1], fMesh[i][j], fMesh[i + 1][j],
01180                                fTexMap[i][j + 1], fTexMap[i][j], fTexMap[i + 1][j],
01181                                fBackBox.Get3DBox()[4].Z(), TGLVector3(0., 0., 1.));
01182          Rgl::DrawFaceTextured(fMesh[i + 1][j], fMesh[i + 1][j + 1], fMesh[i][j + 1],
01183                                fTexMap[i + 1][j], fTexMap[i + 1][j + 1], fTexMap[i][j + 1],
01184                                fBackBox.Get3DBox()[4].Z(), TGLVector3(0., 0., 1.));
01185       }
01186    }
01187 }
01188 
01189 //______________________________________________________________________________
01190 Bool_t TGLSurfacePainter::Textured()const
01191 {
01192    //Checks, if surf requires texture.
01193    switch (fType) {
01194    case kSurf1:
01195    case kSurf2:
01196    case kSurf3:
01197    case kSurf5:
01198       return kTRUE;
01199    default:;
01200    }
01201 
01202    return kFALSE;
01203 }
01204 
01205 //______________________________________________________________________________
01206 Bool_t TGLSurfacePainter::HasSections()const
01207 {
01208    //Any section exists.
01209    return fXOZSectionPos > fBackBox.Get3DBox()[0].Y() || fYOZSectionPos > fBackBox.Get3DBox()[0].X() ||
01210           fXOYSectionPos > fBackBox.Get3DBox()[0].Z();
01211 }
01212 
01213 //______________________________________________________________________________
01214 Bool_t TGLSurfacePainter::HasProjections()const
01215 {
01216    //Any projection exists.
01217    return fXOZProj.size() || fYOZProj.size() || fXOYProj.size();
01218 }
01219 
01220 //______________________________________________________________________________
01221 void TGLSurfacePainter::DrawPalette()const
01222 {
01223    //Draw. Palette.
01224    //Originally, fCamera was never null.
01225    //It can be a null now because of gl-viewer.
01226    if (!fCamera) {
01227       //Thank you, gl-viewer!
01228       return;
01229    }
01230 
01231    Rgl::DrawPalette(fCamera, fPalette);
01232 
01233    glFinish();
01234 
01235    fCamera->SetCamera();
01236    fCamera->Apply(fPadPhi, fPadTheta);
01237 }
01238 
01239 //______________________________________________________________________________
01240 void TGLSurfacePainter::DrawPaletteAxis()const
01241 {
01242    //Draw. Palette. Axis.
01243    gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
01244    Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);
01245 }

Generated on Tue Jul 5 14:18:09 2011 for ROOT_528-00b_version by  doxygen 1.5.1