Skip to content

Commit

Permalink
render in stereo if supported
Browse files Browse the repository at this point in the history
This adds stereo rendering support to Rviz.

To see stereo Rviz must be built against a version of Ogre that was
built with the OGRE_STEREO_ENABLE config option enabled.  This option
is currently only supported in the branch of Ogre found here
  https://bitbucket.org/crefvik/ogre
or here
  https://bitbucket.org/acornacorn/ogre

To see stereo you will need:
- a stereo monitor
   (I am using an ASUS VG278H)
- a video card that supports quad-buffer stereo.
   (I am using an NVIDIA Quadro K4000)

To build rviz with stereo support:
remove debian-installed ogre:
	sudo apt-get remove libogre-1.7.4 libogre-dev
build the stereo-enabled ogre:
	cd $HOME
	mkdir my-ogre
	cd my-ogre
	hg clone https://bitbucket.org/crefvik/ogre
	mkdir build
	cd build
	cmake -DOGRE_FULL_RPATH=ON -DOGRE_BUILD_STEREO_SUPPORT=ON ../ogre
	sudo make install
then build rviz as usual using catkin_make
	cd $HOME
	mkdir -p my-workspace/src
	cd my-workspace/src
	git clone https://github.com/ros-visualization/rviz.git
	cd ..
	catkin_make
Run rviz
	roscore & rosrun rviz
If your HW supports stereo you should see a double image (stereo when
wearing the glasses).  Properties in the ViewController panel can be
used to set eye-separation, focal-distance, to swap the eyes, and to
disable stereo.

If stereo is supported on your hardware, rviz will automatically
render in stereo unless you either
- disable stereo by unchecking the "Enable Stereo Rendering" property in the view panel.
- use the --no-stereo commandline option (stereo properties will be hidden)

If stereo is not suppported on your hardware, rviz will not render in
stereo and the stereo-related properties will be hidden.
  • Loading branch information
Acorn Pooley committed Feb 12, 2014
1 parent 408aba0 commit 9cfaf78
Show file tree
Hide file tree
Showing 8 changed files with 288 additions and 18 deletions.
98 changes: 98 additions & 0 deletions src/rviz/ogre_helpers/qt_ogre_render_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <OgreRenderWindow.h>
#include <OgreStringConverter.h>
#include <OgreGpuProgramManager.h>
#include <OgreRenderTargetListener.h>

#include <ros/console.h>
#include <ros/assert.h>
Expand All @@ -56,6 +57,10 @@ QtOgreRenderWindow::QtOgreRenderWindow( QWidget* parent )
, camera_( 0 )
, overlays_enabled_( true ) // matches the default of Ogre::Viewport.
, background_color_( Ogre::ColourValue::Black ) // matches the default of Ogre::Viewport.
, stereo_enabled_( false )
, rendering_stereo_( false )
, right_camera_( 0 )
, right_viewport_( 0 )
{
render_window_->setVisible(true);
render_window_->setAutoUpdated(true);
Expand All @@ -64,10 +69,90 @@ QtOgreRenderWindow::QtOgreRenderWindow( QWidget* parent )
viewport_->setOverlaysEnabled( overlays_enabled_ );
viewport_->setBackgroundColour( background_color_ );

#if OGRE_STEREO_ENABLE
viewport_->setDrawBuffer(Ogre::CBT_BACK);
#endif
enableStereo(true);

setCameraAspectRatio();
}

QtOgreRenderWindow::~QtOgreRenderWindow()
{
enableStereo(false); // free stereo resources
}

//------------------------------------------------------------------------------
bool QtOgreRenderWindow::enableStereo (bool enable)
{
bool was_enabled = stereo_enabled_;
stereo_enabled_ = enable;
setupStereo();
return was_enabled;
}

void QtOgreRenderWindow::setupStereo()
{
bool render_stereo = stereo_enabled_ && RenderSystem::get()->isStereoSupported();

if (render_stereo == rendering_stereo_)
return;

rendering_stereo_ = render_stereo;

if (rendering_stereo_)
{
right_viewport_ = render_window_->addViewport( NULL, 1 );
#if OGRE_STEREO_ENABLE
right_viewport_->setDrawBuffer(Ogre::CBT_BACK_RIGHT);
viewport_->setDrawBuffer(Ogre::CBT_BACK_LEFT);
#endif

setOverlaysEnabled(overlays_enabled_);
setBackgroundColor(background_color_);
if (camera_)
setCamera(camera_);

// addListener causes preViewportUpdate() to be called when rendering.
render_window_->addListener(this);
}
else
{
render_window_->removeListener(this);
render_window_->removeViewport(1);
right_viewport_ = NULL;

#if OGRE_STEREO_ENABLE
viewport_->setDrawBuffer(Ogre::CBT_BACK);
#endif

if (right_camera_)
right_camera_->getSceneManager()->destroyCamera( right_camera_ );
right_camera_ = NULL;
}

}

// this is called just before rendering either viewport when stereo is enabled.
void QtOgreRenderWindow::preViewportUpdate(
const Ogre::RenderTargetViewportEvent& evt)
{
Ogre::Viewport* viewport = evt.source;

if (viewport != right_viewport_)
return;

if (camera_->getProjectionType() != Ogre::PT_PERSPECTIVE || !right_camera_)
{
viewport->setCamera( camera_ );
return;
}

right_camera_->synchroniseBaseSettingsWith(camera_);
right_camera_->setFrustumOffset(-camera_->getFrustumOffset());
right_viewport_->setCamera(right_camera_);
}

Ogre::Viewport* QtOgreRenderWindow::getViewport () const
{
return viewport_;
Expand All @@ -80,19 +165,32 @@ void QtOgreRenderWindow::setCamera( Ogre::Camera* camera )

setCameraAspectRatio();

if (camera_ && rendering_stereo_ && !right_camera_)
{
right_camera_ = camera_->getSceneManager()->createCamera(camera_->getName() + "-right");
}

update();
}

void QtOgreRenderWindow::setOverlaysEnabled( bool overlays_enabled )
{
overlays_enabled_ = overlays_enabled;
viewport_->setOverlaysEnabled( overlays_enabled );
if (right_viewport_)
{
right_viewport_->setOverlaysEnabled( overlays_enabled );
}
}

void QtOgreRenderWindow::setBackgroundColor( Ogre::ColourValue background_color )
{
background_color_ = background_color;
viewport_->setBackgroundColour( background_color );
if (right_viewport_)
{
right_viewport_->setBackgroundColour( background_color );
}
}

void QtOgreRenderWindow::setCameraAspectRatio()
Expand Down
31 changes: 30 additions & 1 deletion src/rviz/ogre_helpers/qt_ogre_render_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "render_widget.h"

#include <OgreColourValue.h>
#include <OgreRenderTargetListener.h>

namespace Ogre
{
Expand All @@ -51,13 +52,16 @@ namespace rviz
* the guts replaced by new RenderSystem and RenderWidget classes
* inspired by the initialization sequence of Gazebo's renderer.
*/
class QtOgreRenderWindow : public RenderWidget {
class QtOgreRenderWindow : public RenderWidget, public Ogre::RenderTargetListener {
public:
/** Constructor.
@param parent The parent wxWindow component.
*/
QtOgreRenderWindow( QWidget* parent = 0 );

/** Destructor. */
virtual ~QtOgreRenderWindow();

/**
* Set a callback which is called before each render
* @param func The callback functor
Expand Down Expand Up @@ -95,6 +99,15 @@ class QtOgreRenderWindow : public RenderWidget {
*/
void setOrthoScale( float scale );

/** \brief Enable or disable stereo rendering
* If stereo is not supported this is ignored.
* @return the old setting (whether stereo was enabled before)
*/
bool enableStereo(bool enable);

/** \brief Prepare to render in stereo if enabled and supported. */
void setupStereo();

void setAutoRender(bool auto_render) { auto_render_ = auto_render; }

////// Functions mimicked from Ogre::Viewport to satisfy timing of
Expand All @@ -106,11 +119,21 @@ class QtOgreRenderWindow : public RenderWidget {
virtual void paintEvent( QPaintEvent* e );
virtual void resizeEvent( QResizeEvent* event );

// When stereo is enabled, this is called before rendering each viewport.
virtual void preViewportUpdate(const Ogre::RenderTargetViewportEvent& evt);

/**
* Sets the aspect ratio on the camera
*/
void setCameraAspectRatio();

/**
* prepare a viewport's camera for stereo rendering.
* This should only be called from StereoRenderTargetListener
*/
void prepareStereoViewport(Ogre::Viewport*);


Ogre::Viewport* viewport_;

Ogre::Root* ogre_root_;
Expand All @@ -124,6 +147,12 @@ class QtOgreRenderWindow : public RenderWidget {
Ogre::Camera* camera_;
bool overlays_enabled_;
Ogre::ColourValue background_color_;

// stereo rendering
bool stereo_enabled_; // true if we were asked to render stereo
bool rendering_stereo_; // true if we are actually rendering stereo
Ogre::Camera* right_camera_;
Ogre::Viewport* right_viewport_;
};

} // namespace rviz
Expand Down
95 changes: 78 additions & 17 deletions src/rviz/ogre_helpers/render_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ namespace rviz

RenderSystem* RenderSystem::instance_ = 0;
int RenderSystem::force_gl_version_ = 0;
bool RenderSystem::force_no_stereo_ = false;

RenderSystem* RenderSystem::get()
{
Expand All @@ -80,8 +81,15 @@ void RenderSystem::forceGlVersion( int version )
ROS_INFO_STREAM( "Forcing OpenGl version " << (float)version / 100.0 << "." );
}

void RenderSystem::forceNoStereo()
{
force_no_stereo_ = true;
ROS_INFO("Forcing Stereo OFF");
}

RenderSystem::RenderSystem()
: ogre_overlay_system_(NULL)
, stereo_supported_(false)
{
OgreLogging::configureLogging();

Expand Down Expand Up @@ -352,16 +360,81 @@ Ogre::RenderWindow* RenderSystem::makeRenderWindow( intptr_t window_id, unsigned
std::ostringstream stream;
stream << "OgreWindow(" << windowCounter++ << ")";


// don't bother trying stereo if Ogre does not support it.
#if !OGRE_STEREO_ENABLE
force_no_stereo_ = true;
#endif

// attempt to create a stereo window
bool is_stereo = false;
if (!force_no_stereo_)
{
params["stereoMode"] = "Frame Sequential";
window = tryMakeRenderWindow( stream.str(), width, height, &params, 100);
params.erase("stereoMode");

if (window)
{
#if OGRE_STEREO_ENABLE
is_stereo = window->isStereoEnabled();
#endif
if (!is_stereo)
{
// Created a non-stereo window. Discard it and try again (below)
// without the stereo parameter.
ogre_root_->detachRenderTarget(window);
window->destroy();
window = NULL;
stream << "x";
is_stereo = false;
}
}
}

if ( window == NULL )
{
window = tryMakeRenderWindow( stream.str(), width, height, &params, 100);
}

if( window == NULL )
{
ROS_ERROR( "Unable to create the rendering window after 100 tries." );
assert(false);
}

if (window)
{
window->setActive(true);
//window->setVisible(true);
window->setAutoUpdated(false);
}

stereo_supported_ = is_stereo;
ROS_INFO_THROTTLE(5, "Stereo is %s", stereo_supported_ ? "SUPPORTED" : "NOT SUPPORTED");

return window;
}

Ogre::RenderWindow* RenderSystem::tryMakeRenderWindow(
const std::string& name,
unsigned int width,
unsigned int height,
const Ogre::NameValuePairList* params,
int max_attempts )
{
Ogre::RenderWindow *window = NULL;
int attempts = 0;

#ifdef Q_WS_X11
old_error_handler = XSetErrorHandler( &checkBadDrawable );
#endif

int attempts = 0;
while (window == NULL && (attempts++) < 100)
while (window == NULL && (attempts++) < max_attempts)
{
try
{
window = ogre_root_->createRenderWindow( stream.str(), width, height, false, &params );
window = ogre_root_->createRenderWindow( name, width, height, false, params );

// If the driver bug happened, tell Ogre we are done with that
// window and then try again.
Expand All @@ -384,25 +457,13 @@ Ogre::RenderWindow* RenderSystem::makeRenderWindow( intptr_t window_id, unsigned
XSetErrorHandler( old_error_handler );
#endif

if( window == NULL )
{
ROS_ERROR( "Unable to create the rendering window after 100 tries." );
assert(false);
}

if( attempts > 1 )
if( window && attempts > 1 )
{
ROS_INFO( "Created render window after %d attempts.", attempts );
}

if (window)
{
window->setActive(true);
//window->setVisible(true);
window->setAutoUpdated(false);
}

return window;
}


} // end namespace rviz
15 changes: 15 additions & 0 deletions src/rviz/ogre_helpers/render_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,24 @@ class RenderSystem
// @brief Force to use the provided OpenGL version on startup
static void forceGlVersion( int version );

// @brief Disable stereo rendering even if supported in HW.
static void forceNoStereo();

// @brief True if we can render stereo on this device.
bool isStereoSupported() { return stereo_supported_; }

private:
RenderSystem();
void setupDummyWindowId();
void loadOgrePlugins();

// helper for makeRenderWindow()
Ogre::RenderWindow* tryMakeRenderWindow(const std::string& name,
unsigned int width,
unsigned int height,
const Ogre::NameValuePairList* params,
int max_attempts);

// Find and configure the render system.
void setupRenderSystem();
void setupResources();
Expand All @@ -84,6 +97,8 @@ class RenderSystem
int gl_version_;
int glsl_version_;
static int force_gl_version_;
bool stereo_supported_;
static bool force_no_stereo_;
};

} // end namespace rviz
Expand Down
Loading

0 comments on commit 9cfaf78

Please sign in to comment.