Logo ROOT   6.14/05
Reference Guide
TGLUtil.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Richard Maunder 25/05/2005
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include <algorithm>
13 #include <cassert>
14 #include <string>
15 #include <map>
16 
17 #include "THLimitsFinder.h"
18 #include "TVirtualPad.h"
19 #include "TVirtualX.h"
20 #include "Riostream.h"
21 #include "TStyle.h"
22 #include "TGaxis.h"
23 #include "TColor.h"
24 #include "TError.h"
25 #include "TH1.h"
26 #include "TMath.h"
27 #include "TROOT.h"
28 #include "TClass.h"
29 #include "TEnv.h"
30 
31 #include "TGLBoundingBox.h"
32 #include "TGLCamera.h"
33 #include "TGLPlotPainter.h"
34 #include "TGLIncludes.h"
35 #include "TGLQuadric.h"
36 #include "TGLUtil.h"
37 
38 /** \class TGLVertex3
39 \ingroup opengl
40 3 component (x/y/z) vertex class.
41 
42 This is part of collection of simple utility classes for GL only in
43 TGLUtil.h/cxx. These provide const and non-const accessors Arr() &
44 CArr() to a GL compatible internal field - so can be used directly
45 with OpenGL C API calls - which TVector3 etc cannot (easily).
46 They are not intended to be fully featured just provide minimum required.
47 */
48 
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 /// Construct a default (0.0, 0.0, 0.0) vertex
53 
55 {
56  Fill(0.0);
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Construct a vertex with components (x,y,z)
61 
63 {
64  Set(x,y,z);
65 }
66 
67 ////////////////////////////////////////////////////////////////////////////////
68 /// Construct a vertex with components (v[0], v[1], v[2])
69 
71 {
72  Set(v[0], v[1], v[2]);
73 }
74 
75 ////////////////////////////////////////////////////////////////////////////////
76 /// Construct a vertex from 'other'
77 
79 {
80  Set(other);
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// Destroy vertex object
85 
87 {
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Offset a vertex by vector 'shift'
92 
94 {
95  fVals[0] += shift[0];
96  fVals[1] += shift[1];
97  fVals[2] += shift[2];
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Offset a vertex by components (xDelta, yDelta, zDelta)
102 
103 void TGLVertex3::Shift(Double_t xDelta, Double_t yDelta, Double_t zDelta)
104 {
105  fVals[0] += xDelta;
106  fVals[1] += yDelta;
107  fVals[2] += zDelta;
108 }
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 
112 void TGLVertex3::Minimum(const TGLVertex3 & other)
113 {
114  fVals[0] = TMath::Min(fVals[0], other.fVals[0]);
115  fVals[1] = TMath::Min(fVals[1], other.fVals[1]);
116  fVals[2] = TMath::Min(fVals[2], other.fVals[2]);
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 
121 void TGLVertex3::Maximum(const TGLVertex3 & other)
122 {
123  fVals[0] = TMath::Max(fVals[0], other.fVals[0]);
124  fVals[1] = TMath::Max(fVals[1], other.fVals[1]);
125  fVals[2] = TMath::Max(fVals[2], other.fVals[2]);
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Output vertex component values to std::cout
130 
131 void TGLVertex3::Dump() const
132 {
133  std::cout << "(" << fVals[0] << "," << fVals[1] << "," << fVals[2] << ")" << std::endl;
134 }
135 
136 /** \class TGLVector3
137 \ingroup opengl
138 3 component (x/y/z) vector class.
139 
140 This is part of collection of utility classes for GL in TGLUtil.h/cxx
141 These provide const and non-const accessors Arr() / CArr() to a GL
142 compatible internal field - so can be used directly with OpenGL C API
143 calls. They are not intended to be fully featured just provide
144 minimum required.
145 */
146 
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// Construct a default (0.0, 0.0, 0.0) vector
151 
153  TGLVertex3()
154 {
155 }
156 
157 ////////////////////////////////////////////////////////////////////////////////
158 /// Construct a vector with components (x,y,z)
159 
161  TGLVertex3(x, y, z)
162 {
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Construct a vector from components of 'other'
167 
169  TGLVertex3(other.fVals[0], other.fVals[1], other.fVals[2])
170 {
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Construct a vector with components (src[0], src[1], src[2])
175 
177  TGLVertex3(src[0], src[1], src[2])
178 {
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// Destroy vector object
183 
185 {
186 }
187 
188 /** \class TGLLine3
189 \ingroup opengl
190 3D space, fixed length, line class, with direction / length 'vector',
191 passing through point 'vertex'. Just wraps a TGLVector3 / TGLVertex3 pair.
192 */
193 
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 /// Construct 3D line running from 'start' to 'end'
198 
199 TGLLine3::TGLLine3(const TGLVertex3 & start, const TGLVertex3 & end) :
200  fVertex(start), fVector(end - start)
201 {
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Construct 3D line running from 'start', magnitude 'vect'
206 
207 TGLLine3::TGLLine3(const TGLVertex3 & start, const TGLVector3 & vect) :
208  fVertex(start), fVector(vect)
209 {
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Destroy 3D line object
214 
216 {
217 }
218 
219 ////////////////////////////////////////////////////////////////////////////////
220 /// Set 3D line running from 'start' to 'end'
221 
222 void TGLLine3::Set(const TGLVertex3 & start, const TGLVertex3 & end)
223 {
224  fVertex = start;
225  fVector = end - start;
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 /// Set 3D line running from start, magnitude 'vect'
230 
231 void TGLLine3::Set(const TGLVertex3 & start, const TGLVector3 & vect)
232 {
233  fVertex = start;
234  fVector = vect;
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// Draw line in current basic GL color. Assume we are in the correct reference
239 /// frame
240 
241 void TGLLine3::Draw() const
242 {
243  glBegin(GL_LINE_LOOP);
244  glVertex3dv(fVertex.CArr());
245  glVertex3dv(End().CArr());
246  glEnd();
247 }
248 
249 /** \class TGLRect
250 \ingroup opengl
251 Viewport (pixel base) 2D rectangle class.
252 */
253 
255 
256 ////////////////////////////////////////////////////////////////////////////////
257 /// Construct empty rect object, corner (0,0), width/height 0
258 
260  fX(0), fY(0), fWidth(0), fHeight(0)
261 {
262 }
263 
264 ////////////////////////////////////////////////////////////////////////////////
265 /// Construct rect object, corner (x,y), dimensions 'width', 'height'
266 
268  fX(x), fY(y), fWidth(width), fHeight(height)
269 {
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// Construct rect object, corner (x,y), dimensions 'width', 'height'
274 
276  fX(x), fY(y), fWidth(width), fHeight(height)
277 {
278 }
279 
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// Destroy rect object
283 
285 {
286 }
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// Expand the rect to encompass point (x,y)
290 
292 {
293  Int_t delX = x - fX;
294  Int_t delY = y - fY;
295 
296  if (delX > fWidth) {
297  fWidth = delX;
298  }
299  if (delY > fHeight) {
300  fHeight = delY;
301  }
302 
303  if (delX < 0) {
304  fX = x;
305  fWidth += -delX;
306  }
307  if (delY < 0) {
308  fY = y;
309  fHeight += -delY;
310  }
311 }
312 
313 ////////////////////////////////////////////////////////////////////////////////
314 /// Return the diagonal of the rectangle.
315 
317 {
318  const Double_t w = static_cast<Double_t>(fWidth);
319  const Double_t h = static_cast<Double_t>(fHeight);
320  return TMath::Nint(TMath::Sqrt(w*w + h*h));
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// Return overlap result (kInside, kOutside, kPartial) of this
325 /// rect with 'other'
326 
328 {
329  using namespace Rgl;
330 
331  if ((fX <= other.fX) && (fX + fWidth >= other.fX + other.fWidth) &&
332  (fY <= other.fY) && (fY + fHeight >= other.fY + other.fHeight))
333  {
334  return kInside;
335  }
336  else if ((fX >= other.fX + static_cast<Int_t>(other.fWidth)) ||
337  (fX + static_cast<Int_t>(fWidth) <= other.fX) ||
338  (fY >= other.fY + static_cast<Int_t>(other.fHeight)) ||
339  (fY + static_cast<Int_t>(fHeight) <= other.fY))
340  {
341  return kOutside;
342  }
343  else
344  {
345  return kPartial;
346  }
347 }
348 
349 /** \class TGLPlane
350 \ingroup opengl
351 3D plane class - of format Ax + By + Cz + D = 0
352 
353 This is part of collection of simple utility classes for GL only in
354 TGLUtil.h/cxx. These provide const and non-const accessors Arr() &
355 CArr() to a GL compatible internal field - so can be used directly
356 with OpenGL C API calls - which TVector3 etc cannot (easily).
357 They are not intended to be fully featured just provide minimum
358 required.
359 */
360 
362 
363 ////////////////////////////////////////////////////////////////////////////////
364 /// Construct a default plane of x + y + z = 0
365 
367 {
368  Set(1.0, 1.0, 1.0, 0.0);
369 }
370 
371 ////////////////////////////////////////////////////////////////////////////////
372 /// Construct plane from 'other'
373 
375 {
376  Set(other);
377 }
378 
379 ////////////////////////////////////////////////////////////////////////////////
380 /// Construct plane with equation a.x + b.y + c.z + d = 0
381 /// with optional normalisation
382 
384 {
385  Set(a, b, c, d);
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 /// Construct plane with equation eq[0].x + eq[1].y + eq[2].z + eq[3] = 0
390 /// with optional normalisation
391 
393 {
394  Set(eq);
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// Construct plane passing through 3 supplied points
399 /// with optional normalisation
400 
402  const TGLVertex3 & p3)
403 {
404  Set(p1, p2, p3);
405 }
406 
407 ////////////////////////////////////////////////////////////////////////////////
408 /// Construct plane with supplied normal vector, passing through point
409 /// with optional normalisation
410 
412 {
413  Set(v, p);
414 }
415 
416 ////////////////////////////////////////////////////////////////////////////////
417 /// Destroy plane object
418 
420 {
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Normalise the plane.
425 
427 {
428  Double_t mag = sqrt(fVals[0]*fVals[0] + fVals[1]*fVals[1] + fVals[2]*fVals[2]);
429 
430  if (mag == 0.0 ) {
431  Error("TGLPlane::Normalise", "trying to normalise plane with zero magnitude normal");
432  return;
433  }
434  mag = 1.0 / mag;
435  fVals[0] *= mag;
436  fVals[1] *= mag;
437  fVals[2] *= mag;
438  fVals[3] *= mag;
439 }
440 
441 ////////////////////////////////////////////////////////////////////////////////
442 /// Output plane equation to std::out
443 
444 void TGLPlane::Dump() const
445 {
446  std::cout.precision(6);
447  std::cout << "Plane : " << fVals[0] << "x + " << fVals[1] << "y + " << fVals[2] << "z + " << fVals[3] << std::endl;
448 }
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Assign from other.
452 
453 void TGLPlane::Set(const TGLPlane & other)
454 {
455  fVals[0] = other.fVals[0];
456  fVals[1] = other.fVals[1];
457  fVals[2] = other.fVals[2];
458  fVals[3] = other.fVals[3];
459 }
460 
461 ////////////////////////////////////////////////////////////////////////////////
462 /// Set by values.
463 
465 {
466  fVals[0] = a;
467  fVals[1] = b;
468  fVals[2] = c;
469  fVals[3] = d;
470  Normalise();
471 }
472 
473 ////////////////////////////////////////////////////////////////////////////////
474 /// Set by array values.
475 
477 {
478  fVals[0] = eq[0];
479  fVals[1] = eq[1];
480  fVals[2] = eq[2];
481  fVals[3] = eq[3];
482  Normalise();
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// Set plane from a normal vector and in-plane point pair
487 
488 void TGLPlane::Set(const TGLVector3 & norm, const TGLVertex3 & point)
489 {
490  fVals[0] = norm[0];
491  fVals[1] = norm[1];
492  fVals[2] = norm[2];
493  fVals[3] = -(fVals[0]*point[0] + fVals[1]*point[1] + fVals[2]*point[2]);
494  Normalise();
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 /// Set plane by three points.
499 
500 void TGLPlane::Set(const TGLVertex3 & p1, const TGLVertex3 & p2, const TGLVertex3 & p3)
501 {
502  TGLVector3 norm = Cross(p2 - p1, p3 - p1);
503  Set(norm, p2);
504 }
505 
506 ////////////////////////////////////////////////////////////////////////////////
507 /// Negate the plane.
508 
510 {
511  fVals[0] = -fVals[0];
512  fVals[1] = -fVals[1];
513  fVals[2] = -fVals[2];
514  fVals[3] = -fVals[3];
515 }
516 
517 ////////////////////////////////////////////////////////////////////////////////
518 /// Distance from plane to vertex.
519 
521 {
522  return (fVals[0]*vertex[0] + fVals[1]*vertex[1] + fVals[2]*vertex[2] + fVals[3]);
523 }
524 
525 ////////////////////////////////////////////////////////////////////////////////
526 /// Return nearest point on plane.
527 
529 {
530  TGLVector3 o = Norm() * (Dot(Norm(), TGLVector3(point[0], point[1], point[2])) + D() / Dot(Norm(), Norm()));
531  TGLVertex3 v = point - o;
532  return v;
533 }
534 
535 // Some free functions for plane intersections
536 
537 ////////////////////////////////////////////////////////////////////////////////
538 /// Find 3D line interestion of this plane with 'other'. Returns a std::pair
539 ///
540 /// first (Bool_t) second (TGLLine3)
541 /// kTRUE - planes intersect intersection line between planes
542 /// kFALSE - no intersect (parallel) undefined
543 
544 std::pair<Bool_t, TGLLine3> Intersection(const TGLPlane & p1, const TGLPlane & p2)
545 {
546  TGLVector3 lineDir = Cross(p1.Norm(), p2.Norm());
547 
548  if (lineDir.Mag() == 0.0) {
549  return std::make_pair(kFALSE, TGLLine3(TGLVertex3(0.0, 0.0, 0.0),
550  TGLVector3(0.0, 0.0, 0.0)));
551  }
552  TGLVertex3 linePoint = Cross((p1.Norm()*p2.D() - p2.Norm()*p1.D()), lineDir) /
553  Dot(lineDir, lineDir);
554  return std::make_pair(kTRUE, TGLLine3(linePoint, lineDir));
555 }
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 
559 std::pair<Bool_t, TGLVertex3> Intersection(const TGLPlane & p1, const TGLPlane & p2, const TGLPlane & p3)
560 {
561  Double_t denom = Dot(p1.Norm(), Cross(p2.Norm(), p3.Norm()));
562  if (denom == 0.0) {
563  return std::make_pair(kFALSE, TGLVertex3(0.0, 0.0, 0.0));
564  }
565  TGLVector3 vect = ((Cross(p2.Norm(),p3.Norm())* -p1.D()) -
566  (Cross(p3.Norm(),p1.Norm())*p2.D()) -
567  (Cross(p1.Norm(),p2.Norm())*p3.D())) / denom;
568  TGLVertex3 interVert(vect.X(), vect.Y(), vect.Z());
569  return std::make_pair(kTRUE, interVert);
570 }
571 
572 ////////////////////////////////////////////////////////////////////////////////
573 /// Find intersection of 3D space 'line' with this plane. If 'extend' is kTRUE
574 /// then line extents can be extended (infinite length) to find intersection.
575 /// If 'extend' is kFALSE the fixed extents of line is respected.
576 ///
577 /// The return a std::pair
578 ///
579 /// - first (Bool_t) second (TGLVertex3)
580 /// - kTRUE - line/plane intersect intersection vertex on plane
581 /// - kFALSE - no line/plane intersect undefined
582 ///
583 /// If intersection is not found (first == kFALSE) & 'extend' was kTRUE (infinite line)
584 /// this implies line and plane are parallel. If 'extend' was kFALSE, then
585 /// either line parallel or insufficient length.
586 
587 std::pair<Bool_t, TGLVertex3> Intersection(const TGLPlane & plane, const TGLLine3 & line, Bool_t extend)
588 {
589  Double_t denom = -(plane.A()*line.Vector().X() +
590  plane.B()*line.Vector().Y() +
591  plane.C()*line.Vector().Z());
592 
593  if (denom == 0.0) {
594  return std::make_pair(kFALSE, TGLVertex3(0.0, 0.0, 0.0));
595  }
596 
597  Double_t num = plane.A()*line.Start().X() + plane.B()*line.Start().Y() +
598  plane.C()*line.Start().Z() + plane.D();
599  Double_t factor = num/denom;
600 
601  // If not extending (projecting) line is length from start enough to reach plane?
602  if (!extend && (factor < 0.0 || factor > 1.0)) {
603  return std::make_pair(kFALSE, TGLVertex3(0.0, 0.0, 0.0));
604  }
605 
606  TGLVector3 toPlane = line.Vector() * factor;
607  return std::make_pair(kTRUE, line.Start() + toPlane);
608 }
609 
610 /** \class TGLMatrix
611 \ingroup opengl
612 16 component (4x4) transform matrix - column MAJOR as per GL.
613 Provides limited support for adjusting the translation, scale and
614 rotation components.
615 
616 This is part of collection of simple utility classes for GL only in
617 TGLUtil.h/cxx. These provide const and non-const accessors Arr() &
618 CArr() to a GL compatible internal field - so can be used directly
619 with OpenGL C API calls - which TVector3 etc cannot (easily).
620 They are not intended to be fully featured just provide minimum
621 required.
622 */
623 
625 
626 ////////////////////////////////////////////////////////////////////////////////
627 /// Construct default identity matrix:
628 ///
629 /// 1 0 0 0
630 /// 0 1 0 0
631 /// 0 0 1 0
632 /// 0 0 0 1
633 
635 {
636  SetIdentity();
637 }
638 
639 ////////////////////////////////////////////////////////////////////////////////
640 /// Construct matrix with translation components x,y,z:
641 ///
642 /// 1 0 0 x
643 /// 0 1 0 y
644 /// 0 0 1 z
645 /// 0 0 0 1
646 
648 {
649  SetIdentity();
650  SetTranslation(x, y, z);
651 }
652 
653 ////////////////////////////////////////////////////////////////////////////////
654 /// Construct matrix with translation components x,y,z:
655 ///
656 /// 1 0 0 translation.X()
657 /// 0 1 0 translation.Y()
658 /// 0 0 1 translation.Z()
659 /// 0 0 0 1
660 
661 TGLMatrix::TGLMatrix(const TGLVertex3 & translation)
662 {
663  SetIdentity();
664  SetTranslation(translation);
665 }
666 
667 ////////////////////////////////////////////////////////////////////////////////
668 /// Construct matrix which when applied puts local origin at
669 /// 'origin' and the local Z axis in direction 'z'. Both
670 /// 'origin' and 'zAxisVec' are expressed in the parent frame
671 
672 TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis)
673 {
674  SetIdentity();
675 
676  TGLVector3 zAxisInt(zAxis);
677  zAxisInt.Normalise();
678  TGLVector3 arbAxis;
679 
680  if (TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Y()) && TMath::Abs(zAxisInt.X()) <= TMath::Abs(zAxisInt.Z())) {
681  arbAxis.Set(1.0, 0.0, 0.0);
682  } else if (TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.X()) && TMath::Abs(zAxisInt.Y()) <= TMath::Abs(zAxisInt.Z())) {
683  arbAxis.Set(0.0, 1.0, 0.0);
684  } else {
685  arbAxis.Set(0.0, 0.0, 1.0);
686  }
687 
688  Set(origin, zAxis, Cross(zAxisInt, arbAxis));
689 }
690 
691 ////////////////////////////////////////////////////////////////////////////////
692 /// Construct matrix which when applied puts local origin at
693 /// 'origin' and the local Z axis in direction 'z'. Both
694 /// 'origin' and 'zAxisVec' are expressed in the parent frame
695 
696 TGLMatrix::TGLMatrix(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis)
697 {
698  SetIdentity();
699  Set(origin, zAxis, xAxis);
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// Construct matrix using the 16 Double_t 'vals' passed,
704 /// ordering is maintained - i.e. should be column major
705 /// as we are
706 
708 {
709  Set(vals);
710 }
711 
712 ////////////////////////////////////////////////////////////////////////////////
713 /// Construct matrix from 'other'
714 
716 {
717  *this = other;
718 }
719 
720 ////////////////////////////////////////////////////////////////////////////////
721 /// Destroy matrix object
722 
724 {
725 }
726 
727 ////////////////////////////////////////////////////////////////////////////////
728 /// Multiply with matrix rhs on right.
729 
731 {
732  Double_t B[4];
733  Double_t* C = fVals;
734  for(int r=0; r<4; ++r, ++C)
735  {
736  const Double_t* T = rhs.fVals;
737  for(int c=0; c<4; ++c, T+=4)
738  B[c] = C[0]*T[0] + C[4]*T[1] + C[8]*T[2] + C[12]*T[3];
739  C[0] = B[0]; C[4] = B[1]; C[8] = B[2]; C[12] = B[3];
740  }
741 }
742 
743 ////////////////////////////////////////////////////////////////////////////////
744 /// Multiply with matrix lhs on left.
745 
746 void TGLMatrix::MultLeft (const TGLMatrix & lhs)
747 {
748  Double_t B[4];
749  Double_t* C = fVals;
750  for (int c=0; c<4; ++c, C+=4)
751  {
752  const Double_t* T = lhs.fVals;
753  for(int r=0; r<4; ++r, ++T)
754  B[r] = T[0]*C[0] + T[4]*C[1] + T[8]*C[2] + T[12]*C[3];
755  C[0] = B[0]; C[1] = B[1]; C[2] = B[2]; C[3] = B[3];
756  }
757 }
758 
759 ////////////////////////////////////////////////////////////////////////////////
760 /// Set matrix which when applied puts local origin at
761 /// 'origin' and the local Z axis in direction 'z'. Both
762 /// 'origin' and 'z' are expressed in the parent frame
763 
764 void TGLMatrix::Set(const TGLVertex3 & origin, const TGLVector3 & zAxis, const TGLVector3 & xAxis)
765 {
766  TGLVector3 zAxisInt(zAxis);
767  zAxisInt.Normalise();
768 
769  TGLVector3 xAxisInt(xAxis);
770  xAxisInt.Normalise();
771  TGLVector3 yAxisInt = Cross(zAxisInt, xAxisInt);
772 
773  fVals[0] = xAxisInt.X(); fVals[4] = yAxisInt.X(); fVals[8 ] = zAxisInt.X(); fVals[12] = origin.X();
774  fVals[1] = xAxisInt.Y(); fVals[5] = yAxisInt.Y(); fVals[9 ] = zAxisInt.Y(); fVals[13] = origin.Y();
775  fVals[2] = xAxisInt.Z(); fVals[6] = yAxisInt.Z(); fVals[10] = zAxisInt.Z(); fVals[14] = origin.Z();
776  fVals[3] = 0.0; fVals[7] = 0.0; fVals[11] = 0.0; fVals[15] = 1.0;
777 }
778 
779 ////////////////////////////////////////////////////////////////////////////////
780 /// Set matrix using the 16 Double_t 'vals' passed,
781 /// ordering is maintained - i.e. should be column major.
782 
783 void TGLMatrix::Set(const Double_t vals[16])
784 {
785  for (UInt_t i=0; i < 16; i++) {
786  fVals[i] = vals[i];
787  }
788 }
789 
790 ////////////////////////////////////////////////////////////////////////////////
791 /// Set matrix to identity.
792 
794 {
795  fVals[0] = 1.0; fVals[4] = 0.0; fVals[8 ] = 0.0; fVals[12] = 0.0;
796  fVals[1] = 0.0; fVals[5] = 1.0; fVals[9 ] = 0.0; fVals[13] = 0.0;
797  fVals[2] = 0.0; fVals[6] = 0.0; fVals[10] = 1.0; fVals[14] = 0.0;
798  fVals[3] = 0.0; fVals[7] = 0.0; fVals[11] = 0.0; fVals[15] = 1.0;
799 }
800 
801 ////////////////////////////////////////////////////////////////////////////////
802 /// Set matrix translation components x,y,z.
803 
805 {
806  SetTranslation(TGLVertex3(x,y,z));
807 }
808 
809 ////////////////////////////////////////////////////////////////////////////////
810 /// Set matrix translation components x,y,z.
811 
812 void TGLMatrix::SetTranslation(const TGLVertex3 & translation)
813 {
814  fVals[12] = translation[0];
815  fVals[13] = translation[1];
816  fVals[14] = translation[2];
817 }
818 
819 ////////////////////////////////////////////////////////////////////////////////
820 /// Return the translation component of matrix.
821 
823 {
824  return TGLVector3(fVals[12], fVals[13], fVals[14]);
825 }
826 
827 ////////////////////////////////////////////////////////////////////////////////
828 /// Shift matrix translation components by 'vect' in parent frame.
829 
831 {
832  fVals[12] += vect[0];
833  fVals[13] += vect[1];
834  fVals[14] += vect[2];
835 }
836 
837 ////////////////////////////////////////////////////////////////////////////////
838 /// Translate in local frame.
839 /// i1, i2 are axes indices: 1 ~ x, 2 ~ y, 3 ~ z.
840 
842 {
843  const Double_t *C = fVals + 4*--ai;
844  fVals[12] += amount*C[0]; fVals[13] += amount*C[1]; fVals[14] += amount*C[2];
845 }
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// Translate in local frame along all base vectors simultaneously.
849 
851 {
852  fVals[12] += x*fVals[0] + y*fVals[4] + z*fVals[8];
853  fVals[13] += x*fVals[1] + y*fVals[5] + z*fVals[9];
854  fVals[14] += x*fVals[2] + y*fVals[6] + z*fVals[10];
855 }
856 
857 ////////////////////////////////////////////////////////////////////////////////
858 /// Set matrix axis scales to 'scale'. Note - this really sets
859 /// the overall (total) scaling for each axis - it does NOT
860 /// apply compounded scale on top of existing one
861 
862 void TGLMatrix::Scale(const TGLVector3 & scale)
863 {
864  TGLVector3 currentScale = GetScale();
865 
866  // x
867  if (currentScale[0] != 0.0) {
868  fVals[0] *= scale[0]/currentScale[0];
869  fVals[1] *= scale[0]/currentScale[0];
870  fVals[2] *= scale[0]/currentScale[0];
871  } else {
872  Error("TGLMatrix::Scale()", "zero scale div by zero");
873  }
874  // y
875  if (currentScale[1] != 0.0) {
876  fVals[4] *= scale[1]/currentScale[1];
877  fVals[5] *= scale[1]/currentScale[1];
878  fVals[6] *= scale[1]/currentScale[1];
879  } else {
880  Error("TGLMatrix::Scale()", "zero scale div by zero");
881  }
882  // z
883  if (currentScale[2] != 0.0) {
884  fVals[8] *= scale[2]/currentScale[2];
885  fVals[9] *= scale[2]/currentScale[2];
886  fVals[10] *= scale[2]/currentScale[2];
887  } else {
888  Error("TGLMatrix::Scale()", "zero scale div by zero");
889  }
890 }
891 
892 ////////////////////////////////////////////////////////////////////////////////
893 /// Update matrix so resulting transform has been rotated about 'pivot'
894 /// (in parent frame), round vector 'axis', through 'angle' (radians)
895 /// Equivalent to glRotate function, but with addition of translation
896 /// and compounded on top of existing.
897 
898 void TGLMatrix::Rotate(const TGLVertex3 & pivot, const TGLVector3 & axis, Double_t angle)
899 {
900  TGLVector3 nAxis = axis;
901  nAxis.Normalise();
902  Double_t x = nAxis.X();
903  Double_t y = nAxis.Y();
904  Double_t z = nAxis.Z();
905  Double_t c = TMath::Cos(angle);
906  Double_t s = TMath::Sin(angle);
907 
908  // Calculate local rotation, with pre-translation to local pivot origin
909  TGLMatrix rotMat;
910  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];
911  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];
912  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];
913  rotMat[ 3] = 0.0; rotMat[ 7] = 0.0; rotMat[11] = 0.0; rotMat[15] = 1.0;
914  TGLMatrix localToWorld(-pivot);
915 
916  // TODO: Ugly - should use quaternions to avoid compound rounding errors and
917  // triple multiplication
918  *this = rotMat * localToWorld * (*this);
919 }
920 
921 ////////////////////////////////////////////////////////////////////////////////
922 /// Rotate in local frame. Does optimised version of MultRight.
923 /// i1, i2 are axes indices: 1 ~ x, 2 ~ y, 3 ~ z.
924 
926 {
927  if(i1 == i2) return;
928  const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
929  Double_t b1, b2;
930  Double_t* c = fVals;
931  --i1 <<= 2; --i2 <<= 2; // column major
932  for(int r=0; r<4; ++r, ++c) {
933  b1 = cos*c[i1] + sin*c[i2];
934  b2 = cos*c[i2] - sin*c[i1];
935  c[i1] = b1; c[i2] = b2;
936  }
937 }
938 
939 ////////////////////////////////////////////////////////////////////////////////
940 /// Rotate in parent frame. Does optimised version of MultLeft.
941 
943 {
944  if(i1 == i2) return;
945 
946  // Optimized version:
947  const Double_t cos = TMath::Cos(amount), sin = TMath::Sin(amount);
948  Double_t b1, b2;
949  Double_t* C = fVals;
950  --i1; --i2;
951  for(int c=0; c<4; ++c, C+=4) {
952  b1 = cos*C[i1] - sin*C[i2];
953  b2 = cos*C[i2] + sin*C[i1];
954  C[i1] = b1; C[i2] = b2;
955  }
956 }
957 
958 ////////////////////////////////////////////////////////////////////////////////
959 /// Transform passed 'vertex' by this matrix - converts local frame to parent
960 
962 {
963  TGLVertex3 orig = vertex;
964  for (UInt_t i = 0; i < 3; i++) {
965  vertex[i] = orig[0] * fVals[0+i] + orig[1] * fVals[4+i] +
966  orig[2] * fVals[8+i] + fVals[12+i];
967  }
968 }
969 
970 ////////////////////////////////////////////////////////////////////////////////
971 /// Transpose the top left 3x3 matrix component along major diagonal
972 /// Supported as currently incompatibility between TGeo and GL matrix
973 /// layouts for this 3x3 only. To be resolved.
974 
976 {
977  // TODO: Move this fix to the TBuffer3D filling side and remove
978  //
979  // 0 4 8 12
980  // 1 5 9 13
981  // 2 6 10 14
982  // 3 7 11 15
983 
984  Double_t temp = fVals[4];
985  fVals[4] = fVals[1];
986  fVals[1] = temp;
987  temp = fVals[8];
988  fVals[8] = fVals[2];
989  fVals[2] = temp;
990  temp = fVals[9];
991  fVals[9] = fVals[6];
992  fVals[6] = temp;
993 }
994 
995 ////////////////////////////////////////////////////////////////////////////////
996 /// Invert the matrix, returns determinant.
997 /// Copied from TMatrixFCramerInv.
998 
1000 {
1001  Double_t* M = fVals;
1002 
1003  const Double_t det2_12_01 = M[1]*M[6] - M[5]*M[2];
1004  const Double_t det2_12_02 = M[1]*M[10] - M[9]*M[2];
1005  const Double_t det2_12_03 = M[1]*M[14] - M[13]*M[2];
1006  const Double_t det2_12_13 = M[5]*M[14] - M[13]*M[6];
1007  const Double_t det2_12_23 = M[9]*M[14] - M[13]*M[10];
1008  const Double_t det2_12_12 = M[5]*M[10] - M[9]*M[6];
1009  const Double_t det2_13_01 = M[1]*M[7] - M[5]*M[3];
1010  const Double_t det2_13_02 = M[1]*M[11] - M[9]*M[3];
1011  const Double_t det2_13_03 = M[1]*M[15] - M[13]*M[3];
1012  const Double_t det2_13_12 = M[5]*M[11] - M[9]*M[7];
1013  const Double_t det2_13_13 = M[5]*M[15] - M[13]*M[7];
1014  const Double_t det2_13_23 = M[9]*M[15] - M[13]*M[11];
1015  const Double_t det2_23_01 = M[2]*M[7] - M[6]*M[3];
1016  const Double_t det2_23_02 = M[2]*M[11] - M[10]*M[3];
1017  const Double_t det2_23_03 = M[2]*M[15] - M[14]*M[3];
1018  const Double_t det2_23_12 = M[6]*M[11] - M[10]*M[7];
1019  const Double_t det2_23_13 = M[6]*M[15] - M[14]*M[7];
1020  const Double_t det2_23_23 = M[10]*M[15] - M[14]*M[11];
1021 
1022 
1023  const Double_t det3_012_012 = M[0]*det2_12_12 - M[4]*det2_12_02 + M[8]*det2_12_01;
1024  const Double_t det3_012_013 = M[0]*det2_12_13 - M[4]*det2_12_03 + M[12]*det2_12_01;
1025  const Double_t det3_012_023 = M[0]*det2_12_23 - M[8]*det2_12_03 + M[12]*det2_12_02;
1026  const Double_t det3_012_123 = M[4]*det2_12_23 - M[8]*det2_12_13 + M[12]*det2_12_12;
1027  const Double_t det3_013_012 = M[0]*det2_13_12 - M[4]*det2_13_02 + M[8]*det2_13_01;
1028  const Double_t det3_013_013 = M[0]*det2_13_13 - M[4]*det2_13_03 + M[12]*det2_13_01;
1029  const Double_t det3_013_023 = M[0]*det2_13_23 - M[8]*det2_13_03 + M[12]*det2_13_02;
1030  const Double_t det3_013_123 = M[4]*det2_13_23 - M[8]*det2_13_13 + M[12]*det2_13_12;
1031  const Double_t det3_023_012 = M[0]*det2_23_12 - M[4]*det2_23_02 + M[8]*det2_23_01;
1032  const Double_t det3_023_013 = M[0]*det2_23_13 - M[4]*det2_23_03 + M[12]*det2_23_01;
1033  const Double_t det3_023_023 = M[0]*det2_23_23 - M[8]*det2_23_03 + M[12]*det2_23_02;
1034  const Double_t det3_023_123 = M[4]*det2_23_23 - M[8]*det2_23_13 + M[12]*det2_23_12;
1035  const Double_t det3_123_012 = M[1]*det2_23_12 - M[5]*det2_23_02 + M[9]*det2_23_01;
1036  const Double_t det3_123_013 = M[1]*det2_23_13 - M[5]*det2_23_03 + M[13]*det2_23_01;
1037  const Double_t det3_123_023 = M[1]*det2_23_23 - M[9]*det2_23_03 + M[13]*det2_23_02;
1038  const Double_t det3_123_123 = M[5]*det2_23_23 - M[9]*det2_23_13 + M[13]*det2_23_12;
1039 
1040  const Double_t det = M[0]*det3_123_123 - M[4]*det3_123_023 +
1041  M[8]*det3_123_013 - M[12]*det3_123_012;
1042 
1043  if(det == 0) {
1044  Warning("TGLMatrix::Invert", "matrix is singular.");
1045  return 0;
1046  }
1047 
1048  const Double_t oneOverDet = 1.0/det;
1049  const Double_t mn1OverDet = - oneOverDet;
1050 
1051  M[0] = det3_123_123 * oneOverDet;
1052  M[4] = det3_023_123 * mn1OverDet;
1053  M[8] = det3_013_123 * oneOverDet;
1054  M[12] = det3_012_123 * mn1OverDet;
1055 
1056  M[1] = det3_123_023 * mn1OverDet;
1057  M[5] = det3_023_023 * oneOverDet;
1058  M[9] = det3_013_023 * mn1OverDet;
1059  M[13] = det3_012_023 * oneOverDet;
1060 
1061  M[2] = det3_123_013 * oneOverDet;
1062  M[6] = det3_023_013 * mn1OverDet;
1063  M[10] = det3_013_013 * oneOverDet;
1064  M[14] = det3_012_013 * mn1OverDet;
1065 
1066  M[3] = det3_123_012 * mn1OverDet;
1067  M[7] = det3_023_012 * oneOverDet;
1068  M[11] = det3_013_012 * mn1OverDet;
1069  M[15] = det3_012_012 * oneOverDet;
1070 
1071  return det;
1072 }
1073 
1074 ////////////////////////////////////////////////////////////////////////////////
1075 /// Multiply vector.
1076 
1078 {
1079  const Double_t* M = fVals;
1080  TGLVector3 r;
1081  r.X() = M[0]*v[0] + M[4]*v[1] + M[8]*v[2] + M[12]*w;
1082  r.Y() = M[1]*v[0] + M[5]*v[1] + M[9]*v[2] + M[13]*w;
1083  r.Z() = M[2]*v[0] + M[6]*v[1] + M[10]*v[2] + M[14]*w;
1084  return r;
1085 }
1086 
1087 ////////////////////////////////////////////////////////////////////////////////
1088 /// Rotate vector. Translation is not applied.
1089 
1091 {
1092  const Double_t* M = fVals;
1093  TGLVector3 r;
1094  r.X() = M[0]*v[0] + M[4]*v[1] + M[8]*v[2];
1095  r.Y() = M[1]*v[0] + M[5]*v[1] + M[9]*v[2];
1096  r.Z() = M[2]*v[0] + M[6]*v[1] + M[10]*v[2];
1097  return r;
1098 }
1099 
1100 ////////////////////////////////////////////////////////////////////////////////
1101 /// Multiply vector in-place.
1102 
1104 {
1105  const Double_t* M = fVals;
1106  Double_t r[3] = { v[0], v[1], v[2] };
1107  v.X() = M[0]*r[0] + M[4]*r[1] + M[8]*r[2] + M[12]*w;
1108  v.Y() = M[1]*r[0] + M[5]*r[1] + M[9]*r[2] + M[13]*w;
1109  v.Z() = M[2]*r[0] + M[6]*r[1] + M[10]*r[2] + M[14]*w;
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////////
1113 /// Rotate vector in-place. Translation is not applied.
1114 
1116 {
1117  const Double_t* M = fVals;
1118  Double_t r[3] = { v[0], v[1], v[2] };
1119  v.X() = M[0]*r[0] + M[4]*r[1] + M[8]*r[2];
1120  v.Y() = M[1]*r[0] + M[5]*r[1] + M[9]*r[2];
1121  v.Z() = M[2]*r[0] + M[6]*r[1] + M[10]*r[2];
1122 }
1123 
1124 ////////////////////////////////////////////////////////////////////////////////
1125 /// Get local axis scaling factors
1126 
1128 {
1129  TGLVector3 x(fVals[0], fVals[1], fVals[2]);
1130  TGLVector3 y(fVals[4], fVals[5], fVals[6]);
1131  TGLVector3 z(fVals[8], fVals[9], fVals[10]);
1132  return TGLVector3(x.Mag(), y.Mag(), z.Mag());
1133 }
1134 
1135 ////////////////////////////////////////////////////////////////////////////////
1136 /// Return true if matrix is to be considered a scaling matrix
1137 /// for rendering.
1138 
1140 {
1141  Double_t ss;
1142  ss = fVals[0]*fVals[0] + fVals[1]*fVals[1] + fVals[2]*fVals[2];
1143  if (ss < 0.8 || ss > 1.2) return kTRUE;
1144  ss = fVals[4]*fVals[4] + fVals[5]*fVals[5] + fVals[6]*fVals[6];
1145  if (ss < 0.8 || ss > 1.2) return kTRUE;
1146  ss = fVals[8]*fVals[8] + fVals[9]*fVals[9] + fVals[10]*fVals[10];
1147  if (ss < 0.8 || ss > 1.2) return kTRUE;
1148  return kFALSE;
1149 }
1150 
1151 ////////////////////////////////////////////////////////////////////////////////
1152 /// Output 16 matrix components to std::cout
1153 ///
1154 /// 0 4 8 12
1155 /// 1 5 9 13
1156 /// 2 6 10 14
1157 /// 3 7 11 15
1158 ///
1159 
1160 void TGLMatrix::Dump() const
1161 {
1162  std::cout.precision(6);
1163  for (Int_t x = 0; x < 4; x++) {
1164  std::cout << "[ ";
1165  for (Int_t y = 0; y < 4; y++) {
1166  std::cout << fVals[y*4 + x] << " ";
1167  }
1168  std::cout << "]" << std::endl;
1169  }
1170 }
1171 
1172 
1173 /** \class TGLColor
1174 \ingroup opengl
1175 Class encapsulating color information in preferred GL format - an
1176 array of four unsigned bytes.
1177 Color index is also cached for easier interfacing with the
1178 traditional ROOT graphics.
1179 */
1180 
1182 
1183 ////////////////////////////////////////////////////////////////////////////////
1184 /// Default constructor. Color is initialized to black.
1185 
1187 {
1188  fRGBA[0] = fRGBA[1] = fRGBA[2] = 0;
1189  fRGBA[3] = 255;
1190  fIndex = -1;
1191 }
1192 
1193 ////////////////////////////////////////////////////////////////////////////////
1194 /// Constructor from Int_t values.
1195 
1197 {
1198  SetColor(r, g, b, a);
1199 }
1200 
1201 ////////////////////////////////////////////////////////////////////////////////
1202 /// Constructor from Float_t values.
1203 
1205 {
1206  SetColor(r, g, b, a);
1207 }
1208 
1209 ////////////////////////////////////////////////////////////////////////////////
1210 /// Constructor from color-index and transparency.
1211 
1212 TGLColor::TGLColor(Color_t color_index, Char_t transparency)
1213 {
1214  SetColor(color_index, transparency);
1215 }
1216 
1217 ////////////////////////////////////////////////////////////////////////////////
1218 /// Destructor.
1219 
1221 {
1222 }
1223 
1224 ////////////////////////////////////////////////////////////////////////////////
1225 /// Assignment operator.
1226 
1228 {
1229  fRGBA[0] = c.fRGBA[0];
1230  fRGBA[1] = c.fRGBA[1];
1231  fRGBA[2] = c.fRGBA[2];
1232  fRGBA[3] = c.fRGBA[3];
1233  fIndex = c.fIndex;
1234  return *this;
1235 }
1236 
1237 ////////////////////////////////////////////////////////////////////////////////
1238 /// Returns color-index representing the color.
1239 
1241 {
1242  if (fIndex == -1)
1243  fIndex = TColor::GetColor(fRGBA[0], fRGBA[1], fRGBA[2]);
1244  return fIndex;
1245 }
1246 
1247 ////////////////////////////////////////////////////////////////////////////////
1248 /// Returns transparency value.
1249 
1251 {
1252  return TMath::Nint(100.0*(1.0 - fRGBA[3]/255.0));
1253 }
1254 
1255 ////////////////////////////////////////////////////////////////////////////////
1256 /// Set color with Int_t values.
1257 
1259 {
1260  fRGBA[0] = r;
1261  fRGBA[1] = g;
1262  fRGBA[2] = b;
1263  fRGBA[3] = a;
1264  fIndex = -1;
1265 }
1266 
1267 ////////////////////////////////////////////////////////////////////////////////
1268 /// Set color with Float_t values.
1269 
1271 {
1272  fRGBA[0] = (UChar_t)(255*r);
1273  fRGBA[1] = (UChar_t)(255*g);
1274  fRGBA[2] = (UChar_t)(255*b);
1275  fRGBA[3] = (UChar_t)(255*a);
1276  fIndex = -1;
1277 }
1278 
1279 ////////////////////////////////////////////////////////////////////////////////
1280 /// Set color by color-index. Alpha is not changed.
1281 /// If color_index is not valid, color is set to magenta.
1282 
1283 void TGLColor::SetColor(Color_t color_index)
1284 {
1285  TColor* c = gROOT->GetColor(color_index);
1286  if (c)
1287  {
1288  fRGBA[0] = (UChar_t)(255*c->GetRed());
1289  fRGBA[1] = (UChar_t)(255*c->GetGreen());
1290  fRGBA[2] = (UChar_t)(255*c->GetBlue());
1291  fIndex = color_index;
1292  }
1293  else
1294  {
1295  // Set to magenta.
1296  fRGBA[0] = 255;
1297  fRGBA[1] = 0;
1298  fRGBA[2] = 255;
1299  fIndex = -1;
1300  }
1301 }
1302 
1303 ////////////////////////////////////////////////////////////////////////////////
1304 /// Set color by color-index and alpha from the transparency.
1305 /// If color_index is not valid, color is set to magenta.
1306 
1307 void TGLColor::SetColor(Color_t color_index, Char_t transparency)
1308 {
1309  UChar_t alpha = (255*(100 - transparency))/100;
1310 
1311  TColor* c = gROOT->GetColor(color_index);
1312  if (c)
1313  {
1314  fRGBA[0] = (UChar_t)(255*c->GetRed());
1315  fRGBA[1] = (UChar_t)(255*c->GetGreen());
1316  fRGBA[2] = (UChar_t)(255*c->GetBlue());
1317  fRGBA[3] = alpha;
1318  fIndex = color_index;
1319  }
1320  else
1321  {
1322  // Set to magenta.
1323  fRGBA[0] = 255;
1324  fRGBA[1] = 0;
1325  fRGBA[2] = 255;
1326  fRGBA[3] = alpha;
1327  fIndex = -1;
1328  return;
1329  }
1330 }
1331 
1332 ////////////////////////////////////////////////////////////////////////////////
1333 /// Set alpha from the transparency.
1334 
1336 {
1337  fRGBA[3] = (255*(100 - transparency))/100;
1338 }
1339 
1340 ////////////////////////////////////////////////////////////////////////////////
1341 /// Return string describing the color.
1342 
1343 TString TGLColor::AsString() const
1344 {
1345  return TString::Format("rgba:%02hhx/%02hhx/%02hhx/%02hhx",
1346  fRGBA[0], fRGBA[1], fRGBA[2], fRGBA[3]);
1347 }
1348 
1349 
1350 /** \class TGLColorSet
1351 \ingroup opengl
1352 Class encapsulating a set of colors used throughout standard rendering.
1353 */
1354 
1356 
1357 ////////////////////////////////////////////////////////////////////////////////
1358 /// Constructor. Sets default for dark background.
1359 
1361 {
1362  StdDarkBackground();
1363 }
1364 
1365 ////////////////////////////////////////////////////////////////////////////////
1366 /// Destructor.
1367 
1369 {
1370 }
1371 
1372 ////////////////////////////////////////////////////////////////////////////////
1373 /// Assignment operator.
1374 
1376 {
1377  fBackground = s.fBackground;
1378  fForeground = s.fForeground;
1379  fOutline = s.fOutline;
1380  fMarkup = s.fMarkup;
1381  for (Int_t i = 0; i < 5; ++i)
1382  fSelection[i] = s.fSelection[i];
1383  return *this;
1384 }
1385 
1386 ////////////////////////////////////////////////////////////////////////////////
1387 /// Set defaults for dark (black) background.
1388 
1390 {
1391  fBackground .SetColor(0, 0, 0);
1392  fForeground .SetColor(255, 255, 255);
1393  fOutline .SetColor(240, 255, 240);
1394  fMarkup .SetColor(200, 200, 200);
1395 
1396  fSelection[0].SetColor( 0, 0, 0);
1397  fSelection[1].SetColor(255, 220, 220);
1398  fSelection[2].SetColor(255, 220, 220);
1399  fSelection[3].SetColor(200, 200, 255);
1400  fSelection[4].SetColor(200, 200, 255);
1401 }
1402 
1403 ////////////////////////////////////////////////////////////////////////////////
1404 /// Set defaults for light (white) background.
1405 
1407 {
1408  fBackground .SetColor(255, 255, 255);
1409  fForeground .SetColor(0, 0, 0);
1410  fOutline .SetColor(0, 0, 0);
1411  fMarkup .SetColor(55, 55, 55);
1412 
1413  fSelection[0].SetColor(0, 0, 0);
1414  fSelection[1].SetColor(200, 100, 100);
1415  fSelection[2].SetColor(200, 100, 100);
1416  fSelection[3].SetColor(100, 100, 200);
1417  fSelection[4].SetColor(100, 100, 200);
1418 }
1419 
1420 
1421 /** \class TGLUtil
1422 \ingroup opengl
1423 Wrapper class for various misc static functions - error checking, draw helpers etc.
1424 */
1425 
1426 ClassImp(TGLUtil);
1427 
1429 UInt_t TGLUtil::fgDrawQuality = fgDefaultDrawQuality;
1431 
1436 
1440 
1441 const UChar_t TGLUtil::fgRed[4] = { 230, 0, 0, 255 };
1442 const UChar_t TGLUtil::fgGreen[4] = { 0, 230, 0, 255 };
1443 const UChar_t TGLUtil::fgBlue[4] = { 0, 0, 230, 255 };
1444 const UChar_t TGLUtil::fgYellow[4] = { 210, 210, 0, 255 };
1445 const UChar_t TGLUtil::fgWhite[4] = { 255, 255, 255, 255 };
1446 const UChar_t TGLUtil::fgGrey[4] = { 128, 128, 128, 100 };
1447 
1448 #ifndef CALLBACK
1449 #define CALLBACK
1450 #endif
1451 
1452 extern "C"
1453 {
1454 #if defined(__APPLE_CC__) && __APPLE_CC__ > 4000 && __APPLE_CC__ < 5450 && !defined(__INTEL_COMPILER)
1455  typedef GLvoid (*tessfuncptr_t)(...);
1456 #elif defined(__linux__) || defined(__FreeBSD__) || defined( __OpenBSD__ ) || defined(__sun) || defined (__CYGWIN__) || defined (__APPLE__)
1457  typedef GLvoid (*tessfuncptr_t)();
1458 #elif defined (WIN32)
1459  typedef GLvoid (CALLBACK *tessfuncptr_t)();
1460 #else
1461  #error "Error - need to define type tessfuncptr_t for this platform/compiler"
1462 #endif
1463 }
1464 
1465 namespace
1466 {
1467 
1468 class TGLTesselatorWrap
1469 {
1470 protected:
1471 
1472 public:
1473  GLUtesselator *fTess;
1474 
1475  TGLTesselatorWrap(tessfuncptr_t vertex_func) : fTess(0)
1476  {
1477  fTess = gluNewTess();
1478  if (!fTess)
1479  throw std::bad_alloc();
1480 
1481  gluTessCallback(fTess, (GLenum)GLU_BEGIN, (tessfuncptr_t) glBegin);
1482  gluTessCallback(fTess, (GLenum)GLU_END, (tessfuncptr_t) glEnd);
1483  gluTessCallback(fTess, (GLenum)GLU_VERTEX, vertex_func);
1484  }
1485 
1486  virtual ~TGLTesselatorWrap()
1487  {
1488  if (fTess)
1489  gluDeleteTess(fTess);
1490  }
1491 };
1492 
1493 }
1494 
1495 ////////////////////////////////////////////////////////////////////////////////
1496 /// Returns a tesselator for direct drawing when using 3-vertices with
1497 /// single precision.
1498 
1500 {
1501  static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex3fv);
1502 
1503  return singleton.fTess;
1504 }
1505 
1506 ////////////////////////////////////////////////////////////////////////////////
1507 /// Returns a tesselator for direct drawing when using 4-vertices with
1508 /// single precision.
1509 
1511 {
1512  static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex4fv);
1513 
1514  return singleton.fTess;
1515 }
1516 
1517 ////////////////////////////////////////////////////////////////////////////////
1518 /// Returns a tesselator for direct drawing when using 3-vertices with
1519 /// double precision.
1520 
1522 {
1523  static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex3dv);
1524 
1525  return singleton.fTess;
1526 }
1527 
1528 ////////////////////////////////////////////////////////////////////////////////
1529 /// Returns a tesselator for direct drawing when using 4-vertices with
1530 /// double precision.
1531 
1533 {
1534  static TGLTesselatorWrap singleton((tessfuncptr_t) glVertex4dv);
1535 
1536  return singleton.fTess;
1537 }
1538 
1539 ////////////////////////////////////////////////////////////////////////////////
1540 /// Initialize globals that require other libraries to be initialized.
1541 /// This is called from TGLWidget creation function.
1542 
1544 {
1545  static Bool_t init_done = kFALSE;
1546  if (init_done) return;
1547  init_done = kTRUE;
1548 
1549  fgScreenScalingFactor = gVirtualX->GetOpenGLScalingFactor();
1550 
1551  if (strcmp(gEnv->GetValue("OpenGL.PointLineScalingFactor", "native"), "native") == 0)
1552  {
1553  fgPointLineScalingFactor = fgScreenScalingFactor;
1554  }
1555  else
1556  {
1557  fgPointLineScalingFactor = gEnv->GetValue("OpenGL.PointLineScalingFactor", 1.0);
1558  }
1559 
1560  fgPickingRadius = TMath::Nint(gEnv->GetValue("OpenGL.PickingRadius", 3.0) * TMath::Sqrt(fgScreenScalingFactor));
1561 }
1562 
1563 ////////////////////////////////////////////////////////////////////////////////
1564 ///static: get draw quality
1565 
1567 {
1568  return fgDrawQuality;
1569 }
1570 
1571 ////////////////////////////////////////////////////////////////////////////////
1572 ///static: set draw quality
1573 
1575 {
1576  fgDrawQuality = dq;
1577 }
1578 
1579 ////////////////////////////////////////////////////////////////////////////////
1580 ///static: reset draw quality
1581 
1583 {
1584  fgDrawQuality = fgDefaultDrawQuality;
1585 }
1586 
1587 ////////////////////////////////////////////////////////////////////////////////
1588 ///static: get default draw quality
1589 
1591 {
1592  return fgDefaultDrawQuality;
1593 }
1594 
1595 ////////////////////////////////////////////////////////////////////////////////
1596 ///static: set default draw quality
1597 
1599 {
1600  fgDefaultDrawQuality = dq;
1601 }
1602 
1603 ////////////////////////////////////////////////////////////////////////////////
1604 /// Check current GL error state, outputting details via ROOT
1605 /// Error method if one
1606 
1607 Int_t TGLUtil::CheckError(const char * loc)
1608 {
1609  GLenum errCode;
1610  const GLubyte *errString;
1611 
1612  if ((errCode = glGetError()) != GL_NO_ERROR) {
1613  errString = gluErrorString(errCode);
1614  if (loc) {
1615  Error(loc, "GL Error %s", (const char *)errString);
1616  } else {
1617  Error("TGLUtil::CheckError", "GL Error %s", (const char *)errString);
1618  }
1619  }
1620  return errCode;
1621 }
1622 
1623 /******************************************************************************/
1624 // Color wrapping functions
1625 /******************************************************************************/
1626 
1627 ////////////////////////////////////////////////////////////////////////////////
1628 /// Prevent further color changes.
1629 
1631 {
1632  return ++fgColorLockCount;
1633 }
1634 
1635 ////////////////////////////////////////////////////////////////////////////////
1636 /// Allow color changes.
1637 
1639 {
1640  if (fgColorLockCount)
1641  --fgColorLockCount;
1642  else
1643  Error("TGLUtil::UnlockColor", "fgColorLockCount already 0.");
1644  return fgColorLockCount;
1645 }
1646 
1647 ////////////////////////////////////////////////////////////////////////////////
1648 /// Returns true if color lock-count is greater than 0.
1649 
1651 {
1652  return fgColorLockCount > 0;
1653 }
1654 
1655 ////////////////////////////////////////////////////////////////////////////////
1656 /// Set color from TGLColor.
1657 
1658 void TGLUtil::Color(const TGLColor& color)
1659 {
1660  if (fgColorLockCount == 0) glColor4ubv(color.CArr());
1661 }
1662 
1663 ////////////////////////////////////////////////////////////////////////////////
1664 /// Set color from TGLColor and alpha value.
1665 
1666 void TGLUtil::ColorAlpha(const TGLColor& color, UChar_t alpha)
1667 {
1668  if (fgColorLockCount == 0)
1669  {
1670  glColor4ub(color.GetRed(), color.GetGreen(), color.GetBlue(), alpha);
1671  }
1672 }
1673 
1674 ////////////////////////////////////////////////////////////////////////////////
1675 /// Set color from TGLColor and alpha value.
1676 
1677 void TGLUtil::ColorAlpha(const TGLColor& color, Float_t alpha)
1678 {
1679  if (fgColorLockCount == 0)
1680  {
1681  glColor4ub(color.GetRed(), color.GetGreen(), color.GetBlue(), (UChar_t)(255*alpha));
1682  }
1683 }
1684 
1685 ////////////////////////////////////////////////////////////////////////////////
1686 /// Set color from color_index and GL-style alpha (default 1).
1687 
1688 void TGLUtil::ColorAlpha(Color_t color_index, Float_t alpha)
1689 {
1690  if (fgColorLockCount == 0) {
1691  if (color_index < 0)
1692  color_index = 1;
1693  TColor* c = gROOT->GetColor(color_index);
1694  if (c)
1695  glColor4f(c->GetRed(), c->GetGreen(), c->GetBlue(), alpha);
1696  }
1697 }
1698 
1699 ////////////////////////////////////////////////////////////////////////////////
1700 /// Set color from color_index and ROOT-style transparency (default 0).
1701 
1702 void TGLUtil::ColorTransparency(Color_t color_index, Char_t transparency)
1703 {
1704  if (fgColorLockCount == 0) {
1705  if (color_index < 0)
1706  color_index = 1;
1707  TColor* c = gROOT->GetColor(color_index);
1708  if (c)
1709  glColor4f(c->GetRed(), c->GetGreen(), c->GetBlue(), 1.0f - 0.01f*transparency);
1710  }
1711 }
1712 
1713 ////////////////////////////////////////////////////////////////////////////////
1714 /// Wrapper for glColor3ub.
1715 
1717 {
1718  if (fgColorLockCount == 0) glColor3ub(r, g, b);
1719 }
1720 
1721 ////////////////////////////////////////////////////////////////////////////////
1722 /// Wrapper for glColor4ub.
1723 
1725 {
1726  if (fgColorLockCount == 0) glColor4ub(r, g, b, a);
1727 }
1728 
1729 ////////////////////////////////////////////////////////////////////////////////
1730 /// Wrapper for glColor3ubv.
1731 
1732 void TGLUtil::Color3ubv(const UChar_t* rgb)
1733 {
1734  if (fgColorLockCount == 0) glColor3ubv(rgb);
1735 }
1736 
1737 ////////////////////////////////////////////////////////////////////////////////
1738 /// Wrapper for glColor4ubv.
1739 
1740 void TGLUtil::Color4ubv(const UChar_t* rgba)
1741 {
1742  if (fgColorLockCount == 0) glColor4ubv(rgba);
1743 }
1744 
1745 ////////////////////////////////////////////////////////////////////////////////
1746 /// Wrapper for glColor3f.
1747 
1749 {
1750  if (fgColorLockCount == 0) glColor3f(r, g, b);
1751 }
1752 
1753 ////////////////////////////////////////////////////////////////////////////////
1754 /// Wrapper for glColor4f.
1755 
1757 {
1758  if (fgColorLockCount == 0) glColor4f(r, g, b, a);
1759 }
1760 
1761 ////////////////////////////////////////////////////////////////////////////////
1762 /// Wrapper for glColor3fv.
1763 
1764 void TGLUtil::Color3fv(const Float_t* rgb)
1765 {
1766  if (fgColorLockCount == 0) glColor3fv(rgb);
1767 }
1768 
1769 ////////////////////////////////////////////////////////////////////////////////
1770 /// Wrapper for glColor4fv.
1771 
1772 void TGLUtil::Color4fv(const Float_t* rgba)
1773 {
1774  if (fgColorLockCount == 0) glColor4fv(rgba);
1775 }
1776 
1777 /******************************************************************************/
1778 // Coordinate conversion and extra scaling (needed for osx retina)
1779 /******************************************************************************/
1780 
1781 ////////////////////////////////////////////////////////////////////////////////
1782 /// Convert from point/screen coordinates to GL viewport coordinates.
1783 
1785 {
1786  if (fgScreenScalingFactor != 1.0)
1787  {
1788  x = TMath::Nint(x * fgScreenScalingFactor);
1789  y = TMath::Nint(y * fgScreenScalingFactor);
1790  }
1791 }
1792 
1793 ////////////////////////////////////////////////////////////////////////////////
1794 /// Convert from point/screen coordinates to GL viewport coordinates.
1795 
1797 {
1798  if (fgScreenScalingFactor != 1.0)
1799  {
1800  x = TMath::Nint(x * fgScreenScalingFactor);
1801  y = TMath::Nint(y * fgScreenScalingFactor);
1802  w = TMath::Nint(w * fgScreenScalingFactor);
1803  h = TMath::Nint(h * fgScreenScalingFactor);
1804  }
1805 }
1806 
1807 ////////////////////////////////////////////////////////////////////////////////
1808 /// Returns scaling factor between screen points and GL viewport pixels.
1809 /// This is what is returned by gVirtualX->GetOpenGLScalingFactor() but is
1810 /// cached here to avoid a virtual function call as it is used quite often in
1811 /// TGLPhysical shape when drawing the selection highlight.
1812 
1814 {
1815  return fgScreenScalingFactor;
1816 }
1817 
1818 ////////////////////////////////////////////////////////////////////////////////
1819 /// Return extra scaling factor for points and lines.
1820 /// By default this is set to the same value as ScreenScalingFactor to keep
1821 /// the same appearance. To override use rootrc entry, e.g.:
1822 /// OpenGL.PointLineScalingFactor: 1.0
1823 
1825 {
1826  return fgPointLineScalingFactor;
1827 }
1828 
1829 ////////////////////////////////////////////////////////////////////////////////
1830 /// Returns picking radius.
1831 
1833 {
1834  return fgPickingRadius;
1835 }
1836 
1837 /******************************************************************************/
1838 // Control for scaling of point-size and line-width.
1839 /******************************************************************************/
1840 
1841 ////////////////////////////////////////////////////////////////////////////////
1842 /// Get global point-size scale.
1843 
1845 {
1846  return fgPointSizeScale;
1847 }
1848 
1849 ////////////////////////////////////////////////////////////////////////////////
1850 /// Set global point-size scale.
1851 
1853 {
1854  fgPointSizeScale = scale;
1855 }
1856 
1857 ////////////////////////////////////////////////////////////////////////////////
1858 /// Returns global line-width scale.
1859 
1861 {
1862  return fgLineWidthScale;
1863 }
1864 
1865 ////////////////////////////////////////////////////////////////////////////////
1866 /// Set global line-width scale.
1867 
1869 {
1870  fgLineWidthScale = scale;
1871 }
1872 
1873 ////////////////////////////////////////////////////////////////////////////////
1874 /// Set the point-size, taking the global scaling into account.
1875 /// Wrapper for glPointSize.
1876 
1877 void TGLUtil::PointSize(Float_t point_size)
1878 {
1879  fgPointSize = point_size * fgPointSizeScale * fgPointLineScalingFactor;
1880  glPointSize(fgPointSize);
1881 }
1882 
1883 ////////////////////////////////////////////////////////////////////////////////
1884 /// Set the line-width, taking the global scaling into account.
1885 /// Wrapper for glLineWidth.
1886 
1887 void TGLUtil::LineWidth(Float_t line_width)
1888 {
1889  fgLineWidth = line_width * fgLineWidthScale * fgPointLineScalingFactor;
1890  glLineWidth(fgLineWidth);
1891 }
1892 
1893 ////////////////////////////////////////////////////////////////////////////////
1894 /// Get the point-size, taking the global scaling into account.
1895 
1897 {
1898  return fgPointSize;
1899 }
1900 
1901 ////////////////////////////////////////////////////////////////////////////////
1902 /// Get the line-width, taking the global scaling into account.
1903 
1905 {
1906  return fgLineWidth;
1907 }
1908 
1909 /******************************************************************************/
1910 // Rendering of polymarkers and lines from logical-shapes.
1911 /******************************************************************************/
1912 
1914 {
1915  // Extend pick region for large point-sizes or line-widths.
1916 
1917  glMatrixMode(GL_PROJECTION);
1918  glPushMatrix();
1919  Float_t pm[16];
1920  glGetFloatv(GL_PROJECTION_MATRIX, pm);
1921  for (Int_t i=0; i<=12; i+=4) {
1922  pm[i] *= scale; pm[i+1] *= scale;
1923  }
1924  glLoadMatrixf(pm);
1925  glMatrixMode(GL_MODELVIEW);
1926 }
1927 
1929 {
1930  // End extension of the pick region.
1931 
1932  glMatrixMode(GL_PROJECTION);
1933  glPopMatrix();
1934  glMatrixMode(GL_MODELVIEW);
1935 }
1936 
1937 ////////////////////////////////////////////////////////////////////////////////
1938 /// Render polymarkers at points specified by p-array.
1939 /// Supports point and cross-like styles.
1940 
1941 void TGLUtil::RenderPolyMarkers(const TAttMarker& marker, Char_t transp,
1942  Float_t* p, Int_t n,
1943  Int_t pick_radius, Bool_t selection,
1944  Bool_t sec_selection)
1945 {
1946  if (n == 0) return;
1947 
1948  glPushAttrib(GL_ENABLE_BIT | GL_POINT_BIT | GL_LINE_BIT);
1949 
1950  glDisable(GL_LIGHTING);
1951  TGLUtil::ColorTransparency(marker.GetMarkerColor(), transp);
1952 
1953  Int_t s = marker.GetMarkerStyle();
1954  if (s == 2 || s == 3 || s == 5 || s == 28)
1955  RenderCrosses(marker, p, n, sec_selection);
1956  else
1957  RenderPoints(marker, p, n, pick_radius, selection, sec_selection);
1958 
1959  glPopAttrib();
1960 }
1961 
1962 ////////////////////////////////////////////////////////////////////////////////
1963 /// Render polymarkers at points specified by p-array.
1964 /// Supports point and cross-like styles.
1965 /// Color is set externally. Lighting is disabled externally.
1966 
1967 void TGLUtil::RenderPolyMarkers(const TAttMarker &marker, const std::vector<Double_t> &points,
1968  Double_t dX, Double_t dY, Double_t dZ)
1969 {
1970  const Int_t s = marker.GetMarkerStyle();
1971  if (s == 2 || s == 3 || s == 5 || s == 28)
1972  RenderCrosses(marker, points, dX, dY, dZ);
1973  else
1974  RenderPoints(marker, points);
1975 }
1976 
1977 ////////////////////////////////////////////////////////////////////////////////
1978 /// Render markers as circular or square points.
1979 /// Color is never changed.
1980 
1982  Float_t* op, Int_t n,
1983  Int_t pick_radius, Bool_t selection,
1984  Bool_t sec_selection)
1985 {
1986  Int_t style = marker.GetMarkerStyle();
1987  Float_t size = 5*marker.GetMarkerSize();
1988  if (style == 4 || style == 20 || style == 24)
1989  {
1990  glEnable(GL_POINT_SMOOTH);
1991  if (style == 4 || style == 24) {
1992  glEnable(GL_BLEND);
1993  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1994  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
1995  }
1996  }
1997  else
1998  {
1999  glDisable(GL_POINT_SMOOTH);
2000  if (style == 1) size = 1;
2001  else if (style == 6) size = 2;
2002  else if (style == 7) size = 3;
2003  }
2004  TGLUtil::PointSize(size);
2005 
2006  // During selection extend picking region for large point-sizes.
2007  Bool_t changePM = selection && PointSize() > pick_radius;
2008  if (changePM)
2009  BeginExtendPickRegion((Float_t) pick_radius / PointSize());
2010 
2011  Float_t* p = op;
2012  if (sec_selection)
2013  {
2014  glPushName(0);
2015  for (Int_t i=0; i<n; ++i, p+=3)
2016  {
2017  glLoadName(i);
2018  glBegin(GL_POINTS);
2019  glVertex3fv(p);
2020  glEnd();
2021  }
2022  glPopName();
2023  }
2024  else
2025  {
2026  glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
2027  glVertexPointer(3, GL_FLOAT, 0, p);
2028  glEnableClientState(GL_VERTEX_ARRAY);
2029  { // Circumvent bug in ATI's linux drivers.
2030  Int_t nleft = n;
2031  Int_t ndone = 0;
2032  const Int_t maxChunk = 8192;
2033  while (nleft > maxChunk)
2034  {
2035  glDrawArrays(GL_POINTS, ndone, maxChunk);
2036  nleft -= maxChunk;
2037  ndone += maxChunk;
2038  }
2039  glDrawArrays(GL_POINTS, ndone, nleft);
2040  }
2041  glPopClientAttrib();
2042  }
2043 
2044  if (changePM)
2045  EndExtendPickRegion();
2046 }
2047 
2048 ////////////////////////////////////////////////////////////////////////////////
2049 /// Render markers as circular or square points.
2050 /// Color is never changed.
2051 
2052 void TGLUtil::RenderPoints(const TAttMarker& marker, const std::vector<Double_t> &points)
2053 {
2054  const Int_t style = marker.GetMarkerStyle();
2055  Float_t size = 5 * marker.GetMarkerSize();
2056 
2057  if (style == 4 || style == 20 || style == 24)
2058  {
2059  glEnable(GL_POINT_SMOOTH);
2060  if (style == 4 || style == 24) {
2061  glEnable(GL_BLEND);
2062  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2063  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
2064  }
2065  }
2066  else
2067  {
2068  glDisable(GL_POINT_SMOOTH);
2069  if (style == 1) size = 1;
2070  else if (style == 6) size = 2;
2071  else if (style == 7) size = 3;
2072  }
2073 
2074  glPointSize(size);
2075 
2076  glVertexPointer(3, GL_DOUBLE, 0, &points[0]);
2077  glEnableClientState(GL_VERTEX_ARRAY);
2078 
2079  // Circumvent bug in ATI's linux drivers.
2080  Int_t nleft = points.size() / 3;
2081  Int_t ndone = 0;
2082  const Int_t maxChunk = 8192;
2083  while (nleft > maxChunk)
2084  {
2085  glDrawArrays(GL_POINTS, ndone, maxChunk);
2086  nleft -= maxChunk;
2087  ndone += maxChunk;
2088  }
2089 
2090  if (nleft > 0)
2091  glDrawArrays(GL_POINTS, ndone, nleft);
2092 
2093  glDisableClientState(GL_VERTEX_ARRAY);
2094  glPointSize(1.f);
2095 }
2096 
2097 ////////////////////////////////////////////////////////////////////////////////
2098 /// Render markers as crosses.
2099 /// Color is never changed.
2100 
2102  Float_t* op, Int_t n,
2103  Bool_t sec_selection)
2104 {
2105  if (marker.GetMarkerStyle() == 28)
2106  {
2107  glEnable(GL_BLEND);
2108  glEnable(GL_LINE_SMOOTH);
2109  TGLUtil::LineWidth(2);
2110  }
2111  else
2112  {
2113  glDisable(GL_LINE_SMOOTH);
2114  TGLUtil::LineWidth(1);
2115  }
2116 
2117  // cross dim
2118  const Float_t d = 2*marker.GetMarkerSize();
2119  Float_t* p = op;
2120  if (sec_selection)
2121  {
2122  glPushName(0);
2123  for (Int_t i=0; i<n; ++i, p+=3)
2124  {
2125  glLoadName(i);
2126  glBegin(GL_LINES);
2127  glVertex3f(p[0]-d, p[1], p[2]); glVertex3f(p[0]+d, p[1], p[2]);
2128  glVertex3f(p[0], p[1]-d, p[2]); glVertex3f(p[0], p[1]+d, p[2]);
2129  glVertex3f(p[0], p[1], p[2]-d); glVertex3f(p[0], p[1], p[2]+d);
2130  glEnd();
2131  }
2132  glPopName();
2133  }
2134  else
2135  {
2136  glBegin(GL_LINES);
2137  for (Int_t i=0; i<n; ++i, p+=3)
2138  {
2139  glVertex3f(p[0]-d, p[1], p[2]); glVertex3f(p[0]+d, p[1], p[2]);
2140  glVertex3f(p[0], p[1]-d, p[2]); glVertex3f(p[0], p[1]+d, p[2]);
2141  glVertex3f(p[0], p[1], p[2]-d); glVertex3f(p[0], p[1], p[2]+d);
2142  }
2143  glEnd();
2144  }
2145 
2146  // Anti-flickering -- when crosses get too small they
2147  // appear / disappear randomly.
2148  {
2149  glDisable(GL_POINT_SMOOTH);
2150  TGLUtil::PointSize(1);
2151 
2152  glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
2153  glVertexPointer(3, GL_FLOAT, 0, op);
2154  glEnableClientState(GL_VERTEX_ARRAY);
2155  { // Circumvent bug in ATI's linux drivers.
2156  Int_t nleft = n;
2157  Int_t ndone = 0;
2158  const Int_t maxChunk = 8192;
2159  while (nleft > maxChunk)
2160  {
2161  glDrawArrays(GL_POINTS, ndone, maxChunk);
2162  nleft -= maxChunk;
2163  ndone += maxChunk;
2164  }
2165  glDrawArrays(GL_POINTS, ndone, nleft);
2166  }
2167  glPopClientAttrib();
2168  }
2169 }
2170 
2171 ////////////////////////////////////////////////////////////////////////////////
2172 /// Render markers as crosses.
2173 /// Color is never changed.
2174 
2175 void TGLUtil::RenderCrosses(const TAttMarker& marker, const std::vector<Double_t> &points,
2176  Double_t dX, Double_t dY, Double_t dZ)
2177 {
2178  if (marker.GetMarkerStyle() == 28)
2179  {
2180  glEnable(GL_BLEND);
2181  glEnable(GL_LINE_SMOOTH);
2182  glLineWidth(2.f);
2183  }
2184  else
2185  {
2186  glDisable(GL_LINE_SMOOTH);
2187  glLineWidth(1.f);
2188  }
2189 
2190  typedef std::vector<Double_t>::size_type size_type;
2191 
2192  glBegin(GL_LINES);
2193 
2194  for (size_type i = 0; i < points.size(); i += 3) {
2195  const Double_t *p = &points[i];
2196  glVertex3f(p[0] - dX, p[1], p[2]); glVertex3f(p[0] + dX, p[1], p[2]);
2197  glVertex3f(p[0], p[1] - dY, p[2]); glVertex3f(p[0], p[1] + dY, p[2]);
2198  glVertex3f(p[0], p[1], p[2] - dZ); glVertex3f(p[0], p[1], p[2] + dZ);
2199  }
2200 
2201  glEnd();
2202 
2203  if (marker.GetMarkerStyle() == 28) {
2204  glDisable(GL_LINE_SMOOTH);
2205  glDisable(GL_BLEND);
2206  glLineWidth(1.f);
2207  }
2208 }
2209 
2210 ////////////////////////////////////////////////////////////////////////////////
2211 /// Render poly-line as specified by the p-array.
2212 
2213 void TGLUtil::RenderPolyLine(const TAttLine& aline, Char_t transp,
2214  Float_t* p, Int_t n,
2215  Int_t pick_radius, Bool_t selection)
2216 {
2217  if (n == 0) return;
2218 
2219  BeginAttLine(aline, transp, pick_radius, selection);
2220 
2221  Float_t* tp = p;
2222  glBegin(GL_LINE_STRIP);
2223  for (Int_t i=0; i<n; ++i, tp+=3)
2224  glVertex3fv(tp);
2225  glEnd();
2226 
2227  EndAttLine(pick_radius, selection);
2228 }
2229 
2230 ////////////////////////////////////////////////////////////////////////////////
2231 /// Setup drawing parameters according to passed TAttLine.
2232 
2233 void TGLUtil::BeginAttLine(const TAttLine& aline, Char_t transp,
2234  Int_t pick_radius, Bool_t selection)
2235 {
2236  glPushAttrib(GL_ENABLE_BIT | GL_LINE_BIT);
2237 
2238  glDisable(GL_LIGHTING);
2239  TGLUtil::ColorTransparency(aline.GetLineColor(), transp);
2241  if (aline.GetLineStyle() > 1)
2242  {
2243  // Int_t fac = 1;
2244  UShort_t pat = 0xffff;
2245  switch (aline.GetLineStyle()) {
2246  case 2: pat = 0x3333; break;
2247  case 3: pat = 0x5555; break;
2248  case 4: pat = 0xf040; break;
2249  case 5: pat = 0xf4f4; break;
2250  case 6: pat = 0xf111; break;
2251  case 7: pat = 0xf0f0; break;
2252  case 8: pat = 0xff11; break;
2253  case 9: pat = 0x3fff; break;
2254  case 10: pat = 0x08ff; /* fac = 2; */ break;
2255  }
2256 
2257  glLineStipple(1, pat);
2258  glEnable(GL_LINE_STIPPLE);
2259  }
2260 
2261  // During selection extend picking region for large line-widths.
2262  if (selection && TGLUtil::LineWidth() > pick_radius)
2263  BeginExtendPickRegion((Float_t) pick_radius / TGLUtil::LineWidth());
2264 }
2265 
2266 ////////////////////////////////////////////////////////////////////////////////
2267 /// Restore previous line drawing state.
2268 
2269 void TGLUtil::EndAttLine(Int_t pick_radius, Bool_t selection)
2270 {
2271  if (selection && TGLUtil::LineWidth() > pick_radius)
2272  EndExtendPickRegion();
2273 
2274  glPopAttrib();
2275 }
2276 
2277 /******************************************************************************/
2278 // Rendering atoms used by TGLViewer / TGScene.
2279 /******************************************************************************/
2280 
2281 ////////////////////////////////////////////////////////////////////////////////
2282 /// Set basic draw colors from 4 component 'rgba'
2283 /// Used by other TGLUtil drawing routines
2284 ///
2285 /// Sets basic (unlit) color - glColor
2286 /// and also GL materials (see OpenGL docs) thus:
2287 ///
2288 /// diffuse : rgba
2289 /// ambient : 0.0 0.0 0.0 1.0
2290 /// specular : 0.6 0.6 0.6 1.0
2291 /// emission : rgba/4.0
2292 /// shininess: 60.0
2293 ///
2294 /// emission is set so objects with no lights (but lighting still enabled)
2295 /// are partially visible
2296 
2297 void TGLUtil::SetDrawColors(const UChar_t rgbai[4])
2298 {
2299 
2300  // Util function to setup GL color for both unlit and lit material
2301  Float_t rgba[4] = {rgbai[0]/255.f, rgbai[1]/255.f, rgbai[2]/255.f, rgbai[3]/255.f};
2302  Float_t ambient[4] = {0.0, 0.0, 0.0, 1.0};
2303  Float_t specular[4] = {0.6, 0.6, 0.6, 1.0};
2304  Float_t emission[4] = {rgba[0]/4.f, rgba[1]/4.f, rgba[2]/4.f, rgba[3]};
2305 
2306  glColor4fv(rgba);
2307  glMaterialfv(GL_FRONT, GL_DIFFUSE, rgba);
2308  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
2309  glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
2310  glMaterialfv(GL_FRONT, GL_EMISSION, emission);
2311  glMaterialf(GL_FRONT, GL_SHININESS, 60.0);
2312 }
2313 
2314 ////////////////////////////////////////////////////////////////////////////////
2315 /// Draw sphere, centered on vertex 'position', with radius 'radius',
2316 /// color 'rgba'
2317 
2318 void TGLUtil::DrawSphere(const TGLVertex3 & position, Double_t radius,
2319  const UChar_t rgba[4])
2320 {
2321  static TGLQuadric quad;
2322  SetDrawColors(rgba);
2323  glPushMatrix();
2324  glTranslated(position.X(), position.Y(), position.Z());
2325  gluSphere(quad.Get(), radius, fgDrawQuality, fgDrawQuality);
2326  glPopMatrix();
2327 }
2328 
2329 ////////////////////////////////////////////////////////////////////////////////
2330 /// Draw thick line (tube) defined by 'line', with head at end shape
2331 /// 'head' - box/arrow/none, (head) size 'size', color 'rgba'
2332 
2334  const UChar_t rgba[4])
2335 {
2336  DrawLine(line.Start(), line.Vector(), head, size, rgba);
2337 }
2338 
2339 ////////////////////////////////////////////////////////////////////////////////
2340 /// Draw thick line (tube) running from 'start', length 'vector',
2341 /// with head at end of shape 'head' - box/arrow/none,
2342 /// (head) size 'size', color 'rgba'
2343 
2344 void TGLUtil::DrawLine(const TGLVertex3 & start, const TGLVector3 & vector,
2345  ELineHeadShape head, Double_t size, const UChar_t rgba[4])
2346 {
2347  static TGLQuadric quad;
2348 
2349  // Draw 3D line (tube) with optional head shape
2350  SetDrawColors(rgba);
2351  glPushMatrix();
2352  TGLMatrix local(start, vector);
2353  glMultMatrixd(local.CArr());
2354 
2355  Double_t headHeight=0;
2356  if (head == kLineHeadNone) {
2357  headHeight = 0.0;
2358  } else if (head == kLineHeadArrow) {
2359  headHeight = size*2.0;
2360  } else if (head == kLineHeadBox) {
2361  headHeight = size*1.4;
2362  }
2363 
2364  // Line (tube) component
2365  gluCylinder(quad.Get(), 0.25*size, 0.25*size, vector.Mag() - headHeight, fgDrawQuality, 1);
2366  gluQuadricOrientation(quad.Get(), (GLenum)GLU_INSIDE);
2367  gluDisk(quad.Get(), 0.0, 0.25*size, fgDrawQuality, 1);
2368 
2369  glTranslated(0.0, 0.0, vector.Mag() - headHeight); // Shift down local Z to end of line
2370 
2371  if (head == kLineHeadNone) {
2372  // Cap end of line
2373  gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
2374  gluDisk(quad.Get(), 0.0, size/4.0, fgDrawQuality, 1);
2375  }
2376  else if (head == kLineHeadArrow) {
2377  // Arrow base / end line cap
2378  gluDisk(quad.Get(), 0.0, size, fgDrawQuality, 1);
2379  // Arrow cone
2380  gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
2381  gluCylinder(quad.Get(), size, 0.0, headHeight, fgDrawQuality, 1);
2382  } else if (head == kLineHeadBox) {
2383  // Box
2384  // TODO: Drawing box should be simpler - maybe make
2385  // a static helper which BB + others use.
2386  // Single face tesselation - ugly lighting
2387  gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
2388  TGLBoundingBox box(TGLVertex3(-size*.7, -size*.7, 0.0),
2389  TGLVertex3(size*.7, size*.7, headHeight));
2390  box.Draw(kTRUE);
2391  }
2392  glPopMatrix();
2393 }
2394 
2395 ////////////////////////////////////////////////////////////////////////////////
2396 /// Draw ring, centered on 'center', lying on plane defined by 'center' & 'normal'
2397 /// of outer radius 'radius', color 'rgba'
2398 
2399 void TGLUtil::DrawRing(const TGLVertex3 & center, const TGLVector3 & normal,
2400  Double_t radius, const UChar_t rgba[4])
2401 {
2402  static TGLQuadric quad;
2403 
2404  // Draw a ring, round vertex 'center', lying on plane defined by 'normal' vector
2405  // Radius defines the outer radius
2406  TGLUtil::SetDrawColors(rgba);
2407 
2408  Double_t outer = radius;
2409  Double_t width = radius*0.05;
2410  Double_t inner = outer - width;
2411 
2412  // Shift into local system, looking down 'normal' vector, origin at center
2413  glPushMatrix();
2414  TGLMatrix local(center, normal);
2415  glMultMatrixd(local.CArr());
2416 
2417  // Shift half width so rings centered over center vertex
2418  glTranslated(0.0, 0.0, -width/2.0);
2419 
2420  // Inner and outer faces
2421  gluCylinder(quad.Get(), inner, inner, width, fgDrawQuality, 1);
2422  gluCylinder(quad.Get(), outer, outer, width, fgDrawQuality, 1);
2423 
2424  // Top/bottom
2425  gluQuadricOrientation(quad.Get(), (GLenum)GLU_INSIDE);
2426  gluDisk(quad.Get(), inner, outer, fgDrawQuality, 1);
2427  glTranslated(0.0, 0.0, width);
2428  gluQuadricOrientation(quad.Get(), (GLenum)GLU_OUTSIDE);
2429  gluDisk(quad.Get(), inner, outer, fgDrawQuality, 1);
2430 
2431  glPopMatrix();
2432 }
2433 
2434 /**************************************************************************/
2435 
2436 ////////////////////////////////////////////////////////////////////////////////
2437 /// Draw a sphere- marker on world-coordinate 'pos' with pixel
2438 /// radius 'radius'. Color argument is optional.
2439 
2441  const TGLVertex3 & pos,
2442  Float_t radius,
2443  const UChar_t * rgba)
2444 {
2445  static const UChar_t defColor[4] = { 250, 110, 0, 255 }; // Orange
2446 
2447  radius = camera.ViewportDeltaToWorld(pos, radius, radius).Mag();
2448  DrawSphere(pos, radius, rgba ? rgba : defColor);
2449 
2450 }
2451 
2452 ////////////////////////////////////////////////////////////////////////////////
2453 /// Draw simple xyz-axes for given bounding-box.
2454 
2456  const TGLBoundingBox & bbox,
2457  Int_t axesType)
2458 {
2459  if (axesType == kAxesNone)
2460  return;
2461 
2462  static const UChar_t axesColors[][4] = {
2463  {128, 0, 0, 255}, // -ive X axis light red
2464  {255, 0, 0, 255}, // +ive X axis deep red
2465  { 0, 128, 0, 255}, // -ive Y axis light green
2466  { 0, 255, 0, 255}, // +ive Y axis deep green
2467  { 0, 0, 128, 255}, // -ive Z axis light blue
2468  { 0, 0, 255, 255} // +ive Z axis deep blue
2469  };
2470 
2471  static const UChar_t xyz[][8] = {
2472  {0x44, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0x44},
2473  {0x10, 0x10, 0x10, 0x10, 0x10, 0x28, 0x44, 0x44},
2474  {0x7c, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x7c}
2475  };
2476 
2477  // Axes draw at fixed screen size - back project to world
2478  TGLVector3 pixelVector = camera.ViewportDeltaToWorld(bbox.Center(), 1, 1);
2479  Double_t pixelSize = pixelVector.Mag();
2480 
2481  // Find x/y/z min/max values
2482  Double_t min[3] = { bbox.XMin(), bbox.YMin(), bbox.ZMin() };
2483  Double_t max[3] = { bbox.XMax(), bbox.YMax(), bbox.ZMax() };
2484 
2485  for (UInt_t i = 0; i < 3; i++) {
2486  TGLVertex3 start;
2487  TGLVector3 vector;
2488 
2489  if (axesType == kAxesOrigin) {
2490  // Through origin axes
2491  start[(i+1)%3] = 0.0;
2492  start[(i+2)%3] = 0.0;
2493  } else {
2494  // Side axes
2495  start[(i+1)%3] = min[(i+1)%3];
2496  start[(i+2)%3] = min[(i+2)%3];
2497  }
2498  vector[(i+1)%3] = 0.0;
2499  vector[(i+2)%3] = 0.0;
2500 
2501  // -ive axis?
2502  if (min[i] < 0.0) {
2503  // Runs from origin?
2504  if (max[i] > 0.0) {
2505  start[i] = 0.0;
2506  vector[i] = min[i];
2507  } else {
2508  start[i] = max[i];
2509  vector[i] = min[i] - max[i];
2510  }
2511  DrawLine(start, vector, kLineHeadNone, pixelSize*2.5, axesColors[i*2]);
2512  }
2513  // +ive axis?
2514  if (max[i] > 0.0) {
2515  // Runs from origin?
2516  if (min[i] < 0.0) {
2517  start[i] = 0.0;
2518  vector[i] = max[i];
2519  } else {
2520  start[i] = min[i];
2521  vector[i] = max[i] - min[i];
2522  }
2523  DrawLine(start, vector, kLineHeadNone, pixelSize*2.5, axesColors[i*2 + 1]);
2524  }
2525  }
2526 
2527  // Draw origin sphere(s)
2528  if (axesType == kAxesOrigin) {
2529  // Single white origin sphere at 0, 0, 0
2530  DrawSphere(TGLVertex3(0.0, 0.0, 0.0), pixelSize*2.0, fgWhite);
2531  } else {
2532  for (UInt_t j = 0; j < 3; j++) {
2533  if (min[j] <= 0.0 && max[j] >= 0.0) {
2534  TGLVertex3 zero;
2535  zero[j] = 0.0;
2536  zero[(j+1)%3] = min[(j+1)%3];
2537  zero[(j+2)%3] = min[(j+2)%3];
2538  DrawSphere(zero, pixelSize*2.0, axesColors[j*2 + 1]);
2539  }
2540  }
2541  }
2542 
2543  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2544 
2545  // Labels
2546  Double_t padPixels = 25.0;
2547 
2548  glDisable(GL_LIGHTING);
2549  for (UInt_t k = 0; k < 3; k++) {
2550  SetDrawColors(axesColors[k*2+1]);
2551  TGLVertex3 minPos, maxPos;
2552  if (axesType == kAxesOrigin) {
2553  minPos[(k+1)%3] = 0.0;
2554  minPos[(k+2)%3] = 0.0;
2555  } else {
2556  minPos[(k+1)%3] = min[(k+1)%3];
2557  minPos[(k+2)%3] = min[(k+2)%3];
2558  }
2559  maxPos = minPos;
2560  minPos[k] = min[k];
2561  maxPos[k] = max[k];
2562 
2563  TGLVector3 axis = maxPos - minPos;
2564  TGLVector3 axisViewport = camera.WorldDeltaToViewport(minPos, axis);
2565 
2566  // Skip drawing if viewport projection of axis very small - labels will overlap
2567  // Occurs with orthographic cameras
2568  if (axisViewport.Mag() < 1) {
2569  continue;
2570  }
2571 
2572  minPos -= camera.ViewportDeltaToWorld(minPos, padPixels*axisViewport.X()/axisViewport.Mag(),
2573  padPixels*axisViewport.Y()/axisViewport.Mag());
2574  axisViewport = camera.WorldDeltaToViewport(maxPos, -axis);
2575  maxPos -= camera.ViewportDeltaToWorld(maxPos, padPixels*axisViewport.X()/axisViewport.Mag(),
2576  padPixels*axisViewport.Y()/axisViewport.Mag());
2577 
2578  DrawNumber(Form("%.0f", min[k]), minPos, kTRUE); // Min value
2579  DrawNumber(Form("%.0f", max[k]), maxPos, kTRUE); // Max value
2580 
2581  // Axis name beside max value
2582  TGLVertex3 namePos = maxPos -
2583  camera.ViewportDeltaToWorld(maxPos, padPixels*axisViewport.X()/axisViewport.Mag(),
2584  padPixels*axisViewport.Y()/axisViewport.Mag());
2585  glRasterPos3dv(namePos.CArr());
2586  glBitmap(8, 8, 0.0, 4.0, 0.0, 0.0, xyz[k]); // Axis Name
2587  }
2588 }
2589 
2590 ////////////////////////////////////////////////////////////////////////////////
2591 /// Draw number in string 'num' via internal 8x8-pixel bitmap on
2592 /// vertex 'pos'. If 'center' is true, the number is centered on 'pos'.
2593 /// Only numbers, '.', '-' and ' ' are supported.
2594 
2595 void TGLUtil::DrawNumber(const TString & num,
2596  const TGLVertex3 & pos,
2597  Bool_t center)
2598 {
2599  static const UChar_t digits[][8] = {
2600  {0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38},//0
2601  {0x10, 0x10, 0x10, 0x10, 0x10, 0x70, 0x10, 0x10},//1
2602  {0x7c, 0x44, 0x20, 0x18, 0x04, 0x04, 0x44, 0x38},//2
2603  {0x38, 0x44, 0x04, 0x04, 0x18, 0x04, 0x44, 0x38},//3
2604  {0x04, 0x04, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x44},//4
2605  {0x7c, 0x44, 0x04, 0x04, 0x7c, 0x40, 0x40, 0x7c},//5
2606  {0x7c, 0x44, 0x44, 0x44, 0x7c, 0x40, 0x40, 0x7c},//6
2607  {0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x44, 0x7c},//7
2608  {0x38, 0x44, 0x44, 0x44, 0x38, 0x44, 0x44, 0x38},//8
2609  {0x7c, 0x44, 0x04, 0x04, 0x7c, 0x44, 0x44, 0x7c},//9
2610  {0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},//.
2611  {0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00},//-
2612  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} //space
2613  };
2614 
2615  Double_t xOffset = 0, yOffset = 0;
2616  if (center)
2617  {
2618  xOffset = 3.5 * num.Length();
2619  yOffset = 4.0;
2620  }
2621 
2622  glRasterPos3dv(pos.CArr());
2623  for (Ssiz_t i = 0, e = num.Length(); i < e; ++i) {
2624  if (num[i] == '.') {
2625  glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[10]);
2626  } else if (num[i] == '-') {
2627  glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[11]);
2628  } else if (num[i] == ' ') {
2629  glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[12]);
2630  } else if (num[i] >= '0' && num[i] <= '9') {
2631  glBitmap(8, 8, xOffset, yOffset, 7.0, 0.0, digits[num[i] - '0']);
2632  }
2633  }
2634 }
2635 
2636 
2637 /**************************************************************************/
2638 /**************************************************************************/
2639 
2640 ////////////////////////////////////////////////////////////////////////////////
2641 /// Constructor - change state only if necessary.
2642 
2644  fWhat(what)
2645 {
2646  fState = glIsEnabled(fWhat);
2647  fFlip = (fState != state);
2648  if (fFlip)
2649  SetState(state);
2650 }
2651 
2652 ////////////////////////////////////////////////////////////////////////////////
2653 /// Destructor - reset state if changed.
2654 
2656 {
2657  if (fFlip)
2658  SetState(fState);
2659 }
2660 
2661 ////////////////////////////////////////////////////////////////////////////////
2662 
2664 {
2665  if (s)
2666  glEnable(fWhat);
2667  else
2668  glDisable(fWhat);
2669 }
2670 
2671 
2672 ////////////////////////////////////////////////////////////////////////////////
2673 /// Constructor - change state only if necessary.
2674 
2676  fWhat(what)
2677 {
2678  fFlip = ! glIsEnabled(fWhat) && state;
2679  if (fFlip)
2680  glEnable(fWhat);
2681 }
2682 
2683 ////////////////////////////////////////////////////////////////////////////////
2684 /// Destructor - reset state if changed.
2685 
2687 {
2688  if (fFlip)
2689  glDisable(fWhat);
2690 }
2691 
2692 
2693 ////////////////////////////////////////////////////////////////////////////////
2694 
2696  fWhat(what), fState(0), fFlip(kFALSE), fFoo(foo)
2697  {
2698  glGetFloatv(fWhat, &fState);
2699  fFlip = (fState != state);
2700  if (fFlip) fFoo(state);
2701  }
2702 
2703 ////////////////////////////////////////////////////////////////////////////////
2704 
2706  {
2707  if (fFlip) fFoo(fState);
2708  }
2709 
2710 
2711 ////////////////////////////////////////////////////////////////////////////////
2712 /// TGLEnableGuard constructor.
2713 
2715  : fCap(cap)
2716 {
2717  glEnable(GLenum(fCap));
2718 }
2719 
2720 ////////////////////////////////////////////////////////////////////////////////
2721 /// TGLEnableGuard destructor.
2722 
2724 {
2725  glDisable(GLenum(fCap));
2726 }
2727 
2728 ////////////////////////////////////////////////////////////////////////////////
2729 /// TGLDisableGuard constructor.
2730 
2732  : fCap(cap)
2733 {
2734  glDisable(GLenum(fCap));
2735 }
2736 
2737 ////////////////////////////////////////////////////////////////////////////////
2738 /// TGLDisableGuard destructor.
2739 
2741 {
2742  glEnable(GLenum(fCap));
2743 }
2744 
2745 /** \class TGLSelectionBuffer
2746 \ingroup opengl
2747 */
2748 
2750 
2751 ////////////////////////////////////////////////////////////////////////////////
2752 /// TGLSelectionBuffer constructor.
2753 
2755  : fWidth(0), fHeight(0)
2756 {
2757 }
2758 
2759 ////////////////////////////////////////////////////////////////////////////////
2760 /// TGLSelectionBuffer destructor.
2761 
2763 {
2764 }
2765 
2766 ////////////////////////////////////////////////////////////////////////////////
2767 /// Read color buffer.
2768 
2770 {
2771  fWidth = w;
2772  fHeight = h;
2773  fBuffer.resize(w * h * 4);
2774  glPixelStorei(GL_PACK_ALIGNMENT, 1);
2775  glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &fBuffer[0]);
2776 }
2777 
2778 ////////////////////////////////////////////////////////////////////////////////
2779 /// Read color buffer.
2780 
2782 {
2783  fWidth = w;
2784  fHeight = h;
2785  fBuffer.resize(w * h * 4);
2786  glPixelStorei(GL_PACK_ALIGNMENT, 1);
2787  glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &fBuffer[0]);
2788 }
2789 
2790 ////////////////////////////////////////////////////////////////////////////////
2791 /// Get pixel color.
2792 
2794 {
2795  if (px < 0)
2796  px = 0;
2797  if (py < 0)
2798  py = 0;
2799 
2800  if (UInt_t(px * fWidth * 4 + py * 4) > fBuffer.size())
2801  return &fBuffer[0];
2802 
2803  return &fBuffer[px * fWidth * 4 + py * 4];
2804 }
2805 
2806 namespace Rgl {
2807 
2808 const Float_t gRedEmission[] = {1.f, 0.f, 0.f, 1.f};
2809 const Float_t gGreenEmission[] = {0.f, 1.f, 0.f, 1.f};
2810 const Float_t gBlueEmission[] = {0.f, 0.f, 1.f, 1.f};
2811 const Float_t gOrangeEmission[] = {1.f, 0.4f, 0.f, 1.f};
2812 const Float_t gWhiteEmission[] = {1.f, 1.f, 1.f, 1.f};
2813 const Float_t gGrayEmission[] = {0.3f,0.3f, 0.3f,1.f};
2814 const Float_t gNullEmission[] = {0.f, 0.f, 0.f, 1.f};
2815 
2816 namespace {
2817  struct RGB_t {
2818  Int_t fRGB[3];
2819  };
2820 
2821  RGB_t gColorTriplets[] = {{{255, 0, 0}},
2822  {{0, 255, 0}},
2823  {{0, 0, 255}},
2824  {{255, 255, 0}},
2825  {{255, 0, 255}},
2826  {{0, 255, 255}},
2827  {{255, 255, 255}}};
2828 
2829  Bool_t operator < (const RGB_t &lhs, const RGB_t &rhs)
2830  {
2831  if (lhs.fRGB[0] < rhs.fRGB[0])
2832  return kTRUE;
2833  else if (lhs.fRGB[0] > rhs.fRGB[0])
2834  return kFALSE;
2835  else if (lhs.fRGB[1] < rhs.fRGB[1])
2836  return kTRUE;
2837  else if (lhs.fRGB[1] > rhs.fRGB[1])
2838  return kFALSE;
2839  else if (lhs.fRGB[2] < rhs.fRGB[2])
2840  return kTRUE;
2841 
2842  return kFALSE;
2843  }
2844 
2845  typedef std::map<Int_t, RGB_t> ColorLookupTable_t;
2846  typedef ColorLookupTable_t::const_iterator CLTCI_t;
2847 
2848  ColorLookupTable_t gObjectIDToColor;
2849 
2850  typedef std::map<RGB_t, Int_t> ObjectLookupTable_t;
2851  typedef ObjectLookupTable_t::const_iterator OLTCI_t;
2852 
2853  ObjectLookupTable_t gColorToObjectID;
2854 }
2855 ////////////////////////////////////////////////////////////////////////////////
2856 ///Object id encoded as rgb triplet.
2857 
2858 void ObjectIDToColor(Int_t objectID, Bool_t highColor)
2859 {
2860  if (!highColor)
2861  glColor3ub(objectID & 0xff, (objectID & 0xff00) >> 8, (objectID & 0xff0000) >> 16);
2862  else {
2863  if (!gObjectIDToColor.size()) {
2864  //Initialize lookup tables.
2865  for (Int_t i = 0, id = 1; i < Int_t(sizeof gColorTriplets / sizeof(RGB_t)); ++i, ++id)
2866  gObjectIDToColor[id] = gColorTriplets[i];
2867  for (Int_t i = 0, id = 1; i < Int_t(sizeof gColorTriplets / sizeof(RGB_t)); ++i, ++id)
2868  gColorToObjectID[gColorTriplets[i]] = id;
2869  }
2870 
2871  CLTCI_t it = gObjectIDToColor.find(objectID);
2872 
2873  if (it != gObjectIDToColor.end())
2874  glColor3ub(it->second.fRGB[0], it->second.fRGB[1], it->second.fRGB[2]);
2875  else {
2876  Error("ObjectIDToColor", "No color for such object ID: %d", objectID);
2877  glColor3ub(0, 0, 0);
2878  }
2879  }
2880 }
2881 
2882 ////////////////////////////////////////////////////////////////////////////////
2883 
2884 Int_t ColorToObjectID(const UChar_t *pixel, Bool_t highColor)
2885 {
2886  if (!highColor)
2887  return pixel[0] | (pixel[1] << 8) | (pixel[2] << 16);
2888  else {
2889  if (!gObjectIDToColor.size())
2890  return 0;
2891 
2892  RGB_t triplet = {{pixel[0], pixel[1], pixel[2]}};
2893  OLTCI_t it = gColorToObjectID.find(triplet);
2894 
2895  if (it != gColorToObjectID.end())
2896  return it->second;
2897  else
2898  return 0;
2899  }
2900 }
2901 
2902 
2903 ////////////////////////////////////////////////////////////////////////////////
2904 ///Draw quad outline.
2905 
2906 void DrawQuadOutline(const TGLVertex3 &v1, const TGLVertex3 &v2,
2907  const TGLVertex3 &v3, const TGLVertex3 &v4)
2908 {
2909  glBegin(GL_LINE_LOOP);
2910  glVertex3dv(v1.CArr());
2911  glVertex3dv(v2.CArr());
2912  glVertex3dv(v3.CArr());
2913  glVertex3dv(v4.CArr());
2914  glEnd();
2915 }
2916 
2917 ////////////////////////////////////////////////////////////////////////////////
2918 ///Draw quad face.
2919 
2920 void DrawQuadFilled(const TGLVertex3 &v0, const TGLVertex3 &v1, const TGLVertex3 &v2,
2921  const TGLVertex3 &v3, const TGLVector3 &normal)
2922 {
2923  glBegin(GL_POLYGON);
2924  glNormal3dv(normal.CArr());
2925  glVertex3dv(v0.CArr());
2926  glVertex3dv(v1.CArr());
2927  glVertex3dv(v2.CArr());
2928  glVertex3dv(v3.CArr());
2929  glEnd();
2930 }
2931 
2932 ////////////////////////////////////////////////////////////////////////////////
2933 ///Draw quad face.
2934 
2935 void DrawQuadFilled(const Double_t *v0, const Double_t *v1, const Double_t *v2, const Double_t *v3,
2936  const Double_t *normal)
2937 {
2938  glBegin(GL_QUADS);
2939  glNormal3dv(normal);
2940  glVertex3dv(v0);
2941  glVertex3dv(v1);
2942  glVertex3dv(v2);
2943  glVertex3dv(v3);
2944  glEnd();
2945 }
2946 
2947 ////////////////////////////////////////////////////////////////////////////////
2948 ///Draws triangle face, each vertex has its own averaged normal
2949 
2950 void DrawSmoothFace(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3,
2951  const TGLVector3 &norm1, const TGLVector3 &norm2, const TGLVector3 &norm3)
2952 {
2953  glBegin(GL_POLYGON);
2954  glNormal3dv(norm1.CArr());
2955  glVertex3dv(v1.CArr());
2956  glNormal3dv(norm2.CArr());
2957  glVertex3dv(v2.CArr());
2958  glNormal3dv(norm3.CArr());
2959  glVertex3dv(v3.CArr());
2960  glEnd();
2961 }
2962 
2963 const Int_t gBoxFrontQuads[][4] = {{0, 1, 2, 3}, {4, 0, 3, 5}, {4, 5, 6, 7}, {7, 6, 2, 1}};
2964 const Double_t gBoxFrontNormals[][3] = {{-1., 0., 0.}, {0., -1., 0.}, {1., 0., 0.}, {0., 1., 0.}};
2965 const Int_t gBoxFrontPlanes[][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};
2966 
2967 const Int_t gBoxBackQuads[][4] = {{7, 1, 2, 6}, {4, 7, 6, 5}, {0, 4, 5, 3}, {0, 3, 2, 1}};
2968 const Double_t gBoxBackNormals[][3] = {{0., -1., 0.}, {-1., 0., 0.}, {0., 1., 0.}, {1., 0., 0.}};
2969 const Int_t gBoxBackPlanes[][2] = {{0, 1}, {3, 0}, {2, 3}, {1, 2}};
2970 
2971 ////////////////////////////////////////////////////////////////////////////////
2972 ///Draws lego's bar as a 3d box
2973 
2974 void DrawBoxFront(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax,
2975  Double_t zMin, Double_t zMax, Int_t fp)
2976 {
2977  if (zMax < zMin)
2978  std::swap(zMax, zMin);
2979 
2980  //Bottom is always drawn.
2981  glBegin(GL_POLYGON);
2982  glNormal3d(0., 0., -1.);
2983  glVertex3d(xMax, yMin, zMin);
2984  glVertex3d(xMin, yMin, zMin);
2985  glVertex3d(xMin, yMax, zMin);
2986  glVertex3d(xMax, yMax, zMin);
2987  glEnd();
2988  //Draw two visible front planes.
2989  const Double_t box[][3] = {{xMin, yMin, zMax}, {xMin, yMax, zMax}, {xMin, yMax, zMin}, {xMin, yMin, zMin},
2990  {xMax, yMin, zMax}, {xMax, yMin, zMin}, {xMax, yMax, zMin}, {xMax, yMax, zMax}};
2991  const Int_t *verts = gBoxFrontQuads[gBoxFrontPlanes[fp][0]];
2992 
2993  glBegin(GL_POLYGON);
2994  glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][0]]);
2995  glVertex3dv(box[verts[0]]);
2996  glVertex3dv(box[verts[1]]);
2997  glVertex3dv(box[verts[2]]);
2998  glVertex3dv(box[verts[3]]);
2999  glEnd();
3000 
3001  verts = gBoxFrontQuads[gBoxFrontPlanes[fp][1]];
3002 
3003  glBegin(GL_POLYGON);
3004  glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][1]]);
3005  glVertex3dv(box[verts[0]]);
3006  glVertex3dv(box[verts[1]]);
3007  glVertex3dv(box[verts[2]]);
3008  glVertex3dv(box[verts[3]]);
3009  glEnd();
3010 
3011  //Top is always drawn.
3012  glBegin(GL_POLYGON);
3013  glNormal3d(0., 0., 1.);
3014  glVertex3d(xMax, yMin, zMax);
3015  glVertex3d(xMax, yMax, zMax);
3016  glVertex3d(xMin, yMax, zMax);
3017  glVertex3d(xMin, yMin, zMax);
3018  glEnd();
3019 }
3020 
3021 ////////////////////////////////////////////////////////////////////////////////
3022 ///Draws lego's bar as a 3d box
3023 
3025  Double_t zMin, Double_t zMax, Int_t fp)
3026 {
3027  if (zMax < zMin)
3028  std::swap(zMax, zMin);
3029 
3030  //The order is: 1) two back planes, 2) bottom plane, 3) two front planes,
3031  //4) top.
3032 
3033  //Bottom is always drawn.
3034  glBegin(GL_POLYGON);
3035  glNormal3d(0., 0., -1.);
3036  glVertex3d(xMax, yMin, zMin);
3037  glVertex3d(xMin, yMin, zMin);
3038  glVertex3d(xMin, yMax, zMin);
3039  glVertex3d(xMax, yMax, zMin);
3040  glEnd();
3041 
3042  const Double_t box[][3] = {{xMin, yMin, zMax}, {xMin, yMax, zMax}, {xMin, yMax, zMin}, {xMin, yMin, zMin},
3043  {xMax, yMin, zMax}, {xMax, yMin, zMin}, {xMax, yMax, zMin}, {xMax, yMax, zMax}};
3044 
3045  //Draw two back planes.
3046  const Int_t *verts = gBoxBackQuads[gBoxBackPlanes[fp][0]];
3047 
3048  glBegin(GL_POLYGON);
3049  glNormal3dv(gBoxBackNormals[gBoxBackPlanes[fp][0]]);
3050  glVertex3dv(box[verts[0]]);
3051  glVertex3dv(box[verts[1]]);
3052  glVertex3dv(box[verts[2]]);
3053  glVertex3dv(box[verts[3]]);
3054  glEnd();
3055 
3056  verts = gBoxBackQuads[gBoxBackPlanes[fp][1]];
3057 
3058  glBegin(GL_POLYGON);
3059  glNormal3dv(gBoxBackNormals[gBoxBackPlanes[fp][1]]);
3060  glVertex3dv(box[verts[0]]);
3061  glVertex3dv(box[verts[1]]);
3062  glVertex3dv(box[verts[2]]);
3063  glVertex3dv(box[verts[3]]);
3064  glEnd();
3065 
3066  //Draw two visible front planes.
3067  verts = gBoxFrontQuads[gBoxFrontPlanes[fp][0]];
3068 
3069  glBegin(GL_POLYGON);
3070  glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][0]]);
3071  glVertex3dv(box[verts[0]]);
3072  glVertex3dv(box[verts[1]]);
3073  glVertex3dv(box[verts[2]]);
3074  glVertex3dv(box[verts[3]]);
3075  glEnd();
3076 
3077  verts = gBoxFrontQuads[gBoxFrontPlanes[fp][1]];
3078 
3079  glBegin(GL_POLYGON);
3080  glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][1]]);
3081  glVertex3dv(box[verts[0]]);
3082  glVertex3dv(box[verts[1]]);
3083  glVertex3dv(box[verts[2]]);
3084  glVertex3dv(box[verts[3]]);
3085  glEnd();
3086 
3087  //Top is always drawn.
3088  glBegin(GL_POLYGON);
3089  glNormal3d(0., 0., 1.);
3090  glVertex3d(xMax, yMin, zMax);
3091  glVertex3d(xMax, yMax, zMax);
3092  glVertex3d(xMin, yMax, zMax);
3093  glVertex3d(xMin, yMin, zMax);
3094  glEnd();
3095 }
3096 
3097 ////////////////////////////////////////////////////////////////////////////////
3098 ///Draws lego's bar as a 3d box
3099 ///LULULULU
3100 
3102  Double_t yMax, Double_t zMin, Double_t zMax,
3103  Double_t texMin, Double_t texMax, Int_t fp)
3104 {
3105  if (zMax < zMin) {
3106  std::swap(zMax, zMin);
3107  std::swap(texMax, texMin);
3108  }
3109 
3110  //Top and bottom are always drawn.
3111  glBegin(GL_POLYGON);
3112  glNormal3d(0., 0., 1.);
3113  glTexCoord1d(texMax);
3114  glVertex3d(xMax, yMin, zMax);
3115  glVertex3d(xMax, yMax, zMax);
3116  glVertex3d(xMin, yMax, zMax);
3117  glVertex3d(xMin, yMin, zMax);
3118  glEnd();
3119 
3120  glBegin(GL_POLYGON);
3121  glTexCoord1d(texMin);
3122  glNormal3d(0., 0., -1.);
3123  glVertex3d(xMax, yMin, zMin);
3124  glVertex3d(xMin, yMin, zMin);
3125  glVertex3d(xMin, yMax, zMin);
3126  glVertex3d(xMax, yMax, zMin);
3127  glEnd();
3128  //Draw two visible front planes.
3129  const Double_t box[][3] = {{xMin, yMin, zMax}, {xMin, yMax, zMax}, {xMin, yMax, zMin}, {xMin, yMin, zMin},
3130  {xMax, yMin, zMax}, {xMax, yMin, zMin}, {xMax, yMax, zMin}, {xMax, yMax, zMax}};
3131 
3132  const Double_t tex[] = {texMax, texMax, texMin, texMin, texMax, texMin, texMin, texMax};
3133  const Int_t *verts = gBoxFrontQuads[gBoxFrontPlanes[fp][0]];
3134 
3135  glBegin(GL_POLYGON);
3136  glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][0]]);
3137  glTexCoord1d(tex[verts[0]]);
3138  glVertex3dv(box[verts[0]]);
3139  glTexCoord1d(tex[verts[1]]);
3140  glVertex3dv(box[verts[1]]);
3141  glTexCoord1d(tex[verts[2]]);
3142  glVertex3dv(box[verts[2]]);
3143  glTexCoord1d(tex[verts[3]]);
3144  glVertex3dv(box[verts[3]]);
3145  glEnd();
3146 
3147  verts = gBoxFrontQuads[gBoxFrontPlanes[fp][1]];
3148 
3149  glBegin(GL_POLYGON);
3150  glNormal3dv(gBoxFrontNormals[gBoxFrontPlanes[fp][1]]);
3151  glTexCoord1d(tex[verts[0]]);
3152  glVertex3dv(box[verts[0]]);
3153  glTexCoord1d(tex[verts[1]]);
3154  glVertex3dv(box[verts[1]]);
3155  glTexCoord1d(tex[verts[2]]);
3156  glVertex3dv(box[verts[2]]);
3157  glTexCoord1d(tex[verts[3]]);
3158  glVertex3dv(box[verts[3]]);
3159  glEnd();
3160 }
3161 
3162 ////////////////////////////////////////////////////////////////////////////////
3163 
3165  const Double_t *rgba1, const Double_t *rgba2)
3166 {
3167  assert(rgba1 != 0 && "DrawBoxWithGradientFill, parameter 'rgba1' is null");
3168  assert(rgba2 != 0 && "DrawBoxWithGradientFill, parameter 'rgba2' is null");
3169 
3170  glBegin(GL_POLYGON);
3171  glColor4dv(rgba1);
3172  glVertex2d(x1, y1);
3173  glVertex2d(x2, y1);
3174  glColor4dv(rgba2);
3175  glVertex2d(x2, y2);
3176  glVertex2d(x1, y2);
3177  glEnd();
3178 }
3179 
3180 ////////////////////////////////////////////////////////////////////////////////
3181 ///TODO: is it possible to use GLdouble to avoid problems with Double_t/GLdouble if they
3182 ///are not the same type?
3183 
3184 void DrawQuadStripWithRadialGradientFill(unsigned nPoints, const Double_t *inner, const Double_t *innerRGBA,
3185  const Double_t *outer, const Double_t *outerRGBA)
3186 {
3187  assert(nPoints != 0 &&
3188  "DrawQuadStripWithRadialGradientFill, invalid number of points");
3189  assert(inner != 0 &&
3190  "DrawQuadStripWithRadialGradientFill, parameter 'inner' is null");
3191  assert(innerRGBA != 0 &&
3192  "DrawQuadStripWithRadialGradientFill, parameter 'innerRGBA' is null");
3193  assert(outer != 0 &&
3194  "DrawQuadStripWithRadialGradientFill, parameter 'outer' is null");
3195  assert(outerRGBA != 0 &&
3196  "DrawQuadStripWithRadialGradientFill, parameter 'outerRGBA' is null");
3197 
3198  glBegin(GL_QUAD_STRIP);
3199  for (UInt_t j = 0; j < nPoints; ++j) {
3200  glColor4dv(innerRGBA);
3201  glVertex2dv(inner + j * 2);
3202  glColor4dv(outerRGBA);
3203  glVertex2dv(outer + j * 2);
3204  }
3205  glEnd();
3206 }
3207 
3208 ////////////////////////////////////////////////////////////////////////////////
3209 ///Cylinder for lego3.
3210 
3211 void DrawCylinder(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin,
3212  Double_t yMax, Double_t zMin, Double_t zMax)
3213 {
3214  GLUquadric *quad = quadric->Get();
3215 
3216  if (quad) {
3217  if (zMin > zMax)
3218  std::swap(zMin, zMax);
3219  const Double_t xCenter = xMin + (xMax - xMin) / 2;
3220  const Double_t yCenter = yMin + (yMax - yMin) / 2;
3221  const Double_t radius = TMath::Min((xMax - xMin) / 2, (yMax - yMin) / 2);
3222 
3223  glPushMatrix();
3224  glTranslated(xCenter, yCenter, zMin);
3225  gluCylinder(quad, radius, radius, zMax - zMin, 40, 1);
3226  glPopMatrix();
3227  glPushMatrix();
3228  glTranslated(xCenter, yCenter, zMax);
3229  gluDisk(quad, 0., radius, 40, 1);
3230  glPopMatrix();
3231  glPushMatrix();
3232  glTranslated(xCenter, yCenter, zMin);
3233  glRotated(180., 0., 1., 0.);
3234  gluDisk(quad, 0., radius, 40, 1);
3235  glPopMatrix();
3236  }
3237 }
3238 
3239 ////////////////////////////////////////////////////////////////////////////////
3240 ///Cylinder for lego3.
3241 
3242 void DrawSphere(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin,
3243  Double_t yMax, Double_t zMin, Double_t zMax)
3244 {
3245  GLUquadric *quad = quadric->Get();
3246 
3247  if (quad) {
3248  const Double_t xCenter = xMin + (xMax - xMin) / 2;
3249  const Double_t yCenter = yMin + (yMax - yMin) / 2;
3250  const Double_t zCenter = zMin + (zMax - zMin) / 2;
3251 
3252  const Double_t radius = TMath::Min((zMax - zMin) / 2,
3253  TMath::Min((xMax - xMin) / 2, (yMax - yMin) / 2));
3254 
3255  glPushMatrix();
3256  glTranslated(xCenter, yCenter, zCenter);
3257  gluSphere(quad, radius, 10, 10);
3258  glPopMatrix();
3259  }
3260 }
3261 
3262 
3263 ////////////////////////////////////////////////////////////////////////////////
3264 
3265 void DrawError(Double_t xMin, Double_t xMax, Double_t yMin,
3266  Double_t yMax, Double_t zMin, Double_t zMax)
3267 {
3268  const Double_t xWid = xMax - xMin;
3269  const Double_t yWid = yMax - yMin;
3270 
3271  glBegin(GL_LINES);
3272  glVertex3d(xMin + xWid / 2, yMin + yWid / 2, zMin);
3273  glVertex3d(xMin + xWid / 2, yMin + yWid / 2, zMax);
3274  glEnd();
3275 
3276  glBegin(GL_LINES);
3277  glVertex3d(xMin + xWid / 2, yMin, zMin);
3278  glVertex3d(xMin + xWid / 2, yMax, zMin);
3279  glEnd();
3280 
3281  glBegin(GL_LINES);
3282  glVertex3d(xMin, yMin + yWid / 2, zMin);
3283  glVertex3d(xMax, yMin + yWid / 2, zMin);
3284  glEnd();
3285 }
3286 
3287 void CylindricalNormal(const Double_t *v, Double_t *normal)
3288 {
3289  const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1]);
3290  if (n > 0.) {
3291  normal[0] = v[0] / n;
3292  normal[1] = v[1] / n;
3293  normal[2] = 0.;
3294  } else {
3295  normal[0] = v[0];
3296  normal[1] = v[1];
3297  normal[2] = 0.;
3298  }
3299 }
3300 
3302 {
3303  const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1]);
3304  if (n > 0.) {
3305  normal[0] = -v[0] / n;
3306  normal[1] = -v[1] / n;
3307  normal[2] = 0.;
3308  } else {
3309  normal[0] = -v[0];
3310  normal[1] = -v[1];
3311  normal[2] = 0.;
3312  }
3313 }
3314 
3315 void DrawTrapezoid(const Double_t ver[][2], Double_t zMin, Double_t zMax, Bool_t color)
3316 {
3317  //In polar coordinates, box became trapezoid.
3318  //Four faces need normal calculations.
3319  if (zMin > zMax)
3320  std::swap(zMin, zMax);
3321  //top
3322  glBegin(GL_POLYGON);
3323  glNormal3d(0., 0., 1.);
3324  glVertex3d(ver[0][0], ver[0][1], zMax);
3325  glVertex3d(ver[1][0], ver[1][1], zMax);
3326  glVertex3d(ver[2][0], ver[2][1], zMax);
3327  glVertex3d(ver[3][0], ver[3][1], zMax);
3328  glEnd();
3329  //bottom
3330  glBegin(GL_POLYGON);
3331  glNormal3d(0., 0., -1.);
3332  glVertex3d(ver[0][0], ver[0][1], zMin);
3333  glVertex3d(ver[3][0], ver[3][1], zMin);
3334  glVertex3d(ver[2][0], ver[2][1], zMin);
3335  glVertex3d(ver[1][0], ver[1][1], zMin);
3336  glEnd();
3337  //
3338 
3339  Double_t trapezoid[][3] = {{ver[0][0], ver[0][1], zMin}, {ver[1][0], ver[1][1], zMin},
3340  {ver[2][0], ver[2][1], zMin}, {ver[3][0], ver[3][1], zMin},
3341  {ver[0][0], ver[0][1], zMax}, {ver[1][0], ver[1][1], zMax},
3342  {ver[2][0], ver[2][1], zMax}, {ver[3][0], ver[3][1], zMax}};
3343  Double_t normal[3] = {0.};
3344  glBegin(GL_POLYGON);
3345  CylindricalNormal(trapezoid[1], normal), glNormal3dv(normal), glVertex3dv(trapezoid[1]);
3346  CylindricalNormal(trapezoid[2], normal), glNormal3dv(normal), glVertex3dv(trapezoid[2]);
3347  CylindricalNormal(trapezoid[6], normal), glNormal3dv(normal), glVertex3dv(trapezoid[6]);
3348  CylindricalNormal(trapezoid[5], normal), glNormal3dv(normal), glVertex3dv(trapezoid[5]);
3349  glEnd();
3350 
3351  glBegin(GL_POLYGON);
3352  CylindricalNormalInv(trapezoid[0], normal), glNormal3dv(normal), glVertex3dv(trapezoid[0]);
3353  CylindricalNormalInv(trapezoid[4], normal), glNormal3dv(normal), glVertex3dv(trapezoid[4]);
3354  CylindricalNormalInv(trapezoid[7], normal), glNormal3dv(normal), glVertex3dv(trapezoid[7]);
3355  CylindricalNormalInv(trapezoid[3], normal), glNormal3dv(normal), glVertex3dv(trapezoid[3]);
3356  glEnd();
3357 
3358  glBegin(GL_POLYGON);
3359  if (color) {
3360  TMath::Normal2Plane(trapezoid[0], trapezoid[1], trapezoid[5], normal);
3361  glNormal3dv(normal);
3362  }
3363  glVertex3dv(trapezoid[0]);
3364  glVertex3dv(trapezoid[1]);
3365  glVertex3dv(trapezoid[5]);
3366  glVertex3dv(trapezoid[4]);
3367  glEnd();
3368 
3369  glBegin(GL_POLYGON);
3370  if (color) {
3371  TMath::Normal2Plane(trapezoid[3], trapezoid[7], trapezoid[6], normal);
3372  glNormal3dv(normal);
3373  }
3374  glVertex3dv(trapezoid[3]);
3375  glVertex3dv(trapezoid[7]);
3376  glVertex3dv(trapezoid[6]);
3377  glVertex3dv(trapezoid[2]);
3378  glEnd();
3379 }
3380 
3381 ////////////////////////////////////////////////////////////////////////////////
3382 ///In polar coordinates, box became trapezoid.
3383 ///Four faces need normal calculations.
3384 
3385 void DrawTrapezoidTextured(const Double_t ver[][2], Double_t zMin, Double_t zMax,
3386  Double_t texMin, Double_t texMax)
3387 {
3388  if (zMin > zMax) {
3389  std::swap(zMin, zMax);
3390  std::swap(texMin, texMax);
3391  }
3392 
3393  //top
3394  glBegin(GL_POLYGON);
3395  glNormal3d(0., 0., 1.);
3396  glTexCoord1d(texMax);
3397  glVertex3d(ver[0][0], ver[0][1], zMax);
3398  glVertex3d(ver[1][0], ver[1][1], zMax);
3399  glVertex3d(ver[2][0], ver[2][1], zMax);
3400  glVertex3d(ver[3][0], ver[3][1], zMax);
3401  glEnd();
3402  //bottom
3403  glBegin(GL_POLYGON);
3404  glNormal3d(0., 0., -1.);
3405  glTexCoord1d(texMin);
3406  glVertex3d(ver[0][0], ver[0][1], zMin);
3407  glVertex3d(ver[3][0], ver[3][1], zMin);
3408  glVertex3d(ver[2][0], ver[2][1], zMin);
3409  glVertex3d(ver[1][0], ver[1][1], zMin);
3410  glEnd();
3411  //
3412 
3413  Double_t trapezoid[][3] = {{ver[0][0], ver[0][1], zMin}, {ver[1][0], ver[1][1], zMin},
3414  {ver[2][0], ver[2][1], zMin}, {ver[3][0], ver[3][1], zMin},
3415  {ver[0][0], ver[0][1], zMax}, {ver[1][0], ver[1][1], zMax},
3416  {ver[2][0], ver[2][1], zMax}, {ver[3][0], ver[3][1], zMax}};
3417  Double_t normal[3] = {0.};
3418  glBegin(GL_POLYGON);
3419  CylindricalNormal(trapezoid[1], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[1]);
3420  CylindricalNormal(trapezoid[2], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[2]);
3421  CylindricalNormal(trapezoid[6], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[6]);
3422  CylindricalNormal(trapezoid[5], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[5]);
3423  glEnd();
3424 
3425  glBegin(GL_POLYGON);
3426  CylindricalNormalInv(trapezoid[0], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[0]);
3427  CylindricalNormalInv(trapezoid[4], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[4]);
3428  CylindricalNormalInv(trapezoid[7], normal), glNormal3dv(normal), glTexCoord1d(texMax), glVertex3dv(trapezoid[7]);
3429  CylindricalNormalInv(trapezoid[3], normal), glNormal3dv(normal), glTexCoord1d(texMin), glVertex3dv(trapezoid[3]);
3430  glEnd();
3431 
3432  glBegin(GL_POLYGON);
3433  TMath::Normal2Plane(trapezoid[0], trapezoid[1], trapezoid[5], normal);
3434  glNormal3dv(normal);
3435  glTexCoord1d(texMin);
3436  glVertex3dv(trapezoid[0]);
3437  glTexCoord1d(texMin);
3438  glVertex3dv(trapezoid[1]);
3439  glTexCoord1d(texMax);
3440  glVertex3dv(trapezoid[5]);
3441  glTexCoord1d(texMax);
3442  glVertex3dv(trapezoid[4]);
3443  glEnd();
3444 
3445  glBegin(GL_POLYGON);
3446  TMath::Normal2Plane(trapezoid[3], trapezoid[7], trapezoid[6], normal);
3447  glNormal3dv(normal);
3448  glTexCoord1d(texMin);
3449  glVertex3dv(trapezoid[3]);
3450  glTexCoord1d(texMax);
3451  glVertex3dv(trapezoid[7]);
3452  glTexCoord1d(texMax);
3453  glVertex3dv(trapezoid[6]);
3454  glTexCoord1d(texMin);
3455  glVertex3dv(trapezoid[2]);
3456  glEnd();
3457 }
3458 
3459 ////////////////////////////////////////////////////////////////////////////////
3460 ///In polar coordinates, box became trapezoid.
3461 
3462 void DrawTrapezoidTextured2(const Double_t ver[][2], Double_t zMin, Double_t zMax,
3463  Double_t texMin, Double_t texMax)
3464 {
3465  if (zMin > zMax)
3466  std::swap(zMin, zMax);
3467 
3468  const Double_t trapezoid[][3] = {{ver[0][0], ver[0][1], zMin}, {ver[1][0], ver[1][1], zMin},
3469  {ver[2][0], ver[2][1], zMin}, {ver[3][0], ver[3][1], zMin},
3470  {ver[0][0], ver[0][1], zMax}, {ver[1][0], ver[1][1], zMax},
3471  {ver[2][0], ver[2][1], zMax}, {ver[3][0], ver[3][1], zMax}};
3472  const Double_t tex[] = {texMin, texMax, texMax, texMin, texMin, texMax, texMax, texMin};
3473  //top
3474  glBegin(GL_POLYGON);
3475  glNormal3d(0., 0., 1.);
3476  glTexCoord1d(tex[4]), glVertex3dv(trapezoid[4]);
3477  glTexCoord1d(tex[5]), glVertex3dv(trapezoid[5]);
3478  glTexCoord1d(tex[6]), glVertex3dv(trapezoid[6]);
3479  glTexCoord1d(tex[7]), glVertex3dv(trapezoid[7]);
3480  glEnd();
3481  //bottom
3482  glBegin(GL_POLYGON);
3483  glNormal3d(0., 0., -1.);
3484  glTexCoord1d(tex[0]), glVertex3dv(trapezoid[0]);
3485  glTexCoord1d(tex[3]), glVertex3dv(trapezoid[3]);
3486  glTexCoord1d(tex[2]), glVertex3dv(trapezoid[2]);
3487  glTexCoord1d(tex[1]), glVertex3dv(trapezoid[1]);
3488  glEnd();
3489  //
3490  glBegin(GL_POLYGON);
3491  Double_t normal[3] = {};
3492  CylindricalNormal(trapezoid[1], normal), glNormal3dv(normal), glTexCoord1d(tex[1]), glVertex3dv(trapezoid[1]);
3493  CylindricalNormal(trapezoid[2], normal), glNormal3dv(normal), glTexCoord1d(tex[2]), glVertex3dv(trapezoid[2]);
3494  CylindricalNormal(trapezoid[6], normal), glNormal3dv(normal), glTexCoord1d(tex[6]), glVertex3dv(trapezoid[6]);
3495  CylindricalNormal(trapezoid[5], normal), glNormal3dv(normal), glTexCoord1d(tex[5]), glVertex3dv(trapezoid[5]);
3496  glEnd();
3497 
3498  glBegin(GL_POLYGON);
3499  CylindricalNormalInv(trapezoid[0], normal), glNormal3dv(normal), glTexCoord1d(tex[0]), glVertex3dv(trapezoid[0]);
3500  CylindricalNormalInv(trapezoid[4], normal), glNormal3dv(normal), glTexCoord1d(tex[4]), glVertex3dv(trapezoid[4]);
3501  CylindricalNormalInv(trapezoid[7], normal), glNormal3dv(normal), glTexCoord1d(tex[7]), glVertex3dv(trapezoid[7]);
3502  CylindricalNormalInv(trapezoid[3], normal), glNormal3dv(normal), glTexCoord1d(tex[3]), glVertex3dv(trapezoid[3]);
3503  glEnd();
3504 
3505  glBegin(GL_POLYGON);
3506  TMath::Normal2Plane(trapezoid[0], trapezoid[1], trapezoid[5], normal);
3507  glNormal3dv(normal);
3508  glTexCoord1d(tex[0]), glVertex3dv(trapezoid[0]);
3509  glTexCoord1d(tex[1]), glVertex3dv(trapezoid[1]);
3510  glTexCoord1d(tex[5]), glVertex3dv(trapezoid[5]);
3511  glTexCoord1d(tex[4]), glVertex3dv(trapezoid[4]);
3512  glEnd();
3513 
3514  glBegin(GL_POLYGON);
3515  TMath::Normal2Plane(trapezoid[3], trapezoid[7], trapezoid[6], normal);
3516  glNormal3dv(normal);
3517  glTexCoord1d(tex[3]), glVertex3dv(trapezoid[3]);
3518  glTexCoord1d(tex[7]), glVertex3dv(trapezoid[7]);
3519  glTexCoord1d(tex[6]), glVertex3dv(trapezoid[6]);
3520  glTexCoord1d(tex[2]), glVertex3dv(trapezoid[2]);
3521  glEnd();
3522 }
3523 
3524 ////////////////////////////////////////////////////////////////////////////////
3525 
3526 void SphericalNormal(const Double_t *v, Double_t *normal)
3527 {
3528  const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
3529  if (n > 0.) {
3530  normal[0] = v[0] / n;
3531  normal[1] = v[1] / n;
3532  normal[2] = v[2] / n;
3533  } else {
3534  normal[0] = v[0];
3535  normal[1] = v[1];
3536  normal[2] = v[2];
3537  }
3538 }
3539 
3540 ////////////////////////////////////////////////////////////////////////////////
3541 
3542 void SphericalNormalInv(const Double_t *v, Double_t *normal)
3543 {
3544  const Double_t n = TMath::Sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
3545  if (n > 0.) {
3546  normal[0] = -v[0] / n;
3547  normal[1] = -v[1] / n;
3548  normal[2] = -v[2] / n;
3549  } else {
3550  normal[0] = -v[0];
3551  normal[1] = -v[1];
3552  normal[2] = -v[2];
3553  }
3554 }
3555 
3556 ////////////////////////////////////////////////////////////////////////////////
3557 
3558 void DrawTrapezoid(const Double_t ver[][3])
3559 {
3560  Double_t normal[3] = {0.};
3561 
3562  glBegin(GL_POLYGON);
3563  TMath::Normal2Plane(ver[1], ver[2], ver[3], normal);
3564  glNormal3dv(normal);
3565  glVertex3dv(ver[0]);
3566  glVertex3dv(ver[1]);
3567  glVertex3dv(ver[2]);
3568  glVertex3dv(ver[3]);
3569  glEnd();
3570  //bottom
3571  glBegin(GL_POLYGON);
3572  TMath::Normal2Plane(ver[4], ver[7], ver[6], normal);
3573  glNormal3dv(normal);
3574  glVertex3dv(ver[4]);
3575  glVertex3dv(ver[7]);
3576  glVertex3dv(ver[6]);
3577  glVertex3dv(ver[5]);
3578  glEnd();
3579  //
3580 
3581  glBegin(GL_POLYGON);
3582  TMath::Normal2Plane(ver[0], ver[3], ver[7], normal);
3583  glNormal3dv(normal);
3584  glVertex3dv(ver[0]);
3585  glVertex3dv(ver[3]);
3586  glVertex3dv(ver[7]);
3587  glVertex3dv(ver[4]);
3588  glEnd();
3589 
3590  glBegin(GL_POLYGON);
3591  SphericalNormal(ver[3], normal), glNormal3dv(normal), glVertex3dv(ver[3]);
3592  SphericalNormal(ver[2], normal), glNormal3dv(normal), glVertex3dv(ver[2]);
3593  SphericalNormal(ver[6], normal), glNormal3dv(normal), glVertex3dv(ver[6]);
3594  SphericalNormal(ver[7], normal), glNormal3dv(normal), glVertex3dv(ver[7]);
3595  glEnd();
3596 
3597  glBegin(GL_POLYGON);
3598  TMath::Normal2Plane(ver[5], ver[6], ver[2], normal);
3599  glNormal3dv(normal);
3600  glVertex3dv(ver[5]);
3601  glVertex3dv(ver[6]);
3602  glVertex3dv(ver[2]);
3603  glVertex3dv(ver[1]);
3604  glEnd();
3605 
3606  glBegin(GL_POLYGON);
3607  SphericalNormalInv(ver[0], normal), glNormal3dv(normal), glVertex3dv(ver[0]);
3608  SphericalNormalInv(ver[4], normal), glNormal3dv(normal), glVertex3dv(ver[4]);
3609  SphericalNormalInv(ver[5], normal), glNormal3dv(normal), glVertex3dv(ver[5]);
3610  SphericalNormalInv(ver[1], normal), glNormal3dv(normal), glVertex3dv(ver[1]);
3611  glEnd();
3612 }
3613 
3614 ////////////////////////////////////////////////////////////////////////////////
3615 
3616 void DrawTrapezoidTextured(const Double_t ver[][3], Double_t texMin, Double_t texMax)
3617 {
3618  Double_t normal[3] = {};
3619  if (texMin > texMax)
3620  std::swap(texMin, texMax);
3621 
3622  const Double_t tex[] = {texMin, texMin, texMax, texMax, texMin, texMin, texMax, texMax};
3623  glBegin(GL_POLYGON);
3624  TMath::Normal2Plane(ver[0], ver[1], ver[2], normal);
3625  glNormal3dv(normal);
3626  glTexCoord1d(tex[0]), glVertex3dv(ver[0]);
3627  glTexCoord1d(tex[1]), glVertex3dv(ver[1]);
3628  glTexCoord1d(tex[2]), glVertex3dv(ver[2]);
3629  glTexCoord1d(tex[3]), glVertex3dv(ver[3]);
3630  glEnd();
3631  glBegin(GL_POLYGON);
3632  TMath::Normal2Plane(ver[4], ver[7], ver[6], normal);
3633  glNormal3dv(normal);
3634  glTexCoord1d(tex[4]), glVertex3dv(ver[4]);
3635  glTexCoord1d(tex[7]), glVertex3dv(ver[7]);
3636  glTexCoord1d(tex[6]), glVertex3dv(ver[6]);
3637  glTexCoord1d(tex[5]), glVertex3dv(ver[5]);
3638  glEnd();
3639  glBegin(GL_POLYGON);
3640  TMath::Normal2Plane(ver[0], ver[3], ver[7], normal);
3641  glNormal3dv(normal);
3642  glTexCoord1d(tex[0]), glVertex3dv(ver[0]);
3643  glTexCoord1d(tex[3]), glVertex3dv(ver[3]);
3644  glTexCoord1d(tex[7]), glVertex3dv(ver[7]);
3645  glTexCoord1d(tex[4]), glVertex3dv(ver[4]);
3646  glEnd();
3647  glBegin(GL_POLYGON);
3648  SphericalNormal(ver[3], normal), glNormal3dv(normal), glTexCoord1d(tex[3]), glVertex3dv(ver[3]);
3649  SphericalNormal(ver[2], normal), glNormal3dv(normal), glTexCoord1d(tex[2]), glVertex3dv(ver[2]);
3650  SphericalNormal(ver[6], normal), glNormal3dv(normal), glTexCoord1d(tex[6]), glVertex3dv(ver[6]);
3651  SphericalNormal(ver[7], normal), glNormal3dv(normal), glTexCoord1d(tex[7]), glVertex3dv(ver[7]);
3652  glEnd();
3653  glBegin(GL_POLYGON);
3654  TMath::Normal2Plane(ver[5], ver[6], ver[2], normal);
3655  glNormal3dv(normal);
3656  glTexCoord1d(tex[5]), glVertex3dv(ver[5]);
3657  glTexCoord1d(tex[6]), glVertex3dv(ver[6]);
3658  glTexCoord1d(tex[2]), glVertex3dv(ver[2]);
3659  glTexCoord1d(tex[1]), glVertex3dv(ver[1]);
3660  glEnd();
3661  glBegin(GL_POLYGON);
3662  SphericalNormalInv(ver[0], normal), glNormal3dv(normal), glTexCoord1d(tex[0]), glVertex3dv(ver[0]);
3663  SphericalNormalInv(ver[4], normal), glNormal3dv(normal), glTexCoord1d(tex[4]), glVertex3dv(ver[4]);
3664  SphericalNormalInv(ver[5], normal), glNormal3dv(normal), glTexCoord1d(tex[5]), glVertex3dv(ver[5]);
3665  SphericalNormalInv(ver[1], normal), glNormal3dv(normal), glTexCoord1d(tex[1]), glVertex3dv(ver[1]);
3666  glEnd();
3667 }
3668 
3669 
3670 void Draw2DAxis(TAxis *axis, Double_t xMin, Double_t yMin, Double_t xMax, Double_t yMax,
3671  Double_t min, Double_t max, Bool_t log, Bool_t z = kFALSE)
3672 {
3673  //Axes are drawn with help of TGaxis class
3674  std::string option;
3675  option.reserve(20);
3676 
3677  if (xMin > xMax || z) option += "SDH=+";
3678  else option += "SDH=-";
3679 
3680  if (log) option += 'G';
3681 
3682  Int_t nDiv = axis->GetNdivisions();
3683 
3684  if (nDiv < 0) {
3685  option += 'N';
3686  nDiv = -nDiv;
3687  }
3688 
3689  TGaxis axisPainter;
3690  axisPainter.SetLineWidth(1);
3691 
3692  static const Double_t zero = 0.001;
3693 
3694  if (TMath::Abs(xMax - xMin) >= zero || TMath::Abs(yMax - yMin) >= zero) {
3695  axisPainter.ImportAxisAttributes(axis);
3696  axisPainter.SetLabelOffset(axis->GetLabelOffset() + axis->GetTickLength());
3697 
3698  if (log) {
3699  min = TMath::Power(10, min);
3700  max = TMath::Power(10, max);
3701  }
3702  //Option time display is required ?
3703  if (axis->GetTimeDisplay()) {
3704  option += 't';
3705 
3706  if (!strlen(axis->GetTimeFormatOnly()))
3707  axisPainter.SetTimeFormat(axis->ChooseTimeFormat(max - min));
3708  else
3709  axisPainter.SetTimeFormat(axis->GetTimeFormat());
3710  }
3711 
3712  axisPainter.SetOption(option.c_str());
3713  axisPainter.PaintAxis(xMin, yMin, xMax, yMax, min, max, nDiv, option.c_str());
3714  }
3715 }
3716 
3717 const Int_t gFramePoints[][2] = {{3, 1}, {0, 2}, {1, 3}, {2, 0}};
3718 //Each point has two "neighbouring axes" (left and right). Axes types are 1 (ordinata) and 0 (abscissa)
3719 const Int_t gAxisType[][2] = {{1, 0}, {0, 1}, {1, 0}, {0, 1}};
3720 
3721 ////////////////////////////////////////////////////////////////////////////////
3722 ///Using front point, find, where to draw axes and which labels to use for them
3723 ///gVirtualX->SelectWindow(gGLManager->GetVirtualXInd(fGLDevice));
3724 ///gVirtualX->SetDrawMode(TVirtualX::kCopy);//TCanvas by default sets in kInverse
3725 
3726 void DrawAxes(Int_t fp, const Int_t *vp, const TGLVertex3 *box, const TGLPlotCoordinates *coord,
3727  TAxis *xAxis, TAxis *yAxis, TAxis *zAxis)
3728 {
3729  const Int_t left = gFramePoints[fp][0];
3730  const Int_t right = gFramePoints[fp][1];
3731  const Double_t xLeft = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw()
3732  + box[left].X() - vp[0]));
3733  const Double_t yLeft = gPad->AbsPixeltoY(Int_t(vp[3] - box[left].Y()
3734  + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
3735  * gPad->GetWh() + vp[1]));
3736  const Double_t xMid = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw()
3737  + box[fp].X() - vp[0]));
3738  const Double_t yMid = gPad->AbsPixeltoY(Int_t(vp[3] - box[fp].Y()
3739  + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
3740  * gPad->GetWh() + vp[1]));
3741  const Double_t xRight = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC()
3742  * gPad->GetWw() + box[right].X() - vp[0]));
3743  const Double_t yRight = gPad->AbsPixeltoY(Int_t(vp[3] - box[right].Y()
3744  + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
3745  * gPad->GetWh() + vp[1]));
3746  const Double_t points[][2] = {{coord->GetXRange().first, coord->GetYRange().first },
3747  {coord->GetXRange().second, coord->GetYRange().first },
3748  {coord->GetXRange().second, coord->GetYRange().second},
3749  {coord->GetXRange().first, coord->GetYRange().second}};
3750  const Int_t leftType = gAxisType[fp][0];
3751  const Int_t rightType = gAxisType[fp][1];
3752  const Double_t leftLabel = points[left][leftType];
3753  const Double_t leftMidLabel = points[fp][leftType];
3754  const Double_t rightMidLabel = points[fp][rightType];
3755  const Double_t rightLabel = points[right][rightType];
3756 
3757  if (xLeft - xMid || yLeft - yMid) {//To suppress error messages from TGaxis
3758  TAxis *axis = leftType ? yAxis : xAxis;
3759  if (leftLabel < leftMidLabel)
3760  Draw2DAxis(axis, xLeft, yLeft, xMid, yMid, leftLabel, leftMidLabel,
3761  leftType ? coord->GetYLog() : coord->GetXLog());
3762  else
3763  Draw2DAxis(axis, xMid, yMid, xLeft, yLeft, leftMidLabel, leftLabel,
3764  leftType ? coord->GetYLog() : coord->GetXLog());
3765  }
3766 
3767  if (xRight - xMid || yRight - yMid) {//To suppress error messages from TGaxis
3768  TAxis *axis = rightType ? yAxis : xAxis;
3769 
3770  if (rightMidLabel < rightLabel)
3771  Draw2DAxis(axis, xMid, yMid, xRight, yRight, rightMidLabel, rightLabel,
3772  rightType ? coord->GetYLog() : coord->GetXLog());
3773  else
3774  Draw2DAxis(axis, xRight, yRight, xMid, yMid, rightLabel, rightMidLabel,
3775  rightType ? coord->GetYLog() : coord->GetXLog());
3776  }
3777 
3778  const Double_t xUp = gPad->AbsPixeltoX(Int_t(gPad->GetXlowNDC() * gPad->GetWw()
3779  + box[left + 4].X() - vp[0]));
3780  const Double_t yUp = gPad->AbsPixeltoY(Int_t(vp[3] - box[left + 4].Y()
3781  + (1 - gPad->GetHNDC() - gPad->GetYlowNDC())
3782  * gPad->GetWh() + vp[1]));
3783  Draw2DAxis(zAxis, xLeft, yLeft, xUp, yUp, coord->GetZRange().first,
3784  coord->GetZRange().second, coord->GetZLog(), kTRUE);
3785 }
3786 
3787 void SetZLevels(TAxis *zAxis, Double_t zMin, Double_t zMax,
3788  Double_t zScale, std::vector<Double_t> &zLevels)
3789 {
3790  Int_t nDiv = zAxis->GetNdivisions() % 100;
3791  Int_t nBins = 0;
3792  Double_t binLow = 0., binHigh = 0., binWidth = 0.;
3793  THLimitsFinder::Optimize(zMin, zMax, nDiv, binLow, binHigh, nBins, binWidth, " ");
3794  zLevels.resize(nBins + 1);
3795 
3796  for (Int_t i = 0; i < nBins + 1; ++i)
3797  zLevels[i] = (binLow + i * binWidth) * zScale;
3798 }
3799 
3800 ////////////////////////////////////////////////////////////////////////////////
3801 ///Draw textured triangle
3802 
3803 void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3,
3804  Double_t t1, Double_t t2, Double_t t3, const TGLVector3 &norm1,
3805  const TGLVector3 &norm2, const TGLVector3 &norm3)
3806 {
3807  glBegin(GL_POLYGON);
3808  glNormal3dv(norm1.CArr());
3809  glTexCoord1d(t1);
3810  glVertex3dv(v1.CArr());
3811  glNormal3dv(norm2.CArr());
3812  glTexCoord1d(t2);
3813  glVertex3dv(v2.CArr());
3814  glNormal3dv(norm3.CArr());
3815  glTexCoord1d(t3);
3816  glVertex3dv(v3.CArr());
3817  glEnd();
3818 }
3819 
3820 ////////////////////////////////////////////////////////////////////////////////
3821 ///Draw textured triangle on a plane
3822 
3823 void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3,
3825  const TGLVector3 &normal)
3826 {
3827  glBegin(GL_POLYGON);
3828  glNormal3dv(normal.CArr());
3829  glTexCoord1d(t1);
3830  glVertex3d(v1.X(), v1.Y(), z);
3831  glTexCoord1d(t2);
3832  glVertex3d(v2.X(), v2.Y(), z);
3833  glTexCoord1d(t3);
3834  glVertex3d(v3.X(), v3.Y(), z);
3835  glEnd();
3836 }
3837 
3838 ////////////////////////////////////////////////////////////////////////////////
3839 ///This function creates color for parametric surface's vertex,
3840 ///using its 'u' value.
3841 ///I've found it in one of Apple's Carbon tutorials , and it's based
3842 ///on Paul Bourke work. Very nice colors!!! :)
3843 
3844 void GetColor(Float_t v, Float_t vmin, Float_t vmax, Int_t type, Float_t *rgba)
3845 {
3846  Float_t dv,vmid;
3847  //Float_t c[] = {1.f, 1.f, 1.f};
3848  Float_t c1[3] = {}, c2[3] = {}, c3[3] = {};
3849  Float_t ratio ;
3850  rgba[3] = 1.f;
3851 
3852  if (v < vmin)
3853  v = vmin;
3854  if (v > vmax)
3855  v = vmax;
3856  dv = vmax - vmin;
3857 
3858  switch (type) {
3859  case 0:
3860  rgba[0] = 1.f;
3861  rgba[1] = 1.f;
3862  rgba[2] = 1.f;
3863  break;
3864  case 1:
3865  if (v < (vmin + 0.25 * dv)) {
3866  rgba[0] = 0;
3867  rgba[1] = 4 * (v - vmin) / dv;
3868  rgba[2] = 1;
3869  } else if (v < (vmin + 0.5 * dv)) {
3870  rgba[0] = 0;
3871  rgba[1] = 1;
3872  rgba[2] = 1 + 4 * (vmin + 0.25 * dv - v) / dv;
3873  } else if (v < (vmin + 0.75 * dv)) {
3874  rgba[0] = 4 * (v - vmin - 0.5 * dv) / dv;
3875  rgba[1] = 1;
3876  rgba[2] = 0;
3877  } else {
3878  rgba[0] = 1;
3879  rgba[1] = 1 + 4 * (vmin + 0.75 * dv - v) / dv;
3880  rgba[2] = 0;
3881  }
3882  break;
3883  case 2:
3884  rgba[0] = (v - vmin) / dv;
3885  rgba[1] = 0;
3886  rgba[2] = (vmax - v) / dv;
3887  break;
3888  case 3:
3889  rgba[0] = (v - vmin) / dv;
3890  rgba[1] = rgba[0];
3891  rgba[2] = rgba[0];
3892  break;
3893  case 4:
3894  if (v < (vmin + dv / 6.0)) {
3895  rgba[0] = 1;
3896  rgba[1] = 6 * (v - vmin) / dv;
3897  rgba[2] = 0;
3898  } else if (v < (vmin + 2.0 * dv / 6.0)) {
3899  rgba[0] = 1 + 6 * (vmin + dv / 6.0 - v) / dv;
3900  rgba[1] = 1;
3901  rgba[2] = 0;
3902  } else if (v < (vmin + 3.0 * dv / 6.0)) {
3903  rgba[0] = 0;
3904  rgba[1] = 1;
3905  rgba[2] = 6 * (v - vmin - 2.0 * dv / 6.0) / dv;
3906  } else if (v < (vmin + 4.0 * dv / 6.0)) {
3907  rgba[0] = 0;
3908  rgba[1] = 1 + 6 * (vmin + 3.0 * dv / 6.0 - v) / dv;
3909  rgba[2] = 1;
3910  } else if (v < (vmin + 5.0 * dv / 6.0)) {
3911  rgba[0] = 6 * (v - vmin - 4.0 * dv / 6.0) / dv;
3912  rgba[1] = 0;
3913  rgba[2] = 1;
3914  } else {
3915  rgba[0] = 1;
3916  rgba[1] = 0;
3917  rgba[2] = 1 + 6 * (vmin + 5.0 * dv / 6.0 - v) / dv;
3918  }
3919  break;
3920  case 5:
3921  rgba[0] = (v - vmin) / (vmax - vmin);
3922  rgba[1] = 1;
3923  rgba[2] = 0;
3924  break;
3925  case 6:
3926  rgba[0] = (v - vmin) / (vmax - vmin);
3927  rgba[1] = (vmax - v) / (vmax - vmin);
3928  rgba[2] = rgba[0];
3929  break;
3930  case 7:
3931  if (v < (vmin + 0.25 * dv)) {
3932  rgba[0] = 0;
3933  rgba[1] = 4 * (v - vmin) / dv;
3934  rgba[2] = 1 - rgba[1];
3935  } else if (v < (vmin + 0.5 * dv)) {
3936  rgba[0] = 4 * (v - vmin - 0.25 * dv) / dv;
3937  rgba[1] = 1 - rgba[0];
3938  rgba[2] = 0;
3939  } else if (v < (vmin + 0.75 * dv)) {
3940  rgba[1] = 4 * (v - vmin - 0.5 * dv) / dv;
3941  rgba[0] = 1 - rgba[1];
3942  rgba[2] = 0;
3943  } else {
3944  rgba[0] = 0;
3945  rgba[2] = 4 * (v - vmin - 0.75 * dv) / dv;
3946  rgba[1] = 1 - rgba[2];
3947  }
3948  break;
3949  case 8:
3950  if (v < (vmin + 0.5 * dv)) {
3951  rgba[0] = 2 * (v - vmin) / dv;
3952  rgba[1] = rgba[0];
3953  rgba[2] = rgba[0];
3954  } else {
3955  rgba[0] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
3956  rgba[1] = rgba[0];
3957  rgba[2] = rgba[0];
3958  }
3959  break;
3960  case 9:
3961  if (v < (vmin + dv / 3)) {
3962  rgba[2] = 3 * (v - vmin) / dv;
3963  rgba[1] = 0;
3964  rgba[0] = 1 - rgba[2];
3965  } else if (v < (vmin + 2 * dv / 3)) {
3966  rgba[0] = 0;
3967  rgba[1] = 3 * (v - vmin - dv / 3) / dv;
3968  rgba[2] = 1;
3969  } else {
3970  rgba[0] = 3 * (v - vmin - 2 * dv / 3) / dv;
3971  rgba[1] = 1 - rgba[0];
3972  rgba[2] = 1;
3973  }
3974  break;
3975  case 10:
3976  if (v < (vmin + 0.2 * dv)) {
3977  rgba[0] = 0;
3978  rgba[1] = 5 * (v - vmin) / dv;
3979  rgba[2] = 1;
3980  } else if (v < (vmin + 0.4 * dv)) {
3981  rgba[0] = 0;
3982  rgba[1] = 1;
3983  rgba[2] = 1 + 5 * (vmin + 0.2 * dv - v) / dv;
3984  } else if (v < (vmin + 0.6 * dv)) {
3985  rgba[0] = 5 * (v - vmin - 0.4 * dv) / dv;
3986  rgba[1] = 1;
3987  rgba[2] = 0;
3988  } else if (v < (vmin + 0.8 * dv)) {
3989  rgba[0] = 1;
3990  rgba[1] = 1 - 5 * (v - vmin - 0.6 * dv) / dv;
3991  rgba[2] = 0;
3992  } else {
3993  rgba[0] = 1;
3994  rgba[1] = 5 * (v - vmin - 0.8 * dv) / dv;
3995  rgba[2] = 5 * (v - vmin - 0.8 * dv) / dv;
3996  }
3997  break;
3998  case 11:
3999  c1[0] = 200 / 255.0; c1[1] = 60 / 255.0; c1[2] = 0 / 255.0;
4000  c2[0] = 250 / 255.0; c2[1] = 160 / 255.0; c2[2] = 110 / 255.0;
4001  rgba[0] = (c2[0] - c1[0]) * (v - vmin) / dv + c1[0];
4002  rgba[1] = (c2[1] - c1[1]) * (v - vmin) / dv + c1[1];
4003  rgba[2] = (c2[2] - c1[2]) * (v - vmin) / dv + c1[2];
4004  break;
4005  case 12:
4006  c1[0] = 55 / 255.0; c1[1] = 55 / 255.0; c1[2] = 45 / 255.0;
4007  c2[0] = 200 / 255.0; c2[1] = 60 / 255.0; c2[2] = 0 / 255.0;
4008  c3[0] = 250 / 255.0; c3[1] = 160 / 255.0; c3[2] = 110 / 255.0;
4009  ratio = 0.4;
4010  vmid = vmin + ratio * dv;
4011  if (v < vmid) {
4012  rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
4013  rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
4014  rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
4015  } else {
4016  rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
4017  rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
4018  rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
4019  }
4020  break;
4021  case 13:
4022  c1[0] = 0 / 255.0; c1[1] = 255 / 255.0; c1[2] = 0 / 255.0;
4023  c2[0] = 255 / 255.0; c2[1] = 150 / 255.0; c2[2] = 0 / 255.0;
4024  c3[0] = 255 / 255.0; c3[1] = 250 / 255.0; c3[2] = 240 / 255.0;
4025  ratio = 0.3;
4026  vmid = vmin + ratio * dv;
4027  if (v < vmid) {
4028  rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
4029  rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
4030  rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
4031  } else {
4032  rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
4033  rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
4034  rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
4035  }
4036  break;
4037  case 14:
4038  rgba[0] = 1;
4039  rgba[1] = 1 - (v - vmin) / dv;
4040  rgba[2] = 0;
4041  break;
4042  case 15:
4043  if (v < (vmin + 0.25 * dv)) {
4044  rgba[0] = 0;
4045  rgba[1] = 4 * (v - vmin) / dv;
4046  rgba[2] = 1;
4047  } else if (v < (vmin + 0.5 * dv)) {
4048  rgba[0] = 0;
4049  rgba[1] = 1;
4050  rgba[2] = 1 - 4 * (v - vmin - 0.25 * dv) / dv;
4051  } else if (v < (vmin + 0.75 * dv)) {
4052  rgba[0] = 4 * (v - vmin - 0.5 * dv) / dv;
4053  rgba[1] = 1;
4054  rgba[2] = 0;
4055  } else {
4056  rgba[0] = 1;
4057  rgba[1] = 1;
4058  rgba[2] = 4 * (v - vmin - 0.75 * dv) / dv;
4059  }
4060  break;
4061  case 16:
4062  if (v < (vmin + 0.5 * dv)) {
4063  rgba[0] = 0.0;
4064  rgba[1] = 2 * (v - vmin) / dv;
4065  rgba[2] = 1 - 2 * (v - vmin) / dv;
4066  } else {
4067  rgba[0] = 2 * (v - vmin - 0.5 * dv) / dv;
4068  rgba[1] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
4069  rgba[2] = 0.0;
4070  }
4071  break;
4072  case 17:
4073  if (v < (vmin + 0.5 * dv)) {
4074  rgba[0] = 1.0;
4075  rgba[1] = 1 - 2 * (v - vmin) / dv;
4076  rgba[2] = 2 * (v - vmin) / dv;
4077  } else {
4078  rgba[0] = 1 - 2 * (v - vmin - 0.5 * dv) / dv;
4079  rgba[1] = 2 * (v - vmin - 0.5 * dv) / dv;
4080  rgba[2] = 1.0;
4081  }
4082  break;
4083  case 18:
4084  rgba[0] = 0;
4085  rgba[1] = (v - vmin) / (vmax - vmin);
4086  rgba[2] = 1;
4087  break;
4088  case 19:
4089  rgba[0] = (v - vmin) / (vmax - vmin);
4090  rgba[1] = rgba[0];
4091  rgba[2] = 1;
4092  break;
4093  case 20:
4094  c1[0] = 0 / 255.0; c1[1] = 160 / 255.0; c1[2] = 0 / 255.0;
4095  c2[0] = 180 / 255.0; c2[1] = 220 / 255.0; c2[2] = 0 / 255.0;
4096  c3[0] = 250 / 255.0; c3[1] = 220 / 255.0; c3[2] = 170 / 255.0;
4097  ratio = 0.3;
4098  vmid = vmin + ratio * dv;
4099  if (v < vmid) {
4100  rgba[0] = (c2[0] - c1[0]) * (v - vmin) / (ratio*dv) + c1[0];
4101  rgba[1] = (c2[1] - c1[1]) * (v - vmin) / (ratio*dv) + c1[1];
4102  rgba[2] = (c2[2] - c1[2]) * (v - vmin) / (ratio*dv) + c1[2];
4103  } else {
4104  rgba[0] = (c3[0] - c2[0]) * (v - vmid) / ((1-ratio)*dv) + c2[0];
4105  rgba[1] = (c3[1] - c2[1]) * (v - vmid) / ((1-ratio)*dv) + c2[1];
4106  rgba[2] = (c3[2] - c2[2]) * (v - vmid) / ((1-ratio)*dv) + c2[2];
4107  }
4108  break;
4109  }
4110 }
4111 
4112 }
4113 
4114 ////////////////////////////////////////////////////////////////////////////////
4115 ///Ctor.
4116 
4118  : fContours(0),
4119  fPaletteSize(0),
4120  fTexture(0),
4121  fMaxPaletteSize(0)
4122 {
4123 }
4124 
4125 ////////////////////////////////////////////////////////////////////////////////
4126 ///Try to find colors for palette.
4127 
4129 {
4130  if (!fMaxPaletteSize && check)
4131  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &fMaxPaletteSize);
4132 
4133  if (!(zRange.second - zRange.first))
4134  return kFALSE;
4135 
4136  if (!paletteSize) {
4137  Error("TGLLevelPaletter::GeneratePalette",
4138  "Invalid palette size, must be a positive number");
4139  return kFALSE;
4140  }
4141 
4142  if (check && paletteSize > UInt_t(fMaxPaletteSize)) {
4143  Error("TGLLevelPalette::GeneratePalette",
4144  "Number of contours %d is too big for GL 1D texture, try to reduce it to %d",
4145  paletteSize, fMaxPaletteSize);
4146  return kFALSE;
4147  }
4148 
4149  UInt_t nearestPow2 = 2;
4150  while (nearestPow2 < paletteSize)
4151  nearestPow2 <<= 1;
4152 
4153  fTexels.resize(4 * nearestPow2);
4154  fPaletteSize = paletteSize;
4155 
4156  //Generate texels.
4157  const Int_t nColors = gStyle->GetNumberOfColors();
4158 
4159  //Map color index into index in real palette.
4160 
4161  for (UInt_t i = 0; i < paletteSize; ++i) {
4162  Int_t paletteInd = Int_t(nColors / Double_t(paletteSize) * i);
4163  if (paletteInd > nColors - 1)
4164  paletteInd = nColors - 1;
4165  Int_t colorInd = gStyle->GetColorPalette(paletteInd);
4166 
4167  if (const TColor *c = gROOT->GetColor(colorInd)) {
4168  Float_t rgb[3] = {};
4169  c->GetRGB(rgb[0], rgb[1], rgb[2]);
4170  fTexels[i * 4] = UChar_t(rgb[0] * 255);
4171  fTexels[i * 4 + 1] = UChar_t(rgb[1] * 255);
4172  fTexels[i * 4 + 2] = UChar_t(rgb[2] * 255);
4173  fTexels[i * 4 + 3] = 200;//alpha
4174  }
4175  }
4176 
4177  fZRange = zRange;
4178 
4179  return kTRUE;
4180 }
4181 
4182 ////////////////////////////////////////////////////////////////////////////////
4183 ///Clear :)
4184 
4185 void TGLLevelPalette::SetContours(const std::vector<Double_t> *cont)
4186 {
4187  fContours = cont;
4188 }
4189 
4190 ////////////////////////////////////////////////////////////////////////////////
4191 ///Enable 1D texture
4192 
4194 {
4195  glEnable(GL_TEXTURE_1D);
4196 
4197  glGenTextures(1, &fTexture);
4198 
4199  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
4200  glBindTexture(GL_TEXTURE_1D, fTexture);
4201  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
4202  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4203  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4204  glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, fTexels.size() / 4, 0,
4205  GL_RGBA, GL_UNSIGNED_BYTE, &fTexels[0]);
4206  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GLint(mode));
4207 }
4208 
4209 ////////////////////////////////////////////////////////////////////////////////
4210 ///Disable 1D texture
4211 
4213 {
4214  glDeleteTextures(1, &fTexture);
4215  glDisable(GL_TEXTURE_1D);
4216 }
4217 
4218 ////////////////////////////////////////////////////////////////////////////////
4219 ///Get. Palette. Size.
4220 
4222 {
4223  return Int_t(fPaletteSize);
4224 }
4225 
4226 ////////////////////////////////////////////////////////////////////////////////
4227 ///Get tex coordinate
4228 
4230 {
4231  if (!fContours) {
4232  if (z - fZRange.first < 0)
4233  z = fZRange.first;
4234  else if (fZRange.second < z)
4235  z = fZRange.second;
4236 
4237  return (z - fZRange.first) / (fZRange.second - fZRange.first) * fPaletteSize / (fTexels.size() / 4);
4238  }
4239  /*
4240  //This part is wrong. To be fixed.
4241  std::vector<Double_t>::size_type i = 0, e = fContours->size();
4242 
4243  if (!e)
4244  return 0.;
4245 
4246  for (; i < e - 1; ++i) {
4247  if (z >= (*fContours)[i] && z <= (*fContours)[i + 1])
4248  return i / Double_t(fTexels.size() / 4);
4249  }
4250  */
4251 
4252  return 1.;
4253 }
4254 
4255 ////////////////////////////////////////////////////////////////////////////////
4256 ///Get color.
4257 
4259 {
4260  if (z - fZRange.first < 0)
4261  z = fZRange.first;
4262  else if (fZRange.second < z)
4263  z = fZRange.second;
4264 
4265  UInt_t ind = UInt_t((z - fZRange.first) / (fZRange.second - fZRange.first) * fPaletteSize);
4266  if (ind >= fPaletteSize)
4267  ind = fPaletteSize - 1;
4268 
4269  return &fTexels[ind * 4];
4270 }
4271 
4272 ////////////////////////////////////////////////////////////////////////////////
4273 ///Get color.
4274 
4276 {
4277  return &fTexels[ind * 4];
4278 }
Int_t fY
Definition: TGLUtil.h:426
virtual ~TGLColor()
Destructor.
Definition: TGLUtil.cxx:1220
static UInt_t fgDefaultDrawQuality
Definition: TGLUtil.h:915
Double_t DistanceTo(const TGLVertex3 &vertex) const
Distance from plane to vertex.
Definition: TGLUtil.cxx:520
static void DrawRing(const TGLVertex3 &center, const TGLVector3 &normal, Double_t radius, const UChar_t *rgba)
Draw ring, centered on &#39;center&#39;, lying on plane defined by &#39;center&#39; & &#39;normal&#39; of outer radius &#39;radiu...
Definition: TGLUtil.cxx:2399
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
void SetZLevels(TAxis *zAxis, Double_t zMin, Double_t zMax, Double_t zScale, std::vector< Double_t > &zLevels)
Definition: TGLUtil.cxx:3787
virtual Float_t GetTickLength() const
Definition: TAttAxis.h:44
static double B[]
std::vector< UChar_t > fTexels
Definition: TGLUtil.h:1339
Double_t ZMax() const
Class encapsulating a set of colors used throughout standard rendering.
Definition: TGLUtil.h:834
TGLVertex3 Center() const
Bool_t operator<(const TDatime &d1, const TDatime &d2)
Definition: TDatime.h:106
static GLUtesselator * GetDrawTesselator3fv()
Returns a tesselator for direct drawing when using 3-vertices with single precision.
Definition: TGLUtil.cxx:1499
const Int_t gBoxBackPlanes[][2]
Definition: TGLUtil.cxx:2969
static UInt_t fgColorLockCount
Definition: TGLUtil.h:918
void DrawFaceTextured(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, Double_t t1, Double_t t2, Double_t t3, const TGLVector3 &norm1, const TGLVector3 &norm2, const TGLVector3 &norm3)
Draw textured triangle.
Definition: TGLUtil.cxx:3803
void ReadColorBuffer(Int_t width, Int_t height)
Read color buffer.
Definition: TGLUtil.cxx:2769
void DrawQuadFilled(const TGLVertex3 &v0, const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVector3 &normal)
Draw quad face.
Definition: TGLUtil.cxx:2920
Abstract base camera class - concrete classes for orthographic and perspective cameras derive from it...
Definition: TGLCamera.h:43
static void Color(const TGLColor &color)
Set color from TGLColor.
Definition: TGLUtil.cxx:1658
Float_t GetRed() const
Definition: TColor.h:56
static double p3(double t, double a, double b, double c, double d)
Wrapper class for various misc static functions - error checking, draw helpers etc.
Definition: TGLUtil.h:876
void SetTranslation(Double_t x, Double_t y, Double_t z)
Set matrix translation components x,y,z.
Definition: TGLUtil.cxx:804
void StdLightBackground()
Set defaults for light (white) background.
Definition: TGLUtil.cxx:1406
static void ColorTransparency(Color_t color_index, Char_t transparency=0)
Set color from color_index and ROOT-style transparency (default 0).
Definition: TGLUtil.cxx:1702
static const UChar_t fgYellow[4]
Definition: TGLUtil.h:1050
Double_t Invert()
Invert the matrix, returns determinant.
Definition: TGLUtil.cxx:999
virtual ~TGLLine3()
Destroy 3D line object.
Definition: TGLUtil.cxx:215
TLine * line
const Float_t gNullEmission[]
Definition: TGLUtil.cxx:2814
float Float_t
Definition: RtypesCore.h:53
Bool_t GetZLog() const
Get Z log.
virtual Float_t GetLabelOffset() const
Definition: TAttAxis.h:40
static void DrawReferenceMarker(const TGLCamera &camera, const TGLVertex3 &pos, Float_t radius=3, const UChar_t *rgba=0)
Draw a sphere- marker on world-coordinate &#39;pos&#39; with pixel radius &#39;radius&#39;.
Definition: TGLUtil.cxx:2440
return c1
Definition: legend1.C:41
void swap(TDirectoryEntry &e1, TDirectoryEntry &e2) noexcept
std::pair< Double_t, Double_t > Range_t
Definition: TGLUtil.h:1193
double T(double x)
Definition: ChebyshevPol.h:34
#define g(i)
Definition: RSha256.hxx:105
16 component (4x4) transform matrix - column MAJOR as per GL.
Definition: TGLUtil.h:596
image html pict1_TGaxis_012 png width
Define new text attributes for the label number "labNum".
Definition: TGaxis.cxx:2551
GLUquadric * Get()
Get the internal raw GLU quadric object. Created on first call.
Definition: TGLQuadric.cxx:44
void DrawQuadStripWithRadialGradientFill(unsigned nPoints, const Double_t *inner, const Double_t *innerRGBA, const Double_t *outer, const Double_t *outerRGBA)
TODO: is it possible to use GLdouble to avoid problems with Double_t/GLdouble if they are not the sam...
Definition: TGLUtil.cxx:3184
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
Class encapsulating color information in preferred GL format - an array of four unsigned bytes...
Definition: TGLUtil.h:783
unsigned short UShort_t
Definition: RtypesCore.h:36
static void DrawLine(const TGLLine3 &line, ELineHeadShape head, Double_t size, const UChar_t rgba[4])
Draw thick line (tube) defined by &#39;line&#39;, with head at end shape &#39;head&#39; - box/arrow/none, (head) size &#39;size&#39;, color &#39;rgba&#39;.
Definition: TGLUtil.cxx:2333
const Double_t gBoxBackNormals[][3]
Definition: TGLUtil.cxx:2968
void Expand(Int_t x, Int_t y)
Expand the rect to encompass point (x,y)
Definition: TGLUtil.cxx:291
static void DrawSimpleAxes(const TGLCamera &camera, const TGLBoundingBox &bbox, Int_t axesType)
Draw simple xyz-axes for given bounding-box.
Definition: TGLUtil.cxx:2455
static void BeginAttLine(const TAttLine &aline, Char_t transp, Int_t pick_radius=0, Bool_t selection=kFALSE)
Setup drawing parameters according to passed TAttLine.
Definition: TGLUtil.cxx:2233
Int_t GetPaletteSize() const
Get. Palette. Size.
Definition: TGLUtil.cxx:4221
Double_t GetTexCoord(Double_t z) const
Get tex coordinate.
Definition: TGLUtil.cxx:4229
static void Optimize(Double_t A1, Double_t A2, Int_t nold, Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BWID, Option_t *option="")
Static function to compute reasonable axis limits.
void Fill(Double_t val)
Definition: TGLUtil.h:203
static void Color3fv(const Float_t *rgb)
Wrapper for glColor3fv.
Definition: TGLUtil.cxx:1764
static UInt_t GetDrawQuality()
static: get draw quality
Definition: TGLUtil.cxx:1566
static void RenderPoints(const TAttMarker &marker, Float_t *p, Int_t n, Int_t pick_radius=0, Bool_t selection=kFALSE, Bool_t sec_selection=kFALSE)
Render markers as circular or square points.
Definition: TGLUtil.cxx:1981
static Float_t GetScreenScalingFactor()
Returns scaling factor between screen points and GL viewport pixels.
Definition: TGLUtil.cxx:1813
void TransformVertex(TGLVertex3 &vertex) const
Transform passed &#39;vertex&#39; by this matrix - converts local frame to parent.
Definition: TGLUtil.cxx:961
TGLRect()
Positive width/height.
Definition: TGLUtil.cxx:259
const Rgl::Range_t & GetZRange() const
Z range.
void Transpose3x3()
Transpose the top left 3x3 matrix component along major diagonal Supported as currently incompatibili...
Definition: TGLUtil.cxx:975
#define gROOT
Definition: TROOT.h:410
void StdDarkBackground()
Set defaults for dark (black) background.
Definition: TGLUtil.cxx:1389
void Set(const TGLVertex3 &start, const TGLVertex3 &end)
Set 3D line running from &#39;start&#39; to &#39;end&#39;.
Definition: TGLUtil.cxx:222
Double_t fVals[16]
Definition: TGLUtil.h:600
#define CALLBACK
Definition: TGLUtil.cxx:1449
static const UChar_t fgGrey[4]
Definition: TGLUtil.h:1052
Double_t YMax() const
TGLVertex3 NearestOn(const TGLVertex3 &point) const
Return nearest point on plane.
Definition: TGLUtil.cxx:528
const Float_t gBlueEmission[]
Definition: TGLUtil.cxx:2810
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition: TGaxis.cxx:906
Double_t XMin() const
#define f(i)
Definition: RSha256.hxx:104
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
virtual ~TGLPlane()
Destroy plane object.
Definition: TGLUtil.cxx:419
const TGLVertex3 & Start() const
Definition: TGLUtil.h:405
static void PointToViewport(Int_t &x, Int_t &y)
Convert from point/screen coordinates to GL viewport coordinates.
Definition: TGLUtil.cxx:1784
const UChar_t * GetColour(Double_t z) const
Get color.
Definition: TGLUtil.cxx:4258
Int_t fMaxPaletteSize
Definition: TGLUtil.h:1343
Bool_t GetYLog() const
Get Y log.
void DrawBoxWithGradientFill(Double_t y1, Double_t y2, Double_t x1, Double_t x2, const Double_t *rgba1, const Double_t *rgba2)
Definition: TGLUtil.cxx:3164
static void RenderPolyMarkers(const TAttMarker &marker, Char_t transp, Float_t *p, Int_t n, Int_t pick_radius=0, Bool_t selection=kFALSE, Bool_t sec_selection=kFALSE)
Render polymarkers at points specified by p-array.
Definition: TGLUtil.cxx:1941
void SetTransparency(Char_t transparency)
Set alpha from the transparency.
Definition: TGLUtil.cxx:1335
Double_t B() const
Definition: TGLUtil.h:553
TGLEnableGuard(Int_t cap)
TGLEnableGuard constructor.
Definition: TGLUtil.cxx:2714
Wrapper class for GLU quadric shape drawing object.
Definition: TGLQuadric.h:27
TGLColor fForeground
Definition: TGLUtil.h:838
Char_t GetTransparency() const
Returns transparency value.
Definition: TGLUtil.cxx:1250
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
Float_t fState
Definition: TGLUtil.h:1096
~TGLCapabilitySwitch()
Destructor - reset state if changed.
Definition: TGLUtil.cxx:2655
void Set(Double_t x, Double_t y, Double_t z)
Definition: TGLUtil.h:209
TGLColor & operator=(const TGLColor &c)
Assignment operator.
Definition: TGLUtil.cxx:1227
Float_t GetBlue() const
Definition: TColor.h:58
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
void DrawAxes(Int_t frontPoint, const Int_t *viewport, const TGLVertex3 *box2D, const TGLPlotCoordinates *plotCoord, TAxis *xAxis, TAxis *yAxis, TAxis *zAxis)
Using front point, find, where to draw axes and which labels to use for them gVirtualX->SelectWindow(...
Definition: TGLUtil.cxx:3726
void RotateIP(TGLVector3 &v) const
Rotate vector in-place. Translation is not applied.
Definition: TGLUtil.cxx:1115
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
double cos(double)
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:734
Double_t fVals[4]
Definition: TGLUtil.h:529
TGLLevelPalette()
Ctor.
Definition: TGLUtil.cxx:4117
static const UChar_t fgRed[4]
Definition: TGLUtil.h:1047
TGLMatrix()
Construct default identity matrix:
Definition: TGLUtil.cxx:634
TGLVertex3()
Construct a default (0.0, 0.0, 0.0) vertex.
Definition: TGLUtil.cxx:54
T * Normal2Plane(const T v1[3], const T v2[3], const T v3[3], T normal[3])
Calculate a normal vector of a plane.
Definition: TMath.h:1309
void DrawQuadOutline(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVertex3 &v4)
Draw quad outline.
Definition: TGLUtil.cxx:2906
TGLVertex3 fVertex
Definition: TGLUtil.h:391
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
Marker Attributes class.
Definition: TAttMarker.h:19
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
double sqrt(double)
static const double x2[5]
Double_t x[n]
Definition: legend1.C:17
const Float_t gWhiteEmission[]
Definition: TGLUtil.cxx:2812
void Translate(const TGLVector3 &vect)
Shift matrix translation components by &#39;vect&#39; in parent frame.
Definition: TGLUtil.cxx:830
const Int_t gBoxFrontQuads[][4]
Definition: TGLUtil.cxx:2963
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2286
Double_t D() const
Definition: TGLUtil.h:555
void Move3LF(Double_t x, Double_t y, Double_t z)
Translate in local frame along all base vectors simultaneously.
Definition: TGLUtil.cxx:850
virtual Bool_t GetTimeDisplay() const
Definition: TAxis.h:126
Float_t GetGreen() const
Definition: TColor.h:57
void Set(const TGLVertex3 &origin, const TGLVector3 &zAxis, const TGLVector3 &xAxis=0)
Set matrix which when applied puts local origin at &#39;origin&#39; and the local Z axis in direction &#39;z&#39;...
Definition: TGLUtil.cxx:764
Rgl::Range_t fZRange
Definition: TGLUtil.h:1344
static void Color3ub(UChar_t r, UChar_t g, UChar_t b)
Wrapper for glColor3ub.
Definition: TGLUtil.cxx:1716
void SetState(Bool_t s)
Definition: TGLUtil.cxx:2663
TGLVector3 fVector
Start vertex of line.
Definition: TGLUtil.h:392
3 component (x/y/z) vertex class.
Definition: TGLUtil.h:82
~TGLCapabilityEnabler()
Destructor - reset state if changed.
Definition: TGLUtil.cxx:2686
static void DrawSphere(const TGLVertex3 &position, Double_t radius, const UChar_t rgba[4])
Draw sphere, centered on vertex &#39;position&#39;, with radius &#39;radius&#39;, color &#39;rgba&#39;.
Definition: TGLUtil.cxx:2318
static GLUtesselator * GetDrawTesselator4dv()
Returns a tesselator for direct drawing when using 4-vertices with double precision.
Definition: TGLUtil.cxx:1532
static Float_t GetPointSizeScale()
Get global point-size scale.
Definition: TGLUtil.cxx:1844
static void Color4ub(UChar_t r, UChar_t g, UChar_t b, UChar_t a)
Wrapper for glColor4ub.
Definition: TGLUtil.cxx:1724
const UChar_t * CArr() const
Definition: TGLUtil.h:799
void RotateLF(Int_t i1, Int_t i2, Double_t amount)
Rotate in local frame.
Definition: TGLUtil.cxx:925
void DrawTrapezoidTextured2(const Double_t ver[][2], Double_t zMin, Double_t zMax, Double_t tMin, Double_t tMax)
In polar coordinates, box became trapezoid.
Definition: TGLUtil.cxx:3462
Rgl::EOverlap Overlap(const TGLRect &other) const
Return overlap result (kInside, kOutside, kPartial) of this rect with &#39;other&#39;.
Definition: TGLUtil.cxx:327
void RotatePF(Int_t i1, Int_t i2, Double_t amount)
Rotate in parent frame. Does optimised version of MultLeft.
Definition: TGLUtil.cxx:942
void EnableTexture(Int_t mode) const
Enable 1D texture.
Definition: TGLUtil.cxx:4193
static double p2(double t, double a, double b, double c)
void SetOption(Option_t *option="")
To set axis options.
Definition: TGaxis.cxx:2682
TGLColor fSelection[5]
Definition: TGLUtil.h:841
static Int_t fgPickingRadius
Definition: TGLUtil.h:927
void Draw2DAxis(TAxis *axis, Double_t xMin, Double_t yMin, Double_t xMax, Double_t yMax, Double_t min, Double_t max, Bool_t log, Bool_t z=kFALSE)
Definition: TGLUtil.cxx:3670
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition: TGaxis.cxx:2717
Viewport (pixel base) 2D rectangle class.
Definition: TGLUtil.h:422
std::vector< UChar_t > fBuffer
Definition: TGLUtil.h:1132
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:33
const TGLVertex3 End() const
Definition: TGLUtil.h:406
3 component (x/y/z) vector class.
Definition: TGLUtil.h:246
XFontStruct * id
Definition: TGX11.cxx:108
TGLVector3 Multiply(const TGLVector3 &v, Double_t w=1) const
Multiply vector.
Definition: TGLUtil.cxx:1077
static UInt_t fgDrawQuality
Definition: TGLUtil.h:916
static Bool_t IsColorLocked()
Returns true if color lock-count is greater than 0.
Definition: TGLUtil.cxx:1650
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition: TStyle.cxx:913
double sin(double)
static UInt_t LockColor()
Prevent further color changes.
Definition: TGLUtil.cxx:1630
static UInt_t UnlockColor()
Allow color changes.
Definition: TGLUtil.cxx:1638
UChar_t GetBlue() const
Definition: TGLUtil.h:803
TGLSelectionBuffer()
TGLSelectionBuffer constructor.
Definition: TGLUtil.cxx:2754
void SetIdentity()
Set matrix to identity.
Definition: TGLUtil.cxx:793
void Error(const char *location, const char *msgfmt,...)
virtual const char * GetTimeFormat() const
Definition: TAxis.h:127
void MultLeft(const TGLMatrix &lhs)
Multiply with matrix lhs on left.
Definition: TGLUtil.cxx:746
TGLColor fMarkup
Definition: TGLUtil.h:840
static void SetDefaultDrawQuality(UInt_t dq)
static: set default draw quality
Definition: TGLUtil.cxx:1598
short Color_t
Definition: RtypesCore.h:79
Int_t ColorToObjectID(const UChar_t *color, Bool_t highColor)
Definition: TGLUtil.cxx:2884
virtual Int_t GetNdivisions() const
Definition: TAttAxis.h:36
REAL * vertex
Definition: triangle.c:512
const UChar_t * GetPixelColor(Int_t px, Int_t py) const
Get pixel color.
Definition: TGLUtil.cxx:2793
TGLVector3 ViewportDeltaToWorld(const TGLVertex3 &worldRef, Double_t viewportXDelta, Double_t viewportYDelta, TGLMatrix *modviewMat=0) const
Apply a 2D viewport delta (shift) to the projection of worldRef onto viewport, returning the resultan...
Definition: TGLCamera.cxx:546
Bool_t GetXLog() const
Get X log.
static void SetPointSizeScale(Float_t scale)
Set global point-size scale.
Definition: TGLUtil.cxx:1852
void SphericalNormalInv(const Double_t *v, Double_t *normal)
Definition: TGLUtil.cxx:3542
void SetContours(const std::vector< Double_t > *contours)
Clear :)
Definition: TGLUtil.cxx:4185
point * points
Definition: X3DBuffer.c:20
void ObjectIDToColor(Int_t objectID, Bool_t highColor)
Object id encoded as rgb triplet.
Definition: TGLUtil.cxx:2858
TGLVector3 GetTranslation() const
Return the translation component of matrix.
Definition: TGLUtil.cxx:822
void MultiplyIP(TGLVector3 &v, Double_t w=1) const
Multiply vector in-place.
Definition: TGLUtil.cxx:1103
static const UChar_t fgBlue[4]
Definition: TGLUtil.h:1049
TGLColorSet & operator=(const TGLColorSet &s)
Assignment operator.
Definition: TGLUtil.cxx:1375
static Float_t fgLineWidth
Definition: TGLUtil.h:921
void DrawBoxFront(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax, Int_t fp)
Draws lego&#39;s bar as a 3d box.
Definition: TGLUtil.cxx:2974
static Float_t fgPointSizeScale
Definition: TGLUtil.h:922
Double_t Mag() const
Definition: TGLUtil.h:299
void DrawError(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax)
Definition: TGLUtil.cxx:3265
static void EndAttLine(Int_t pick_radius=0, Bool_t selection=kFALSE)
Restore previous line drawing state.
Definition: TGLUtil.cxx:2269
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition: TGaxis.cxx:956
TGLFloatHolder(const TGLFloatHolder &)
static double C[]
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition: TAxis.cxx:124
static void SetLineWidthScale(Float_t scale)
Set global line-width scale.
Definition: TGLUtil.cxx:1868
ROOT::R::TRInterface & r
Definition: Object.C:4
void DrawSmoothFace(const TGLVertex3 &v1, const TGLVertex3 &v2, const TGLVertex3 &v3, const TGLVector3 &norm1, const TGLVector3 &norm2, const TGLVector3 &norm3)
Draws triangle face, each vertex has its own averaged normal.
Definition: TGLUtil.cxx:2950
Class to manage histogram axis.
Definition: TAxis.h:30
static void InitializeIfNeeded()
Initialize globals that require other libraries to be initialized.
Definition: TGLUtil.cxx:1543
void Dump() const
Output 16 matrix components to std::cout.
Definition: TGLUtil.cxx:1160
const Float_t gGreenEmission[]
Definition: TGLUtil.cxx:2809
const Float_t gRedEmission[]
Definition: TGLUtil.cxx:2808
SVector< double, 2 > v
Definition: Dict.h:5
static const UChar_t fgWhite[4]
Definition: TGLUtil.h:1051
static GLUtesselator * GetDrawTesselator4fv()
Returns a tesselator for direct drawing when using 4-vertices with single precision.
Definition: TGLUtil.cxx:1510
auto * a
Definition: textangle.C:12
TGLColorSet()
Constructor. Sets default for dark background.
Definition: TGLUtil.cxx:1360
TGLVector3 Norm() const
Definition: TGLUtil.h:557
static void Color4f(Float_t r, Float_t g, Float_t b, Float_t a)
Wrapper for glColor4f.
Definition: TGLUtil.cxx:1756
std::pair< Bool_t, TGLLine3 > Intersection(const TGLPlane &p1, const TGLPlane &p2)
Find 3D line interestion of this plane with &#39;other&#39;.
Definition: TGLUtil.cxx:544
Double_t A() const
Definition: TGLUtil.h:552
const Float_t gGrayEmission[]
Definition: TGLUtil.cxx:2813
Helper class for plot-painters holding information about axis ranges, numbers of bins and flags if ce...
const Double_t * CArr() const
Definition: TGLUtil.h:663
void Minimum(const TGLVertex3 &other)
Definition: TGLUtil.cxx:112
unsigned int UInt_t
Definition: RtypesCore.h:42
static void DrawNumber(const TString &num, const TGLVertex3 &pos, Bool_t center=kFALSE)
Draw number in string &#39;num&#39; via internal 8x8-pixel bitmap on vertex &#39;pos&#39;.
Definition: TGLUtil.cxx:2595
const Rgl::Range_t & GetXRange() const
X range.
void CylindricalNormal(const Double_t *v, Double_t *normal)
Definition: TGLUtil.cxx:3287
char * Form(const char *fmt,...)
const Int_t gBoxBackQuads[][4]
Definition: TGLUtil.cxx:2967
const TGLVector3 & Vector() const
Definition: TGLUtil.h:407
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb"...
Definition: TColor.cxx:1758
Double_t C() const
Definition: TGLUtil.h:554
The axis painter class.
Definition: TGaxis.h:24
UInt_t fTexture
Definition: TGLUtil.h:1342
static void Color4fv(const Float_t *rgba)
Wrapper for glColor4fv.
Definition: TGLUtil.cxx:1772
3D space, fixed length, line class, with direction / length &#39;vector&#39;, passing through point &#39;vertex&#39;...
Definition: TGLUtil.h:387
static Float_t PointSize()
Get the point-size, taking the global scaling into account.
Definition: TGLUtil.cxx:1896
const Double_t gBoxFrontNormals[][3]
Definition: TGLUtil.cxx:2964
void Dump() const
Output plane equation to std::out.
Definition: TGLUtil.cxx:444
static double p1(double t, double a, double b)
~TGLDisableGuard()
TGLDisableGuard destructor.
Definition: TGLUtil.cxx:2740
TGLPlane()
Construct a default plane of x + y + z = 0.
Definition: TGLUtil.cxx:366
UChar_t GetGreen() const
Definition: TGLUtil.h:802
void DrawTransparentBox(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax, Int_t fp)
Draws lego&#39;s bar as a 3d box.
Definition: TGLUtil.cxx:3024
void Warning(const char *location, const char *msgfmt,...)
UChar_t GetRed() const
Definition: TGLUtil.h:801
Double_t XMax() const
TGLColor()
Default constructor. Color is initialized to black.
Definition: TGLUtil.cxx:1186
Bool_t fFlip
Definition: TGLUtil.h:1097
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition: TStyle.cxx:979
TGLColor fOutline
Definition: TGLUtil.h:839
lv DrawLine(0.33, 0.0, 0.33, 1.0)
#define gVirtualX
Definition: TVirtualX.h:350
#define h(i)
Definition: RSha256.hxx:106
Int_t Diagonal() const
Return the diagonal of the rectangle.
Definition: TGLUtil.cxx:316
Double_t Cos(Double_t)
Definition: TMath.h:640
static const UChar_t fgGreen[4]
Definition: TGLUtil.h:1048
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
int Ssiz_t
Definition: RtypesCore.h:63
#define d(i)
Definition: RSha256.hxx:102
Double_t Z() const
Definition: TGLUtil.h:122
static void Color3f(Float_t r, Float_t g, Float_t b)
Wrapper for glColor3f.
Definition: TGLUtil.cxx:1748
TGLColor fBackground
Definition: TGLUtil.h:837
Double_t Dot(const TGLVector3 &v1, const TGLVector3 &v2)
Definition: TGLUtil.h:318
static Float_t fgPointLineScalingFactor
Definition: TGLUtil.h:926
void SetLabelOffset(Float_t labeloffset)
Definition: TGaxis.h:107
return c2
Definition: legend2.C:14
static const double x1[5]
auto * t1
Definition: textangle.C:20
#define ClassImp(name)
Definition: Rtypes.h:359
void CylindricalNormalInv(const Double_t *v, Double_t *normal)
Definition: TGLUtil.cxx:3301
static Float_t fgScreenScalingFactor
Definition: TGLUtil.h:925
double Double_t
Definition: RtypesCore.h:55
void Negate()
Negate the plane.
Definition: TGLUtil.cxx:509
TGLVector3 WorldDeltaToViewport(const TGLVertex3 &worldRef, const TGLVector3 &worldDelta) const
Convert a 3D vector worldDelta (shift) about vertex worldRef to a viewport (screen) &#39;3D&#39; vector...
Definition: TGLCamera.cxx:426
const Int_t gFramePoints[][2]
Definition: TGLUtil.cxx:3717
TGLCapabilitySwitch(const TGLCapabilitySwitch &)
void DrawTrapezoidTextured(const Double_t ver[][2], Double_t zMin, Double_t zMax, Double_t tMin, Double_t tMax)
In polar coordinates, box became trapezoid.
Definition: TGLUtil.cxx:3385
void Draw(Bool_t solid=kFALSE) const
Draw the bounding box as either wireframe (default) of solid using current GL color.
void Rotate(const TGLVertex3 &pivot, const TGLVector3 &axis, Double_t angle)
Update matrix so resulting transform has been rotated about &#39;pivot&#39; (in parent frame), round vector &#39;axis&#39;, through &#39;angle&#39; (radians) Equivalent to glRotate function, but with addition of translation and compounded on top of existing.
Definition: TGLUtil.cxx:898
int type
Definition: TGX11.cxx:120
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
TCanvas * style()
Definition: style.C:1
Double_t y[n]
Definition: legend1.C:17
void MultRight(const TGLMatrix &rhs)
Multiply with matrix rhs on right.
Definition: TGLUtil.cxx:730
Color_t GetColorIndex() const
Returns color-index representing the color.
Definition: TGLUtil.cxx:1240
static void BeginExtendPickRegion(Float_t scale)
Definition: TGLUtil.cxx:1913
static void RenderPolyLine(const TAttLine &aline, Char_t transp, Float_t *p, Int_t n, Int_t pick_radius=0, Bool_t selection=kFALSE)
Render poly-line as specified by the p-array.
Definition: TGLUtil.cxx:2213
Short_t fIndex
Definition: TGLUtil.h:787
static constexpr double s
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
Bool_t IsScalingForRender() const
Return true if matrix is to be considered a scaling matrix for rendering.
Definition: TGLUtil.cxx:1139
The color creation and management class.
Definition: TColor.h:19
Double_t fVals[3]
Definition: TGLUtil.h:87
static void EndExtendPickRegion()
Definition: TGLUtil.cxx:1928
const Rgl::Range_t & GetYRange() const
Y range.
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition: TAxis.cxx:557
void DisableTexture() const
Disable 1D texture.
Definition: TGLUtil.cxx:4212
void DrawTrapezoid(const Double_t ver[][2], Double_t zMin, Double_t zMax, Bool_t color=kTRUE)
Definition: TGLUtil.cxx:3315
void DrawSphere(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax)
Cylinder for lego3.
Definition: TGLUtil.cxx:3242
static Float_t GetPointLineScalingFactor()
Return extra scaling factor for points and lines.
Definition: TGLUtil.cxx:1824
static Int_t CheckError(const char *loc)
Check current GL error state, outputting details via ROOT Error method if one.
Definition: TGLUtil.cxx:1607
Concrete class describing an orientated (free) or axis aligned box of 8 vertices. ...
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
void GetColor(Float_t v, Float_t vmin, Float_t vmax, Int_t type, Float_t *rgba)
This function creates color for parametric surface&#39;s vertex, using its &#39;u&#39; value. ...
Definition: TGLUtil.cxx:3844
const Double_t * CArr() const
Definition: TGLUtil.h:125
virtual ~TGLMatrix()
Destroy matrix object.
Definition: TGLUtil.cxx:723
char Char_t
Definition: RtypesCore.h:29
static void ResetDrawQuality()
static: reset draw quality
Definition: TGLUtil.cxx:1582
Int_t fHeight
Definition: TGLUtil.h:427
static Float_t GetLineWidthScale()
Returns global line-width scale.
Definition: TGLUtil.cxx:1860
TGLLine3(const TGLVertex3 &start, const TGLVertex3 &end)
Vector of line from fVertex.
Definition: TGLUtil.cxx:199
void Normalise()
Definition: TGLUtil.h:305
~TGLEnableGuard()
TGLEnableGuard destructor.
Definition: TGLUtil.cxx:2723
TGLDisableGuard(Int_t cap)
TGLDisableGuard constructor.
Definition: TGLUtil.cxx:2731
EOverlap
Definition: TGLUtil.h:33
static void RenderCrosses(const TAttMarker &marker, Float_t *p, Int_t n, Bool_t sec_selection=kFALSE)
Render markers as crosses.
Definition: TGLUtil.cxx:2101
TGLCapabilityEnabler(const TGLCapabilityEnabler &)
static Float_t fgLineWidthScale
Definition: TGLUtil.h:923
static GLUtesselator * GetDrawTesselator3dv()
Returns a tesselator for direct drawing when using 3-vertices with double precision.
Definition: TGLUtil.cxx:1521
void Maximum(const TGLVertex3 &other)
Definition: TGLUtil.cxx:121
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
void(* fFoo)(Float_t)
Definition: TGLUtil.h:1098
Double_t Sin(Double_t)
Definition: TMath.h:636
virtual ~TGLSelectionBuffer()
TGLSelectionBuffer destructor.
Definition: TGLUtil.cxx:2762
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
void Scale(const TGLVector3 &scale)
Set matrix axis scales to &#39;scale&#39;.
Definition: TGLUtil.cxx:862
#define gPad
Definition: TVirtualPad.h:285
static Int_t GetPickingRadius()
Returns picking radius.
Definition: TGLUtil.cxx:1832
Double_t YMin() const
#define c(i)
Definition: RSha256.hxx:101
static void SetDrawQuality(UInt_t dq)
static: set draw quality
Definition: TGLUtil.cxx:1574
void Draw() const
Draw line in current basic GL color.
Definition: TGLUtil.cxx:241
virtual ~TGLRect()
Destroy rect object.
Definition: TGLUtil.cxx:284
~TGLVertex3()
Destroy vertex object.
Definition: TGLUtil.cxx:86
static Float_t LineWidth()
Get the line-width, taking the global scaling into account.
Definition: TGLUtil.cxx:1904
unsigned char UChar_t
Definition: RtypesCore.h:34
TGLVector3 Cross(const TGLVector3 &v1, const TGLVector3 &v2)
Definition: TGLUtil.h:324
void DrawCylinder(TGLQuadric *quadric, Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax)
Cylinder for lego3.
Definition: TGLUtil.cxx:3211
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
Double_t Sqrt(Double_t x)
Definition: TMath.h:690
const Int_t gBoxFrontPlanes[][2]
Definition: TGLUtil.cxx:2965
static Float_t fgPointSize
Definition: TGLUtil.h:920
void Normalise()
Normalise the plane.
Definition: TGLUtil.cxx:426
void Shift(TGLVector3 &shift)
Offset a vertex by vector &#39;shift&#39;.
Definition: TGLUtil.cxx:93
Double_t ZMin() const
void DrawBoxFrontTextured(Double_t xMin, Double_t xMax, Double_t yMin, Double_t yMax, Double_t zMin, Double_t zMax, Double_t tMin, Double_t tMax, Int_t front)
Draws lego&#39;s bar as a 3d box LULULULU.
Definition: TGLUtil.cxx:3101
void SetColor(Int_t r, Int_t g, Int_t b, Int_t a=255)
Set color with Int_t values.
Definition: TGLUtil.cxx:1258
Int_t fWidth
Corner.
Definition: TGLUtil.h:427
Bool_t GeneratePalette(UInt_t paletteSize, const Rgl::Range_t &zRange, Bool_t checkSize=kTRUE)
Try to find colors for palette.
Definition: TGLUtil.cxx:4128
virtual ~TGLColorSet()
Destructor.
Definition: TGLUtil.cxx:1368
Double_t Y() const
Definition: TGLUtil.h:120
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
static void ColorAlpha(const TGLColor &color, UChar_t alpha)
Set color from TGLColor and alpha value.
Definition: TGLUtil.cxx:1666
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t fX
Definition: TGLUtil.h:426
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition: TMath.h:712
return c3
Definition: legend3.C:15
3D plane class - of format Ax + By + Cz + D = 0
Definition: TGLUtil.h:525
const Float_t gOrangeEmission[]
Definition: TGLUtil.cxx:2811
TString AsString() const
Return string describing the color.
Definition: TGLUtil.cxx:1343
~TGLVector3()
Destroy vector object.
Definition: TGLUtil.cxx:184
UChar_t fRGBA[4]
Definition: TGLUtil.h:786
static void SetDrawColors(const UChar_t rgba[4])
Set basic draw colors from 4 component &#39;rgba&#39; Used by other TGLUtil drawing routines.
Definition: TGLUtil.cxx:2297
const Int_t n
Definition: legend1.C:16
void SphericalNormal(const Double_t *v, Double_t *normal)
Definition: TGLUtil.cxx:3526
Line Attributes class.
Definition: TAttLine.h:18
TGLVector3 GetScale() const
Get local axis scaling factors.
Definition: TGLUtil.cxx:1127
TGLVector3()
Construct a default (0.0, 0.0, 0.0) vector.
Definition: TGLUtil.cxx:152
static void Color4ubv(const UChar_t *rgba)
Wrapper for glColor4ubv.
Definition: TGLUtil.cxx:1740
double log(double)
ELineHeadShape
Definition: TGLUtil.h:946
void MoveLF(Int_t ai, Double_t amount)
Translate in local frame.
Definition: TGLUtil.cxx:841
void Set(Int_t x, Int_t y, Int_t width, Int_t height)
Definition: TGLUtil.h:472
static void Color3ubv(const UChar_t *rgb)
Wrapper for glColor3ubv.
Definition: TGLUtil.cxx:1732
static UInt_t GetDefaultDrawQuality()
static: get default draw quality
Definition: TGLUtil.cxx:1590
UInt_t fPaletteSize
Definition: TGLUtil.h:1341
void Set(const TGLPlane &other)
Assign from other.
Definition: TGLUtil.cxx:453
const std::vector< Double_t > * fContours
Definition: TGLUtil.h:1340
const Int_t gAxisType[][2]
Definition: TGLUtil.cxx:3719
void Dump() const
Output vertex component values to std::cout.
Definition: TGLUtil.cxx:131
Double_t X() const
Definition: TGLUtil.h:118