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 }