Main MRPT website > C++ reference
MRPT logo
CDisplayWindow3D.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef CDisplayWindow3D_H
29 #define CDisplayWindow3D_H
30 
32 #include <mrpt/opengl.h>
34 #include <mrpt/utils/CImage.h>
35 
36 /*---------------------------------------------------------------
37  Class
38  ---------------------------------------------------------------*/
39 namespace mrpt
40 {
41  namespace gui
42  {
43  using namespace mrpt::utils;
44 
45  class C3DWindowDialog;
46  class CMyGLCanvas_DisplayWindow3D;
47 
49 
50  /** A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.
51  * This class always contains internally an instance of opengl::COpenGLScene, which
52  * the objects, viewports, etc. to be rendered.
53  *
54  * Images can be grabbed automatically to disk for easy creation of videos.
55  * See CDisplayWindow3D::grabImagesStart (and for creating videos, mrpt::utils::CVideoFileWriter).
56  *
57  * A short-cut for displaying 2D images (using the OpenGL rendering hardware) is available
58  * through \a setImageView() and \a setImageView_fast(). Internally, these methods call methods
59  * in the "main" viewport of the window (see \a COpenGLViewport).
60  *
61  * Since the 3D rendering is performed in a detached thread, especial care must be taken
62  * when updating the 3D scene to be rendered. The process involves an internal critical section
63  * and it must always consist of these steps:
64  *
65  * \code
66  * CDisplayWindow3D win("My window");
67  *
68  * // Adquire the scene:
69  * opengl::COpenGLScenePtr &ptrScene = win.get3DSceneAndLock();
70  *
71  * // Modify the scene:
72  * ptrScene->...
73  * // or replace by another scene:
74  * ptrScene = otherScene;
75  *
76  * // Unlock it, so the window can use it for redraw:
77  * win.unlockAccess3DScene();
78  *
79  * // Update window, if required
80  * win.forceRepaint();
81  * \endcode
82  *
83  * An alternative way of updating the scene is by creating, before locking the 3D window, a new object
84  * of class COpenGLScene, then locking the window only for replacing the smart pointer. This may be
85  * advantageous is generating the 3D scene takes a long time, since while the window
86  * is locked it will not be responsive to the user input or window redraw.
87  *
88  * The window can also display a set of 2D text messages overlapped to the 3D scene.
89  * See CDisplayWindow3D::add2DTextMessage
90  *
91  * For a list of supported events with the observer/observable pattern, see the discussion in mrpt::gui::CBaseGUIWindow.
92  * In addition to those events, this class introduces mrpt::gui::mrptEvent3DWindowGrabImageFile
93  *
94  *
95  * \sa The example /samples/display3D, the <a href="http://www.mrpt.org/Tutorial_3D_Scenes" > tutorial only</a>.
96  * \ingroup mrpt_gui_grp
97  */
98  class GUI_IMPEXP CDisplayWindow3D : public mrpt::gui::CBaseGUIWindow
99  {
100  // This must be added to any CObject derived class:
102 
103  protected:
104  friend class C3DWindowDialog;
105  friend class CMyGLCanvas_DisplayWindow3D;
106 
107 
108  float m_FOV;
109 
110 
111  /** Internal OpenGL object (see general discussion in about usage of this object)
112  */
113  opengl::COpenGLScenePtr m_3Dscene;
114 
115  /** Critical section for accesing m_3Dscene
116  */
117  synch::CCriticalSection m_csAccess3DScene;
118 
119  /** Throws an exception on initialization error
120  */
121  void createOpenGLContext();
122 
123  void_ptr_noncopy m_DisplayDeviceContext;
124  void_ptr_noncopy m_GLRenderingContext;
125 
126  std::string m_grab_imgs_prefix;
127  unsigned int m_grab_imgs_idx;
128 
129  bool m_is_capturing_imgs;
130  CImagePtr m_last_captured_img;
131  synch::CCriticalSection m_last_captured_img_cs;
132 
133  void doRender();
134 
135  mrpt::system::TTimeStamp m_lastFullScreen;
136 
137  double m_last_FPS; //!< \sa getRenderingFPS
138 
139  void internalSetMinMaxRange();
140 
141  public:
142  /** Constructor
143  */
145  const std::string &windowCaption = std::string(),
146  unsigned int initialWindowWidth = 400,
147  unsigned int initialWindowHeight = 300 );
148 
149  /** Class factory returning a smart pointer */
150  static CDisplayWindow3DPtr Create(
151  const std::string &windowCaption = std::string(),
152  unsigned int initialWindowWidth = 400,
153  unsigned int initialWindowHeight = 300 )
154  {
155  return CDisplayWindow3DPtr(new CDisplayWindow3D(windowCaption,initialWindowWidth,initialWindowHeight));
156  }
157 
158  /** Destructor
159  */
160  virtual ~CDisplayWindow3D();
161 
162  /** Gets a reference to the smart shared pointer that holds the internal scene (carefuly read introduction in gui::CDisplayWindow3D before use!)
163  * This also locks the critical section for accesing the scene, thus the window will not be repainted until it is unlocked.
164  */
165  opengl::COpenGLScenePtr & get3DSceneAndLock( );
166 
167  /** Unlocks the access to the internal 3D scene.
168  * Typically user will want to call forceRepaint after updating the scene.
169  */
170  void unlockAccess3DScene();
171 
172  /** Repaints the window.
173  * forceRepaint, repaint and updateWindow are all aliases of the same method.
174  */
175  void forceRepaint();
176 
177  /** Repaints the window.
178  * forceRepaint, repaint and updateWindow are all aliases of the same method.
179  */
180  void repaint() { forceRepaint(); }
181 
182  /** Repaints the window.
183  * forceRepaint, repaint and updateWindow are all aliases of the same method.
184  */
185  void updateWindow() { forceRepaint(); }
186 
187  /** Return the camera field of view (in degrees) (used for gluPerspective).
188  */
189  float getFOV() const { return m_FOV; };
190 
191  /** Changes the camera min clip range (z) (used for gluPerspective).
192  * The window is not updated with this method, call "forceRepaint" to update the 3D view.
193  */
194  void setMinRange(double new_min);
195 
196  /** Changes the camera max clip range (z) (used for gluPerspective).
197  * The window is not updated with this method, call "forceRepaint" to update the 3D view.
198  */
199  void setMaxRange(double new_max);
200 
201  /** Changes the camera field of view (in degrees) (used for gluPerspective).
202  * The window is not updated with this method, call "forceRepaint" to update the 3D view.
203  */
204  void setFOV(float v) { m_FOV=v; };
205 
206  /** Resizes the window, stretching the image to fit into the display area.
207  */
208  void resize( unsigned int width, unsigned int height );
209 
210  /** Changes the position of the window on the screen.
211  */
212  void setPos( int x, int y );
213 
214  /** Changes the window title.
215  */
216  void setWindowTitle( const std::string &str );
217 
218  /** Changes the camera parameters programatically
219  */
220  void setCameraElevationDeg( float deg );
221 
222  /** Changes the camera parameters programatically
223  */
224  void setCameraAzimuthDeg( float deg );
225 
226  /** Changes the camera parameters programatically
227  */
228  void setCameraPointingToPoint( float x,float y, float z );
229 
230  /** Changes the camera parameters programatically
231  */
232  void setCameraZoom( float zoom );
233 
234  /** Sets the camera as projective, or orthogonal. */
235  void setCameraProjective( bool isProjective );
236 
237 
238  /** Get camera parameters programatically */
239  float getCameraElevationDeg() const;
240 
241  /** Get camera parameters programatically */
242  float getCameraAzimuthDeg() const;
243 
244  /** Get camera parameters programatically */
245  void getCameraPointingToPoint( float &x,float &y, float &z ) const;
246 
247  /** Get camera parameters programatically */
248  float getCameraZoom() const;
249 
250  /** Sets the camera as projective, or orthogonal. */
251  bool isCameraProjective() const;
252 
253  /** If set to true (default = false), the mouse-based scene navigation will be disabled and the camera position will be determined by the opengl viewports in the 3D scene.
254  */
255  void useCameraFromScene(bool useIt = true);
256 
257  /** Gets the 3D ray for the direction line of the pixel where the mouse cursor is at. \return False if the window is closed. \sa getLastMousePosition */
258  bool getLastMousePositionRay(mrpt::math::TLine3D &ray) const;
259 
260  /** Gets the last x,y pixel coordinates of the mouse. \return False if the window is closed. \sa getLastMousePositionRay */
261  virtual bool getLastMousePosition(int &x, int &y) const;
262 
263  /** Set cursor style to default (cursorIsCross=false) or to a cross (cursorIsCross=true) \sa getLastMousePositionRay */
264  virtual void setCursorCross(bool cursorIsCross);
265 
266  /** Start to save rendered images to disk.
267  * Images will be saved independently as png files, depending on
268  * the template path passed to this method. For example:
269  *
270  * path_prefix: "./video_"
271  *
272  * Will generate "./video_000001.png", etc.
273  *
274  * If this feature is enabled, the window will emit events of the type mrpt::gui::mrptEvent3DWindowGrabImageFile() which you can subscribe to.
275  *
276  * \sa grabImagesStop
277  */
278  void grabImagesStart( const std::string &grab_imgs_prefix = std::string("video_") );
279 
280  /** Stops image grabbing started by grabImagesStart
281  * \sa grabImagesStart
282  */
283  void grabImagesStop();
284 
285  /** Enables the grabbing of CImage objects from screenshots of the window.
286  * \sa getLastWindowImage
287  */
288  void captureImagesStart();
289 
290  /** Stop image grabbing
291  * \sa captureImagesStart
292  */
293  void captureImagesStop();
294 
295  /** Retrieve the last captured image from the window.
296  * You MUST CALL FIRST captureImagesStart to enable image grabbing.
297  * \sa captureImagesStart, getLastWindowImagePtr
298  */
299  void getLastWindowImage( mrpt::utils::CImage &out_img) const;
300 
301  /** Retrieve the last captured image from the window, as a smart pointer.
302  * This method is more efficient than getLastWindowImage since only a copy of the pointer is performed, while
303  * getLastWindowImage would copy the entire image.
304  *
305  * You MUST CALL FIRST captureImagesStart to enable image grabbing.
306  * \sa captureImagesStart, getLastWindowImage
307  */
308  mrpt::utils::CImagePtr getLastWindowImagePtr() const;
309 
310  /** Increments by one the image counter and return the next image file name (Users normally don't want to call this method).
311  * \sa grabImagesStart
312  */
313  std::string grabImageGetNextFile();
314 
315  bool isCapturingImgs() const { return m_is_capturing_imgs; }
316 
317 
318  /** Add 2D text messages overlapped to the 3D rendered scene. The string will remain displayed in the 3D window
319  * until it's changed with subsequent calls to this same method, or all the texts are cleared with clearTextMessages().
320  *
321  * \param x The X position, interpreted as absolute pixels from the left if X>=1, absolute pixels from the left if X<0 or as a width factor if in the range [0,1[.
322  * \param y The Y position, interpreted as absolute pixels from the bottom if Y>=1, absolute pixels from the top if Y<0 or as a height factor if in the range [0,1[.
323  * \param text The text string to display.
324  * \param color The text color. For example: TColorf(1.0,1.0,1.0)
325  * \param unique_index An "index" for this text message, so that subsequent calls with the same index will overwrite this text message instead of creating new ones.
326  *
327  * You'll need to refresh the display manually with forceRepaint().
328  *
329  * \sa clearTextMessages
330  */
331  void addTextMessage(
332  const double x,
333  const double y,
334  const std::string &text,
335  const mrpt::utils::TColorf &color = mrpt::utils::TColorf(1.0,1.0,1.0),
336  const size_t unique_index = 0,
338  );
339 
340  /* \overload with more font parameters - refer to mrpt::opengl::gl_utils::glDrawText()
341  * Available fonts are enumerated at mrpt::opengl::gl_utils::glSetFont() */
342  void addTextMessage(
343  const double x_frac,
344  const double y_frac,
345  const std::string &text,
346  const mrpt::utils::TColorf &color,
347  const std::string &font_name,
348  const double font_size,
350  const size_t unique_index = 0,
351  const double font_spacing = 1.5,
352  const double font_kerning = 0.1
353  );
354 
355  /** Clear all text messages created with addTextMessage().
356  * You'll need to refresh the display manually with forceRepaint().
357  * \sa addTextMessage
358  */
359  void clearTextMessages();
360 
361  /** Get the average Frames Per Second (FPS) value from the last 250 rendering events */
362  double getRenderingFPS() const { return m_last_FPS; }
363 
364  /** A short cut for getting the "main" viewport of the scene object, it is equivalent to:
365  * \code
366  * mrpt::opengl::COpenGLScenePtr &scene = win3D.get3DSceneAndLock();
367  * viewport = scene->getViewport("main");
368  * win3D.unlockAccess3DScene();
369  * \endcode
370  */
371  mrpt::opengl::COpenGLViewportPtr getDefaultViewport();
372 
373  /** Set the "main" viewport into "image view"-mode, where an image is efficiently drawn (fitting the viewport area) using an OpenGL textured quad.
374  * Call this method with the new image to update the displayed image (but recall to first lock the parent openglscene's critical section, then do the update, then release the lock, and then issue a window repaint).
375  * Internally, the texture is drawn using a mrpt::opengl::CTexturedPlane
376  * The viewport can be reverted to behave like a normal viewport by calling setNormalMode()
377  * \sa setImageView_fast, COpenGLViewport
378  */
379  void setImageView(const mrpt::utils::CImage &img);
380 
381  /** Just like \a setImageView but moves the internal image memory instead of making a copy, so it's faster but empties the input image.
382  * \sa setImageView, COpenGLViewport
383  */
384  void setImageView_fast(mrpt::utils::CImage &img);
385 
386 
387  protected:
388  void internal_setRenderingFPS(double FPS); //!< Set the rendering FPS (users don't call this, the method is for internal MRPT objects only) \sa getRenderingFPS
389  void internal_emitGrabImageEvent(const std::string &fil); //!< called by CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers
390 
391  }; // End of class def.
392 
393 
394  /** @name Events specific to CDisplayWindow3D
395  @{ */
396 
397  /** An event sent by a CDisplayWindow3D window when an image is saved after enabling this feature with CDisplayWindow3D::grabImagesStart()
398  *
399  * IMPORTANTE NOTICE: Event handlers in your observer class will be invoked from the wxWidgets internal MRPT thread,
400  * so all your code in the handler must be thread safe.
401  */
403  {
404  protected:
405  virtual void do_nothing() { } //!< Just to allow this class to be polymorphic
406  public:
408  CDisplayWindow3D *obj,
409  const std::string &_img_file
410  ) : source_object(obj), img_file(_img_file) { }
411 
413  const std::string &img_file; //!< The absolute path of the file that has been just saved.
414  }; // End of class def.
415 
416  /** @} */
417 
418 
419  } // End of namespace
420 } // End of namespace
421 
422 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013