I'm currently developping a research project using Irrlicht engine for 3D display. I follow the Irrlicht forum for many days and found lot of revealing informations and helped me to develop lot of things. However, right now, i really do not manage to make stereo vision work.
In order to build a working example of Red/Cyan Anaglyph Stereovision (see source code below), I've been inspired by the following topics of the forum:
2009: http://irrlicht.sourceforge.net/forum/v ... p?p=185215
2009: http://irrlicht.sourceforge.net/forum/v ... =9&t=33463
2008: http://irrlicht.sourceforge.net/forum/v ... hp?t=28893
It seams these examples are working according to their authors. When creating device with EDT_SOFTWARE driver, examples don't work at all, but with EDT_OPENGL it begins to work. However it is like buffer are not correctly cleaned or if overriding material is not working well.
I'm running a Debian 8 Jessie Linux distribution, with Irrlicht 1.8, and compiling with g++
The NVIDIA proprietary display driver (nvidia-driver) is correctly installed.
The graphic card is a NVidia Quadro NVS 3100M (GT218M).
When loading the Quake 3 map example, it is working (with both OpenGL native primitives or Irrlicht primitives):

But, when having an animated mesh, it is dirty:
using Irrlicht primitives

or using OpenGL primitives

And also when having a moving mesh, it is dirty:

Here is my source code:
Code: Select all
/* File: stereo.cpp
Red/Cyan anaglyph stereovision using Irrlicht engine under Linux width video::EDT_OPENGL driver.
Directly inspired by:
http://irrlicht.sourceforge.net/forum/viewtopic.php?p=185215
And for Irrlich primitives by
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=33463
COMPILATION:
$ g++ -o irrsteroexample main.cpp stereo.cpp -I/usr/include/irrlicht/ -I/usr/include/GL/ -lIrrlicht -lGL
DOWNLOAD MEDIA NEEDED FOR RUNTIME:
$ mkdir ./media/
$ cd ./media/
$ wget https://github.com/zaki/irrlicht/blob/master/media/map-20kdm2.pk3
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.bmp
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.md2
USAGE:
$ ./irrsteroexample quake irr
$ ./irrsteroexample sydney irr
$ ./irrsteroexample quake gl
$ ./irrsteroexample sydney gl
*/
#include <irrlicht.h>
#include <iostream>
#include <gl.h>
#include "stereo.hpp"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
/********************
* Functions to prepare left and right eyes
* and then restore when finished
* with OPENGL primitives.
****/
void prepareLeftEye_OPENGL (unsigned long ulLEyeKey) {
glClear( GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColorMask( 0 != ( ulLEyeKey & 0x00ff0000 ),
0 != ( ulLEyeKey & 0x0000ff00 ),
0 != ( ulLEyeKey & 0x000000ff ),
0 != ( ulLEyeKey & 0xff000000 ) );
}
void prepareRightEye_OPENGL (unsigned long ulREyeKey) {
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glColorMask( 0 != ( ulREyeKey & 0x00ff0000 ),
0 != ( ulREyeKey & 0x0000ff00 ),
0 != ( ulREyeKey & 0x000000ff ),
0 != ( ulREyeKey & 0xff000000 ) );
}
void restore_OPENGL () {
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
}
/********************
* Functions to prepare left and right eyes
* and then restore when finished
* with IRRLICHT primitives.
****/
void prepareRightEye_IRRLICHT (irr::video::IVideoDriver *pDriver) {
pDriver->getOverrideMaterial().Material.ColorMask=ECP_GREEN+ECP_BLUE; // ECP_GREEN+ECP_BLUE
pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK;
pDriver->getOverrideMaterial().EnablePasses=
ESNRP_SKY_BOX
+ESNRP_SOLID
+ESNRP_TRANSPARENT
+ESNRP_TRANSPARENT_EFFECT
+ESNRP_SHADOW;
}
void prepareLeftEye_IRRLICHT (irr::video::IVideoDriver *pDriver) {
pDriver->getOverrideMaterial().Material.ColorMask=ECP_RED;
pDriver->getOverrideMaterial().EnableFlags=EMF_COLOR_MASK;
pDriver->getOverrideMaterial().EnablePasses=
ESNRP_SKY_BOX
+ESNRP_SOLID
+ESNRP_TRANSPARENT
+ESNRP_TRANSPARENT_EFFECT
+ESNRP_SHADOW;
}
void restore_IRRLICHT (irr::video::IVideoDriver *pDriver) {
pDriver->getOverrideMaterial().Material.ColorMask=ECP_ALL;
pDriver->getOverrideMaterial().EnableFlags=0;
pDriver->getOverrideMaterial().EnablePasses=0;
}
bool DrawAnaglyph( enum EPrimitives primitives,
irr::video::IVideoDriver *pDriver,
irr::scene::ISceneManager *pSm,
irr::scene::ICameraSceneNode *pCamera,
irr::video::SColor colBackground,
float fWidth, float fFocus, int nDriverType,
unsigned long ulREyeKey, unsigned long ulLEyeKey )
{
// Right eye
irr::core::vector3df reye = pCamera->getPosition();
// Left eye
irr::core::vector3df v( fWidth, 0, 0 );
irr::core::matrix4 m;
m.setRotationDegrees( pCamera->getRotation() + irr::core::vector3df( 90.f, 0, 0 ) );
m.transformVect( v );
irr::core::vector3df leye = reye + v;
if (primitives == PRIMITIVES_OPENGL) {
// Setup right eye
prepareRightEye_OPENGL (ulREyeKey) ;
}
//pDriver->beginScene( true, true, colBackground );
pDriver->beginScene( true, true, SColor(0,200,200,255) );
if (primitives == PRIMITIVES_IRRLICHT) {
// Setup right eye
prepareRightEye_IRRLICHT (pDriver) ;
}
// Tried here (but with no success) some code from: http://irrlicht.sourceforge.net/forum/viewtopic.php?t=28893
//pDriver->setRenderTarget (video::ERT_STEREO_BOTH_BUFFERS, true, true, video::SColor(0, 0, 0, 1)) ;
//pDriver->setRenderTarget (video::ERT_STEREO_RIGHT_BUFFER, true, true, video::SColor(0, 0, 0, 1)) ;
// Eye target
irr::core::vector3df oldt = pCamera->getTarget();
irr::core::vector3df eyet = ( oldt - reye ).normalize() * fFocus;
pCamera->setTarget( eyet );
pDriver->clearZBuffer();
pSm->drawAll(); // right eye
if (primitives == PRIMITIVES_OPENGL) {
// Setup left Eye
prepareLeftEye_OPENGL (ulLEyeKey) ;
}
pDriver->clearZBuffer();
if (primitives == PRIMITIVES_IRRLICHT) {
// Setup left Eye
prepareLeftEye_IRRLICHT (pDriver) ;
}
pCamera->setPosition( leye );
pCamera->OnRegisterSceneNode();
// Tried here (but with no success) some code from: http://irrlicht.sourceforge.net/forum/viewtopic.php?t=28893
//pDriver->setRenderTarget (video::ERT_STEREO_LEFT_BUFFER, true, true, video::SColor(0, 0, 0, 1)) ;
pSm->drawAll(); // left eye
pDriver->endScene();
if (primitives == PRIMITIVES_OPENGL) {
restore_OPENGL () ;
}
else if (primitives == PRIMITIVES_IRRLICHT) {
restore_IRRLICHT (pDriver) ;
}
// Restore original position
pCamera->setPosition( reye );
pCamera->setTarget( oldt );
return true;
}
Code: Select all
// File stereo.hpp
#ifndef STEREO_HPP
#define STEREO_HPP
enum EPrimitives { PRIMITIVES_IRRLICHT , PRIMITIVES_OPENGL } ;
bool DrawAnaglyph( enum EPrimitives primitives,
irr::video::IVideoDriver *pDriver,
irr::scene::ISceneManager *pSm,
irr::scene::ICameraSceneNode *pCamera,
irr::video::SColor colBackground,
float fWidth, float fFocus, int nDriverType,
unsigned long ulREyeKey, unsigned long ulLEyeKey ) ;
#endif /* STEREO_HPP */
Code: Select all
/* File: main.cpp
Red/Cyan anaglyph stereovision using Irrlicht engine under Linux width video::EDT_OPENGL driver.
Directly inspired by:
http://irrlicht.sourceforge.net/forum/viewtopic.php?p=185215
And for Irrlich primitives by
http://irrlicht.sourceforge.net/forum/viewtopic.php?f=9&t=33463
COMPILATION:
$ g++ -o irrsteroexample main.cpp stereo.cpp -I/usr/include/irrlicht/ -I/usr/include/GL/ -lIrrlicht -lGL
DOWNLOAD MEDIA NEEDED FOR RUNTIME:
$ mkdir ./media/
$ cd ./media/
$ wget https://github.com/zaki/irrlicht/blob/master/media/map-20kdm2.pk3
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.bmp
$ wget https://raw.githubusercontent.com/freeminer/irrlicht/master/media/sydney.md2
USAGE:
$ ./irrsteroexample quake irr
$ ./irrsteroexample sydney irr
$ ./irrsteroexample quake gl
$ ./irrsteroexample sydney gl
*/
/** Example 002 Quake3Map
This Tutorial shows how to load a Quake 3 map into the engine, create a
SceneNode for optimizing the speed of rendering, and how to create a user
controlled camera.
Please note that you should know the basics of the engine before starting this
tutorial. Just take a short look at the first tutorial, if you haven't done
this yet: http://irrlicht.sourceforge.net/tut001.html
Lets start like the HelloWorld example: We include the irrlicht header files
and an additional file to be able to ask the user for a driver type using the
console.
*/
#include <irrlicht.h>
#include <iostream>
#include "stereo.hpp"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
/*
Again, to be able to use the Irrlicht.DLL file, we need to link with the
Irrlicht.lib. We could set this option in the project settings, but to make it
easy, we use a pragma comment lib:
*/
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
enum EModel { MODEL_QUAKE3MAP , MODEL_SYDNEY } ;
void usage (const char *program) {
std::cerr << "Usage: " << program << " <model> <primitives>" << std::endl ;
std::cerr << " with model: quake|sydney" << std::endl ;
std::cerr << " and primitives: irr|gl" << std::endl ;
exit (1) ;
}
/*
Ok, lets start. Again, we use the main() method as start, not the WinMain().
*/
int main(int argc, char *argv[])
{
enum EModel modelChoice ;
enum EPrimitives primitivesChoice ;
/* Command line treatment */
// Count
if (argc != 3) {
usage(argv[0]) ;
}
// First arg
if (!strcmp (argv[1], "quake")) {
modelChoice = MODEL_QUAKE3MAP ;
}
else if (!strcmp (argv[1], "sydney")) {
modelChoice = MODEL_SYDNEY ;
}
else {
usage (argv[0]) ;
}
// Second arg
if (!strcmp (argv[2], "irr")) {
primitivesChoice = PRIMITIVES_IRRLICHT ;
}
else if (!strcmp (argv[2], "gl")) {
primitivesChoice = PRIMITIVES_OPENGL ;
}
else {
usage (argv[0]) ;
}
// create device and exit if creation failed
IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(640, 480));
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
device->getFileSystem()->addZipFileArchive("media/map-20kdm2.pk3");
scene::ICameraSceneNode* Cam = smgr->addCameraSceneNodeFPS();
scene::IAnimatedMesh* mesh = 0;
scene::IAnimatedMeshSceneNode* node = 0;
if (modelChoice == MODEL_QUAKE3MAP) {
mesh = smgr->getMesh("20kdm2.bsp");
if (mesh) {
//node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
node = smgr->addAnimatedMeshSceneNode(mesh);
}
/*
Because the level was not modelled around the origin (0,0,0), we
translate the whole level a little bit.
*/
if (node) {
node->setPosition(core::vector3df(-1300,-144,-1249));
}
}
else { /* modelChoice == MODEL_SYDNEY */
mesh = smgr->getMesh("media/sydney.md2");
if (mesh)
node = smgr->addAnimatedMeshSceneNode( mesh );
if (node) {
node->setMaterialFlag(EMF_LIGHTING, false);
node->setMD2Animation(scene::EMAT_STAND);
node->setMaterialTexture( 0, driver->getTexture("media/sydney.bmp") );
}
Cam->setPosition(vector3df(0,30,-40)) ;
}
/*
The mouse cursor needs not be visible, so we hide it via the
irr::IrrlichtDevice::ICursorControl.
*/
device->getCursorControl()->setVisible(false);
while(device->run())
{
if (device->isWindowActive())
{
DrawAnaglyph(
primitivesChoice,
driver, smgr, Cam,
video::SColor(0,200,200,255), // Background color (255,200,200,200)
2, // fWidth
1000, // fFocus
video::EDT_OPENGL,
0x000000ff, // ulREyeKey
0x00ffff00 // ulLEyeKey
);
//driver->beginScene(true, true, video::SColor(255,200,200,200));
//smgr->drawAll();
//driver->endScene();
}
else
device->yield();
}
/*
In the end, delete the Irrlicht device.
*/
device->drop();
return 0;
}
/*
That's it. Compile and play around with the program.
**/
Thanks,
Guillaume