Beginings of support for quad bufferd, red/green, and slit screen stereo.

This commit is contained in:
Robert Osfield
2001-12-02 22:20:46 +00:00
parent bca8b68a18
commit 34a4c18a26
8 changed files with 248 additions and 34 deletions

View File

@@ -25,6 +25,8 @@ class SG_EXPORT Camera: public osg::Referenced
public:
Camera();
Camera(const Camera&);
Camera& operator=(const Camera&);
virtual ~Camera();
/** Range of projection types.
@@ -254,11 +256,15 @@ class SG_EXPORT Camera: public osg::Referenced
const bool unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) const;
/** Convinience method for adjusting the project and model view to account for
* and eye offset, as used in stereo work, assumes that the users will use
* a seperate camera for each eye, adjustEyePointForStereo(..) being used to
* specialize the camera for each eye view.*/
void adjustEyeOffsetForStereo(const osg::Vec3& offset,float screenDistance);
protected:
// Disallow copy construction & assignment (for now)
Camera(const Camera&);
Camera& operator=(const Camera&);
void copy(const Camera&);
// projection details.
ProjectionType _projectionType;
@@ -306,7 +312,10 @@ class SG_EXPORT Camera: public osg::Referenced
void calculateMatricesAndClippingVolume() const;
// values to offset
bool _useEyeOffset;
osg::Vec3 _eyeOffset;
float _screenDistance;
};

View File

@@ -6,6 +6,7 @@
#define OSGUTIL_RENDERSTAGE 1
#include <osg/Camera>
#include <osg/ColorMask>
#include <osgUtil/RenderBin>
#include <osgUtil/RenderStageLighting>
@@ -53,6 +54,11 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
const GLbitfield getClearMask() const { return _clearMask; }
void setColorMask(osg::ColorMask* cm) { _colorMask = cm; }
osg::ColorMask* getColorMask() { return _colorMask.get(); }
const osg::ColorMask* getColorMask() const { return _colorMask.get(); }
/** Set the clear color used in glClearColor(..).
* glClearColor is only called if mask & GL_COLOR_BUFFER_BIT is true*/
void setClearColor(const osg::Vec4& color) { _clearColor=color; }
@@ -131,6 +137,7 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
osg::ref_ptr<osg::Viewport> _viewport;
GLbitfield _clearMask;
osg::ref_ptr<osg::ColorMask> _colorMask;
osg::Vec4 _clearColor;
osg::Vec4 _clearAccum;
double _clearDepth;

View File

@@ -101,14 +101,32 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced
osg::Light* getLight() { return _light.get(); }
const osg::Light* getLight() const { return _light.get(); }
void setCamera(osg::Camera* camera) { _camera = camera; }
osg::Camera* getCamera() { return _camera.get(); }
const osg::Camera* getCamera() const { return _camera.get(); }
void setState(osg::State* state) { _state = state; }
osg::State* getState() { return _state.get(); }
const osg::State* getState() const { return _state.get(); }
enum StereoMode
{
MONO,
QUAD_BUFFER_STEREO,
RED_GREEN_STEREO,
HORIZONTAL_SPLIT_STEREO,
VERTICAL_SPLIT_STEREO
};
void setStereoMode(const StereoMode mode) { _stereoMode = mode; }
const StereoMode getStereoMode() const { return _stereoMode; }
void setLeftEyeOffset(const osg::Vec3& pos) { _leftEye = pos; }
void setRightEyeOffset(const osg::Vec3& pos) { _rightEye = pos; }
void setFocalLength(float length) { _focalLength = length; }
void setScreenDistance(float distance) { _screenDistance = distance; }
void setCamera(osg::Camera* camera) { _camera = camera; }
osg::Camera* getCamera() { return _camera.get(); }
const osg::Camera* getCamera() const { return _camera.get(); }
void setInitVisitor(osg::NodeVisitor* av) { _initVisitor = av; }
osg::NodeVisitor* getInitVisitor() { return _initVisitor.get(); }
@@ -212,6 +230,14 @@ class OSGUTIL_EXPORT SceneView : public osg::Referenced
osg::ref_ptr<osg::Light> _light;
osg::ref_ptr<osg::Camera> _camera;
osg::ref_ptr<osg::State> _state;
StereoMode _stereoMode;
osg::Vec3 _leftEye;
osg::Vec3 _rightEye;
float _focalLength;
float _screenDistance;
bool _initCalled;
osg::ref_ptr<osg::NodeVisitor> _initVisitor;

View File

@@ -14,7 +14,7 @@ Camera::Camera()
_adjustAspectRatioMode = ADJUST_HORIZONTAL;
// projection details.
setPerspective(60,1.0,1.0,1000.0);
setPerspective(30,1.0,1.0,1000.0);
// look at details.
_lookAtType =USE_HOME_POSITON;
@@ -28,8 +28,70 @@ Camera::Camera()
_useNearClippingPlane = false;
_useFarClippingPlane = false;
_useEyeOffset = false;
_eyeOffset.set(0.0f,0.0f,0.0f);
_screenDistance = 1.0f;
}
Camera::Camera(const Camera& camera)
{
copy(camera);
}
Camera& Camera::operator=(const Camera& camera)
{
if (&camera==this) return *this;
copy(camera);
return *this;
}
void Camera::copy(const Camera& camera)
{
_projectionType = camera._projectionType;
// how the window dimensions should be altered during a window resize.
_adjustAspectRatioMode = camera._adjustAspectRatioMode;
// note, in Frustum/Perspective mode these values are scaled
// by the zNear from when they were initialised to ensure that
// subsequent changes in zNear do not affect them.
_left = camera._left;
_right = camera._right;
_bottom = camera._bottom;
_top = camera._top;
_zNear = camera._zNear;
_zFar = camera._zFar;
// look at details.
_lookAtType = camera._lookAtType;
_eye = camera._eye;
_center = camera._center;
_up = camera._up;
_focalLength = camera._focalLength;
_attachedTransformMode = camera._attachedTransformMode;
_eyeToModelTransform = camera._eyeToModelTransform;
_modelToEyeTransform = camera._modelToEyeTransform;
// flags to determine if near and far clipping planes are required.
_useNearClippingPlane = camera._useNearClippingPlane;
_useFarClippingPlane = camera._useFarClippingPlane;
// cached matrix and clipping volume derived from above settings.
_dirty = camera._dirty;
_projectionMatrix = camera._projectionMatrix;
_modelViewMatrix = camera._modelViewMatrix;
_clippingVolume = camera._clippingVolume;
_mp = camera._mp;
_inversemp = camera._inversemp;
}
Camera::~Camera()
{
@@ -324,6 +386,10 @@ void Camera::transformLookAt(const Matrix& matrix)
_center = _center*matrix;
_up -= _eye;
_up.normalize();
_focalLength = (_center-_eye).length();
_dirty = true;
}
const Vec3 Camera::getLookVector() const
@@ -520,17 +586,31 @@ const ClippingVolume& Camera::getClippingVolume() const
void Camera::calculateMatricesAndClippingVolume() const
{
float left = _left;
float right = _right;
float top = _top;
float bottom = _bottom;
if (_useEyeOffset)
{
float dx = -_eyeOffset.x()*(1.0f/_screenDistance);
left += dx;
right += dx;
cout << "dx="<<dx<<" left="<<left<<" right="<<right<<endl;
}
// set up the projection matrix.
switch(_projectionType)
{
case(ORTHO):
case(ORTHO2D):
{
float A = 2.0/(_right-_left);
float B = 2.0/(_top-_bottom);
float A = 2.0/(right-left);
float B = 2.0/(top-bottom);
float C = -2.0 / (_zFar-_zNear);
float tx = -(_right+_left)/(_right-_left);
float ty = -(_top+_bottom)/(_top-_bottom);
float tx = -(right+left)/(right-left);
float ty = -(top+bottom)/(top-bottom);
float tz = -(_zFar+_zNear)/(_zFar-_zNear);
_projectionMatrix = new Matrix(
@@ -548,10 +628,10 @@ void Camera::calculateMatricesAndClippingVolume() const
// by the zNear from when they were initialised to ensure that
// subsequent changes in zNear do not affect them.
float A = (2.0)/(_right-_left);
float B = (2.0)/(_top-_bottom);
float C = (_right+_left) / (_right-_left);
float D = (_top+_bottom) / (_top-_bottom);
float A = (2.0)/(right-left);
float B = (2.0)/(top-bottom);
float C = (right+left) / (right-left);
float D = (top+bottom) / (top-bottom);
float E = -(_zFar+_zNear) / (_zFar-_zNear);
float F = -(2.0*_zFar*_zNear) / (_zFar-_zNear);
@@ -615,6 +695,18 @@ void Camera::calculateMatricesAndClippingVolume() const
break;
}
if (_useEyeOffset)
{
cout << " screenDistance ="<<_screenDistance<<" focalLength="<<_focalLength<<endl;
cout << " offset="<<_eyeOffset<<endl;
// cout << " trans ="<<-_eyeOffset*(_screenDistance/_focalLength)<<endl;
cout << " trans ="<<-_eyeOffset*(_screenDistance)<<endl;
// (*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::trans(-_eyeOffset*(_screenDistance/_focalLength)) ;
(*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::trans(-_eyeOffset*_focalLength/_screenDistance) ;
}
_clippingVolume.clear();
// set the clipping volume.
@@ -719,3 +811,11 @@ const bool Camera::unproject(const Vec3& win,const Viewport& viewport,Vec3& obj)
else
return false;
}
void Camera::adjustEyeOffsetForStereo(const osg::Vec3& offset,float screenDistance)
{
_useEyeOffset = true;
_eyeOffset = offset;
_screenDistance = screenDistance;
_dirty = true;
}

View File

@@ -174,6 +174,9 @@ bool Viewer::open()
GLUTEventAdapter::setWindowSize( wx, wy, ww, wh );
GLUTEventAdapter::setButtonMask(0);
bool needQuadBufferStereo = false;
// Set the absolute viewport for each SceneView based on the
// relative viewport coordinates given to us
for(itr=_viewportList.begin();
@@ -195,6 +198,9 @@ bool Viewer::open()
{
// osg::notify(osg::INFO) << "Handled reshape "<<endl;
}
if (sceneView->getStereoMode()==osgUtil::SceneView::QUAD_BUFFER_STEREO) needQuadBufferStereo = true;
}
//glutInit( &argc, argv ); // I moved this into main to avoid passing
@@ -238,6 +244,7 @@ bool Viewer::open()
if (vrv.requiresDepthBuffer()) displayMode |= GLUT_DEPTH;
if (vrv.requiresAlphaBuffer()) displayMode |= GLUT_ALPHA;
if (vrv.requiresStencilBuffer()) displayMode |= GLUT_STENCIL;
if (needQuadBufferStereo) displayMode |= GLUT_STEREO;
// and we'll add in multisample so that on systems like Onyx's can
// go ahead and use there loverly anti-aliasing. This is ignored
@@ -245,14 +252,15 @@ bool Viewer::open()
displayMode |= GLUT_MULTISAMPLE;
osg::notify(osg::INFO) <<"osgGLUT::Viewer::open() requesting displayMode = "<<displayMode<<endl;
if (displayMode & GLUT_DOUBLE) osg::notify(osg::INFO)<<" requesting GLUT_DOUBLE."<<endl;
if (displayMode & GLUT_SINGLE) osg::notify(osg::INFO)<<" requesting GLUT_SINGLE."<<endl;
if (displayMode & GLUT_RGB) osg::notify(osg::INFO)<<" requesting GLUT_RGB."<<endl;
if (displayMode & GLUT_DEPTH) osg::notify(osg::INFO)<<" requesting GLUT_DEPTH."<<endl;
if (displayMode & GLUT_ALPHA) osg::notify(osg::INFO)<<" requesting GLUT_ALPHA."<<endl;
if (displayMode & GLUT_STENCIL) osg::notify(osg::INFO)<<" requesting GLUT_STENCIL."<<endl;
if (displayMode & GLUT_MULTISAMPLE) osg::notify(osg::INFO)<<" requesting GLUT_MULTISAMPLE."<<endl;
osg::notify(osg::INFO) <<"osgGLUT::Viewer::open() requesting displayMode = "<<displayMode<<endl;
if (displayMode & GLUT_DOUBLE) osg::notify(osg::INFO)<<" requesting GLUT_DOUBLE."<<endl;
if (displayMode & GLUT_SINGLE) osg::notify(osg::INFO)<<" requesting GLUT_SINGLE."<<endl;
if (displayMode & GLUT_RGB) osg::notify(osg::INFO)<<" requesting GLUT_RGB."<<endl;
if (displayMode & GLUT_DEPTH) osg::notify(osg::INFO)<<" requesting GLUT_DEPTH."<<endl;
if (displayMode & GLUT_ALPHA) osg::notify(osg::INFO)<<" requesting GLUT_ALPHA."<<endl;
if (displayMode & GLUT_STENCIL) osg::notify(osg::INFO)<<" requesting GLUT_STENCIL."<<endl;
if (displayMode & GLUT_MULTISAMPLE) osg::notify(osg::INFO)<<" requesting GLUT_MULTISAMPLE."<<endl;
if (displayMode & GLUT_STEREO) osg::notify(osg::INFO)<<" requesting GLUT_STEREO."<<endl;
glutInitDisplayMode( displayMode);

View File

@@ -96,7 +96,7 @@ void Paragraph::createDrawables()
osg::Vec3 pos = _position;
typedef vector<std::string> TextList;
typedef std::vector<std::string> TextList;
TextList formatedText;
createFormatedText(_maxCharsPerLine,_text,formatedText);

View File

@@ -73,6 +73,10 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
// glEnable( GL_DEPTH_TEST );
// set which color planes to operate on.
if (_colorMask.valid()) _colorMask->apply(state);
else glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
if (_clearMask & GL_COLOR_BUFFER_BIT)
glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
@@ -85,8 +89,6 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous)
if (_clearMask & GL_ACCUM_BUFFER_BIT)
glClearAccum( _clearAccum[0], _clearAccum[1], _clearAccum[2], _clearAccum[3]);
// clear a color bit planes - osg::ColorMask could also be used here.
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
glClear( _clearMask );

View File

@@ -45,14 +45,23 @@ void SceneView::setDefaults()
_lightingMode=HEADLIGHT;
_light = new osg::Light;
_light->setAmbient(Vec4(0.05f,0.05f,0.05f,1.0f));
_light->setAmbient(Vec4(0.00f,0.0f,0.00f,1.0f));
_light->setDiffuse(Vec4(0.8f,0.8f,0.8f,1.0f));
_light->setSpecular(Vec4(0.1f,0.1f,0.1f,1.0f));
_light->setSpecular(Vec4(1.0f,1.0f,1.0f,1.0f));
_camera = new Camera;
_state = new State;
_camera = new Camera;
_stereoMode = MONO;
_leftEye.set(-0.03f,0.0f,0.0f);
_rightEye.set(0.03f,0.0f,0.0f);
_focalLength = 1.0f;
_screenDistance = 1.0f;
_rendergraph = new RenderGraph;
_renderStage = new RenderStage;
@@ -281,7 +290,60 @@ void SceneView::draw()
osg::Texture::flushDeletedTextureObjects(_state->getContextID());
RenderLeaf* previous = NULL;
_renderStage->draw(*_state,previous);
switch(getStereoMode())
{
case(MONO):
{
_renderStage->draw(*_state,previous);
}
break;
case(QUAD_BUFFER_STEREO):
{
osg::ref_ptr<osg::Camera> left_camera = new osg::Camera(*_camera);
osg::ref_ptr<osg::Camera> right_camera = new osg::Camera(*_camera);
float screenDistance = 3.5f;
float iod = 0.05;
left_camera->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f),screenDistance);
right_camera->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f),screenDistance);
cout << "draw"<<endl;
cout << " back left"<<endl;
glDrawBuffer(GL_BACK_LEFT);
_renderStage->setCamera(left_camera.get());
_renderStage->draw(*_state,previous);
cout << " back right"<<endl;
glDrawBuffer(GL_BACK_RIGHT);
_renderStage->setCamera(right_camera.get());
_renderStage->_stageDrawnThisFrame = false;
_renderStage->draw(*_state,previous);
}
break;
case(RED_GREEN_STEREO):
{
osg::ColorMask* red = new osg::ColorMask;
osg::ColorMask* green = new osg::ColorMask;
red->setMask(true,false,false,true);
_renderStage->setColorMask(red);
_renderStage->draw(*_state,previous);
green->setMask(false,true,false,true);
_renderStage->setColorMask(green);
_renderStage->_stageDrawnThisFrame = false;
_renderStage->draw(*_state,previous);
}
break;
default:
{
_renderStage->draw(*_state,previous);
}
break;
}
GLenum errorNo = glGetError();
if (errorNo!=GL_NO_ERROR)