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);
245 
248 
250  glReadPixels(0, 0, w, h, GL_BGR_EXT, GL_UNSIGNED_BYTE, (*frame)(0, 0));
251  frame->flipVertical();
252 
253  if (!grabFile.empty())
254  {
255  frame->saveToFile(grabFile);
256  m_win3D->internal_emitGrabImageEvent(grabFile);
257  }
258 
259  if (m_win3D->isCapturingImgs())
260  {
261  {
262  std::lock_guard<std::mutex> lock(
263  m_win3D->m_last_captured_img_cs);
264  m_win3D->m_last_captured_img = frame;
265  frame.reset();
266  }
267  }
268  }
269 }
270 
271 #endif // Wx + OpenGL
272 
273 #if MRPT_HAS_WXWIDGETS
274 
275 BEGIN_EVENT_TABLE(C3DWindowDialog, wxFrame)
276 
277 END_EVENT_TABLE()
278 
279 const long C3DWindowDialog::ID_MENUITEM1 = wxNewId();
280 const long C3DWindowDialog::ID_MENUITEM2 = wxNewId();
281 
283  CDisplayWindow3D* win3D, WxSubsystem::CWXMainFrame* parent, wxWindowID id,
284  const std::string& caption, wxSize initialSize)
285  : m_win3D(win3D), m_mainFrame(parent)
286 {
287 #if MRPT_HAS_OPENGL_GLUT
288 
289  Create(
290  parent, id, caption.c_str(), wxDefaultPosition, initialSize,
291  wxDEFAULT_FRAME_STYLE, _T("id"));
292 
293  wxIcon FrameIcon;
294  FrameIcon.CopyFromBitmap(mrpt::gui::WxSubsystem::getMRPTDefaultIcon());
295  SetIcon(FrameIcon);
296 
297  // Create the wxCanvas object:
298  m_canvas = new CMyGLCanvas_DisplayWindow3D(
299  win3D, this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
300 
301  // Events:
302  this->Bind(wxEVT_CLOSE_WINDOW, &C3DWindowDialog::OnClose, this);
303  this->Bind(
304  wxEVT_COMMAND_MENU_SELECTED, &C3DWindowDialog::OnMenuClose, this,
305  ID_MENUITEM1);
306  this->Bind(
307  wxEVT_COMMAND_MENU_SELECTED, &C3DWindowDialog::OnMenuAbout, this,
308  ID_MENUITEM2);
309  this->Bind(wxEVT_CHAR, &C3DWindowDialog::OnChar, this);
310  this->Bind(wxEVT_SIZE, &C3DWindowDialog::OnResize, this);
311 
312  // Increment number of windows:
313  // int winCount =
315 // cout << "[C3DWindowDialog] Notifying new window: " << winCount << endl;
316 #else
317  THROW_EXCEPTION("MRPT was compiled without OpenGL support");
318 #endif
319  // this->Iconize(false);
320 }
321 
322 // Destructor
324 {
325  // cout << "[C3DWindowDialog::~C3DWindowDialog]" << endl;
326 }
327 
328 // OnClose event:
329 void C3DWindowDialog::OnClose(wxCloseEvent& event)
330 {
331  // Send the event:
332  bool allow_close = true;
333  try
334  {
335  mrptEventWindowClosed ev(m_win3D, true /* allow close */);
336  m_win3D->publishEvent(ev);
337  allow_close = ev.allow_close;
338  }
339  catch (...)
340  {
341  }
342  if (!allow_close) return; // Don't process this close event.
343 
344  // cout << "[C3DWindowDialog::OnClose]" << endl;
345  // Set the m_hwnd=nullptr in our parent object.
347 
348  // Decrement number of windows:
350 
351  // Signal we are destroyed:
352  m_win3D->m_windowDestroyed.set_value();
353 
354  event.Skip(); // keep processing by parent classes.
355 }
356 
357 // Menu: Close
358 void C3DWindowDialog::OnMenuClose(wxCommandEvent& event) { Close(); }
359 // Menu: About
360 void C3DWindowDialog::OnMenuAbout(wxCommandEvent& event)
361 {
362  ::wxMessageBox(
363  _("3D Scene viewer\n Class gui::CDisplayWindow3D\n MRPT C++ library"),
364  _("About..."));
365 }
366 
367 void C3DWindowDialog::OnChar(wxKeyEvent& ev)
368 {
369 #if MRPT_HAS_OPENGL_GLUT
370  CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(m_win3D, ev);
371 #endif
372 }
373 
374 void C3DWindowDialog::OnResize(wxSizeEvent& event)
375 {
376 #if MRPT_HAS_OPENGL_GLUT
377  // Send the event:
378  if (m_win3D)
379  {
380  try
381  {
383  m_win3D, event.GetSize().GetWidth(),
384  event.GetSize().GetHeight()));
385  }
386  catch (...)
387  {
388  }
389  }
390  event.Skip(); // so it's processed by the wx system!
391 #endif
392 }
393 
395 {
396 #if MRPT_HAS_OPENGL_GLUT
397  m_canvas->m_text_msgs.clearTextMessages();
398 #endif
399 }
400 
402  const double x_frac, const double y_frac, const std::string& text,
403  const mrpt::img::TColorf& color, const size_t unique_index,
404  const mrpt::opengl::TOpenGLFont font)
405 {
406 #if MRPT_HAS_OPENGL_GLUT
407  m_canvas->m_text_msgs.addTextMessage(
408  x_frac, y_frac, text, color, unique_index, font);
409 #endif
410 }
411 
413  const double x_frac, const double y_frac, const std::string& text,
414  const mrpt::img::TColorf& color, const std::string& font_name,
415  const double font_size, const mrpt::opengl::TOpenGLFontStyle font_style,
416  const size_t unique_index, const double font_spacing,
417  const double font_kerning, const bool has_shadow,
418  const mrpt::img::TColorf& shadow_color)
419 {
420 #if MRPT_HAS_OPENGL_GLUT
421  m_canvas->m_text_msgs.addTextMessage(
422  x_frac, y_frac, text, color, font_name, font_size, font_style,
423  unique_index, font_spacing, font_kerning, has_shadow, shadow_color);
424 #endif
425 }
426 
427 #endif // MRPT_HAS_WXWIDGETS
428 
429 /*---------------------------------------------------------------
430  Constructor
431  ---------------------------------------------------------------*/
433  const std::string& windowCaption, unsigned int initialWindowWidth,
434  unsigned int initialWindowHeight)
435  : CBaseGUIWindow(static_cast<void*>(this), 300, 399, windowCaption),
436  m_lastFullScreen(mrpt::system::now())
437 {
438  m_3Dscene = COpenGLScene::Create();
439  CBaseGUIWindow::createWxWindow(initialWindowWidth, initialWindowHeight);
440 }
441 
443  const std::string& windowCaption, unsigned int initialWindowWidth,
444  unsigned int initialWindowHeight)
445 {
446  return std::make_shared<CDisplayWindow3D>(
447  windowCaption, initialWindowWidth, initialWindowHeight);
448 }
449 /*---------------------------------------------------------------
450  Destructor
451  ---------------------------------------------------------------*/
453 {
454  // get lock so we make sure nobody else is touching the window right now.
455  m_csAccess3DScene.lock();
456  m_csAccess3DScene.unlock();
457 
459 }
460 
461 /*---------------------------------------------------------------
462  resize
463  ---------------------------------------------------------------*/
464 void CDisplayWindow3D::resize(unsigned int width, unsigned int height)
465 {
466 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
467  if (!isOpen())
468  {
469  cerr << "[CDisplayWindow3D::setPos] Window closed!: " << m_caption
470  << endl;
471  return;
472  }
473 
474  // Send a request to destroy this object:
475  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
476  REQ->source3D = this;
477  REQ->OPCODE = 303;
478  REQ->x = width;
479  REQ->y = height;
481 #else
484 #endif
485 }
486 
487 /*---------------------------------------------------------------
488  setPos
489  ---------------------------------------------------------------*/
491 {
492 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
493  if (!isOpen())
494  {
495  cerr << "[CDisplayWindow3D::setPos] Window closed!: " << m_caption
496  << endl;
497  return;
498  }
499 
500  // Send a request to destroy this object:
501  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
502  REQ->source3D = this;
503  REQ->OPCODE = 302;
504  REQ->x = x;
505  REQ->y = y;
507 #else
510 #endif
511 }
512 
513 /*---------------------------------------------------------------
514  setWindowTitle
515  ---------------------------------------------------------------*/
517 {
518 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
519  if (!isOpen())
520  {
521  cerr << "[CDisplayWindow3D::setWindowTitle] Window closed!: "
522  << m_caption << endl;
523  return;
524  }
525 
526  // Send a request to destroy this object:
527  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
528  REQ->source3D = this;
529  REQ->OPCODE = 304;
530  REQ->str = str;
532 #else
533  MRPT_UNUSED_PARAM(str);
534 #endif
535 }
536 
537 /*---------------------------------------------------------------
538  get3DSceneAndLock
539  ---------------------------------------------------------------*/
541 {
542  m_csAccess3DScene.lock();
543  return m_3Dscene;
544 }
545 
546 /*---------------------------------------------------------------
547  unlockAccess3DScene
548  ---------------------------------------------------------------*/
550 /*---------------------------------------------------------------
551  forceRepaint
552  ---------------------------------------------------------------*/
554 {
555 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
556  auto* win = (C3DWindowDialog*)m_hwnd.get();
557  if (win)
558  {
559  // win->Refresh(false); // Do not erase background
560  // We must do this from the wx thread!
561 
562  // Send refresh request:
563  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
564  REQ->source3D = this;
565  REQ->OPCODE = 350;
567  }
568 #endif
569 }
570 
571 /*---------------------------------------------------------------
572  setCameraElevationDeg
573  ---------------------------------------------------------------*/
575 {
576 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
577  auto* win = (C3DWindowDialog*)m_hwnd.get();
578  if (win) win->m_canvas->setElevationDegrees(deg);
579 #else
580  MRPT_UNUSED_PARAM(deg);
581 #endif
582 }
583 
585 {
586 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
587  auto* win = (C3DWindowDialog*)m_hwnd.get();
588  if (win) win->m_canvas->setUseCameraFromScene(useIt);
589 #else
590  MRPT_UNUSED_PARAM(useIt);
591 #endif
592 }
593 
594 /*---------------------------------------------------------------
595  setCameraAzimuthDeg
596  ---------------------------------------------------------------*/
598 {
599 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
600  auto* win = (C3DWindowDialog*)m_hwnd.get();
601  if (win) win->m_canvas->setAzimuthDegrees(deg);
602 #else
603  MRPT_UNUSED_PARAM(deg);
604 #endif
605 }
606 
607 /*---------------------------------------------------------------
608  setCameraPointingToPoint
609  ---------------------------------------------------------------*/
611 {
612 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
613  auto* win = (C3DWindowDialog*)m_hwnd.get();
614  if (win)
615  {
616  win->m_canvas->setCameraPointing(x, y, z);
617  }
618 #else
622 #endif
623 }
624 
625 /*---------------------------------------------------------------
626  setCameraZoom
627  ---------------------------------------------------------------*/
629 {
630 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
631  auto* win = (C3DWindowDialog*)m_hwnd.get();
632  if (win) win->m_canvas->setZoomDistance(zoom);
633 #else
634  MRPT_UNUSED_PARAM(zoom);
635 #endif
636 }
637 
638 /*---------------------------------------------------------------
639  setCameraProjective
640  ---------------------------------------------------------------*/
642 {
643 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
644  auto* win = (C3DWindowDialog*)m_hwnd.get();
645  if (win) win->m_canvas->setCameraProjective(isProjective);
646 #else
647  MRPT_UNUSED_PARAM(isProjective);
648 #endif
649 }
650 
651 void CDisplayWindow3D::setMinRange(double new_min)
652 {
653  if (m_3Dscene)
654  {
656  m_3Dscene->getViewport("main");
657  if (gl_view)
658  {
659  double m, M;
660  gl_view->getViewportClipDistances(m, M);
661  gl_view->setViewportClipDistances(new_min, M);
662  }
663  }
664 }
665 void CDisplayWindow3D::setMaxRange(double new_max)
666 {
667  if (m_3Dscene)
668  {
670  m_3Dscene->getViewport("main");
671  if (gl_view)
672  {
673  double m, M;
674  gl_view->getViewportClipDistances(m, M);
675  gl_view->setViewportClipDistances(m, new_max);
676  }
677  }
678 }
679 
681 {
682 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
683  auto* win = (C3DWindowDialog*)m_hwnd.get();
684  if (win) return win->m_canvas->cameraFOV();
685 #endif
686  return .0f;
687 }
688 
690 {
691 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
692  auto* win = (C3DWindowDialog*)m_hwnd.get();
693  if (win) win->m_canvas->setCameraFOV(v);
694 #endif
695 }
696 
697 /*---------------------------------------------------------------
698  getCameraElevationDeg
699  ---------------------------------------------------------------*/
701 {
702 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
703  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
704  return win ? win->m_canvas->getElevationDegrees() : 0;
705 #else
706  return 0;
707 #endif
708 }
709 
710 /*---------------------------------------------------------------
711  getCameraAzimuthDeg
712  ---------------------------------------------------------------*/
714 {
715 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
716  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
717  return win ? win->m_canvas->getAzimuthDegrees() : 0;
718 #else
719  return 0;
720 #endif
721 }
722 
723 /*---------------------------------------------------------------
724  getCameraPointingToPoint
725  ---------------------------------------------------------------*/
727  float& x, float& y, float& z) const
728 {
729 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
730  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
731  if (win)
732  {
733  x = win->m_canvas->getCameraPointingX();
734  y = win->m_canvas->getCameraPointingY();
735  z = win->m_canvas->getCameraPointingZ();
736  }
737  else
738  x = y = z = 0;
739 #else
743 #endif
744 }
745 
746 /*---------------------------------------------------------------
747  getCameraZoom
748  ---------------------------------------------------------------*/
750 {
751 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
752  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
753  return win ? win->m_canvas->getZoomDistance() : 0;
754 #else
755  return 0;
756 #endif
757 }
758 
759 /*---------------------------------------------------------------
760  isCameraProjective
761  ---------------------------------------------------------------*/
763 {
764 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
765  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
766  return win ? win->m_canvas->isCameraProjective() : true;
767 #else
768  return true;
769 #endif
770 }
771 
772 /*---------------------------------------------------------------
773  getLastMousePosition
774  ---------------------------------------------------------------*/
776 {
777 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
778  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
779  if (!win) return false;
780  win->m_canvas->getLastMousePosition(x, y);
781  return true;
782 #else
785  return false;
786 #endif
787 }
788 
789 /*---------------------------------------------------------------
790  getLastMousePositionRay
791  ---------------------------------------------------------------*/
793 {
794  int x, y;
795  if (getLastMousePosition(x, y))
796  {
797  m_csAccess3DScene.lock();
798  m_3Dscene->getViewport("main")->get3DRayForPixelCoord(x, y, ray);
799  m_csAccess3DScene.unlock();
800  return true;
801  }
802  else
803  return false;
804 }
805 
806 /*---------------------------------------------------------------
807  setCursorCross
808  ---------------------------------------------------------------*/
809 void CDisplayWindow3D::setCursorCross(bool cursorIsCross)
810 {
811 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
812  const auto* win = (const C3DWindowDialog*)m_hwnd.get();
813  if (!win) return;
814  win->m_canvas->SetCursor(
815  *(cursorIsCross ? wxCROSS_CURSOR : wxSTANDARD_CURSOR));
816 #else
817  MRPT_UNUSED_PARAM(cursorIsCross);
818 #endif
819 }
820 
821 /*---------------------------------------------------------------
822  grabImagesStart
823  ---------------------------------------------------------------*/
824 void CDisplayWindow3D::grabImagesStart(const std::string& grab_imgs_prefix)
825 {
826  m_grab_imgs_prefix = grab_imgs_prefix;
827  m_grab_imgs_idx = 0;
828 }
829 
830 /*---------------------------------------------------------------
831  grabImagesStop
832  ---------------------------------------------------------------*/
834 /*---------------------------------------------------------------
835  grabImageGetNextFile
836  ---------------------------------------------------------------*/
838 {
839  if (m_grab_imgs_prefix.empty())
840  return string();
841  else
842  return format(
843  "%s%06u.png", m_grab_imgs_prefix.c_str(), m_grab_imgs_idx++);
844 }
845 
846 /*---------------------------------------------------------------
847  captureImagesStart
848  ---------------------------------------------------------------*/
850 /*---------------------------------------------------------------
851  captureImagesStop
852  ---------------------------------------------------------------*/
854 /*---------------------------------------------------------------
855  getLastWindowImage
856  ---------------------------------------------------------------*/
858 {
859  bool ret;
860 
861  {
862  std::lock_guard<std::mutex> lock(m_last_captured_img_cs);
864  {
865  out_img = *m_last_captured_img; // Copy the full image
866  ret = true;
867  }
868  else
869  ret = false;
870  }
871  return ret;
872 }
873 
874 /*---------------------------------------------------------------
875  getLastWindowImagePtr
876  ---------------------------------------------------------------*/
878 {
879  std::lock_guard<std::mutex> lock(m_last_captured_img_cs);
880  return m_last_captured_img;
881 }
882 
883 /*---------------------------------------------------------------
884  addTextMessage
885  ---------------------------------------------------------------*/
887  const double x_frac, const double y_frac, const std::string& text,
888  const mrpt::img::TColorf& color, const size_t unique_index,
889  const TOpenGLFont font)
890 {
891 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
892  auto* win = (C3DWindowDialog*)m_hwnd.get();
893  if (win)
894  {
895  // Send request:
896  // Add a 2D text message:
897  // vector_x: [0]:x, [1]:y, [2,3,4]:R G B, "x": enum of desired font.
898  // "y": unique index, "str": String.
899  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
900  REQ->source3D = this;
901  REQ->OPCODE = 360;
902  REQ->str = text;
903  REQ->vector_x.resize(5);
904  REQ->vector_x[0] = x_frac;
905  REQ->vector_x[1] = y_frac;
906  REQ->vector_x[2] = color.R;
907  REQ->vector_x[3] = color.G;
908  REQ->vector_x[4] = color.B;
909  REQ->x = int(font);
910  REQ->y = int(unique_index);
911 
913  }
914 #else
915  MRPT_UNUSED_PARAM(x_frac);
916  MRPT_UNUSED_PARAM(y_frac);
917  MRPT_UNUSED_PARAM(text);
919  MRPT_UNUSED_PARAM(unique_index);
920  MRPT_UNUSED_PARAM(font);
921 #endif
922 }
923 
924 /*---------------------------------------------------------------
925  addTextMessage
926  ---------------------------------------------------------------*/
928  const double x_frac, const double y_frac, const std::string& text,
929  const mrpt::img::TColorf& color, const std::string& font_name,
930  const double font_size, const mrpt::opengl::TOpenGLFontStyle font_style,
931  const size_t unique_index, const double font_spacing,
932  const double font_kerning, const bool draw_shadow,
933  const mrpt::img::TColorf& shadow_color)
934 {
935 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
936  auto* win = (C3DWindowDialog*)m_hwnd.get();
937  if (win)
938  {
939  // Send request:
940  // Add a 2D text message:
941  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
942  REQ->source3D = this;
943  REQ->OPCODE = 362;
944  REQ->str = text;
945  REQ->plotName = font_name;
946  REQ->vector_x.resize(12);
947  REQ->vector_x[0] = x_frac;
948  REQ->vector_x[1] = y_frac;
949  REQ->vector_x[2] = color.R;
950  REQ->vector_x[3] = color.G;
951  REQ->vector_x[4] = color.B;
952  REQ->vector_x[5] = font_size;
953  REQ->vector_x[6] = font_spacing;
954  REQ->vector_x[7] = font_kerning;
955  REQ->vector_x[8] = draw_shadow ? 1 : 0;
956  REQ->vector_x[9] = shadow_color.R;
957  REQ->vector_x[10] = shadow_color.G;
958  REQ->vector_x[11] = shadow_color.B;
959 
960  REQ->x = int(font_style);
961  REQ->y = int(unique_index);
962 
964  }
965 #else
966  MRPT_UNUSED_PARAM(x_frac);
967  MRPT_UNUSED_PARAM(y_frac);
968  MRPT_UNUSED_PARAM(text);
970  MRPT_UNUSED_PARAM(font_name);
971  MRPT_UNUSED_PARAM(font_size);
972  MRPT_UNUSED_PARAM(font_style);
973  MRPT_UNUSED_PARAM(unique_index);
974  MRPT_UNUSED_PARAM(font_spacing);
975  MRPT_UNUSED_PARAM(font_kerning);
976  MRPT_UNUSED_PARAM(draw_shadow);
977  MRPT_UNUSED_PARAM(shadow_color);
978 #endif
979 }
980 
981 /*---------------------------------------------------------------
982  clearTextMessages
983  ---------------------------------------------------------------*/
985 {
986 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
987  auto* win = (C3DWindowDialog*)m_hwnd.get();
988  if (win)
989  {
990  // Send request:
991  auto* REQ = new WxSubsystem::TRequestToWxMainThread[1];
992  REQ->source3D = this;
993  REQ->OPCODE = 361;
995  }
996 #endif
997 }
998 
1000 {
1001  const double ALPHA = 0.99;
1002  m_last_FPS = ALPHA * m_last_FPS + (1 - ALPHA) * FPS;
1003 }
1004 
1005 // Called by CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers
1007 {
1008  const mrptEvent3DWindowGrabImageFile ev(this, fil);
1009  publishEvent(ev);
1010 }
1011 
1012 // Returns the "main" viewport of the scene.
1014 {
1015  m_csAccess3DScene.lock();
1016  mrpt::opengl::COpenGLViewport::Ptr view = m_3Dscene->getViewport("main");
1017  m_csAccess3DScene.unlock();
1018  return view;
1019 }
1020 
1022 {
1023  m_csAccess3DScene.lock();
1024  mrpt::opengl::COpenGLViewport::Ptr view = m_3Dscene->getViewport("main");
1025  view->setImageView(img);
1026  m_csAccess3DScene.unlock();
1027 }
1028 
1030 {
1031  m_csAccess3DScene.lock();
1032  mrpt::opengl::COpenGLViewport::Ptr view = m_3Dscene->getViewport("main");
1033  view->setImageView(std::move(img));
1034  m_csAccess3DScene.unlock();
1035 }
1036 
1039  : m_win(win)
1040 {
1041  out_scene_ptr = m_win.get3DSceneAndLock();
1042 }
1044  : m_win(win)
1045 {
1047 }
1049 {
1051 }
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:67
#define GL_PACK_ALIGNMENT
Definition: glew.h:491
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
#define GL_PACK_ROW_LENGTH
Definition: glew.h:488
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().
GLAPI void GLAPIENTRY glPixelStorei(GLenum pname, GLint param)
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.
Definition: TLine3D.h:19
#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: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019