#include <iostream>
#include <algorithm>
#include <cctype>
#include "Buttons.h"
#include "TString.h"
#include "TStyle.h"
#include "TColor.h"
#include "TError.h"
#include "TMath.h"
#include "TAxis.h"
#include "TH1.h"
#include "TGLLegoPainter.h"
#include "TGLAxisPainter.h"
#include "TGLIncludes.h"
ClassImp(TGLLegoPainter)
const Float_t TGLLegoPainter::fRedEmission[] = {1.f, 0.f, 0.f, 1.f};
const Float_t TGLLegoPainter::fOrangeEmission[] = {1.f, 0.4f, 0.f, 1.f};
const Float_t TGLLegoPainter::fGreenEmission[] = {0.f, 1.f, 0.f, 1.f};
const Float_t TGLLegoPainter::fNullEmission[] = {0.f, 0.f, 0.f, 1.f};
namespace {
const UChar_t gDefTexture[] =
{
128, 0, 255, 200,
169, 4, 240, 200,
199, 73, 255, 200,
222, 149, 253, 200,
255, 147, 201, 200,
255, 47, 151, 200,
232, 0, 116, 200,
253, 0, 0, 200,
255, 62, 62, 200,
217, 111, 15, 200,
242, 151, 28, 200,
245, 172, 73, 200,
251, 205, 68, 200,
255, 255, 21, 200,
255, 255, 128, 200,
255, 255, 185, 200
};
}
TGLLegoPainter::TGLLegoPainter(TH1 *hist, TGLAxisPainter *axisPainter, Int_t ctx, EGLCoordType type,
Bool_t logX, Bool_t logY, Bool_t logZ)
: TGLPlotFrame(logX, logY, logZ),
fHist(hist),
fGLContext(ctx),
fCoordType(type),
fMinZ(0.),
fLegoType(kColorSimple),
fSelectionPass(kFALSE),
fUpdateSelection(kTRUE),
fSelectedBin(-1, -1),
fSelectionMode(kSelectionSimple),
fSelectedPlane(0),
fPadColor(0),
fFrameColor(0),
fXOZProfilePos(0.),
fYOZProfilePos(0.),
fIsMoving(kFALSE),
fAxisPainter(axisPainter),
fTextureName(0),
fTexture(gDefTexture, gDefTexture + sizeof gDefTexture),
fDrawErrors(kFALSE)
{
if (MakeGLContextCurrent()) {
gGLManager->ExtractViewport(fGLContext, fViewport);
fArcBall.SetBounds(fViewport[2], fViewport[3]);
}
}
void TGLLegoPainter::Paint()
{
if (!MakeGLContextCurrent())
return;
InitGL();
glPushAttrib(GL_LIGHTING_BIT);
const Int_t oldW = fViewport[2];
const Int_t oldH = fViewport[3];
gGLManager->ExtractViewport(fGLContext, fViewport);
if (oldW != fViewport[2] || oldH != fViewport[3]) {
fArcBall.SetBounds(fViewport[2], fViewport[3]);
fUpdateSelection = kTRUE;
}
SetCamera();
ClearBuffers();
const Float_t pos[] = {0.f, 0.f, 0.f, 1.f};
glLightfv(GL_LIGHT0, GL_POSITION, pos);
SetTransformation();
FindFrontPoint();
DrawPlot();
glPopAttrib();
glFlush();
gGLManager->ReadGLBuffer(fGLContext);
if (fCoordType == kGLCartesian)
fAxisPainter->Paint(fGLContext);
gGLManager->Flush(fGLContext);
fAxisPainter->Paint(fGLContext);
glFlush();
gGLManager->Flush(fGLContext);
*/
}
void TGLLegoPainter::SetGLContext(Int_t ctx)
{
fGLContext = ctx;
}
char *TGLLegoPainter::GetObjectInfo(Int_t px, Int_t py)
{
if (fIsMoving)
return "Moving ...";
py = fViewport[3] - py;
std::swap(px, py);
Selection_t newSelected(ColorToObject(fSelection.GetPixelColor(px, py)));
fBinInfo = "";
if (newSelected.first >= 0 && newSelected.second >= 0) {
fBinInfo.Form(
"(binx = %d; biny = %d; binc = %f)",
newSelected.first + fBinsX.first,
newSelected.second + fBinsY.first,
fHist->GetBinContent(newSelected.first + fBinsX.first, newSelected.second + fBinsY.first)
);
return (Char_t *)fBinInfo.Data();
} else if (fSelectedPlane) {
if (fHist->Class())
fBinInfo += fHist->Class()->GetName();
fBinInfo += "::";
fBinInfo += fHist->GetName();
return (Char_t *)fBinInfo.Data();
}
return " ";
}
Bool_t TGLLegoPainter::InitGeometry()
{
switch (fCoordType) {
case kGLCartesian:
return InitGeometryCartesian();
case kGLPolar:
return InitGeometryPolar();
case kGLCylindrical:
return InitGeometryCylindrical();
case kGLSpherical:
return InitGeometrySpherical();
default:
return kFALSE;
}
}
Bool_t TGLLegoPainter::InitGeometryCartesian()
{
using RootGL::FindAxisRange;
BinRange_t xBins;
Range_t xRange;
const TAxis *xAxis = fHist->GetXaxis();
if (!FindAxisRange(xAxis, fLogX, xBins, xRange)) {
Error("TGLLegoPainter::InitGeometryCartesian", "Cannot set X axis to log scale");
return kFALSE;
}
BinRange_t yBins;
Range_t yRange;
const TAxis *yAxis = fHist->GetYaxis();
if (!FindAxisRange(yAxis, fLogY, yBins, yRange)) {
Error("TGLLegoPainter::InitGeometryCartesian", "Cannot set Y axis to log scale");
return kFALSE;
}
Range_t zRange;
Double_t factor = 1.;
if (!FindAxisRange(fHist, fLogZ, xBins, yBins, zRange, factor, fDrawErrors))
{
Error("TGLLegoPainter::InitGeometryCartesian",
"Log scale is requested for Z, but maximum less or equal 0. (%f)", zRange.second);
return kFALSE;
}
CalculateGLCameraParams(xRange, yRange, zRange);
fAxisPainter->SetRanges(xRange, yRange, zRange);
if (xBins != fBinsX || yBins != fBinsY || xRange != fRangeX || yRange != fRangeY
|| zRange != fRangeZ || factor != fFactor) {
fUpdateSelection = kTRUE;
fXOZProfilePos = fFrame[0].Y();
fYOZProfilePos = fFrame[0].X();
}
fBinsX = xBins, fBinsY = yBins, fRangeX = xRange, fRangeY = yRange, fRangeZ = zRange, fFactor = factor;
const Int_t nX = fBinsX.second - fBinsX.first + 1;
const Double_t barWidth = fHist->GetBarWidth();
const Double_t barOffset = fHist->GetBarOffset();
fXEdges.resize(nX);
if (fLogX)
for (Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
const Double_t xWidth = xAxis->GetBinWidth(ir);
Double_t low = xAxis->GetBinLowEdge(ir) + xWidth * barOffset;
fXEdges[i].first = TMath::Log10(low) * fScaleX;
fXEdges[i].second = TMath::Log10(low + xWidth * barWidth) * fScaleX;;
if (fXEdges[i].second > fFrame[1].X())
fXEdges[i].second = fFrame[1].X();
if (fXEdges[i].first < fFrame[0].X())
fXEdges[i].first = fFrame[0].X();
if (fXEdges[i].second < fFrame[0].X())
fXEdges[i].second = fFrame[0].X();
}
else
for (Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
const Double_t xWidth = xAxis->GetBinWidth(ir);
fXEdges[i].first = (xAxis->GetBinLowEdge(ir) + xWidth * barOffset) * fScaleX;
fXEdges[i].second = fXEdges[i].first + xWidth * barWidth * fScaleX;
if (fXEdges[i].second > fFrame[1].X())
fXEdges[i].second = fFrame[1].X();
if (fXEdges[i].first < fFrame[0].X())
fXEdges[i].first = fFrame[0].X();
if (fXEdges[i].second < fFrame[0].X())
fXEdges[i].second = fFrame[0].X();
}
const Int_t nY = fBinsY.second - fBinsY.first + 1;
fYEdges.resize(nY);
if (fLogY)
for (Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
const Double_t yWidth = yAxis->GetBinWidth(jr);
Double_t low = yAxis->GetBinLowEdge(jr) + yWidth * barOffset;
fYEdges[j].first = TMath::Log10(low) * fScaleY;
fYEdges[j].second = TMath::Log10(low + yWidth * barWidth) * fScaleY;
if (fYEdges[j].second > fFrame[2].Y())
fYEdges[j].second = fFrame[2].Y();
if (fYEdges[j].first < fFrame[0].Y())
fYEdges[j].first = fFrame[0].Y();
if (fYEdges[j].second < fFrame[0].Y())
fYEdges[j].second = fFrame[0].Y();
}
else
for (Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
const Double_t yWidth = yAxis->GetBinWidth(jr);
fYEdges[j].first = (yAxis->GetBinLowEdge(jr) + yWidth * barOffset) * fScaleY;
fYEdges[j].second = fYEdges[j].first + yWidth * barWidth * fScaleY;
if (fYEdges[j].second > fFrame[2].Y())
fYEdges[j].second = fFrame[2].Y();
if (fYEdges[j].first < fFrame[0].Y())
fYEdges[j].first = fFrame[0].Y();
if (fYEdges[j].second < fFrame[0].Y())
fYEdges[j].second = fFrame[0].Y();
}
fMinZ = fFrame[0].Z();
if (fMinZ < 0. && !fLogZ)
fFrame[4].Z() > 0. ? fMinZ = 0. : fMinZ = fFrame[4].Z();
fAxisPainter->SetZLevels(fZLevels);
return kTRUE;
}
Bool_t TGLLegoPainter::InitGeometryPolar()
{
using RootGL::FindAxisRange;
BinRange_t xBins;
Range_t phiRange;
const TAxis *xAxis = fHist->GetXaxis();
if (!FindAxisRange(xAxis, kFALSE, xBins, phiRange)) {
Error("TGLLegoPainter::InitGeometryPolar", "Cannot set X axis to log scale");
return kFALSE;
}
if (xBins.second - xBins.first + 1 > 360) {
Error("TGLLegoPainter::InitGeometryPolar", "To many PHI sectors");
return kFALSE;
}
BinRange_t yBins;
Range_t roRange;
const TAxis *yAxis = fHist->GetYaxis();
if (!FindAxisRange(yAxis, kFALSE, yBins, roRange)) {
Error("TGLLegoPainter::InitGeometryPolar", "Cannot set Y axis to log scale");
return kFALSE;
}
Range_t zRange;
Double_t factor = 1.;
if (!FindAxisRange(fHist, fLogZ, xBins, yBins, zRange, factor))
{
Error("TGLLegoPainter::InitGeometryPolar",
"Log scale is requested for Z, but maximum less or equal 0. (%f)", zRange.second);
return kFALSE;
}
CalculateGLCameraParams(Range_t(-1., 1.), Range_t(-1., 1.), zRange);
if (xBins != fBinsX || yBins != fBinsY || phiRange != fRangeX || roRange != fRangeY || zRange != fRangeZ)
fUpdateSelection = kTRUE;
fBinsX = xBins, fBinsY = yBins, fRangeX = phiRange, fRangeY = roRange, fRangeZ = zRange;
const Int_t nY = yBins.second - yBins.first + 1;
fYEdges.resize(nY);
const Double_t yLow = roRange.first;
const Double_t maxRadius = roRange.second - roRange.first;
for (Int_t j = 0, jr = yBins.first; j < nY; ++j, ++jr) {
fYEdges[j].first = ((yAxis->GetBinLowEdge(jr)) - yLow) / maxRadius * fScaleY;
fYEdges[j].second = ((yAxis->GetBinUpEdge(jr)) - yLow) / maxRadius * fScaleY;
}
const Int_t nX = xBins.second - xBins.first + 1;
fCosSinTableX.resize(nX + 1);
const Double_t fullAngle = xAxis->GetXmax() - xAxis->GetXmin();
const Double_t phiLow = xAxis->GetXmin();
Double_t angle = 0;
for (Int_t i = 0, ir = xBins.first; i < nX; ++i, ++ir) {
angle = (xAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
fCosSinTableX[i].first = TMath::Cos(angle);
fCosSinTableX[i].second = TMath::Sin(angle);
}
angle = (xAxis->GetBinUpEdge(fBinsX.second) - phiLow) / fullAngle * TMath::TwoPi();
fCosSinTableX[nX].first = TMath::Cos(angle);
fCosSinTableX[nX].second = TMath::Sin(angle);
fMinZ = fFrame[0].Z();
if (fMinZ < 0. && !fLogZ)
fFrame[4].Z() > 0. ? fMinZ = 0. : fMinZ = fFrame[4].Z();
return kTRUE;
}
Bool_t TGLLegoPainter::InitGeometryCylindrical()
{
using RootGL::FindAxisRange;
BinRange_t xBins, yBins;
Range_t angleRange, heightRange, radiusRange;
const TAxis *xAxis = fHist->GetXaxis();
const TAxis *yAxis = fHist->GetYaxis();
Double_t factor = 1.;
FindAxisRange(xAxis, kFALSE, xBins, angleRange);
if (xBins.second - xBins.first + 1 > 360) {
Error("TGLLegoPainter::InitGeometryCylindrical", "To many PHI sectors");
return kFALSE;
}
if (!FindAxisRange(yAxis, fLogY, yBins, heightRange)) {
Error("TGLLegoPainter::InitGeometryCylindrical", "Cannot set Y axis to log scale");
return kFALSE;
}
FindAxisRange(fHist, kFALSE, xBins, yBins, radiusRange, factor);
CalculateGLCameraParams(Range_t(-1., 1.), Range_t(-1., 1.), heightRange);
const Int_t nY = yBins.second - yBins.first + 1;
fYEdges.resize(nY);
if (fLogY)
for (Int_t j = 0, jr = yBins.first; j < nY; ++j, ++jr) {
fYEdges[j].first = TMath::Log10(yAxis->GetBinLowEdge(jr)) * fScaleZ;
fYEdges[j].second = TMath::Log10(yAxis->GetBinUpEdge(jr)) * fScaleZ;
}
else
for (Int_t j = 0, jr = yBins.first; j < nY; ++j, ++jr) {
fYEdges[j].first = yAxis->GetBinLowEdge(jr) * fScaleZ;
fYEdges[j].second = yAxis->GetBinUpEdge(jr) * fScaleZ;
}
const Int_t nX = xBins.second - xBins.first + 1;
fCosSinTableX.resize(nX + 1);
const Double_t fullAngle = xAxis->GetXmax() - xAxis->GetXmin();
const Double_t phiLow = xAxis->GetXmin();
Double_t angle = 0.;
for (Int_t i = 0, ir = xBins.first; i < nX; ++i, ++ir) {
angle = (xAxis->GetBinLowEdge(ir) - phiLow) / fullAngle * TMath::TwoPi();
fCosSinTableX[i].first = TMath::Cos(angle);
fCosSinTableX[i].second = TMath::Sin(angle);
}
angle = (xAxis->GetBinUpEdge(fBinsX.second) - phiLow) / fullAngle * TMath::TwoPi();
fCosSinTableX[nX].first = TMath::Cos(angle);
fCosSinTableX[nX].second = TMath::Sin(angle);
if (xBins != fBinsX || yBins != fBinsY || angleRange != fRangeX || heightRange != fRangeY || radiusRange != fRangeZ)
fUpdateSelection = kTRUE;
fBinsX = xBins, fBinsY = yBins, fRangeX = angleRange, fRangeY = heightRange, fRangeZ = radiusRange;
return kTRUE;
}
Bool_t TGLLegoPainter::InitGeometrySpherical()
{
using RootGL::FindAxisRange;
BinRange_t xBins, yBins;
Range_t phiRange, thetaRange, radiusRange;
const TAxis *xAxis = fHist->GetXaxis();
const TAxis *yAxis = fHist->GetYaxis();
Double_t factor = 1.;
FindAxisRange(xAxis, kFALSE, xBins, phiRange);
if (xBins.second - xBins.first + 1 > 360) {
Error("TGLLegoPainter::InitGeometrySpherical", "To many PHI sectors");
return kFALSE;
}
FindAxisRange(yAxis, kFALSE, yBins, thetaRange);
if (yBins.second - yBins.first + 1 > 180) {
Error("TGLLegoPainter::InitGeometrySpherical", "To many THETA sectors");
return kFALSE;
}
FindAxisRange(fHist, kFALSE, xBins, yBins, radiusRange, factor);
CalculateGLCameraParams(Range_t(-1., 1.), Range_t(-1., 1.), Range_t(-1., 1.));
const Int_t nY = yBins.second - yBins.first + 1;
fCosSinTableY.resize(nY + 1);
const Double_t fullTheta = yAxis->GetXmax() - yAxis->GetXmin();
const Double_t thetaLow = yAxis->GetXmin();
Double_t angle = 0.;
for (Int_t j = 0, jr = yBins.first; j < nY; ++j, ++jr) {
angle = (yAxis->GetBinLowEdge(jr) - thetaLow) / fullTheta * TMath::Pi();
fCosSinTableY[j].first = TMath::Cos(angle);
fCosSinTableY[j].second = TMath::Sin(angle);
}
angle = (yAxis->GetBinUpEdge(fBinsY.second) - thetaLow) / fullTheta * TMath::Pi();
fCosSinTableY[nY].first = TMath::Cos(angle);
fCosSinTableY[nY].second = TMath::Sin(angle);
const Int_t nX = xBins.second - xBins.first + 1;
fCosSinTableX.resize(nX + 1);
const Double_t fullPhi = xAxis->GetXmax() - xAxis->GetXmin();
const Double_t phiLow = xAxis->GetXmin();
for (Int_t i = 0, ir = xBins.first; i < nX; ++i, ++ir) {
angle = (xAxis->GetBinLowEdge(ir) - phiLow) / fullPhi * TMath::TwoPi();
fCosSinTableX[i].first = TMath::Cos(angle);
fCosSinTableX[i].second = TMath::Sin(angle);
}
angle = (xAxis->GetBinUpEdge(fBinsX.second) - phiLow) / fullPhi * TMath::TwoPi();
fCosSinTableX[nX].first = TMath::Cos(angle);
fCosSinTableX[nX].second = TMath::Sin(angle);
if (xBins != fBinsX || yBins != fBinsY || phiRange != fRangeX || thetaRange != fRangeY || radiusRange != fRangeZ)
fUpdateSelection = kTRUE;
fBinsX = xBins, fBinsY = yBins, fRangeX = phiRange, fRangeY = thetaRange, fRangeZ = radiusRange;
return kTRUE;
}
void TGLLegoPainter::StartRotation(Int_t px, Int_t py)
{
fArcBall.Click(TPoint(px, py));
fIsMoving = kTRUE;
}
void TGLLegoPainter::Rotate(Int_t px, Int_t py)
{
fArcBall.Drag(TPoint(px, py));
fUpdateSelection = kTRUE;
}
void TGLLegoPainter::StopRotation()
{
fIsMoving = kFALSE;
}
void TGLLegoPainter::StartPan(Int_t px, Int_t py)
{
fMousePosition.fX = px;
fMousePosition.fY = fViewport[3] - py;
fIsMoving = kTRUE;
}
void TGLLegoPainter::Pan(Int_t px, Int_t py)
{
if (!MakeGLContextCurrent())
return;
py = fViewport[3] - py;
if (fSelectedPlane < 2)
AdjustShift(fMousePosition, TPoint(px, py), fPan, fViewport);
else if (fSelectedPlane >= 2 && fSelectedPlane <= 5)
MoveDynamicProfile(px, py);
fMousePosition.fX = px, fMousePosition.fY = py;
fUpdateSelection = kTRUE;
}
void TGLLegoPainter::StopPan()
{
fIsMoving = kFALSE;
}
TObject *TGLLegoPainter::Select(Int_t px, Int_t py)
{
if (!MakeGLContextCurrent())
return 0;
if (fUpdateSelection) {
SetSelectionMode();
fSelectionPass = kTRUE;
SetCamera();
glDisable(GL_LIGHTING);
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SetTransformation();
DrawPlot();
glFlush();
fSelection.ReadColorBuffer(fViewport[2], fViewport[3]);
fSelectionPass = kFALSE;
fUpdateSelection = kFALSE;
glEnable(GL_LIGHTING);
}
py = fViewport[3] - py;
std::swap(px, py);
Selection_t newSelected(ColorToObject(fSelection.GetPixelColor(px, py)));
if (newSelected != fSelectedBin) {
fSelectedBin = newSelected;
gGLManager->MarkForDirectCopy(fGLContext, kTRUE);
Paint();
gGLManager->MarkForDirectCopy(fGLContext, kFALSE);
}
return fSelectedBin.first != -1 || fSelectedPlane ? fHist : 0;
}
void TGLLegoPainter::ZoomIn()
{
fZoom /= 1.2;
fUpdateSelection = kTRUE;
}
void TGLLegoPainter::ZoomOut()
{
fZoom *= 1.2;
fUpdateSelection = kTRUE;
}
void TGLLegoPainter::SetLogX(Bool_t log)
{
fCoordType == kGLCartesian ? fLogX = log : fLogX = kFALSE;
}
void TGLLegoPainter::SetLogY(Bool_t log)
{
fCoordType == kGLCartesian || fCoordType == kGLCylindrical ? fLogY = log : fLogY = kFALSE;
}
void TGLLegoPainter::SetLogZ(Bool_t log)
{
fCoordType == kGLCartesian || fCoordType == kGLPolar ? fLogZ = log : fLogZ = kFALSE;
}
void TGLLegoPainter::SetCoordType(EGLCoordType type)
{
if (type != fCoordType) {
fUpdateSelection = kTRUE;
if (type == kGLCartesian) {
fBinsX = BinRange_t(0, 0);
}
}
fCoordType = type;
}
void TGLLegoPainter::AddOption(const TString &option)
{
const Ssiz_t legoPos = option.Index("lego");
if (legoPos + 4 < option.Length() && std::isdigit(option[legoPos + 4])) {
switch (option[legoPos + 4] - '0') {
case 1:
fLegoType = kColorSimple;
break;
case 2:
fLegoType = kColorLevel;
break;
case 3:
fLegoType = kCylindricBars;
break;
}
} else
fLegoType = kColorSimple;
fDrawErrors = option.Index("e", legoPos + 4) != kNPOS;
}
void TGLLegoPainter::SetPadColor(TColor *c)
{
fPadColor = c;
}
void TGLLegoPainter::SetFrameColor(TColor *c)
{
fFrameColor = c;
}
void TGLLegoPainter::InitGL()
{
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
}
TGLLegoPainter::Selection_t TGLLegoPainter::ColorToObject(const UChar_t *color)
{
const Int_t nY = fBinsY.second - fBinsY.first + 1;
const Int_t nBins = nY * (fBinsX.second - fBinsX.first + 1);
Selection_t selected(-1, -1);
if (fSelectionMode == kSelectionSimple) {
if (color[0])
fSelectedPlane = 1;
} else {
if (Int_t selectedNum = color[0] | (color[1] << 8) | (color[2] << 16)) {
selectedNum -= 1;
if (selectedNum < nBins) {
fSelectedPlane = 0;
selected.first = selectedNum / nY;
selected.second = selectedNum % nY;
} else {
selectedNum -= nBins;
if (fSelectedPlane != selectedNum) {
fSelectedPlane = selectedNum;
gGLManager->MarkForDirectCopy(fGLContext, kTRUE);
Paint();
gGLManager->MarkForDirectCopy(fGLContext, kFALSE);
}
}
} else if (fSelectedPlane) {
fSelectedPlane = 0;
gGLManager->MarkForDirectCopy(fGLContext, kTRUE);
Paint();
gGLManager->MarkForDirectCopy(fGLContext, kFALSE);
}
}
return selected;
}
void TGLLegoPainter::EncodeToColor(Int_t i, Int_t j)const
{
if (fSelectionMode == kSelectionSimple)
glColor3ub(255, 255, 255);
else {
const Int_t code = i * (fBinsY.second - fBinsY.first + 1) + j + 1;
glColor3ub(code & 0xff, (code & 0xff00) >> 8, (code & 0xff0000) >> 16);
}
}
void TGLLegoPainter::DrawPlot()
{
switch (fCoordType) {
case kGLPolar:
return DrawLegoPolar();
case kGLCylindrical:
return DrawLegoCylindrical();
case kGLSpherical:
return DrawLegoSpherical();
case kGLCartesian:
default:
DrawLegoCartesian();
}
}
void TGLLegoPainter::DrawLegoCartesian()
{
DrawFrame();
if (!fSelectionPass) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.f, 1.f);
SetLegoColor();
if (fXOZProfilePos > fFrame[0].Y() || fYOZProfilePos > fFrame[0].X()) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
}
const Int_t nX = fXEdges.size();
const Int_t nY = fYEdges.size();
Int_t iInit = 0, jInit = 0, irInit = fBinsX.first, jrInit = fBinsY.first;
const Int_t addI = fFrontPoint == 2 || fFrontPoint == 1 ? 1 : (iInit = nX - 1, irInit = fBinsX.second, -1);
const Int_t addJ = fFrontPoint == 2 || fFrontPoint == 3 ? 1 : (jInit = nY - 1, jrInit = fBinsY.second, -1);
if (fLegoType == kColorLevel && !fSelectionPass)
Enable1DTexture();
for(Int_t i = iInit, ir = irInit; addI > 0 ? i < nX : i >= 0; i += addI, ir += addI) {
for(Int_t j = jInit, jr = jrInit; addJ > 0 ? j < nY : j >= 0; j += addJ, jr += addJ) {
Double_t zMax = fHist->GetCellContent(ir, jr) * fFactor;
if (!ClampZ(zMax))
continue;
if (fSelectionPass)
EncodeToColor(i, j);
else if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fOrangeEmission);
if (fLegoType == kCylindricBars) {
RootGL::DrawCylinder(&fQuadric, fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
fYEdges[j].second, fMinZ, zMax);
} else if (fLegoType == kColorLevel && !fSelectionPass) {
const Double_t zRange = fRangeZ.second - fRangeZ.first;
RootGL::DrawBoxFrontTextured(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
fYEdges[j].second, fMinZ, zMax, (fMinZ - fRangeZ.first) / zRange,
(zMax - fRangeZ.first) / zRange, fFrontPoint);
} else {
RootGL::DrawBoxFront(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
fYEdges[j].second, fMinZ, zMax, fFrontPoint);
}
if (!fSelectionPass && fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fNullEmission);
}
}
if (fLegoType == kColorLevel && !fSelectionPass)
Disable1DTexture();
if (!fSelectionPass) {
glDisable(GL_POLYGON_OFFSET_FILL);
RootGL::TGLDisableGuard lightGuard(GL_LIGHTING);
if (fXOZProfilePos <= fFrame[0].Y() && fYOZProfilePos <= fFrame[0].X())
glColor3d(0., 0., 0.);
else
glColor4d(0., 0., 0., 0.4);
glPolygonMode(GL_FRONT, GL_LINE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
for(Int_t i = iInit, ir = irInit; addI > 0 ? i < nX : i >= 0; i += addI, ir += addI) {
for(Int_t j = jInit, jr = jrInit; addJ > 0 ? j < nY : j >= 0; j += addJ, jr += addJ) {
Double_t zMax = fHist->GetCellContent(ir, jr) * fFactor;
if (!ClampZ(zMax))
continue;
if (fLegoType != kCylindricBars) {
RootGL::DrawBoxFront(
fXEdges[i].first, fXEdges[i].second,
fYEdges[j].first, fYEdges[j].second,
fMinZ, zMax, fFrontPoint
);
}
if (fDrawErrors && zMax > 0.) {
Double_t errorZMax = (fHist->GetCellContent(ir, jr) + fHist->GetCellError(ir, jr))* fFactor;
ClampZ(errorZMax);
RootGL::DrawError(fXEdges[i].first, fXEdges[i].second, fYEdges[j].first,
fYEdges[j].second, zMax, errorZMax);
}
}
}
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT, GL_FILL);
}
}
void TGLLegoPainter::DrawLegoPolar()
{
const Int_t nX = fCosSinTableX.size() - 1;
const Int_t nY = fYEdges.size();
if (!fSelectionPass) {
SetLegoColor();
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.f, 1.f);
}
Double_t points[4][2] = {};
if (!fSelectionPass && fLegoType == kColorLevel)
Enable1DTexture();
for(Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
for(Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
Double_t zMax = fHist->GetCellContent(ir, jr) * fFactor;
if (!ClampZ(zMax))
continue;
points[0][0] = fYEdges[j].first * fCosSinTableX[i].first;
points[0][1] = fYEdges[j].first * fCosSinTableX[i].second;
points[1][0] = fYEdges[j].second * fCosSinTableX[i].first;
points[1][1] = fYEdges[j].second * fCosSinTableX[i].second;
points[2][0] = fYEdges[j].second * fCosSinTableX[i + 1].first;
points[2][1] = fYEdges[j].second * fCosSinTableX[i + 1].second;
points[3][0] = fYEdges[j].first * fCosSinTableX[i + 1].first;
points[3][1] = fYEdges[j].first * fCosSinTableX[i + 1].second;
if (fSelectionPass)
EncodeToColor(i, j);
else if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fOrangeEmission);
if (fLegoType == kColorLevel && !fSelectionPass) {
const Double_t zRange = fRangeZ.second - fRangeZ.first;
RootGL::DrawTrapezoidTextured(
points, fMinZ, zMax,
(fMinZ - fRangeZ.first) / zRange,
(zMax - fRangeZ.first) / zRange
);
}
else
RootGL::DrawTrapezoid(points, fMinZ, zMax);
if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fNullEmission);
}
}
if (fLegoType == kColorLevel && !fSelectionPass)
Disable1DTexture();
if (!fSelectionPass) {
glDisable(GL_POLYGON_OFFSET_FILL);
RootGL::TGLDisableGuard lightGuard(GL_LIGHTING);
glColor3d(0., 0., 0.);
glPolygonMode(GL_FRONT, GL_LINE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
for(Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
for(Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
Double_t zMax = fHist->GetCellContent(ir, jr) * fFactor;
if (!ClampZ(zMax))
continue;
points[0][0] = fYEdges[j].first * fCosSinTableX[i].first;
points[0][1] = fYEdges[j].first * fCosSinTableX[i].second;
points[1][0] = fYEdges[j].second * fCosSinTableX[i].first;
points[1][1] = fYEdges[j].second * fCosSinTableX[i].second;
points[2][0] = fYEdges[j].second * fCosSinTableX[i + 1].first;
points[2][1] = fYEdges[j].second * fCosSinTableX[i + 1].second;
points[3][0] = fYEdges[j].first * fCosSinTableX[i + 1].first;
points[3][1] = fYEdges[j].first * fCosSinTableX[i + 1].second;
RootGL::DrawTrapezoid(points, fMinZ, zMax, kFALSE);
}
}
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT, GL_FILL);
}
}
void TGLLegoPainter::DrawLegoCylindrical()
{
const Int_t nX = fCosSinTableX.size() - 1;
const Int_t nY = fYEdges.size();
const Double_t rRange = fRangeZ.second - fRangeZ.first;
Double_t legoR = gStyle->GetLegoInnerR();
if (legoR > 1. || legoR < 0.)
legoR = 0.5;
if (!fSelectionPass) {
SetLegoColor();
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.f, 1.f);
}
Double_t points[4][2] = {};
const Double_t sc = (1 - legoR) * fScaleX;
Double_t zMax = 0, zMin = 0, zVal = 0;
if (!fSelectionPass && fLegoType == kColorLevel)
Enable1DTexture();
for(Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
for(Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
zVal = fHist->GetCellContent(ir, jr) * fFactor;
if (zVal >= 0.) {
zMin = legoR * fScaleX;
zMax = legoR * fScaleX + zVal / rRange * sc;
} else {
zMax = legoR * fScaleX;
zMin = legoR * fScaleX + zVal / rRange * sc;
}
points[0][0] = fCosSinTableX[i].first * zMin;
points[0][1] = fCosSinTableX[i].second * zMin;
points[1][0] = fCosSinTableX[i].first * zMax;
points[1][1] = fCosSinTableX[i].second * zMax;
points[2][0] = fCosSinTableX[i + 1].first * zMax;
points[2][1] = fCosSinTableX[i + 1].second * zMax;
points[3][0] = fCosSinTableX[i + 1].first * zMin;
points[3][1] = fCosSinTableX[i + 1].second * zMin;
if (fSelectionPass)
EncodeToColor(i, j);
else if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fOrangeEmission);
if (fLegoType == kColorLevel && !fSelectionPass) {
const Double_t zRange = fRangeZ.second - fRangeZ.first;
RootGL::DrawTrapezoidTextured2(
points, fYEdges[j].first, fYEdges[j].second,
(fMinZ - fRangeZ.first) / zRange,
(zVal - fRangeZ.first) / zRange
);
}
else
RootGL::DrawTrapezoid(points, fYEdges[j].first, fYEdges[j].second);
if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fNullEmission);
}
}
if (!fSelectionPass && fLegoType == kColorLevel)
Disable1DTexture();
if (!fSelectionPass) {
glDisable(GL_POLYGON_OFFSET_FILL);
RootGL::TGLDisableGuard lightGuard(GL_LIGHTING);
glColor3d(0., 0., 0.);
glPolygonMode(GL_FRONT, GL_LINE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
for(Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
for(Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
zVal = fHist->GetCellContent(ir, jr) * fFactor;
if (zVal >= 0.) {
zMin = legoR * fScaleX;
zMax = legoR * fScaleX + zVal / rRange * sc;
} else {
zMax = legoR * fScaleX;
zMin = legoR * fScaleX + zVal / rRange * sc;
}
points[0][0] = fCosSinTableX[i].first * zMin;
points[0][1] = fCosSinTableX[i].second * zMin;
points[1][0] = fCosSinTableX[i].first * zMax;
points[1][1] = fCosSinTableX[i].second * zMax;
points[2][0] = fCosSinTableX[i + 1].first * zMax;
points[2][1] = fCosSinTableX[i + 1].second * zMax;
points[3][0] = fCosSinTableX[i + 1].first * zMin;
points[3][1] = fCosSinTableX[i + 1].second * zMin;
RootGL::DrawTrapezoid(points, fYEdges[j].first, fYEdges[j].second);
}
}
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT, GL_FILL);
}
}
void TGLLegoPainter::DrawLegoSpherical()
{
const Int_t nX = fCosSinTableX.size() - 1;
const Int_t nY = fCosSinTableY.size() - 1;
const Double_t rRange = fRangeZ.second - fRangeZ.first;
Double_t legoR = gStyle->GetLegoInnerR();
if (legoR > 1. || legoR < 0.)
legoR = 0.5;
if (!fSelectionPass) {
SetLegoColor();
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.f, 1.f);
}
Double_t points[8][3] = {};
const Double_t sc = (1 - legoR) * fScaleX;
Double_t zMax = 0, zMin = 0, zVal = 0;
if (!fSelectionPass && fLegoType == kColorLevel)
Enable1DTexture();
for(Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
for(Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
zVal = fHist->GetCellContent(ir, jr) * fFactor;
if (zVal >= 0.) {
zMin = legoR * fScaleX;
zMax = legoR * fScaleX + zVal / rRange * sc;
} else {
zMax = legoR * fScaleX;
zMin = legoR * fScaleX + zVal / rRange * sc;
}
points[4][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].first;
points[4][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].second;
points[4][2] = zMin * fCosSinTableY[j].first;
points[5][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
points[5][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
points[5][2] = zMin * fCosSinTableY[j].first;
points[6][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
points[6][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
points[6][2] = zMax * fCosSinTableY[j].first;
points[7][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].first;
points[7][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].second;
points[7][2] = zMax * fCosSinTableY[j].first;
points[0][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
points[0][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
points[0][2] = zMin * fCosSinTableY[j + 1].first;
points[1][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
points[1][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
points[1][2] = zMin * fCosSinTableY[j + 1].first;
points[2][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
points[2][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
points[2][2] = zMax * fCosSinTableY[j + 1].first;
points[3][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
points[3][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
points[3][2] = zMax * fCosSinTableY[j + 1].first;
if (fSelectionPass)
EncodeToColor(i, j);
else if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fOrangeEmission);
if (fLegoType == kColorLevel && !fSelectionPass) {
const Double_t zRange = fRangeZ.second - fRangeZ.first;
RootGL::DrawTrapezoidTextured(
points,
(fMinZ - fRangeZ.first) / zRange,
(zVal - fRangeZ.first) / zRange
);
}
else
RootGL::DrawTrapezoid(points);
if(fSelectedBin == Selection_t(i, j))
glMaterialfv(GL_FRONT, GL_EMISSION, fNullEmission);
}
}
if (!fSelectionPass && fLegoType == kColorLevel)
Disable1DTexture();
if (!fSelectionPass) {
glDisable(GL_POLYGON_OFFSET_FILL);
RootGL::TGLDisableGuard lightGuard(GL_LIGHTING);
glColor3d(0., 0., 0.);
glPolygonMode(GL_FRONT, GL_LINE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
for(Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
for(Int_t j = 0, jr = fBinsY.first; j < nY; ++j, ++jr) {
zVal = fHist->GetCellContent(ir, jr) * fFactor;
if (zVal >= 0.) {
zMin = legoR * fScaleX;
zMax = legoR * fScaleX + zVal / rRange * sc;
} else {
zMax = legoR * fScaleX;
zMin = legoR * fScaleX + zVal / rRange * sc;
}
points[4][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].first;
points[4][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i].second;
points[4][2] = zMin * fCosSinTableY[j].first;
points[5][0] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
points[5][1] = zMin * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
points[5][2] = zMin * fCosSinTableY[j].first;
points[6][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].first;
points[6][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i + 1].second;
points[6][2] = zMax * fCosSinTableY[j].first;
points[7][0] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].first;
points[7][1] = zMax * fCosSinTableY[j].second * fCosSinTableX[i].second;
points[7][2] = zMax * fCosSinTableY[j].first;
points[0][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
points[0][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
points[0][2] = zMin * fCosSinTableY[j + 1].first;
points[1][0] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
points[1][1] = zMin * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
points[1][2] = zMin * fCosSinTableY[j + 1].first;
points[2][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].first;
points[2][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i + 1].second;
points[2][2] = zMax * fCosSinTableY[j + 1].first;
points[3][0] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].first;
points[3][1] = zMax * fCosSinTableY[j + 1].second * fCosSinTableX[i].second;
points[3][2] = zMax * fCosSinTableY[j + 1].first;
RootGL::DrawTrapezoid(points);
}
}
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT, GL_FILL);
}
}
void TGLLegoPainter::SetLegoColor()
{
Float_t diffColor[] = {0.8f, 0.8f, 0.8f, 0.15f};
if (fLegoType != kColorLevel && fHist->GetFillColor() != kWhite)
if (TColor *c = gROOT->GetColor(fHist->GetFillColor()))
c->GetRGB(diffColor[0], diffColor[1], diffColor[2]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diffColor);
const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
glMaterialfv(GL_FRONT, GL_SPECULAR, specColor);
glMaterialf(GL_FRONT, GL_SHININESS, 70.f);
}
Bool_t TGLLegoPainter::MakeGLContextCurrent()const
{
return fGLContext != -1 && gGLManager->MakeCurrent(fGLContext);
}
void TGLLegoPainter::ClearBuffers()
{
Float_t rgb[3] = {1.f, 1.f, 1.f};
if (fPadColor)
fPadColor->GetRGB(rgb[0], rgb[1], rgb[2]);
glClearColor(rgb[0], rgb[1], rgb[2], 1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void TGLLegoPainter::SetSelectionMode()
{
if (unsigned((fBinsX.second - fBinsX.first) * (fBinsY.second - fBinsY.first)) > (1u<<24) - 5) {
fSelectionMode = kSelectionSimple;
fSelectedPlane = 0;
fSelectedBin = Selection_t(-1, -1);
} else
fSelectionMode = kSelectionFull;
}
void TGLLegoPainter::DrawFrame()
{
if (!fSelectionPass) {
glEnable(GL_BLEND);
glDepthMask(GL_FALSE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Float_t backColor[] = {0.9f, 0.9f, 0.9f, 0.85f};
if (fFrameColor)
fFrameColor->GetRGB(backColor[0], backColor[1], backColor[2]);
const Int_t selectionBase = fBinsX.second - fBinsX.first + 1;
if (!fSelectionPass) {
glMaterialfv(GL_FRONT, GL_DIFFUSE, backColor);
if (fSelectedPlane == 1)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fRedEmission);
} else
EncodeToColor(selectionBase, 1);
RootGL::DrawQuadFilled(fFrame[0], fFrame[1], fFrame[2], fFrame[3], TGLVertex3(0., 0., 1.));
if (!fSelectionPass) {
if (fSelectedPlane == 1)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fNullEmission);
}
if (!fSelectionPass) {
if (fSelectedPlane == 2)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fGreenEmission);
} else
EncodeToColor(selectionBase, 2);
DrawBackPlane(fBackPairs[fFrontPoint][0]);
if (!fSelectionPass) {
if (fSelectedPlane == 2)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fNullEmission);
}
if (!fSelectionPass) {
glMaterialfv(GL_FRONT, GL_DIFFUSE, backColor);
if (fSelectedPlane == 3)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fGreenEmission);
} else
EncodeToColor(selectionBase, 3);
DrawBackPlane(fBackPairs[fFrontPoint][1]);
if (!fSelectionPass) {
if (fSelectedPlane == 3)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, fNullEmission);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
DrawProfiles();
}
void TGLLegoPainter::DrawBackPlane(Int_t plane)const
{
const Int_t *vertInd = fFramePlanes[plane];
TGLVertex3 normal(fFrameNormals[plane][0], fFrameNormals[plane][1], fFrameNormals[plane][2]);
RootGL::DrawQuadFilled(fFrame[vertInd[0]], fFrame[vertInd[1]], fFrame[vertInd[2]], fFrame[vertInd[3]], normal);
if (!fSelectionPass) {
using namespace RootGL;
TGLEnableGuard lineGuard(GL_LINE_SMOOTH);
TGLEnableGuard blendGuard(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
TGLDisableGuard depthGuard(GL_DEPTH_TEST);
TGLDisableGuard lightGuard(GL_LIGHTING);
glColor3d(0., 0., 0.);
DrawQuadOutline(fFrame[vertInd[0]], fFrame[vertInd[1]], fFrame[vertInd[2]], fFrame[vertInd[3]]);
DrawGrid(plane);
}
}
void TGLLegoPainter::DrawProfiles()
{
using namespace RootGL;
const Int_t selectionBase = fBinsX.second - fBinsX.first + 1;
if (fXOZProfilePos > fFrame[0].Y()) {
if (fXOZProfilePos > fFrame[2].Y())
fXOZProfilePos = fFrame[2].Y();
TGLDisableGuard cullGuard(GL_CULL_FACE);
TGLVertex3 v1(fFrame[0].X(), fXOZProfilePos, fFrame[0].Z());
TGLVertex3 v2(fFrame[1].X(), fXOZProfilePos, fFrame[1].Z());
TGLVertex3 v3(fFrame[5].X(), fXOZProfilePos, fFrame[5].Z());
TGLVertex3 v4(fFrame[4].X(), fXOZProfilePos, fFrame[4].Z());
if (fSelectionPass) {
EncodeToColor(selectionBase, 4);
} else {
glDisable(GL_LIGHTING);
if (fSelectedPlane == 4) {
TGLEnableGuard blendGuard(GL_BLEND);
TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(3.f);
glColor3d(0., 0.6, 1.);
DrawQuadOutline(v1, v2, v3, v4);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(1.f);
}
glColor3d(0.6, 0.6, 0.6);
}
RootGL::DrawQuadFilled(v1, v2, v3, v4, TGLVertex3(0., 1., 0.));
TGLDisableGuard depth(GL_DEPTH_TEST);
DrawProfileX();
if (!fSelectionPass)
glEnable(GL_LIGHTING);
}
if (fYOZProfilePos > fFrame[0].X()) {
if (fYOZProfilePos > fFrame[1].X())
fYOZProfilePos = fFrame[1].X();
TGLDisableGuard cullGuard(GL_CULL_FACE);
TGLVertex3 v1(fYOZProfilePos, fFrame[0].Y(), fFrame[0].Z());
TGLVertex3 v2(fYOZProfilePos, fFrame[3].Y(), fFrame[3].Z());
TGLVertex3 v3(fYOZProfilePos, fFrame[7].Y(), fFrame[7].Z());
TGLVertex3 v4(fYOZProfilePos, fFrame[4].Y(), fFrame[4].Z());
if (fSelectionPass) {
EncodeToColor(selectionBase, 5);
} else {
glDisable(GL_LIGHTING);
if (fSelectedPlane == 5) {
TGLEnableGuard blendGuard(GL_BLEND);
TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(3.f);
glColor3d(0., 0.6, 1.);
DrawQuadOutline(v1, v2, v3, v4);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLineWidth(1.f);
}
glColor3d(0.6, 0.6, 0.6);
}
RootGL::DrawQuadFilled(v1, v2, v3, v4, TGLVertex3(1., 0., 0.));
TGLDisableGuard depth(GL_DEPTH_TEST);
DrawProfileY();
if (!fSelectionPass)
glEnable(GL_LIGHTING);
}
}
void TGLLegoPainter::MoveDynamicProfile(Int_t px, Int_t py)
{
if (fSelectedPlane == 2) {
if (fFrontPoint == 2) {
fXOZProfilePos = fFrame[0].Y();
fSelectedPlane = 4;
} else if (!fFrontPoint) {
fXOZProfilePos = fFrame[2].Y();
fSelectedPlane = 4;
} else if (fFrontPoint == 1) {
fYOZProfilePos = fFrame[0].X();
fSelectedPlane = 5;
} else if (fFrontPoint == 3) {
fYOZProfilePos = fFrame[1].X();
fSelectedPlane = 5;
}
} else if (fSelectedPlane == 3) {
if (fFrontPoint == 2) {
fYOZProfilePos = fFrame[0].X();
fSelectedPlane = 5;
} else if (!fFrontPoint) {
fYOZProfilePos = fFrame[1].X();
fSelectedPlane = 5;
} else if (fFrontPoint == 1) {
fXOZProfilePos = fFrame[2].Y();
fSelectedPlane = 4;
} else if (fFrontPoint == 3) {
fXOZProfilePos = fFrame[0].Y();
fSelectedPlane = 4;
}
}
Double_t mvMatrix[16] = {0.};
glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix);
Double_t prMatrix[16] = {0.};
glGetDoublev(GL_PROJECTION_MATRIX, prMatrix);
Double_t winVertex[3] = {0.};
gluProject(
fSelectedPlane == 5 ? fYOZProfilePos : 0.,
fSelectedPlane == 4 ? fXOZProfilePos : 0.,
0., mvMatrix, prMatrix, fViewport,
&winVertex[0], &winVertex[1], &winVertex[2]
);
winVertex[0] += px - fMousePosition.fX;
winVertex[1] += py - fMousePosition.fY;
Double_t newPoint[3] = {0.};
gluUnProject(winVertex[0], winVertex[1], winVertex[2], mvMatrix, prMatrix, fViewport,
newPoint, newPoint + 1, newPoint + 2);
if (fSelectedPlane == 4)
fXOZProfilePos = newPoint[1];
else
fYOZProfilePos = newPoint[0];
}
void TGLLegoPainter::DrawProfileX()
{
const Int_t nX = fBinsX.second - fBinsX.first + 1;
const Int_t nY = fBinsY.second - fBinsY.first + 1;
Int_t binY = -1;
for (Int_t i = 0; i < nY; ++i)
if (fYEdges[i].first <= fXOZProfilePos && fXOZProfilePos <= fYEdges[i].second) {
binY = i;
break;
}
if (binY >= 0) {
binY += fBinsY.first;
RootGL::TGLEnableGuard blendGuard(GL_BLEND);
RootGL::TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glPushAttrib(GL_LINE_BIT);
glEnable(GL_LINE_STIPPLE);
const UShort_t stipple = 0x5555;
glLineStipple(1, stipple);
glColor3d(0., 0., 0.);
for (UInt_t i = 0; i < fZLevels.size(); ++i) {
glBegin(GL_LINES);
glVertex3d(fFrame[0].X(), fXOZProfilePos, fZLevels[i] * fScaleZ);
glVertex3d(fFrame[1].X(), fXOZProfilePos, fZLevels[i] * fScaleZ);
glEnd();
}
glDisable(GL_LINE_STIPPLE);
glPopAttrib();
glColor3d(1., 0., 0.);
glLineWidth(3.f);
for (Int_t i = 0, ir = fBinsX.first; i < nX; ++i, ++ir) {
Double_t zMax = fHist->GetBinContent(ir, binY);
if (!ClampZ(zMax))
continue;
glBegin(GL_LINE_LOOP);
glVertex3d(fXEdges[i].first, fXOZProfilePos, fMinZ);
glVertex3d(fXEdges[i].first, fXOZProfilePos, zMax);
glVertex3d(fXEdges[i].second, fXOZProfilePos, zMax);
glVertex3d(fXEdges[i].second, fXOZProfilePos, fMinZ);
glEnd();
}
glLineWidth(1.f);
}
}
void TGLLegoPainter::DrawProfileY()
{
const Int_t nX = fBinsX.second - fBinsX.first + 1;
const Int_t nY = fBinsY.second - fBinsY.first + 1;
Int_t binX = -1;
for (Int_t i = 0; i < nX; ++i)
if (fXEdges[i].first <= fYOZProfilePos && fYOZProfilePos <= fXEdges[i].second) {
binX = i;
break;
}
if (binX >= 0) {
binX += fBinsX.first;
RootGL::TGLEnableGuard blendGuard(GL_BLEND);
RootGL::TGLEnableGuard lineSmooth(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glPushAttrib(GL_LINE_BIT);
glEnable(GL_LINE_STIPPLE);
const UShort_t stipple = 0x5555;
glLineStipple(1, stipple);
glColor3d(0., 0., 0.);
for (UInt_t i = 0; i < fZLevels.size(); ++i) {
glBegin(GL_LINES);
glVertex3d(fYOZProfilePos, fFrame[0].Y(), fZLevels[i] * fScaleZ);
glVertex3d(fYOZProfilePos, fFrame[2].Y(), fZLevels[i] * fScaleZ);
glEnd();
}
glDisable(GL_LINE_STIPPLE);
glPopAttrib();
glColor3d(1., 0., 0.);
glLineWidth(3.f);
for (Int_t i = 0, ir = fBinsY.first; i < nY; ++i, ++ir) {
Double_t zMax = fHist->GetBinContent(binX, ir);
if (!ClampZ(zMax))
continue;
glBegin(GL_LINE_LOOP);
glVertex3d(fYOZProfilePos, fYEdges[i].first, fMinZ);
glVertex3d(fYOZProfilePos, fYEdges[i].first, zMax);
glVertex3d(fYOZProfilePos, fYEdges[i].second, zMax);
glVertex3d(fYOZProfilePos, fYEdges[i].second, fMinZ);
glEnd();
}
glLineWidth(1.f);
}
}
void TGLLegoPainter::ProcessEvent(Int_t event, Int_t, Int_t)
{
if (event == kButton1Double && (fXOZProfilePos > fFrame[0].Y() || fYOZProfilePos > fFrame[0].X())) {
fXOZProfilePos = fFrame[0].Y();
fYOZProfilePos = fFrame[0].X();
gGLManager->PaintSingleObject(this);
}
}
Bool_t TGLLegoPainter::ClampZ(Double_t &zVal)const
{
if (fLogZ)
if (zVal <= 0.)
return kFALSE;
else
zVal = TMath::Log10(zVal) * fScaleZ;
else
zVal *= fScaleZ;
if (zVal > fFrame[4].Z())
zVal = fFrame[4].Z();
else if (zVal < fFrame[0].Z())
zVal = fFrame[0].Z();
return kTRUE;
}
void TGLLegoPainter::Enable1DTexture()
{
glEnable(GL_TEXTURE_1D);
if (!glIsTexture(fTextureName)) {
glGenTextures(1, &fTextureName);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_1D, fTextureName);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, fTexture.size() / 4, 0,
GL_RGBA, GL_UNSIGNED_BYTE, &fTexture[0]);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
void TGLLegoPainter::Disable1DTexture()
{
glDisable(GL_TEXTURE_1D);
glDeleteTextures(1, &fTextureName);
}
void TGLLegoPainter::DrawGrid(Int_t plane)const
{
glPushAttrib(GL_LINE_BIT);
RootGL::TGLEnableGuard stippleGuard(GL_LINE_STIPPLE);
const UShort_t stipple = 0x5555;
glLineStipple(1, stipple);
Double_t lineCaps[][4] = {
{fFrame[0].X(), fFrame[0].Y(), fFrame[1].X(), fFrame[1].Y()},
{fFrame[1].X(), fFrame[1].Y(), fFrame[2].X(), fFrame[2].Y()},
{fFrame[2].X(), fFrame[2].Y(), fFrame[3].X(), fFrame[3].Y()},
{fFrame[0].X(), fFrame[0].Y(), fFrame[3].X(), fFrame[3].Y()}
};
for (UInt_t i = 0; i < fZLevels.size(); ++i) {
glBegin(GL_LINES);
glVertex3d(lineCaps[plane][0], lineCaps[plane][1], fZLevels[i] * fScaleZ);
glVertex3d(lineCaps[plane][2], lineCaps[plane][3], fZLevels[i] * fScaleZ);
glEnd();
}
glPopAttrib();
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.