00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
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 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 ClassImp(TGLVertex3);
00051 
00052 
00053 TGLVertex3::TGLVertex3()
00054 {
00055    
00056    Fill(0.0);
00057 }
00058 
00059 
00060 TGLVertex3::TGLVertex3(Double_t x, Double_t y, Double_t z)
00061 {
00062    
00063    Set(x,y,z);
00064 }
00065 
00066 
00067 TGLVertex3::TGLVertex3(Double_t* v)
00068 {
00069    
00070    Set(v[0], v[1], v[2]);
00071 }
00072 
00073 
00074 TGLVertex3::TGLVertex3(const TGLVertex3 & other)
00075 {
00076    
00077    Set(other);
00078 }
00079 
00080 
00081 TGLVertex3::~TGLVertex3()
00082 {
00083    
00084 }
00085 
00086 
00087 void TGLVertex3::Shift(TGLVector3 & shift)
00088 {
00089    
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    
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    
00124    std::cout << "(" << fVals[0] << "," << fVals[1] << "," << fVals[2] << ")" << std::endl;
00125 }
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 ClassImp(TGLVector3);
00141 
00142 
00143 TGLVector3::TGLVector3() :
00144    TGLVertex3()
00145 {
00146    
00147 }
00148 
00149 
00150 TGLVector3::TGLVector3(Double_t x, Double_t y, Double_t z) :
00151    TGLVertex3(x, y, z)
00152 {
00153    
00154 }
00155 
00156 
00157 TGLVector3::TGLVector3(const TGLVector3 & other) :
00158    TGLVertex3(other.fVals[0], other.fVals[1], other.fVals[2])
00159 {
00160    
00161 }
00162 
00163 
00164 TGLVector3::TGLVector3(const Double_t *src) :
00165    TGLVertex3(src[0], src[1], src[2])
00166 {
00167    
00168 }
00169 
00170 
00171 TGLVector3::~TGLVector3()
00172 {
00173    
00174 }
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 ClassImp(TGLLine3);
00186 
00187 
00188 TGLLine3::TGLLine3(const TGLVertex3 & start, const TGLVertex3 & end) :
00189    fVertex(start), fVector(end - start)
00190 {
00191    
00192 }
00193 
00194 
00195 TGLLine3::TGLLine3(const TGLVertex3 & start, const TGLVector3 & vect) :
00196    fVertex(start), fVector(vect)
00197 {
00198    
00199 }
00200 
00201 
00202 TGLLine3::~TGLLine3()
00203 {
00204    
00205 }
00206 
00207 
00208 void TGLLine3::Set(const TGLVertex3 & start, const TGLVertex3 & end)
00209 {
00210    
00211 
00212    fVertex = start;
00213    fVector = end - start;
00214 }
00215 
00216 
00217 void TGLLine3::Set(const TGLVertex3 & start, const TGLVector3 & vect)
00218 {
00219    
00220    fVertex = start;
00221    fVector = vect;
00222 }
00223 
00224 
00225 void TGLLine3::Draw() const
00226 {
00227    
00228    
00229    glBegin(GL_LINE_LOOP);
00230    glVertex3dv(fVertex.CArr());
00231    glVertex3dv(End().CArr());
00232    glEnd();
00233 }
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 ClassImp(TGLRect);
00243 
00244 
00245 TGLRect::TGLRect() :
00246       fX(0), fY(0), fWidth(0), fHeight(0)
00247 {
00248    
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    
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    
00263 }
00264 
00265 
00266 
00267 TGLRect::~TGLRect()
00268 {
00269    
00270 }
00271 
00272 
00273 void TGLRect::Expand(Int_t x, Int_t y)
00274 {
00275    
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    
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    
00310    
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 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 ClassImp(TGLPlane);
00340 
00341 
00342 TGLPlane::TGLPlane()
00343 {
00344    
00345    Set(1.0, 1.0, 1.0, 0.0);
00346 }
00347 
00348 
00349 TGLPlane::TGLPlane(const TGLPlane & other)
00350 {
00351    
00352    Set(other);
00353 }
00354 
00355 
00356 TGLPlane::TGLPlane(Double_t a, Double_t b, Double_t c, Double_t d)
00357 {
00358    
00359    
00360    Set(a, b, c, d);
00361 }
00362 
00363 
00364 TGLPlane::TGLPlane(Double_t eq[4])
00365 {
00366    
00367    
00368    Set(eq);
00369 }
00370 
00371 
00372 TGLPlane::TGLPlane(const TGLVertex3 & p1, const TGLVertex3 & p2,
00373                    const TGLVertex3 & p3)
00374 {
00375    
00376    
00377    Set(p1, p2, p3);
00378 }
00379 
00380 
00381 TGLPlane::TGLPlane(const TGLVector3 & v, const TGLVertex3 & p)
00382 {
00383    
00384    
00385    Set(v, p);
00386 }
00387 
00388 
00389 TGLPlane::~TGLPlane()
00390 {
00391    
00392 }
00393 
00394 
00395 void TGLPlane::Normalise()
00396 {
00397    
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    
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    
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    
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    
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    
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    
00472 
00473    TGLVector3 norm = Cross(p2 - p1, p3 - p1);
00474    Set(norm, p2);
00475 }
00476 
00477 
00478 void TGLPlane::Negate()
00479 {
00480    
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    
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    
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 
00507 
00508 
00509 std::pair<Bool_t, TGLLine3> Intersection(const TGLPlane & p1, const TGLPlane & p2)
00510 {
00511    
00512    
00513    
00514    
00515    
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    
00545    
00546    
00547    
00548    
00549    
00550    
00551    
00552    
00553    
00554    
00555    
00556    
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    
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 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 
00589 
00590 
00591 
00592 
00593 
00594 ClassImp(TGLMatrix);
00595 
00596 
00597 TGLMatrix::TGLMatrix()
00598 {
00599    
00600    
00601    
00602    
00603    
00604    
00605    SetIdentity();
00606 }
00607 
00608 
00609 TGLMatrix::TGLMatrix(Double_t x, Double_t y, Double_t z)
00610 {
00611    
00612    
00613    
00614    
00615    
00616    
00617    SetIdentity();
00618    SetTranslation(x, y, z);
00619 }
00620 
00621 
00622 TGLMatrix::TGLMatrix(const TGLVertex3 & translation)
00623 {
00624    
00625    
00626    
00627    
00628    
00629    
00630    SetIdentity();
00631    SetTranslation(translation);
00632 }
00633 
00634 
00635 TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis)
00636 {
00637    
00638    
00639    
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    
00661    
00662    
00663    SetIdentity();
00664    Set(origin, zAxis, xAxis);
00665 }
00666 
00667 
00668 TGLMatrix::TGLMatrix(const Double_t vals[16])
00669 {
00670    
00671    
00672    
00673    Set(vals);
00674 }
00675 
00676 
00677 TGLMatrix::TGLMatrix(const TGLMatrix & other)
00678 {
00679    
00680    *this = other;
00681 }
00682 
00683 
00684 TGLMatrix::~TGLMatrix()
00685 {
00686    
00687 }
00688 
00689 
00690 void TGLMatrix::MultRight(const TGLMatrix & rhs)
00691 {
00692    
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    
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    
00725    
00726    
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    
00744    
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    
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    
00766 
00767    SetTranslation(TGLVertex3(x,y,z));
00768 }
00769 
00770 
00771 void TGLMatrix::SetTranslation(const TGLVertex3 & translation)
00772 {
00773    
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    
00784 
00785    return TGLVector3(fVals[12], fVals[13], fVals[14]);
00786 }
00787 
00788 
00789 void TGLMatrix::Translate(const TGLVector3 & vect)
00790 {
00791    
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    
00802    
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    
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    
00822    
00823    
00824    TGLVector3 currentScale = GetScale();
00825 
00826    
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    
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    
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    
00856    
00857    
00858    
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    
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    
00876    
00877    *this = rotMat * localToWorld * (*this);
00878 }
00879 
00880 
00881 void TGLMatrix::RotateLF(Int_t i1, Int_t i2, Double_t amount)
00882 {
00883    
00884    
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; 
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    
00902 
00903    if(i1 == i2) return;
00904 
00905    
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    
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    
00932    
00933    
00934 
00935    
00936    
00937    
00938    
00939    
00940    
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    
00957    
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    
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    
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    
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    
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    
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    
01092    
01093    
01094    
01095    
01096    
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 
01111 
01112 
01113 
01114 
01115 
01116 
01117 
01118 
01119 
01120 
01121 ClassImp(TGLColor);
01122 
01123 
01124 TGLColor::TGLColor()
01125 {
01126    
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    
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    
01145 
01146    SetColor(r, g, b, a);
01147 }
01148 
01149 
01150 TGLColor::TGLColor(Color_t color_index, Char_t transparency)
01151 {
01152    
01153 
01154    SetColor(color_index, transparency);
01155 }
01156 
01157 
01158 TGLColor::~TGLColor()
01159 {
01160    
01161 }
01162 
01163 
01164 TGLColor& TGLColor::operator=(const TGLColor& c)
01165 {
01166    
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    
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    
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    
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    
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    
01222    
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       
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    
01246    
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       
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    
01275 
01276    fRGBA[3] = (255*(100 - transparency))/100;
01277 }
01278 
01279 
01280 TString TGLColor::AsString() const
01281 {
01282    
01283 
01284    return TString::Format("rgba:%02hhx/%02hhx/%02hhx/%02hhx",
01285                           fRGBA[0], fRGBA[1], fRGBA[2], fRGBA[3]);
01286 }
01287 
01288 
01289 
01290 
01291 
01292 
01293 
01294 
01295 
01296 
01297 
01298 ClassImp(TGLColorSet);
01299 
01300 
01301 TGLColorSet::TGLColorSet()
01302 {
01303    
01304 
01305    StdDarkBackground();
01306 }
01307 
01308 
01309 TGLColorSet::~TGLColorSet()
01310 {
01311    
01312 }
01313 
01314 
01315 TGLColorSet& TGLColorSet::operator=(const TGLColorSet& s)
01316 {
01317    
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    
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    
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 
01365 
01366 
01367 
01368 
01369 
01370 
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    
01442    
01443 
01444    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex3fv);
01445 
01446    return singleton.fTess;
01447 }
01448 
01449 
01450 GLUtesselator* TGLUtil::GetDrawTesselator4fv()
01451 {
01452    
01453    
01454 
01455    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex4fv);
01456 
01457    return singleton.fTess;
01458 }
01459 
01460 
01461 GLUtesselator* TGLUtil::GetDrawTesselator3dv()
01462 {
01463    
01464    
01465 
01466    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex3dv);
01467 
01468    return singleton.fTess;
01469 }
01470 
01471 
01472 GLUtesselator* TGLUtil::GetDrawTesselator4dv()
01473 {
01474    
01475    
01476 
01477    static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex4dv);
01478 
01479    return singleton.fTess;
01480 }
01481 
01482 
01483 UInt_t TGLUtil::GetDrawQuality()
01484 {
01485    
01486    return fgDrawQuality;
01487 }
01488 
01489 
01490 void TGLUtil::SetDrawQuality(UInt_t dq)
01491 {
01492    
01493    fgDrawQuality = dq;
01494 }
01495 
01496 
01497 void TGLUtil::ResetDrawQuality()
01498 {
01499    
01500    fgDrawQuality = fgDefaultDrawQuality;
01501 }
01502 
01503 
01504 UInt_t TGLUtil::GetDefaultDrawQuality()
01505 {
01506    
01507    return fgDefaultDrawQuality;
01508 }
01509 
01510 
01511 void TGLUtil::SetDefaultDrawQuality(UInt_t dq)
01512 {
01513    
01514    fgDefaultDrawQuality = dq;
01515 }
01516 
01517 
01518 void TGLUtil::CheckError(const char * loc)
01519 {
01520    
01521    
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 
01537 
01538 
01539 
01540 UInt_t TGLUtil::LockColor()
01541 {
01542    
01543 
01544    return ++fgColorLockCount;
01545 }
01546 
01547 
01548 UInt_t TGLUtil::UnlockColor()
01549 {
01550    
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    
01563 
01564    return fgColorLockCount > 0;
01565 }
01566 
01567 
01568 void TGLUtil::Color(const TGLColor& color)
01569 {
01570    
01571 
01572    if (fgColorLockCount == 0) glColor4ubv(color.CArr());
01573 }
01574 
01575 
01576 void TGLUtil::ColorAlpha(const TGLColor& color, UChar_t alpha)
01577 {
01578    
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    
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    
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    
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    
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    
01636    if (fgColorLockCount == 0) glColor4ub(r, g, b, a);
01637 }
01638 
01639 
01640 void TGLUtil::Color3ubv(const UChar_t* rgb)
01641 {
01642    
01643    if (fgColorLockCount == 0) glColor3ubv(rgb);
01644 }
01645 
01646 
01647 void TGLUtil::Color4ubv(const UChar_t* rgba)
01648 {
01649    
01650    if (fgColorLockCount == 0) glColor4ubv(rgba);
01651 }
01652 
01653 
01654 void TGLUtil::Color3f(Float_t r, Float_t g, Float_t b)
01655 {
01656    
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    
01664    if (fgColorLockCount == 0) glColor4f(r, g, b, a);
01665 }
01666 
01667 
01668 void TGLUtil::Color3fv(const Float_t* rgb)
01669 {
01670    
01671    if (fgColorLockCount == 0) glColor3fv(rgb);
01672 }
01673 
01674 
01675 void TGLUtil::Color4fv(const Float_t* rgba)
01676 {
01677    
01678    if (fgColorLockCount == 0) glColor4fv(rgba);
01679 }
01680 
01681 
01682 
01683 
01684 
01685 
01686 Float_t TGLUtil::GetPointSizeScale()
01687 {
01688    
01689 
01690    return fgPointSizeScale;
01691 }
01692 
01693 
01694 void TGLUtil::SetPointSizeScale(Float_t scale)
01695 {
01696    
01697 
01698    fgPointSizeScale = scale;
01699 }
01700 
01701 
01702 Float_t TGLUtil::GetLineWidthScale()
01703 {
01704    
01705 
01706    return fgLineWidthScale;
01707 }
01708 
01709 
01710 void TGLUtil::SetLineWidthScale(Float_t scale)
01711 {
01712    
01713 
01714    fgLineWidthScale = scale;
01715 }
01716 
01717 
01718 void TGLUtil::PointSize(Float_t point_size)
01719 {
01720    
01721    
01722 
01723    fgPointSize = point_size * fgPointSizeScale;
01724    glPointSize(fgPointSize);
01725 }
01726 
01727 
01728 void TGLUtil::LineWidth(Float_t line_width)
01729 {
01730    
01731    
01732 
01733    fgLineWidth = line_width * fgLineWidthScale;
01734    glLineWidth(fgLineWidth);
01735 }
01736 
01737 
01738 Float_t TGLUtil::PointSize()
01739 {
01740    
01741 
01742    return fgPointSize;
01743 }
01744 
01745 
01746 Float_t TGLUtil::LineWidth()
01747 {
01748    
01749 
01750    return fgLineWidth;
01751 }
01752 
01753 
01754 
01755 
01756 
01757 void TGLUtil::BeginExtendPickRegion(Float_t scale)
01758 {
01759    
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    
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    
01788    
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    
01813    
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    
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       { 
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    
01883    
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    
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    
01927    
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       { 
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    
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    
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    
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    
02011 
02012    if (selection && TGLUtil::LineWidth() > pick_radius)
02013      EndExtendPickRegion();
02014 
02015    glPopAttrib(); 
02016 }
02017 
02018 
02019 
02020 
02021 
02022 
02023 void TGLUtil::SetDrawColors(const UChar_t rgbai[4])
02024 {
02025    
02026    
02027    
02028    
02029    
02030    
02031    
02032    
02033    
02034    
02035    
02036    
02037    
02038    
02039 
02040 
02041    
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    
02060    
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    
02074    
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    
02083    
02084    
02085    static TGLQuadric quad;
02086 
02087    
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    
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); 
02108 
02109    if (head == kLineHeadNone) {
02110       
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       
02116       gluDisk(quad.Get(), 0.0, size, fgDrawQuality, 1);
02117       
02118       gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
02119       gluCylinder(quad.Get(), size, 0.0, headHeight, fgDrawQuality, 1);
02120    } else if (head == kLineHeadBox) {
02121       
02122       
02123       
02124       
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    
02138    
02139    static TGLQuadric quad;
02140 
02141    
02142    
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    
02150    glPushMatrix();
02151    TGLMatrix local(center, normal);
02152    glMultMatrixd(local.CArr());
02153 
02154    
02155    glTranslated(0.0, 0.0, -width/2.0);
02156 
02157    
02158    gluCylinder(quad.Get(), inner, inner, width, fgDrawQuality, 1);
02159    gluCylinder(quad.Get(), outer, outer, width, fgDrawQuality, 1);
02160 
02161    
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    
02180    
02181 
02182    static const UChar_t defColor[4] = { 250, 110, 0, 255 }; 
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    
02195 
02196    if (axesType == kAxesNone)
02197       return;
02198 
02199    static const UChar_t axesColors[][4] = {
02200       {128,   0,   0, 255},  
02201       {255,   0,   0, 255},  
02202       {  0, 128,   0, 255},  
02203       {  0, 255,   0, 255},  
02204       {  0,   0, 128, 255},  
02205       {  0,   0, 255, 255}   
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    
02215    TGLVector3 pixelVector = camera.ViewportDeltaToWorld(bbox.Center(), 1, 1);
02216    Double_t   pixelSize   = pixelVector.Mag();
02217 
02218    
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          
02228          start[(i+1)%3] = 0.0;
02229          start[(i+2)%3] = 0.0;
02230       } else {
02231          
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       
02239       if (min[i] < 0.0) {
02240          
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       
02251       if (max[i] > 0.0) {
02252          
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    
02265    if (axesType == kAxesOrigin) {
02266       
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    
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       
02304       
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); 
02316       DrawNumber(Form("%.0f", max[k]), maxPos, kTRUE); 
02317 
02318       
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]); 
02324    }
02325 }
02326 
02327 
02328 void TGLUtil::DrawNumber(const TString    & num,
02329                          const TGLVertex3 & pos,
02330                                Bool_t       center)
02331 {
02332    
02333    
02334    
02335 
02336    static const UChar_t digits[][8] = {
02337       {0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38},
02338       {0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x10, 0x10},
02339       {0x7c, 0x44, 0x20, 0x18, 0x04, 0x04, 0x44, 0x38},
02340       {0x38, 0x44, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38},
02341       {0x04, 0x04, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x44},
02342       {0x7c, 0x44, 0x04, 0x04, 0x7c, 0x40, 0x40, 0x7c},
02343       {0x7c, 0x44, 0x44, 0x44, 0x7c, 0x40, 0x40, 0x7c},
02344       {0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x44, 0x7c},
02345       {0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38},
02346       {0x7c, 0x44, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x7c},
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} 
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    
02382 
02383    fState = glIsEnabled(fWhat);
02384    fFlip  = (fState != state);
02385    if (fFlip)
02386       SetState(state);
02387 }
02388 
02389 
02390 TGLCapabilitySwitch::~TGLCapabilitySwitch()
02391 {
02392    
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    
02413 
02414    fFlip = ! glIsEnabled(fWhat) && state;
02415    if (fFlip)
02416       glEnable(fWhat);
02417 }
02418 
02419 
02420 TGLCapabilityEnabler::~TGLCapabilityEnabler()
02421 {
02422    
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    
02450    glEnable(GLenum(fCap));
02451 }
02452 
02453 
02454 TGLEnableGuard::~TGLEnableGuard()
02455 {
02456    
02457    glDisable(GLenum(fCap));
02458 }
02459 
02460 
02461 TGLDisableGuard::TGLDisableGuard(Int_t cap)
02462                   : fCap(cap)
02463 {
02464    
02465    glDisable(GLenum(fCap));
02466 }
02467 
02468 
02469 TGLDisableGuard::~TGLDisableGuard()
02470 {
02471    
02472    glEnable(GLenum(fCap));
02473 }
02474 
02475 ClassImp(TGLSelectionBuffer);
02476 
02477 
02478 TGLSelectionBuffer::TGLSelectionBuffer()
02479                         : fWidth(0), fHeight(0)
02480 {
02481    
02482 }
02483 
02484 
02485 TGLSelectionBuffer::~TGLSelectionBuffer()
02486 {
02487    
02488 }
02489 
02490 
02491 void TGLSelectionBuffer::ReadColorBuffer(Int_t w, Int_t h)
02492 {
02493    
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    
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    
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    
02580    if (!highColor)
02581       glColor3ub(objectID & 0xff, (objectID & 0xff00) >> 8, (objectID & 0xff0000) >> 16);
02582    else {
02583       if (!gObjectIDToColor.size()) {
02584       
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    
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    
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    
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    
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    
02687    if (zMax < zMin)
02688       std::swap(zMax, zMin);
02689 
02690    
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    
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    
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    
02737    
02738    if (zMax < zMin) {
02739       std::swap(zMax, zMin);
02740       std::swap(texMax, texMin);
02741    }
02742 
02743    
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    
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    
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    
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    
02903    
02904    if (zMin > zMax)
02905       std::swap(zMin, zMax);
02906    
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    
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    
02971    
02972    if (zMin > zMax) {
02973       std::swap(zMin, zMax);
02974       std::swap(texMin, texMax);
02975    }
02976 
02977    
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    
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    
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    
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    
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    
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    
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       
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 
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    
03305    
03306    
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) {
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) {
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    
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    
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    
03420    
03421    
03422    
03423    Float_t dv,vmid;
03424    
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    
03699 }
03700 
03701 
03702 Bool_t TGLLevelPalette::GeneratePalette(UInt_t paletteSize, const Rgl::Range_t &zRange, Bool_t check)
03703 {
03704    
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    
03726    const Int_t nColors = gStyle->GetNumberOfColors();
03727 
03728    
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;
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    
03755    fContours = cont;
03756 }
03757 
03758 
03759 void TGLLevelPalette::EnableTexture(Int_t mode)const
03760 {
03761    
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    
03780    glDeleteTextures(1, &fTexture);
03781    glDisable(GL_TEXTURE_1D);
03782 }
03783 
03784 
03785 Int_t TGLLevelPalette::GetPaletteSize()const
03786 {
03787    
03788    return Int_t(fPaletteSize);
03789 }
03790 
03791 
03792 Double_t TGLLevelPalette::GetTexCoord(Double_t z)const
03793 {
03794    
03795    if (!fContours)
03796       return (z - fZRange.first) / (fZRange.second - fZRange.first) * fPaletteSize / (fTexels.size() / 4);
03797 
03798    
03799 
03800 
03801 
03802 
03803 
03804 
03805 
03806 
03807 
03808 
03809 
03810 
03811    return 1.;
03812 }
03813 
03814 
03815 const UChar_t *TGLLevelPalette::GetColour(Double_t z)const
03816 {
03817    
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    
03826    return &fTexels[ind * 4];
03827 }