MRPT  1.9.9
CDisplayWindow3D.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "gui-precomp.h" // Precompiled headers
11 
12 #include <mrpt/config.h>
13 
15 #include <mrpt/img/CImage.h>
16 #include <mrpt/system/CTicTac.h>
17 
18 #include <mrpt/gui/WxSubsystem.h>
19 #include <mrpt/gui/WxUtils.h>
20 
21 #if MRPT_HAS_OPENGL_GLUT
22 #ifdef _WIN32
23 // Windows:
24 #include <windows.h>
25 #endif
26 
27 #ifdef __APPLE__
28 #include <GLUT/glut.h>
29 #include <OpenGL/gl.h>
30 #include <OpenGL/glu.h>
31 #else
32 #include <GL/gl.h>
33 #include <GL/glu.h>
34 #include <GL/glut.h>
35 #ifdef HAVE_FREEGLUT_EXT_H
36 #include <GL/freeglut_ext.h>
37 #endif
38 #endif
39 #endif
40 
41 using namespace mrpt;
42 using namespace mrpt::gui;
43 using namespace mrpt::opengl;
44 using namespace mrpt::math;
45 using namespace mrpt::img;
46 using namespace std;
47 
48 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
49 
50 #if !wxUSE_GLCANVAS
51 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild wxWidgets"
52 #endif
53 
56 
57 namespace mrpt::gui
58 {
59 class CMyGLCanvas_DisplayWindow3D : public mrpt::gui::CWxGLCanvasBase
60 {
61  public:
62  CMyGLCanvas_DisplayWindow3D(
63  CDisplayWindow3D* win3D, wxWindow* parent, wxWindowID id = wxID_ANY,
64  const wxPoint& pos = wxDefaultPosition,
65  const wxSize& size = wxDefaultSize, long style = 0,
66  const wxString& name = _T("CMyGLCanvas_DisplayWindow3D"));
67 
68  ~CMyGLCanvas_DisplayWindow3D() override;
69 
70  CDisplayWindow3D* m_win3D = nullptr;
71 
72  // The idea is that CMyGLCanvas_DisplayWindow3D was derived from
73  // CTextMessageCapable, but
74  // that raises errors in MSVC when converting method pointers to
75  // wxObjectEventFunction...
76  struct THubClass : public mrpt::opengl::CTextMessageCapable
77  {
78  void render_text_messages_public(const int w, const int h) const
79  {
80  render_text_messages(w, h);
81  }
82  };
83  THubClass m_text_msgs;
84 
85  void OnCharCustom(wxKeyEvent& event) override;
86  void OnMouseDown(wxMouseEvent& event);
87  void OnMouseMove(wxMouseEvent& event);
88 
89  void OnPreRender() override;
90  void OnPostRender() override;
91  void OnPostRenderSwapBuffers(double At, wxPaintDC& dc) override;
92 
93  static void display3D_processKeyEvent(
94  CDisplayWindow3D* m_win3D, wxKeyEvent& ev);
95 };
96 } // namespace mrpt::gui
97 
98 CMyGLCanvas_DisplayWindow3D::CMyGLCanvas_DisplayWindow3D(
99  CDisplayWindow3D* win3D, wxWindow* parent, wxWindowID id,
100  const wxPoint& pos, const wxSize& size, long style, const wxString& name)
101  : CWxGLCanvasBase(parent, id, pos, size, style, name), m_win3D(win3D)
102 {
103  this->Bind(wxEVT_CHAR, &CMyGLCanvas_DisplayWindow3D::OnCharCustom, this);
104  this->Bind(
105  wxEVT_CHAR_HOOK, &CMyGLCanvas_DisplayWindow3D::OnCharCustom, this);
106  this->Bind(
107  wxEVT_LEFT_DOWN, &CMyGLCanvas_DisplayWindow3D::OnMouseDown, this);
108  this->Bind(
109  wxEVT_RIGHT_DOWN, &CMyGLCanvas_DisplayWindow3D::OnMouseDown, this);
110  this->Bind(wxEVT_MOTION, &CMyGLCanvas_DisplayWindow3D::OnMouseMove, this);
111 }
112 
113 void CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(
114  CDisplayWindow3D* m_win3D, wxKeyEvent& ev)
115 {
116  if (m_win3D)
117  {
118  if (ev.AltDown() && ev.GetKeyCode() == MRPTK_RETURN)
119  {
121  m_win3D->m_lastFullScreen, mrpt::system::now()) > 0.2)
122  {
123  m_win3D->m_lastFullScreen = mrpt::system::now();
124  cout << "[CDisplayWindow3D] Switching fullscreen...\n";
125  auto* win = (C3DWindowDialog*)m_win3D->m_hwnd.get();
126  if (win)
127  {
128  win->ShowFullScreen(!win->IsFullScreen());
129  }
130  }
131  // Alt+Enter: Don't notify on this key stroke, since if we're
132  // switching to fullscreen
133  // and the user is waiting for a key to close the window, a runtime
134  // crash will occur,
135  // so return now:
136  return;
137  }
138 
139  const int code = ev.GetKeyCode();
141 
142  m_win3D->m_keyPushedCode = code;
143  m_win3D->m_keyPushedModifier = mod;
144  m_win3D->m_keyPushed = true;
145 
146  // Send the event:
147  try
148  {
149  m_win3D->publishEvent(mrptEventWindowChar(m_win3D, code, mod));
150  }
151  catch (...)
152  {
153  }
154  }
155  // ev.Skip(); // Pass the event to whoever else.
156 }
157 
158 void CMyGLCanvas_DisplayWindow3D::OnCharCustom(wxKeyEvent& ev)
159 {
160  CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(m_win3D, ev);
161 }
162 
163 void CMyGLCanvas_DisplayWindow3D::OnMouseDown(wxMouseEvent& event)
164 {
165  // Send the event:
166  if (m_win3D && m_win3D->hasSubscribers())
167  {
168  try
169  {
171  m_win3D, TPixelCoord(event.GetX(), event.GetY()),
172  event.LeftDown(), event.RightDown()));
173  }
174  catch (...)
175  {
176  }
177  }
178 
179  event.Skip(); // so it's processed by the wx system!
180 }
181 
182 void CMyGLCanvas_DisplayWindow3D::OnMouseMove(wxMouseEvent& event)
183 {
184  // Send the event:
185  if (m_win3D && m_win3D->hasSubscribers())
186  {
187  try
188  {
190  m_win3D, TPixelCoord(event.GetX(), event.GetY()),
191  event.LeftDown(), event.RightDown()));
192  }
193  catch (...)
194  {
195  }
196  }
197 
198  event.Skip(); // so it's processed by the wx system!
199 }
200 
201 CMyGLCanvas_DisplayWindow3D::~CMyGLCanvas_DisplayWindow3D()
202 {
203  getOpenGLSceneRef().reset(); // Avoid the base class to free this object
204  // (it's freed by CDisplayWindow3D)
205 }
206 
207 void CMyGLCanvas_DisplayWindow3D::OnPreRender()
208 {
209  auto& openGLSceneRef = getOpenGLSceneRef();
210  if (openGLSceneRef) openGLSceneRef.reset();
211 
212  COpenGLScene::Ptr& ptrScene = m_win3D->get3DSceneAndLock();
213  if (ptrScene) openGLSceneRef = ptrScene;
214 }
215 
216 void CMyGLCanvas_DisplayWindow3D::OnPostRender()
217 {
218  // Avoid the base class to free this object (it's freed by CDisplayWindow3D)
219  getOpenGLSceneRef().reset();
220  m_win3D->unlockAccess3DScene();
221 
222  // If any, draw the 2D text messages:
223  int w, h;
224  this->GetSize(&w, &h);
225 
226  m_text_msgs.render_text_messages_public(w, h);
227 }
228 
229 void CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers(
230  double At, wxPaintDC& dc)
231 {
232  if (m_win3D) m_win3D->internal_setRenderingFPS(At > 0 ? 1.0 / At : 1e9);
233 
234  // If we are requested to do so, grab images to disk as they are rendered:
235  string grabFile;
236  if (m_win3D) grabFile = m_win3D->grabImageGetNextFile();
237  if (m_win3D && (!grabFile.empty() || m_win3D->isCapturingImgs()))
238  {
239  int w, h;
240  dc.GetSize(&w, &h);
241 
242  // Save image directly from OpenGL - It could also use 4 channels and
243  // save with GL_BGRA_EXT
244  auto frame = CImage::Create(w, h, mrpt::img::CH_RGB);
246  glReadPixels(0, 0, w, h, GL_BGR_EXT, GL_UNSIGNED_BYTE, (*frame)(0, 0));
247  frame->flipVertical();
248 
249  if (!grabFile.empty())
250  {
251  frame->saveToFile(grabFile);
252  m_win3D->internal_emitGrabImageEvent(grabFile);
253  }
254 
255  if (m_win3D->isCapturingImgs())
256  {
257  {
258  std::lock_guard<std::mutex> lock(
259  m_win3D->m_last_captured_img_cs);
260  m_win3D->m_last_captured_img = frame;
261  frame.reset();
262  }
263  }
264  }
265 }
266 
267 #endif // Wx + OpenGL
268 
269 #if MRPT_HAS_WXWIDGETS
270 
271 BEGIN_EVENT_TABLE(C3DWindowDialog, wxFrame)
272 
273 END_EVENT_TABLE()
274 
275 const long C3DWindowDialog::ID_MENUITEM1 = wxNewId();
276 const long C3DWindowDialog::ID_MENUITEM2 = wxNewId();
277 
279  CDisplayWindow3D* win3D, WxSubsystem::CWXMainFrame* parent, wxWindowID id,
280  const std::string& caption, wxSize initialSize)
281  : m_win3D(win3D), m_mainFrame(parent)
282 {
283 #if MRPT_HAS_OPENGL_GLUT
284 
285  Create(
286  parent, id, caption.c_str(), wxDefaultPosition, initialSize,
287  wxDEFAULT_FRAME_STYLE, _T("id"));
288 
289  wxIcon FrameIcon;
290  FrameIcon.CopyFromBitmap(mrpt::gui::WxSubsystem::getMRPTDefaultIcon());
291  SetIcon(FrameIcon);
292 
293  // Create the wxCanvas object:
294  m_canvas = new CMyGLCanvas_DisplayWindow3D(
295  win3D, this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
296 
297  // Events:
298  this->Bind(wxEVT_CLOSE_WINDOW, &C3DWindowDialog::OnClose, this);
299  this->Bind(
300  wxEVT_COMMAND_MENU_SELECTED, &C3DWindowDialog::OnMenuClose, this,
301  ID_MENUITEM1);
302  this->Bind(
303  wxEVT_COMMAND_MENU_SELECTED, &C3DWindowDialog::OnMenuAbout, this,
304  ID_MENUITEM2);
305  this->Bind(wxEVT_CHAR, &C3DWindowDialog::OnChar, this);
306  this->Bind(wxEVT_SIZE, &C3DWindowDialog::OnResize, this);
307 
308  // Increment number of windows:
309  // int winCount =
311 // cout << "[C3DWindowDialog] Notifying new window: " << winCount << endl;
312 #else
313  THROW_EXCEPTION("MRPT was compiled without OpenGL support");
314 #endif
315  // this->Iconize(false);
316 }
317 
318 // Destructor
320 {
321  // cout << "[C3DWindowDialog::~C3DWindowDialog]" << endl;
322 }
323 
324 // OnClose event:
325 void C3DWindowDialog::OnClose(wxCloseEvent& event)
326 {
327  // Send the event:
328  bool allow_close = true;
329  try
330  {
331  mrptEventWindowClosed ev(m_win3D, true /* allow close */);
332  m_win3D->publishEvent(ev);
333  allow_close = ev.allow_close;
334  }
335  catch (...)
336  {
337  }
338  if (!allow_close) return; // Don't process this close event.
339 
340  // cout << "[C3DWindowDialog::OnClose]" << endl;
341  // Set the m_hwnd=nullptr in our parent object.
343 
344  // Decrement number of windows:
346 
347  // Signal we are destroyed:
348  m_win3D->m_windowDestroyed.set_value();
349 
350  event.Skip(); // keep processing by parent classes.
351 }
352 
353 // Menu: Close
354 void C3DWindowDialog::OnMenuClose(wxCommandEvent& event) { Close(); }
355 // Menu: About
356 void C3DWindowDialog::OnMenuAbout(wxCommandEvent& event)
357 {
358  ::wxMessageBox(
359  _("3D Scene viewer\n Class gui::CDisplayWindow3D\n MRPT C++ library"),
360  _("About..."));
361 }
362 
363 void C3DWindowDialog::OnChar(wxKeyEvent& ev)
364 {
365 #if MRPT_HAS_OPENGL_GLUT
366  CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(m_win3D, ev);
367 #endif
368 }
369 
370 void C3DWindowDialog::OnResize(wxSizeEvent& event)
371 {
372 #if MRPT_HAS_OPENGL_GLUT
373  // Send the event:
374  if (m_win3D)
375  {
376  try
377  {
379  m_win3D, event.GetSize().GetWidth(),
380  event.GetSize().GetHeight()));
381  }
382  catch (...)
383  {
384  }
385  }
386  event.Skip(); // so it's processed by the wx system!
387 #endif
388 }
389 
391 {
392 #if MRPT_HAS_OPENGL_GLUT
393  m_canvas->m_text_msgs.clearTextMessages();
394 #endif
395 }
396 
398  const double x_frac, const double y_frac, const std::string& text,
399  const mrpt::img::TColorf& color, const size_t unique_index,
400  const mrpt::opengl::TOpenGLFont font)
401 {
402 #if MRPT_HAS_OPENGL_GLUT
403  m_canvas->m_text_msgs.addTextMessage(
404  x_frac, y_frac, text, color, unique_index, font);
405 #endif
406 }
407 
409  const double x_frac, const double y_frac, const std::string& text,
410  const mrpt::img::TColorf& color, const std::string& font_name,
411  const double font_size, const mrpt::opengl::TOpenGLFontStyle font_style,
412  const size_t unique_index, const double font_spacing,
413  const double font_kerning, const bool has_shadow,
414  const mrpt::img::TColorf& shadow_color)
415 {
416 #if MRPT_HAS_OPENGL_GLUT
417  m_canvas->m_text_msgs.addTextMessage(
418  x_frac, y_frac, text, color, font_name, font_size, font_style,
419  unique_index, font_spacing, font_kerning, has_shadow, shadow_color);
420 #endif
421 }
422 
423 #endif // MRPT_HAS_WXWIDGETS
424 
425 /*---------------------------------------------------------------
426  Constructor
427  ---------------------------------------------------------------*/
429  const std::string& windowCaption, unsigned int initialWindowWidth,
430  unsigned int initialWindowHeight)
431  : CBaseGUIWindow(static_cast<void*>(this), 300, 399, windowCaption),
432  m_lastFullScreen(mrpt::system::now())
433 {
434  m_3Dscene = COpenGLScene::Create();
435  CBaseGUIWindow::createWxWindow(initialWindowWidth, initialWindowHeight);
436 }
437 
439  const std::string& windowCaption, unsigned int initialWindowWidth,
440  unsigned int initialWindowHeight)
441 {
442  return std::make_shared<CDisplayWindow3D>(
443  windowCaption, initialWindowWidth, initialWindowHeight);
444 }
445 /*---------------------------------------------------------------
446  Destructor
447  ---------------------------------------------------------------*/
449 {
450  // get lock so we make sure nobody else is touching the window right now.
451  m_csAccess3DScene.lock();
452  m_csAccess3DScene.unlock();
453 
455 }
456 
457 /*---------------------------------------------------------------
458  resize
459  ---------------------------------------------------------------*/
460 void CDisplayWindow3D::resize(unsigned int width, unsigned int height)
461 {
462 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
463  if (!isOpen())
464  {
465  cerr << "[CDisplayWindow3D::setPos] Window closed!: " << m_caption
466  << endl;
467  return;
468  }
469 
470  // Send a request to destroy this object:
471  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
472  REQ->source3D = this;
473  REQ->OPCODE = 303;
474  REQ->x = width;
475  REQ->y = height;
477 #else
480 #endif
481 }
482 
483 /*---------------------------------------------------------------
484  setPos
485  ---------------------------------------------------------------*/
487 {
488 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
489  if (!isOpen())
490  {
491  cerr << "[CDisplayWindow3D::setPos] Window closed!: " << m_caption
492  << endl;
493  return;
494  }
495 
496  // Send a request to destroy this object:
497  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
498  REQ->source3D = this;
499  REQ->OPCODE = 302;
500  REQ->x = x;
501  REQ->y = y;
503 #else
506 #endif
507 }
508 
509 /*---------------------------------------------------------------
510  setWindowTitle
511  ---------------------------------------------------------------*/
513 {
514 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
515  if (!isOpen())
516  {
517  cerr << "[CDisplayWindow3D::setWindowTitle] Window closed!: "
518  << m_caption << endl;
519  return;
520  }
521 
522  // Send a request to destroy this object:
523  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
524  REQ->source3D = this;
525  REQ->OPCODE = 304;
526  REQ->str = str;
528 #else
529  MRPT_UNUSED_PARAM(str);
530 #endif
531 }
532 
533 /*---------------------------------------------------------------
534  get3DSceneAndLock
535  ---------------------------------------------------------------*/
537 {
538  m_csAccess3DScene.lock();
539  return m_3Dscene;
540 }
541 
542 /*---------------------------------------------------------------
543  unlockAccess3DScene
544  ---------------------------------------------------------------*/
546 /*---------------------------------------------------------------
547  forceRepaint
548  ---------------------------------------------------------------*/
550 {
551 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
552  auto* win = (C3DWindowDialog*)m_hwnd.get();
553  if (win)
554  {
555  // win->Refresh(false); // Do not erase background
556  // We must do this from the wx thread!
557 
558  // Send refresh request:
559  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
560  REQ->source3D = this;
561  REQ->OPCODE = 350;
563  }
564 #endif
565 }
566 
567 /*---------------------------------------------------------------
568  setCameraElevationDeg
569  ---------------------------------------------------------------*/
571 {
572 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
573  auto* win = (C3DWindowDialog*)m_hwnd.get();
574  if (win) win->m_canvas->setElevationDegrees(deg);
575 #else
576  MRPT_UNUSED_PARAM(deg);
577 #endif
578 }
579 
581 {
582 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
583  auto* win = (C3DWindowDialog*)m_hwnd.get();
584  if (win) win->m_canvas->setUseCameraFromScene(useIt);
585 #else
586  MRPT_UNUSED_PARAM(useIt);
587 #endif
588 }
589 
590 /*---------------------------------------------------------------
591  setCameraAzimuthDeg
592  ---------------------------------------------------------------*/
594 {
595 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
596  auto* win = (C3DWindowDialog*)m_hwnd.get();
597  if (win) win->m_canvas->setAzimuthDegrees(deg);
598 #else
599  MRPT_UNUSED_PARAM(deg);
600 #endif
601 }
602 
603 /*---------------------------------------------------------------
604  setCameraPointingToPoint
605  ---------------------------------------------------------------*/
607 {
608 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
609  auto* win = (C3DWindowDialog*)m_hwnd.get();
610  if (win)
611  {
612  win->m_canvas->setCameraPointing(x, y, z);
613  }
614 #else
618 #endif
619 }
620 
621 /*---------------------------------------------------------------
622  setCameraZoom
623  ---------------------------------------------------------------*/
625 {
626 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
627  auto* win = (C3DWindowDialog*)m_hwnd.get();
628  if (win) win->m_canvas->setZoomDistance(zoom);
629 #else
630  MRPT_UNUSED_PARAM(zoom);
631 #endif
632 }
633 
634 /*---------------------------------------------------------------
635  setCameraProjective
636  ---------------------------------------------------------------*/
638 {
639 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
640  auto* win = (C3DWindowDialog*)m_hwnd.get();
641  if (win) win->m_canvas->setCameraProjective(isProjective);
642 #else
643  MRPT_UNUSED_PARAM(isProjective);
644 #endif
645 }
646 
647 void CDisplayWindow3D::setMinRange(double new_min)
648 {
649  if (m_3Dscene)
650  {
652  m_3Dscene->getViewport("main");
653  if (gl_view)
654  {
655  double m, M;
656  gl_view->getViewportClipDistances(m, M);
657  gl_view->setViewportClipDistances(new_min, M);
658  }
659  }
660 }
661 void CDisplayWindow3D::setMaxRange(double new_max)
662 {
663  if (m_3Dscene)
664  {
666  m_3Dscene->getViewport("main");
667  if (gl_view)
668  {
669  double m, M;
670  gl_view->getViewportClipDistances(m, M);
671  gl_view->setViewportClipDistances(m, new_max);
672  }
673  }
674 }
675 
677 {
678 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
679  auto* win = (C3DWindowDialog*)m_hwnd.get();
680  if (win) return win->m_canvas->cameraFOV();
681 #endif
682  return .0f;
683 }
684 
686 {
687 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
688  auto* win = (C3DWindowDialog*)m_hwnd.get();
689  if (win) win->m_canvas->setCameraFOV(v);
690 #endif
691 }
692 
693 /*---------------------------------------------------------------
694  getCameraElevationDeg
695  ---------------------------------------------------------------*/
697 {
698 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
699  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
700  return win ? win->m_canvas->getElevationDegrees() : 0;
701 #else
702  return 0;
703 #endif
704 }
705 
706 /*---------------------------------------------------------------
707  getCameraAzimuthDeg
708  ---------------------------------------------------------------*/
710 {
711 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
712  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
713  return win ? win->m_canvas->getAzimuthDegrees() : 0;
714 #else
715  return 0;
716 #endif
717 }
718 
719 /*---------------------------------------------------------------
720  getCameraPointingToPoint
721  ---------------------------------------------------------------*/
723  float& x, float& y, float& z) const
724 {
725 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
726  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
727  if (win)
728  {
729  x = win->m_canvas->getCameraPointingX();
730  y = win->m_canvas->getCameraPointingY();
731  z = win->m_canvas->getCameraPointingZ();
732  }
733  else
734  x = y = z = 0;
735 #else
739 #endif
740 }
741 
742 /*---------------------------------------------------------------
743  getCameraZoom
744  ---------------------------------------------------------------*/
746 {
747 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
748  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
749  return win ? win->m_canvas->getZoomDistance() : 0;
750 #else
751  return 0;
752 #endif
753 }
754 
755 /*---------------------------------------------------------------
756  isCameraProjective
757  ---------------------------------------------------------------*/
759 {
760 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
761  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
762  return win ? win->m_canvas->isCameraProjective() : true;
763 #else
764  return true;
765 #endif
766 }
767 
768 /*---------------------------------------------------------------
769  getLastMousePosition
770  ---------------------------------------------------------------*/
772 {
773 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
774  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
775  if (!win) return false;
776  win->m_canvas->getLastMousePosition(x, y);
777  return true;
778 #else
781  return false;
782 #endif
783 }
784 
785 /*---------------------------------------------------------------
786  getLastMousePositionRay
787  ---------------------------------------------------------------*/
789 {
790  int x, y;
791  if (getLastMousePosition(x, y))
792  {
793  m_csAccess3DScene.lock();
794  m_3Dscene->getViewport("main")->get3DRayForPixelCoord(x, y, ray);
795  m_csAccess3DScene.unlock();
796  return true;
797  }
798  else
799  return false;
800 }
801 
802 /*---------------------------------------------------------------
803  setCursorCross
804  ---------------------------------------------------------------*/
805 void CDisplayWindow3D::setCursorCross(bool cursorIsCross)
806 {
807 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
808  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
809  if (!win) return;
810  win->m_canvas->SetCursor(
811  *(cursorIsCross ? wxCROSS_CURSOR : wxSTANDARD_CURSOR));
812 #else
813  MRPT_UNUSED_PARAM(cursorIsCross);
814 #endif
815 }
816 
817 /*---------------------------------------------------------------
818  grabImagesStart
819  ---------------------------------------------------------------*/
820 void CDisplayWindow3D::grabImagesStart(const std::string& grab_imgs_prefix)
821 {
822  m_grab_imgs_prefix = grab_imgs_prefix;
823  m_grab_imgs_idx = 0;
824 }
825 
826 /*---------------------------------------------------------------
827  grabImagesStop
828  ---------------------------------------------------------------*/
830 /*---------------------------------------------------------------
831  grabImageGetNextFile
832  ---------------------------------------------------------------*/
834 {
835  if (m_grab_imgs_prefix.empty())
836  return string();
837  else
838  return format(
839  "%s%06u.png", m_grab_imgs_prefix.c_str(), m_grab_imgs_idx++);
840 }
841 
842 /*---------------------------------------------------------------
843  captureImagesStart
844  ---------------------------------------------------------------*/
846 /*---------------------------------------------------------------
847  captureImagesStop
848  ---------------------------------------------------------------*/
850 /*---------------------------------------------------------------
851  getLastWindowImage
852  ---------------------------------------------------------------*/
854 {
855  bool ret;
856 
857  {
858  std::lock_guard<std::mutex> lock(m_last_captured_img_cs);
860  {
861  out_img = *m_last_captured_img; // Copy the full image
862  ret = true;
863  }
864  else
865  ret = false;
866  }
867  return ret;
868 }
869 
870 /*---------------------------------------------------------------
871  getLastWindowImagePtr
872  ---------------------------------------------------------------*/
874 {
875  std::lock_guard<std::mutex> lock(m_last_captured_img_cs);
876  return m_last_captured_img;
877 }
878 
879 /*---------------------------------------------------------------
880  addTextMessage
881  ---------------------------------------------------------------*/
883  const double x_frac, const double y_frac, const std::string& text,
884  const mrpt::img::TColorf& color, const size_t unique_index,
885  const TOpenGLFont font)
886 {
887 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
888  auto* win = (C3DWindowDialog*)m_hwnd.get();
889  if (win)
890  {
891  // Send request:
892  // Add a 2D text message:
893  // vector_x: [0]:x, [1]:y, [2,3,4]:R G B, "x": enum of desired font.
894  // "y": unique index, "str": String.
895  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
896  REQ->source3D = this;
897  REQ->OPCODE = 360;
898  REQ->str = text;
899  REQ->vector_x.resize(5);
900  REQ->vector_x[0] = x_frac;
901  REQ->vector_x[1] = y_frac;
902  REQ->vector_x[2] = color.R;
903  REQ->vector_x[3] = color.G;
904  REQ->vector_x[4] = color.B;
905  REQ->x = int(font);
906  REQ->y = int(unique_index);
907 
909  }
910 #else
911  MRPT_UNUSED_PARAM(x_frac);
912  MRPT_UNUSED_PARAM(y_frac);
913  MRPT_UNUSED_PARAM(text);
915  MRPT_UNUSED_PARAM(unique_index);
916  MRPT_UNUSED_PARAM(font);
917 #endif
918 }
919 
920 /*---------------------------------------------------------------
921  addTextMessage
922  ---------------------------------------------------------------*/
924  const double x_frac, const double y_frac, const std::string& text,
925  const mrpt::img::TColorf& color, const std::string& font_name,
926  const double font_size, const mrpt::opengl::TOpenGLFontStyle font_style,
927  const size_t unique_index, const double font_spacing,
928  const double font_kerning, const bool draw_shadow,
929  const mrpt::img::TColorf& shadow_color)
930 {
931 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
932  auto* win = (C3DWindowDialog*)m_hwnd.get();
933  if (win)
934  {
935  // Send request:
936  // Add a 2D text message:
937  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
938  REQ->source3D = this;
939  REQ->OPCODE = 362;
940  REQ->str = text;
941  REQ->plotName = font_name;
942  REQ->vector_x.resize(12);
943  REQ->vector_x[0] = x_frac;
944  REQ->vector_x[1] = y_frac;
945  REQ->vector_x[2] = color.R;
946  REQ->vector_x[3] = color.G;
947  REQ->vector_x[4] = color.B;
948  REQ->vector_x[5] = font_size;
949  REQ->vector_x[6] = font_spacing;
950  REQ->vector_x[7] = font_kerning;
951  REQ->vector_x[8] = draw_shadow ? 1 : 0;
952  REQ->vector_x[9] = shadow_color.R;
953  REQ->vector_x[10] = shadow_color.G;
954  REQ->vector_x[11] = shadow_color.B;
955 
956  REQ->x = int(font_style);
957  REQ->y = int(unique_index);
958 
960  }
961 #else
962  MRPT_UNUSED_PARAM(x_frac);
963  MRPT_UNUSED_PARAM(y_frac);
964  MRPT_UNUSED_PARAM(text);
966  MRPT_UNUSED_PARAM(font_name);
967  MRPT_UNUSED_PARAM(font_size);
968  MRPT_UNUSED_PARAM(font_style);
969  MRPT_UNUSED_PARAM(unique_index);
970  MRPT_UNUSED_PARAM(font_spacing);
971  MRPT_UNUSED_PARAM(font_kerning);
972  MRPT_UNUSED_PARAM(draw_shadow);
973  MRPT_UNUSED_PARAM(shadow_color);
974 #endif
975 }
976 
977 /*---------------------------------------------------------------
978  clearTextMessages
979  ---------------------------------------------------------------*/
981 {
982 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
983  auto* win = (C3DWindowDialog*)m_hwnd.get();
984  if (win)
985  {
986  // Send request:
987  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
988  REQ->source3D = this;
989  REQ->OPCODE = 361;
991  }
992 #endif
993 }
994 
996 {
997  const double ALPHA = 0.99;
998  m_last_FPS = ALPHA * m_last_FPS + (1 - ALPHA) * FPS;
999 }
1000 
1001 // Called by CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers
1003 {
1004  const mrptEvent3DWindowGrabImageFile ev(this, fil);
1005  publishEvent(ev);
1006 }
1007 
1008 // Returns the "main" viewport of the scene.
1010 {
1011  m_csAccess3DScene.lock();
1012  mrpt::opengl::COpenGLViewport::Ptr view = m_3Dscene->getViewport("main");
1013  m_csAccess3DScene.unlock();
1014  return view;
1015 }
1016 
1018 {
1019  m_csAccess3DScene.lock();
1020  mrpt::opengl::COpenGLViewport::Ptr view = m_3Dscene->getViewport("main");
1021  view->setImageView(img);
1022  m_csAccess3DScene.unlock();
1023 }
1024 
1026 {
1027  m_csAccess3DScene.lock();
1028  mrpt::opengl::COpenGLViewport::Ptr view = m_3Dscene->getViewport("main");
1029  view->setImageView(std::move(img));
1030  m_csAccess3DScene.unlock();
1031 }
1032 
1035  : m_win(win)
1036 {
1037  out_scene_ptr = m_win.get3DSceneAndLock();
1038 }
1040  : m_win(win)
1041 {
1043 }
1045 {
1047 }
An event sent by a window upon resize.
bool getLastMousePosition(int &x, int &y) const override
Gets the last x,y pixel coordinates of the mouse.
float getCameraAzimuthDeg() const
Get camera parameters programmatically.
bool getLastMousePositionRay(mrpt::math::TLine3D &ray) const
Gets the 3D ray for the direction line of the pixel where the mouse cursor is at. ...
static void pushPendingWxRequest(TRequestToWxMainThread *data)
Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "ne...
An event sent by a CDisplayWindow3D window when an image is saved after enabling this feature with CD...
void OnMenuAbout(wxCommandEvent &event)
void unlockAccess3DScene()
Unlocks the access to the internal 3D scene.
GLAPI void GLAPIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
An event sent by a window upon a mouse click, giving the (x,y) pixel coordinates. ...
std::recursive_mutex m_csAccess3DScene
Critical section for accesing m_3Dscene.
void OnClose(wxCloseEvent &event)
GLdouble GLdouble z
Definition: glext.h:3879
mrpt::gui::CDisplayWindow3D * source3D
Only one of source* can be non-nullptr, indicating the class that generated the request.
Definition: WxSubsystem.h:199
mrpt::img::CImage::Ptr getLastWindowImagePtr() const
Retrieve the last captured image from the window, as a smart pointer.
The data structure for each inter-thread request:
Definition: WxSubsystem.h:189
CDisplayWindow3DLocker(CDisplayWindow3D &win, mrpt::opengl::COpenGLScene::Ptr &out_scene_ptr)
Acquires the lock of the 3D scene of the referenced window, and returns a copy of the smart pointer t...
void setWindowTitle(const std::string &str) override
Changes the window title.
void addTextMessage(const double x_frac, const double y_frac, const std::string &text, const mrpt::img::TColorf &color, const size_t unique_index, const mrpt::opengl::TOpenGLFont font)
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:108
mrpt::void_ptr_noncopy m_hwnd
The window handle.
std::string m_caption
The caption of the window.
mrpt::opengl::COpenGLScene::Ptr & get3DSceneAndLock()
Gets a reference to the smart shared pointer that holds the internal scene (carefuly read introductio...
void grabImagesStart(const std::string &grab_imgs_prefix=std::string("video_"))
Start to save rendered images to disk.
static int notifyWindowCreation()
Atomically increments the number of windows created with the main frame as parent.
void resize(unsigned int width, unsigned int height) override
Resizes the window, stretching the image to fit into the display area.
Keeps a list of text messages which can be rendered to OpenGL contexts by graphic classes...
void setCameraPointingToPoint(float x, float y, float z)
Changes the camera parameters programmatically.
mrptKeyModifier
Definition: keycodes.h:156
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
Definition: datetime.h:86
void OnMenuClose(wxCommandEvent &event)
static wxBitmap getMRPTDefaultIcon()
GLAPI void GLAPIENTRY glReadBuffer(GLenum mode)
STL namespace.
CDisplayWindow3D * m_win3D
Definition: WxSubsystem.h:395
static CDisplayWindow3D::Ptr Create(const std::string &windowCaption, unsigned int initialWindowWidth=400, unsigned int initialWindowHeight=300)
Class factory returning a smart pointer.
#define GL_UNSIGNED_BYTE
Definition: glew.h:303
void internal_emitGrabImageEvent(const std::string &fil)
called by CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers
void setCameraProjective(bool isProjective)
Sets the camera as projective, or orthogonal.
float getCameraZoom() const
Get camera parameters programmatically.
void OnResize(wxSizeEvent &event)
An event sent by a window upon when it&#39;s about to be closed, either manually by the user or programma...
An event sent by a window when the mouse is moved over it.
GLenum GLsizei width
Definition: glext.h:3535
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4199
void OnChar(wxKeyEvent &event)
void notifyChildWindowDestruction()
Called by wx main thread to set m_hwnd to NULL.
mrpt::opengl::COpenGLViewport::Ptr getDefaultViewport()
A short cut for getting the "main" viewport of the scene object, it is equivalent to: ...
GLuint color
Definition: glext.h:8459
const long ID_MENUITEM1
This base provides a set of functions for maths stuff.
#define GL_BGR_EXT
Definition: glew.h:5555
void getCameraPointingToPoint(float &x, float &y, float &z) const
Get camera parameters programmatically.
TOpenGLFont
Existing fonts for 2D texts in mrpt::opengl methods.
Definition: opengl_fonts.h:22
void setMaxRange(double new_max)
Changes the camera max clip range (z) (used for gluPerspective.
void setPos(int x, int y) override
Changes the position of the window on the screen.
~CDisplayWindow3D() override
Destructor.
std::string grabImageGetNextFile()
Increments by one the image counter and return the next image file name (Users normally don&#39;t want to...
GLint GLvoid * img
Definition: glext.h:3769
TOpenGLFontStyle
Different style for vectorized font rendering.
Definition: opengl_fonts.h:33
bool isOpen()
Returns false if the user has already closed the window.
A pair (x,y) of pixel coordinates (integer resolution).
Definition: TPixelCoord.h:39
An event sent by a window upon a char pressed by the user.
const long ID_MENUITEM2
mrpt::gui::CDisplayWindow3D::Ptr win
GLsizei const GLchar ** string
Definition: glext.h:4116
mrptKeyModifier keyEventToMrptKeyModifier(const wxKeyEvent &ev)
Extracts the key modifiers from a wxKeyEvent.
Definition: WxUtils.cpp:942
volatile mrptKeyModifier m_keyPushedModifier
void forceRepaint()
Repaints the window.
void setImageView(const mrpt::img::CImage &img)
Set the "main" viewport into "image view"-mode, where an image is efficiently drawn (fitting the view...
float getFOV() const
Return the camera field of view (in degrees) (used for gluPerspective)
const GLdouble * v
Definition: glext.h:3684
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::system::TTimeStamp m_lastFullScreen
This class implements the GUI thread required for the wxWidgets-based GUI.
Definition: WxSubsystem.h:96
Definition: inftrees.h:28
void grabImagesStop()
Stops image grabbing started by grabImagesStart.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:16
GLuint id
Definition: glext.h:3920
A RGB color - floats in the range [0,1].
Definition: TColor.h:77
bool isCameraProjective() const
Sets the camera as projective, or orthogonal.
bool hasSubscribers() const
Can be called by a derived class before preparing an event for publishing with publishEvent to determ...
Definition: CObservable.h:53
void publishEvent(const mrptEvent &e) const
Called when you want this object to emit an event to all the observers currently subscribed to this o...
Definition: CObservable.cpp:48
void setCameraZoom(float zoom)
Changes the camera parameters programmatically.
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
GLuint const GLchar * name
Definition: glext.h:4068
void setCursorCross(bool cursorIsCross) override
Set cursor style to default (cursorIsCross=false) or to a cross (cursorIsCross=true) ...
void destroyWxWindow()
Must be called by child classes in their destructors.
GLenum GLint GLint y
Definition: glext.h:3542
void setMinRange(double new_min)
Changes the camera min clip range (z) (used for gluPerspective).
bool getLastWindowImage(mrpt::img::CImage &out_img) const
Retrieve the last captured image from the window.
void addTextMessage(const double x, const double y, const std::string &text, const mrpt::img::TColorf &color=mrpt::img::TColorf(1.0, 1.0, 1.0), const size_t unique_index=0, const mrpt::opengl::TOpenGLFont font=mrpt::opengl::MRPT_GLUT_BITMAP_TIMES_ROMAN_24)
Add 2D text messages overlapped to the 3D rendered scene.
mrpt::img::CImage::Ptr m_last_captured_img
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:14
void createWxWindow(unsigned int initialWidth, unsigned int initialHeight)
Must be called by child classes just within the constructor.
void captureImagesStop()
Stop image grabbing.
GLsizeiptr size
Definition: glext.h:3934
CDisplayWindow3D(const std::string &windowCaption=std::string(), unsigned int initialWindowWidth=400, unsigned int initialWindowHeight=300)
Constructor.
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
Definition: datetime.h:123
GLenum GLint x
Definition: glext.h:3542
GLenum GLsizei GLsizei height
Definition: glext.h:3558
#define GL_FRONT
Definition: glew.h:318
void internal_setRenderingFPS(double FPS)
Set the rendering FPS (users don&#39;t call this, the method is for internal MRPT objects only) ...
std::promise< void > m_windowDestroyed
This semaphore will be signaled when the wx window is destroyed.
void clearTextMessages()
Clear all text messages created with addTextMessage().
mrpt::opengl::COpenGLScene::Ptr m_3Dscene
Internal OpenGL object (see general discussion in about usage of this object)
The base class for GUI window classes.
void setFOV(float v)
Changes the camera field of view (in degrees) (used for gluPerspective).
static int notifyWindowDestruction()
Atomically decrements the number of windows created with the main frame as parent.
void setCameraAzimuthDeg(float deg)
Changes the camera parameters programmatically.
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:147
void setCameraElevationDeg(float deg)
Changes the camera parameters programmatically.
CMyGLCanvas_DisplayWindow3D * m_canvas
Definition: WxSubsystem.h:398
void useCameraFromScene(bool useIt=true)
If set to true (default = false), the mouse-based scene navigation will be disabled and the camera po...
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.
void captureImagesStart()
Enables the grabbing of CImage objects from screenshots of the window.
3D line, represented by a base point and a director vector.
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
float getCameraElevationDeg() const
Get camera parameters programmatically.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 5887d2b31 Wed Apr 24 13:03:27 2019 +0200 at miƩ abr 24 13:10:13 CEST 2019