00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "Riostream.h"
00013 #include <stdexcept>
00014
00015 #include "TVirtualPad.h"
00016 #include "TVirtualX.h"
00017 #include "RStipples.h"
00018 #include "TColor.h"
00019 #include "TROOT.h"
00020 #include "TMath.h"
00021
00022 #include "TGLPadUtils.h"
00023 #include "TGLIncludes.h"
00024
00025 namespace Rgl {
00026 namespace Pad {
00027
00028 const UInt_t PolygonStippleSet::fgBitSwap[] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
00029
00030
00031
00032
00033
00034 #ifndef GL_VERSION_1_2
00035 const GLenum lineWidthPNAME = GLenum(0xB22);
00036 const GLenum pointSizePNAME = GLenum(0xB12);
00037 #else
00038 const GLenum lineWidthPNAME = GLenum(GL_SMOOTH_LINE_WIDTH_RANGE);
00039 const GLenum pointSizePNAME = GLenum(GL_SMOOTH_POINT_SIZE_RANGE);
00040 #endif
00041
00042
00043
00044
00045
00046
00047 PolygonStippleSet::PolygonStippleSet()
00048 {
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 const UInt_t numOfStipples = sizeof gStipples / sizeof gStipples[0];
00081 fStipples.resize(kStippleSize * numOfStipples);
00082
00083 for (UInt_t i = 0; i < numOfStipples; ++i) {
00084 const UInt_t baseInd = i * kStippleSize;
00085
00086 for (Int_t j = 15, j1 = 0; j >= 0; --j, ++j1) {
00087 const UInt_t rowShift = j1 * kRowSize;
00088
00089 for (Int_t k = 1, k1 = 0; k >= 0; --k, ++k1) {
00090 const UChar_t pixel = SwapBits(gStipples[i][j * 2 + k]);
00091 const UInt_t ind = baseInd + rowShift + k1;
00092
00093 fStipples[ind] = pixel;
00094 fStipples[ind + 2] = pixel;
00095 fStipples[ind + 64] = pixel;
00096 fStipples[ind + 66] = pixel;
00097 }
00098 }
00099 }
00100 }
00101
00102
00103 UInt_t PolygonStippleSet::SwapBits(UInt_t b)
00104 {
00105 b &= k16Bits;
00106
00107 const UInt_t low = fgBitSwap[b & kLow4] << 4;
00108 const UInt_t up = fgBitSwap[(b & kUp4) >> 4];
00109
00110 return low | up;
00111 }
00112
00113
00114
00115
00116
00117 FillAttribSet::FillAttribSet(const PolygonStippleSet &set, Bool_t ignoreStipple)
00118 : fStipple(0)
00119 {
00120
00121 const UInt_t style = gVirtualX->GetFillStyle() / 1000;
00122
00123 if (!ignoreStipple) {
00124 if (style == 3) {
00125 const UInt_t fasi = gVirtualX->GetFillStyle() % 1000;
00126 fStipple = (fasi >= 1 && fasi <=25) ? fasi : 2;
00127 glPolygonStipple(&set.fStipples[fStipple * PolygonStippleSet::kStippleSize]);
00128 glEnable(GL_POLYGON_STIPPLE);
00129 }
00130 }
00131
00132
00133 Float_t rgba[] = {0.f, 0.f, 0.f, 1.f};
00134 ExtractRGB(gVirtualX->GetFillColor(), rgba);
00135 glColor4fv(rgba);
00136 }
00137
00138
00139 FillAttribSet::~FillAttribSet()
00140 {
00141 if (fStipple)
00142 glDisable(GL_POLYGON_STIPPLE);
00143 }
00144
00145
00146
00147
00148
00149 const UShort_t gLineStipples[] = {0xffff, 0xffff, 0x3333, 0x5555,
00150 0xf040, 0xf4f4, 0xf111, 0xf0f0,
00151 0xff11, 0x3fff, 0x08ff};
00152
00153 const UInt_t gMaxStipple = sizeof gLineStipples / sizeof gLineStipples[0];
00154
00155
00156
00157
00158
00159 LineAttribSet::LineAttribSet(Bool_t smooth, UInt_t stipple, Double_t maxWidth, Bool_t setWidth)
00160 : fSmooth(smooth), fStipple(stipple), fSetWidth(setWidth)
00161 {
00162
00163
00164 if (fSmooth) {
00165 glEnable(GL_BLEND);
00166 glEnable(GL_LINE_SMOOTH);
00167 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00168 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00169 }
00170
00171
00172 if (fStipple > 1) {
00173 if (fStipple >= gMaxStipple)
00174 fStipple = 1;
00175 else {
00176 glEnable(GL_LINE_STIPPLE);
00177 glLineStipple(fStipple == 10 ? 2 : 1, gLineStipples[fStipple]);
00178 }
00179 }
00180
00181
00182 Float_t rgba[] = {0.f, 0.f, 0.f, 0.8f};
00183 ExtractRGB(gVirtualX->GetLineColor(), rgba);
00184 glColor4fv(rgba);
00185
00186 if (fSetWidth) {
00187 const Width_t w = gVirtualX->GetLineWidth();
00188 glLineWidth(w > maxWidth ? maxWidth : !w ? 1.f : w);
00189 }
00190 }
00191
00192
00193 LineAttribSet::~LineAttribSet()
00194 {
00195 if (fSmooth) {
00196 glDisable(GL_LINE_SMOOTH);
00197 glDisable(GL_BLEND);
00198 }
00199
00200 if (fStipple > 1)
00201 glDisable(GL_LINE_STIPPLE);
00202
00203 if (fSetWidth)
00204 glLineWidth(1.f);
00205 }
00206
00207
00208
00209
00210
00211 void MarkerPainter::DrawDot(UInt_t n, const TPoint *xy)const
00212 {
00213
00214 glBegin(GL_POINTS);
00215
00216 for (UInt_t i = 0; i < n; ++i)
00217 glVertex2d(xy[i].fX, xy[i].fY);
00218
00219 glEnd();
00220 }
00221
00222
00223 void MarkerPainter::DrawPlus(UInt_t n, const TPoint *xy)const
00224 {
00225
00226 const Double_t im = 4 * gVirtualX->GetMarkerSize() + 0.5;
00227 glBegin(GL_LINES);
00228
00229 for (UInt_t i = 0; i < n; ++i) {
00230 const Double_t x = xy[i].fX;
00231 const Double_t y = xy[i].fY;
00232 glVertex2d(-im + x, y);
00233 glVertex2d(im + x, y);
00234 glVertex2d(x, -im + y);
00235 glVertex2d(x, im + y);
00236 }
00237
00238 glEnd();
00239 }
00240
00241
00242 void MarkerPainter::DrawStar(UInt_t n, const TPoint *xy)const
00243 {
00244
00245 SCoord_t im = SCoord_t(4 * gVirtualX->GetMarkerSize() + 0.5);
00246 fStar[0].fX = -im; fStar[0].fY = 0;
00247 fStar[1].fX = im; fStar[1].fY = 0;
00248 fStar[2].fX = 0 ; fStar[2].fY = -im;
00249 fStar[3].fX = 0 ; fStar[3].fY = im;
00250 im = SCoord_t(0.707*Float_t(im) + 0.5);
00251 fStar[4].fX = -im; fStar[4].fY = -im;
00252 fStar[5].fX = im; fStar[5].fY = im;
00253 fStar[6].fX = -im; fStar[6].fY = im;
00254 fStar[7].fX = im; fStar[7].fY = -im;
00255
00256 glBegin(GL_LINES);
00257
00258 for (UInt_t i = 0; i < n; ++i) {
00259 const Double_t x = xy[i].fX;
00260 const Double_t y = xy[i].fY;
00261
00262 glVertex2d(fStar[0].fX + x, fStar[0].fY + y);
00263 glVertex2d(fStar[1].fX + x, fStar[1].fY + y);
00264 glVertex2d(fStar[2].fX + x, fStar[2].fY + y);
00265 glVertex2d(fStar[3].fX + x, fStar[3].fY + y);
00266 glVertex2d(fStar[4].fX + x, fStar[4].fY + y);
00267 glVertex2d(fStar[5].fX + x, fStar[5].fY + y);
00268 glVertex2d(fStar[6].fX + x, fStar[6].fY + y);
00269 glVertex2d(fStar[7].fX + x, fStar[7].fY + y);
00270 }
00271
00272 glEnd();
00273 }
00274
00275
00276 void MarkerPainter::DrawX(UInt_t n, const TPoint *xy)const
00277 {
00278 const Double_t im = 0.707 * (4 * gVirtualX->GetMarkerSize() + 0.5) + 0.5;
00279
00280 glBegin(GL_LINES);
00281
00282 for (UInt_t i = 0; i < n; ++i) {
00283 const Double_t x = xy[i].fX;
00284 const Double_t y = xy[i].fY;
00285
00286 glVertex2d(-im + x, -im + y);
00287 glVertex2d(im + x, im + y);
00288 glVertex2d(-im + x, im + y);
00289 glVertex2d(im + x, -im + y);
00290 }
00291
00292 glEnd();
00293 }
00294
00295
00296 void MarkerPainter::DrawFullDotSmall(UInt_t n, const TPoint *xy)const
00297 {
00298 glBegin(GL_LINES);
00299
00300 for (UInt_t i = 0; i < n; ++i) {
00301 const Double_t x = xy[i].fX;
00302 const Double_t y = xy[i].fY;
00303
00304 glVertex2d(-1. + x, y);
00305 glVertex2d(x + 1., y);
00306 glVertex2d(x, -1. + y);
00307 glVertex2d(x, 1. + y);
00308 }
00309
00310 glEnd();
00311 }
00312
00313
00314 void MarkerPainter::DrawFullDotMedium(UInt_t n, const TPoint *xy)const
00315 {
00316 for (UInt_t i = 0; i < n; ++i)
00317 glRectd(xy[i].fX - 1, xy[i].fY - 1, xy[i].fX + 1, xy[i].fY + 1);
00318 }
00319
00320 namespace {
00321
00322 void CalculateCircle(std::vector<TPoint> &circle, Double_t r, UInt_t pts);
00323 }
00324
00325
00326 void MarkerPainter::DrawCircle(UInt_t n, const TPoint *xy)const
00327 {
00328 Double_t r = 4 * gVirtualX->GetMarkerSize() + 0.5;
00329 if (r > 100.)
00330 r = 100.;
00331
00332 fCircle.clear();
00333 CalculateCircle(fCircle, r, r < 100. ? kSmallCirclePts : kLargeCirclePts);
00334
00335 for (UInt_t i = 0; i < n; ++i) {
00336 const Double_t x = xy[i].fX;
00337 const Double_t y = xy[i].fY;
00338
00339 glBegin(GL_LINE_LOOP);
00340 for (UInt_t j = 0, e = fCircle.size(); j < e; ++j)
00341 glVertex2d(fCircle[j].fX + x, fCircle[j].fY + y);
00342 glEnd();
00343 }
00344 }
00345
00346
00347 void MarkerPainter::DrawFullDotLarge(UInt_t n, const TPoint *xy)const
00348 {
00349 fCircle.clear();
00350 fCircle.push_back(TPoint(0, 0));
00351
00352 Double_t r = 4 * gVirtualX->GetMarkerSize() + 0.5;
00353 if (r > 100.)
00354 r = 100;
00355
00356 CalculateCircle(fCircle, r, r < 100 ? kSmallCirclePts : kLargeCirclePts);
00357
00358 for (UInt_t i = 0; i < n; ++i) {
00359 const Double_t x = xy[i].fX;
00360 const Double_t y = xy[i].fY;
00361
00362 glBegin(GL_TRIANGLE_FAN);
00363 for (UInt_t j = 0, e = fCircle.size(); j < e; ++j)
00364 glVertex2d(fCircle[j].fX + x, fCircle[j].fY + y);
00365 glEnd();
00366 }
00367 }
00368
00369
00370 void MarkerPainter::DrawFullSquare(UInt_t n, const TPoint *xy)const
00371 {
00372 const Double_t im = 4 * gVirtualX->GetMarkerSize() + 0.5;
00373 for (UInt_t i = 0; i < n; ++i)
00374 glRectd(xy[i].fX - im, xy[i].fY - im, xy[i].fX + im, xy[i].fY + im);
00375 }
00376
00377
00378 void MarkerPainter::DrawFullTrianlgeUp(UInt_t n, const TPoint *xy)const
00379 {
00380 const Double_t im = 4 * gVirtualX->GetMarkerSize() + 0.5;
00381 for (UInt_t i = 0; i < n; ++i) {
00382 const Double_t x = xy[i].fX;
00383 const Double_t y = xy[i].fY;
00384 glBegin(GL_POLYGON);
00385 glVertex2d(x - im, y - im);
00386 glVertex2d(x + im, y - im);
00387 glVertex2d(x, im + y);
00388 glEnd();
00389 }
00390 }
00391
00392
00393 void MarkerPainter::DrawFullTrianlgeDown(UInt_t n, const TPoint *xy)const
00394 {
00395 const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5);
00396
00397 for (UInt_t i = 0; i < n; ++i) {
00398 const Double_t x = xy[i].fX;
00399 const Double_t y = xy[i].fY;
00400 glBegin(GL_POLYGON);
00401 glVertex2d(x - im, y + im);
00402 glVertex2d(x, y - im);
00403 glVertex2d(im + x, y + im);
00404 glEnd();
00405 }
00406 }
00407
00408
00409 void MarkerPainter::DrawDiamond(UInt_t n, const TPoint *xy)const
00410 {
00411 const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5);
00412 const Int_t imx = Int_t(2.66 * gVirtualX->GetMarkerSize() + 0.5);
00413
00414 for (UInt_t i = 0; i < n; ++i) {
00415 const Double_t x = xy[i].fX;
00416 const Double_t y = xy[i].fY;
00417
00418 glBegin(GL_LINE_LOOP);
00419 glVertex2d(x - imx, y);
00420 glVertex2d(x, y - im);
00421 glVertex2d(x + imx, y);
00422 glVertex2d(x, y + im);
00423 glEnd();
00424 }
00425 }
00426
00427
00428 void MarkerPainter::DrawCross(UInt_t n, const TPoint *xy)const
00429 {
00430 const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5);
00431 const Int_t imx = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5);
00432
00433 for (UInt_t i = 0; i < n; ++i) {
00434 const Double_t x = xy[i].fX;
00435 const Double_t y = xy[i].fY;
00436
00437 glBegin(GL_LINE_LOOP);
00438 glVertex2d(x - im, y - imx);
00439 glVertex2d(x - imx, y - imx);
00440 glVertex2d(x - imx, y - im);
00441 glVertex2d(x + imx, y - im);
00442 glVertex2d(x + imx, y - imx);
00443 glVertex2d(x + im, y - imx);
00444 glVertex2d(x + im, y + imx);
00445 glVertex2d(x + imx, y + imx);
00446 glVertex2d(x + imx, y + im);
00447 glVertex2d(x - imx, y + im);
00448 glVertex2d(x - imx, y + imx);
00449 glVertex2d(x - im, y + imx);
00450 glEnd();
00451 }
00452 }
00453
00454
00455 void MarkerPainter::DrawFullStar(UInt_t n, const TPoint *xy)const
00456 {
00457
00458 const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5);
00459 const Int_t im1 = Int_t(0.66 * gVirtualX->GetMarkerSize() + 0.5);
00460 const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5);
00461 const Int_t im3 = Int_t(2.66 * gVirtualX->GetMarkerSize() + 0.5);
00462 const Int_t im4 = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5);
00463
00464 for (UInt_t i = 0; i < n; ++i) {
00465 const Double_t x = xy[i].fX;
00466 const Double_t y = xy[i].fY;
00467
00468 glBegin(GL_TRIANGLES);
00469 glVertex2d(x - im, y - im4);
00470 glVertex2d(x - im2, y + im1);
00471 glVertex2d(x - im4, y - im4);
00472
00473 glVertex2d(x - im2, y + im1);
00474 glVertex2d(x - im3, y + im);
00475 glVertex2d(x, y + im2);
00476
00477 glVertex2d(x, y + im2);
00478 glVertex2d(x + im3, y + im);
00479 glVertex2d(x + im2, y + im1);
00480
00481 glVertex2d(x + im2, y + im1);
00482 glVertex2d(x + im, y - im4);
00483 glVertex2d(x + im4, y - im4);
00484
00485 glVertex2d(x + im4, y - im4);
00486 glVertex2d(x, y - im);
00487 glVertex2d(x - im4, y - im4);
00488
00489 glVertex2d(x - im4, y - im4);
00490 glVertex2d(x - im2, y + im1);
00491 glVertex2d(x, y + im2);
00492
00493 glVertex2d(x - im4, y - im4);
00494 glVertex2d(x, y + im2);
00495 glVertex2d(x + im2, y + im1);
00496
00497 glVertex2d(x - im4, y - im4);
00498 glVertex2d(x + im2, y + im1);
00499 glVertex2d(x + im4, y - im4);
00500
00501 glEnd();
00502
00503 }
00504 }
00505
00506
00507 void MarkerPainter::DrawOpenStar(UInt_t n, const TPoint *xy)const
00508 {
00509
00510 const Int_t im = Int_t(4 * gVirtualX->GetMarkerSize() + 0.5);
00511 const Int_t im1 = Int_t(0.66 * gVirtualX->GetMarkerSize() + 0.5);
00512 const Int_t im2 = Int_t(2.00 * gVirtualX->GetMarkerSize() + 0.5);
00513 const Int_t im3 = Int_t(2.66 * gVirtualX->GetMarkerSize() + 0.5);
00514 const Int_t im4 = Int_t(1.33 * gVirtualX->GetMarkerSize() + 0.5);
00515
00516 for (UInt_t i = 0; i < n; ++i) {
00517 const Double_t x = xy[i].fX;
00518 const Double_t y = xy[i].fY;
00519
00520 glBegin(GL_LINE_LOOP);
00521 glVertex2d(x - im, y - im4);
00522 glVertex2d(x - im2, y + im1);
00523 glVertex2d(x - im3, y + im);
00524 glVertex2d(x, y + im2);
00525 glVertex2d(x + im3, y + im);
00526 glVertex2d(x + im2, y + im1);
00527 glVertex2d(x + im, y - im4);
00528 glVertex2d(x + im4, y - im4);
00529 glVertex2d(x, y - im);
00530 glVertex2d(x - im4, y - im4);
00531 glEnd();
00532 }
00533 }
00534
00535
00536
00537
00538 #ifndef CALLBACK
00539 #define CALLBACK
00540 #endif
00541
00542 extern "C" {
00543 #if defined(__APPLE_CC__) && __APPLE_CC__ > 4000 && __APPLE_CC__ < 5450 && !defined(__INTEL_COMPILER)
00544 typedef GLvoid (*tess_t)(...);
00545 #elif defined( __mips ) || defined( __linux__ ) || defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __sun ) || defined (__CYGWIN__) || defined (__APPLE__)
00546 typedef GLvoid (*tess_t)();
00547 #elif defined ( WIN32)
00548 typedef GLvoid (CALLBACK *tess_t)( );
00549 #else
00550 #error "Error - need to define type tess_t for this platform/compiler"
00551 #endif
00552 }
00553
00554
00555 void Begin(Int_t type)
00556 {
00557 Tesselation_t *dump = Tesselator::GetDump();
00558 if (!dump)
00559 return;
00560
00561 dump->push_back(MeshPatch_t(type));
00562 }
00563
00564
00565 void Vertex(const Double_t *v)
00566 {
00567 Tesselation_t *dump = Tesselator::GetDump();
00568 if (!dump)
00569 return;
00570
00571 std::vector<Double_t> & vs = dump->back().fPatch;
00572 vs.push_back(v[0]);
00573 vs.push_back(v[1]);
00574 vs.push_back(v[2]);
00575 }
00576
00577
00578 void End()
00579 {
00580 }
00581
00582 Tesselation_t *Tesselator::fVs = 0;
00583
00584
00585 Tesselator::Tesselator(Bool_t dump)
00586 : fTess(0)
00587 {
00588 GLUtesselator *tess = gluNewTess();
00589 if (!tess)
00590 throw std::runtime_error("tesselator creation failed");
00591
00592 if (!dump) {
00593 gluTessCallback(tess, (GLenum)GLU_BEGIN, (tess_t) glBegin);
00594 gluTessCallback(tess, (GLenum)GLU_END, (tess_t) glEnd);
00595 gluTessCallback(tess, (GLenum)GLU_VERTEX, (tess_t) glVertex3dv);
00596 } else {
00597 gluTessCallback(tess, (GLenum)GLU_BEGIN, (tess_t) Begin);
00598 gluTessCallback(tess, (GLenum)GLU_END, (tess_t) End);
00599 gluTessCallback(tess, (GLenum)GLU_VERTEX, (tess_t) Vertex);
00600 }
00601
00602 gluTessProperty(tess, GLU_TESS_TOLERANCE, 1e-10);
00603 fTess = tess;
00604 }
00605
00606
00607 Tesselator::~Tesselator()
00608 {
00609 gluDeleteTess((GLUtesselator *)fTess);
00610 }
00611
00612
00613
00614
00615
00616
00617 OffScreenDevice::OffScreenDevice(UInt_t w, UInt_t h, UInt_t x, UInt_t y, Bool_t top)
00618 : fW(w), fH(h), fX(x), fY(y), fTop(top)
00619 {
00620 }
00621
00622
00623 GLLimits::GLLimits()
00624 : fMaxLineWidth(0.),
00625 fMaxPointSize(0.)
00626 {
00627 }
00628
00629
00630 Double_t GLLimits::GetMaxLineWidth()const
00631 {
00632 if (!fMaxLineWidth) {
00633 Double_t lp[2] = {};
00634 glGetDoublev(lineWidthPNAME, lp);
00635 fMaxLineWidth = lp[1];
00636 }
00637
00638 return fMaxLineWidth;
00639 }
00640
00641
00642 Double_t GLLimits::GetMaxPointSize()const
00643 {
00644 if (!fMaxPointSize) {
00645 Double_t lp[2] = {};
00646 glGetDoublev(pointSizePNAME, lp);
00647 fMaxPointSize = lp[1];
00648 }
00649
00650 return fMaxLineWidth;
00651 }
00652
00653
00654
00655 void ExtractRGB(Color_t colorIndex, Float_t *rgb)
00656 {
00657 const TColor *color = gROOT->GetColor(colorIndex);
00658 if (color)
00659 color->GetRGB(rgb[0], rgb[1], rgb[2]);
00660 }
00661
00662 namespace {
00663
00664
00665 void CalculateCircle(std::vector<TPoint> &circle, Double_t r, UInt_t pts)
00666 {
00667 const Double_t delta = TMath::TwoPi() / pts;
00668 const UInt_t first = circle.size();
00669 Double_t angle = 0.;
00670 circle.resize(circle.size() + pts + 1);
00671
00672 for (UInt_t i = 0; i < pts; ++i, angle += delta) {
00673 circle[first + i].fX = SCoord_t(r * TMath::Cos(angle));
00674 circle[first + i].fY = SCoord_t(r * TMath::Sin(angle));
00675 }
00676
00677 circle.back().fX = circle[first].fX;
00678 circle.back().fY = circle[first].fY;
00679 }
00680
00681 }
00682
00683 }
00684 }