00001 #include "wx_ogre_render_window.h"
00002 #include "orthographic.h"
00003
00004 #include <OGRE/OgreRoot.h>
00005 #include <OGRE/OgreViewport.h>
00006 #include <OGRE/OgreCamera.h>
00007 #include <OGRE/OgreRenderWindow.h>
00008 #include <OGRE/OgreStringConverter.h>
00009
00010 #ifdef __WXGTK__
00011 #include <gdk/gdk.h>
00012 #include <gtk/gtk.h>
00013 #include <gdk/gdkx.h>
00014 #include <wx/gtk/win_gtk.h>
00015 #include <GL/glx.h>
00016 #endif
00017
00018 #include <ros/console.h>
00019 #include <ros/assert.h>
00020
00021 #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
00022 #include <stdlib.h>
00023 #endif
00024
00025 namespace ogre_tools
00026 {
00027
00028 IMPLEMENT_CLASS (wxOgreRenderWindow, wxControl)
00029
00030 BEGIN_EVENT_TABLE (wxOgreRenderWindow, wxControl)
00031 EVT_PAINT (wxOgreRenderWindow::onPaint)
00032 EVT_SIZE (wxOgreRenderWindow::onSize)
00033 EVT_MOUSE_EVENTS (wxOgreRenderWindow::onMouseEvents)
00034 EVT_MOVE(wxOgreRenderWindow::onMove)
00035 END_EVENT_TABLE ()
00036
00037
00038 unsigned int wxOgreRenderWindow::sm_NextRenderWindowId = 1;
00039
00040 wxOgreRenderWindow::wxOgreRenderWindow (Ogre::Root* ogre_root, wxWindow *parent, wxWindowID id,
00041 const wxPoint &pos, const wxSize &size, long style, const wxValidator &validator, bool create_render_window)
00042 : wxControl( parent, id, pos, size, style, validator )
00043 , render_window_( 0 )
00044 , ogre_root_( ogre_root )
00045 , ortho_scale_( 1.0f )
00046 , auto_render_(true)
00047 {
00048 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
00049
00050 if (create_render_window)
00051 {
00052 createRenderWindow();
00053 }
00054 }
00055
00056
00057 wxOgreRenderWindow::~wxOgreRenderWindow ()
00058 {
00059 if (render_window_)
00060 {
00061 render_window_->removeViewport( 0 );
00062 render_window_->destroy();
00063 ogre_root_->detachRenderTarget(render_window_);
00064 }
00065
00066 render_window_ = 0;
00067 }
00068
00069
00070 inline wxSize wxOgreRenderWindow::DoGetBestSize () const
00071 {
00072 return wxSize (320, 240);
00073 }
00074
00075 Ogre::RenderWindow* wxOgreRenderWindow::getRenderWindow () const
00076 {
00077 return render_window_;
00078 }
00079
00080
00081 Ogre::Viewport* wxOgreRenderWindow::getViewport () const
00082 {
00083 return viewport_;
00084 }
00085
00086 void wxOgreRenderWindow::setCamera( Ogre::Camera* camera )
00087 {
00088 viewport_->setCamera( camera );
00089
00090 setCameraAspectRatio();
00091
00092 Refresh();
00093 }
00094
00095 void wxOgreRenderWindow::setCameraAspectRatio()
00096 {
00097 Ogre::Camera* camera = viewport_->getCamera();
00098 if ( camera )
00099 {
00100 int width;
00101 int height;
00102 GetSize( &width, &height );
00103
00104 camera->setAspectRatio( Ogre::Real( width ) / Ogre::Real( height ) );
00105
00106 if ( camera->getProjectionType() == Ogre::PT_ORTHOGRAPHIC )
00107 {
00108 Ogre::Matrix4 proj;
00109 buildScaledOrthoMatrix( proj, -width / ortho_scale_ / 2, width / ortho_scale_ / 2, -height / ortho_scale_ / 2, height / ortho_scale_ / 2,
00110 camera->getNearClipDistance(), camera->getFarClipDistance() );
00111 camera->setCustomProjectionMatrix(true, proj);
00112 }
00113 }
00114 }
00115
00116 void wxOgreRenderWindow::setOrthoScale( float scale )
00117 {
00118 ortho_scale_ = scale;
00119
00120 setCameraAspectRatio();
00121 }
00122
00123 void wxOgreRenderWindow::setPreRenderCallback( boost::function<void ()> func )
00124 {
00125 pre_render_callback_ = func;
00126 }
00127
00128 void wxOgreRenderWindow::setPostRenderCallback( boost::function<void ()> func )
00129 {
00130 post_render_callback_ = func;
00131 }
00132
00133
00134 void wxOgreRenderWindow::onPaint (wxPaintEvent &evt)
00135 {
00136 evt.Skip();
00137
00138 if (auto_render_)
00139 {
00140 if ( pre_render_callback_ )
00141 {
00142 pre_render_callback_();
00143 }
00144
00145 if( ogre_root_->_fireFrameStarted() )
00146 {
00147 #if (OGRE_VERSION_MAJOR >= 1 && OGRE_VERSION_MINOR >= 6)
00148 ogre_root_->_fireFrameRenderingQueued();
00149 #endif
00150
00151 render_window_->update();
00152
00153 ogre_root_->_fireFrameEnded();
00154 }
00155
00156 if ( post_render_callback_ )
00157 {
00158 post_render_callback_();
00159 }
00160 }
00161 }
00162
00163
00164 void wxOgreRenderWindow::onSize (wxSizeEvent &evt)
00165 {
00166 int width;
00167 int height;
00168 wxSize size = evt.GetSize ();
00169 width = size.GetWidth ();
00170 height = size.GetHeight ();
00171
00172 if (render_window_)
00173 {
00174 #if !defined(__WXMAC__)
00175 render_window_->resize (width, height);
00176 #endif
00177
00178 render_window_->windowMovedOrResized ();
00179
00180 setCameraAspectRatio();
00181
00182 if (auto_render_)
00183 {
00184 Refresh();
00185 }
00186 }
00187
00188 evt.Skip();
00189 }
00190
00191 void wxOgreRenderWindow::onMove(wxMoveEvent& evt)
00192 {
00193 evt.Skip();
00194
00195 if (render_window_)
00196 {
00197
00198 }
00199 }
00200
00201
00202 void wxOgreRenderWindow::onMouseEvents (wxMouseEvent &evt)
00203 {
00204 evt.Skip();
00205 }
00206
00207 void wxOgreRenderWindow::createRenderWindow ()
00208 {
00209 Ogre::NameValuePairList params;
00210 #if defined(__WXMAC__)
00211 params["externalWindowHandle"] = getOgreHandle();
00212 #else
00213 params["parentWindowHandle"] = getOgreHandle();
00214 #endif
00215
00216
00217 #ifdef __WXOSX_COCOA__
00218 params["macAPI"] = "cocoa";
00219 params["macAPICocoaUseNSView"] = "true";
00220 #else
00221 params["macAPI"] = "carbon";
00222 #endif
00223
00224
00225 #ifdef __WXOSX_COCOA__
00226 params["macAPI"] = "cocoa";
00227 params["macAPICocoaUseNSView"] = "true";
00228 #else
00229 params["macAPI"] = "carbon";
00230 #endif
00231
00232
00233 int width;
00234 int height;
00235 GetSize (&width, &height);
00236
00237 #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
00238 {
00239
00240
00241
00242
00243
00244 char *rtt_default = "PBuffer";
00245
00246 char* rtt_preferred_mode = getenv("OGRE_RTT_MODE");
00247 if( rtt_preferred_mode )
00248 {
00249 if( strcmp( rtt_preferred_mode, "Copy" ) != 0 &&
00250 strcmp( rtt_preferred_mode, "PBuffer" ) != 0 &&
00251 strcmp( rtt_preferred_mode, "FBO" ) != 0 )
00252 {
00253 ROS_ERROR( "Environtment variable OGRE_RTT_MODE has invalid value: '%s'. Should be", rtt_preferred_mode );
00254 ROS_ERROR( "either FBO, PBuffer, Copy, or should not be set. Using default value %s.", rtt_default );
00255 rtt_preferred_mode = rtt_default;
00256 }
00257 }
00258 else
00259 {
00260 rtt_preferred_mode = rtt_default;
00261 }
00262 ogre_root_->getRenderSystem()->setConfigOption( "RTT Preferred Mode", rtt_preferred_mode );
00263 ROS_INFO( "RTT Preferred Mode is %s.", rtt_preferred_mode );
00264 }
00265 #endif
00266
00267
00268 render_window_ = ogre_root_->createRenderWindow (
00269 Ogre::String ("OgreRenderWindow") + Ogre::StringConverter::toString (sm_NextRenderWindowId++),
00270 width, height, false, ¶ms);
00271
00272 render_window_->setActive (true);
00273 render_window_->setVisible(true);
00274 render_window_->setAutoUpdated(true);
00275
00276 viewport_ = render_window_->addViewport( NULL );
00277 }
00278
00279 std::string wxOgreRenderWindow::getOgreHandle () const
00280 {
00281 std::string handle;
00282
00283 #ifdef __WXMSW__
00284
00285 handle = Ogre::StringConverter::toString((size_t)((HWND)GetHandle()));
00286 #elif defined(__WXGTK__)
00287
00288 std::stringstream str;
00289 GtkWidget* widget = m_wxwindow;
00290 gtk_widget_set_double_buffered (widget, FALSE);
00291 if (!GTK_WIDGET_REALIZED(widget))
00292 {
00293 gtk_widget_realize( widget );
00294 }
00295
00296
00297 GtkPizza* pizza = GTK_PIZZA(widget);
00298 GdkWindow* gdkWin = pizza->bin_window;
00299 Window wid = GDK_WINDOW_XWINDOW(gdkWin);
00300
00301 XSync(GDK_WINDOW_XDISPLAY(widget->window), False);
00302 XSync(GDK_WINDOW_XDISPLAY(pizza->bin_window), False);
00303
00304 str << wid;
00305 handle = str.str();
00306 #elif defined(__WXMAC__)
00307 handle = Ogre::StringConverter::toString((size_t)(GetHandle()));
00308 #else
00309
00310 #error("Not supported on this platform.")
00311 #endif
00312
00313 return handle;
00314 }
00315
00316 bool wxOgreRenderWindow::Reparent(wxWindowBase* new_parent)
00317 {
00318
00319
00320
00321
00322
00323
00324
00325
00326 #if defined(__WXGTK__)
00327 Window win;
00328 Display* disp;
00329
00330 if (render_window_)
00331 {
00332 render_window_->getCustomAttribute("WINDOW", &win);
00333 render_window_->getCustomAttribute("XDISPLAY", &disp);
00334
00335 wxWindow* top = wxTheApp->GetTopWindow();
00336 GtkPizza* pizza = GTK_PIZZA(top->m_wxwindow);
00337 Window parent = GDK_WINDOW_XWINDOW(pizza->bin_window);
00338
00339 XSync(disp, False);
00340 XReparentWindow(disp, win, parent, 0, 0);
00341 XSync(disp, False);
00342 }
00343 #endif
00344
00345 bool ret = wxControl::Reparent(new_parent);
00346
00347 #if defined(__WXGTK__)
00348 if (render_window_)
00349 {
00350 XSync(disp, False);
00351
00352 gtk_widget_set_double_buffered(m_wxwindow, FALSE);
00353 if (!GTK_WIDGET_REALIZED(m_wxwindow))
00354 {
00355 gtk_widget_realize(m_wxwindow);
00356 }
00357
00358 GtkPizza* pizza = GTK_PIZZA(m_wxwindow);
00359
00360 XSync(GDK_WINDOW_XDISPLAY(m_wxwindow->window), False);
00361 XSync(GDK_WINDOW_XDISPLAY(pizza->bin_window), False);
00362
00363 GdkWindow* gdkWin = pizza->bin_window;
00364 Window parent = GDK_WINDOW_XWINDOW(gdkWin);
00365 XReparentWindow(disp, win, parent, 0, 0);
00366
00367
00368
00369 XMapWindow(disp, win);
00370
00371 XSync(disp, False);
00372 }
00373 #endif
00374
00375 return ret;
00376 }
00377
00378 }