diff --git a/gl/inc/LinkDef.h b/gl/inc/LinkDef.h
index f2c14bc4b4250914c6e8503ba6371f7513d363df..51649c6fc73183d8b240c623d4085a18ab90cb15 100644
--- a/gl/inc/LinkDef.h
+++ b/gl/inc/LinkDef.h
@@ -78,6 +78,8 @@
 #pragma link C++ class TGLPlotBox;
 #pragma link C++ class TGLTH3Slice;
 #pragma link C++ class TGLBoxCut;
+#pragma link C++ class TGLParametricEquation;
+#pragma link C++ class TGLParametricPlot;
 
 #ifndef _WIN32
 #pragma link C++ class TX11GL;
diff --git a/gl/inc/TGLBoxPainter.h b/gl/inc/TGLBoxPainter.h
index 76f75a6f92563c045f014fb3987d7afa097b2fe8..4a71b1f70a0aae139229451cd14586affa5a3166 100644
--- a/gl/inc/TGLBoxPainter.h
+++ b/gl/inc/TGLBoxPainter.h
@@ -95,7 +95,6 @@ private:
    //Overriders
    void    InitGL()const;
    void    DrawPlot()const;
-   void    ClearBuffers()const;
 
    void    SetPlotColor()const;
 
diff --git a/gl/inc/TGLHistPainter.h b/gl/inc/TGLHistPainter.h
index e4d92b6cf0e09b0fe90d57b50ab1e90c770e4135..3f8afd3c7b8bdc162119e687e87af3ca5fba4135 100644
--- a/gl/inc/TGLHistPainter.h
+++ b/gl/inc/TGLHistPainter.h
@@ -24,6 +24,7 @@
       TGLTF3Painter - TF3.
 */
 
+class TGLParametricEquation;
 class TString;
 class TList;
 class TF3;
@@ -37,15 +38,17 @@ private:
    //This member can have different dynamic types: TGLLegoPainter, etc.
    std::auto_ptr<TGLPlotPainter>      fGLPainter;
 
-   TH1                *fHist;
-   TF3                *fF3;
-   TList              *fStack;
-   EGLPlotType         fPlotType;
-   TGLOrthoCamera      fCamera;
-   TGLPlotCoordinates  fCoord;
+   TGLParametricEquation *fEq;
+   TH1                   *fHist;
+   TF3                   *fF3;
+   TList                 *fStack;
+   EGLPlotType            fPlotType;
+   TGLOrthoCamera         fCamera;
+   TGLPlotCoordinates     fCoord;
 
 public:
    TGLHistPainter(TH1 *hist);
+   TGLHistPainter(TGLParametricEquation *equation);
    
    //TVirtualHistPainter final overriders
    Int_t          DistancetoPrimitive(Int_t px, Int_t py);
diff --git a/gl/inc/TGLLegoPainter.h b/gl/inc/TGLLegoPainter.h
index fc5d161570e4e728e4a43a5ffadc246a238081a7..df07bf545a091dd5d5310c03887aa28eaa76067e 100644
--- a/gl/inc/TGLLegoPainter.h
+++ b/gl/inc/TGLLegoPainter.h
@@ -1,4 +1,4 @@
-// @(#)root/gl:$Name:  $:$Id: TGLLegoPainter.h,v 1.5 2006/10/02 12:55:47 couet Exp $
+// @(#)root/gl:$Name:  $:$Id: TGLLegoPainter.h,v 1.6 2006/11/22 16:19:55 couet Exp $
 // Author:  Timur Pocheptsov  14/06/2006
                                                                                 
 /*************************************************************************
@@ -82,7 +82,6 @@ private:
    //Overriders
    void         InitGL()const;
    void         DrawPlot()const;
-   void         ClearBuffers()const;
 
    void         DrawLegoCartesian()const;
    void         DrawLegoPolar()const;
diff --git a/gl/inc/TGLParametric.h b/gl/inc/TGLParametric.h
new file mode 100644
index 0000000000000000000000000000000000000000..3fa66701f7668b480528aa2b044e8cb832c4a0ff
--- /dev/null
+++ b/gl/inc/TGLParametric.h
@@ -0,0 +1,139 @@
+// @(#)root/gl:$Name:  $:$Id: TGLParametric.h,v 1.1 Exp $
+// 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.             *
+ *************************************************************************/
+
+#ifndef ROOT_TGLParametric
+#define ROOT_TGLParametric
+
+#include <memory>
+
+#ifndef ROOT_TGLHistPainter
+#include "TGLHistPainter.h"
+#endif
+#ifndef ROOT_TGLUtil
+#include "TGLUtil.h"
+#endif
+#ifndef ROOT_TF2
+#include "TF2.h"
+#endif
+
+class TString;
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TGLParametricEquation                                                //
+//                                                                      //
+// Parametric equations drawing with GL.                                //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+
+typedef void (*ParametricEquation_t)(TGLVertex3 &, Double_t u, Double_t v);
+
+class TGLParametricEquation : public TNamed {
+private:
+   typedef std::auto_ptr<TF2> Ptr_t;
+
+   Ptr_t                fXEquation;
+   Ptr_t                fYEquation;
+   Ptr_t                fZEquation;
+
+   ParametricEquation_t fEquation;
+
+   Rgl::Range_t         fURange;
+   Rgl::Range_t         fVRange;
+
+   Bool_t               fConstrained;
+   Bool_t               fModified;
+
+   typedef std::auto_ptr<TGLHistPainter> Painter_t;
+   //C++ compiler do not need TGLhistPainter definition here, but I'm not sure about CINT,
+   //so I've included TGLHistPainter definition.
+   Painter_t            fPainter;
+
+public:
+   TGLParametricEquation(const TString &name, const TString &xEquation,
+                 const TString &yEquation, const TString &zEquation,
+                 Double_t uMin, Double_t uMax,
+                 Double_t vMin, Double_t vMax);
+   TGLParametricEquation(const TString &name, ParametricEquation_t equation,
+                 Double_t uMin, Double_t uMax, Double_t vMin, Double_t vMax);
+
+   Rgl::Range_t GetURange()const;
+   Rgl::Range_t GetVRange()const;
+
+   Bool_t       IsConstrained()const;
+   void         SetConstrained(Bool_t c);
+
+   Bool_t       IsModified()const;
+   void         SetModified(Bool_t m);
+
+   void         EvalVertex(TGLVertex3 &newVertex, Double_t u, Double_t v)const;
+
+   Int_t        DistancetoPrimitive(Int_t px, Int_t py);
+   void         ExecuteEvent(Int_t event, Int_t px, Int_t py);
+   char        *GetObjectInfo(Int_t px, Int_t py) const;
+   void         Paint(Option_t *option);
+
+private:
+
+   TGLParametricEquation(const TGLParametricEquation &);
+   TGLParametricEquation &operator = (const TGLParametricEquation &);
+
+   ClassDef(TGLParametricEquation, 0)//Equation of parametric surface.
+};
+
+class TGLParametricPlot : public TGLPlotPainter {
+private:
+   struct Vertex_t {
+      TGLVertex3 fPos;
+      TGLVector3 fNormal;
+      Float_t    fRGBA[4];
+   };
+
+   enum EMeshSize {kLow = 30, kHigh = 150};
+
+   Int_t                  fMeshSize;
+   TGL2DArray<Vertex_t>   fMesh;
+
+   Bool_t                 fShowMesh;
+   Int_t                  fColorScheme;
+
+   TGLParametricEquation *fEquation;
+
+public:
+   TGLParametricPlot(TGLParametricEquation *equation, TGLOrthoCamera *camera, Int_t context = -1);
+
+   Bool_t   InitGeometry();
+   void     StartPan(Int_t px, Int_t py);
+   void     Pan(Int_t px, Int_t py);
+   char    *GetPlotInfo(Int_t px, Int_t py);
+   void     AddOption(const TString &option);
+   void     ProcessEvent(Int_t event, Int_t px, Int_t py);
+
+private:
+   void     InitGL()const;
+   void     DrawPlot()const;
+
+   void     InitColors();
+
+   void     DrawSectionXOZ()const;
+   void     DrawSectionYOZ()const;
+   void     DrawSectionXOY()const;
+
+   void     SetSurfaceColor()const;
+
+   TGLParametricPlot(const TGLParametricPlot &);
+   TGLParametricPlot &operator = (const TGLParametricPlot &);
+
+   ClassDef(TGLParametricPlot, 0)//Parametric plot's painter.
+};
+
+#endif
diff --git a/gl/inc/TGLPlotPainter.h b/gl/inc/TGLPlotPainter.h
index d0e88f5e0bb66cbdeffe2178de147c53c29a172a..7a21d927bb7b644893aa7c79ecf1fad8c3f193fc 100644
--- a/gl/inc/TGLPlotPainter.h
+++ b/gl/inc/TGLPlotPainter.h
@@ -1,4 +1,4 @@
-// @(#)root/gl:$Name:  $:$Id: TGLPlotPainter.h,v 1.10 2006/11/24 15:57:44 couet Exp $
+// @(#)root/gl:$Name:  $:$Id: TGLPlotPainter.h,v 1.11 2006/12/13 09:33:29 brun Exp $
 // Author:  Timur Pocheptsov  14/06/2006
                                                                                 
 /*************************************************************************
@@ -119,6 +119,7 @@ protected:
 public:
    TGLPlotPainter(TH1 *hist, TGLOrthoCamera *camera, TGLPlotCoordinates *coord, Int_t context,
                   Bool_t xoySelectable, Bool_t xozSelectable, Bool_t yozSelectable);
+   TGLPlotPainter(TGLOrthoCamera *camera, Int_t context);
 
    virtual void     Paint();
    //Checks, if mouse cursor is above plot.
@@ -161,9 +162,10 @@ protected:
    virtual void     DrawSectionXOY()const = 0;
 
    virtual void     InitGL()const = 0;
-   virtual void     ClearBuffers()const = 0;
    virtual void     DrawPlot()const = 0;
 
+   virtual void     ClearBuffers()const;
+
    void             PrintPlot()const;
    //
 
diff --git a/gl/inc/TGLSurfacePainter.h b/gl/inc/TGLSurfacePainter.h
index c04bf576fb906e0bf44e98db105e917b69c455f2..068ff0efd54199e8da8d63a2733f032ab4198605 100644
--- a/gl/inc/TGLSurfacePainter.h
+++ b/gl/inc/TGLSurfacePainter.h
@@ -67,7 +67,6 @@ public:
 
 private:
    void   InitGL()const;
-   void   ClearBuffers()const;
    void   DrawPlot()const;
 
    void   SetNormals();
diff --git a/gl/inc/TGLTF3Painter.h b/gl/inc/TGLTF3Painter.h
index cd1c88072793efa66210a9d59fcfb87bc18d2e2a..5dffa1f396a29fa6a4e300f17d72bbab57f52ab2 100644
--- a/gl/inc/TGLTF3Painter.h
+++ b/gl/inc/TGLTF3Painter.h
@@ -47,7 +47,6 @@ public:
 
 private:
    void    InitGL()const;
-   void    ClearBuffers()const;
    void    DrawPlot()const;
 
    void    SetSurfaceColor()const;
diff --git a/gl/inc/TGLUtil.h b/gl/inc/TGLUtil.h
index 0dcb74e09b23ecf0bfeaba15bc9b527160a6fc46..28e8a61b5b30431c93b3086f734a1271f18dd9ed 100644
--- a/gl/inc/TGLUtil.h
+++ b/gl/inc/TGLUtil.h
@@ -1,4 +1,4 @@
-// @(#)root/gl:$Name:  $:$Id: TGLUtil.h,v 1.35 2006/12/08 10:00:39 brun Exp $
+// @(#)root/gl:$Name:  $:$Id: TGLUtil.h,v 1.36 2007/01/15 11:30:47 brun Exp $
 // Author:  Richard Maunder  25/05/2005
 
 /*************************************************************************
@@ -66,6 +66,7 @@ enum EGLPlotType {
    kGLBoxPlot,
    kGLTF3Plot,
    kGLStackPlot,
+   kGLParametricPlot,
    kGLDefaultPlot
 };
 
@@ -968,6 +969,7 @@ namespace Rgl {
                          const TGLVector3 &norm2, const TGLVector3 &norm3);
    void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, 
                          Double_t t1, Double_t t2, Double_t t3, Double_t z, const TGLVector3 &planeNormal);
+   void GetColor(Float_t v, Float_t vmin, Float_t vmax, Int_t type, Float_t *rgba);
 }
 
 class TGLLevelPalette {
diff --git a/gl/src/TGLBoxPainter.cxx b/gl/src/TGLBoxPainter.cxx
index e3005607ab14872f521d82f4c408c80b234eb0fe..976bff63f25345c94d129a17281cb5a61f1b83ab 100644
--- a/gl/src/TGLBoxPainter.cxx
+++ b/gl/src/TGLBoxPainter.cxx
@@ -305,20 +305,6 @@ void TGLBoxPainter::DrawPlot()const
    }
 }
 
-
-//______________________________________________________________________________
-void TGLBoxPainter::ClearBuffers()const
-{
-   // Clear buffer.
-
-   Float_t rgb[3] = {1.f, 1.f, 1.f};
-   if (const TColor *color = GetPadColor())
-      color->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 TGLBoxPainter::SetPlotColor()const
 {
diff --git a/gl/src/TGLHistPainter.cxx b/gl/src/TGLHistPainter.cxx
index c68b5ae2d41e717127a72c1fa1946ac9fff19a8d..25a788b41d75ea86513199cd965d9ce872f20067 100644
--- a/gl/src/TGLHistPainter.cxx
+++ b/gl/src/TGLHistPainter.cxx
@@ -10,6 +10,7 @@
 #include "TGLLegoPainter.h"
 #include "TGLBoxPainter.h"
 #include "TGLTF3Painter.h"
+#include "TGLParametric.h"
 
 ClassImp(TGLHistPainter)
 
@@ -25,7 +26,7 @@ ClassImp(TGLHistPainter)
 //______________________________________________________________________________
 TGLHistPainter::TGLHistPainter(TH1 *hist)
                    : fDefaultPainter(TVirtualHistPainter::HistPainter(hist)),
-                     fGLPainter(0),
+                     fEq(0),
                      fHist(hist),
                      fF3(0),
                      fStack(0),
@@ -35,6 +36,18 @@ TGLHistPainter::TGLHistPainter(TH1 *hist)
    //fDefaultPainter is 0. In each function, which use it, I have to check the pointer first.
 }
 
+//______________________________________________________________________________
+TGLHistPainter::TGLHistPainter(TGLParametricEquation *equation)
+                   : fEq(equation),
+                     fHist(0),
+                     fF3(0),
+                     fStack(0),
+                     fPlotType(kGLParametricPlot)//THistPainter
+{
+   //This ctor creates gl-parametric plot's painter.
+   fGLPainter.reset(new TGLParametricPlot(equation, &fCamera));
+}
+
 //______________________________________________________________________________
 Int_t TGLHistPainter::DistancetoPrimitive(Int_t px, Int_t py)
 {
@@ -176,7 +189,8 @@ void TGLHistPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
             gGLManager->PaintSingleObject(fGLPainter.get());
          } else if (py == kKey_p || py == kKey_P || py == kKey_S || py == kKey_s
                     || py == kKey_c || py == kKey_C || py == kKey_x || py == kKey_X
-                    || py == kKey_y || py == kKey_Y || py == kKey_z || py == kKey_Z) 
+                    || py == kKey_y || py == kKey_Y || py == kKey_z || py == kKey_Z
+                    || py == kKey_w || py == kKey_W || py == kKey_l || py == kKey_L) 
          {
             fGLPainter->ProcessEvent(event, px, py);
             gGLManager->PaintSingleObject(fGLPainter.get());
@@ -323,14 +337,15 @@ void TGLHistPainter::Paint(Option_t *o)
    const Ssiz_t glPos = option.Index("gl");
    if (glPos != kNPOS)
       option.Remove(glPos, 2);
-   else {
+   else if (fPlotType != kGLParametricPlot){
       gPad->SetCopyGLDevice(kFALSE);
       if (fDefaultPainter.get())
          fDefaultPainter->Paint(o);//option.Data());
       return;
    }
 
-   CreatePainter(ParsePaintOption(option), option);
+   if (fPlotType != kGLParametricPlot)
+      CreatePainter(ParsePaintOption(option), option);
 
    if (fPlotType == kGLDefaultPlot) {
       //In case of default plot pad 
@@ -347,6 +362,9 @@ void TGLHistPainter::Paint(Option_t *o)
          //gl-buffer into the final pad/canvas pixmap/DIB.
          gPad->SetCopyGLDevice(kTRUE);
          fGLPainter->SetGLContext(glContext);
+         if (gPad->GetFrameFillColor() != kWhite)
+            fGLPainter->SetFrameColor(gROOT->GetColor(gPad->GetFrameFillColor()));  
+         fGLPainter->SetPadColor(gROOT->GetColor(gPad->GetFillColor()));
          if (fGLPainter->InitGeometry())
             gGLManager->PaintSingleObject(fGLPainter.get());
       }
@@ -408,11 +426,6 @@ void TGLHistPainter::CreatePainter(const PlotOption_t &option, const TString &ad
       fCoord.SetYLog(gPad->GetLogy());
       fCoord.SetZLog(gPad->GetLogz());
       fCoord.SetCoordType(option.fCoordType);
-
-      if (gPad->GetFrameFillColor() != kWhite)
-         fGLPainter->SetFrameColor(gROOT->GetColor(gPad->GetFrameFillColor()));
-
-      fGLPainter->SetPadColor(gROOT->GetColor(gPad->GetFillColor()));
       fGLPainter->AddOption(addOption);
    } else
       fPlotType = kGLDefaultPlot;
diff --git a/gl/src/TGLLegoPainter.cxx b/gl/src/TGLLegoPainter.cxx
index 8afb078d33fa74826c8da045752487326ed4b30f..173a411fbd0de5ca22cc10f5f8c9e140c4f6fca9 100644
--- a/gl/src/TGLLegoPainter.cxx
+++ b/gl/src/TGLLegoPainter.cxx
@@ -1,4 +1,4 @@
-// @(#)root/gl:$Name:  $:$Id: TGLLegoPainter.cxx,v 1.7 2006/11/22 16:19:55 couet Exp $
+// @(#)root/gl:$Name:  $:$Id: TGLLegoPainter.cxx,v 1.8 2006/11/24 15:57:45 couet Exp $
 // Author:  Timur Pocheptsov  14/06/2006
                                                                                 
 /*************************************************************************
@@ -901,17 +901,6 @@ void TGLLegoPainter::SetLegoColor()const
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
 }
 
-//______________________________________________________________________________
-void TGLLegoPainter::ClearBuffers()const
-{
-   //Clear buffer with pad's color.
-   Float_t rgb[3] = {1.f, 1.f, 1.f};
-   if (const TColor *color = GetPadColor())
-      color->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::DrawSectionXOZ()const
 {
diff --git a/gl/src/TGLParametric.cxx b/gl/src/TGLParametric.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ddb3614ab36e9412c3440e4ece8e56229848d780
--- /dev/null
+++ b/gl/src/TGLParametric.cxx
@@ -0,0 +1,610 @@
+// @(#)root/gl:$Name:  $:$Id: TGLParametric.cxx,v 1.1 Exp $
+// 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 "TGLOrthoCamera.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.
+   return "parametric surface";
+}
+
+//______________________________________________________________________________
+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,
+                                     TGLOrthoCamera *camera, Int_t context)
+                      : TGLPlotPainter(camera, context),
+                        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.
+   Bool_t constrained = 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;
+            if (!constrained) {
+               fEquation->EvalVertex(v1, u + dd, v);
+               fEquation->EvalVertex(v2, u, v + dd);
+               Normal2Plane(newVert.CArr(), v1.CArr(), v2.CArr(), fMesh[i][j].fNormal.Arr());
+            }
+            v += dV;
+         }
+         u += dU;
+      }
+
+      const Double_t xRange = max.X() - min.X(), yRange = max.Y() - min.Y(), zRange = max.Z() - min.Z();
+
+      if (!xRange || !yRange || !zRange) {
+         Error("InitGeometry", "Zero axis range");
+         return kFALSE;
+      }
+
+      Double_t maxRange = Max(Max(xRange, yRange), zRange);
+      const Double_t xZoom = maxRange / xRange, yZoom = maxRange / yRange, zZoom = maxRange / zRange;
+
+      if (constrained) {
+         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;
+               ver.X() *= xZoom, ver.Y() *= yZoom, ver.Z() *= zZoom;
+               fEquation->EvalVertex(v1, u + dd, v);
+               fEquation->EvalVertex(v2, u, v + dd);
+               v1.X() *= xZoom, v1.Y() *= yZoom, v1.Z() *= zZoom;
+               v2.X() *= xZoom, v2.Y() *= yZoom, v2.Z() *= zZoom;
+               Normal2Plane(ver.CArr(), v1.CArr(), v2.CArr(), fMesh[i][j].fNormal.Arr());
+               v += dV;
+            }
+            u += dU;
+         }
+      }
+
+      using Rgl::Range_t;
+      constrained ? fBackBox.SetPlotBox(Range_t(min.X(), max.X()), Range_t(min.Y(), max.Y()), Range_t(min.Z(), max.Z())):
+                    fBackBox.SetPlotBox(Range_t(min.X() * xZoom, max.X() * xZoom),
+                                        Range_t(min.Y() * yZoom, max.Y() * yZoom),
+                                        Range_t(min.Z() * zZoom, max.Z() * zZoom));
+      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 (!MakeGLContextCurrent())
+      return;
+
+   if (fSelectedPart) {
+      if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis))
+         fBoxCut.MoveBox(px, fCamera->GetHeight() - py, fSelectedPart);
+      else
+         fCamera->Pan(px, py);
+   }
+
+   fUpdateSelection = kTRUE;
+}
+
+//______________________________________________________________________________
+char *TGLParametricPlot::GetPlotInfo(Int_t /*px*/, Int_t /*py*/)
+{
+   //No object info yet.
+   return "parametric surface";
+}
+
+//______________________________________________________________________________
+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();
+      gGLManager->PaintSingleObject(this);
+   } 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::DrawPlot()const
+{
+   //Draw parametric surface.
+   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);
+   }
+}
diff --git a/gl/src/TGLPlotPainter.cxx b/gl/src/TGLPlotPainter.cxx
index 4a71c96e75d442f6aa285a58bab8650fefb71849..c72cd7616c9a7e572d18c4ce3bbe12b2c14183f2 100644
--- a/gl/src/TGLPlotPainter.cxx
+++ b/gl/src/TGLPlotPainter.cxx
@@ -1,4 +1,4 @@
-// @(#)root/gl:$Name:  $:$Id: TGLPlotPainter.cxx,v 1.10 2006/11/24 10:45:13 couet Exp $
+// @(#)root/gl:$Name:  $:$Id: TGLPlotPainter.cxx,v 1.11 2006/11/24 15:57:45 couet Exp $
 // Author:  Timur Pocheptsov  14/06/2006
                                                                                 
 /*************************************************************************
@@ -13,6 +13,7 @@
 #include "TVirtualPS.h"
 #include "TStyle.h"
 #include "TError.h"
+#include "TColor.h"
 #include "TAxis.h"
 #include "TMath.h"
 #include "TH1.h"
@@ -52,6 +53,32 @@ TGLPlotPainter::TGLPlotPainter(TH1 *hist, TGLOrthoCamera *camera, TGLPlotCoordin
       fCamera->SetViewport(GetGLContext());
 }
 
+//______________________________________________________________________________
+TGLPlotPainter::TGLPlotPainter(TGLOrthoCamera *camera, Int_t context)
+                  : fGLContext(context),
+                    fPadColor(0),
+                    fHist(0),
+                    fXAxis(0),
+                    fYAxis(0),
+                    fZAxis(0),
+                    fCoord(0),
+                    fCamera(camera),
+                    fUpdateSelection(kTRUE),
+                    fSelectionPass(kFALSE),
+                    fSelectedPart(0),
+                    fXOZSectionPos(0.),
+                    fYOZSectionPos(0.),
+                    fXOYSectionPos(0.),
+                    fBackBox(kFALSE, kFALSE, kFALSE),
+                    fBoxCut(&fBackBox),
+                    fHighColor(kFALSE),
+                    fSelectionBase(kTrueColorSelectionBase)
+{
+   //TGLPlotPainter's ctor.
+   if (MakeGLContextCurrent())
+      fCamera->SetViewport(GetGLContext());
+}
+
 //______________________________________________________________________________
 void TGLPlotPainter::Paint()
 {
@@ -89,7 +116,7 @@ void TGLPlotPainter::Paint()
    //Here changes are possible in future, if we have real 3d axis painter.
    gGLManager->ReadGLBuffer(GetGLContext());
    //Select pixmap/DIB
-   if (fCoord->GetCoordType() == kGLCartesian) {
+   if (fCoord && fCoord->GetCoordType() == kGLCartesian) {
       gGLManager->SelectOffScreenDevice(GetGLContext());
       //Draw axes into pixmap/DIB
       Int_t viewport[] = {fCamera->GetX(), fCamera->GetY(), fCamera->GetWidth(), fCamera->GetHeight()};
@@ -409,6 +436,17 @@ void TGLPlotPainter::DrawSections()const
    }
 }
 
+//______________________________________________________________________________
+void TGLPlotPainter::ClearBuffers()const
+{
+   // Clear buffer.
+   Float_t rgb[3] = {1.f, 1.f, 1.f};
+   if (const TColor *color = GetPadColor())
+      color->GetRGB(rgb[0], rgb[1], rgb[2]);
+   glClearColor(rgb[0], rgb[1], rgb[2], 1.);
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
 ClassImp(TGLPlotCoordinates)
 
 //______________________________________________________________________________
diff --git a/gl/src/TGLSurfacePainter.cxx b/gl/src/TGLSurfacePainter.cxx
index c0bfd5b6b5efaa2c941745e6a20a2cd5d6de573a..d5d4179fa4747bda05435bd05c28d89e4448fa60 100644
--- a/gl/src/TGLSurfacePainter.cxx
+++ b/gl/src/TGLSurfacePainter.cxx
@@ -255,17 +255,6 @@ void TGLSurfacePainter::SetSurfaceColor()const
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 70.f);
 }
 
-//______________________________________________________________________________
-void TGLSurfacePainter::ClearBuffers()const
-{
-   //Clears gl buffers (possibly with pad's background color).
-   Float_t rgb[3] = {1.f, 1.f, 1.f};
-   if (GetPadColor())
-      GetPadColor()->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 TGLSurfacePainter::DrawPlot()const
 {
diff --git a/gl/src/TGLTF3Painter.cxx b/gl/src/TGLTF3Painter.cxx
index 453099c1543c9a29d9a431c1011a8f27bc24ff11..b10e89097cb2054486e9f53c0106e9a8572ad75f 100644
--- a/gl/src/TGLTF3Painter.cxx
+++ b/gl/src/TGLTF3Painter.cxx
@@ -147,17 +147,6 @@ void TGLTF3Painter::InitGL()const
    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 }
 
-//______________________________________________________________________________
-void TGLTF3Painter::ClearBuffers()const
-{
-   //Clears gl buffers (possibly with pad's background color).
-   Float_t rgb[3] = {1.f, 1.f, 1.f};
-   if (GetPadColor())
-      GetPadColor()->GetRGB(rgb[0], rgb[1], rgb[2]);
-   glClearColor(rgb[0], rgb[1], rgb[2], 1.);
-   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
 namespace {
    void GetColor(TGLVector3 &rfColor, const TGLVector3 &normal);
 }
diff --git a/gl/src/TGLUtil.cxx b/gl/src/TGLUtil.cxx
index 90fe724c1a41e34dd75f3a588902e3166120873a..6ee56c84cb6e13971ae9cc290ee8aa84449d2e86 100644
--- a/gl/src/TGLUtil.cxx
+++ b/gl/src/TGLUtil.cxx
@@ -1,4 +1,4 @@
-// @(#)root/gl:$Name:  $:$Id: TGLUtil.cxx,v 1.34 2007/01/15 11:30:47 brun Exp $
+// @(#)root/gl:$Name:  $:$Id: TGLUtil.cxx,v 1.35 2007/01/15 16:10:09 brun Exp $
 // Author:  Richard Maunder  25/05/2005
 
 /*************************************************************************
@@ -789,7 +789,7 @@ void TGLUtil::SetDrawColors(const Float_t rgba[4])
    // Util function to setup GL color for both unlit and lit material
    static Float_t ambient[4] = {0.0, 0.0, 0.0, 1.0};
    static Float_t specular[4] = {0.6, 0.6, 0.6, 1.0};
-   Float_t emission[4] = {rgba[0]/4.0, rgba[1]/4.0, rgba[2]/4.0, rgba[3]};
+   Float_t emission[4] = {rgba[0]/4.f, rgba[1]/4.f, rgba[2]/4.f, rgba[3]};
 
    glColor3d(rgba[0], rgba[1], rgba[2]);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, rgba);
@@ -1856,15 +1856,286 @@ namespace Rgl {
       glNormal3dv(normal.CArr());
       glTexCoord1d(t1);
       glVertex3d(v1.X(), v1.Y(), z);
-//      glNormal3dv(normal.CArr());
       glTexCoord1d(t2);
       glVertex3d(v2.X(), v2.Y(), z);
-//      glNormal3dv(normal.CArr());
       glTexCoord1d(t3);
       glVertex3d(v3.X(), v3.Y(), z);
       glEnd();   
    }
 
+   //______________________________________________________________________________
+   void GetColor(Float_t v, Float_t vmin, Float_t vmax, Int_t type, Float_t *rgba)
+   {
+      //This function creates color for parametric surface's vertex,
+      //using its 'u' value.
+      //I've found it in one of Apple's Carbon tutorials , and it's based
+      //on Paul Bourke work. Very nice colors!!! :)
+      Float_t dv,vmid;
+      //Float_t c[] = {1.f, 1.f, 1.f};
+      Float_t c1[3] = {}, c2[3] = {}, c3[3] = {};
+      Float_t ratio ;
+      rgba[3] = 1.f;
+
+      if (v < vmin)
+         v = vmin;
+      if (v > vmax)
+         v = vmax;
+      dv = vmax - vmin;
+
+      switch (type) {
+      case 0:
+         rgba[0] = 1.f;
+         rgba[1] = 1.f;
+         rgba[2] = 1.f;
+      break;
+      case 1:
+      if (v < (vmin + 0.25 * dv)) {
+         rgba[0] = 0;
+         rgba[1] = 4 * (v - vmin) / dv;
+         rgba[2] = 1;
+      } else if (v < (vmin + 0.5 * dv)) {
+         rgba[0] = 0;
+         rgba[1] = 1;
+         rgba[2] = 1 + 4 * (vmin + 0.25 * dv - v) / dv;
+      } else if (v < (vmin + 0.75 * dv)) {
+         rgba[0] = 4 * (v - vmin - 0.5 * dv) / dv;
+         rgba[1] = 1;
+         rgba[2] = 0;
+      } else {
+         rgba[0] = 1;
+         rgba[1] = 1 + 4 * (vmin + 0.75 * dv - v) / dv;
+         rgba[2] = 0;
+      }
+      break;
+      case 2:
+         rgba[0] = (v - vmin) / dv;
+         rgba[1] = 0;
+         rgba[2] = (vmax - v) / dv;
+         break;
+      case 3:
+         rgba[0] = (v - vmin) / dv;
+         rgba[1] = rgba[0];
+         rgba[2] = rgba[0];
+         break;
+      case 4:
+         if (v < (vmin + dv / 6.0)) {
+            rgba[0] = 1;
+            rgba[1] = 6 * (v - vmin) / dv;
+            rgba[2] = 0;
+         } else if (v < (vmin + 2.0 * dv / 6.0)) {
+            rgba[0] = 1 + 6 * (vmin + dv / 6.0 - v) / dv;
+            rgba[1] = 1;
+            rgba[2] = 0;
+         } else if (v < (vmin + 3.0 * dv / 6.0)) {
+            rgba[0] = 0;
+            rgba[1] = 1;
+            rgba[2] = 6 * (v - vmin - 2.0 * dv / 6.0) / dv;
+         } else if (v < (vmin + 4.0 * dv / 6.0)) {
+            rgba[0] = 0;
+            rgba[1] = 1 + 6 * (vmin + 3.0 * dv / 6.0 - v) / dv;
+            rgba[2] = 1;
+         } else if (v < (vmin + 5.0 * dv / 6.0)) {
+            rgba[0] = 6 * (v - vmin - 4.0 * dv / 6.0) / dv;
+            rgba[1] = 0;
+            rgba[2] = 1;
+         } else {
+            rgba[0] = 1;
+            rgba[1] = 0;
+            rgba[2] = 1 + 6 * (vmin + 5.0 * dv / 6.0 - v) / dv;
+         }
+         break;
+      case 5:
+         rgba[0] = (v - vmin) / (vmax - vmin);
+         rgba[1] = 1;
+         rgba[2] = 0;
+         break;
+      case 6:
+         rgba[0] = (v - vmin) / (vmax - vmin);
+         rgba[1] = (vmax - v) / (vmax - vmin);
+         rgba[2] = rgba[0];
+         break;
+      case 7:
+         if (v < (vmin + 0.25 * dv)) {
+            rgba[0] = 0;
+            rgba[1] = 4 * (v - vmin) / dv;
+            rgba[2] = 1 - rgba[1];
+         } else if (v < (vmin + 0.5 * dv)) {
+            rgba[0] = 4 * (v - vmin - 0.25 * dv) / dv;
+            rgba[1] = 1 - rgba[0];
+            rgba[2] = 0;
+         } else if (v < (vmin + 0.75 * dv)) {
+            rgba[1] = 4 * (v - vmin - 0.5 * dv) / dv;
+            rgba[0] = 1 - rgba[1];
+            rgba[2] = 0;
+         } else {
+            rgba[0] = 0;
+            rgba[2] = 4 * (v - vmin - 0.75 * dv) / dv;
+            rgba[1] = 1 - rgba[2];
+         }
+         break;
+      case 8:
+         if (v < (vmin + 0.5 * dv)) {
+            rgba[0] = 2 * (v - vmin) / dv;
+            rgba[1] = rgba[0];
+            rgba[2] = rgba[0];
+         } else {
+            rgba[0] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
+            rgba[1] = rgba[0];
+            rgba[2] = rgba[0];
+         }
+         break;
+      case 9:
+         if (v < (vmin + dv / 3)) {
+            rgba[2] = 3 * (v - vmin) / dv;
+            rgba[1] = 0;
+            rgba[0] = 1 - rgba[2];
+         } else if (v < (vmin + 2 * dv / 3)) {
+            rgba[0] = 0;
+            rgba[1] = 3 * (v - vmin - dv / 3) / dv;
+            rgba[2] = 1;
+         } else {
+            rgba[0] = 3 * (v - vmin - 2 * dv / 3) / dv;
+            rgba[1] = 1 - rgba[0];
+            rgba[2] = 1;
+         }
+         break;
+      case 10:
+         if (v < (vmin + 0.2 * dv)) {
+            rgba[0] = 0;
+            rgba[1] = 5 * (v - vmin) / dv;
+            rgba[2] = 1;
+         } else if (v < (vmin + 0.4 * dv)) {
+            rgba[0] = 0;
+            rgba[1] = 1;
+            rgba[2] = 1 + 5 * (vmin + 0.2 * dv - v) / dv;
+         } else if (v < (vmin + 0.6 * dv)) {
+            rgba[0] = 5 * (v - vmin - 0.4 * dv) / dv;
+            rgba[1] = 1;
+            rgba[2] = 0;
+         } else if (v < (vmin + 0.8 * dv)) {
+            rgba[0] = 1;
+            rgba[1] = 1 - 5 * (v - vmin - 0.6 * dv) / dv;
+            rgba[2] = 0;
+         } else {
+            rgba[0] = 1;
+            rgba[1] = 5 * (v - vmin - 0.8 * dv) / dv;
+            rgba[2] = 5 * (v - vmin - 0.8 * dv) / dv;
+         }
+         break;
+      case 11:
+         c1[0] = 200 / 255.0; c1[1] =  60 / 255.0; c1[2] =   0 / 255.0;
+         c2[0] = 250 / 255.0; c2[1] = 160 / 255.0; c2[2] = 110 / 255.0;
+         rgba[0] = (c2[0] - c1[0]) * (v - vmin) / dv + c1[0];
+         rgba[1] = (c2[1] - c1[1]) * (v - vmin) / dv + c1[1];
+         rgba[2] = (c2[2] - c1[2]) * (v - vmin) / dv + c1[2];
+         break;
+      case 12:
+         c1[0] =  55 / 255.0; c1[1] =  55 / 255.0; c1[2] =  45 / 255.0;
+         c2[0] = 200 / 255.0; c2[1] =  60 / 255.0; c2[2] =   0 / 255.0;
+         c3[0] = 250 / 255.0; c3[1] = 160 / 255.0; c3[2] = 110 / 255.0;
+         ratio = 0.4;
+         vmid = vmin + ratio * dv;
+         if (v < vmid) {
+            rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
+            rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
+            rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
+         } else {
+            rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
+            rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
+            rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
+         }
+         break;
+      case 13:
+         c1[0] =   0 / 255.0; c1[1] = 255 / 255.0; c1[2] =   0 / 255.0;
+         c2[0] = 255 / 255.0; c2[1] = 150 / 255.0; c2[2] =   0 / 255.0;
+         c3[0] = 255 / 255.0; c3[1] = 250 / 255.0; c3[2] = 240 / 255.0;
+         ratio = 0.3;
+         vmid = vmin + ratio * dv;
+         if (v < vmid) {
+            rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
+            rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
+            rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
+         } else {
+            rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
+            rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
+            rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
+         }
+         break;
+      case 14:
+         rgba[0] = 1;
+         rgba[1] = 1 - (v - vmin) / dv;
+         rgba[2] = 0;
+         break;
+      case 15:
+         if (v < (vmin + 0.25 * dv)) {
+            rgba[0] = 0;
+            rgba[1] = 4 * (v - vmin) / dv;
+            rgba[2] = 1;
+         } else if (v < (vmin + 0.5 * dv)) {
+            rgba[0] = 0;
+            rgba[1] = 1;
+            rgba[2] = 1 - 4 * (v - vmin - 0.25 * dv) / dv;
+         } else if (v < (vmin + 0.75 * dv)) {
+            rgba[0] = 4 * (v - vmin - 0.5 * dv) / dv;
+            rgba[1] = 1;
+            rgba[2] = 0;
+         } else {
+            rgba[0] = 1;
+            rgba[1] = 1;
+            rgba[2] = 4 * (v - vmin - 0.75 * dv) / dv;
+         }
+         break;
+      case 16:
+         if (v < (vmin + 0.5 * dv)) {
+            rgba[0] = 0.0;
+            rgba[1] = 2 * (v - vmin) / dv;
+            rgba[2] = 1 - 2 * (v - vmin) / dv;
+         } else {
+            rgba[0] = 2 * (v - vmin - 0.5 * dv) / dv;
+            rgba[1] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
+            rgba[2] = 0.0;
+         }
+         break;
+      case 17:
+         if (v < (vmin + 0.5 * dv)) {
+            rgba[0] = 1.0;
+            rgba[1] = 1 - 2 * (v - vmin) / dv;
+            rgba[2] = 2 * (v - vmin) / dv;
+         } else {
+            rgba[0] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
+            rgba[1] = 2 * (v - vmin - 0.5 * dv) / dv;
+            rgba[2] = 1.0;
+         }
+         break;
+      case 18:
+         rgba[0] = 0;
+         rgba[1] = (v - vmin) / (vmax - vmin);
+         rgba[2] = 1;
+         break;
+      case 19:
+         rgba[0] = (v - vmin) / (vmax - vmin);
+         rgba[1] = rgba[0];
+         rgba[2] = 1;
+         break;
+      case 20:
+         c1[0] =   0 / 255.0; c1[1] = 160 / 255.0; c1[2] =   0 / 255.0;
+         c2[0] = 180 / 255.0; c2[1] = 220 / 255.0; c2[2] =   0 / 255.0;
+         c3[0] = 250 / 255.0; c3[1] = 220 / 255.0; c3[2] = 170 / 255.0;
+         ratio = 0.3;
+         vmid = vmin + ratio * dv;
+         if (v < vmid) {
+            rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
+            rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
+            rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
+         } else {
+            rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
+            rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
+            rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
+         }
+         break;
+      }
+   }
+
 }
 
 //______________________________________________________________________________