#include "TMath.h"
#include "TEveQuadSetGL.h"
#include "TGLRnrCtx.h"
#include "TGLIncludes.h"
ClassImp(TEveQuadSetGL);
TEveQuadSetGL::TEveQuadSetGL() : TEveDigitSetGL(), fM(0)
{
fMultiColor = kTRUE;
}
Bool_t TEveQuadSetGL::SetModel(TObject* obj, const Option_t* )
{
fM = SetModelDynCast<TEveQuadSet>(obj);
return kTRUE;
}
namespace
{
inline void AntiFlick(Float_t x, Float_t y, Float_t z)
{
glBegin(GL_POINTS);
glVertex3f(x, y, z);
glEnd();
}
}
void TEveQuadSetGL::DirectDraw(TGLRnrCtx & rnrCtx) const
{
static const TEveException eH("TEveQuadSetGL::DirectDraw ");
TEveQuadSet& mQ = * fM;
if (mQ.fPlex.Size() > 0)
{
if (! mQ.fSingleColor && ! mQ.fValueIsColor && mQ.fPalette == 0)
{
mQ.AssertPalette();
}
glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glDisable(GL_CULL_FACE);
if ( ! rnrCtx.IsDrawPassOutlineLine())
{
if (mQ.fRenderMode == TEveDigitSet::kRM_Fill)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
else if (mQ.fRenderMode == TEveDigitSet::kRM_Line)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
if (mQ.fDisableLighting) glDisable(GL_LIGHTING);
if (mQ.fQuadType < TEveQuadSet::kQT_Rectangle_End) RenderQuads(rnrCtx);
else if (mQ.fQuadType < TEveQuadSet::kQT_Line_End) RenderLines(rnrCtx);
else if (mQ.fQuadType < TEveQuadSet::kQT_Hexagon_End) RenderHexagons(rnrCtx);
glPopAttrib();
}
DrawFrameIfNeeded(rnrCtx);
}
void TEveQuadSetGL::RenderQuads(TGLRnrCtx& rnrCtx) const
{
static const TEveException eH("TEveQuadSetGL::RenderQuads ");
TEveQuadSet& mQ = * fM;
GLenum primitiveType;
if (mQ.fRenderMode != TEveDigitSet::kRM_Line)
{
primitiveType = GL_QUADS;
if (mQ.fQuadType == TEveQuadSet::kQT_FreeQuad)
glEnable(GL_NORMALIZE);
else
glNormal3f(0, 0, 1);
} else {
primitiveType = GL_LINE_LOOP;
}
TEveChunkManager::iterator qi(mQ.fPlex);
if (rnrCtx.Highlight() && fHighlightSet)
qi.fSelection = fHighlightSet;
if (rnrCtx.SecSelection()) glPushName(0);
switch (mQ.fQuadType)
{
case TEveQuadSet::kQT_FreeQuad:
{
Float_t e1[3], e2[3], normal[3];
while (qi.next()) {
TEveQuadSet::QFreeQuad_t& q = * (TEveQuadSet::QFreeQuad_t*) qi();
if (SetupColor(q))
{
Float_t* p = q.fVertices;
e1[0] = p[3] - p[0]; e1[1] = p[4] - p[1]; e1[2] = p[5] - p[2];
e2[0] = p[6] - p[0]; e2[1] = p[7] - p[1]; e2[2] = p[8] - p[2];
TMath::Cross(e1, e2, normal);
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glNormal3fv(normal);
glVertex3fv(p);
glVertex3fv(p + 3);
glVertex3fv(p + 6);
glVertex3fv(p + 9);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(0.5f*(p[0]+p[6]), 0.5f*(p[1]+p[7]), 0.5f*(p[2]+p[8]));
}
}
break;
}
case TEveQuadSet::kQT_RectangleXY:
{
while (qi.next()) {
TEveQuadSet::QRect_t& q = * (TEveQuadSet::QRect_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, q.fB, q.fC);
glVertex3f(q.fA + q.fW, q.fB, q.fC);
glVertex3f(q.fA + q.fW, q.fB + q.fH, q.fC);
glVertex3f(q.fA, q.fB + q.fH, q.fC);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*q.fW, q.fB + 0.5f*q.fH, q.fC);
}
}
break;
}
case TEveQuadSet::kQT_RectangleXZ:
{
while (qi.next()) {
TEveQuadSet::QRect_t& q = * (TEveQuadSet::QRect_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, q.fC, q.fB);
glVertex3f(q.fA + q.fW, q.fC, q.fB);
glVertex3f(q.fA + q.fW, q.fC, q.fB + q.fH);
glVertex3f(q.fA, q.fC, q.fB + q.fH);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*q.fW, q.fC, q.fB + 0.5f*q.fH);
}
}
break;
}
case TEveQuadSet::kQT_RectangleYZ:
{
while (qi.next()) {
TEveQuadSet::QRect_t& q = * (TEveQuadSet::QRect_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fC, q.fA, q.fB);
glVertex3f(q.fC, q.fA + q.fW, q.fB);
glVertex3f(q.fC, q.fA + q.fW, q.fB + q.fH);
glVertex3f(q.fC, q.fA, q.fB + q.fH);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fC, q.fA + 0.5f*q.fW, q.fB + 0.5f*q.fH);
}
}
break;
}
case TEveQuadSet::kQT_RectangleXYFixedDim:
{
const Float_t& w = mQ.fDefWidth;
const Float_t& h = mQ.fDefHeight;
while (qi.next()) {
TEveQuadSet::QRectFixDim_t& q = * (TEveQuadSet::QRectFixDim_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, q.fB, q.fC);
glVertex3f(q.fA + w, q.fB, q.fC);
glVertex3f(q.fA + w, q.fB + h, q.fC);
glVertex3f(q.fA, q.fB + h, q.fC);
glEnd();
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*w, q.fB + 0.5f*h, q.fC);
}
}
break;
}
case TEveQuadSet::kQT_RectangleXYFixedZ:
{
const Float_t& z = mQ.fDefCoord;
while (qi.next()) {
TEveQuadSet::QRectFixC_t& q = * (TEveQuadSet::QRectFixC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, q.fB, z);
glVertex3f(q.fA + q.fW, q.fB, z);
glVertex3f(q.fA + q.fW, q.fB + q.fH, z);
glVertex3f(q.fA, q.fB + q.fH, z);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*q.fW, q.fB + 0.5f*q.fH, z);
}
}
break;
}
case TEveQuadSet::kQT_RectangleXZFixedY:
{
const Float_t& y = mQ.fDefCoord;
while (qi.next()) {
TEveQuadSet::QRectFixC_t& q = * (TEveQuadSet::QRectFixC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, y, q.fB);
glVertex3f(q.fA + q.fW, y, q.fB);
glVertex3f(q.fA + q.fW, y, q.fB + q.fH);
glVertex3f(q.fA, y, q.fB + q.fH);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*q.fW, y, q.fB + 0.5f*q.fH);
}
}
break;
}
case TEveQuadSet::kQT_RectangleYZFixedX:
{
const Float_t& x = mQ.fDefCoord;
while (qi.next()) {
TEveQuadSet::QRectFixC_t& q = * (TEveQuadSet::QRectFixC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(x, q.fA, q.fB);
glVertex3f(x, q.fA + q.fW, q.fB);
glVertex3f(x, q.fA + q.fW, q.fB + q.fH);
glVertex3f(x, q.fA, q.fB + q.fH);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(x, q.fA + 0.5f*q.fW, q.fB + 0.5f*q.fH);
}
}
break;
}
case TEveQuadSet::kQT_RectangleXYFixedDimZ:
{
const Float_t& z = mQ.fDefCoord;
const Float_t& w = mQ.fDefWidth;
const Float_t& h = mQ.fDefHeight;
while (qi.next()) {
TEveQuadSet::QRectFixDimC_t& q = * (TEveQuadSet::QRectFixDimC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, q.fB, z);
glVertex3f(q.fA + w, q.fB, z);
glVertex3f(q.fA + w, q.fB + h, z);
glVertex3f(q.fA, q.fB + h, z);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*w, q.fB + 0.5f*h, z);
}
}
break;
}
case TEveQuadSet::kQT_RectangleXZFixedDimY:
{
const Float_t& y = mQ.fDefCoord;
const Float_t& w = mQ.fDefWidth;
const Float_t& h = mQ.fDefHeight;
while (qi.next()) {
TEveQuadSet::QRectFixDimC_t& q = * (TEveQuadSet::QRectFixDimC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(q.fA, y, q.fB);
glVertex3f(q.fA + w, y, q.fB);
glVertex3f(q.fA + w, y, q.fB + h);
glVertex3f(q.fA, y, q.fB + h);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA + 0.5f*w, y, q.fB + 0.5f*h);
}
}
break;
}
case TEveQuadSet::kQT_RectangleYZFixedDimX:
{
const Float_t& x = mQ.fDefCoord;
const Float_t& w = mQ.fDefWidth;
const Float_t& h = mQ.fDefHeight;
while (qi.next()) {
TEveQuadSet::QRectFixDimC_t& q = * (TEveQuadSet::QRectFixDimC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitiveType);
glVertex3f(x, q.fA, q.fB);
glVertex3f(x, q.fA + w, q.fB);
glVertex3f(x, q.fA + w, q.fB + h);
glVertex3f(x, q.fA, q.fB + h);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(x, q.fA + 0.5f*w, q.fB + 0.5f*h);
}
}
break;
}
default:
throw(eH + "unsupported quad-type.");
}
if (rnrCtx.SecSelection()) glPopName();
}
void TEveQuadSetGL::RenderLines(TGLRnrCtx & rnrCtx) const
{
static const TEveException eH("TEveQuadSetGL::RenderLines ");
TEveQuadSet& mQ = * fM;
TEveChunkManager::iterator qi(mQ.fPlex);
if (rnrCtx.Highlight() && fHighlightSet)
qi.fSelection = fHighlightSet;
if (rnrCtx.SecSelection()) glPushName(0);
switch (mQ.fQuadType)
{
case TEveQuadSet::kQT_LineXYFixedZ:
{
const Float_t& z = mQ.fDefCoord;
while (qi.next()) {
TEveQuadSet::QLineFixC_t& q = * (TEveQuadSet::QLineFixC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(GL_LINES);
glVertex3f(q.fA, q.fB, z);
glVertex3f(q.fA + q.fDx, q.fB + q.fDy, z);
glEnd();
}
}
break;
}
case TEveQuadSet::kQT_LineXZFixedY:
{
const Float_t& z = mQ.fDefCoord;
while (qi.next()) {
TEveQuadSet::QLineFixC_t& q = * (TEveQuadSet::QLineFixC_t*) qi();
if (SetupColor(q))
{
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(GL_LINES);
glVertex3f(q.fA, z, q.fB);
glVertex3f(q.fA + q.fDx, z, q.fB + q.fDy);
glEnd();
}
}
break;
}
default:
throw(eH + "unsupported quad-type.");
}
if (rnrCtx.SecSelection()) glPopName();
}
void TEveQuadSetGL::RenderHexagons(TGLRnrCtx & rnrCtx) const
{
static const TEveException eH("TEveQuadSetGL::RenderHexagons ");
const Float_t sqr3hf = 0.5*TMath::Sqrt(3);
TEveQuadSet& mQ = * fM;
GLenum primitveType = (mQ.fRenderMode != TEveDigitSet::kRM_Line) ?
GL_POLYGON : GL_LINE_LOOP;
glNormal3f(0, 0, 1);
TEveChunkManager::iterator qi(mQ.fPlex);
if (rnrCtx.Highlight() && fHighlightSet)
qi.fSelection = fHighlightSet;
if (rnrCtx.SecSelection()) glPushName(0);
switch (mQ.fQuadType)
{
case TEveQuadSet::kQT_HexagonXY:
{
while (qi.next()) {
TEveQuadSet::QHex_t& q = * (TEveQuadSet::QHex_t*) qi();
if (SetupColor(q))
{
const Float_t rh = q.fR * 0.5;
const Float_t rs = q.fR * sqr3hf;
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitveType);
glVertex3f( q.fR + q.fA, q.fB, q.fC);
glVertex3f( rh + q.fA, rs + q.fB, q.fC);
glVertex3f( -rh + q.fA, rs + q.fB, q.fC);
glVertex3f(-q.fR + q.fA, q.fB, q.fC);
glVertex3f( -rh + q.fA, -rs + q.fB, q.fC);
glVertex3f( rh + q.fA, -rs + q.fB, q.fC);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA, q.fB, q.fC);
}
}
break;
}
case TEveQuadSet::kQT_HexagonYX:
{
while (qi.next()) {
TEveQuadSet::QHex_t& q = * (TEveQuadSet::QHex_t*) qi();
if (SetupColor(q))
{
const Float_t rh = q.fR * 0.5;
const Float_t rs = q.fR * sqr3hf;
if (rnrCtx.SecSelection()) glLoadName(qi.index());
glBegin(primitveType);
glVertex3f( rs + q.fA, rh + q.fB, q.fC);
glVertex3f( q.fA, q.fR + q.fB, q.fC);
glVertex3f(-rs + q.fA, rh + q.fB, q.fC);
glVertex3f(-rs + q.fA, -rh + q.fB, q.fC);
glVertex3f( q.fA, -q.fR + q.fB, q.fC);
glVertex3f( rs + q.fA, -rh + q.fB, q.fC);
glEnd();
if (mQ.fAntiFlick)
AntiFlick(q.fA, q.fB, q.fC);
}
}
break;
}
default:
throw(eH + "unsupported quad-type.");
}
if (rnrCtx.SecSelection()) glPopName();
}