00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
00061 }
00062
00063
00064 char *TGLSurfacePainter::GetPlotInfo(Int_t px, Int_t py)
00065 {
00066
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
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
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
00112
00113 if (fSelectedPart >= fSelectionBase) {
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
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
00155 using namespace std;
00156 const Ssiz_t surfPos = option.Index("surf");
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 , Int_t py)
00189 {
00190
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
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
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
00254
00255
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
00265 for (Int_t i = 0; i < nX - 1; ++i) {
00266 for (Int_t j = 0; j < nY - 1; ++j) {
00267
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
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
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
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
00320
00321
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
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
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
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
00481
00482
00483
00484
00485
00486 if (!fCoord->SetRanges(fHist, kFALSE, kFALSE))
00487 return kFALSE;
00488
00489 fBackBox.SetPlotBox(fCoord->GetXRangeScaled(), fCoord->GetYRangeScaled(), fCoord->GetZRangeScaled());
00490
00491
00492
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
00549
00550
00551
00552
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
00616
00617
00618
00619
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
00689
00690
00691
00692
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
00721 const Double_t fullTheta = fXAxis->GetBinCenter(fXAxis->GetNbins()) - fXAxis->GetBinCenter(1);
00722 const Double_t thetaLow = fXAxis->GetBinCenter(1);
00723
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
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
00857
00858 using namespace std;
00859
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
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
00908
00909 using namespace std;
00910
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
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
00959
00960 using namespace std;
00961
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
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
01076
01077
01078
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
01127 if (!fUpdateTexMap)
01128 return kTRUE;
01129
01130 if(fMinMaxVal.first == fMinMaxVal.second)
01131 return kFALSE;
01132
01133
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
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
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
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
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
01217 return fXOZProj.size() || fYOZProj.size() || fXOYProj.size();
01218 }
01219
01220
01221 void TGLSurfacePainter::DrawPalette()const
01222 {
01223
01224
01225
01226 if (!fCamera) {
01227
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
01243 gVirtualX->SetDrawMode(TVirtualX::kCopy);
01244 Rgl::DrawPaletteAxis(fCamera, fMinMaxVal, fCoord->GetCoordType() == kGLCartesian ? fCoord->GetZLog() : kFALSE);
01245 }