TGLUtil.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TGLUtil.cxx 36560 2010-11-09 15:26:23Z couet $
00002 // Author:  Richard Maunder  25/05/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include <algorithm>
00013 #include <string>
00014 #include <map>
00015 
00016 #include "THLimitsFinder.h"
00017 #include "TVirtualPad.h"
00018 #include "TVirtualX.h"
00019 #include "Riostream.h"
00020 #include "TStyle.h"
00021 #include "TGaxis.h"
00022 #include "TColor.h"
00023 #include "TError.h"
00024 #include "TH1.h"
00025 #include "TMath.h"
00026 #include "TROOT.h"
00027 #include "TClass.h"
00028 
00029 #include "TGLBoundingBox.h"
00030 #include "TGLCamera.h"
00031 #include "TGLPlotPainter.h"
00032 #include "TGLIncludes.h"
00033 #include "TGLQuadric.h"
00034 #include "TGLUtil.h"
00035 
00036 //////////////////////////////////////////////////////////////////////////
00037 //                                                                      //
00038 // TGLVertex3                                                           //
00039 //                                                                      //
00040 // 3 component (x/y/z) vertex class                                     //
00041 //                                                                      //
00042 // This is part of collection of simple utility classes for GL only in  //
00043 // TGLUtil.h/cxx. These provide const and non-const accessors Arr() &   //
00044 // CArr() to a GL compatible internal field - so can be used directly   //
00045 // with OpenGL C API calls - which TVector3 etc cannot (easily).        //
00046 // They are not intended to be fully featured just provide minimum      //
00047 // required.                                                            //
00048 //////////////////////////////////////////////////////////////////////////
00049 
00050 ClassImp(TGLVertex3);
00051 
00052 //______________________________________________________________________________
00053 TGLVertex3::TGLVertex3()
00054 {
00055    // Construct a default (0.0, 0.0, 0.0) vertex
00056    Fill(0.0);
00057 }
00058 
00059 //______________________________________________________________________________
00060 TGLVertex3::TGLVertex3(Double_t x, Double_t y, Double_t z)
00061 {
00062    // Construct a vertex with components (x,y,z)
00063    Set(x,y,z);
00064 }
00065 
00066 //______________________________________________________________________________
00067 TGLVertex3::TGLVertex3(Double_t* v)
00068 {
00069    // Construct a vertex with components (v[0], v[1], v[2])
00070    Set(v[0], v[1], v[2]);
00071 }
00072 
00073 //______________________________________________________________________________
00074 TGLVertex3::TGLVertex3(const TGLVertex3 & other)
00075 {
00076    // Construct a vertex from 'other'
00077    Set(other);
00078 }
00079 
00080 //______________________________________________________________________________
00081 TGLVertex3::~TGLVertex3()
00082 {
00083    // Destroy vertex object
00084 }
00085 
00086 //______________________________________________________________________________
00087 void TGLVertex3::Shift(TGLVector3 & shift)
00088 {
00089    // Offset a vertex by vector 'shift'
00090    fVals[0] += shift[0];
00091    fVals[1] += shift[1];
00092    fVals[2] += shift[2];
00093 }
00094 
00095 //______________________________________________________________________________
00096 void TGLVertex3::Shift(Double_t xDelta, Double_t yDelta, Double_t zDelta)
00097 {
00098    // Offset a vertex by components (xDelta, yDelta, zDelta)
00099    fVals[0] += xDelta;
00100    fVals[1] += yDelta;
00101    fVals[2] += zDelta;
00102 }
00103 
00104 //______________________________________________________________________________
00105 void TGLVertex3::Minimum(const TGLVertex3 & other)
00106 {
00107    fVals[0] = TMath::Min(fVals[0], other.fVals[0]);
00108    fVals[1] = TMath::Min(fVals[1], other.fVals[1]);
00109    fVals[2] = TMath::Min(fVals[2], other.fVals[2]);
00110 }
00111 
00112 //______________________________________________________________________________
00113 void TGLVertex3::Maximum(const TGLVertex3 & other)
00114 {
00115    fVals[0] = TMath::Max(fVals[0], other.fVals[0]);
00116    fVals[1] = TMath::Max(fVals[1], other.fVals[1]);
00117    fVals[2] = TMath::Max(fVals[2], other.fVals[2]);
00118 }
00119 
00120 //______________________________________________________________________________
00121 void TGLVertex3::Dump() const
00122 {
00123    // Output vertex component values to std::cout
00124    std::cout << "(" << fVals[0] << "," << fVals[1] << "," << fVals[2] << ")" << std::endl;
00125 }
00126 
00127 //////////////////////////////////////////////////////////////////////////
00128 //                                                                      //
00129 // TGLVector3                                                           //
00130 //                                                                      //
00131 // 3 component (x/y/z) vector class                                     //
00132 //                                                                      //
00133 // This is part of collection of utility classes for GL in TGLUtil.h/cxx//
00134 // These provide const and non-const accessors Arr() / CArr() to a GL   //
00135 // compatible internal field - so can be used directly with OpenGL C API//
00136 // calls. They are not intended to be fully featured just provide       //
00137 // minimum required.                                                    //
00138 //////////////////////////////////////////////////////////////////////////
00139 
00140 ClassImp(TGLVector3);
00141 
00142 //______________________________________________________________________________
00143 TGLVector3::TGLVector3() :
00144    TGLVertex3()
00145 {
00146    // Construct a default (0.0, 0.0, 0.0) vector
00147 }
00148 
00149 //______________________________________________________________________________
00150 TGLVector3::TGLVector3(Double_t x, Double_t y, Double_t z) :
00151    TGLVertex3(x, y, z)
00152 {
00153    // Construct a vector with components (x,y,z)
00154 }
00155 
00156 //______________________________________________________________________________
00157 TGLVector3::TGLVector3(const TGLVector3 & other) :
00158    TGLVertex3(other.fVals[0], other.fVals[1], other.fVals[2])
00159 {
00160    // Construct a vector from components of 'other'
00161 }
00162 
00163 //______________________________________________________________________________
00164 TGLVector3::TGLVector3(const Double_t *src) :
00165    TGLVertex3(src[0], src[1], src[2])
00166 {
00167    // Construct a vector with components (src[0], src[1], src[2])
00168 }
00169 
00170 //______________________________________________________________________________
00171 TGLVector3::~TGLVector3()
00172 {
00173    // Destroy vector object
00174 }
00175 
00176 //////////////////////////////////////////////////////////////////////////
00177 //                                                                      //
00178 // TGLLine3                                                             //
00179 //                                                                      //
00180 // 3D space, fixed length, line class, with direction / length 'vector',//
00181 // passing through point 'vertex'. Just wraps a TGLVector3 / TGLVertex3 //
00182 // pair.                                                                //
00183 //////////////////////////////////////////////////////////////////////////
00184 
00185 ClassImp(TGLLine3);
00186 
00187 //______________________________________________________________________________
00188 TGLLine3::TGLLine3(const TGLVertex3 & start, const TGLVertex3 & end) :
00189    fVertex(start), fVector(end - start)
00190 {
00191    // Construct 3D line running from 'start' to 'end'
00192 }
00193 
00194 //______________________________________________________________________________
00195 TGLLine3::TGLLine3(const TGLVertex3 & start, const TGLVector3 & vect) :
00196    fVertex(start), fVector(vect)
00197 {
00198    // Construct 3D line running from 'start', magnitude 'vect'
00199 }
00200 
00201 //______________________________________________________________________________
00202 TGLLine3::~TGLLine3()
00203 {
00204    // Destroy 3D line object
00205 }
00206 
00207 //______________________________________________________________________________
00208 void TGLLine3::Set(const TGLVertex3 & start, const TGLVertex3 & end)
00209 {
00210    // Set 3D line running from 'start' to 'end'
00211 
00212    fVertex = start;
00213    fVector = end - start;
00214 }
00215 
00216 //______________________________________________________________________________
00217 void TGLLine3::Set(const TGLVertex3 & start, const TGLVector3 & vect)
00218 {
00219    // Set 3D line running from start, magnitude 'vect'
00220    fVertex = start;
00221    fVector = vect;
00222 }
00223 
00224 //______________________________________________________________________________
00225 void TGLLine3::Draw() const
00226 {
00227    // Draw line in current basic GL color. Assume we are in the correct reference
00228    // frame
00229    glBegin(GL_LINE_LOOP);
00230    glVertex3dv(fVertex.CArr());
00231    glVertex3dv(End().CArr());
00232    glEnd();
00233 }
00234 
00235 //////////////////////////////////////////////////////////////////////////
00236 //                                                                      //
00237 // TGLRect                                                              //
00238 //                                                                      //
00239 // Viewport (pixel base) 2D rectangle class                             //
00240 //////////////////////////////////////////////////////////////////////////
00241 
00242 ClassImp(TGLRect);
00243 
00244 //______________________________________________________________________________
00245 TGLRect::TGLRect() :
00246       fX(0), fY(0), fWidth(0), fHeight(0)
00247 {
00248    // Construct empty rect object, corner (0,0), width/height 0
00249 }
00250 
00251 //______________________________________________________________________________
00252 TGLRect::TGLRect(Int_t x, Int_t y, Int_t width, Int_t height) :
00253       fX(x), fY(y), fWidth(width), fHeight(height)
00254 {
00255    // Construct rect object, corner (x,y), dimensions 'width', 'height'
00256 }
00257 
00258 //______________________________________________________________________________
00259 TGLRect::TGLRect(Int_t x, Int_t y, UInt_t width, UInt_t height) :
00260       fX(x), fY(y), fWidth(width), fHeight(height)
00261 {
00262    // Construct rect object, corner (x,y), dimensions 'width', 'height'
00263 }
00264 
00265 
00266 //______________________________________________________________________________
00267 TGLRect::~TGLRect()
00268 {
00269    // Destroy rect object
00270 }
00271 
00272 //______________________________________________________________________________
00273 void TGLRect::Expand(Int_t x, Int_t y)
00274 {
00275    // Expand the rect to encompass point (x,y)
00276    Int_t delX = x - fX;
00277    Int_t delY = y - fY;
00278 
00279    if (delX > fWidth) {
00280       fWidth = delX;
00281    }
00282    if (delY > fHeight) {
00283       fHeight = delY;
00284    }
00285 
00286    if (delX < 0) {
00287       fX = x;
00288       fWidth += -delX;
00289    }
00290    if (delY < 0) {
00291       fY = y;
00292       fHeight += -delY;
00293    }
00294 }
00295 
00296 //______________________________________________________________________________
00297 Int_t TGLRect::Diagonal() const
00298 {
00299    // Return the diagonal of the rectangle.
00300 
00301    const Double_t w = static_cast<Double_t>(fWidth);
00302    const Double_t h = static_cast<Double_t>(fHeight);
00303    return TMath::Nint(TMath::Sqrt(w*w + h*h));
00304 }
00305 
00306 //______________________________________________________________________________
00307 EOverlap TGLRect::Overlap(const TGLRect & other) const
00308 {
00309    // Return overlap result (kInside, kOutside, kPartial) of this
00310    // rect with 'other'
00311    if ((fX <= other.fX) && (fX + fWidth >= other.fX + other.fWidth) &&
00312        (fY <= other.fY) && (fY +fHeight >= other.fY + other.fHeight)) {
00313       return kInside;
00314    }
00315    else if ((fX >= other.fX + static_cast<Int_t>(other.fWidth)) ||
00316             (fX + static_cast<Int_t>(fWidth) <= other.fX) ||
00317             (fY >= other.fY + static_cast<Int_t>(other.fHeight)) ||
00318             (fY + static_cast<Int_t>(fHeight) <= other.fY)) {
00319       return kOutside;
00320    } else {
00321       return kPartial;
00322    }
00323 }
00324 
00325 //////////////////////////////////////////////////////////////////////////
00326 //                                                                      //
00327 // TGLPlane                                                             //
00328 //                                                                      //
00329 // 3D plane class - of format Ax + By + Cz + D = 0                      //
00330 //                                                                      //
00331 // This is part of collection of simple utility classes for GL only in  //
00332 // TGLUtil.h/cxx. These provide const and non-const accessors Arr() &   //
00333 // CArr() to a GL compatible internal field - so can be used directly   //
00334 // with OpenGL C API calls - which TVector3 etc cannot (easily).        //
00335 // They are not intended to be fully featured just provide minimum      //
00336 // required.                                                            //
00337 //////////////////////////////////////////////////////////////////////////
00338 
00339 ClassImp(TGLPlane);
00340 
00341 //______________________________________________________________________________
00342 TGLPlane::TGLPlane()
00343 {
00344    // Construct a default plane of x + y + z = 0
00345    Set(1.0, 1.0, 1.0, 0.0);
00346 }
00347 
00348 //______________________________________________________________________________
00349 TGLPlane::TGLPlane(const TGLPlane & other)
00350 {
00351    // Construct plane from 'other'
00352    Set(other);
00353 }
00354 
00355 //______________________________________________________________________________
00356 TGLPlane::TGLPlane(Double_t a, Double_t b, Double_t c, Double_t d)
00357 {
00358    // Construct plane with equation a.x + b.y + c.z + d = 0
00359    // with optional normalisation
00360    Set(a, b, c, d);
00361 }
00362 
00363 //______________________________________________________________________________
00364 TGLPlane::TGLPlane(Double_t eq[4])
00365 {
00366    // Construct plane with equation eq[0].x + eq[1].y + eq[2].z + eq[3] = 0
00367    // with optional normalisation
00368    Set(eq);
00369 }
00370 
00371 //______________________________________________________________________________
00372 TGLPlane::TGLPlane(const TGLVertex3 & p1, const TGLVertex3 & p2,
00373                    const TGLVertex3 & p3)
00374 {
00375    // Construct plane passing through 3 supplied points
00376    // with optional normalisation
00377    Set(p1, p2, p3);
00378 }
00379 
00380 //______________________________________________________________________________
00381 TGLPlane::TGLPlane(const TGLVector3 & v, const TGLVertex3 & p)
00382 {
00383    // Construct plane with supplied normal vector, passing through point
00384    // with optional normalisation
00385    Set(v, p);
00386 }
00387 
00388 //______________________________________________________________________________
00389 TGLPlane::~TGLPlane()
00390 {
00391    // Destroy plane object
00392 }
00393 
00394 //______________________________________________________________________________
00395 void TGLPlane::Normalise()
00396 {
00397    // Normalise the plane.
00398 
00399    Double_t mag = sqrt(fVals[0]*fVals[0] + fVals[1]*fVals[1] + fVals[2]*fVals[2]);
00400 
00401    if (mag == 0.0 ) {
00402       Error("TGLPlane::Normalise", "trying to normalise plane with zero magnitude normal");
00403       return;
00404    }
00405    mag = 1.0 / mag;
00406    fVals[0] *= mag;
00407    fVals[1] *= mag;
00408    fVals[2] *= mag;
00409    fVals[3] *= mag;
00410 }
00411 
00412 //______________________________________________________________________________
00413 void TGLPlane::Dump() const
00414 {
00415    // Output plane equation to std::out
00416 
00417    std::cout.precision(6);
00418    std::cout << "Plane : " << fVals[0] << "x + " << fVals[1] << "y + " << fVals[2] << "z + " << fVals[3] << std::endl;
00419 }
00420 
00421 //______________________________________________________________________________
00422 void TGLPlane::Set(const TGLPlane & other)
00423 {
00424    // Assign from other.
00425 
00426    fVals[0] = other.fVals[0];
00427    fVals[1] = other.fVals[1];
00428    fVals[2] = other.fVals[2];
00429    fVals[3] = other.fVals[3];
00430 }
00431 
00432 //______________________________________________________________________________
00433 void TGLPlane::Set(Double_t a, Double_t b, Double_t c, Double_t d)
00434 {
00435    // Set by values.
00436 
00437    fVals[0] = a;
00438    fVals[1] = b;
00439    fVals[2] = c;
00440    fVals[3] = d;
00441    Normalise();
00442 }
00443 
00444 //______________________________________________________________________________
00445 void TGLPlane::Set(Double_t eq[4])
00446 {
00447    // Set by array values.
00448 
00449    fVals[0] = eq[0];
00450    fVals[1] = eq[1];
00451    fVals[2] = eq[2];
00452    fVals[3] = eq[3];
00453    Normalise();
00454 }
00455 
00456 //______________________________________________________________________________
00457 void TGLPlane::Set(const TGLVector3 & norm, const TGLVertex3 & point)
00458 {
00459    // Set plane from a normal vector and in-plane point pair
00460 
00461    fVals[0] = norm[0];
00462    fVals[1] = norm[1];
00463    fVals[2] = norm[2];
00464    fVals[3] = -(fVals[0]*point[0] + fVals[1]*point[1] + fVals[2]*point[2]);
00465    Normalise();
00466 }
00467 
00468 //______________________________________________________________________________
00469 void TGLPlane::Set(const TGLVertex3 & p1, const TGLVertex3 & p2, const TGLVertex3 & p3)
00470 {
00471    // Set plane by three points.
00472 
00473    TGLVector3 norm = Cross(p2 - p1, p3 - p1);
00474    Set(norm, p2);
00475 }
00476 
00477 //______________________________________________________________________________
00478 void TGLPlane::Negate()
00479 {
00480    // Negate the plane.
00481 
00482    fVals[0] = -fVals[0];
00483    fVals[1] = -fVals[1];
00484    fVals[2] = -fVals[2];
00485    fVals[3] = -fVals[3];
00486 }
00487 
00488 //______________________________________________________________________________
00489 Double_t TGLPlane::DistanceTo(const TGLVertex3 & vertex) const
00490 {
00491    // Distance from plane to vertex.
00492 
00493    return (fVals[0]*vertex[0] + fVals[1]*vertex[1] + fVals[2]*vertex[2] + fVals[3]);
00494 }
00495 
00496 //______________________________________________________________________________
00497 TGLVertex3 TGLPlane::NearestOn(const TGLVertex3 & point) const
00498 {
00499    // Return nearest point on plane.
00500 
00501    TGLVector3 o = Norm() * (Dot(Norm(), TGLVector3(point[0], point[1], point[2])) + D() / Dot(Norm(), Norm()));
00502    TGLVertex3 v = point - o;
00503    return v;
00504 }
00505 
00506 // Some free functions for plane intersections
00507 
00508 //______________________________________________________________________________
00509 std::pair<Bool_t, TGLLine3> Intersection(const TGLPlane & p1, const TGLPlane & p2)
00510 {
00511    // Find 3D line interestion of this plane with 'other'. Returns a std::pair
00512    //
00513    // first (Bool_t)                   second (TGLLine3)
00514    // kTRUE - planes intersect         intersection line between planes
00515    // kFALSE - no intersect (parallel) undefined
00516    TGLVector3 lineDir = Cross(p1.Norm(), p2.Norm());
00517 
00518    if (lineDir.Mag() == 0.0) {
00519       return std::make_pair(kFALSE, TGLLine3(TGLVertex3(0.0, 0.0, 0.0),
00520                                              TGLVector3(0.0, 0.0, 0.0)));
00521    }
00522    TGLVertex3 linePoint = Cross((p1.Norm()*p2.D() - p2.Norm()*p1.D()), lineDir) /
00523                            Dot(lineDir, lineDir);
00524    return std::make_pair(kTRUE, TGLLine3(linePoint, lineDir));
00525 }
00526 
00527 //______________________________________________________________________________
00528 std::pair<Bool_t, TGLVertex3> Intersection(const TGLPlane & p1, const TGLPlane & p2, const TGLPlane & p3)
00529 {
00530    Double_t denom = Dot(p1.Norm(), Cross(p2.Norm(), p3.Norm()));
00531    if (denom == 0.0) {
00532       return std::make_pair(kFALSE, TGLVertex3(0.0, 0.0, 0.0));
00533    }
00534    TGLVector3 vect = ((Cross(p2.Norm(),p3.Norm())* -p1.D()) -
00535                       (Cross(p3.Norm(),p1.Norm())*p2.D()) -
00536                       (Cross(p1.Norm(),p2.Norm())*p3.D())) / denom;
00537    TGLVertex3 interVert(vect.X(), vect.Y(), vect.Z());
00538    return std::make_pair(kTRUE, interVert);
00539 }
00540 
00541 //______________________________________________________________________________
00542 std::pair<Bool_t, TGLVertex3> Intersection(const TGLPlane & plane, const TGLLine3 & line, Bool_t extend)
00543 {
00544    // Find intersection of 3D space 'line' with this plane. If 'extend' is kTRUE
00545    // then line extents can be extended (infinite length) to find intersection.
00546    // If 'extend' is kFALSE the fixed extents of line is respected.
00547    //
00548    // The return a std::pair
00549    //
00550    // first (Bool_t)                   second (TGLVertex3)
00551    // kTRUE - line/plane intersect     intersection vertex on plane
00552    // kFALSE - no line/plane intersect undefined
00553    //
00554    // If intersection is not found (first == kFALSE) & 'extend' was kTRUE (infinite line)
00555    // this implies line and plane are parallel. If 'extend' was kFALSE, then
00556    // either line parallel or insuffient length.
00557    Double_t denom = -(plane.A()*line.Vector().X() +
00558                       plane.B()*line.Vector().Y() +
00559                       plane.C()*line.Vector().Z());
00560 
00561    if (denom == 0.0) {
00562       return std::make_pair(kFALSE, TGLVertex3(0.0, 0.0, 0.0));
00563    }
00564 
00565    Double_t num = plane.A()*line.Start().X() + plane.B()*line.Start().Y() +
00566                   plane.C()*line.Start().Z() + plane.D();
00567    Double_t factor = num/denom;
00568 
00569    // If not extending (projecting) line is length from start enough to reach plane?
00570    if (!extend && (factor < 0.0 || factor > 1.0)) {
00571       return std::make_pair(kFALSE, TGLVertex3(0.0, 0.0, 0.0));
00572    }
00573 
00574    TGLVector3 toPlane = line.Vector() * factor;
00575    return std::make_pair(kTRUE, line.Start() + toPlane);
00576 }
00577 
00578 //////////////////////////////////////////////////////////////////////////
00579 //                                                                      //
00580 // TGLMatrix                                                            //
00581 //                                                                      //
00582 // 16 component (4x4) transform matrix - column MAJOR as per GL.        //
00583 // Provides limited support for adjusting the translation, scale and    //
00584 // rotation components.                                                 //
00585 //                                                                      //
00586 // This is part of collection of simple utility classes for GL only in  //
00587 // TGLUtil.h/cxx. These provide const and non-const accessors Arr() &   //
00588 // CArr() to a GL compatible internal field - so can be used directly   //
00589 // with OpenGL C API calls - which TVector3 etc cannot (easily).        //
00590 // They are not intended to be fully featured just provide minimum      //
00591 // required.                                                            //
00592 //////////////////////////////////////////////////////////////////////////
00593 
00594 ClassImp(TGLMatrix);
00595 
00596 //______________________________________________________________________________
00597 TGLMatrix::TGLMatrix()
00598 {
00599    // Construct default identity matrix:
00600    //
00601    // 1 0 0 0
00602    // 0 1 0 0
00603    // 0 0 1 0
00604    // 0 0 0 1
00605    SetIdentity();
00606 }
00607 
00608 //______________________________________________________________________________
00609 TGLMatrix::TGLMatrix(Double_t x, Double_t y, Double_t z)
00610 {
00611    // Construct matrix with translation components x,y,z:
00612    //
00613    // 1 0 0 x
00614    // 0 1 0 y
00615    // 0 0 1 z
00616    // 0 0 0 1
00617    SetIdentity();
00618    SetTranslation(x, y, z);
00619 }
00620 
00621 //______________________________________________________________________________
00622 TGLMatrix::TGLMatrix(const TGLVertex3 & translation)
00623 {
00624    // Construct matrix with translation components x,y,z:
00625    //
00626    // 1 0 0 translation.X()
00627    // 0 1 0 translation.Y()
00628    // 0 0 1 translation.Z()
00629    // 0 0 0 1
00630    SetIdentity();
00631    SetTranslation(translation);
00632 }
00633 
00634 //______________________________________________________________________________
00635 TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis)
00636 {
00637    // Construct matrix which when applied puts local origin at
00638    // 'origin' and the local Z axis in direction 'z'. Both
00639    // 'origin' and 'zAxisVec' are expressed in the parent frame
00640    SetIdentity();
00641 
00642    TGLVector3 zAxisInt(zAxis);
00643    zAxisInt.Normalise();
00644    TGLVector3 arbAxis;
00645 
00646    if (TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Y()) && TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Z())) {
00647       arbAxis.Set(1.0, 0.0, 0.0);
00648    } else if (TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.X()) && TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.Z())) {
00649       arbAxis.Set(0.0, 1.0, 0.0);
00650    } else {
00651       arbAxis.Set(0.0, 0.0, 1.0);
00652    }
00653 
00654    Set(origin, zAxis, Cross(zAxisInt, arbAxis));
00655 }
00656 
00657 //______________________________________________________________________________
00658 TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis)
00659 {
00660    // Construct matrix which when applied puts local origin at
00661    // 'origin' and the local Z axis in direction 'z'. Both
00662    // 'origin' and 'zAxisVec' are expressed in the parent frame
00663    SetIdentity();
00664    Set(origin, zAxis, xAxis);
00665 }
00666 
00667 //______________________________________________________________________________
00668 TGLMatrix::TGLMatrix(const Double_t vals[16])
00669 {
00670    // Construct matrix using the 16 Double_t 'vals' passed,
00671    // ordering is maintained - i.e. should be column major
00672    // as we are
00673    Set(vals);
00674 }
00675 
00676 //______________________________________________________________________________
00677 TGLMatrix::TGLMatrix(const TGLMatrix & other)
00678 {
00679    // Construct matrix from 'other'
00680    *this = other;
00681 }
00682 
00683 //______________________________________________________________________________
00684 TGLMatrix::~TGLMatrix()
00685 {
00686    // Destroy matirx object
00687 }
00688 
00689 //______________________________________________________________________________
00690 void TGLMatrix::MultRight(const TGLMatrix & rhs)
00691 {
00692    // Multiply with matrix rhs on right.
00693 
00694   Double_t  B[4];
00695   Double_t* C = fVals;
00696   for(int r=0; r<4; ++r, ++C)
00697   {
00698     const Double_t* T = rhs.fVals;
00699     for(int c=0; c<4; ++c, T+=4)
00700       B[c] = C[0]*T[0] + C[4]*T[1] + C[8]*T[2] + C[12]*T[3];
00701     C[0] = B[0]; C[4] = B[1]; C[8] = B[2]; C[12] = B[3];
00702   }
00703 }
00704 
00705 //______________________________________________________________________________
00706 void TGLMatrix::MultLeft (const TGLMatrix & lhs)
00707 {
00708    // Multiply with matrix lhs on left.
00709 
00710    Double_t  B[4];
00711    Double_t* C = fVals;
00712    for (int c=0; c<4; ++c, C+=4)
00713    {
00714       const Double_t* T = lhs.fVals;
00715       for(int r=0; r<4; ++r, ++T)
00716          B[r] = T[0]*C[0] + T[4]*C[1] + T[8]*C[2] + T[12]*C[3];
00717       C[0] = B[0]; C[1] = B[1]; C[2] = B[2]; C[3] = B[3];
00718    }
00719 }
00720 
00721 //______________________________________________________________________________
00722 void TGLMatrix::Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis)
00723 {
00724    // Set matrix which when applied puts local origin at
00725    // 'origin' and the local Z axis in direction 'z'. Both
00726    // 'origin' and 'z' are expressed in the parent frame
00727    TGLVector3 zAxisInt(zAxis);
00728    zAxisInt.Normalise();
00729 
00730    TGLVector3 xAxisInt(xAxis);
00731    xAxisInt.Normalise();
00732    TGLVector3 yAxisInt = Cross(zAxisInt, xAxisInt);
00733 
00734    fVals[0] = xAxisInt.X(); fVals[4] = yAxisInt.X(); fVals[8 ] = zAxisInt.X(); fVals[12] = origin.X();
00735    fVals[1] = xAxisInt.Y(); fVals[5] = yAxisInt.Y(); fVals[9 ] = zAxisInt.Y(); fVals[13] = origin.Y();
00736    fVals[2] = xAxisInt.Z(); fVals[6] = yAxisInt.Z(); fVals[10] = zAxisInt.Z(); fVals[14] = origin.Z();
00737    fVals[3] = 0.0;          fVals[7] = 0.0;          fVals[11] = 0.0;          fVals[15] = 1.0;
00738 }
00739 
00740 //______________________________________________________________________________
00741 void TGLMatrix::Set(const Double_t vals[16])
00742 {
00743    // Set matrix using the 16 Double_t 'vals' passed,
00744    // ordering is maintained - i.e. should be column major.
00745 
00746    for (UInt_t i=0; i < 16; i++) {
00747       fVals[i] = vals[i];
00748    }
00749 }
00750 
00751 //______________________________________________________________________________
00752 void TGLMatrix::SetIdentity()
00753 {
00754    // Set matrix to identity.
00755 
00756    fVals[0] = 1.0; fVals[4] = 0.0; fVals[8 ] = 0.0; fVals[12] = 0.0;
00757    fVals[1] = 0.0; fVals[5] = 1.0; fVals[9 ] = 0.0; fVals[13] = 0.0;
00758    fVals[2] = 0.0; fVals[6] = 0.0; fVals[10] = 1.0; fVals[14] = 0.0;
00759    fVals[3] = 0.0; fVals[7] = 0.0; fVals[11] = 0.0; fVals[15] = 1.0;
00760 }
00761 
00762 //______________________________________________________________________________
00763 void TGLMatrix::SetTranslation(Double_t x, Double_t y, Double_t z)
00764 {
00765    // Set matrix translation components x,y,z.
00766 
00767    SetTranslation(TGLVertex3(x,y,z));
00768 }
00769 
00770 //______________________________________________________________________________
00771 void TGLMatrix::SetTranslation(const TGLVertex3 & translation)
00772 {
00773    // Set matrix translation components x,y,z.
00774 
00775    fVals[12] = translation[0];
00776    fVals[13] = translation[1];
00777    fVals[14] = translation[2];
00778 }
00779 
00780 //______________________________________________________________________________
00781 TGLVector3 TGLMatrix::GetTranslation() const
00782 {
00783    // Return the translation component of matrix.
00784 
00785    return TGLVector3(fVals[12], fVals[13], fVals[14]);
00786 }
00787 
00788 //______________________________________________________________________________
00789 void TGLMatrix::Translate(const TGLVector3 & vect)
00790 {
00791    // Shift matrix translation components by 'vect' in parent frame.
00792 
00793    fVals[12] += vect[0];
00794    fVals[13] += vect[1];
00795    fVals[14] += vect[2];
00796 }
00797 
00798 //______________________________________________________________________________
00799 void TGLMatrix::MoveLF(Int_t ai, Double_t amount)
00800 {
00801    // Translate in local frame.
00802    // i1, i2 are axes indices: 1 ~ x, 2 ~ y, 3 ~ z.
00803 
00804    const Double_t *C = fVals + 4*--ai;
00805    fVals[12] += amount*C[0]; fVals[13] += amount*C[1]; fVals[14] += amount*C[2];
00806 }
00807 
00808 //______________________________________________________________________________
00809 void TGLMatrix::Move3LF(Double_t x, Double_t y, Double_t z)
00810 {
00811    // Translate in local frame along all base vectors simultaneously.
00812 
00813    fVals[12] += x*fVals[0] + y*fVals[4] + z*fVals[8];
00814    fVals[13] += x*fVals[1] + y*fVals[5] + z*fVals[9];
00815    fVals[14] += x*fVals[2] + y*fVals[6] + z*fVals[10];
00816 }
00817 
00818 //______________________________________________________________________________
00819 void TGLMatrix::Scale(const TGLVector3 & scale)
00820 {
00821    // Set matrix axis scales to 'scale'. Note - this really sets
00822    // the overall (total) scaling for each axis - it does NOT
00823    // apply compounded scale on top of existing one
00824    TGLVector3 currentScale = GetScale();
00825 
00826    // x
00827    if (currentScale[0] != 0.0) {
00828       fVals[0] *= scale[0]/currentScale[0];
00829       fVals[1] *= scale[0]/currentScale[0];
00830       fVals[2] *= scale[0]/currentScale[0];
00831    } else {
00832       Error("TGLMatrix::Scale()", "zero scale div by zero");
00833    }
00834    // y
00835    if (currentScale[1] != 0.0) {
00836       fVals[4] *= scale[1]/currentScale[1];
00837       fVals[5] *= scale[1]/currentScale[1];
00838       fVals[6] *= scale[1]/currentScale[1];
00839    } else {
00840       Error("TGLMatrix::Scale()", "zero scale div by zero");
00841    }
00842    // z
00843    if (currentScale[2] != 0.0) {
00844       fVals[8] *= scale[2]/currentScale[2];
00845       fVals[9] *= scale[2]/currentScale[2];
00846       fVals[10] *= scale[2]/currentScale[2];
00847    } else {
00848       Error("TGLMatrix::Scale()", "zero scale div by zero");
00849    }
00850 }
00851 
00852 //______________________________________________________________________________
00853 void TGLMatrix::Rotate(const TGLVertex3 & pivot, const TGLVector3 & axis, Double_t angle)
00854 {
00855    // Update martix so resulting transform has been rotated about 'pivot'
00856    // (in parent frame), round vector 'axis', through 'angle' (radians)
00857    // Equivalent to glRotate function, but with addition of translation
00858    // and compounded on top of existing.
00859    TGLVector3 nAxis = axis;
00860    nAxis.Normalise();
00861    Double_t x = nAxis.X();
00862    Double_t y = nAxis.Y();
00863    Double_t z = nAxis.Z();
00864    Double_t c = TMath::Cos(angle);
00865    Double_t s = TMath::Sin(angle);
00866 
00867    // Calculate local rotation, with pre-translation to local pivot origin
00868    TGLMatrix rotMat;
00869    rotMat[ 0] = x*x*(1-c) + c;   rotMat[ 4] = x*y*(1-c) - z*s; rotMat[ 8] = x*z*(1-c) + y*s; rotMat[12] = pivot[0];
00870    rotMat[ 1] = y*x*(1-c) + z*s; rotMat[ 5] = y*y*(1-c) + c;   rotMat[ 9] = y*z*(1-c) - x*s; rotMat[13] = pivot[1];
00871    rotMat[ 2] = x*z*(1-c) - y*s; rotMat[ 6] = y*z*(1-c) + x*s; rotMat[10] = z*z*(1-c) + c;   rotMat[14] = pivot[2];
00872    rotMat[ 3] = 0.0;             rotMat[ 7] = 0.0;             rotMat[11] = 0.0;             rotMat[15] = 1.0;
00873    TGLMatrix localToWorld(-pivot);
00874 
00875    // TODO: Ugly - should use quaternions to avoid compound rounding errors and
00876    // triple multiplication
00877    *this = rotMat * localToWorld * (*this);
00878 }
00879 
00880 //______________________________________________________________________________
00881 void TGLMatrix::RotateLF(Int_t i1, Int_t i2, Double_t amount)
00882 {
00883    // Rotate in local frame. Does optimised version of MultRight.
00884    // i1, i2 are axes indices: 1 ~ x, 2 ~ y, 3 ~ z.
00885 
00886    if(i1 == i2) return;
00887    const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
00888    Double_t  b1, b2;
00889    Double_t* c = fVals;
00890    --i1 <<= 2; --i2 <<= 2; // column major
00891    for(int r=0; r<4; ++r, ++c) {
00892       b1 = cos*c[i1] + sin*c[i2];
00893       b2 = cos*c[i2] - sin*c[i1];
00894       c[i1] = b1; c[i2] = b2;
00895    }
00896 }
00897 
00898 //______________________________________________________________________________
00899 void TGLMatrix::RotatePF(Int_t i1, Int_t i2, Double_t amount)
00900 {
00901    // Rotate in parent frame. Does optimised version of MultLeft.
00902 
00903    if(i1 == i2) return;
00904 
00905    // Optimized version:
00906    const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
00907    Double_t  b1, b2;
00908    Double_t* C = fVals;
00909    --i1; --i2;
00910    for(int c=0; c<4; ++c, C+=4) {
00911       b1 = cos*C[i1] - sin*C[i2];
00912       b2 = cos*C[i2] + sin*C[i1];
00913       C[i1] = b1; C[i2] = b2;
00914    }
00915 }
00916 
00917 //______________________________________________________________________________
00918 void TGLMatrix::TransformVertex(TGLVertex3 & vertex) const
00919 {
00920    // Transform passed 'vertex' by this matrix - converts local frame to parent
00921    TGLVertex3 orig = vertex;
00922    for (UInt_t i = 0; i < 3; i++) {
00923       vertex[i] = orig[0] * fVals[0+i] + orig[1] * fVals[4+i] +
00924                   orig[2] * fVals[8+i] + fVals[12+i];
00925    }
00926 }
00927 
00928 //______________________________________________________________________________
00929 void TGLMatrix::Transpose3x3()
00930 {
00931    // Transpose the top left 3x3 matrix component along major diagonal
00932    // Supported as currently incompatability between TGeo and GL matrix
00933    // layouts for this 3x3 only. To be resolved.
00934 
00935    // TODO: Move this fix to the TBuffer3D filling side and remove
00936    //
00937    // 0  4  8 12
00938    // 1  5  9 13
00939    // 2  6 10 14
00940    // 3  7 11 15
00941 
00942    Double_t temp = fVals[4];
00943    fVals[4] = fVals[1];
00944    fVals[1] = temp;
00945    temp = fVals[8];
00946    fVals[8] = fVals[2];
00947    fVals[2] = temp;
00948    temp = fVals[9];
00949    fVals[9] = fVals[6];
00950    fVals[6] = temp;
00951 }
00952 
00953 //______________________________________________________________________________
00954 Double_t TGLMatrix::Invert()
00955 {
00956    // Invert the matrix, returns determinant.
00957    // Copied from TMatrixFCramerInv.
00958 
00959    Double_t* M = fVals;
00960 
00961    const Double_t det2_12_01 = M[1]*M[6]  - M[5]*M[2];
00962    const Double_t det2_12_02 = M[1]*M[10] - M[9]*M[2];
00963    const Double_t det2_12_03 = M[1]*M[14] - M[13]*M[2];
00964    const Double_t det2_12_13 = M[5]*M[14] - M[13]*M[6];
00965    const Double_t det2_12_23 = M[9]*M[14] - M[13]*M[10];
00966    const Double_t det2_12_12 = M[5]*M[10] - M[9]*M[6];
00967    const Double_t det2_13_01 = M[1]*M[7]  - M[5]*M[3];
00968    const Double_t det2_13_02 = M[1]*M[11] - M[9]*M[3];
00969    const Double_t det2_13_03 = M[1]*M[15] - M[13]*M[3];
00970    const Double_t det2_13_12 = M[5]*M[11] - M[9]*M[7];
00971    const Double_t det2_13_13 = M[5]*M[15] - M[13]*M[7];
00972    const Double_t det2_13_23 = M[9]*M[15] - M[13]*M[11];
00973    const Double_t det2_23_01 = M[2]*M[7]  - M[6]*M[3];
00974    const Double_t det2_23_02 = M[2]*M[11] - M[10]*M[3];
00975    const Double_t det2_23_03 = M[2]*M[15] - M[14]*M[3];
00976    const Double_t det2_23_12 = M[6]*M[11] - M[10]*M[7];
00977    const Double_t det2_23_13 = M[6]*M[15] - M[14]*M[7];
00978    const Double_t det2_23_23 = M[10]*M[15] - M[14]*M[11];
00979 
00980 
00981    const Double_t det3_012_012 = M[0]*det2_12_12 - M[4]*det2_12_02 + M[8]*det2_12_01;
00982    const Double_t det3_012_013 = M[0]*det2_12_13 - M[4]*det2_12_03 + M[12]*det2_12_01;
00983    const Double_t det3_012_023 = M[0]*det2_12_23 - M[8]*det2_12_03 + M[12]*det2_12_02;
00984    const Double_t det3_012_123 = M[4]*det2_12_23 - M[8]*det2_12_13 + M[12]*det2_12_12;
00985    const Double_t det3_013_012 = M[0]*det2_13_12 - M[4]*det2_13_02 + M[8]*det2_13_01;
00986    const Double_t det3_013_013 = M[0]*det2_13_13 - M[4]*det2_13_03 + M[12]*det2_13_01;
00987    const Double_t det3_013_023 = M[0]*det2_13_23 - M[8]*det2_13_03 + M[12]*det2_13_02;
00988    const Double_t det3_013_123 = M[4]*det2_13_23 - M[8]*det2_13_13 + M[12]*det2_13_12;
00989    const Double_t det3_023_012 = M[0]*det2_23_12 - M[4]*det2_23_02 + M[8]*det2_23_01;
00990    const Double_t det3_023_013 = M[0]*det2_23_13 - M[4]*det2_23_03 + M[12]*det2_23_01;
00991    const Double_t det3_023_023 = M[0]*det2_23_23 - M[8]*det2_23_03 + M[12]*det2_23_02;
00992    const Double_t det3_023_123 = M[4]*det2_23_23 - M[8]*det2_23_13 + M[12]*det2_23_12;
00993    const Double_t det3_123_012 = M[1]*det2_23_12 - M[5]*det2_23_02 + M[9]*det2_23_01;
00994    const Double_t det3_123_013 = M[1]*det2_23_13 - M[5]*det2_23_03 + M[13]*det2_23_01;
00995    const Double_t det3_123_023 = M[1]*det2_23_23 - M[9]*det2_23_03 + M[13]*det2_23_02;
00996    const Double_t det3_123_123 = M[5]*det2_23_23 - M[9]*det2_23_13 + M[13]*det2_23_12;
00997 
00998    const Double_t det = M[0]*det3_123_123 - M[4]*det3_123_023 +
00999       M[8]*det3_123_013 - M[12]*det3_123_012;
01000 
01001    if(det == 0) {
01002       Warning("TGLMatrix::Invert", "matrix is singular.");
01003       return 0;
01004    }
01005 
01006    const Double_t oneOverDet = 1.0/det;
01007    const Double_t mn1OverDet = - oneOverDet;
01008 
01009    M[0]  = det3_123_123 * oneOverDet;
01010    M[4]  = det3_023_123 * mn1OverDet;
01011    M[8]  = det3_013_123 * oneOverDet;
01012    M[12] = det3_012_123 * mn1OverDet;
01013 
01014    M[1]  = det3_123_023 * mn1OverDet;
01015    M[5]  = det3_023_023 * oneOverDet;
01016    M[9]  = det3_013_023 * mn1OverDet;
01017    M[13] = det3_012_023 * oneOverDet;
01018 
01019    M[2]  = det3_123_013 * oneOverDet;
01020    M[6]  = det3_023_013 * mn1OverDet;
01021    M[10] = det3_013_013 * oneOverDet;
01022    M[14] = det3_012_013 * mn1OverDet;
01023 
01024    M[3]  = det3_123_012 * mn1OverDet;
01025    M[7]  = det3_023_012 * oneOverDet;
01026    M[11] = det3_013_012 * mn1OverDet;
01027    M[15] = det3_012_012 * oneOverDet;
01028 
01029    return det;
01030 }
01031 
01032 //______________________________________________________________________________
01033 TGLVector3 TGLMatrix::Multiply(const TGLVector3& v, Double_t w) const
01034 {
01035    // Multiply vector.
01036    const Double_t* M = fVals;
01037    TGLVector3 r;
01038    r.X() = M[0]*v[0] + M[4]*v[1] +  M[8]*v[2] + M[12]*w;
01039    r.Y() = M[1]*v[0] + M[5]*v[1] +  M[9]*v[2] + M[13]*w;
01040    r.Z() = M[2]*v[0] + M[6]*v[1] + M[10]*v[2] + M[14]*w;
01041    return r;
01042 }
01043 
01044 //______________________________________________________________________________
01045 TGLVector3 TGLMatrix::Rotate(const TGLVector3& v) const
01046 {
01047    // Rotate vector. Translation is not applied.
01048    const Double_t* M = fVals;
01049    TGLVector3 r;
01050    r.X() = M[0]*v[0] + M[4]*v[1] +  M[8]*v[2];
01051    r.Y() = M[1]*v[0] + M[5]*v[1] +  M[9]*v[2];
01052    r.Z() = M[2]*v[0] + M[6]*v[1] + M[10]*v[2];
01053    return r;
01054 }
01055 
01056 //______________________________________________________________________________
01057 void TGLMatrix::MultiplyIP(TGLVector3& v, Double_t w) const
01058 {
01059    // Multiply vector in-place.
01060    const Double_t* M = fVals;
01061    Double_t r[3] = { v[0], v[1], v[2] };
01062    v.X() = M[0]*r[0] + M[4]*r[1] +  M[8]*r[2] + M[12]*w;
01063    v.Y() = M[1]*r[0] + M[5]*r[1] +  M[9]*r[2] + M[13]*w;
01064    v.Z() = M[2]*r[0] + M[6]*r[1] + M[10]*r[2] + M[14]*w;
01065 }
01066 
01067 //______________________________________________________________________________
01068 void TGLMatrix::RotateIP(TGLVector3& v) const
01069 {
01070    // Rotate vector in-place. Translation is not applied.
01071    const Double_t* M = fVals;
01072    Double_t r[3] = { v[0], v[1], v[2] };
01073    v.X() = M[0]*r[0] + M[4]*r[1] +  M[8]*r[2];
01074    v.Y() = M[1]*r[0] + M[5]*r[1] +  M[9]*r[2];
01075    v.Z() = M[2]*r[0] + M[6]*r[1] + M[10]*r[2];
01076 }
01077 
01078 //______________________________________________________________________________
01079 TGLVector3 TGLMatrix::GetScale() const
01080 {
01081    // Get local axis scaling factors
01082    TGLVector3 x(fVals[0], fVals[1], fVals[2]);
01083    TGLVector3 y(fVals[4], fVals[5], fVals[6]);
01084    TGLVector3 z(fVals[8], fVals[9], fVals[10]);
01085    return TGLVector3(x.Mag(), y.Mag(), z.Mag());
01086 }
01087 
01088 //______________________________________________________________________________
01089 void TGLMatrix::Dump() const
01090 {
01091    // Output 16 matrix components to std::cout
01092    //
01093    // 0  4   8  12
01094    // 1  5   9  13
01095    // 2  6  10  14
01096    // 3  7  11  15
01097    //
01098    std::cout.precision(6);
01099    for (Int_t x = 0; x < 4; x++) {
01100       std::cout << "[ ";
01101       for (Int_t y = 0; y < 4; y++) {
01102          std::cout << fVals[y*4 + x] << " ";
01103       }
01104       std::cout << "]" << std::endl;
01105    }
01106 }
01107 
01108 
01109 //==============================================================================
01110 // TGLColor
01111 //==============================================================================
01112 
01113 //______________________________________________________________________________
01114 //
01115 // Class encapsulating color information in preferred GL format - an
01116 // array of four unsigned bytes.
01117 // Color index is also cached for easier interfacing with the
01118 // traditional ROOT graphics.
01119 //
01120 
01121 ClassImp(TGLColor);
01122 
01123 //______________________________________________________________________________
01124 TGLColor::TGLColor()
01125 {
01126    // Default constructor. Color is initialized to black.
01127 
01128    fRGBA[0] = fRGBA[1] = fRGBA[2] = 0;
01129    fRGBA[3] = 255;
01130    fIndex   = -1;
01131 }
01132 
01133 //______________________________________________________________________________
01134 TGLColor::TGLColor(Int_t r, Int_t g, Int_t b, Int_t a)
01135 {
01136    // Constructor from Int_t values.
01137 
01138    SetColor(r, g, b, a);
01139 }
01140 
01141 //______________________________________________________________________________
01142 TGLColor::TGLColor(Float_t r, Float_t g, Float_t b, Float_t a)
01143 {
01144    // Constructor from Float_t values.
01145 
01146    SetColor(r, g, b, a);
01147 }
01148 
01149 //______________________________________________________________________________
01150 TGLColor::TGLColor(Color_t color_index, Char_t transparency)
01151 {
01152    // Constructor from color-index and transparency.
01153 
01154    SetColor(color_index, transparency);
01155 }
01156 
01157 //______________________________________________________________________________
01158 TGLColor::~TGLColor()
01159 {
01160    // Dectructor.
01161 }
01162 
01163 //______________________________________________________________________________
01164 TGLColor& TGLColor::operator=(const TGLColor& c)
01165 {
01166    // Assignment operator.
01167 
01168    fRGBA[0] = c.fRGBA[0];
01169    fRGBA[1] = c.fRGBA[1];
01170    fRGBA[2] = c.fRGBA[2];
01171    fRGBA[3] = c.fRGBA[3];
01172    fIndex   = c.fIndex;
01173    return *this;
01174 }
01175 
01176 //______________________________________________________________________________
01177 Color_t TGLColor::GetColorIndex() const
01178 {
01179    // Returns color-index representing the color.
01180 
01181    if (fIndex == -1)
01182       fIndex = TColor::GetColor(fRGBA[0], fRGBA[1], fRGBA[2]);
01183    return fIndex;
01184 }
01185 
01186 //______________________________________________________________________________
01187 Char_t TGLColor::GetTransparency() const
01188 {
01189    // Returns transparecy value.
01190 
01191    return TMath::Nint(100.0*(1.0 - fRGBA[3]/255.0));
01192 }
01193 
01194 //______________________________________________________________________________
01195 void TGLColor::SetColor(Int_t r, Int_t g, Int_t b, Int_t a)
01196 {
01197    // Set color with Int_t values.
01198 
01199    fRGBA[0] = r;
01200    fRGBA[1] = g;
01201    fRGBA[2] = b;
01202    fRGBA[3] = a;
01203    fIndex   = -1;
01204 }
01205 
01206 //______________________________________________________________________________
01207 void TGLColor::SetColor(Float_t r, Float_t g, Float_t b, Float_t a)
01208 {
01209    // Set color with Float_t values.
01210 
01211    fRGBA[0] = (UChar_t)(255*r);
01212    fRGBA[1] = (UChar_t)(255*g);
01213    fRGBA[2] = (UChar_t)(255*b);
01214    fRGBA[3] = (UChar_t)(255*a);
01215    fIndex   = -1;
01216 }
01217 
01218 //______________________________________________________________________________
01219 void TGLColor::SetColor(Color_t color_index)
01220 {
01221    // Set color by color-index. Alpha is not changed.
01222    // If color_index is not valid, color is set to magenta.
01223 
01224    TColor* c = gROOT->GetColor(color_index);
01225    if (c)
01226    {
01227       fRGBA[0] = (UChar_t)(255*c->GetRed());
01228       fRGBA[1] = (UChar_t)(255*c->GetGreen());
01229       fRGBA[2] = (UChar_t)(255*c->GetBlue());
01230       fIndex   = color_index;
01231    }
01232    else
01233    {
01234       // Set to magenta.
01235       fRGBA[0] = 255;
01236       fRGBA[1] = 0;
01237       fRGBA[2] = 255;
01238       fIndex   = -1;
01239    }
01240 }
01241 
01242 //______________________________________________________________________________
01243 void TGLColor::SetColor(Color_t color_index, Char_t transparency)
01244 {
01245    // Set color by color-index and alpha from the transparency.
01246    // If color_index is not valid, color is set to magenta.
01247 
01248    UChar_t alpha = (255*(100 - transparency))/100;
01249    
01250    TColor* c = gROOT->GetColor(color_index);
01251    if (c)
01252    {
01253       fRGBA[0] = (UChar_t)(255*c->GetRed());
01254       fRGBA[1] = (UChar_t)(255*c->GetGreen());
01255       fRGBA[2] = (UChar_t)(255*c->GetBlue());
01256       fRGBA[3] = alpha;
01257       fIndex   = color_index;
01258    }
01259    else
01260    {
01261       // Set to magenta.
01262       fRGBA[0] = 255;
01263       fRGBA[1] = 0;
01264       fRGBA[2] = 255;
01265       fRGBA[3] = alpha;
01266       fIndex   = -1;
01267       return;
01268    }
01269 }
01270 
01271 //______________________________________________________________________________
01272 void TGLColor::SetTransparency(Char_t transparency)
01273 {
01274    // Set alpha from the transparency.
01275 
01276    fRGBA[3] = (255*(100 - transparency))/100;
01277 }
01278 
01279 //______________________________________________________________________________
01280 TString TGLColor::AsString() const
01281 {
01282    // Return string describing the color.
01283 
01284    return TString::Format("rgba:%02hhx/%02hhx/%02hhx/%02hhx",
01285                           fRGBA[0], fRGBA[1], fRGBA[2], fRGBA[3]);
01286 }
01287 
01288 
01289 //==============================================================================
01290 // TGLColorSet
01291 //==============================================================================
01292 
01293 //______________________________________________________________________________
01294 //
01295 // Class encapsulating a set of colors used throughout standard rendering.
01296 //
01297 
01298 ClassImp(TGLColorSet);
01299 
01300 //______________________________________________________________________________
01301 TGLColorSet::TGLColorSet()
01302 {
01303    // Constructor. Sets default for dark background.
01304 
01305    StdDarkBackground();
01306 }
01307 
01308 //______________________________________________________________________________
01309 TGLColorSet::~TGLColorSet()
01310 {
01311    // Destructor.
01312 }
01313 
01314 //______________________________________________________________________________
01315 TGLColorSet& TGLColorSet::operator=(const TGLColorSet& s)
01316 {
01317    // Assignment operator.
01318 
01319    fBackground = s.fBackground;
01320    fForeground = s.fForeground;
01321    fOutline    = s.fOutline;
01322    fMarkup     = s.fMarkup;
01323    for (Int_t i = 0; i < 5; ++i)
01324       fSelection[i] = s.fSelection[i];
01325    return *this;
01326 }
01327 
01328 //______________________________________________________________________________
01329 void TGLColorSet::StdDarkBackground()
01330 {
01331    // Set defaults for dark (black) background.
01332 
01333    fBackground .SetColor(0,   0,   0);
01334    fForeground .SetColor(255, 255, 255);
01335    fOutline    .SetColor(240, 255, 240);
01336    fMarkup     .SetColor(200, 200, 200);
01337 
01338    fSelection[0].SetColor(  0,   0,   0);
01339    fSelection[1].SetColor(255, 220, 220);
01340    fSelection[2].SetColor(255, 220, 220);
01341    fSelection[3].SetColor(200, 200, 255);
01342    fSelection[4].SetColor(200, 200, 255);
01343 }
01344 
01345 //______________________________________________________________________________
01346 void TGLColorSet::StdLightBackground()
01347 {
01348    // Set defaults for light (white) background.
01349 
01350    fBackground .SetColor(255, 255, 255);
01351    fForeground .SetColor(0,   0,   0);
01352    fOutline    .SetColor(0,   0,   0);
01353    fMarkup     .SetColor(55,  55,  55);
01354 
01355    fSelection[0].SetColor(0,   0,   0);
01356    fSelection[1].SetColor(200, 100, 100);
01357    fSelection[2].SetColor(200, 100, 100);
01358    fSelection[3].SetColor(100, 100, 200);
01359    fSelection[4].SetColor(100, 100, 200);
01360 }
01361 
01362 
01363 //==============================================================================
01364 // TGLUtil
01365 //==============================================================================
01366 
01367 //______________________________________________________________________________
01368 //
01369 // Wrapper class for various misc static functions - error checking,
01370 // draw helpers etc.
01371 //
01372 
01373 ClassImp(TGLUtil);
01374 
01375 UInt_t TGLUtil::fgDefaultDrawQuality = 10;
01376 UInt_t TGLUtil::fgDrawQuality        = fgDefaultDrawQuality;
01377 UInt_t TGLUtil::fgColorLockCount     = 0;
01378 
01379 Float_t TGLUtil::fgPointSize      = 1.0f;
01380 Float_t TGLUtil::fgLineWidth      = 1.0f;
01381 Float_t TGLUtil::fgPointSizeScale = 1.0f;
01382 Float_t TGLUtil::fgLineWidthScale = 1.0f;
01383 
01384 const UChar_t TGLUtil::fgRed[4]    = { 230,   0,   0, 255 };
01385 const UChar_t TGLUtil::fgGreen[4]  = {   0, 230,   0, 255 };
01386 const UChar_t TGLUtil::fgBlue[4]   = {   0,   0, 230, 255 };
01387 const UChar_t TGLUtil::fgYellow[4] = { 210, 210,   0, 255 };
01388 const UChar_t TGLUtil::fgWhite[4]  = { 255, 255, 255, 255 };
01389 const UChar_t TGLUtil::fgGrey[4]   = { 128, 128, 128, 100 };
01390 
01391 #ifndef CALLBACK
01392 #define CALLBACK
01393 #endif
01394 
01395 extern "C"
01396 {
01397 #if defined(__APPLE_CC__) && __APPLE_CC__ > 4000 && __APPLE_CC__ < 5450 && !defined(__INTEL_COMPILER)
01398     typedef GLvoid (*tessfuncptr_t)(...);
01399 #elif defined(__mips) || defined(__linux__) || defined(__FreeBSD__) || defined( __OpenBSD__ ) || defined(__sun) || defined (__CYGWIN__) || defined (__APPLE__)
01400     typedef GLvoid (*tessfuncptr_t)();
01401 #elif defined (WIN32)
01402     typedef GLvoid (CALLBACK *tessfuncptr_t)();
01403 #else
01404     #error "Error - need to define type tessfuncptr_t for this platform/compiler"
01405 #endif
01406 }
01407 
01408 namespace
01409 {
01410 
01411 class TGLTesselatorWrap
01412 {
01413 protected:
01414 
01415 public:
01416    GLUtesselator *fTess;
01417 
01418    TGLTesselatorWrap(tessfuncptr_t vertex_func) : fTess(0)
01419    {
01420       fTess = gluNewTess();
01421       if (!fTess)
01422          throw std::bad_alloc();
01423 
01424       gluTessCallback(fTess, (GLenum)GLU_BEGIN,  (tessfuncptr_t) glBegin);
01425       gluTessCallback(fTess, (GLenum)GLU_END,    (tessfuncptr_t) glEnd);
01426       gluTessCallback(fTess, (GLenum)GLU_VERTEX, vertex_func);
01427    }
01428 
01429    virtual ~TGLTesselatorWrap()
01430    {
01431       if (fTess)
01432          gluDeleteTess(fTess);
01433    }
01434 };
01435 
01436 }
01437 
01438 //______________________________________________________________________________
01439 GLUtesselator* TGLUtil::GetDrawTesselator3fv()
01440 {
01441    // Returns a tesselator for direct drawing when using 3-vertices with
01442    // single precision.
01443 
01444    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex3fv);
01445 
01446    return singleton.fTess;
01447 }
01448 
01449 //______________________________________________________________________________
01450 GLUtesselator* TGLUtil::GetDrawTesselator4fv()
01451 {
01452    // Returns a tesselator for direct drawing when using 4-vertices with
01453    // single precision.
01454 
01455    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex4fv);
01456 
01457    return singleton.fTess;
01458 }
01459 
01460 //______________________________________________________________________________
01461 GLUtesselator* TGLUtil::GetDrawTesselator3dv()
01462 {
01463    // Returns a tesselator for direct drawing when using 3-vertices with
01464    // double precision.
01465 
01466    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex3dv);
01467 
01468    return singleton.fTess;
01469 }
01470 
01471 //______________________________________________________________________________
01472 GLUtesselator* TGLUtil::GetDrawTesselator4dv()
01473 {
01474    // Returns a tesselator for direct drawing when using 4-vertices with
01475    // double precision.
01476 
01477    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex4dv);
01478 
01479    return singleton.fTess;
01480 }
01481 
01482 //______________________________________________________________________________
01483 UInt_t TGLUtil::GetDrawQuality()
01484 {
01485    //static: get draw quality
01486    return fgDrawQuality;
01487 }
01488 
01489 //______________________________________________________________________________
01490 void TGLUtil::SetDrawQuality(UInt_t dq)
01491 {
01492    //static: set draw quality
01493    fgDrawQuality = dq;
01494 }
01495 
01496 //______________________________________________________________________________
01497 void TGLUtil::ResetDrawQuality()
01498 {
01499    //static: reset draw quality
01500    fgDrawQuality = fgDefaultDrawQuality;
01501 }
01502 
01503 //______________________________________________________________________________
01504 UInt_t TGLUtil::GetDefaultDrawQuality()
01505 {
01506    //static: get default draw quality
01507    return fgDefaultDrawQuality;
01508 }
01509 
01510 //______________________________________________________________________________
01511 void TGLUtil::SetDefaultDrawQuality(UInt_t dq)
01512 {
01513    //static: set default draw quality
01514    fgDefaultDrawQuality = dq;
01515 }
01516 
01517 //______________________________________________________________________________
01518 void TGLUtil::CheckError(const char * loc)
01519 {
01520    // Check current GL error state, outputing details via ROOT
01521    // Error method if one
01522    GLenum errCode;
01523    const GLubyte *errString;
01524 
01525    if ((errCode = glGetError()) != GL_NO_ERROR) {
01526       errString = gluErrorString(errCode);
01527       if (loc) {
01528          Error(loc, "GL Error %s", (const char *)errString);
01529       } else {
01530          Error("TGLUtil::CheckError", "GL Error %s", (const char *)errString);
01531       }
01532    }
01533 }
01534 
01535 /******************************************************************************/
01536 // Color wrapping functions
01537 /******************************************************************************/
01538 
01539 //______________________________________________________________________________
01540 UInt_t TGLUtil::LockColor()
01541 {
01542    // Prevent further color changes.
01543 
01544    return ++fgColorLockCount;
01545 }
01546 
01547 //______________________________________________________________________________
01548 UInt_t TGLUtil::UnlockColor()
01549 {
01550    // Allow color changes.
01551 
01552    if (fgColorLockCount)
01553       --fgColorLockCount;
01554    else
01555       Error("TGLUtil::UnlockColor", "fgColorLockCount already 0.");
01556    return fgColorLockCount;
01557 }
01558 
01559 //______________________________________________________________________________
01560 Bool_t TGLUtil::IsColorLocked()
01561 {
01562    // Returns true if color lockcount is greater than 0.
01563 
01564    return fgColorLockCount > 0;
01565 }
01566 
01567 //______________________________________________________________________________
01568 void TGLUtil::Color(const TGLColor& color)
01569 {
01570    // Set color from TGLColor.
01571 
01572    if (fgColorLockCount == 0) glColor4ubv(color.CArr());
01573 }
01574 
01575 //______________________________________________________________________________
01576 void TGLUtil::ColorAlpha(const TGLColor& color, UChar_t alpha)
01577 {
01578    // Set color from TGLColor and alpha value.
01579 
01580    if (fgColorLockCount == 0)
01581    {
01582       glColor4ub(color.GetRed(), color.GetGreen(), color.GetBlue(), alpha);
01583    }
01584 }
01585 
01586 //______________________________________________________________________________
01587 void TGLUtil::ColorAlpha(const TGLColor& color, Float_t alpha)
01588 {
01589    // Set color from TGLColor and alpha value.
01590 
01591    if (fgColorLockCount == 0)
01592    {
01593       glColor4ub(color.GetRed(), color.GetGreen(), color.GetBlue(), (UChar_t)(255*alpha));
01594    }
01595 }
01596 
01597 //______________________________________________________________________________
01598 void TGLUtil::ColorAlpha(Color_t color_index, Float_t alpha)
01599 {
01600    // Set color from color_index and GL-style alpha (default 1).
01601 
01602    if (fgColorLockCount == 0) {
01603       if (color_index < 0)
01604          color_index = 1;
01605       TColor* c = gROOT->GetColor(color_index);
01606       if (c)
01607          glColor4f(c->GetRed(), c->GetGreen(), c->GetBlue(), alpha);
01608    }
01609 }
01610 
01611 //______________________________________________________________________________
01612 void TGLUtil::ColorTransparency(Color_t color_index, Char_t transparency)
01613 {
01614    // Set color from color_index and ROOT-style transparency (default 0).
01615 
01616    if (fgColorLockCount == 0) {
01617       if (color_index < 0)
01618          color_index = 1;
01619       TColor* c = gROOT->GetColor(color_index);
01620       if (c)
01621          glColor4f(c->GetRed(), c->GetGreen(), c->GetBlue(), 1.0f - 0.01f*transparency);
01622    }
01623 }
01624 
01625 //______________________________________________________________________________
01626 void TGLUtil::Color3ub(UChar_t r, UChar_t g, UChar_t b)
01627 {
01628    // Wrapper for glColor3ub.
01629    if (fgColorLockCount == 0) glColor3ub(r, g, b);
01630 }
01631 
01632 //______________________________________________________________________________
01633 void TGLUtil::Color4ub(UChar_t r, UChar_t g, UChar_t b, UChar_t a)
01634 {
01635    // Wrapper for glColor4ub.
01636    if (fgColorLockCount == 0) glColor4ub(r, g, b, a);
01637 }
01638 
01639 //______________________________________________________________________________
01640 void TGLUtil::Color3ubv(const UChar_t* rgb)
01641 {
01642    // Wrapper for glColor3ubv.
01643    if (fgColorLockCount == 0) glColor3ubv(rgb);
01644 }
01645 
01646 //______________________________________________________________________________
01647 void TGLUtil::Color4ubv(const UChar_t* rgba)
01648 {
01649    // Wrapper for glColor4ubv.
01650    if (fgColorLockCount == 0) glColor4ubv(rgba);
01651 }
01652 
01653 //______________________________________________________________________________
01654 void TGLUtil::Color3f(Float_t r, Float_t g, Float_t b)
01655 {
01656    // Wrapper for glColor3f.
01657    if (fgColorLockCount == 0) glColor3f(r, g, b);
01658 }
01659 
01660 //______________________________________________________________________________
01661 void TGLUtil::Color4f(Float_t r, Float_t g, Float_t b, Float_t a)
01662 {
01663    // Wrapper for glColor4f.
01664    if (fgColorLockCount == 0) glColor4f(r, g, b, a);
01665 }
01666 
01667 //______________________________________________________________________________
01668 void TGLUtil::Color3fv(const Float_t* rgb)
01669 {
01670    // Wrapper for glColor3fv.
01671    if (fgColorLockCount == 0) glColor3fv(rgb);
01672 }
01673 
01674 //______________________________________________________________________________
01675 void TGLUtil::Color4fv(const Float_t* rgba)
01676 {
01677    // Wrapper for glColor4fv.
01678    if (fgColorLockCount == 0) glColor4fv(rgba);
01679 }
01680 
01681 /******************************************************************************/
01682 // Control for scaling of point-size and line-width.
01683 /******************************************************************************/
01684 
01685 //______________________________________________________________________________
01686 Float_t TGLUtil::GetPointSizeScale()
01687 {
01688    // Get global point-size scale.
01689 
01690    return fgPointSizeScale;
01691 }
01692 
01693 //______________________________________________________________________________
01694 void TGLUtil::SetPointSizeScale(Float_t scale)
01695 {
01696    // Set global point-size scale.
01697 
01698    fgPointSizeScale = scale;
01699 }
01700 
01701 //______________________________________________________________________________
01702 Float_t TGLUtil::GetLineWidthScale()
01703 {
01704    // Returns global line-width scale.
01705 
01706    return fgLineWidthScale;
01707 }
01708 
01709 //______________________________________________________________________________
01710 void TGLUtil::SetLineWidthScale(Float_t scale)
01711 {
01712    // Set global line-width scale.
01713 
01714    fgLineWidthScale = scale;
01715 }
01716 
01717 //______________________________________________________________________________
01718 void TGLUtil::PointSize(Float_t point_size)
01719 {
01720    // Set the point-size, taking the global scaling into account.
01721    // Wrapper for glPointSize.
01722 
01723    fgPointSize = point_size * fgPointSizeScale;
01724    glPointSize(fgPointSize);
01725 }
01726 
01727 //______________________________________________________________________________
01728 void TGLUtil::LineWidth(Float_t line_width)
01729 {
01730    // Set the line-width, taking the global scaling into account.
01731    // Wrapper for glLineWidth.
01732 
01733    fgLineWidth = line_width * fgLineWidthScale;
01734    glLineWidth(fgLineWidth);
01735 }
01736 
01737 //______________________________________________________________________________
01738 Float_t TGLUtil::PointSize()
01739 {
01740    // Get the point-size, taking the global scaling into account.
01741 
01742    return fgPointSize;
01743 }
01744 
01745 //______________________________________________________________________________
01746 Float_t TGLUtil::LineWidth()
01747 {
01748    // Get the line-width, taking the global scaling into account.
01749 
01750    return fgLineWidth;
01751 }
01752 
01753 /******************************************************************************/
01754 // Rendering of polymarkers and lines from logical-shapes.
01755 /******************************************************************************/
01756 
01757 void TGLUtil::BeginExtendPickRegion(Float_t scale)
01758 {
01759    // Extend pick region for large point-sizes or line-widths.
01760 
01761    glMatrixMode(GL_PROJECTION);
01762    glPushMatrix();
01763    Float_t pm[16];
01764    glGetFloatv(GL_PROJECTION_MATRIX, pm);
01765    for (Int_t i=0; i<=12; i+=4) {
01766       pm[i] *= scale; pm[i+1] *= scale;
01767    }
01768    glLoadMatrixf(pm);
01769    glMatrixMode(GL_MODELVIEW);
01770 }
01771 
01772 void TGLUtil::EndExtendPickRegion()
01773 {
01774    // End extension of the pick region.
01775 
01776    glMatrixMode(GL_PROJECTION);
01777    glPopMatrix();
01778    glMatrixMode(GL_MODELVIEW);
01779 }
01780 
01781 //______________________________________________________________________________
01782 void TGLUtil::RenderPolyMarkers(const TAttMarker& marker, Char_t transp,
01783                                 Float_t* p, Int_t n,
01784                                 Int_t pick_radius, Bool_t selection,
01785                                 Bool_t sec_selection)
01786 {
01787    // Render polymarkers at points specified by p-array.
01788    // Supports point and cross-like styles.
01789 
01790    if (n == 0) return;
01791 
01792    glPushAttrib(GL_ENABLE_BIT | GL_POINT_BIT | GL_LINE_BIT);
01793 
01794    glDisable(GL_LIGHTING);
01795    TGLUtil::ColorTransparency(marker.GetMarkerColor(), transp);
01796 
01797    Int_t s = marker.GetMarkerStyle();
01798    if (s == 2 || s == 3 || s == 5 || s == 28)
01799       RenderCrosses(marker, p, n, sec_selection);
01800    else
01801       RenderPoints(marker, p, n, pick_radius, selection, sec_selection);
01802 
01803    glPopAttrib();
01804 }
01805 
01806 //______________________________________________________________________________
01807 void TGLUtil::RenderPoints(const TAttMarker& marker,
01808                            Float_t* op, Int_t n,
01809                            Int_t pick_radius, Bool_t selection,
01810                            Bool_t sec_selection)
01811 {
01812    // Render markers as circular or square points.
01813    // Color is never changed.
01814 
01815    Int_t   style = marker.GetMarkerStyle();
01816    Float_t size  = 5*marker.GetMarkerSize();
01817    if (style == 4 || style == 20 || style == 24)
01818    {
01819       glEnable(GL_POINT_SMOOTH);
01820       if (style == 4 || style == 24) {
01821          glEnable(GL_BLEND);
01822          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01823          glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
01824       }
01825    }
01826    else
01827    {
01828       glDisable(GL_POINT_SMOOTH);
01829       if      (style == 1) size = 1;
01830       else if (style == 6) size = 2;
01831       else if (style == 7) size = 3;
01832    }
01833    TGLUtil::PointSize(size);
01834 
01835    // During selection extend picking region for large point-sizes.
01836    Bool_t changePM = selection && PointSize() > pick_radius;
01837    if (changePM)
01838       BeginExtendPickRegion((Float_t) pick_radius / PointSize());
01839 
01840    Float_t* p = op;
01841    if (sec_selection)
01842    {
01843       glPushName(0);
01844       for (Int_t i=0; i<n; ++i, p+=3)
01845       {
01846          glLoadName(i);
01847          glBegin(GL_POINTS);
01848          glVertex3fv(p);
01849          glEnd();
01850       }
01851       glPopName();
01852    }
01853    else
01854    {
01855       glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
01856       glVertexPointer(3, GL_FLOAT, 0, p);
01857       glEnableClientState(GL_VERTEX_ARRAY);
01858       { // Circumvent bug in ATI's linux drivers.
01859          Int_t nleft = n;
01860          Int_t ndone = 0;
01861          const Int_t maxChunk = 8192;
01862          while (nleft > maxChunk)
01863          {
01864             glDrawArrays(GL_POINTS, ndone, maxChunk);
01865             nleft -= maxChunk;
01866             ndone += maxChunk;
01867          }
01868          glDrawArrays(GL_POINTS, ndone, nleft);
01869       }
01870       glPopClientAttrib();
01871    }
01872 
01873    if (changePM)
01874       EndExtendPickRegion();
01875 }
01876 
01877 //______________________________________________________________________________
01878 void TGLUtil::RenderCrosses(const TAttMarker& marker,
01879                             Float_t* op, Int_t n,
01880                             Bool_t sec_selection)
01881 {
01882    // Render markers as crosses.
01883    // Color is never changed.
01884 
01885    if (marker.GetMarkerStyle() == 28)
01886    {
01887       glEnable(GL_BLEND);
01888       glEnable(GL_LINE_SMOOTH);
01889       TGLUtil::LineWidth(2);
01890    }
01891    else
01892    {
01893       glDisable(GL_LINE_SMOOTH);
01894       TGLUtil::LineWidth(1);
01895    }
01896 
01897    // cross dim
01898    const Float_t d = 2*marker.GetMarkerSize();
01899    Float_t* p = op;
01900    if (sec_selection)
01901    {
01902       glPushName(0);
01903       for (Int_t i=0; i<n; ++i, p+=3)
01904       {
01905          glLoadName(i);
01906          glBegin(GL_LINES);
01907          glVertex3f(p[0]-d, p[1],   p[2]);   glVertex3f(p[0]+d, p[1],   p[2]);
01908          glVertex3f(p[0],   p[1]-d, p[2]);   glVertex3f(p[0],   p[1]+d, p[2]);
01909          glVertex3f(p[0],   p[1],   p[2]-d); glVertex3f(p[0],   p[1],   p[2]+d);
01910          glEnd();
01911       }
01912       glPopName();
01913    }
01914    else
01915    {
01916       glBegin(GL_LINES);
01917       for (Int_t i=0; i<n; ++i, p+=3)
01918       {
01919          glVertex3f(p[0]-d, p[1],   p[2]);   glVertex3f(p[0]+d, p[1],   p[2]);
01920          glVertex3f(p[0],   p[1]-d, p[2]);   glVertex3f(p[0],   p[1]+d, p[2]);
01921          glVertex3f(p[0],   p[1],   p[2]-d); glVertex3f(p[0],   p[1],   p[2]+d);
01922       }
01923       glEnd();
01924    }
01925 
01926    // Anti-flickering -- when crosses get too small they
01927    // appear / disappear randomly.
01928    {
01929       glDisable(GL_POINT_SMOOTH);
01930       TGLUtil::PointSize(1);
01931 
01932       glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
01933       glVertexPointer(3, GL_FLOAT, 0, op);
01934       glEnableClientState(GL_VERTEX_ARRAY);
01935       { // Circumvent bug in ATI's linux drivers.
01936          Int_t nleft = n;
01937          Int_t ndone = 0;
01938          const Int_t maxChunk = 8192;
01939          while (nleft > maxChunk)
01940          {
01941             glDrawArrays(GL_POINTS, ndone, maxChunk);
01942             nleft -= maxChunk;
01943             ndone += maxChunk;
01944          }
01945          glDrawArrays(GL_POINTS, ndone, nleft);
01946       }
01947       glPopClientAttrib();
01948    }
01949 }
01950 
01951 //______________________________________________________________________________
01952 void TGLUtil::RenderPolyLine(const TAttLine& aline, Char_t transp,
01953                              Float_t* p, Int_t n,
01954                              Int_t pick_radius, Bool_t selection)
01955 {
01956    // Render poly-line as specified by the p-array.
01957 
01958    if (n == 0) return;
01959 
01960    BeginAttLine(aline, transp, pick_radius, selection);
01961 
01962    Float_t* tp = p;
01963    glBegin(GL_LINE_STRIP);
01964    for (Int_t i=0; i<n; ++i, tp+=3)
01965       glVertex3fv(tp);
01966    glEnd();
01967 
01968    EndAttLine(pick_radius, selection);
01969 }
01970 
01971 //______________________________________________________________________________
01972 void TGLUtil::BeginAttLine(const TAttLine& aline, Char_t transp,
01973                            Int_t pick_radius, Bool_t selection)
01974 {
01975    // Setup drawing parrameters according to passed TAttLine.
01976 
01977    glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
01978 
01979    glDisable(GL_LIGHTING);
01980    TGLUtil::ColorTransparency(aline.GetLineColor(), transp);
01981    TGLUtil::LineWidth(aline.GetLineWidth());
01982    if (aline.GetLineStyle() > 1)
01983    {
01984       Int_t    fac = 1;
01985       UShort_t pat = 0xffff;
01986       switch (aline.GetLineStyle()) {
01987          case 2:  pat = 0x3333; break;
01988          case 3:  pat = 0x5555; break;
01989          case 4:  pat = 0xf040; break;
01990          case 5:  pat = 0xf4f4; break;
01991          case 6:  pat = 0xf111; break;
01992          case 7:  pat = 0xf0f0; break;
01993          case 8:  pat = 0xff11; break;
01994          case 9:  pat = 0x3fff; break;
01995          case 10: pat = 0x08ff; fac = 2; break;
01996       }
01997 
01998       glLineStipple(1, pat);
01999       glEnable(GL_LINE_STIPPLE);
02000    }
02001 
02002    // During selection extend picking region for large line-widths.
02003    if (selection && TGLUtil::LineWidth() > pick_radius)
02004       BeginExtendPickRegion((Float_t) pick_radius / TGLUtil::LineWidth());
02005 }
02006 
02007 //______________________________________________________________________________
02008 void TGLUtil::EndAttLine(Int_t pick_radius, Bool_t selection)
02009 {
02010    // Restore previous line drawing state.
02011 
02012    if (selection && TGLUtil::LineWidth() > pick_radius)
02013      EndExtendPickRegion();
02014 
02015    glPopAttrib(); 
02016 }
02017 
02018 /******************************************************************************/
02019 // Rendering atoms used by TGLViewer / TGScene.
02020 /******************************************************************************/
02021 
02022 //______________________________________________________________________________
02023 void TGLUtil::SetDrawColors(const UChar_t rgbai[4])
02024 {
02025    // Set basic draw colors from 4 component 'rgba'
02026    // Used by other TGLUtil drawing routines
02027    //
02028    // Sets basic (unlit) color - glColor
02029    // and also GL materials (see OpenGL docs) thus:
02030    //
02031    // diffuse  : rgba
02032    // ambient  : 0.0 0.0 0.0 1.0
02033    // specular : 0.6 0.6 0.6 1.0
02034    // emission : rgba/4.0
02035    // shininess: 60.0
02036    //
02037    // emission is set so objects with no lights (but lighting still enabled)
02038    // are partially visible
02039 
02040 
02041    // Util function to setup GL color for both unlit and lit material
02042    Float_t rgba[4]     = {rgbai[0]/255.f, rgbai[1]/255.f, rgbai[2]/255.f, rgbai[3]/255.f};
02043    Float_t ambient[4]  = {0.0, 0.0, 0.0, 1.0};
02044    Float_t specular[4] = {0.6, 0.6, 0.6, 1.0};
02045    Float_t emission[4] = {rgba[0]/4.f, rgba[1]/4.f, rgba[2]/4.f, rgba[3]};
02046 
02047    glColor4fv(rgba);
02048    glMaterialfv(GL_FRONT, GL_DIFFUSE, rgba);
02049    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
02050    glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
02051    glMaterialfv(GL_FRONT, GL_EMISSION, emission);
02052    glMaterialf(GL_FRONT, GL_SHININESS, 60.0);
02053 }
02054 
02055 //______________________________________________________________________________
02056 void TGLUtil::DrawSphere(const TGLVertex3 & position, Double_t radius,
02057                          const UChar_t rgba[4])
02058 {
02059    // Draw sphere, centered on vertex 'position', with radius 'radius',
02060    // color 'rgba'
02061    static TGLQuadric quad;
02062    SetDrawColors(rgba);
02063    glPushMatrix();
02064    glTranslated(position.X(), position.Y(), position.Z());
02065    gluSphere(quad.Get(), radius, fgDrawQuality, fgDrawQuality);
02066    glPopMatrix();
02067 }
02068 
02069 //______________________________________________________________________________
02070 void TGLUtil::DrawLine(const TGLLine3 & line, ELineHeadShape head, Double_t size,
02071                        const UChar_t rgba[4])
02072 {
02073    // Draw thick line (tube) defined by 'line', with head at end shape
02074    // 'head' - box/arrow/none, (head) size 'size', color 'rgba'
02075    DrawLine(line.Start(), line.Vector(), head, size, rgba);
02076 }
02077 
02078 //______________________________________________________________________________
02079 void TGLUtil::DrawLine(const TGLVertex3 & start, const TGLVector3 & vector,
02080                        ELineHeadShape head, Double_t size, const UChar_t rgba[4])
02081 {
02082    // Draw thick line (tube) running from 'start', length 'vector',
02083    // with head at end of shape 'head' - box/arrow/none,
02084    // (head) size 'size', color 'rgba'
02085    static TGLQuadric quad;
02086 
02087    // Draw 3D line (tube) with optional head shape
02088    SetDrawColors(rgba);
02089    glPushMatrix();
02090    TGLMatrix local(start, vector);
02091    glMultMatrixd(local.CArr());
02092 
02093    Double_t headHeight=0;
02094    if (head == kLineHeadNone) {
02095       headHeight = 0.0;
02096    } else if (head == kLineHeadArrow) {
02097       headHeight = size*2.0;
02098    } else if (head == kLineHeadBox) {
02099       headHeight = size*1.4;
02100    }
02101 
02102    // Line (tube) component
02103    gluCylinder(quad.Get(), 0.25*size, 0.25*size, vector.Mag() - headHeight, fgDrawQuality, 1);
02104    gluQuadricOrientation(quad.Get(), (GLenum)GLU_INSIDE);
02105    gluDisk(quad.Get(), 0.0, 0.25*size, fgDrawQuality, 1);
02106 
02107    glTranslated(0.0, 0.0, vector.Mag() - headHeight); // Shift down local Z to end of line
02108 
02109    if (head == kLineHeadNone) {
02110       // Cap end of line
02111       gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
02112       gluDisk(quad.Get(), 0.0, size/4.0, fgDrawQuality, 1);
02113    }
02114    else if (head == kLineHeadArrow) {
02115       // Arrow base / end line cap
02116       gluDisk(quad.Get(), 0.0, size, fgDrawQuality, 1);
02117       // Arrow cone
02118       gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
02119       gluCylinder(quad.Get(), size, 0.0, headHeight, fgDrawQuality, 1);
02120    } else if (head == kLineHeadBox) {
02121       // Box
02122       // TODO: Drawing box should be simplier - maybe make
02123       // a static helper which BB + others use.
02124       // Single face tesselation - ugly lighting
02125       gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
02126       TGLBoundingBox box(TGLVertex3(-size*.7, -size*.7, 0.0),
02127                          TGLVertex3(size*.7, size*.7, headHeight));
02128       box.Draw(kTRUE);
02129    }
02130    glPopMatrix();
02131 }
02132 
02133 //______________________________________________________________________________
02134 void TGLUtil::DrawRing(const TGLVertex3 & center, const TGLVector3 & normal,
02135                        Double_t radius, const UChar_t rgba[4])
02136 {
02137    // Draw ring, centered on 'center', lying on plane defined by 'center' & 'normal'
02138    // of outer radius 'radius', color 'rgba'
02139    static TGLQuadric quad;
02140 
02141    // Draw a ring, round vertex 'center', lying on plane defined by 'normal' vector
02142    // Radius defines the outer radius
02143    TGLUtil::SetDrawColors(rgba);
02144 
02145    Double_t outer = radius;
02146    Double_t width = radius*0.05;
02147    Double_t inner = outer - width;
02148 
02149    // Shift into local system, looking down 'normal' vector, origin at center
02150    glPushMatrix();
02151    TGLMatrix local(center, normal);
02152    glMultMatrixd(local.CArr());
02153 
02154    // Shift half width so rings centered over center vertex
02155    glTranslated(0.0, 0.0, -width/2.0);
02156 
02157    // Inner and outer faces
02158    gluCylinder(quad.Get(), inner, inner, width, fgDrawQuality, 1);
02159    gluCylinder(quad.Get(), outer, outer, width, fgDrawQuality, 1);
02160 
02161    // Top/bottom
02162    gluQuadricOrientation(quad.Get(), (GLenum)GLU_INSIDE);
02163    gluDisk(quad.Get(), inner, outer, fgDrawQuality, 1);
02164    glTranslated(0.0, 0.0, width);
02165    gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
02166    gluDisk(quad.Get(), inner, outer, fgDrawQuality, 1);
02167 
02168    glPopMatrix();
02169 }
02170 
02171 /**************************************************************************/
02172 
02173 //______________________________________________________________________________
02174 void TGLUtil::DrawReferenceMarker(const TGLCamera  & camera,
02175                                   const TGLVertex3 & pos,
02176                                         Float_t      radius,
02177                                   const UChar_t    * rgba)
02178 {
02179    // Draw a sphere- marker on world-coordinate 'pos' with pixel
02180    // radius 'radius'. Color argument is optional.
02181 
02182    static const UChar_t defColor[4] = { 250, 110, 0, 255 }; // Orange
02183 
02184    radius = camera.ViewportDeltaToWorld(pos, radius, radius).Mag();
02185    DrawSphere(pos, radius, rgba ? rgba : defColor);
02186 
02187 }
02188 
02189 //______________________________________________________________________________
02190 void TGLUtil::DrawSimpleAxes(const TGLCamera      & camera,
02191                              const TGLBoundingBox & bbox,
02192                                    Int_t            axesType)
02193 {
02194    // Draw simple xyz-axes for given bounding-box.
02195 
02196    if (axesType == kAxesNone)
02197       return;
02198 
02199    static const UChar_t axesColors[][4] = {
02200       {128,   0,   0, 255},  // -ive X axis light red
02201       {255,   0,   0, 255},  // +ive X axis deep red
02202       {  0, 128,   0, 255},  // -ive Y axis light green
02203       {  0, 255,   0, 255},  // +ive Y axis deep green
02204       {  0,   0, 128, 255},  // -ive Z axis light blue
02205       {  0,   0, 255, 255}   // +ive Z axis deep blue
02206    };
02207 
02208    static const UChar_t xyz[][8] = {
02209       {0x44, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0x44},
02210       {0x10, 0x10, 0x10, 0x10, 0x10, 0x28, 0x44, 0x44},
02211       {0x7c, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x7c}
02212    };
02213 
02214    // Axes draw at fixed screen size - back project to world
02215    TGLVector3 pixelVector = camera.ViewportDeltaToWorld(bbox.Center(), 1, 1);
02216    Double_t   pixelSize   = pixelVector.Mag();
02217 
02218    // Find x/y/z min/max values
02219    Double_t min[3] = { bbox.XMin(), bbox.YMin(), bbox.ZMin() };
02220    Double_t max[3] = { bbox.XMax(), bbox.YMax(), bbox.ZMax() };
02221 
02222    for (UInt_t i = 0; i < 3; i++) {
02223       TGLVertex3 start;
02224       TGLVector3 vector;
02225 
02226       if (axesType == kAxesOrigin) {
02227          // Through origin axes
02228          start[(i+1)%3] = 0.0;
02229          start[(i+2)%3] = 0.0;
02230       } else {
02231          // Side axes
02232          start[(i+1)%3] = min[(i+1)%3];
02233          start[(i+2)%3] = min[(i+2)%3];
02234       }
02235       vector[(i+1)%3] = 0.0;
02236       vector[(i+2)%3] = 0.0;
02237 
02238       // -ive axis?
02239       if (min[i] < 0.0) {
02240          // Runs from origin?
02241          if (max[i] > 0.0) {
02242             start[i] = 0.0;
02243             vector[i] = min[i];
02244          } else {
02245             start[i] = max[i];
02246             vector[i] = min[i] - max[i];
02247          }
02248          DrawLine(start, vector, kLineHeadNone, pixelSize*2.5, axesColors[i*2]);
02249       }
02250       // +ive axis?
02251       if (max[i] > 0.0) {
02252          // Runs from origin?
02253          if (min[i] < 0.0) {
02254             start[i] = 0.0;
02255             vector[i] = max[i];
02256          } else {
02257             start[i] = min[i];
02258             vector[i] = max[i] - min[i];
02259          }
02260          DrawLine(start, vector, kLineHeadNone, pixelSize*2.5, axesColors[i*2 + 1]);
02261       }
02262    }
02263 
02264    // Draw origin sphere(s)
02265    if (axesType == kAxesOrigin) {
02266       // Single white origin sphere at 0, 0, 0
02267       DrawSphere(TGLVertex3(0.0, 0.0, 0.0), pixelSize*2.0, fgWhite);
02268    } else {
02269       for (UInt_t j = 0; j < 3; j++) {
02270          if (min[j] <= 0.0 && max[j] >= 0.0) {
02271             TGLVertex3 zero;
02272             zero[j] = 0.0;
02273             zero[(j+1)%3] = min[(j+1)%3];
02274             zero[(j+2)%3] = min[(j+2)%3];
02275             DrawSphere(zero, pixelSize*2.0, axesColors[j*2 + 1]);
02276          }
02277       }
02278    }
02279 
02280    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
02281 
02282    // Labels
02283    Double_t padPixels = 25.0;
02284 
02285    glDisable(GL_LIGHTING);
02286    for (UInt_t k = 0; k < 3; k++) {
02287       SetDrawColors(axesColors[k*2+1]);
02288       TGLVertex3 minPos, maxPos;
02289       if (axesType == kAxesOrigin) {
02290          minPos[(k+1)%3] = 0.0;
02291          minPos[(k+2)%3] = 0.0;
02292       } else {
02293          minPos[(k+1)%3] = min[(k+1)%3];
02294          minPos[(k+2)%3] = min[(k+2)%3];
02295       }
02296       maxPos = minPos;
02297       minPos[k] = min[k];
02298       maxPos[k] = max[k];
02299 
02300       TGLVector3 axis = maxPos - minPos;
02301       TGLVector3 axisViewport = camera.WorldDeltaToViewport(minPos, axis);
02302 
02303       // Skip drawning if viewport projection of axis very small - labels will overlap
02304       // Occurs with orthographic cameras
02305       if (axisViewport.Mag() < 1) {
02306          continue;
02307       }
02308 
02309       minPos -= camera.ViewportDeltaToWorld(minPos, padPixels*axisViewport.X()/axisViewport.Mag(),
02310                                                     padPixels*axisViewport.Y()/axisViewport.Mag());
02311       axisViewport = camera.WorldDeltaToViewport(maxPos, -axis);
02312       maxPos -= camera.ViewportDeltaToWorld(maxPos, padPixels*axisViewport.X()/axisViewport.Mag(),
02313                                                     padPixels*axisViewport.Y()/axisViewport.Mag());
02314 
02315       DrawNumber(Form("%.0f", min[k]), minPos, kTRUE); // Min value
02316       DrawNumber(Form("%.0f", max[k]), maxPos, kTRUE); // Max value
02317 
02318       // Axis name beside max value
02319       TGLVertex3 namePos = maxPos -
02320          camera.ViewportDeltaToWorld(maxPos, padPixels*axisViewport.X()/axisViewport.Mag(),
02321                                      padPixels*axisViewport.Y()/axisViewport.Mag());
02322       glRasterPos3dv(namePos.CArr());
02323       glBitmap(8, 8, 0.0, 4.0, 0.0, 0.0, xyz[k]); // Axis Name
02324    }
02325 }
02326 
02327 //______________________________________________________________________________
02328 void TGLUtil::DrawNumber(const TString    & num,
02329                          const TGLVertex3 & pos,
02330                                Bool_t       center)
02331 {
02332    // Draw number in string 'num' via internal 8x8-pixel bitmap on
02333    // vertex 'pos'. If 'center' is true, the number is centered on 'pos'.
02334    // Only numbers, '.', '-' and ' ' are supported.
02335 
02336    static const UChar_t digits[][8] = {
02337       {0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38},//0
02338       {0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x10, 0x10},//1
02339       {0x7c, 0x44, 0x20, 0x18, 0x04, 0x04, 0x44, 0x38},//2
02340       {0x38, 0x44, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38},//3
02341       {0x04, 0x04, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x44},//4
02342       {0x7c, 0x44, 0x04, 0x04, 0x7c, 0x40, 0x40, 0x7c},//5
02343       {0x7c, 0x44, 0x44, 0x44, 0x7c, 0x40, 0x40, 0x7c},//6
02344       {0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x44, 0x7c},//7
02345       {0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38},//8
02346       {0x7c, 0x44, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x7c},//9
02347       {0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//.
02348       {0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00},//-
02349       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} //space
02350    };
02351 
02352    Double_t xOffset = 0, yOffset = 0;
02353    if (center)
02354    {
02355       xOffset = 3.5 * num.Length();
02356       yOffset = 4.0;
02357    }
02358 
02359    glRasterPos3dv(pos.CArr());
02360    for (Ssiz_t i = 0, e = num.Length(); i < e; ++i) {
02361       if (num[i] == '.') {
02362          glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[10]);
02363       } else if (num[i] == '-') {
02364          glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[11]);
02365       } else if (num[i] == ' ') {
02366          glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[12]);
02367       } else if (num[i] >= '0' && num[i] <= '9') {
02368          glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[num[i] - '0']);
02369       }
02370    }
02371 }
02372 
02373 
02374 /**************************************************************************/
02375 /**************************************************************************/
02376 
02377 //______________________________________________________________________________
02378 TGLCapabilitySwitch::TGLCapabilitySwitch(Int_t what, Bool_t state) :
02379    fWhat(what)
02380 {
02381    // Constructor - change state only if necessary.
02382 
02383    fState = glIsEnabled(fWhat);
02384    fFlip  = (fState != state);
02385    if (fFlip)
02386       SetState(state);
02387 }
02388 
02389 //______________________________________________________________________________
02390 TGLCapabilitySwitch::~TGLCapabilitySwitch()
02391 {
02392    // Destructor - reset state if changed.
02393 
02394    if (fFlip)
02395       SetState(fState);
02396 }
02397 
02398 //______________________________________________________________________________
02399 void TGLCapabilitySwitch::SetState(Bool_t s)
02400 {
02401    if (s)
02402       glEnable(fWhat);
02403    else
02404       glDisable(fWhat);
02405 }
02406 
02407 
02408 //______________________________________________________________________________
02409 TGLCapabilityEnabler::TGLCapabilityEnabler(Int_t what, Bool_t state) :
02410    fWhat(what)
02411 {
02412    // Constructor - change state only if necessary.
02413 
02414    fFlip = ! glIsEnabled(fWhat) && state;
02415    if (fFlip)
02416       glEnable(fWhat);
02417 }
02418 
02419 //______________________________________________________________________________
02420 TGLCapabilityEnabler::~TGLCapabilityEnabler()
02421 {
02422    // Destructor - reset state if changed.
02423 
02424    if (fFlip)
02425       glDisable(fWhat);
02426 }
02427 
02428 
02429 //______________________________________________________________________________
02430 TGLFloatHolder::TGLFloatHolder(Int_t what, Float_t state, void (*foo)(Float_t)) :
02431       fWhat(what), fState(0), fFlip(kFALSE), fFoo(foo)
02432    {
02433       glGetFloatv(fWhat, &fState);
02434       fFlip = (fState != state);
02435       if (fFlip) fFoo(state);
02436    }
02437 
02438 //______________________________________________________________________________
02439 TGLFloatHolder::~TGLFloatHolder()
02440    {
02441       if (fFlip) fFoo(fState);
02442    }
02443 
02444 
02445 //______________________________________________________________________________
02446 TGLEnableGuard::TGLEnableGuard(Int_t cap)
02447                   : fCap(cap)
02448 {
02449    // TGLEnableGuard constructor.
02450    glEnable(GLenum(fCap));
02451 }
02452 
02453 //______________________________________________________________________________
02454 TGLEnableGuard::~TGLEnableGuard()
02455 {
02456    // TGLEnableGuard destructor.
02457    glDisable(GLenum(fCap));
02458 }
02459 
02460 //______________________________________________________________________________
02461 TGLDisableGuard::TGLDisableGuard(Int_t cap)
02462                   : fCap(cap)
02463 {
02464    // TGLDisableGuard constructor.
02465    glDisable(GLenum(fCap));
02466 }
02467 
02468 //______________________________________________________________________________
02469 TGLDisableGuard::~TGLDisableGuard()
02470 {
02471    // TGLDisableGuard destructor.
02472    glEnable(GLenum(fCap));
02473 }
02474 
02475 ClassImp(TGLSelectionBuffer);
02476 
02477 //______________________________________________________________________________
02478 TGLSelectionBuffer::TGLSelectionBuffer()
02479                         : fWidth(0), fHeight(0)
02480 {
02481    // TGLSelectionBuffer constructor.
02482 }
02483 
02484 //______________________________________________________________________________
02485 TGLSelectionBuffer::~TGLSelectionBuffer()
02486 {
02487    // TGLSelectionBuffer destructor.
02488 }
02489 
02490 //______________________________________________________________________________
02491 void TGLSelectionBuffer::ReadColorBuffer(Int_t w, Int_t h)
02492 {
02493    // Read color buffer.
02494    fWidth = w;
02495    fHeight = h;
02496    fBuffer.resize(w * h * 4);
02497    glPixelStorei(GL_PACK_ALIGNMENT, 1);
02498    glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &fBuffer[0]);
02499 }
02500 
02501 //______________________________________________________________________________
02502 void TGLSelectionBuffer::ReadColorBuffer(Int_t x, Int_t y, Int_t w, Int_t h)
02503 {
02504    // Read color buffer.
02505    fWidth = w;
02506    fHeight = h;
02507    fBuffer.resize(w * h * 4);
02508    glPixelStorei(GL_PACK_ALIGNMENT, 1);
02509    glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &fBuffer[0]);
02510 }
02511 
02512 //______________________________________________________________________________
02513 const UChar_t *TGLSelectionBuffer::GetPixelColor(Int_t px, Int_t py)const
02514 {
02515    // Get pixel color.
02516    if (px < 0)
02517       px = 0;
02518    if (py < 0)
02519       py = 0;
02520 
02521    if (UInt_t(px * fWidth * 4 + py * 4) > fBuffer.size())
02522       return &fBuffer[0];
02523 
02524    return &fBuffer[px * fWidth * 4 + py * 4];
02525 }
02526 
02527 namespace Rgl {
02528 
02529 const Float_t gRedEmission[]    = {1.f, 0.f,  0.f, 1.f};
02530 const Float_t gGreenEmission[]  = {0.f, 1.f,  0.f, 1.f};
02531 const Float_t gBlueEmission[]   = {0.f, 0.f,  1.f, 1.f};
02532 const Float_t gOrangeEmission[] = {1.f, 0.4f, 0.f, 1.f};
02533 const Float_t gWhiteEmission[]  = {1.f, 1.f,  1.f, 1.f};
02534 const Float_t gGrayEmission[]   = {0.3f,0.3f, 0.3f,1.f};
02535 const Float_t gNullEmission[]   = {0.f, 0.f,  0.f, 1.f};
02536 
02537 namespace {
02538    struct RGB_t {
02539       Int_t fRGB[3];
02540    };
02541 
02542    RGB_t gColorTriplets[] = {{{255, 0, 0}},
02543                               {{0, 255, 0}},
02544                               {{0, 0, 255}},
02545                               {{255, 255, 0}},
02546                               {{255, 0, 255}},
02547                               {{0, 255, 255}},
02548                               {{255, 255, 255}}};
02549 
02550    Bool_t operator < (const RGB_t &lhs, const RGB_t &rhs)
02551    {
02552       if (lhs.fRGB[0] < rhs.fRGB[0])
02553          return kTRUE;
02554       else if (lhs.fRGB[0] > rhs.fRGB[0])
02555          return kFALSE;
02556       else if (lhs.fRGB[1] < rhs.fRGB[1])
02557          return kTRUE;
02558       else if (lhs.fRGB[1] > rhs.fRGB[1])
02559          return kFALSE;
02560       else if (lhs.fRGB[2] < rhs.fRGB[2])
02561          return kTRUE;
02562 
02563       return kFALSE;
02564    }
02565 
02566    typedef std::map<Int_t, RGB_t> ColorLookupTable_t;
02567    typedef ColorLookupTable_t::const_iterator CLTCI_t;
02568 
02569    ColorLookupTable_t gObjectIDToColor;
02570 
02571    typedef std::map<RGB_t, Int_t> ObjectLookupTable_t;
02572    typedef ObjectLookupTable_t::const_iterator OLTCI_t;
02573 
02574    ObjectLookupTable_t gColorToObjectID;
02575 }
02576 //______________________________________________________________________________
02577 void ObjectIDToColor(Int_t objectID, Bool_t highColor)
02578 {
02579    //Object id encoded as rgb triplet.
02580    if (!highColor)
02581       glColor3ub(objectID & 0xff, (objectID & 0xff00) >> 8, (objectID & 0xff0000) >> 16);
02582    else {
02583       if (!gObjectIDToColor.size()) {
02584       //Initialize lookup tables.
02585          for (Int_t i = 0, id = 1; i < Int_t(sizeof gColorTriplets / sizeof(RGB_t)); ++i, ++id)
02586             gObjectIDToColor[id] = gColorTriplets[i];
02587          for (Int_t i = 0, id = 1; i < Int_t(sizeof gColorTriplets / sizeof(RGB_t)); ++i, ++id)
02588             gColorToObjectID[gColorTriplets[i]] = id;
02589       }
02590 
02591       CLTCI_t it = gObjectIDToColor.find(objectID);
02592 
02593       if (it != gObjectIDToColor.end())
02594          glColor3ub(it->second.fRGB[0], it->second.fRGB[1], it->second.fRGB[2]);
02595       else {
02596          Error("ObjectIDToColor", "No color for such object ID: %d", objectID);
02597          glColor3ub(0, 0, 0);
02598       }
02599    }
02600 }
02601 
02602 //______________________________________________________________________________
02603 Int_t ColorToObjectID(const UChar_t *pixel, Bool_t highColor)
02604 {
02605    if (!highColor)
02606       return pixel[0] | (pixel[1] << 8) | (pixel[2] << 16);
02607    else {
02608       if (!gObjectIDToColor.size())
02609          return 0;
02610 
02611       RGB_t triplet = {{pixel[0], pixel[1], pixel[2]}};
02612       OLTCI_t it = gColorToObjectID.find(triplet);
02613 
02614       if (it != gColorToObjectID.end())
02615          return it->second;
02616       else
02617          return 0;
02618    }
02619 }
02620 
02621 
02622 //______________________________________________________________________________
02623 void DrawQuadOutline(const TGLVertex3 &v1, const TGLVertex3 &v2,
02624                      const TGLVertex3 &v3, const TGLVertex3 &v4)
02625 {
02626    //Draw quad outline.
02627    glBegin(GL_LINE_LOOP);
02628    glVertex3dv(v1.CArr());
02629    glVertex3dv(v2.CArr());
02630    glVertex3dv(v3.CArr());
02631    glVertex3dv(v4.CArr());
02632    glEnd();
02633 }
02634 
02635 //______________________________________________________________________________
02636 void DrawQuadFilled(const TGLVertex3 &v0, const TGLVertex3 &v1, const TGLVertex3 &v2,
02637                      const TGLVertex3 &v3, const TGLVector3 &normal)
02638 {
02639    //Draw quad face.
02640    glBegin(GL_POLYGON);
02641    glNormal3dv(normal.CArr());
02642    glVertex3dv(v0.CArr());
02643    glVertex3dv(v1.CArr());
02644    glVertex3dv(v2.CArr());
02645    glVertex3dv(v3.CArr());
02646    glEnd();
02647 }
02648 
02649 //______________________________________________________________________________
02650 void DrawQuadFilled(const Double_t *v0, const Double_t *v1, const Double_t *v2, const Double_t *v3,
02651                     const Double_t *normal)
02652 {
02653    //Draw quad face.
02654    glBegin(GL_QUADS);
02655    glNormal3dv(normal);
02656    glVertex3dv(v0);
02657    glVertex3dv(v1);
02658    glVertex3dv(v2);
02659    glVertex3dv(v3);
02660    glEnd();
02661 }
02662 
02663 //______________________________________________________________________________
02664 void DrawSmoothFace(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3,
02665                   const TGLVector3 &norm1, const TGLVector3 &norm2, const TGLVector3 &norm3)
02666 {
02667    //Draws triangle face, each vertex has its own averaged normal
02668    glBegin(GL_POLYGON);
02669    glNormal3dv(norm1.CArr());
02670    glVertex3dv(v1.CArr());
02671    glNormal3dv(norm2.CArr());
02672    glVertex3dv(v2.CArr());
02673    glNormal3dv(norm3.CArr());
02674    glVertex3dv(v3.CArr());
02675    glEnd();
02676 }
02677 
02678 const Int_t    gBoxFrontQuads[][4] = {{0, 1, 2, 3}, {4, 0, 3, 5}, {4, 5, 6, 7}, {7, 6, 2, 1}};
02679 const Double_t gBoxFrontNormals[][3] = {{-1., 0., 0.}, {0., -1., 0.}, {1., 0., 0.}, {0., 1., 0.}};
02680 const Int_t    gBoxFrontPlanes[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};
02681 
02682 //______________________________________________________________________________
02683 void DrawBoxFront(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax,
02684                   Double_t zMin, Double_t zMax, Int_t fp)
02685 {
02686    //Draws lego's bar as a 3d box
02687    if (zMax < zMin)
02688       std::swap(zMax, zMin);
02689 
02690    //Bottom is always drawn.
02691    glBegin(GL_POLYGON);
02692    glNormal3d(0., 0., -1.);
02693    glVertex3d(xMax, yMin, zMin);
02694    glVertex3d(xMin, yMin, zMin);
02695    glVertex3d(xMin, yMax, zMin);
02696    glVertex3d(xMax, yMax, zMin);
02697    glEnd();
02698    //Draw two visible front planes.
02699    const Double_t box[][3] = {{xMin, yMin, zMax}, {xMin, yMax, zMax}, {xMin, yMax, zMin}, {xMin, yMin, zMin},
02700                               {xMax, yMin, zMax}, {xMax, yMin, zMin}, {xMax, yMax, zMin}, {xMax, yMax, zMax}};
02701    const Int_t *verts = gBoxFrontQuads[gBoxFrontPlanes[fp][0]];
02702 
02703    glBegin(GL_POLYGON);
02704    glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][0]]);
02705    glVertex3dv(box[verts[0]]);
02706    glVertex3dv(box[verts[1]]);
02707    glVertex3dv(box[verts[2]]);
02708    glVertex3dv(box[verts[3]]);
02709    glEnd();
02710 
02711    verts = gBoxFrontQuads[gBoxFrontPlanes[fp][1]];
02712 
02713    glBegin(GL_POLYGON);
02714    glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][1]]);
02715    glVertex3dv(box[verts[0]]);
02716    glVertex3dv(box[verts[1]]);
02717    glVertex3dv(box[verts[2]]);
02718    glVertex3dv(box[verts[3]]);
02719    glEnd();
02720 
02721    //Top is always drawn.
02722    glBegin(GL_POLYGON);
02723    glNormal3d(0., 0., 1.);
02724    glVertex3d(xMax, yMin, zMax);
02725    glVertex3d(xMax, yMax, zMax);
02726    glVertex3d(xMin, yMax, zMax);
02727    glVertex3d(xMin, yMin, zMax);
02728    glEnd();
02729 }
02730 
02731 //______________________________________________________________________________
02732 void DrawBoxFrontTextured(Double_t xMin, Double_t xMax, Double_t yMin,
02733                            Double_t yMax, Double_t zMin, Double_t zMax,
02734                            Double_t texMin, Double_t texMax, Int_t fp)
02735 {
02736    //Draws lego's bar as a 3d box
02737    //LULULULU
02738    if (zMax < zMin) {
02739       std::swap(zMax, zMin);
02740       std::swap(texMax, texMin);
02741    }
02742 
02743    //Top and bottom are always drawn.
02744    glBegin(GL_POLYGON);
02745    glNormal3d(0., 0., 1.);
02746    glTexCoord1d(texMax);
02747    glVertex3d(xMax, yMin, zMax);
02748    glVertex3d(xMax, yMax, zMax);
02749    glVertex3d(xMin, yMax, zMax);
02750    glVertex3d(xMin, yMin, zMax);
02751    glEnd();
02752 
02753    glBegin(GL_POLYGON);
02754    glTexCoord1d(texMin);
02755    glNormal3d(0., 0., -1.);
02756    glVertex3d(xMax, yMin, zMin);
02757    glVertex3d(xMin, yMin, zMin);
02758    glVertex3d(xMin, yMax, zMin);
02759    glVertex3d(xMax, yMax, zMin);
02760    glEnd();
02761    //Draw two visible front planes.
02762    const Double_t box[][3] = {{xMin, yMin, zMax}, {xMin, yMax, zMax}, {xMin, yMax, zMin}, {xMin, yMin, zMin},
02763                               {xMax, yMin, zMax}, {xMax, yMin, zMin}, {xMax, yMax, zMin}, {xMax, yMax, zMax}};
02764 
02765    const Double_t tex[] = {texMax, texMax, texMin, texMin, texMax, texMin, texMin, texMax};
02766    const Int_t *verts = gBoxFrontQuads[gBoxFrontPlanes[fp][0]];
02767 
02768    glBegin(GL_POLYGON);
02769    glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][0]]);
02770    glTexCoord1d(tex[verts[0]]);
02771    glVertex3dv(box[verts[0]]);
02772    glTexCoord1d(tex[verts[1]]);
02773    glVertex3dv(box[verts[1]]);
02774    glTexCoord1d(tex[verts[2]]);
02775    glVertex3dv(box[verts[2]]);
02776    glTexCoord1d(tex[verts[3]]);
02777    glVertex3dv(box[verts[3]]);
02778    glEnd();
02779 
02780    verts = gBoxFrontQuads[gBoxFrontPlanes[fp][1]];
02781 
02782    glBegin(GL_POLYGON);
02783    glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][1]]);
02784    glTexCoord1d(tex[verts[0]]);
02785    glVertex3dv(box[verts[0]]);
02786    glTexCoord1d(tex[verts[1]]);
02787    glVertex3dv(box[verts[1]]);
02788    glTexCoord1d(tex[verts[2]]);
02789    glVertex3dv(box[verts[2]]);
02790    glTexCoord1d(tex[verts[3]]);
02791    glVertex3dv(box[verts[3]]);
02792    glEnd();
02793 }
02794 
02795 
02796 //______________________________________________________________________________
02797 void DrawCylinder(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin,
02798                   Double_t yMax, Double_t zMin, Double_t zMax)
02799 {
02800    //Cylinder for lego3.
02801    GLUquadric *quad = quadric->Get();
02802 
02803    if (quad) {
02804       if (zMin > zMax)
02805          std::swap(zMin, zMax);
02806       const Double_t xCenter = xMin + (xMax - xMin) / 2;
02807       const Double_t yCenter = yMin + (yMax - yMin) / 2;
02808       const Double_t radius = TMath::Min((xMax - xMin) / 2, (yMax - yMin) / 2);
02809 
02810       glPushMatrix();
02811       glTranslated(xCenter, yCenter, zMin);
02812       gluCylinder(quad, radius, radius, zMax - zMin, 40, 1);
02813       glPopMatrix();
02814       glPushMatrix();
02815       glTranslated(xCenter, yCenter, zMax);
02816       gluDisk(quad, 0., radius, 40, 1);
02817       glPopMatrix();
02818       glPushMatrix();
02819       glTranslated(xCenter, yCenter, zMin);
02820       glRotated(180., 0., 1., 0.);
02821       gluDisk(quad, 0., radius, 40, 1);
02822       glPopMatrix();
02823    }
02824 }
02825 
02826 //______________________________________________________________________________
02827 void DrawSphere(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin,
02828                   Double_t yMax, Double_t zMin, Double_t zMax)
02829 {
02830    //Cylinder for lego3.
02831    GLUquadric *quad = quadric->Get();
02832 
02833    if (quad) {
02834       const Double_t xCenter = xMin + (xMax - xMin) / 2;
02835       const Double_t yCenter = yMin + (yMax - yMin) / 2;
02836       const Double_t zCenter = zMin + (zMax - zMin) / 2;
02837 
02838       const Double_t radius = TMath::Min((zMax - zMin) / 2,
02839                                           TMath::Min((xMax - xMin) / 2, (yMax - yMin) / 2));
02840 
02841       glPushMatrix();
02842       glTranslated(xCenter, yCenter, zCenter);
02843       gluSphere(quad, radius, 10, 10);
02844       glPopMatrix();
02845    }
02846 }
02847 
02848 
02849 //______________________________________________________________________________
02850 void DrawError(Double_t xMin, Double_t xMax, Double_t yMin,
02851                Double_t yMax, Double_t zMin, Double_t zMax)
02852 {
02853    const Double_t xWid = xMax - xMin;
02854    const Double_t yWid = yMax - yMin;
02855 
02856    glBegin(GL_LINES);
02857    glVertex3d(xMin + xWid / 2, yMin + yWid / 2, zMin);
02858    glVertex3d(xMin + xWid / 2, yMin + yWid / 2, zMax);
02859    glEnd();
02860 
02861    glBegin(GL_LINES);
02862    glVertex3d(xMin + xWid / 2, yMin, zMin);
02863    glVertex3d(xMin + xWid / 2, yMax, zMin);
02864    glEnd();
02865 
02866    glBegin(GL_LINES);
02867    glVertex3d(xMin, yMin + yWid / 2, zMin);
02868    glVertex3d(xMax, yMin + yWid / 2, zMin);
02869    glEnd();
02870 }
02871 
02872 void CylindricalNormal(const Double_t *v, Double_t *normal)
02873 {
02874    const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1]);
02875    if (n > 0.) {
02876       normal[0] = v[0] / n;
02877       normal[1] = v[1] / n;
02878       normal[2] = 0.;
02879    } else {
02880       normal[0] = v[0];
02881       normal[1] = v[1];
02882       normal[2] = 0.;
02883    }
02884 }
02885 
02886 void CylindricalNormalInv(const Double_t *v, Double_t *normal)
02887 {
02888    const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1]);
02889    if (n > 0.) {
02890       normal[0] = -v[0] / n;
02891       normal[1] = -v[1] / n;
02892       normal[2] = 0.;
02893    } else {
02894       normal[0] = -v[0];
02895       normal[1] = -v[1];
02896       normal[2] = 0.;
02897    }
02898 }
02899 
02900 void DrawTrapezoid(const Double_t ver[][2], Double_t zMin, Double_t zMax, Bool_t color)
02901 {
02902    //In polar coordinates, box became trapezoid.
02903    //Four faces need normal calculations.
02904    if (zMin > zMax)
02905       std::swap(zMin, zMax);
02906    //top
02907    glBegin(GL_POLYGON);
02908    glNormal3d(0., 0., 1.);
02909    glVertex3d(ver[0][0], ver[0][1], zMax);
02910    glVertex3d(ver[1][0], ver[1][1], zMax);
02911    glVertex3d(ver[2][0], ver[2][1], zMax);
02912    glVertex3d(ver[3][0], ver[3][1], zMax);
02913    glEnd();
02914    //bottom
02915    glBegin(GL_POLYGON);
02916    glNormal3d(0., 0., -1.);
02917    glVertex3d(ver[0][0], ver[0][1], zMin);
02918    glVertex3d(ver[3][0], ver[3][1], zMin);
02919    glVertex3d(ver[2][0], ver[2][1], zMin);
02920    glVertex3d(ver[1][0], ver[1][1], zMin);
02921    glEnd();
02922    //
02923 
02924    Double_t trapezoid[][3] = {{ver[0][0], ver[0][1], zMin}, {ver[1][0], ver[1][1], zMin},
02925                               {ver[2][0], ver[2][1], zMin}, {ver[3][0], ver[3][1], zMin},
02926                               {ver[0][0], ver[0][1], zMax}, {ver[1][0], ver[1][1], zMax},
02927                               {ver[2][0], ver[2][1], zMax}, {ver[3][0], ver[3][1], zMax}};
02928    Double_t normal[3] = {0.};
02929    glBegin(GL_POLYGON);
02930    CylindricalNormal(trapezoid[1], normal), glNormal3dv(normal), glVertex3dv(trapezoid[1]);
02931    CylindricalNormal(trapezoid[2], normal), glNormal3dv(normal), glVertex3dv(trapezoid[2]);
02932    CylindricalNormal(trapezoid[6], normal), glNormal3dv(normal), glVertex3dv(trapezoid[6]);
02933    CylindricalNormal(trapezoid[5], normal), glNormal3dv(normal), glVertex3dv(trapezoid[5]);
02934    glEnd();
02935 
02936    glBegin(GL_POLYGON);
02937    CylindricalNormalInv(trapezoid[0], normal), glNormal3dv(normal), glVertex3dv(trapezoid[0]);
02938    CylindricalNormalInv(trapezoid[4], normal), glNormal3dv(normal), glVertex3dv(trapezoid[4]);
02939    CylindricalNormalInv(trapezoid[7], normal), glNormal3dv(normal), glVertex3dv(trapezoid[7]);
02940    CylindricalNormalInv(trapezoid[3], normal), glNormal3dv(normal), glVertex3dv(trapezoid[3]);
02941    glEnd();
02942 
02943    glBegin(GL_POLYGON);
02944    if (color) {
02945       TMath::Normal2Plane(trapezoid[0], trapezoid[1], trapezoid[5], normal);
02946       glNormal3dv(normal);
02947    }
02948    glVertex3dv(trapezoid[0]);
02949    glVertex3dv(trapezoid[1]);
02950    glVertex3dv(trapezoid[5]);
02951    glVertex3dv(trapezoid[4]);
02952    glEnd();
02953 
02954    glBegin(GL_POLYGON);
02955    if (color) {
02956       TMath::Normal2Plane(trapezoid[3], trapezoid[7], trapezoid[6], normal);
02957       glNormal3dv(normal);
02958    }
02959    glVertex3dv(trapezoid[3]);
02960    glVertex3dv(trapezoid[7]);
02961    glVertex3dv(trapezoid[6]);
02962    glVertex3dv(trapezoid[2]);
02963    glEnd();
02964 }
02965 
02966 //______________________________________________________________________________
02967 void DrawTrapezoidTextured(const Double_t ver[][2], Double_t zMin, Double_t zMax,
02968                            Double_t texMin, Double_t texMax)
02969 {
02970    //In polar coordinates, box became trapezoid.
02971    //Four faces need normal calculations.
02972    if (zMin > zMax) {
02973       std::swap(zMin, zMax);
02974       std::swap(texMin, texMax);
02975    }
02976 
02977    //top
02978    glBegin(GL_POLYGON);
02979    glNormal3d(0., 0., 1.);
02980    glTexCoord1d(texMax);
02981    glVertex3d(ver[0][0], ver[0][1], zMax);
02982    glVertex3d(ver[1][0], ver[1][1], zMax);
02983    glVertex3d(ver[2][0], ver[2][1], zMax);
02984    glVertex3d(ver[3][0], ver[3][1], zMax);
02985    glEnd();
02986    //bottom
02987    glBegin(GL_POLYGON);
02988    glNormal3d(0., 0., -1.);
02989    glTexCoord1d(texMin);
02990    glVertex3d(ver[0][0], ver[0][1], zMin);
02991    glVertex3d(ver[3][0], ver[3][1], zMin);
02992    glVertex3d(ver[2][0], ver[2][1], zMin);
02993    glVertex3d(ver[1][0], ver[1][1], zMin);
02994    glEnd();
02995    //
02996 
02997    Double_t trapezoid[][3] = {{ver[0][0], ver[0][1], zMin}, {ver[1][0], ver[1][1], zMin},
02998                               {ver[2][0], ver[2][1], zMin}, {ver[3][0], ver[3][1], zMin},
02999                               {ver[0][0], ver[0][1], zMax}, {ver[1][0], ver[1][1], zMax},
03000                               {ver[2][0], ver[2][1], zMax}, {ver[3][0], ver[3][1], zMax}};
03001    Double_t normal[3] = {0.};
03002    glBegin(GL_POLYGON);
03003    CylindricalNormal(trapezoid[1], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[1]);
03004    CylindricalNormal(trapezoid[2], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[2]);
03005    CylindricalNormal(trapezoid[6], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[6]);
03006    CylindricalNormal(trapezoid[5], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[5]);
03007    glEnd();
03008 
03009    glBegin(GL_POLYGON);
03010    CylindricalNormalInv(trapezoid[0], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[0]);
03011    CylindricalNormalInv(trapezoid[4], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[4]);
03012    CylindricalNormalInv(trapezoid[7], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[7]);
03013    CylindricalNormalInv(trapezoid[3], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[3]);
03014    glEnd();
03015 
03016    glBegin(GL_POLYGON);
03017    TMath::Normal2Plane(trapezoid[0], trapezoid[1], trapezoid[5], normal);
03018    glNormal3dv(normal);
03019    glTexCoord1d(texMin);
03020    glVertex3dv(trapezoid[0]);
03021    glTexCoord1d(texMin);
03022    glVertex3dv(trapezoid[1]);
03023    glTexCoord1d(texMax);
03024    glVertex3dv(trapezoid[5]);
03025    glTexCoord1d(texMax);
03026    glVertex3dv(trapezoid[4]);
03027    glEnd();
03028 
03029    glBegin(GL_POLYGON);
03030    TMath::Normal2Plane(trapezoid[3], trapezoid[7], trapezoid[6], normal);
03031    glNormal3dv(normal);
03032    glTexCoord1d(texMin);
03033    glVertex3dv(trapezoid[3]);
03034    glTexCoord1d(texMax);
03035    glVertex3dv(trapezoid[7]);
03036    glTexCoord1d(texMax);
03037    glVertex3dv(trapezoid[6]);
03038    glTexCoord1d(texMin);
03039    glVertex3dv(trapezoid[2]);
03040    glEnd();
03041 }
03042 
03043 //______________________________________________________________________________
03044 void DrawTrapezoidTextured2(const Double_t ver[][2], Double_t zMin, Double_t zMax,
03045                               Double_t texMin, Double_t texMax)
03046 {
03047    //In polar coordinates, box became trapezoid.
03048    if (zMin > zMax)
03049       std::swap(zMin, zMax);
03050 
03051    const Double_t trapezoid[][3] = {{ver[0][0], ver[0][1], zMin}, {ver[1][0], ver[1][1], zMin},
03052                                     {ver[2][0], ver[2][1], zMin}, {ver[3][0], ver[3][1], zMin},
03053                                     {ver[0][0], ver[0][1], zMax}, {ver[1][0], ver[1][1], zMax},
03054                                     {ver[2][0], ver[2][1], zMax}, {ver[3][0], ver[3][1], zMax}};
03055    const Double_t tex[] = {texMin, texMax, texMax, texMin, texMin, texMax, texMax, texMin};
03056    //top
03057    glBegin(GL_POLYGON);
03058    glNormal3d(0., 0., 1.);
03059    glTexCoord1d(tex[4]), glVertex3dv(trapezoid[4]);
03060    glTexCoord1d(tex[5]), glVertex3dv(trapezoid[5]);
03061    glTexCoord1d(tex[6]), glVertex3dv(trapezoid[6]);
03062    glTexCoord1d(tex[7]), glVertex3dv(trapezoid[7]);
03063    glEnd();
03064    //bottom
03065    glBegin(GL_POLYGON);
03066    glNormal3d(0., 0., -1.);
03067    glTexCoord1d(tex[0]), glVertex3dv(trapezoid[0]);
03068    glTexCoord1d(tex[3]), glVertex3dv(trapezoid[3]);
03069    glTexCoord1d(tex[2]), glVertex3dv(trapezoid[2]);
03070    glTexCoord1d(tex[1]), glVertex3dv(trapezoid[1]);
03071    glEnd();
03072    //
03073    glBegin(GL_POLYGON);
03074    Double_t normal[3] = {};
03075    CylindricalNormal(trapezoid[1], normal), glNormal3dv(normal), glTexCoord1d(tex[1]), glVertex3dv(trapezoid[1]);
03076    CylindricalNormal(trapezoid[2], normal), glNormal3dv(normal), glTexCoord1d(tex[2]), glVertex3dv(trapezoid[2]);
03077    CylindricalNormal(trapezoid[6], normal), glNormal3dv(normal), glTexCoord1d(tex[6]), glVertex3dv(trapezoid[6]);
03078    CylindricalNormal(trapezoid[5], normal), glNormal3dv(normal), glTexCoord1d(tex[5]), glVertex3dv(trapezoid[5]);
03079    glEnd();
03080 
03081    glBegin(GL_POLYGON);
03082    CylindricalNormalInv(trapezoid[0], normal), glNormal3dv(normal), glTexCoord1d(tex[0]), glVertex3dv(trapezoid[0]);
03083    CylindricalNormalInv(trapezoid[4], normal), glNormal3dv(normal), glTexCoord1d(tex[4]), glVertex3dv(trapezoid[4]);
03084    CylindricalNormalInv(trapezoid[7], normal), glNormal3dv(normal), glTexCoord1d(tex[7]), glVertex3dv(trapezoid[7]);
03085    CylindricalNormalInv(trapezoid[3], normal), glNormal3dv(normal), glTexCoord1d(tex[3]), glVertex3dv(trapezoid[3]);
03086    glEnd();
03087 
03088    glBegin(GL_POLYGON);
03089    TMath::Normal2Plane(trapezoid[0], trapezoid[1], trapezoid[5], normal);
03090    glNormal3dv(normal);
03091    glTexCoord1d(tex[0]), glVertex3dv(trapezoid[0]);
03092    glTexCoord1d(tex[1]), glVertex3dv(trapezoid[1]);
03093    glTexCoord1d(tex[5]), glVertex3dv(trapezoid[5]);
03094    glTexCoord1d(tex[4]), glVertex3dv(trapezoid[4]);
03095    glEnd();
03096 
03097    glBegin(GL_POLYGON);
03098    TMath::Normal2Plane(trapezoid[3], trapezoid[7], trapezoid[6], normal);
03099    glNormal3dv(normal);
03100    glTexCoord1d(tex[3]), glVertex3dv(trapezoid[3]);
03101    glTexCoord1d(tex[7]), glVertex3dv(trapezoid[7]);
03102    glTexCoord1d(tex[6]), glVertex3dv(trapezoid[6]);
03103    glTexCoord1d(tex[2]), glVertex3dv(trapezoid[2]);
03104    glEnd();
03105 }
03106 
03107 //______________________________________________________________________________
03108 void SphericalNormal(const Double_t *v, Double_t *normal)
03109 {
03110    const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
03111    if (n > 0.) {
03112       normal[0] = v[0] / n;
03113       normal[1] = v[1] / n;
03114       normal[2] = v[2] / n;
03115    } else {
03116       normal[0] = v[0];
03117       normal[1] = v[1];
03118       normal[2] = v[2];
03119    }
03120 }
03121 
03122 //______________________________________________________________________________
03123 void SphericalNormalInv(const Double_t *v, Double_t *normal)
03124 {
03125    const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
03126    if (n > 0.) {
03127       normal[0] = -v[0] / n;
03128       normal[1] = -v[1] / n;
03129       normal[2] = -v[2] / n;
03130    } else {
03131       normal[0] = -v[0];
03132       normal[1] = -v[1];
03133       normal[2] = -v[2];
03134    }
03135 }
03136 
03137 //______________________________________________________________________________
03138 void DrawTrapezoid(const Double_t ver[][3])
03139 {
03140    Double_t normal[3] = {0.};
03141 
03142    glBegin(GL_POLYGON);
03143    TMath::Normal2Plane(ver[1], ver[2], ver[3], normal);
03144    glNormal3dv(normal);
03145    glVertex3dv(ver[0]);
03146    glVertex3dv(ver[1]);
03147    glVertex3dv(ver[2]);
03148    glVertex3dv(ver[3]);
03149    glEnd();
03150    //bottom
03151    glBegin(GL_POLYGON);
03152    TMath::Normal2Plane(ver[4], ver[7], ver[6], normal);
03153    glNormal3dv(normal);
03154    glVertex3dv(ver[4]);
03155    glVertex3dv(ver[7]);
03156    glVertex3dv(ver[6]);
03157    glVertex3dv(ver[5]);
03158    glEnd();
03159    //
03160 
03161    glBegin(GL_POLYGON);
03162    TMath::Normal2Plane(ver[0], ver[3], ver[7], normal);
03163    glNormal3dv(normal);
03164    glVertex3dv(ver[0]);
03165    glVertex3dv(ver[3]);
03166    glVertex3dv(ver[7]);
03167    glVertex3dv(ver[4]);
03168    glEnd();
03169 
03170    glBegin(GL_POLYGON);
03171    SphericalNormal(ver[3], normal), glNormal3dv(normal), glVertex3dv(ver[3]);
03172    SphericalNormal(ver[2], normal), glNormal3dv(normal), glVertex3dv(ver[2]);
03173    SphericalNormal(ver[6], normal), glNormal3dv(normal), glVertex3dv(ver[6]);
03174    SphericalNormal(ver[7], normal), glNormal3dv(normal), glVertex3dv(ver[7]);
03175    glEnd();
03176 
03177    glBegin(GL_POLYGON);
03178    TMath::Normal2Plane(ver[5], ver[6], ver[2], normal);
03179    glNormal3dv(normal);
03180    glVertex3dv(ver[5]);
03181    glVertex3dv(ver[6]);
03182    glVertex3dv(ver[2]);
03183    glVertex3dv(ver[1]);
03184    glEnd();
03185 
03186    glBegin(GL_POLYGON);
03187    SphericalNormalInv(ver[0], normal), glNormal3dv(normal), glVertex3dv(ver[0]);
03188    SphericalNormalInv(ver[4], normal), glNormal3dv(normal), glVertex3dv(ver[4]);
03189    SphericalNormalInv(ver[5], normal), glNormal3dv(normal), glVertex3dv(ver[5]);
03190    SphericalNormalInv(ver[1], normal), glNormal3dv(normal), glVertex3dv(ver[1]);
03191    glEnd();
03192 }
03193 
03194 //______________________________________________________________________________
03195 void DrawTrapezoidTextured(const Double_t ver[][3], Double_t texMin, Double_t texMax)
03196 {
03197    Double_t normal[3] = {};
03198    if (texMin > texMax)
03199       std::swap(texMin, texMax);
03200 
03201    const Double_t tex[] = {texMin, texMin, texMax, texMax, texMin, texMin, texMax, texMax};
03202    glBegin(GL_POLYGON);
03203    TMath::Normal2Plane(ver[0], ver[1], ver[2], normal);
03204    glNormal3dv(normal);
03205    glTexCoord1d(tex[0]), glVertex3dv(ver[0]);
03206    glTexCoord1d(tex[1]), glVertex3dv(ver[1]);
03207    glTexCoord1d(tex[2]), glVertex3dv(ver[2]);
03208    glTexCoord1d(tex[3]), glVertex3dv(ver[3]);
03209    glEnd();
03210    glBegin(GL_POLYGON);
03211    TMath::Normal2Plane(ver[4], ver[7], ver[6], normal);
03212    glNormal3dv(normal);
03213    glTexCoord1d(tex[4]), glVertex3dv(ver[4]);
03214    glTexCoord1d(tex[7]), glVertex3dv(ver[7]);
03215    glTexCoord1d(tex[6]), glVertex3dv(ver[6]);
03216    glTexCoord1d(tex[5]), glVertex3dv(ver[5]);
03217    glEnd();
03218    glBegin(GL_POLYGON);
03219    TMath::Normal2Plane(ver[0], ver[3], ver[7], normal);
03220    glNormal3dv(normal);
03221    glTexCoord1d(tex[0]), glVertex3dv(ver[0]);
03222    glTexCoord1d(tex[3]), glVertex3dv(ver[3]);
03223    glTexCoord1d(tex[7]), glVertex3dv(ver[7]);
03224    glTexCoord1d(tex[4]), glVertex3dv(ver[4]);
03225    glEnd();
03226    glBegin(GL_POLYGON);
03227    SphericalNormal(ver[3], normal), glNormal3dv(normal), glTexCoord1d(tex[3]), glVertex3dv(ver[3]);
03228    SphericalNormal(ver[2], normal), glNormal3dv(normal), glTexCoord1d(tex[2]), glVertex3dv(ver[2]);
03229    SphericalNormal(ver[6], normal), glNormal3dv(normal), glTexCoord1d(tex[6]), glVertex3dv(ver[6]);
03230    SphericalNormal(ver[7], normal), glNormal3dv(normal), glTexCoord1d(tex[7]), glVertex3dv(ver[7]);
03231    glEnd();
03232    glBegin(GL_POLYGON);
03233    TMath::Normal2Plane(ver[5], ver[6], ver[2], normal);
03234    glNormal3dv(normal);
03235    glTexCoord1d(tex[5]), glVertex3dv(ver[5]);
03236    glTexCoord1d(tex[6]), glVertex3dv(ver[6]);
03237    glTexCoord1d(tex[2]), glVertex3dv(ver[2]);
03238    glTexCoord1d(tex[1]), glVertex3dv(ver[1]);
03239    glEnd();
03240    glBegin(GL_POLYGON);
03241    SphericalNormalInv(ver[0], normal), glNormal3dv(normal), glTexCoord1d(tex[0]), glVertex3dv(ver[0]);
03242    SphericalNormalInv(ver[4], normal), glNormal3dv(normal), glTexCoord1d(tex[4]), glVertex3dv(ver[4]);
03243    SphericalNormalInv(ver[5], normal), glNormal3dv(normal), glTexCoord1d(tex[5]), glVertex3dv(ver[5]);
03244    SphericalNormalInv(ver[1], normal), glNormal3dv(normal), glTexCoord1d(tex[1]), glVertex3dv(ver[1]);
03245    glEnd();
03246 }
03247 
03248 
03249 void Draw2DAxis(TAxis *axis, Double_t xMin, Double_t yMin, Double_t xMax, Double_t yMax,
03250                Double_t min, Double_t max, Bool_t log, Bool_t z = kFALSE)
03251 {
03252    //Axes are drawn with help of TGaxis class
03253    std::string option;
03254    option.reserve(20);
03255 
03256    if (xMin > xMax || z) option += "SDH=+";
03257    else option += "SDH=-";
03258 
03259    if (log) option += 'G';
03260 
03261    Int_t nDiv = axis->GetNdivisions();
03262 
03263    if (nDiv < 0) {
03264       option += 'N';
03265       nDiv = -nDiv;
03266    }
03267 
03268    TGaxis axisPainter;
03269    axisPainter.SetLineWidth(1);
03270 
03271    static const Double_t zero = 0.001;
03272 
03273    if (TMath::Abs(xMax - xMin) >= zero || TMath::Abs(yMax - yMin) >= zero) {
03274       axisPainter.ImportAxisAttributes(axis);
03275       axisPainter.SetLabelOffset(axis->GetLabelOffset() + axis->GetTickLength());
03276 
03277       if (log) {
03278          min = TMath::Power(10, min);
03279          max = TMath::Power(10, max);
03280       }
03281       //Option time display is required ?
03282       if (axis->GetTimeDisplay()) {
03283          option += 't';
03284 
03285          if (!strlen(axis->GetTimeFormatOnly()))
03286             axisPainter.SetTimeFormat(axis->ChooseTimeFormat(max - min));
03287          else
03288             axisPainter.SetTimeFormat(axis->GetTimeFormat());
03289       }
03290 
03291       axisPainter.SetOption(option.c_str());
03292       axisPainter.PaintAxis(xMin, yMin, xMax, yMax, min, max, nDiv, option.c_str());
03293    }
03294 }
03295 
03296 const Int_t gFramePoints[][2] = {{3, 1}, {0, 2}, {1, 3}, {2, 0}};
03297 //Each point has two "neighbouring axes" (left and right). Axes types are 1 (ordinata) and 0 (abscissa)
03298 const Int_t gAxisType[][2]    = {{1, 0}, {0, 1}, {1, 0}, {0, 1}};
03299 
03300 //______________________________________________________________________________
03301 void DrawAxes(Int_t fp, const Int_t *vp, const TGLVertex3 *box, const TGLPlotCoordinates *coord,
03302                TAxis *xAxis, TAxis *yAxis, TAxis *zAxis)
03303 {
03304    //Using front point, find, where to draw axes and which labels to use for them
03305    //gVirtualX->SelectWindow(gGLManager->GetVirtualXInd(fGLDevice));
03306    //gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
03307 
03308    const Int_t left  = gFramePoints[fp][0];
03309    const Int_t right = gFramePoints[fp][1];
03310    const Double_t xLeft = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw()
03311                                              + box[left].X() - vp[0]));
03312    const Double_t yLeft = gPad->AbsPixeltoY(Int_t(vp[3] - box[left].Y()
03313                                              + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
03314                                              * gPad->GetWh() + vp[1]));
03315    const Double_t xMid = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw()
03316                                              + box[fp].X()  - vp[0]));
03317    const Double_t yMid = gPad->AbsPixeltoY(Int_t(vp[3] - box[fp].Y()
03318                                              + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
03319                                              * gPad->GetWh() + vp[1]));
03320    const Double_t xRight = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC()
03321                                              * gPad->GetWw() + box[right].X() - vp[0]));
03322    const Double_t yRight = gPad->AbsPixeltoY(Int_t(vp[3] - box[right].Y()
03323                                              + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
03324                                              * gPad->GetWh() + vp[1]));
03325    const Double_t points[][2] = {{coord->GetXRange().first,  coord->GetYRange().first },
03326                                  {coord->GetXRange().second, coord->GetYRange().first },
03327                                  {coord->GetXRange().second, coord->GetYRange().second},
03328                                  {coord->GetXRange().first,  coord->GetYRange().second}};
03329    const Int_t    leftType      = gAxisType[fp][0];
03330    const Int_t    rightType     = gAxisType[fp][1];
03331    const Double_t leftLabel     = points[left][leftType];
03332    const Double_t leftMidLabel  = points[fp][leftType];
03333    const Double_t rightMidLabel = points[fp][rightType];
03334    const Double_t rightLabel    = points[right][rightType];
03335 
03336    if (xLeft - xMid || yLeft - yMid) {//To supress error messages from TGaxis
03337       TAxis *axis = leftType ? yAxis : xAxis;
03338       if (leftLabel < leftMidLabel)
03339          Draw2DAxis(axis, xLeft, yLeft, xMid, yMid, leftLabel, leftMidLabel,
03340                      leftType ? coord->GetYLog() : coord->GetXLog());
03341       else
03342          Draw2DAxis(axis, xMid, yMid, xLeft, yLeft, leftMidLabel, leftLabel,
03343                      leftType ? coord->GetYLog() : coord->GetXLog());
03344    }
03345 
03346    if (xRight - xMid || yRight - yMid) {//To supress error messages from TGaxis
03347       TAxis *axis = rightType ? yAxis : xAxis;
03348 
03349       if (rightMidLabel < rightLabel)
03350          Draw2DAxis(axis, xMid, yMid, xRight, yRight, rightMidLabel, rightLabel,
03351                      rightType ? coord->GetYLog() : coord->GetXLog());
03352       else
03353          Draw2DAxis(axis, xRight, yRight, xMid, yMid, rightLabel, rightMidLabel,
03354                      rightType ? coord->GetYLog() : coord->GetXLog());
03355    }
03356 
03357    const Double_t xUp = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw()
03358                                           + box[left + 4].X() - vp[0]));
03359    const Double_t yUp = gPad->AbsPixeltoY(Int_t(vp[3] - box[left + 4].Y()
03360                                           + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
03361                                           * gPad->GetWh() + vp[1]));
03362    Draw2DAxis(zAxis, xLeft, yLeft, xUp, yUp, coord->GetZRange().first,
03363                coord->GetZRange().second, coord->GetZLog(), kTRUE);
03364 }
03365 
03366 void SetZLevels(TAxis *zAxis, Double_t zMin, Double_t zMax,
03367                   Double_t zScale, std::vector<Double_t> &zLevels)
03368 {
03369    Int_t nDiv = zAxis->GetNdivisions() % 100;
03370    Int_t nBins = 0;
03371    Double_t binLow = 0., binHigh = 0., binWidth = 0.;
03372    THLimitsFinder::Optimize(zMin, zMax, nDiv, binLow, binHigh, nBins, binWidth, " ");
03373    zLevels.resize(nBins + 1);
03374 
03375    for (Int_t i = 0; i < nBins + 1; ++i)
03376       zLevels[i] = (binLow + i * binWidth) * zScale;
03377 }
03378 
03379 //______________________________________________________________________________
03380 void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3,
03381                         Double_t t1, Double_t t2, Double_t t3, const TGLVector3 &norm1,
03382                         const TGLVector3 &norm2, const TGLVector3 &norm3)
03383 {
03384    //Draw textured triangle
03385 
03386    glBegin(GL_POLYGON);
03387    glNormal3dv(norm1.CArr());
03388    glTexCoord1d(t1);
03389    glVertex3dv(v1.CArr());
03390    glNormal3dv(norm2.CArr());
03391    glTexCoord1d(t2);
03392    glVertex3dv(v2.CArr());
03393    glNormal3dv(norm3.CArr());
03394    glTexCoord1d(t3);
03395    glVertex3dv(v3.CArr());
03396    glEnd();
03397 }
03398 
03399 //______________________________________________________________________________
03400 void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3,
03401                         Double_t t1, Double_t t2, Double_t t3, Double_t z,
03402                         const TGLVector3 &normal)
03403 {
03404    //Draw textured triangle on a plane
03405    glBegin(GL_POLYGON);
03406    glNormal3dv(normal.CArr());
03407    glTexCoord1d(t1);
03408    glVertex3d(v1.X(), v1.Y(), z);
03409    glTexCoord1d(t2);
03410    glVertex3d(v2.X(), v2.Y(), z);
03411    glTexCoord1d(t3);
03412    glVertex3d(v3.X(), v3.Y(), z);
03413    glEnd();
03414 }
03415 
03416 //______________________________________________________________________________
03417 void GetColor(Float_t v, Float_t vmin, Float_t vmax, Int_t type, Float_t *rgba)
03418 {
03419    //This function creates color for parametric surface's vertex,
03420    //using its 'u' value.
03421    //I've found it in one of Apple's Carbon tutorials , and it's based
03422    //on Paul Bourke work. Very nice colors!!! :)
03423    Float_t dv,vmid;
03424    //Float_t c[] = {1.f, 1.f, 1.f};
03425    Float_t c1[3] = {}, c2[3] = {}, c3[3] = {};
03426    Float_t ratio ;
03427    rgba[3] = 1.f;
03428 
03429    if (v < vmin)
03430       v = vmin;
03431    if (v > vmax)
03432       v = vmax;
03433    dv = vmax - vmin;
03434 
03435    switch (type) {
03436    case 0:
03437       rgba[0] = 1.f;
03438       rgba[1] = 1.f;
03439       rgba[2] = 1.f;
03440    break;
03441    case 1:
03442    if (v < (vmin + 0.25 * dv)) {
03443       rgba[0] = 0;
03444       rgba[1] = 4 * (v - vmin) / dv;
03445       rgba[2] = 1;
03446    } else if (v < (vmin + 0.5 * dv)) {
03447       rgba[0] = 0;
03448       rgba[1] = 1;
03449       rgba[2] = 1 + 4 * (vmin + 0.25 * dv - v) / dv;
03450    } else if (v < (vmin + 0.75 * dv)) {
03451       rgba[0] = 4 * (v - vmin - 0.5 * dv) / dv;
03452       rgba[1] = 1;
03453       rgba[2] = 0;
03454    } else {
03455       rgba[0] = 1;
03456       rgba[1] = 1 + 4 * (vmin + 0.75 * dv - v) / dv;
03457       rgba[2] = 0;
03458    }
03459    break;
03460    case 2:
03461       rgba[0] = (v - vmin) / dv;
03462       rgba[1] = 0;
03463       rgba[2] = (vmax - v) / dv;
03464       break;
03465    case 3:
03466       rgba[0] = (v - vmin) / dv;
03467       rgba[1] = rgba[0];
03468       rgba[2] = rgba[0];
03469       break;
03470    case 4:
03471       if (v < (vmin + dv / 6.0)) {
03472          rgba[0] = 1;
03473          rgba[1] = 6 * (v - vmin) / dv;
03474          rgba[2] = 0;
03475       } else if (v < (vmin + 2.0 * dv / 6.0)) {
03476          rgba[0] = 1 + 6 * (vmin + dv / 6.0 - v) / dv;
03477          rgba[1] = 1;
03478          rgba[2] = 0;
03479       } else if (v < (vmin + 3.0 * dv / 6.0)) {
03480          rgba[0] = 0;
03481          rgba[1] = 1;
03482          rgba[2] = 6 * (v - vmin - 2.0 * dv / 6.0) / dv;
03483       } else if (v < (vmin + 4.0 * dv / 6.0)) {
03484          rgba[0] = 0;
03485          rgba[1] = 1 + 6 * (vmin + 3.0 * dv / 6.0 - v) / dv;
03486          rgba[2] = 1;
03487       } else if (v < (vmin + 5.0 * dv / 6.0)) {
03488          rgba[0] = 6 * (v - vmin - 4.0 * dv / 6.0) / dv;
03489          rgba[1] = 0;
03490          rgba[2] = 1;
03491       } else {
03492          rgba[0] = 1;
03493          rgba[1] = 0;
03494          rgba[2] = 1 + 6 * (vmin + 5.0 * dv / 6.0 - v) / dv;
03495       }
03496       break;
03497    case 5:
03498       rgba[0] = (v - vmin) / (vmax - vmin);
03499       rgba[1] = 1;
03500       rgba[2] = 0;
03501       break;
03502    case 6:
03503       rgba[0] = (v - vmin) / (vmax - vmin);
03504       rgba[1] = (vmax - v) / (vmax - vmin);
03505       rgba[2] = rgba[0];
03506       break;
03507    case 7:
03508       if (v < (vmin + 0.25 * dv)) {
03509          rgba[0] = 0;
03510          rgba[1] = 4 * (v - vmin) / dv;
03511          rgba[2] = 1 - rgba[1];
03512       } else if (v < (vmin + 0.5 * dv)) {
03513          rgba[0] = 4 * (v - vmin - 0.25 * dv) / dv;
03514          rgba[1] = 1 - rgba[0];
03515          rgba[2] = 0;
03516       } else if (v < (vmin + 0.75 * dv)) {
03517          rgba[1] = 4 * (v - vmin - 0.5 * dv) / dv;
03518          rgba[0] = 1 - rgba[1];
03519          rgba[2] = 0;
03520       } else {
03521          rgba[0] = 0;
03522          rgba[2] = 4 * (v - vmin - 0.75 * dv) / dv;
03523          rgba[1] = 1 - rgba[2];
03524       }
03525       break;
03526    case 8:
03527       if (v < (vmin + 0.5 * dv)) {
03528          rgba[0] = 2 * (v - vmin) / dv;
03529          rgba[1] = rgba[0];
03530          rgba[2] = rgba[0];
03531       } else {
03532          rgba[0] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
03533          rgba[1] = rgba[0];
03534          rgba[2] = rgba[0];
03535       }
03536       break;
03537    case 9:
03538       if (v < (vmin + dv / 3)) {
03539          rgba[2] = 3 * (v - vmin) / dv;
03540          rgba[1] = 0;
03541          rgba[0] = 1 - rgba[2];
03542       } else if (v < (vmin + 2 * dv / 3)) {
03543          rgba[0] = 0;
03544          rgba[1] = 3 * (v - vmin - dv / 3) / dv;
03545          rgba[2] = 1;
03546       } else {
03547          rgba[0] = 3 * (v - vmin - 2 * dv / 3) / dv;
03548          rgba[1] = 1 - rgba[0];
03549          rgba[2] = 1;
03550       }
03551       break;
03552    case 10:
03553       if (v < (vmin + 0.2 * dv)) {
03554          rgba[0] = 0;
03555          rgba[1] = 5 * (v - vmin) / dv;
03556          rgba[2] = 1;
03557       } else if (v < (vmin + 0.4 * dv)) {
03558          rgba[0] = 0;
03559          rgba[1] = 1;
03560          rgba[2] = 1 + 5 * (vmin + 0.2 * dv - v) / dv;
03561       } else if (v < (vmin + 0.6 * dv)) {
03562          rgba[0] = 5 * (v - vmin - 0.4 * dv) / dv;
03563          rgba[1] = 1;
03564          rgba[2] = 0;
03565       } else if (v < (vmin + 0.8 * dv)) {
03566          rgba[0] = 1;
03567          rgba[1] = 1 - 5 * (v - vmin - 0.6 * dv) / dv;
03568          rgba[2] = 0;
03569       } else {
03570          rgba[0] = 1;
03571          rgba[1] = 5 * (v - vmin - 0.8 * dv) / dv;
03572          rgba[2] = 5 * (v - vmin - 0.8 * dv) / dv;
03573       }
03574       break;
03575    case 11:
03576       c1[0] = 200 / 255.0; c1[1] =  60 / 255.0; c1[2] =   0 / 255.0;
03577       c2[0] = 250 / 255.0; c2[1] = 160 / 255.0; c2[2] = 110 / 255.0;
03578       rgba[0] = (c2[0] - c1[0]) * (v - vmin) / dv + c1[0];
03579       rgba[1] = (c2[1] - c1[1]) * (v - vmin) / dv + c1[1];
03580       rgba[2] = (c2[2] - c1[2]) * (v - vmin) / dv + c1[2];
03581       break;
03582    case 12:
03583       c1[0] =  55 / 255.0; c1[1] =  55 / 255.0; c1[2] =  45 / 255.0;
03584       c2[0] = 200 / 255.0; c2[1] =  60 / 255.0; c2[2] =   0 / 255.0;
03585       c3[0] = 250 / 255.0; c3[1] = 160 / 255.0; c3[2] = 110 / 255.0;
03586       ratio = 0.4;
03587       vmid = vmin + ratio * dv;
03588       if (v < vmid) {
03589          rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
03590          rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
03591          rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
03592       } else {
03593          rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
03594          rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
03595          rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
03596       }
03597       break;
03598    case 13:
03599       c1[0] =   0 / 255.0; c1[1] = 255 / 255.0; c1[2] =   0 / 255.0;
03600       c2[0] = 255 / 255.0; c2[1] = 150 / 255.0; c2[2] =   0 / 255.0;
03601       c3[0] = 255 / 255.0; c3[1] = 250 / 255.0; c3[2] = 240 / 255.0;
03602       ratio = 0.3;
03603       vmid = vmin + ratio * dv;
03604       if (v < vmid) {
03605          rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
03606          rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
03607          rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
03608       } else {
03609          rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
03610          rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
03611          rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
03612       }
03613       break;
03614    case 14:
03615       rgba[0] = 1;
03616       rgba[1] = 1 - (v - vmin) / dv;
03617       rgba[2] = 0;
03618       break;
03619    case 15:
03620       if (v < (vmin + 0.25 * dv)) {
03621          rgba[0] = 0;
03622          rgba[1] = 4 * (v - vmin) / dv;
03623          rgba[2] = 1;
03624       } else if (v < (vmin + 0.5 * dv)) {
03625          rgba[0] = 0;
03626          rgba[1] = 1;
03627          rgba[2] = 1 - 4 * (v - vmin - 0.25 * dv) / dv;
03628       } else if (v < (vmin + 0.75 * dv)) {
03629          rgba[0] = 4 * (v - vmin - 0.5 * dv) / dv;
03630          rgba[1] = 1;
03631          rgba[2] = 0;
03632       } else {
03633          rgba[0] = 1;
03634          rgba[1] = 1;
03635          rgba[2] = 4 * (v - vmin - 0.75 * dv) / dv;
03636       }
03637       break;
03638    case 16:
03639       if (v < (vmin + 0.5 * dv)) {
03640          rgba[0] = 0.0;
03641          rgba[1] = 2 * (v - vmin) / dv;
03642          rgba[2] = 1 - 2 * (v - vmin) / dv;
03643       } else {
03644          rgba[0] = 2 * (v - vmin - 0.5 * dv) / dv;
03645          rgba[1] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
03646          rgba[2] = 0.0;
03647       }
03648       break;
03649    case 17:
03650       if (v < (vmin + 0.5 * dv)) {
03651          rgba[0] = 1.0;
03652          rgba[1] = 1 - 2 * (v - vmin) / dv;
03653          rgba[2] = 2 * (v - vmin) / dv;
03654       } else {
03655          rgba[0] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
03656          rgba[1] = 2 * (v - vmin - 0.5 * dv) / dv;
03657          rgba[2] = 1.0;
03658       }
03659       break;
03660    case 18:
03661       rgba[0] = 0;
03662       rgba[1] = (v - vmin) / (vmax - vmin);
03663       rgba[2] = 1;
03664       break;
03665    case 19:
03666       rgba[0] = (v - vmin) / (vmax - vmin);
03667       rgba[1] = rgba[0];
03668       rgba[2] = 1;
03669       break;
03670    case 20:
03671       c1[0] =   0 / 255.0; c1[1] = 160 / 255.0; c1[2] =   0 / 255.0;
03672       c2[0] = 180 / 255.0; c2[1] = 220 / 255.0; c2[2] =   0 / 255.0;
03673       c3[0] = 250 / 255.0; c3[1] = 220 / 255.0; c3[2] = 170 / 255.0;
03674       ratio = 0.3;
03675       vmid = vmin + ratio * dv;
03676       if (v < vmid) {
03677          rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
03678          rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
03679          rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
03680       } else {
03681          rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
03682          rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
03683          rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
03684       }
03685       break;
03686    }
03687 }
03688 
03689 }
03690 
03691 //______________________________________________________________________________
03692 TGLLevelPalette::TGLLevelPalette()
03693                   : fContours(0),
03694                     fPaletteSize(0),
03695                     fTexture(0),
03696                     fMaxPaletteSize(0)
03697 {
03698    //Ctor.
03699 }
03700 
03701 //______________________________________________________________________________
03702 Bool_t TGLLevelPalette::GeneratePalette(UInt_t paletteSize, const Rgl::Range_t &zRange, Bool_t check)
03703 {
03704    //Try to find colors for palette.
03705    if (!fMaxPaletteSize && check)
03706       glGetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxPaletteSize);
03707 
03708    if (!(zRange.second - zRange.first))
03709       return kFALSE;
03710 
03711    if (check && paletteSize > UInt_t(fMaxPaletteSize)) {
03712       Error("TGLLevelPalette::GeneratePalette",
03713             "Number of contours %d is too big for GL 1D texture, try to reduce it to %d",
03714             paletteSize, fMaxPaletteSize);
03715       return kFALSE;
03716    }
03717 
03718    UInt_t nearestPow2 = 2;
03719    while (nearestPow2 < paletteSize)
03720       nearestPow2 <<= 1;
03721 
03722    fTexels.resize(4 * nearestPow2);
03723    fPaletteSize = paletteSize;
03724 
03725    //Generate texels.
03726    const Int_t nColors = gStyle->GetNumberOfColors();
03727 
03728    //Map color index into index in real palette.
03729 
03730    for (UInt_t i = 0; i < paletteSize; ++i) {
03731       Int_t paletteInd = Int_t(nColors / Double_t(paletteSize) * i);
03732       if (paletteInd > nColors - 1)
03733          paletteInd = nColors - 1;
03734       Int_t colorInd = gStyle->GetColorPalette(paletteInd);
03735 
03736       if (const TColor *c = gROOT->GetColor(colorInd)) {
03737          Float_t rgb[3] = {};
03738          c->GetRGB(rgb[0], rgb[1], rgb[2]);
03739          fTexels[i * 4]     = UChar_t(rgb[0] * 255);
03740          fTexels[i * 4 + 1] = UChar_t(rgb[1] * 255);
03741          fTexels[i * 4 + 2] = UChar_t(rgb[2] * 255);
03742          fTexels[i * 4 + 3] = 200;//alpha
03743       }
03744    }
03745 
03746    fZRange = zRange;
03747 
03748    return kTRUE;
03749 }
03750 
03751 //______________________________________________________________________________
03752 void TGLLevelPalette::SetContours(const std::vector<Double_t> *cont)
03753 {
03754    //Clear :)
03755    fContours = cont;
03756 }
03757 
03758 //______________________________________________________________________________
03759 void TGLLevelPalette::EnableTexture(Int_t mode)const
03760 {
03761    //Enable 1D texture
03762    glEnable(GL_TEXTURE_1D);
03763 
03764    glGenTextures(1, &fTexture);
03765    
03766    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
03767    glBindTexture(GL_TEXTURE_1D, fTexture);
03768    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
03769    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
03770    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
03771    glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, fTexels.size() / 4, 0,
03772                 GL_RGBA, GL_UNSIGNED_BYTE, &fTexels[0]);
03773    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GLint(mode));
03774 }
03775 
03776 //______________________________________________________________________________
03777 void TGLLevelPalette::DisableTexture()const
03778 {
03779    //Disable 1D texture
03780    glDeleteTextures(1, &fTexture);
03781    glDisable(GL_TEXTURE_1D);
03782 }
03783 
03784 //______________________________________________________________________________
03785 Int_t TGLLevelPalette::GetPaletteSize()const
03786 {
03787    //Get. Palette. Size.
03788    return Int_t(fPaletteSize);
03789 }
03790 
03791 //______________________________________________________________________________
03792 Double_t TGLLevelPalette::GetTexCoord(Double_t z)const
03793 {
03794    //Get tex coordinate
03795    if (!fContours)
03796       return (z - fZRange.first) / (fZRange.second - fZRange.first) * fPaletteSize / (fTexels.size() / 4);
03797 
03798    /*
03799    //This part is wrong. To be fixed.
03800    std::vector<Double_t>::size_type i = 0, e = fContours->size();
03801 
03802    if (!e)
03803       return 0.;
03804 
03805    for (; i < e - 1; ++i) {
03806       if (z >= (*fContours)[i] && z <= (*fContours)[i + 1])
03807          return i / Double_t(fTexels.size() / 4);
03808    }
03809    */
03810 
03811    return 1.;
03812 }
03813 
03814 //______________________________________________________________________________
03815 const UChar_t *TGLLevelPalette::GetColour(Double_t z)const
03816 {
03817    //Get color.
03818    const Int_t ind = Int_t((z - fZRange.first) / (fZRange.second - fZRange.first) * fPaletteSize);
03819    return &fTexels[ind * 4];
03820 }
03821 
03822 //______________________________________________________________________________
03823 const UChar_t *TGLLevelPalette::GetColour(Int_t ind)const
03824 {
03825    //Get color.
03826    return &fTexels[ind * 4];
03827 }

Generated on Tue Jul 5 14:18:09 2011 for ROOT_528-00b_version by  doxygen 1.5.1