12 #include <mrpt/config.h>
21 #if MRPT_HAS_OPENGL_GLUT
28 #include <OpenGL/gl.h>
29 #include <OpenGL/glu.h>
30 #include <GLUT/glut.h>
35 #ifdef HAVE_FREEGLUT_EXT_H
36 #include <GL/freeglut_ext.h>
48 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
51 #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild wxWidgets"
59 class CMyGLCanvas_DisplayWindow3D :
public mrpt::gui::CWxGLCanvasBase
62 CMyGLCanvas_DisplayWindow3D(
64 const wxPoint& pos = wxDefaultPosition,
65 const wxSize&
size = wxDefaultSize,
long style = 0,
66 const wxString&
name = _T(
"CMyGLCanvas_DisplayWindow3D"));
68 virtual ~CMyGLCanvas_DisplayWindow3D();
78 void render_text_messages_public(
const int w,
const int h)
const
80 render_text_messages(
w, h);
83 THubClass m_text_msgs;
85 void OnCharCustom(wxKeyEvent& event);
86 void OnMouseDown(wxMouseEvent& event);
87 void OnMouseMove(wxMouseEvent& event);
91 void OnPostRenderSwapBuffers(
double At, wxPaintDC& dc);
93 static void display3D_processKeyEvent(
98 CMyGLCanvas_DisplayWindow3D::CMyGLCanvas_DisplayWindow3D(
100 const wxPoint& pos,
const wxSize&
size,
long style,
const wxString&
name)
101 : CWxGLCanvasBase(parent,
id, pos,
size, style,
name), m_win3D(win3D)
103 this->Bind(wxEVT_CHAR, &CMyGLCanvas_DisplayWindow3D::OnCharCustom,
this);
105 wxEVT_CHAR_HOOK, &CMyGLCanvas_DisplayWindow3D::OnCharCustom,
this);
107 wxEVT_LEFT_DOWN, &CMyGLCanvas_DisplayWindow3D::OnMouseDown,
this);
109 wxEVT_RIGHT_DOWN, &CMyGLCanvas_DisplayWindow3D::OnMouseDown,
this);
110 this->Bind(wxEVT_MOTION, &CMyGLCanvas_DisplayWindow3D::OnMouseMove,
this);
113 void CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(
124 cout <<
"[CDisplayWindow3D] Switching fullscreen...\n";
128 win->ShowFullScreen(!
win->IsFullScreen());
139 const int code = ev.GetKeyCode();
158 void CMyGLCanvas_DisplayWindow3D::OnCharCustom(wxKeyEvent& ev)
160 CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(m_win3D, ev);
163 void CMyGLCanvas_DisplayWindow3D::OnMouseDown(wxMouseEvent& event)
172 event.LeftDown(), event.RightDown()));
182 void CMyGLCanvas_DisplayWindow3D::OnMouseMove(wxMouseEvent& event)
191 event.LeftDown(), event.RightDown()));
201 CMyGLCanvas_DisplayWindow3D::~CMyGLCanvas_DisplayWindow3D()
203 getOpenGLSceneRef().reset();
207 void CMyGLCanvas_DisplayWindow3D::OnPreRender()
209 auto& openGLSceneRef = getOpenGLSceneRef();
210 if (openGLSceneRef) openGLSceneRef.reset();
213 if (ptrScene) openGLSceneRef = ptrScene;
216 void CMyGLCanvas_DisplayWindow3D::OnPostRender()
219 getOpenGLSceneRef().reset();
224 this->GetSize(&
w, &h);
226 m_text_msgs.render_text_messages_public(
w, h);
229 void CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers(
230 double At, wxPaintDC& dc)
248 if (!grabFile.empty())
250 frame->saveToFile(grabFile);
257 std::lock_guard<std::mutex> lock(
268 #if MRPT_HAS_WXWIDGETS
279 const std::
string& caption, wxSize initialSize)
280 : m_win3D(win3D), m_mainFrame(parent)
282 #if MRPT_HAS_OPENGL_GLUT
285 parent,
id,
_U(caption.c_str()), wxDefaultPosition, initialSize,
286 wxDEFAULT_FRAME_STYLE, _T(
"id"));
293 m_canvas =
new CMyGLCanvas_DisplayWindow3D(
294 win3D,
this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
297 this->Bind(wxEVT_CLOSE_WINDOW, &C3DWindowDialog::OnClose,
this);
299 wxEVT_COMMAND_MENU_SELECTED, &C3DWindowDialog::OnMenuClose,
this,
302 wxEVT_COMMAND_MENU_SELECTED, &C3DWindowDialog::OnMenuAbout,
this,
304 this->Bind(wxEVT_CHAR, &C3DWindowDialog::OnChar,
this);
305 this->Bind(wxEVT_SIZE, &C3DWindowDialog::OnResize,
this);
309 WxSubsystem::CWXMainFrame::notifyWindowCreation();
318 C3DWindowDialog::~C3DWindowDialog()
327 bool allow_close =
true;
337 if (!allow_close)
return;
358 _(
"3D Scene viewer\n Class gui::CDisplayWindow3D\n MRPT C++ library"),
364 #if MRPT_HAS_OPENGL_GLUT
365 CMyGLCanvas_DisplayWindow3D::display3D_processKeyEvent(
m_win3D, ev);
371 #if MRPT_HAS_OPENGL_GLUT
378 m_win3D, event.GetSize().GetWidth(),
379 event.GetSize().GetHeight()));
391 #if MRPT_HAS_OPENGL_GLUT
392 m_canvas->m_text_msgs.clearTextMessages();
397 const double x_frac,
const double y_frac,
const std::string& text,
401 #if MRPT_HAS_OPENGL_GLUT
402 m_canvas->m_text_msgs.addTextMessage(
403 x_frac, y_frac, text,
color, unique_index, font);
408 const double x_frac,
const double y_frac,
const std::string& text,
411 const size_t unique_index,
const double font_spacing,
412 const double font_kerning,
const bool has_shadow,
415 #if MRPT_HAS_OPENGL_GLUT
416 m_canvas->m_text_msgs.addTextMessage(
417 x_frac, y_frac, text,
color, font_name, font_size, font_style,
418 unique_index, font_spacing, font_kerning, has_shadow, shadow_color);
428 const std::string& windowCaption,
unsigned int initialWindowWidth,
429 unsigned int initialWindowHeight)
431 m_grab_imgs_prefix(),
433 m_is_capturing_imgs(false),
434 m_lastFullScreen(
mrpt::system::
now()),
445 const std::string& windowCaption,
unsigned int initialWindowWidth,
446 unsigned int initialWindowHeight)
449 windowCaption, initialWindowWidth, initialWindowHeight));
468 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
471 cerr <<
"[CDisplayWindow3D::setPos] Window closed!: " <<
m_caption
495 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
498 cerr <<
"[CDisplayWindow3D::setPos] Window closed!: " <<
m_caption
522 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
525 cerr <<
"[CDisplayWindow3D::setWindowTitle] Window closed!: "
560 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
582 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
584 if (
win)
win->m_canvas->setElevationDegrees(deg);
592 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
594 if (
win)
win->m_canvas->setUseCameraFromScene(useIt);
605 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
607 if (
win)
win->m_canvas->setAzimuthDegrees(deg);
618 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
622 win->m_canvas->setCameraPointing(
x,
y,
z);
636 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
638 if (
win)
win->m_canvas->setZoomDistance(zoom);
649 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
651 if (
win)
win->m_canvas->setCameraProjective(isProjective);
666 gl_view->getViewportClipDistances(m, M);
667 gl_view->setViewportClipDistances(new_min, M);
680 gl_view->getViewportClipDistances(m, M);
681 gl_view->setViewportClipDistances(m, new_max);
688 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
690 if (
win)
return win->m_canvas->cameraFOV();
697 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
699 if (
win)
win->m_canvas->setCameraFOV(
v);
708 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
710 return win ?
win->m_canvas->getElevationDegrees() : 0;
721 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
723 return win ?
win->m_canvas->getAzimuthDegrees() : 0;
733 float&
x,
float&
y,
float&
z)
const
735 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
739 x =
win->m_canvas->getCameraPointingX();
740 y =
win->m_canvas->getCameraPointingY();
741 z =
win->m_canvas->getCameraPointingZ();
757 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
759 return win ?
win->m_canvas->getZoomDistance() : 0;
770 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
772 return win ?
win->m_canvas->isCameraProjective() :
true;
783 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
785 if (!
win)
return false;
786 win->m_canvas->getLastMousePosition(
x,
y);
804 m_3Dscene->getViewport(
"main")->get3DRayForPixelCoord(
x,
y, ray);
817 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
820 win->m_canvas->SetCursor(
821 *(cursorIsCross ? wxCROSS_CURSOR : wxSTANDARD_CURSOR));
893 const double x_frac,
const double y_frac,
const std::string& text,
897 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
917 REQ->
y = int(unique_index);
935 const double x_frac,
const double y_frac,
const std::string& text,
938 const size_t unique_index,
const double font_spacing,
939 const double font_kerning,
const bool draw_shadow,
942 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
963 REQ->
vector_x[8] = draw_shadow ? 1 : 0;
968 REQ->
x = int(font_style);
969 REQ->
y = int(unique_index);
994 #if MRPT_HAS_WXWIDGETS && MRPT_HAS_OPENGL_GLUT
1010 const double ALPHA = 0.99;
1034 view->setImageView(
img);
1042 view->setImageView_fast(
img);
void OnMenuClose(wxCommandEvent &event)
void OnClose(wxCloseEvent &event)
CMyGLCanvas_DisplayWindow3D * m_canvas
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)
void OnResize(wxSizeEvent &event)
void OnChar(wxKeyEvent &event)
CDisplayWindow3D * m_win3D
void OnMenuAbout(wxCommandEvent &event)
The base class for GUI window classes.
std::string m_caption
The caption of the window.
void notifyChildWindowDestruction()
Called by wx main thread to set m_hwnd to NULL.
bool isOpen()
Returns false if the user has already closed the window.
std::promise< void > m_windowDestroyed
This semaphore will be signaled when the wx window is destroyed.
void createWxWindow(unsigned int initialWidth, unsigned int initialHeight)
Must be called by child classes just within the constructor.
void destroyWxWindow()
Must be called by child classes in their destructors.
mrpt::void_ptr_noncopy m_hwnd
The window handle.
volatile int m_keyPushedCode
volatile mrptKeyModifier m_keyPushedModifier
volatile bool m_keyPushed
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.
static CDisplayWindow3D::Ptr Create(const std::string &windowCaption, unsigned int initialWindowWidth=400, unsigned int initialWindowHeight=300)
Class factory returning a smart pointer.
void setCameraPointingToPoint(float x, float y, float z)
Changes the camera parameters programmatically.
mrpt::img::CImage::Ptr getLastWindowImagePtr() const
Retrieve the last captured image from the window, as a smart pointer.
void internal_setRenderingFPS(double FPS)
Set the rendering FPS (users don't call this, the method is for internal MRPT objects only)
unsigned int m_grab_imgs_idx
void forceRepaint()
Repaints the window.
void unlockAccess3DScene()
Unlocks the access to the internal 3D scene.
void setPos(int x, int y) override
Changes the position of the window on the screen.
virtual void setCursorCross(bool cursorIsCross) override
Set cursor style to default (cursorIsCross=false) or to a cross (cursorIsCross=true)
std::recursive_mutex m_csAccess3DScene
Critical section for accesing m_3Dscene.
bool getLastMousePositionRay(mrpt::math::TLine3D &ray) const
Gets the 3D ray for the direction line of the pixel where the mouse cursor is at.
void setCameraZoom(float zoom)
Changes the camera parameters programmatically.
float getCameraElevationDeg() const
Get camera parameters programmatically.
bool isCapturingImgs() const
void setImageView_fast(mrpt::img::CImage &img)
Just like setImageView but moves the internal image memory instead of making a copy,...
void getCameraPointingToPoint(float &x, float &y, float &z) const
Get camera parameters programmatically.
void setFOV(float v)
Changes the camera field of view (in degrees) (used for gluPerspective).
void setWindowTitle(const std::string &str) override
Changes the window title.
void setCameraProjective(bool isProjective)
Sets the camera as projective, or orthogonal.
void grabImagesStart(const std::string &grab_imgs_prefix=std::string("video_"))
Start to save rendered images to disk.
CDisplayWindow3D(const std::string &windowCaption=std::string(), unsigned int initialWindowWidth=400, unsigned int initialWindowHeight=300)
Constructor.
mrpt::opengl::COpenGLScene::Ptr & get3DSceneAndLock()
Gets a reference to the smart shared pointer that holds the internal scene (carefuly read introductio...
void setCameraAzimuthDeg(float deg)
Changes the camera parameters programmatically.
virtual bool getLastMousePosition(int &x, int &y) const override
Gets the last x,y pixel coordinates of the mouse.
virtual ~CDisplayWindow3D()
Destructor.
std::string m_grab_imgs_prefix
bool isCameraProjective() const
Sets the camera as projective, or orthogonal.
void captureImagesStart()
Enables the grabbing of CImage objects from screenshots of the window.
void setMaxRange(double new_max)
Changes the camera max clip range (z) (used for gluPerspective.
void resize(unsigned int width, unsigned int height) override
Resizes the window, stretching the image to fit into the display area.
float getFOV() const
Return the camera field of view (in degrees) (used for gluPerspective)
void internal_emitGrabImageEvent(const std::string &fil)
called by CMyGLCanvas_DisplayWindow3D::OnPostRenderSwapBuffers
mrpt::opengl::COpenGLViewport::Ptr getDefaultViewport()
A short cut for getting the "main" viewport of the scene object, it is equivalent to:
mrpt::opengl::COpenGLScene::Ptr m_3Dscene
Internal OpenGL object (see general discussion in about usage of this object)
mrpt::system::TTimeStamp m_lastFullScreen
std::string grabImageGetNextFile()
Increments by one the image counter and return the next image file name (Users normally don't want to...
float getCameraAzimuthDeg() const
Get camera parameters programmatically.
mrpt::img::CImage::Ptr m_last_captured_img
void setMinRange(double new_min)
Changes the camera min clip range (z) (used for gluPerspective).
float getCameraZoom() const
Get camera parameters programmatically.
void clearTextMessages()
Clear all text messages created with addTextMessage().
std::mutex m_last_captured_img_cs
void setImageView(const mrpt::img::CImage &img)
Set the "main" viewport into "image view"-mode, where an image is efficiently drawn (fitting the view...
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.
void grabImagesStop()
Stops image grabbing started by grabImagesStart.
bool getLastWindowImage(mrpt::img::CImage &out_img) const
Retrieve the last captured image from the window.
void setCameraElevationDeg(float deg)
Changes the camera parameters programmatically.
void captureImagesStop()
Stop image grabbing.
std::shared_ptr< CDisplayWindow3D > Ptr
void useCameraFromScene(bool useIt=true)
If set to true (default = false), the mouse-based scene navigation will be disabled and the camera po...
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...
~CDisplayWindow3DLocker()
static int notifyWindowDestruction()
Atomically decrements the number of windows created with the main frame as parent.
This class implements the GUI thread required for the wxWidgets-based GUI.
static void pushPendingWxRequest(TRequestToWxMainThread *data)
Thread-safe method to insert a new pending request (The memory must be dinamically allocated with "ne...
static wxBitmap getMRPTDefaultIcon()
An event sent by a CDisplayWindow3D window when an image is saved after enabling this feature with CD...
An event sent by a window upon a mouse click, giving the (x,y) pixel coordinates.
An event sent by a window when the mouse is moved over it.
An event sent by a window upon a char pressed by the user.
An event sent by a window upon when it's about to be closed, either manually by the user or programma...
An event sent by a window upon resize.
A class for storing images as grayscale or RGB bitmaps.
std::shared_ptr< CImage > Ptr
std::shared_ptr< COpenGLScene > Ptr
std::shared_ptr< COpenGLViewport > Ptr
Keeps a list of text messages which can be rendered to OpenGL contexts by graphic classes.
bool hasSubscribers() const
Can be called by a derived class before preparing an event for publishing with publishEvent to determ...
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...
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
#define THROW_EXCEPTION(msg)
GLAPI void GLAPIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
GLAPI void GLAPIENTRY glReadBuffer(GLenum mode)
GLubyte GLubyte GLubyte GLubyte w
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
GLuint const GLchar * name
GLenum GLsizei GLsizei height
GLsizei const GLchar ** string
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
mrptKeyModifier keyEventToMrptKeyModifier(const wxKeyEvent &ev)
Extracts the key modifiers from a wxKeyEvent.
TOpenGLFont
Existing fonts for 2D texts in mrpt::opengl methods.
mrpt::system::TTimeStamp now()
A shortcut for system::getCurrentTime.
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
Classes for creating GUI windows for 2D and 3D visualization.
This base provides a set of functions for maths stuff.
The namespace for 3D scene representation and rendering.
TOpenGLFontStyle
Different style for vectorized font rendering.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
The data structure for each inter-thread request:
int OPCODE
Valid codes are: For CDisplayWindow:
mrpt::math::CVectorFloat vector_x
mrpt::gui::CDisplayWindow3D * source3D
Only one of source* can be non-nullptr, indicating the class that generated the request.
std::string str
Parameters, depending on OPCODE.
A RGB color - floats in the range [0,1].
A pair (x,y) of pixel coordinates (integer resolution).
3D line, represented by a base point and a director vector.
mrpt::gui::CDisplayWindow3D::Ptr win