ROOT logo
// @(#)root/gl:$Id: TGLParametric.cxx 30298 2009-09-19 13:07:06Z matevz $
// Author:  Timur Pocheptsov  26/01/2007

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include <iostream>
#include <cctype>

#ifdef WIN32
#define NOMINMAX
#endif

#include "TVirtualX.h"
#include "TString.h"
#include "TROOT.h"

#include "TGLPlotCamera.h"
#include "TGLParametric.h"
#include "TGLIncludes.h"
#include "TVirtualPad.h"
#include "KeySymbols.h"
#include "Buttons.h"
#include "TString.h"
#include "TColor.h"
#include "TMath.h"

//______________________________________________________________________________
//
// A parametric surface is a surface defined by a parametric equation, involving
// two parameters (u, v):
//
// S(u, v) = (x(u, v), y(u, v), z(u, v)).
// For example, "limpet torus" surface can be defined as:
//    x = cos(u) / (sqrt(2) + sin(v))
//    y = sin(u) / (sqrt(2) + sin(v))
//    z = 1 / (sqrt(2) + cos(v)),
// where -pi <= u <= pi, -pi <= v <= pi.
//
//
// TGLParametricEquation * eq =
//    new TGLParametricEquation("Limpet_torus", "cos(u) / (sqrt(2.) + sin(v))",
//                              "sin(u) / (sqrt(2.) + sin(v))",
//                              "1 / (sqrt(2) + cos(v))");
//
// $ROOTSYS/tutorials/gl/glparametric.C contains more examples.
//
// Parametric equations can be specified:
//    1. by string expressions, as with TF2, but with 'u' instead of 'x' and
//       'v' instead of 'y'.
//    2. by function - see ParametricEquation_t declaration.

namespace
{

   //______________________________________________________________________________
   void ReplaceUVNames(TString &equation)
   {
      //User defines equations using names 'u' and 'v' for
      //parameters. But TF2 works with 'x' and 'y'. So,
      //find 'u' and 'v' (which are not parts of other names)
      //and replace them with 'x' and 'y' correspondingly.
      using namespace std;
      const Ssiz_t len = equation.Length();
      //TF2 requires 'y' in formula.
      //'v' <=> 'y', so if none 'v' was found, I'll append "+0*y" to the equation.
      Int_t vFound = 0;

      for (Ssiz_t i = 0; i < len;) {
         const char c = equation[i];
         if (!isalpha(c)) {
            ++i;
            continue;
         } else{
            ++i;
            if (c == 'u' || c == 'v') {
               //1. This 'u' or 'v' is the last symbol in a string or
               //2. After this 'u' or 'v' symbol, which cannot be part of longer name.
               if (i == len || (!isalpha(equation[i]) && !isdigit(equation[i]) && equation[i] != '_')) {
                  //Replace 'u' with 'x' or 'v' with 'y'.
                  equation[i - 1] = c == 'u' ? 'x' : (++vFound, 'y');
               } else {
                  //This 'u' or 'v' is the beginning of some longer name.
                  //Skip the remaining part of this name.
                  while (i < len && (isalpha(equation[i]) || isdigit(equation[i]) || equation[i] == '_'))
                     ++i;
               }
            } else {
               while (i < len && (isalpha(equation[i]) || isdigit(equation[i]) || equation[i] == '_'))
                  ++i;
            }
         }
      }

      if (!vFound)
         equation += "+0*y";
   }

}

ClassImp(TGLParametricEquation)

//______________________________________________________________________________
TGLParametricEquation::TGLParametricEquation(const TString &name, const TString &xFun, const TString &yFun,
                             const TString &zFun, Double_t uMin, Double_t uMax,
                             Double_t vMin, Double_t vMax)
                  : TNamed(name, name),
                    fEquation(0),
                    fURange(uMin, uMax),
                    fVRange(vMin, vMax),
                    fConstrained(kFALSE),
                    fModified(kFALSE)
{
   //Surface is defined by three strings.
   //ROOT does not use exceptions in ctors,
   //so, I have to use MakeZombie to let
   //external user know about errors.
   if (!xFun.Length() || !yFun.Length() || !zFun.Length()) {
      Error("TGLParametricEquation", "One of string expressions iz empty");
      MakeZombie();
      return;
   }

   TString equation(xFun);
   equation.ToLower();
   ReplaceUVNames(equation);
   fXEquation.reset(new TF2(name + "xEquation", equation.Data(), uMin, uMax, vMin, vMax));
   //Formula was incorrect.
   if (fXEquation->IsZombie()) {
      MakeZombie();
      return;
   }

   equation = yFun;
   equation.ToLower();
   ReplaceUVNames(equation);
   fYEquation.reset(new TF2(name + "yEquation", equation.Data(), uMin, uMax, vMin, vMax));
   //Formula was incorrect.
   if (fYEquation->IsZombie()) {
      MakeZombie();
      return;
   }

   equation = zFun;
   equation.ToLower();
   ReplaceUVNames(equation);
   fZEquation.reset(new TF2(name + "zEquation", equation.Data(), uMin, uMax, vMin, vMax));
   //Formula was incorrect.
   if (fZEquation->IsZombie())
      MakeZombie();
}

//______________________________________________________________________________
TGLParametricEquation::TGLParametricEquation(const TString &name, ParametricEquation_t equation,
                             Double_t uMin, Double_t uMax, Double_t vMin, Double_t vMax)
                  : TNamed(name, name),
                    fEquation(equation),
                    fURange(uMin, uMax),
                    fVRange(vMin, vMax),
                    fConstrained(kFALSE),
                    fModified(kFALSE)
{
   //Surface defined by user's function (see ParametricEquation_t declaration in TGLParametricEquation.h)
   if (!fEquation) {
      Error("TGLParametricEquation", "Function ptr is null");
      MakeZombie();
   }
}

//______________________________________________________________________________
Rgl::Range_t TGLParametricEquation::GetURange()const
{
   //[uMin, uMax]
   return fURange;
}

//______________________________________________________________________________
Rgl::Range_t TGLParametricEquation::GetVRange()const
{
   //[vMin, vMax]
   return fVRange;
}

//______________________________________________________________________________
Bool_t TGLParametricEquation::IsConstrained()const
{
   //Check is constrained.
   return fConstrained;
}

//______________________________________________________________________________
void TGLParametricEquation::SetConstrained(Bool_t c)
{
   //Set constrained.
   fConstrained = c;
}

//______________________________________________________________________________
Bool_t TGLParametricEquation::IsModified()const
{
   //Something was changed in parametric equation (or constrained option was changed).
   return fModified;
}

//______________________________________________________________________________
void TGLParametricEquation::SetModified(Bool_t m)
{
   //Set modified.
   fModified = m;
}

//______________________________________________________________________________
void TGLParametricEquation::EvalVertex(TGLVertex3 &newVertex, Double_t u, Double_t v)const
{
   //Calculate vertex.
   if (fEquation)
      return fEquation(newVertex, u, v);

   if (IsZombie())
      return;

   newVertex.X() = fXEquation->Eval(u, v);
   newVertex.Y() = fYEquation->Eval(u, v);
   newVertex.Z() = fZEquation->Eval(u, v);
}

//______________________________________________________________________________
Int_t TGLParametricEquation::DistancetoPrimitive(Int_t px, Int_t py)
{
   //Check, if parametric surface is under cursor.
   if (fPainter.get())
      return fPainter->DistancetoPrimitive(px, py);
   return 9999;
}

//______________________________________________________________________________
void TGLParametricEquation::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
   //Pass event to painter.
   if (fPainter.get())
      return fPainter->ExecuteEvent(event, px, py);
}

//______________________________________________________________________________
char *TGLParametricEquation::GetObjectInfo(Int_t /*px*/, Int_t /*py*/) const
{
   //No object info yet.

   static char mess[] = { "parametric surface" };
   return mess;
}

//______________________________________________________________________________
void TGLParametricEquation::Paint(Option_t * /*option*/)
{
   //Delegate paint.
   if (!fPainter.get())
      fPainter.reset(new TGLHistPainter(this));
   fPainter->Paint("dummyoption");
}

ClassImp(TGLParametricPlot)

//______________________________________________________________________________
TGLParametricPlot::TGLParametricPlot(TGLParametricEquation *eq,
                                     TGLPlotCamera *camera)
                      : TGLPlotPainter(camera),
                        fMeshSize(90),
                        fShowMesh(kFALSE),
                        fColorScheme(4),
                        fEquation(eq)
{
   //Constructor.
   InitGeometry();
   InitColors();
}

//______________________________________________________________________________
Bool_t TGLParametricPlot::InitGeometry()
{
   //Build mesh. The surface is 'immutable':
   //the only reason to rebuild it - the change in size or
   //if one of equations contain reference to TF2 function, whose
   //parameters were changed.

   // const Bool_t constrained = kTRUE;//fEquation->IsConstrained();

   if (fMeshSize * fMeshSize != (Int_t)fMesh.size() || fEquation->IsModified()) {
      if (fEquation->IsZombie())
         return kFALSE;

      fEquation->SetModified(kFALSE);

      fMesh.resize(fMeshSize * fMeshSize);
      fMesh.SetRowLen(fMeshSize);

      const Rgl::Range_t uRange(fEquation->GetURange());
      const Rgl::Range_t vRange(fEquation->GetVRange());

      const Double_t dU = (uRange.second - uRange.first) / (fMeshSize - 1);
      const Double_t dV = (vRange.second - vRange.first) / (fMeshSize - 1);
      const Double_t dd = 0.001;
      Double_t u = uRange.first;

      TGLVertex3 min;
      fEquation->EvalVertex(min, uRange.first, vRange.first);
      TGLVertex3 max(min), newVert, v1, v2;
      using namespace TMath;

      for (Int_t i = 0; i < fMeshSize; ++i) {
         Double_t v = vRange.first;
         for (Int_t j = 0; j < fMeshSize; ++j) {
            fEquation->EvalVertex(newVert, u, v);
            min.X() = Min(min.X(), newVert.X());
            max.X() = Max(max.X(), newVert.X());
            min.Y() = Min(min.Y(), newVert.Y());
            max.Y() = Max(max.Y(), newVert.Y());
            min.Z() = Min(min.Z(), newVert.Z());
            max.Z() = Max(max.Z(), newVert.Z());

            fMesh[i][j].fPos = newVert;

            v += dV;
         }
         u += dU;
      }

      const Double_t xRange = max.X() - min.X(), yRange = max.Y() - min.Y(), zRange = max.Z() - min.Z();
      const Double_t xS = 1. / xRange, yS = 1. / yRange, zS = 1. / zRange;

      for (Int_t i = 0; i < fMeshSize; ++i) {
         for (Int_t j = 0; j < fMeshSize; ++j) {
            TGLVertex3 &ver = fMesh[i][j].fPos;
            ver.X() *= xS, ver.Y() *= yS, ver.Z() *= zS;
         }
      }

      if (!xRange || !yRange || !zRange) {
         Error("InitGeometry", "Zero axis range");
         return kFALSE;
      }

      u = uRange.first;
      for (Int_t i = 0; i < fMeshSize; ++i) {
         Double_t v = vRange.first;
         for (Int_t j = 0; j < fMeshSize; ++j) {
            TGLVertex3 &ver = fMesh[i][j].fPos;
            fEquation->EvalVertex(v1, u + dd, v);
            fEquation->EvalVertex(v2, u, v + dd);
            v1.X() *= xS, v1.Y() *= yS, v1.Z() *= zS;
            v2.X() *= xS, v2.Y() *= yS, v2.Z() *= zS;
            Normal2Plane(ver.CArr(), v1.CArr(), v2.CArr(), fMesh[i][j].fNormal.Arr());
            v += dV;
         }
         u += dU;
      }

      using Rgl::Range_t;
      fBackBox.SetPlotBox(Range_t(min.X() * xS, max.X() * xS),
                          Range_t(min.Y() * yS, max.Y() * yS),
                          Range_t(min.Z() * zS, max.Z() * zS));
      if (fCamera) fCamera->SetViewVolume(fBackBox.Get3DBox());
   }

   return kTRUE;
}

//______________________________________________________________________________
void TGLParametricPlot::StartPan(Int_t px, Int_t py)
{
   //User clicks right mouse button (in a pad).
   fMousePosition.fX = px;
   fMousePosition.fY = fCamera->GetHeight() - py;
   fCamera->StartPan(px, py);
   fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
}

//______________________________________________________________________________
void TGLParametricPlot::Pan(Int_t px, Int_t py)
{
   //User's moving mouse cursor, with middle mouse button pressed (for pad).
   //Calculate 3d shift related to 2d mouse movement.
   if (fSelectedPart) {
      SaveModelviewMatrix();
      SaveProjectionMatrix();
      
      fCamera->SetCamera();
      fCamera->Apply(fPadPhi, fPadTheta);
   
      if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
         fBoxCut.MoveBox(px, fCamera->GetHeight() - py, fSelectedPart);
      else
         fCamera->Pan(px, py);
         
      RestoreProjectionMatrix();
      RestoreModelviewMatrix();
   }

   fUpdateSelection = kTRUE;//
}

//______________________________________________________________________________
char *TGLParametricPlot::GetPlotInfo(Int_t /*px*/, Int_t /*py*/)
{
   //No object info yet.

   static char mess[] = { "parametric surface" };
   return mess;
}

//______________________________________________________________________________
void TGLParametricPlot::AddOption(const TString &/*option*/)
{
   //No additional options for parametric surfaces.
}

//______________________________________________________________________________
void TGLParametricPlot::ProcessEvent(Int_t event, Int_t /*px*/, Int_t py)
{
   //Change color/mesh size or switch on/off mesh/box cut.
   //Left double click - remove box cut.
   if (event == kButton1Double && fBoxCut.IsActive()) {
      fBoxCut.TurnOnOff();
      if (!gVirtualX->IsCmdThread())
         gROOT->ProcessLineFast(Form("((TGLPlotPainter *)0x%lx)->Paint()", this));
      else
         Paint();
   } else if (event == kKeyPress) {
      if (py == kKey_c || py == kKey_C) {
         if (fHighColor)
            Info("ProcessEvent", "Switch to true color to use box cut");
         else {
            fBoxCut.TurnOnOff();
            fUpdateSelection = kTRUE;
         }
      } else if (py == kKey_s || py == kKey_S) {
         fColorScheme == 20 ? fColorScheme = -1 : ++fColorScheme;
         InitColors();//color scheme was changed! recalculate vertices colors.
      } else if (py == kKey_w || py == kKey_W) {
         fShowMesh = !fShowMesh;
      } else if (py == kKey_l || py == kKey_L) {
         fMeshSize == kHigh ? fMeshSize = kLow : fMeshSize += 15;
         InitGeometry();
         InitColors();
      }
   }
}

//______________________________________________________________________________
void TGLParametricPlot::InitGL()const
{
   //Initialize gl state.
   glEnable(GL_DEPTH_TEST);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glDisable(GL_CULL_FACE);
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
}

//______________________________________________________________________________
void TGLParametricPlot::DeInitGL()const
{
   //Initialize gl state.
   glDisable(GL_DEPTH_TEST);
   glDisable(GL_LIGHTING);
   glDisable(GL_LIGHT0);
   glDisable(GL_CULL_FACE);
   glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
}

//______________________________________________________________________________
void TGLParametricPlot::DrawPlot()const
{
   //Draw parametric surface.

   //Shift plot to point of origin.
   const Rgl::PlotTranslation trGuard(this);

   if (!fSelectionPass) {
      SetSurfaceColor();
      if (fShowMesh) {
         glEnable(GL_POLYGON_OFFSET_FILL);
         glPolygonOffset(1.f, 1.f);
      }
   } else {
      Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
   }

   glBegin(GL_TRIANGLES);

   for (Int_t i = 0; i < fMeshSize - 1; ++i) {
      for (Int_t j = 0; j < fMeshSize - 1; ++j) {
         if (fBoxCut.IsActive()) {
            using TMath::Min;
            using TMath::Max;
            const Double_t xMin = Min(Min(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Min(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
            const Double_t xMax = Max(Max(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Max(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
            const Double_t yMin = Min(Min(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Min(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
            const Double_t yMax = Max(Max(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Max(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
            const Double_t zMin = Min(Min(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Min(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));
            const Double_t zMax = Max(Max(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Max(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));

            if (fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
               continue;
         }

         glNormal3dv(fMesh[i + 1][j + 1].fNormal.CArr());
         if(fColorScheme != -1)
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j + 1].fRGBA);
         glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());

         glNormal3dv(fMesh[i][j + 1].fNormal.CArr());
         if(fColorScheme != -1)
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j + 1].fRGBA);
         glVertex3dv(fMesh[i][j + 1].fPos.CArr());

         glNormal3dv(fMesh[i][j].fNormal.CArr());
         if(fColorScheme != -1)
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j].fRGBA);
         glVertex3dv(fMesh[i][j].fPos.CArr());

         glNormal3dv(fMesh[i + 1][j].fNormal.CArr());
         if(fColorScheme != -1)
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j].fRGBA);
         glVertex3dv(fMesh[i + 1][j].fPos.CArr());

         glNormal3dv(fMesh[i + 1][j + 1].fNormal.CArr());
         if(fColorScheme != -1)
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i + 1][j + 1].fRGBA);
         glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());

         glNormal3dv(fMesh[i][j].fNormal.CArr());
         if(fColorScheme != -1)
            glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, fMesh[i][j].fRGBA);
         glVertex3dv(fMesh[i][j].fPos.CArr());
      }
   }

   glEnd();

   if (!fSelectionPass && fShowMesh) {
      glDisable(GL_POLYGON_OFFSET_FILL);
      const TGLDisableGuard lightGuard(GL_LIGHTING);
      const TGLEnableGuard blendGuard(GL_BLEND);
      const TGLEnableGuard smoothGuard(GL_LINE_SMOOTH);

      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glColor4d(0., 0., 0., 0.5);
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

      for (Int_t i = 0; i < fMeshSize - 1; ++i) {
         for (Int_t j = 0; j < fMeshSize - 1; ++j) {
            if (fBoxCut.IsActive()) {
               using TMath::Min;
               using TMath::Max;
               const Double_t xMin = Min(Min(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Min(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
               const Double_t xMax = Max(Max(fMesh[i][j].fPos.X(), fMesh[i + 1][j].fPos.X()), Max(fMesh[i][j + 1].fPos.X(), fMesh[i + 1][j + 1].fPos.X()));
               const Double_t yMin = Min(Min(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Min(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
               const Double_t yMax = Max(Max(fMesh[i][j].fPos.Y(), fMesh[i + 1][j].fPos.Y()), Max(fMesh[i][j + 1].fPos.Y(), fMesh[i + 1][j + 1].fPos.Y()));
               const Double_t zMin = Min(Min(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Min(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));
               const Double_t zMax = Max(Max(fMesh[i][j].fPos.Z(), fMesh[i + 1][j].fPos.Z()), Max(fMesh[i][j + 1].fPos.Z(), fMesh[i + 1][j + 1].fPos.Z()));

               if (fBoxCut.IsInCut(xMin, xMax, yMin, yMax, zMin, zMax))
                  continue;
            }
            glBegin(GL_POLYGON);
            glVertex3dv(fMesh[i][j].fPos.CArr());
            glVertex3dv(fMesh[i][j + 1].fPos.CArr());
            glVertex3dv(fMesh[i + 1][j + 1].fPos.CArr());
            glVertex3dv(fMesh[i + 1][j].fPos.CArr());
            glEnd();
         }
      }

      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   }

   if (fBoxCut.IsActive())
      fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
}

//______________________________________________________________________________
void TGLParametricPlot::InitColors()
{
   //Calculate colors for vertices,
   //using one of 20 color themes.
   //-1 simple 'metal' surface.
   if (fColorScheme == -1)
      return;

   const Rgl::Range_t uRange(fEquation->GetURange());

   const Float_t dU = Float_t((uRange.second - uRange.first) / (fMeshSize - 1));
   Float_t u = Float_t(uRange.first);

   for (Int_t i = 0; i < fMeshSize; ++i) {
      for (Int_t j = 0; j < fMeshSize; ++j)
         Rgl::GetColor(u, uRange.first, uRange.second, fColorScheme, fMesh[i][j].fRGBA);
      u += dU;
   }
}

//______________________________________________________________________________
void TGLParametricPlot::DrawSectionXOZ()const
{
   //No such sections.
}

//______________________________________________________________________________
void TGLParametricPlot::DrawSectionYOZ()const
{
   //No such sections.
}

//______________________________________________________________________________
void TGLParametricPlot::DrawSectionXOY()const
{
   //No such sections.
}

//______________________________________________________________________________
void TGLParametricPlot::SetSurfaceColor()const
{
   //Set material properties.
   const Float_t specular[] = {1.f, 1.f, 1.f, 1.f};
   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.f);

   if (fColorScheme == -1) {
      const Float_t outerDiff[] = {0.5f, 0.42f, 0.f, 1.f};
      glMaterialfv(GL_FRONT, GL_DIFFUSE, outerDiff);
      const Float_t innerDiff[] = {0.5f, 0.2f,  0.f, 1.f};
      glMaterialfv(GL_BACK,  GL_DIFFUSE, innerDiff);
   }
}
 TGLParametric.cxx:1
 TGLParametric.cxx:2
 TGLParametric.cxx:3
 TGLParametric.cxx:4
 TGLParametric.cxx:5
 TGLParametric.cxx:6
 TGLParametric.cxx:7
 TGLParametric.cxx:8
 TGLParametric.cxx:9
 TGLParametric.cxx:10
 TGLParametric.cxx:11
 TGLParametric.cxx:12
 TGLParametric.cxx:13
 TGLParametric.cxx:14
 TGLParametric.cxx:15
 TGLParametric.cxx:16
 TGLParametric.cxx:17
 TGLParametric.cxx:18
 TGLParametric.cxx:19
 TGLParametric.cxx:20
 TGLParametric.cxx:21
 TGLParametric.cxx:22
 TGLParametric.cxx:23
 TGLParametric.cxx:24
 TGLParametric.cxx:25
 TGLParametric.cxx:26
 TGLParametric.cxx:27
 TGLParametric.cxx:28
 TGLParametric.cxx:29
 TGLParametric.cxx:30
 TGLParametric.cxx:31
 TGLParametric.cxx:32
 TGLParametric.cxx:33
 TGLParametric.cxx:34
 TGLParametric.cxx:35
 TGLParametric.cxx:36
 TGLParametric.cxx:37
 TGLParametric.cxx:38
 TGLParametric.cxx:39
 TGLParametric.cxx:40
 TGLParametric.cxx:41
 TGLParametric.cxx:42
 TGLParametric.cxx:43
 TGLParametric.cxx:44
 TGLParametric.cxx:45
 TGLParametric.cxx:46
 TGLParametric.cxx:47
 TGLParametric.cxx:48
 TGLParametric.cxx:49
 TGLParametric.cxx:50
 TGLParametric.cxx:51
 TGLParametric.cxx:52
 TGLParametric.cxx:53
 TGLParametric.cxx:54
 TGLParametric.cxx:55
 TGLParametric.cxx:56
 TGLParametric.cxx:57
 TGLParametric.cxx:58
 TGLParametric.cxx:59
 TGLParametric.cxx:60
 TGLParametric.cxx:61
 TGLParametric.cxx:62
 TGLParametric.cxx:63
 TGLParametric.cxx:64
 TGLParametric.cxx:65
 TGLParametric.cxx:66
 TGLParametric.cxx:67
 TGLParametric.cxx:68
 TGLParametric.cxx:69
 TGLParametric.cxx:70
 TGLParametric.cxx:71
 TGLParametric.cxx:72
 TGLParametric.cxx:73
 TGLParametric.cxx:74
 TGLParametric.cxx:75
 TGLParametric.cxx:76
 TGLParametric.cxx:77
 TGLParametric.cxx:78
 TGLParametric.cxx:79
 TGLParametric.cxx:80
 TGLParametric.cxx:81
 TGLParametric.cxx:82
 TGLParametric.cxx:83
 TGLParametric.cxx:84
 TGLParametric.cxx:85
 TGLParametric.cxx:86
 TGLParametric.cxx:87
 TGLParametric.cxx:88
 TGLParametric.cxx:89
 TGLParametric.cxx:90
 TGLParametric.cxx:91
 TGLParametric.cxx:92
 TGLParametric.cxx:93
 TGLParametric.cxx:94
 TGLParametric.cxx:95
 TGLParametric.cxx:96
 TGLParametric.cxx:97
 TGLParametric.cxx:98
 TGLParametric.cxx:99
 TGLParametric.cxx:100
 TGLParametric.cxx:101
 TGLParametric.cxx:102
 TGLParametric.cxx:103
 TGLParametric.cxx:104
 TGLParametric.cxx:105
 TGLParametric.cxx:106
 TGLParametric.cxx:107
 TGLParametric.cxx:108
 TGLParametric.cxx:109
 TGLParametric.cxx:110
 TGLParametric.cxx:111
 TGLParametric.cxx:112
 TGLParametric.cxx:113
 TGLParametric.cxx:114
 TGLParametric.cxx:115
 TGLParametric.cxx:116
 TGLParametric.cxx:117
 TGLParametric.cxx:118
 TGLParametric.cxx:119
 TGLParametric.cxx:120
 TGLParametric.cxx:121
 TGLParametric.cxx:122
 TGLParametric.cxx:123
 TGLParametric.cxx:124
 TGLParametric.cxx:125
 TGLParametric.cxx:126
 TGLParametric.cxx:127
 TGLParametric.cxx:128
 TGLParametric.cxx:129
 TGLParametric.cxx:130
 TGLParametric.cxx:131
 TGLParametric.cxx:132
 TGLParametric.cxx:133
 TGLParametric.cxx:134
 TGLParametric.cxx:135
 TGLParametric.cxx:136
 TGLParametric.cxx:137
 TGLParametric.cxx:138
 TGLParametric.cxx:139
 TGLParametric.cxx:140
 TGLParametric.cxx:141
 TGLParametric.cxx:142
 TGLParametric.cxx:143
 TGLParametric.cxx:144
 TGLParametric.cxx:145
 TGLParametric.cxx:146
 TGLParametric.cxx:147
 TGLParametric.cxx:148
 TGLParametric.cxx:149
 TGLParametric.cxx:150
 TGLParametric.cxx:151
 TGLParametric.cxx:152
 TGLParametric.cxx:153
 TGLParametric.cxx:154
 TGLParametric.cxx:155
 TGLParametric.cxx:156
 TGLParametric.cxx:157
 TGLParametric.cxx:158
 TGLParametric.cxx:159
 TGLParametric.cxx:160
 TGLParametric.cxx:161
 TGLParametric.cxx:162
 TGLParametric.cxx:163
 TGLParametric.cxx:164
 TGLParametric.cxx:165
 TGLParametric.cxx:166
 TGLParametric.cxx:167
 TGLParametric.cxx:168
 TGLParametric.cxx:169
 TGLParametric.cxx:170
 TGLParametric.cxx:171
 TGLParametric.cxx:172
 TGLParametric.cxx:173
 TGLParametric.cxx:174
 TGLParametric.cxx:175
 TGLParametric.cxx:176
 TGLParametric.cxx:177
 TGLParametric.cxx:178
 TGLParametric.cxx:179
 TGLParametric.cxx:180
 TGLParametric.cxx:181
 TGLParametric.cxx:182
 TGLParametric.cxx:183
 TGLParametric.cxx:184
 TGLParametric.cxx:185
 TGLParametric.cxx:186
 TGLParametric.cxx:187
 TGLParametric.cxx:188
 TGLParametric.cxx:189
 TGLParametric.cxx:190
 TGLParametric.cxx:191
 TGLParametric.cxx:192
 TGLParametric.cxx:193
 TGLParametric.cxx:194
 TGLParametric.cxx:195
 TGLParametric.cxx:196
 TGLParametric.cxx:197
 TGLParametric.cxx:198
 TGLParametric.cxx:199
 TGLParametric.cxx:200
 TGLParametric.cxx:201
 TGLParametric.cxx:202
 TGLParametric.cxx:203
 TGLParametric.cxx:204
 TGLParametric.cxx:205
 TGLParametric.cxx:206
 TGLParametric.cxx:207
 TGLParametric.cxx:208
 TGLParametric.cxx:209
 TGLParametric.cxx:210
 TGLParametric.cxx:211
 TGLParametric.cxx:212
 TGLParametric.cxx:213
 TGLParametric.cxx:214
 TGLParametric.cxx:215
 TGLParametric.cxx:216
 TGLParametric.cxx:217
 TGLParametric.cxx:218
 TGLParametric.cxx:219
 TGLParametric.cxx:220
 TGLParametric.cxx:221
 TGLParametric.cxx:222
 TGLParametric.cxx:223
 TGLParametric.cxx:224
 TGLParametric.cxx:225
 TGLParametric.cxx:226
 TGLParametric.cxx:227
 TGLParametric.cxx:228
 TGLParametric.cxx:229
 TGLParametric.cxx:230
 TGLParametric.cxx:231
 TGLParametric.cxx:232
 TGLParametric.cxx:233
 TGLParametric.cxx:234
 TGLParametric.cxx:235
 TGLParametric.cxx:236
 TGLParametric.cxx:237
 TGLParametric.cxx:238
 TGLParametric.cxx:239
 TGLParametric.cxx:240
 TGLParametric.cxx:241
 TGLParametric.cxx:242
 TGLParametric.cxx:243
 TGLParametric.cxx:244
 TGLParametric.cxx:245
 TGLParametric.cxx:246
 TGLParametric.cxx:247
 TGLParametric.cxx:248
 TGLParametric.cxx:249
 TGLParametric.cxx:250
 TGLParametric.cxx:251
 TGLParametric.cxx:252
 TGLParametric.cxx:253
 TGLParametric.cxx:254
 TGLParametric.cxx:255
 TGLParametric.cxx:256
 TGLParametric.cxx:257
 TGLParametric.cxx:258
 TGLParametric.cxx:259
 TGLParametric.cxx:260
 TGLParametric.cxx:261
 TGLParametric.cxx:262
 TGLParametric.cxx:263
 TGLParametric.cxx:264
 TGLParametric.cxx:265
 TGLParametric.cxx:266
 TGLParametric.cxx:267
 TGLParametric.cxx:268
 TGLParametric.cxx:269
 TGLParametric.cxx:270
 TGLParametric.cxx:271
 TGLParametric.cxx:272
 TGLParametric.cxx:273
 TGLParametric.cxx:274
 TGLParametric.cxx:275
 TGLParametric.cxx:276
 TGLParametric.cxx:277
 TGLParametric.cxx:278
 TGLParametric.cxx:279
 TGLParametric.cxx:280
 TGLParametric.cxx:281
 TGLParametric.cxx:282
 TGLParametric.cxx:283
 TGLParametric.cxx:284
 TGLParametric.cxx:285
 TGLParametric.cxx:286
 TGLParametric.cxx:287
 TGLParametric.cxx:288
 TGLParametric.cxx:289
 TGLParametric.cxx:290
 TGLParametric.cxx:291
 TGLParametric.cxx:292
 TGLParametric.cxx:293
 TGLParametric.cxx:294
 TGLParametric.cxx:295
 TGLParametric.cxx:296
 TGLParametric.cxx:297
 TGLParametric.cxx:298
 TGLParametric.cxx:299
 TGLParametric.cxx:300
 TGLParametric.cxx:301
 TGLParametric.cxx:302
 TGLParametric.cxx:303
 TGLParametric.cxx:304
 TGLParametric.cxx:305
 TGLParametric.cxx:306
 TGLParametric.cxx:307
 TGLParametric.cxx:308
 TGLParametric.cxx:309
 TGLParametric.cxx:310
 TGLParametric.cxx:311
 TGLParametric.cxx:312
 TGLParametric.cxx:313
 TGLParametric.cxx:314
 TGLParametric.cxx:315
 TGLParametric.cxx:316
 TGLParametric.cxx:317
 TGLParametric.cxx:318
 TGLParametric.cxx:319
 TGLParametric.cxx:320
 TGLParametric.cxx:321
 TGLParametric.cxx:322
 TGLParametric.cxx:323
 TGLParametric.cxx:324
 TGLParametric.cxx:325
 TGLParametric.cxx:326
 TGLParametric.cxx:327
 TGLParametric.cxx:328
 TGLParametric.cxx:329
 TGLParametric.cxx:330
 TGLParametric.cxx:331
 TGLParametric.cxx:332
 TGLParametric.cxx:333
 TGLParametric.cxx:334
 TGLParametric.cxx:335
 TGLParametric.cxx:336
 TGLParametric.cxx:337
 TGLParametric.cxx:338
 TGLParametric.cxx:339
 TGLParametric.cxx:340
 TGLParametric.cxx:341
 TGLParametric.cxx:342
 TGLParametric.cxx:343
 TGLParametric.cxx:344
 TGLParametric.cxx:345
 TGLParametric.cxx:346
 TGLParametric.cxx:347
 TGLParametric.cxx:348
 TGLParametric.cxx:349
 TGLParametric.cxx:350
 TGLParametric.cxx:351
 TGLParametric.cxx:352
 TGLParametric.cxx:353
 TGLParametric.cxx:354
 TGLParametric.cxx:355
 TGLParametric.cxx:356
 TGLParametric.cxx:357
 TGLParametric.cxx:358
 TGLParametric.cxx:359
 TGLParametric.cxx:360
 TGLParametric.cxx:361
 TGLParametric.cxx:362
 TGLParametric.cxx:363
 TGLParametric.cxx:364
 TGLParametric.cxx:365
 TGLParametric.cxx:366
 TGLParametric.cxx:367
 TGLParametric.cxx:368
 TGLParametric.cxx:369
 TGLParametric.cxx:370
 TGLParametric.cxx:371
 TGLParametric.cxx:372
 TGLParametric.cxx:373
 TGLParametric.cxx:374
 TGLParametric.cxx:375
 TGLParametric.cxx:376
 TGLParametric.cxx:377
 TGLParametric.cxx:378
 TGLParametric.cxx:379
 TGLParametric.cxx:380
 TGLParametric.cxx:381
 TGLParametric.cxx:382
 TGLParametric.cxx:383
 TGLParametric.cxx:384
 TGLParametric.cxx:385
 TGLParametric.cxx:386
 TGLParametric.cxx:387
 TGLParametric.cxx:388
 TGLParametric.cxx:389
 TGLParametric.cxx:390
 TGLParametric.cxx:391
 TGLParametric.cxx:392
 TGLParametric.cxx:393
 TGLParametric.cxx:394
 TGLParametric.cxx:395
 TGLParametric.cxx:396
 TGLParametric.cxx:397
 TGLParametric.cxx:398
 TGLParametric.cxx:399
 TGLParametric.cxx:400
 TGLParametric.cxx:401
 TGLParametric.cxx:402
 TGLParametric.cxx:403
 TGLParametric.cxx:404
 TGLParametric.cxx:405
 TGLParametric.cxx:406
 TGLParametric.cxx:407
 TGLParametric.cxx:408
 TGLParametric.cxx:409
 TGLParametric.cxx:410
 TGLParametric.cxx:411
 TGLParametric.cxx:412
 TGLParametric.cxx:413
 TGLParametric.cxx:414
 TGLParametric.cxx:415
 TGLParametric.cxx:416
 TGLParametric.cxx:417
 TGLParametric.cxx:418
 TGLParametric.cxx:419
 TGLParametric.cxx:420
 TGLParametric.cxx:421
 TGLParametric.cxx:422
 TGLParametric.cxx:423
 TGLParametric.cxx:424
 TGLParametric.cxx:425
 TGLParametric.cxx:426
 TGLParametric.cxx:427
 TGLParametric.cxx:428
 TGLParametric.cxx:429
 TGLParametric.cxx:430
 TGLParametric.cxx:431
 TGLParametric.cxx:432
 TGLParametric.cxx:433
 TGLParametric.cxx:434
 TGLParametric.cxx:435
 TGLParametric.cxx:436
 TGLParametric.cxx:437
 TGLParametric.cxx:438
 TGLParametric.cxx:439
 TGLParametric.cxx:440
 TGLParametric.cxx:441
 TGLParametric.cxx:442
 TGLParametric.cxx:443
 TGLParametric.cxx:444
 TGLParametric.cxx:445
 TGLParametric.cxx:446
 TGLParametric.cxx:447
 TGLParametric.cxx:448
 TGLParametric.cxx:449
 TGLParametric.cxx:450
 TGLParametric.cxx:451
 TGLParametric.cxx:452
 TGLParametric.cxx:453
 TGLParametric.cxx:454
 TGLParametric.cxx:455
 TGLParametric.cxx:456
 TGLParametric.cxx:457
 TGLParametric.cxx:458
 TGLParametric.cxx:459
 TGLParametric.cxx:460
 TGLParametric.cxx:461
 TGLParametric.cxx:462
 TGLParametric.cxx:463
 TGLParametric.cxx:464
 TGLParametric.cxx:465
 TGLParametric.cxx:466
 TGLParametric.cxx:467
 TGLParametric.cxx:468
 TGLParametric.cxx:469
 TGLParametric.cxx:470
 TGLParametric.cxx:471
 TGLParametric.cxx:472
 TGLParametric.cxx:473
 TGLParametric.cxx:474
 TGLParametric.cxx:475
 TGLParametric.cxx:476
 TGLParametric.cxx:477
 TGLParametric.cxx:478
 TGLParametric.cxx:479
 TGLParametric.cxx:480
 TGLParametric.cxx:481
 TGLParametric.cxx:482
 TGLParametric.cxx:483
 TGLParametric.cxx:484
 TGLParametric.cxx:485
 TGLParametric.cxx:486
 TGLParametric.cxx:487
 TGLParametric.cxx:488
 TGLParametric.cxx:489
 TGLParametric.cxx:490
 TGLParametric.cxx:491
 TGLParametric.cxx:492
 TGLParametric.cxx:493
 TGLParametric.cxx:494
 TGLParametric.cxx:495
 TGLParametric.cxx:496
 TGLParametric.cxx:497
 TGLParametric.cxx:498
 TGLParametric.cxx:499
 TGLParametric.cxx:500
 TGLParametric.cxx:501
 TGLParametric.cxx:502
 TGLParametric.cxx:503
 TGLParametric.cxx:504
 TGLParametric.cxx:505
 TGLParametric.cxx:506
 TGLParametric.cxx:507
 TGLParametric.cxx:508
 TGLParametric.cxx:509
 TGLParametric.cxx:510
 TGLParametric.cxx:511
 TGLParametric.cxx:512
 TGLParametric.cxx:513
 TGLParametric.cxx:514
 TGLParametric.cxx:515
 TGLParametric.cxx:516
 TGLParametric.cxx:517
 TGLParametric.cxx:518
 TGLParametric.cxx:519
 TGLParametric.cxx:520
 TGLParametric.cxx:521
 TGLParametric.cxx:522
 TGLParametric.cxx:523
 TGLParametric.cxx:524
 TGLParametric.cxx:525
 TGLParametric.cxx:526
 TGLParametric.cxx:527
 TGLParametric.cxx:528
 TGLParametric.cxx:529
 TGLParametric.cxx:530
 TGLParametric.cxx:531
 TGLParametric.cxx:532
 TGLParametric.cxx:533
 TGLParametric.cxx:534
 TGLParametric.cxx:535
 TGLParametric.cxx:536
 TGLParametric.cxx:537
 TGLParametric.cxx:538
 TGLParametric.cxx:539
 TGLParametric.cxx:540
 TGLParametric.cxx:541
 TGLParametric.cxx:542
 TGLParametric.cxx:543
 TGLParametric.cxx:544
 TGLParametric.cxx:545
 TGLParametric.cxx:546
 TGLParametric.cxx:547
 TGLParametric.cxx:548
 TGLParametric.cxx:549
 TGLParametric.cxx:550
 TGLParametric.cxx:551
 TGLParametric.cxx:552
 TGLParametric.cxx:553
 TGLParametric.cxx:554
 TGLParametric.cxx:555
 TGLParametric.cxx:556
 TGLParametric.cxx:557
 TGLParametric.cxx:558
 TGLParametric.cxx:559
 TGLParametric.cxx:560
 TGLParametric.cxx:561
 TGLParametric.cxx:562
 TGLParametric.cxx:563
 TGLParametric.cxx:564
 TGLParametric.cxx:565
 TGLParametric.cxx:566
 TGLParametric.cxx:567
 TGLParametric.cxx:568
 TGLParametric.cxx:569
 TGLParametric.cxx:570
 TGLParametric.cxx:571
 TGLParametric.cxx:572
 TGLParametric.cxx:573
 TGLParametric.cxx:574
 TGLParametric.cxx:575
 TGLParametric.cxx:576
 TGLParametric.cxx:577
 TGLParametric.cxx:578
 TGLParametric.cxx:579
 TGLParametric.cxx:580
 TGLParametric.cxx:581
 TGLParametric.cxx:582
 TGLParametric.cxx:583
 TGLParametric.cxx:584
 TGLParametric.cxx:585
 TGLParametric.cxx:586
 TGLParametric.cxx:587
 TGLParametric.cxx:588
 TGLParametric.cxx:589
 TGLParametric.cxx:590
 TGLParametric.cxx:591
 TGLParametric.cxx:592
 TGLParametric.cxx:593
 TGLParametric.cxx:594
 TGLParametric.cxx:595
 TGLParametric.cxx:596
 TGLParametric.cxx:597
 TGLParametric.cxx:598
 TGLParametric.cxx:599
 TGLParametric.cxx:600
 TGLParametric.cxx:601
 TGLParametric.cxx:602
 TGLParametric.cxx:603
 TGLParametric.cxx:604
 TGLParametric.cxx:605
 TGLParametric.cxx:606
 TGLParametric.cxx:607
 TGLParametric.cxx:608
 TGLParametric.cxx:609
 TGLParametric.cxx:610
 TGLParametric.cxx:611
 TGLParametric.cxx:612
 TGLParametric.cxx:613
 TGLParametric.cxx:614
 TGLParametric.cxx:615
 TGLParametric.cxx:616
 TGLParametric.cxx:617
 TGLParametric.cxx:618
 TGLParametric.cxx:619
 TGLParametric.cxx:620
 TGLParametric.cxx:621
 TGLParametric.cxx:622
 TGLParametric.cxx:623
 TGLParametric.cxx:624
 TGLParametric.cxx:625
 TGLParametric.cxx:626
 TGLParametric.cxx:627
 TGLParametric.cxx:628
 TGLParametric.cxx:629
 TGLParametric.cxx:630
 TGLParametric.cxx:631
 TGLParametric.cxx:632
 TGLParametric.cxx:633
 TGLParametric.cxx:634
 TGLParametric.cxx:635
 TGLParametric.cxx:636
 TGLParametric.cxx:637
 TGLParametric.cxx:638
 TGLParametric.cxx:639
 TGLParametric.cxx:640