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; + } + } + } //______________________________________________________________________________