MRPT  2.0.2
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-2020, 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 
55 
56 namespace mrpt::gui
57 {
58 class CMyGLCanvas_DisplayWindow3D : public mrpt::gui::CWxGLCanvasBase
59 {
60  public:
61  CMyGLCanvas_DisplayWindow3D(
62  CDisplayWindow3D* win3D, wxWindow* parent, wxWindowID id = wxID_ANY,
63  const wxPoint& pos = wxDefaultPosition,
64  const wxSize& size = wxDefaultSize, long style = 0,
65  const wxString& name = _T("CMyGLCanvas_DisplayWindow3D"));
66 
67  ~CMyGLCanvas_DisplayWindow3D() override;
68 
69  CDisplayWindow3D* m_win3D = nullptr;
70 
71  void OnCharCustom(wxKeyEvent& event) override;
72  void OnMouseDown(wxMouseEvent& event);
73  void OnMouseMove(wxMouseEvent& event);
74 
75  void OnPreRender() override;
76  void OnPostRender() override;
77  void OnPostRenderSwapBuffers(double At, wxPaintDC& dc) override;
78 
79  static void display3D_processKeyEvent(
80  CDisplayWindow3D* m_win3D, wxKeyEvent& ev);
81 };
82 } // namespace mrpt::gui
83 
84 CMyGLCanvas_DisplayWindow3D::CMyGLCanvas_DisplayWindow3D(
85  CDisplayWindow3D* win3D, wxWindow* parent, wxWindowID id,
86  const wxPoint& pos, const wxSize& size, long style, const wxString& name)
87  : CWxGLCanvasBase(parent, id, pos, size, style, name), m_win3D(win3D)
88 {
89  this->Bind(wxEVT_CHAR, &CMyGLCanvas_DisplayWindow3D::OnCharCustom, this);
90  this->Bind(
91  wxEVT_CHAR_HOOK, &CMyGLCanvas_DisplayWindow3D::OnCharCustom, this);
92  this->Bind(
93  wxEVT_LEFT_DOWN, &CMyGLCanvas_DisplayWindow3D::OnMouseDown, this);
94  this->Bind(
95  wxEVT_RIGHT_DOWN, &CMyGLCanvas_DisplayWindow3D::OnMouseDown, this);
96  this->Bind(wxEVT_MOTION, &CMyGLCanvas_DisplayWindow3D::OnMouseMove, this);
97 }
98 
99 void CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(
100  CDisplayWindow3D* m_win3D, wxKeyEvent& ev)
101 {
102  if (m_win3D)
103  {
104  if (ev.AltDown() && ev.GetKeyCode() == MRPTK_RETURN)
105  {
107  m_win3D->m_lastFullScreen, mrpt::system::now()) > 0.2)
108  {
109  m_win3D->m_lastFullScreen = mrpt::system::now();
110  cout << "[CDisplayWindow3D] Switching fullscreen...\n";
111  auto* win = (C3DWindowDialog*)m_win3D->m_hwnd.get();
112  if (win)
113  {
114  win->ShowFullScreen(!win->IsFullScreen());
115  }
116  }
117  // Alt+Enter: Don't notify on this key stroke, since if we're
118  // switching to fullscreen
119  // and the user is waiting for a key to close the window, a runtime
120  // crash will occur,
121  // so return now:
122  return;
123  }
124 
125  const int code = ev.GetKeyCode();
127 
128  m_win3D->m_keyPushedCode = code;
129  m_win3D->m_keyPushedModifier = mod;
130  m_win3D->m_keyPushed = true;
131 
132  // Send the event:
133  try
134  {
135  m_win3D->publishEvent(mrptEventWindowChar(m_win3D, code, mod));
136  }
137  catch (...)
138  {
139  }
140  }
141  // ev.Skip(); // Pass the event to whoever else.
142 }
143 
144 void CMyGLCanvas_DisplayWindow3D::OnCharCustom(wxKeyEvent& ev)
145 {
146  CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(m_win3D, ev);
147 }
148 
149 void CMyGLCanvas_DisplayWindow3D::OnMouseDown(wxMouseEvent& event)
150 {
151  // Send the event:
152  if (m_win3D && m_win3D->hasSubscribers())
153  {
154  try
155  {
157  m_win3D, TPixelCoord(event.GetX(), event.GetY()),
158  event.LeftDown(), event.RightDown()));
159  }
160  catch (...)
161  {
162  }
163  }
164 
165  event.Skip(); // so it's processed by the wx system!
166 }
167 
168 void CMyGLCanvas_DisplayWindow3D::OnMouseMove(wxMouseEvent& event)
169 {
170  // Send the event:
171  if (m_win3D && m_win3D->hasSubscribers())
172  {
173  try
174  {
176  m_win3D, TPixelCoord(event.GetX(), event.GetY()),
177  event.LeftDown(), event.RightDown()));
178  }
179  catch (...)
180  {
181  }
182  }
183 
184  event.Skip(); // so it's processed by the wx system!
185 }
186 
187 CMyGLCanvas_DisplayWindow3D::~CMyGLCanvas_DisplayWindow3D()
188 {
189  // Ensure all OpenGL resources are freed before the opengl context is gone:
190  if (getOpenGLSceneRef()) getOpenGLSceneRef()->unloadShaders();
191 
192  // Unbind all objects, free all buffers:
193  auto& scene = getOpenGLSceneRef();
194  if (scene) scene->freeOpenGLResources();
195 }
196 
197 void CMyGLCanvas_DisplayWindow3D::OnPreRender()
198 {
199  auto& openGLSceneRef = getOpenGLSceneRef();
200  if (openGLSceneRef) openGLSceneRef.reset();
201 
202  COpenGLScene::Ptr& ptrScene = m_win3D->get3DSceneAndLock();
203  if (ptrScene) openGLSceneRef = ptrScene;
204 }
205 
206 void CMyGLCanvas_DisplayWindow3D::OnPostRender()
207 {
208  m_win3D->unlockAccess3DScene();
209 }
210 
211 void CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers(
212  double At, wxPaintDC& dc)
213 {
214  if (m_win3D) m_win3D->internal_setRenderingFPS(At > 0 ? 1.0 / At : 1e9);
215 
216  // If we are requested to do so, grab images to disk as they are rendered:
217  string grabFile;
218  if (m_win3D) grabFile = m_win3D->grabImageGetNextFile();
219  if (m_win3D && (!grabFile.empty() || m_win3D->isCapturingImgs()))
220  {
221  int w, h;
222  dc.GetSize(&w, &h);
223 
224  // Save image directly from OpenGL - It could also use 4 channels and
225  // save with GL_BGRA_EXT
226  auto frame = CImage::Create(w, h, mrpt::img::CH_RGB);
227 
228  glPixelStorei(GL_PACK_ALIGNMENT, 1);
229  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
230 
231  glReadBuffer(GL_FRONT);
232  glReadPixels(0, 0, w, h, GL_BGR_EXT, GL_UNSIGNED_BYTE, (*frame)(0, 0));
233  frame->flipVertical();
234 
235  if (!grabFile.empty())
236  {
237  frame->saveToFile(grabFile);
238  m_win3D->internal_emitGrabImageEvent(grabFile);
239  }
240 
241  if (m_win3D->isCapturingImgs())
242  {
243  {
244  std::lock_guard<std::mutex> lock(
245  m_win3D->m_last_captured_img_cs);
246  m_win3D->m_last_captured_img = frame;
247  frame.reset();
248  }
249  }
250  }
251 }
252 
253 #endif // Wx + OpenGL
254 
255 #if MRPT_HAS_WXWIDGETS
256 
257 BEGIN_EVENT_TABLE(C3DWindowDialog, wxFrame)
258 
259 END_EVENT_TABLE()
260 
261 const long C3DWindowDialog::ID_MENUITEM1 = wxNewId();
262 const long C3DWindowDialog::ID_MENUITEM2 = wxNewId();
263 
265  CDisplayWindow3D* win3D, WxSubsystem::CWXMainFrame* parent, wxWindowID id,
266  const std::string& caption, wxSize initialSize)
267  : m_win3D(win3D), m_mainFrame(parent)
268 {
269 #if MRPT_HAS_OPENGL_GLUT
270 
271  Create(
272  parent, id, caption.c_str(), wxDefaultPosition, initialSize,
273  wxDEFAULT_FRAME_STYLE, _T("id"));
274 
275  wxIcon FrameIcon;
276  FrameIcon.CopyFromBitmap(mrpt::gui::WxSubsystem::getMRPTDefaultIcon());
277  SetIcon(FrameIcon);
278 
279  // Create the wxCanvas object:
280  m_canvas = new CMyGLCanvas_DisplayWindow3D(
281  win3D, this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
282 
283  // Events:
284  this->Bind(wxEVT_CLOSE_WINDOW, &C3DWindowDialog::OnClose, this);
285  this->Bind(wxEVT_MENU, &C3DWindowDialog::OnMenuClose, this, ID_MENUITEM1);
286  this->Bind(wxEVT_MENU, &C3DWindowDialog::OnMenuAbout, this, ID_MENUITEM2);
287  this->Bind(wxEVT_CHAR, &C3DWindowDialog::OnChar, this);
288  this->Bind(wxEVT_SIZE, &C3DWindowDialog::OnResize, this);
289 
290  // Increment number of windows:
291  // int winCount =
293 // cout << "[C3DWindowDialog] Notifying new window: " << winCount << endl;
294 #else
295  THROW_EXCEPTION("MRPT was compiled without OpenGL support");
296 #endif
297  // this->Iconize(false);
298 }
299 
300 // Destructor
302 {
303  // cout << "[C3DWindowDialog::~C3DWindowDialog]" << endl;
304 }
305 
306 // OnClose event:
307 void C3DWindowDialog::OnClose(wxCloseEvent& event)
308 {
309  // Send the event:
310  bool allow_close = true;
311  try
312  {
313  mrptEventWindowClosed ev(m_win3D, true /* allow close */);
314  m_win3D->publishEvent(ev);
315  allow_close = ev.allow_close;
316  }
317  catch (...)
318  {
319  }
320  if (!allow_close) return; // Don't process this close event.
321 
322  // cout << "[C3DWindowDialog::OnClose]" << endl;
323  // Set the m_hwnd=nullptr in our parent object.
325 
326  // Decrement number of windows:
328 
329  // Signal we are destroyed:
330  m_win3D->m_windowDestroyed.set_value();
331 
332  event.Skip(); // keep processing by parent classes.
333 }
334 
335 // Menu: Close
336 void C3DWindowDialog::OnMenuClose(wxCommandEvent& event) { Close(); }
337 // Menu: About
338 void C3DWindowDialog::OnMenuAbout(wxCommandEvent& event)
339 {
340  ::wxMessageBox(
341  _("3D Scene viewer\n Class gui::CDisplayWindow3D\n MRPT C++ library"),
342  _("About..."));
343 }
344 
345 void C3DWindowDialog::OnChar(wxKeyEvent& ev)
346 {
347 #if MRPT_HAS_OPENGL_GLUT
348  CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(m_win3D, ev);
349 #endif
350 }
351 
352 void C3DWindowDialog::OnResize(wxSizeEvent& event)
353 {
354 #if MRPT_HAS_OPENGL_GLUT
355  // Send the event:
356  if (m_win3D)
357  {
358  try
359  {
361  m_win3D, event.GetSize().GetWidth(),
362  event.GetSize().GetHeight()));
363  }
364  catch (...)
365  {
366  }
367  }
368  event.Skip(); // so it's processed by the wx system!
369 #endif
370 }
371 
372 #endif // MRPT_HAS_WXWIDGETS
373 
374 /*---------------------------------------------------------------
375  Constructor
376  ---------------------------------------------------------------*/
378  const std::string& windowCaption, unsigned int initialWindowWidth,
379  unsigned int initialWindowHeight)
380  : CBaseGUIWindow(static_cast<void*>(this), 300, 399, windowCaption),
381  m_lastFullScreen(mrpt::system::now())
382 {
383  m_3Dscene = COpenGLScene::Create();
384  CBaseGUIWindow::createWxWindow(initialWindowWidth, initialWindowHeight);
385 }
386 
388  const std::string& windowCaption, unsigned int initialWindowWidth,
389  unsigned int initialWindowHeight)
390 {
391  return std::make_shared<CDisplayWindow3D>(
392  windowCaption, initialWindowWidth, initialWindowHeight);
393 }
394 /*---------------------------------------------------------------
395  Destructor
396  ---------------------------------------------------------------*/
398 {
399  // get lock so we make sure nobody else is touching the window right now.
400  bool lock_ok = m_csAccess3DScene.try_lock_for(std::chrono::seconds(2));
401  m_csAccess3DScene.unlock();
402 
404 
405  if (!lock_ok)
406  std::cerr
407  << "[~CDisplayWindow3D] Warning: Timeout acquiring mutex lock.\n";
408 }
409 
410 /*---------------------------------------------------------------
411  resize
412  ---------------------------------------------------------------*/
414  [[maybe_unused]] unsigned int width, [[maybe_unused]] unsigned int height)
415 {
416 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
417  if (!isOpen())
418  {
419  cerr << "[CDisplayWindow3D::setPos] Window closed!: " << m_caption
420  << endl;
421  return;
422  }
423 
424  // Send a request to destroy this object:
425  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
426  REQ->source3D = this;
427  REQ->OPCODE = 303;
428  REQ->x = width;
429  REQ->y = height;
431 #endif
432 }
433 
434 /*---------------------------------------------------------------
435  setPos
436  ---------------------------------------------------------------*/
437 void CDisplayWindow3D::setPos([[maybe_unused]] int x, [[maybe_unused]] int y)
438 {
439 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
440  if (!isOpen())
441  {
442  cerr << "[CDisplayWindow3D::setPos] Window closed!: " << m_caption
443  << endl;
444  return;
445  }
446 
447  // Send a request to destroy this object:
448  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
449  REQ->source3D = this;
450  REQ->OPCODE = 302;
451  REQ->x = x;
452  REQ->y = y;
454 #endif
455 }
456 
457 /*---------------------------------------------------------------
458  setWindowTitle
459  ---------------------------------------------------------------*/
460 void CDisplayWindow3D::setWindowTitle([[maybe_unused]] const std::string& str)
461 {
462 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
463  if (!isOpen())
464  {
465  cerr << "[CDisplayWindow3D::setWindowTitle] Window closed!: "
466  << m_caption << 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 = 304;
474  REQ->str = str;
476 #endif
477 }
478 
480 {
481  m_csAccess3DScene.lock();
482  return m_3Dscene;
483 }
484 
486 
488 {
489 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
490  auto* win = (C3DWindowDialog*)m_hwnd.get();
491  if (win)
492  {
493  // win->Refresh(false); // Do not erase background
494  // We must do this from the wx thread!
495 
496  // Send refresh request:
497  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
498  REQ->source3D = this;
499  REQ->OPCODE = 350;
501  }
502 #endif
503 }
504 
505 /*---------------------------------------------------------------
506  setCameraElevationDeg
507  ---------------------------------------------------------------*/
508 void CDisplayWindow3D::setCameraElevationDeg([[maybe_unused]] float deg)
509 {
510 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
511  auto* win = (C3DWindowDialog*)m_hwnd.get();
512  if (win) win->m_canvas->setElevationDegrees(deg);
513 #endif
514 }
515 
516 void CDisplayWindow3D::useCameraFromScene([[maybe_unused]] bool useIt)
517 {
518 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
519  auto* win = (C3DWindowDialog*)m_hwnd.get();
520  if (win) win->m_canvas->setUseCameraFromScene(useIt);
521 #endif
522 }
523 
524 /*---------------------------------------------------------------
525  setCameraAzimuthDeg
526  ---------------------------------------------------------------*/
527 void CDisplayWindow3D::setCameraAzimuthDeg([[maybe_unused]] float deg)
528 {
529 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
530  auto* win = (C3DWindowDialog*)m_hwnd.get();
531  if (win) win->m_canvas->setAzimuthDegrees(deg);
532 #endif
533 }
534 
535 /*---------------------------------------------------------------
536  setCameraPointingToPoint
537  ---------------------------------------------------------------*/
539  [[maybe_unused]] float x, [[maybe_unused]] float y,
540  [[maybe_unused]] float z)
541 {
542 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
543  auto* win = (C3DWindowDialog*)m_hwnd.get();
544  if (win)
545  {
546  win->m_canvas->setCameraPointing(x, y, z);
547  }
548 #endif
549 }
550 
551 /*---------------------------------------------------------------
552  setCameraZoom
553  ---------------------------------------------------------------*/
554 void CDisplayWindow3D::setCameraZoom([[maybe_unused]] float zoom)
555 {
556 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
557  auto* win = (C3DWindowDialog*)m_hwnd.get();
558  if (win) win->m_canvas->setZoomDistance(zoom);
559 #endif
560 }
561 
562 /*---------------------------------------------------------------
563  setCameraProjective
564  ---------------------------------------------------------------*/
565 void CDisplayWindow3D::setCameraProjective([[maybe_unused]] bool isProjective)
566 {
567 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
568  auto* win = (C3DWindowDialog*)m_hwnd.get();
569  if (win) win->m_canvas->setCameraProjective(isProjective);
570 #endif
571 }
572 
573 void CDisplayWindow3D::setMinRange(float new_min)
574 {
575  if (m_3Dscene)
576  {
578  m_3Dscene->getViewport("main");
579  if (gl_view)
580  {
581  float m, M;
582  gl_view->getViewportClipDistances(m, M);
583  gl_view->setViewportClipDistances(new_min, M);
584  }
585  }
586 }
587 void CDisplayWindow3D::setMaxRange(float new_max)
588 {
589  if (m_3Dscene)
590  {
592  m_3Dscene->getViewport("main");
593  if (gl_view)
594  {
595  float m, M;
596  gl_view->getViewportClipDistances(m, M);
597  gl_view->setViewportClipDistances(m, new_max);
598  }
599  }
600 }
601 
603 {
604 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
605  auto* win = (C3DWindowDialog*)m_hwnd.get();
606  if (win) return win->m_canvas->cameraFOV();
607 #endif
608  return .0f;
609 }
610 
612 {
613 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
614  auto* win = (C3DWindowDialog*)m_hwnd.get();
615  if (win) win->m_canvas->setCameraFOV(v);
616 #endif
617 }
618 
619 /*---------------------------------------------------------------
620  getCameraElevationDeg
621  ---------------------------------------------------------------*/
623 {
624 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
625  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
626  return win ? win->m_canvas->getElevationDegrees() : 0;
627 #else
628  return 0;
629 #endif
630 }
631 
632 /*---------------------------------------------------------------
633  getCameraAzimuthDeg
634  ---------------------------------------------------------------*/
636 {
637 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
638  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
639  return win ? win->m_canvas->getAzimuthDegrees() : 0;
640 #else
641  return 0;
642 #endif
643 }
644 
645 /*---------------------------------------------------------------
646  getCameraPointingToPoint
647  ---------------------------------------------------------------*/
649  [[maybe_unused]] float& x, [[maybe_unused]] float& y,
650  [[maybe_unused]] float& z) const
651 {
652 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
653  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
654  if (win)
655  {
656  x = win->m_canvas->getCameraPointingX();
657  y = win->m_canvas->getCameraPointingY();
658  z = win->m_canvas->getCameraPointingZ();
659  }
660  else
661  x = y = z = 0;
662 #endif
663 }
664 
665 /*---------------------------------------------------------------
666  getCameraZoom
667  ---------------------------------------------------------------*/
669 {
670 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
671  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
672  return win ? win->m_canvas->getZoomDistance() : 0;
673 #else
674  return 0;
675 #endif
676 }
677 
678 /*---------------------------------------------------------------
679  isCameraProjective
680  ---------------------------------------------------------------*/
682 {
683 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
684  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
685  return win ? win->m_canvas->isCameraProjective() : true;
686 #else
687  return true;
688 #endif
689 }
690 
691 /*---------------------------------------------------------------
692  getLastMousePosition
693  ---------------------------------------------------------------*/
695  [[maybe_unused]] int& x, [[maybe_unused]] int& y) const
696 {
697 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
698  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
699  if (!win) return false;
700  win->m_canvas->getLastMousePosition(x, y);
701  return true;
702 #else
703  return false;
704 #endif
705 }
706 
707 /*---------------------------------------------------------------
708  getLastMousePositionRay
709  ---------------------------------------------------------------*/
711 {
712  int x, y;
713  if (getLastMousePosition(x, y))
714  {
715  std::lock_guard<std::recursive_timed_mutex> lck(m_csAccess3DScene);
716  m_3Dscene->getViewport("main")->get3DRayForPixelCoord(x, y, ray);
717  return true;
718  }
719  else
720  return false;
721 }
722 
723 /*---------------------------------------------------------------
724  setCursorCross
725  ---------------------------------------------------------------*/
726 void CDisplayWindow3D::setCursorCross([[maybe_unused]] bool cursorIsCross)
727 {
728 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
729  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
730  if (!win) return;
731  win->m_canvas->SetCursor(
732  *(cursorIsCross ? wxCROSS_CURSOR : wxSTANDARD_CURSOR));
733 #endif
734 }
735 
736 /*---------------------------------------------------------------
737  grabImagesStart
738  ---------------------------------------------------------------*/
739 void CDisplayWindow3D::grabImagesStart(const std::string& grab_imgs_prefix)
740 {
741  m_grab_imgs_prefix = grab_imgs_prefix;
742  m_grab_imgs_idx = 0;
743 }
744 
745 /*---------------------------------------------------------------
746  grabImagesStop
747  ---------------------------------------------------------------*/
749 /*---------------------------------------------------------------
750  grabImageGetNextFile
751  ---------------------------------------------------------------*/
753 {
754  if (m_grab_imgs_prefix.empty())
755  return string();
756  else
757  return format(
758  "%s%06u.png", m_grab_imgs_prefix.c_str(), m_grab_imgs_idx++);
759 }
760 
761 /*---------------------------------------------------------------
762  captureImagesStart
763  ---------------------------------------------------------------*/
765 /*---------------------------------------------------------------
766  captureImagesStop
767  ---------------------------------------------------------------*/
769 /*---------------------------------------------------------------
770  getLastWindowImage
771  ---------------------------------------------------------------*/
773 {
774  bool ret;
775 
776  {
777  std::lock_guard<std::mutex> lock(m_last_captured_img_cs);
779  {
780  out_img = *m_last_captured_img; // Copy the full image
781  ret = true;
782  }
783  else
784  ret = false;
785  }
786  return ret;
787 }
788 
789 /*---------------------------------------------------------------
790  getLastWindowImagePtr
791  ---------------------------------------------------------------*/
793 {
794  std::lock_guard<std::mutex> lock(m_last_captured_img_cs);
795  return m_last_captured_img;
796 }
797 
799 {
800  const double ALPHA = 0.99;
801  m_last_FPS = ALPHA * m_last_FPS + (1 - ALPHA) * FPS;
802 }
803 
804 // Called by CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers
806 {
807  const mrptEvent3DWindowGrabImageFile ev(this, fil);
808  publishEvent(ev);
809 }
810 
811 // Returns the "main" viewport of the scene.
813 {
814  std::lock_guard<std::recursive_timed_mutex> lck(m_csAccess3DScene);
815  return m_3Dscene->getViewport("main");
816 }
817 
819 {
820  std::lock_guard<std::recursive_timed_mutex> lck(m_csAccess3DScene);
821  m_3Dscene->getViewport("main")->setImageView(img);
822 }
823 
825 {
826  std::lock_guard<std::recursive_timed_mutex> lck(m_csAccess3DScene);
827  m_3Dscene->getViewport("main")->setImageView(std::move(img));
828 }
829 
832  : m_win(win)
833 {
834  out_scene_ptr = m_win.get3DSceneAndLock();
835 }
837  : m_win(win)
838 {
840 }
842 {
844 }
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.
An event sent by a window upon a mouse click, giving the (x,y) pixel coordinates. ...
std::atomic_int m_keyPushedCode
void OnClose(wxCloseEvent &event)
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.
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
mrpt::void_ptr_noncopy m_hwnd
The window handle.
std::string std::string format(std::string_view fmt, ARGS &&... args)
Definition: format.h:26
std::string m_caption
The caption of the window.
size_t size(const MATRIXLIKE &m, const int dim)
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.
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()
void setMaxRange(float new_max)
Changes the camera max clip range (z) (used for gluPerspective.
STL namespace.
CDisplayWindow3D * m_win3D
Definition: WxSubsystem.h:393
static CDisplayWindow3D::Ptr Create(const std::string &windowCaption, unsigned int initialWindowWidth=400, unsigned int initialWindowHeight=300)
Class factory returning a smart pointer.
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.
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: ...
void setMinRange(float new_min)
Changes the camera min clip range (z) (used for gluPerspective).
const long ID_MENUITEM1
This base provides a set of functions for maths stuff.
void getCameraPointingToPoint(float &x, float &y, float &z) const
Get camera parameters programmatically.
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...
bool isOpen()
Returns false if the user has already closed the window.
std::atomic< mrptKeyModifier > m_keyPushedModifier
A pair (x,y) of pixel coordinates (integer resolution).
Definition: TPixelCoord.h:40
An event sent by a window upon a char pressed by the user.
const long ID_MENUITEM2
mrpt::gui::CDisplayWindow3D::Ptr win
mrptKeyModifier keyEventToMrptKeyModifier(const wxKeyEvent &ev)
Extracts the key modifiers from a wxKeyEvent.
Definition: WxUtils.cpp:939
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)
std::recursive_timed_mutex m_csAccess3DScene
Critical section for accesing m_3Dscene.
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
void grabImagesStop()
Stops image grabbing started by grabImagesStart.
std::atomic_bool m_keyPushed
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:57
void setCameraZoom(float zoom)
Changes the camera parameters programmatically.
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:13
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.
bool getLastWindowImage(mrpt::img::CImage &out_img) const
Retrieve the last captured image from the window.
mrpt::img::CImage::Ptr m_last_captured_img
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.
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
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.
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 based on wxWidgets.
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:148
void setCameraElevationDeg(float deg)
Changes the camera parameters programmatically.
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.
Definition: TLine3D.h:19
float getCameraElevationDeg() const
Get camera parameters programmatically.



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020