Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGLRnrCtx.cxx
Go to the documentation of this file.
1 // @(#)root/gl:$Id$
2 // Author: Matevz Tadel, Feb 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, 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 "TVirtualX.h"
13 #include "TString.h"
14 #include "TROOT.h"
15 
16 #include "TGLRnrCtx.h"
17 #include "TGLSceneInfo.h"
18 #include "TGLSelectBuffer.h"
19 #include "TGLIncludes.h"
20 #include "TGLUtil.h"
21 #include "TGLCamera.h"
22 #include "TGLFontManager.h"
23 #include "TGLContext.h"
24 
25 #include "TError.h"
26 #include "TMathBase.h"
27 #include "TMath.h"
28 
29 #include <list>
30 #include <algorithm>
31 #include <cassert>
32 
33 /** \class TGLRnrCtx
34 \ingroup opengl
35 The TGLRnrCtx class aggregates data for a given redering context as
36 needed by various parts of the ROOT's OpenGL infrastructure. It
37 serves as a connecting point between the steering part of the
38 infrastructure (viewer, scene) and concrete rendering classes
39 (logical, physical shape). It is just a data-holder, there is no
40 functionality in it.
41 
42 Development notes:
43 
44 One RnrCtx is created by each viewer and it is just an extension of
45 the viewer context that changes along the render
46 descend. Separating this also has some abstract benefit of hiding
47 viewer implementation from those that do not need to know it.
48 
49 Current scene / scene-info part is always initialized by viewer,
50 scenes can assume they're ok.
51 */
52 
53 ClassImp(TGLRnrCtx);
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 
57 TGLRnrCtx::TGLRnrCtx(TGLViewerBase* viewer) :
58  fViewer (viewer),
59  fCamera (0),
60  fSceneInfo (0),
61 
62  fViewerLOD (kLODUndef),
63  fSceneLOD (kLODUndef),
64  fCombiLOD (kLODUndef),
65  fShapeLOD (kLODUndef),
66  fShapePixSize (0),
67 
68  fViewerStyle (kStyleUndef),
69  fSceneStyle (kStyleUndef),
70 
71  fViewerWFLineW (0),
72  fSceneWFLineW (0),
73  fViewerOLLineW (0),
74  fSceneOLLineW (0),
75 
76  fViewerClip (0),
77  fSceneClip (0),
78  fClip (0),
79  fDrawPass (kPassUndef),
80 
81  fStopwatch (),
82  fRenderTimeOut(0.0),
83  fIsRunning (kFALSE),
84  fHasTimedOut (kFALSE),
85 
86  fHighlight (kFALSE), fHighlightOutline (kFALSE),
87  fSelection (kFALSE), fSecSelection (kFALSE),
88  fSelectTransparents (kIfNoOpaques),
89  fPickRadius (0),
90  fPickRectangle(0),
91  fSelectBuffer (0),
92 
93  fColorSetStack(0),
94  fRenderScale (1),
95 
96  fEventKeySym (0),
97 
98  fDLCaptureOpen (kFALSE),
99  fGLCtxIdentity (0),
100  fQuadric (0),
101 
102  fGrabImage (kFALSE),
103  fGrabBuffer (-1),
104  fGrabbedImage (0)
105 {
106  // Constructor.
107 
108  fColorSetStack = new lpTGLColorSet_t;
109  fColorSetStack->push_back(0);
110 
111  fSelectBuffer = new TGLSelectBuffer;
112  if (fViewer == 0)
113  {
114  // Assume external usage, initialize for highest quality.
115  fViewerLOD = fSceneLOD = fCombiLOD = fShapeLOD = kLODHigh;
116  fViewerStyle = fSceneStyle = kFill;
117  fDrawPass = kPassFill;
118  }
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// Destructor.
123 
124 TGLRnrCtx::~TGLRnrCtx()
125 {
126  gluDeleteQuadric(fQuadric);
127  delete fPickRectangle;
128  delete fSelectBuffer;
129  delete fColorSetStack;
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Return current scene (based on scene-info data).
134 
135 TGLSceneBase * TGLRnrCtx::GetScene()
136 {
137  return fSceneInfo->GetScene();
138 }
139 
140 ////////////////////////////////////////////////////////////////////////////////
141 /// Return current scene (based on scene-info data).
142 
143 TGLSceneBase & TGLRnrCtx::RefScene()
144 {
145  return *fSceneInfo->GetScene();
146 }
147 
148 /**************************************************************************/
149 
150 ////////////////////////////////////////////////////////////////////////////////
151 /// Returns true if current render-pass uses filled polygon style.
152 
153 Bool_t TGLRnrCtx::IsDrawPassFilled() const
154 {
155  return fDrawPass == kPassFill || fDrawPass == kPassOutlineFill;
156 }
157 
158 
159 /******************************************************************************/
160 // Stopwatch
161 /******************************************************************************/
162 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// Start the stopwatch.
165 
166 void TGLRnrCtx:: StartStopwatch()
167 {
168  if (fIsRunning)
169  return;
170 
171  fStopwatch.Start();
172  fIsRunning = kTRUE;
173  fHasTimedOut = kFALSE;
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Stop the stopwatch.
178 
179 void TGLRnrCtx:: StopStopwatch()
180 {
181  fHasTimedOut = fStopwatch.End() > fRenderTimeOut;
182  fIsRunning = kFALSE;
183 }
184 
185 ////////////////////////////////////////////////////////////////////////////////
186 /// Check if the stopwatch went beyond the render time limit.
187 
188 Bool_t TGLRnrCtx::HasStopwatchTimedOut()
189 {
190  if (fHasTimedOut) return kTRUE;
191  if (fIsRunning && fStopwatch.Lap() > fRenderTimeOut)
192  fHasTimedOut = kTRUE;
193  return fHasTimedOut;
194 }
195 
196 
197 /******************************************************************************/
198 // Selection & picking
199 /******************************************************************************/
200 
201 ////////////////////////////////////////////////////////////////////////////////
202 /// Setup context for running selection.
203 /// x and y are in window coordinates.
204 
205 void TGLRnrCtx::BeginSelection(Int_t x, Int_t y, Int_t r)
206 {
207  fSelection = kTRUE;
208  fSecSelection = kFALSE;
209  fPickRadius = r;
210  if (!fPickRectangle) fPickRectangle = new TGLRect;
211  fPickRectangle->Set(x, y, r, r);
212 
213  glSelectBuffer(fSelectBuffer->GetBufSize(), fSelectBuffer->GetBuf());
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// End selection.
218 
219 void TGLRnrCtx::EndSelection(Int_t glResult)
220 {
221  fSelection = kFALSE;
222  fSecSelection = kFALSE;
223  fPickRadius = 0;
224  delete fPickRectangle; fPickRectangle = 0;
225 
226  if (glResult < 0)
227  {
228  if (fSelectBuffer->CanGrow())
229  {
230  Warning("TGLRnrCtx::EndSelection",
231  "Select buffer size (%d) insufficient, doubling it.",
232  fSelectBuffer->GetBufSize());
233  fSelectBuffer->Grow();
234  }
235  else
236  {
237  Warning("TGLRnrCtx::EndSelection",
238  "Select buffer size (%d) insufficient. This is maximum.",
239  fSelectBuffer->GetBufSize());
240  }
241  }
242  fSelectBuffer->ProcessResult(glResult);
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Return current pick rectangle. This is *zero* when
247 /// selection is not set.
248 
249 TGLRect * TGLRnrCtx::GetPickRectangle()
250 {
251  return fPickRectangle;
252 }
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Return pick radius. If selection is not active it returns 0.
256 
257 Int_t TGLRnrCtx::GetPickRadius()
258 {
259  return fPickRadius;
260 }
261 
262 
263 /**************************************************************************/
264 // ColorSet access & management
265 /******************************************************************************/
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Create copy of current color-set on the top of the stack.
269 
270 void TGLRnrCtx::PushColorSet()
271 {
272  fColorSetStack->push_back(new TGLColorSet(*fColorSetStack->back()));
273 }
274 
275 ////////////////////////////////////////////////////////////////////////////////
276 /// Return reference to current color-set (top of the stack).
277 
278 TGLColorSet& TGLRnrCtx::ColorSet()
279 {
280  return * fColorSetStack->back();
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Pops the top-most color-set.
285 /// If only one entry is available, error is printed and the entry remains.
286 
287 void TGLRnrCtx::PopColorSet()
288 {
289  if (fColorSetStack->size() >= 2)
290  {
291  delete fColorSetStack->back();
292  fColorSetStack->pop_back();
293  }
294  else
295  {
296  Error("PopColorSet()", "Attempting to remove the last entry.");
297  }
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Change the default/bottom color-set.
302 /// Returns the previous color-set.
303 
304 TGLColorSet* TGLRnrCtx::ChangeBaseColorSet(TGLColorSet* set)
305 {
306  TGLColorSet* old = fColorSetStack->front();
307  fColorSetStack->front() = set;
308  return old;
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Returns the current base color-set.
313 
314 TGLColorSet* TGLRnrCtx::GetBaseColorSet()
315 {
316  return fColorSetStack->front();
317 }
318 
319 ////////////////////////////////////////////////////////////////////////////////
320 /// Set col if it is different from background, otherwise use
321 /// current foreground color.
322 
323 void TGLRnrCtx::ColorOrForeground(Color_t col)
324 {
325  if (fColorSetStack->back()->Background().GetColorIndex() == col)
326  TGLUtil::Color(fColorSetStack->back()->Foreground());
327  else
328  TGLUtil::Color(col);
329 }
330 
331 /**************************************************************************/
332 // Display-list state
333 /******************************************************************************/
334 
335 ////////////////////////////////////////////////////////////////////////////////
336 /// Start display-list capture.
337 
338 void TGLRnrCtx::OpenDLCapture()
339 {
340  assert(fDLCaptureOpen == kFALSE);
341  fDLCaptureOpen = kTRUE;
342 }
343 
344 ////////////////////////////////////////////////////////////////////////////////
345 /// End display list capture.
346 
347 void TGLRnrCtx::CloseDLCapture()
348 {
349  assert(fDLCaptureOpen == kTRUE);
350  fDLCaptureOpen = kFALSE;
351 }
352 
353 /******************************************************************************/
354 // TGLFont interface
355 /******************************************************************************/
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Release font in the GL rendering context.
358 
359 void TGLRnrCtx::ReleaseFont(TGLFont& font)
360 {
361  fGLCtxIdentity->GetFontManager()->ReleaseFont(font);
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Get font in the GL rendering context.
366 
367 void TGLRnrCtx::RegisterFontNoScale(Int_t size, Int_t file, Int_t mode, TGLFont& out)
368 {
369  fGLCtxIdentity->GetFontManager()->RegisterFont( size, file, (TGLFont::EMode)mode, out);
370 }
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Get font in the GL rendering context.
374 
375 void TGLRnrCtx::RegisterFontNoScale(Int_t size, const char* name, Int_t mode, TGLFont& out)
376 {
377  fGLCtxIdentity->GetFontManager()->RegisterFont(size, name, (TGLFont::EMode)mode, out);
378 }
379 
380 ////////////////////////////////////////////////////////////////////////////////
381 /// Get font in the GL rendering context.
382 /// The font is scaled relative to current render scale.
383 
384 void TGLRnrCtx::RegisterFont(Int_t size, Int_t file, Int_t mode, TGLFont& out)
385 {
386  RegisterFontNoScale(TMath::Nint(size*fRenderScale), file, mode, out);
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Get font in the GL rendering context.
391 /// The font is scaled relative to current render scale.
392 
393 void TGLRnrCtx::RegisterFont(Int_t size, const char* name, Int_t mode, TGLFont& out)
394 {
395  RegisterFontNoScale(TMath::Nint(size*fRenderScale), name, mode, out);
396 }
397 
398 /******************************************************************************/
399 // fQuadric's initialization.
400 /******************************************************************************/
401 
402 ////////////////////////////////////////////////////////////////////////////////
403 /// Initialize fQuadric.
404 
405 GLUquadric *TGLRnrCtx::GetGluQuadric()
406 {
407  if (!fQuadric) {
408  if ((fQuadric = gluNewQuadric())) {
409  gluQuadricOrientation(fQuadric, (GLenum)GLU_OUTSIDE);
410  gluQuadricNormals(fQuadric, (GLenum)GLU_SMOOTH);
411  } else
412  Error("TGLRnrCtx::GetGluQuadric", "gluNewQuadric failed");
413  }
414 
415  return fQuadric;
416 }
417 
418 
419 /******************************************************************************/
420 // Matrix manipulation helpers
421 /******************************************************************************/
422 
423 void TGLRnrCtx::ProjectionMatrixPushIdentity()
424 {
425  glMatrixMode(GL_PROJECTION);
426  glPushMatrix();
427  glLoadIdentity();
428  if (Selection())
429  {
430  TGLRect rect(*GetPickRectangle());
431  GetCamera()->WindowToViewport(rect);
432  gluPickMatrix(rect.X(), rect.Y(), rect.Width(), rect.Height(),
433  (Int_t*) GetCamera()->RefViewport().CArr());
434  }
435  glMatrixMode(GL_MODELVIEW);
436 }
437 
438 void TGLRnrCtx::ProjectionMatrixPop()
439 {
440  glMatrixMode(GL_PROJECTION);
441  glPopMatrix();
442  glMatrixMode(GL_MODELVIEW);
443 }
444 
445 
446 /**************************************************************************/
447 // Static helpers
448 /**************************************************************************/
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Return string describing the style.
452 
453 const char* TGLRnrCtx::StyleName(Short_t style)
454 {
455  switch (style)
456  {
457  case TGLRnrCtx::kFill: return "Filled Polys";
458  case TGLRnrCtx::kWireFrame: return "Wireframe";
459  case TGLRnrCtx::kOutline: return "Outline";
460  default: return "Oogaa-dooga style";
461  }
462 }