Beginings of support for quad bufferd, red/green, and slit screen stereo.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user