#include <algorithm>
#include "TColor.h"
#include "TGLIncludes.h"
#include "TGLPlotBox.h"
ClassImp(TGLPlotBox)
const Int_t TGLPlotBox::fgFramePlanes[][4] =
{
{0, 4, 5, 1},
{1, 5, 6, 2},
{2, 6, 7, 3},
{0, 3, 7, 4},
{0, 1, 2, 3}
};
const Double_t TGLPlotBox::fgNormals[][3] =
{
{ 0., 1., 0.},
{-1., 0., 0.},
{ 0.,-1., 0.},
{ 1., 0., 0.},
{ 0., 0., 1.}
};
const Int_t TGLPlotBox::fgBackPairs[][2] =
{
{2, 1},
{3, 2},
{0, 3},
{1, 0}
};
const Int_t TGLPlotBox::fgFrontPairs[][2] =
{
{3, 0},
{0, 1},
{1, 2},
{2, 3}
};
TGLPlotBox::TGLPlotBox(Bool_t xoy, Bool_t xoz, Bool_t yoz)
: fFrameColor(0),
fXOYSelectable(xoy),
fXOZSelectable(xoz),
fYOZSelectable(yoz),
fSelectablePairs(),
fFrontPoint(0),
fRangeXU(1.),
fRangeYU(1.),
fRangeZU(1.),
fDrawBack(kTRUE),
fDrawFront(kTRUE)
{
fSelectablePairs[0][0] = xoz;
fSelectablePairs[0][1] = yoz;
fSelectablePairs[1][0] = yoz;
fSelectablePairs[1][1] = xoz;
fSelectablePairs[2][0] = xoz;
fSelectablePairs[2][1] = yoz;
fSelectablePairs[3][0] = yoz;
fSelectablePairs[3][1] = xoz;
}
TGLPlotBox::~TGLPlotBox()
{
}
void TGLPlotBox::DrawBack(Int_t selected, Bool_t selectionPass, const std::vector<Double_t> &zLevels,
Bool_t highColor)const
{
using namespace Rgl;
TGLDisableGuard depthTest(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
if (!selectionPass) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_LINE_SMOOTH);
}
Float_t backColor[] = {0.9f, 0.9f, 0.9f, 0.85f};
if (fFrameColor)
fFrameColor->GetRGB(backColor[0], backColor[1], backColor[2]);
if (!selectionPass) {
glMaterialfv(GL_FRONT, GL_DIFFUSE, backColor);
if (selected == 1) {
fXOYSelectable ?
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gGreenEmission)
:
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gRedEmission);
}
} else
ObjectIDToColor(1, highColor);
DrawQuadFilled(f3DBox[0], f3DBox[1], f3DBox[2], f3DBox[3], TGLVector3(0., 0., 1.));
if (!selectionPass) {
if (selected == 1)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
else if (selected == 2)
fSelectablePairs[fFrontPoint][0] ? glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gGreenEmission)
: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gRedEmission);
} else
ObjectIDToColor(2, highColor);
DrawBackPlane(fgBackPairs[fFrontPoint][0], selectionPass, zLevels);
if (!selectionPass) {
if (selected == 2)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
else if (selected == 3)
fSelectablePairs[fFrontPoint][1] ? glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gGreenEmission)
: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gRedEmission);
} else
ObjectIDToColor(3, highColor);
DrawBackPlane(fgBackPairs[fFrontPoint][1], selectionPass, zLevels);
glDepthMask(GL_TRUE);
if (!selectionPass) {
if (selected == 3)
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, Rgl::gNullEmission);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
}
void TGLPlotBox::DrawFront()const
{
using namespace Rgl;
const TGLDisableGuard lightGuard(GL_LIGHTING);
glColor3d(0., 0., 0.);
const Int_t *vertInd = fgFramePlanes[fgFrontPairs[fFrontPoint][0]];
DrawQuadOutline(f3DBox[vertInd[0]], f3DBox[vertInd[1]], f3DBox[vertInd[2]], f3DBox[vertInd[3]]);
vertInd = fgFramePlanes[fgFrontPairs[fFrontPoint][1]];
DrawQuadOutline(f3DBox[vertInd[0]], f3DBox[vertInd[1]], f3DBox[vertInd[2]], f3DBox[vertInd[3]]);
}
void TGLPlotBox::DrawBox(Int_t selected, Bool_t selectionPass, const std::vector<Double_t> &zLevels,
Bool_t highColor)const
{
if (fDrawBack)
DrawBack(selected, selectionPass, zLevels, highColor);
if (fDrawFront && !selectionPass)
DrawFront();
}
void TGLPlotBox::SetPlotBox(const Rgl::Range_t &x, const Rgl::Range_t &y, const Rgl::Range_t &z)
{
f3DBox[0].Set(x.first, y.first, z.first);
f3DBox[1].Set(x.second, y.first, z.first);
f3DBox[2].Set(x.second, y.second, z.first);
f3DBox[3].Set(x.first, y.second, z.first);
f3DBox[4].Set(x.first, y.first, z.second);
f3DBox[5].Set(x.second, y.first, z.second);
f3DBox[6].Set(x.second, y.second, z.second);
f3DBox[7].Set(x.first, y.second, z.second);
}
void TGLPlotBox::SetPlotBox(const Rgl::Range_t &x, Double_t xr, const Rgl::Range_t &y, Double_t yr,
const Rgl::Range_t &z, Double_t zr)
{
fRangeXU = xr;
fRangeYU = yr;
fRangeZU = zr;
SetPlotBox(x, y, z);
}
void TGLPlotBox::SetFrameColor(const TColor *color)
{
fFrameColor = color;
}
namespace {
bool Compare(const TGLVertex3 &v1, const TGLVertex3 &v2)
{
return v1.Z() < v2.Z();
}
}
Int_t TGLPlotBox::FindFrontPoint()const
{
Double_t mvMatrix[16] = {0.};
glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix);
Double_t prMatrix[16] = {0.};
glGetDoublev(GL_PROJECTION_MATRIX, prMatrix);
Int_t viewport[4] = {0};
glGetIntegerv(GL_VIEWPORT, viewport);
const Double_t zMin = f3DBox[0].Z();
const Double_t zMax = f3DBox[4].Z();
const Double_t uBox[][2] = {{-fRangeXU / 2., -fRangeYU / 2.},
{ fRangeXU / 2., -fRangeYU / 2.},
{ fRangeXU / 2., fRangeYU / 2.},
{-fRangeXU / 2., fRangeYU / 2.}};
for (Int_t i = 0; i < 4; ++i) {
gluProject(f3DBox[i].X(), f3DBox[i].Y(), zMin, mvMatrix, prMatrix, viewport,
&f2DBox[i].X(), &f2DBox[i].Y(), &f2DBox[i].Z());
gluProject(f3DBox[i].X(), f3DBox[i].Y(), zMax, mvMatrix, prMatrix, viewport,
&f2DBox[i + 4].X(), &f2DBox[i + 4].Y(), &f2DBox[i + 4].Z());
gluProject(uBox[i][0], uBox[i][1], -0.5, mvMatrix, prMatrix, viewport,
&f2DBoxU[i].X(), &f2DBoxU[i].Y(), &f2DBoxU[i].Z());
gluProject(uBox[i][0], uBox[i][1], 0.5, mvMatrix, prMatrix, viewport,
&f2DBoxU[i + 4].X(), &f2DBoxU[i + 4].Y(), &f2DBoxU[i + 4].Z());
}
TGLUtil::InitializeIfNeeded();
const Float_t scale = TGLUtil::GetScreenScalingFactor();
if (scale) {
for (Int_t i = 0; i < 8; ++i) {
f2DBoxU[i].X() /= scale;
f2DBoxU[i].Y() /= scale;
}
}
return fFrontPoint = std::min_element(f2DBoxU, f2DBoxU + 4, Compare) - f2DBoxU;
}
Int_t TGLPlotBox::GetFrontPoint()const
{
return fFrontPoint;
}
const TGLVertex3 *TGLPlotBox::Get3DBox()const
{
return f3DBox;
}
const TGLVertex3 *TGLPlotBox::Get2DBox()const
{
return f2DBoxU;
}
void TGLPlotBox::DrawBackPlane(Int_t plane, Bool_t selectionPass,
const std::vector<Double_t> &zLevels)const
{
using namespace Rgl;
const Int_t *vertInd = fgFramePlanes[plane];
DrawQuadFilled(f3DBox[vertInd[0]], f3DBox[vertInd[1]], f3DBox[vertInd[2]],
f3DBox[vertInd[3]], fgNormals[plane]);
if (!selectionPass) {
const TGLDisableGuard lightGuard(GL_LIGHTING);
glColor3d(0., 0., 0.);
DrawQuadOutline(f3DBox[vertInd[0]], f3DBox[vertInd[1]],
f3DBox[vertInd[2]], f3DBox[vertInd[3]]);
const TGLEnableGuard stippleGuard(GL_LINE_STIPPLE);
const UShort_t stipple = 0x5555;
glLineStipple(1, stipple);
Double_t lineCaps[][4] =
{
{f3DBox[1].X(), f3DBox[0].Y(), f3DBox[0].X(), f3DBox[0].Y()},
{f3DBox[1].X(), f3DBox[0].Y(), f3DBox[1].X(), f3DBox[2].Y()},
{f3DBox[1].X(), f3DBox[2].Y(), f3DBox[0].X(), f3DBox[3].Y()},
{f3DBox[0].X(), f3DBox[3].Y(), f3DBox[0].X(), f3DBox[0].Y()}
};
for (UInt_t i = 0; i < zLevels.size(); ++i) {
glBegin(GL_LINES);
glVertex3d(lineCaps[plane][0], lineCaps[plane][1], zLevels[i]);
glVertex3d(lineCaps[plane][2], lineCaps[plane][3], zLevels[i]);
glEnd();
}
}
}