Updates to the support for stereo in osg::Camera, osgUtil::SceneView and

the CameraManipulators.
This commit is contained in:
Robert Osfield 2001-12-21 13:07:35 +00:00
parent 9365f0e3b1
commit 734be18471
6 changed files with 83 additions and 32 deletions

View File

@ -125,15 +125,8 @@ class SG_EXPORT Camera: public osg::Referenced
const Matrix& getProjectionMatrix() const;
/** set the fusion distance, the distance in model coords, when viewing stereo, that the
* left and right eye images converge. This value is dual of the screen distance,
* which is distance between viewers eyes and display device, while the fusion distance is
* this equivilant distance but in the virtual world (model coords.)*/
inline const double setFusionDistance() const { return _fusionDistance; }
/** get fusion distance.*/
inline const double getFusionDistance() const { return _fusionDistance; }
enum LookAtType
@ -195,7 +188,8 @@ class SG_EXPORT Camera: public osg::Referenced
/** calculate side vector.*/
const Vec3 getSideVector() const;
/** calculate the look distance which is the distance between the eye and the center.*/
inline float getLookDistance() const { return (_center-_eye).length(); }
enum TransformMode
{
@ -274,11 +268,46 @@ class SG_EXPORT Camera: public osg::Referenced
const bool unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) const;
enum FusionDistanceMode
{
PROPORTIONAL_TO_LOOK_DISTANCE,
PROPORTIONAL_TO_SCREEN_DISTANCE
};
/** Set the fusion distance function which in use to calculate the
* fusion distance used in stereo rendering. Default value is
* PROPORTIONAL_TO_LOOK_DISTANCE, 1.0f.*/
void setFusionDistanceFunction(FusionDistanceMode mode, float ratio=1.0f)
{
_fusionDistanceMode = mode;
_fusionDistanceRatio = ratio;
_dirty = true;
}
/** Get the fusion distance function.*/
void getFusionDistanceFunction(FusionDistanceMode& mode, float& ratio)
{
mode = _fusionDistanceMode;
ratio = _fusionDistanceRatio;
}
/** Calculate and return the fusion distance, using the FusionDistanceFunction.*/
const float getFusionDistance() const;
/** Set the physical distance between the viewers eyes and the display system.
* Note, only used when rendering in stereo.*/
void setScreenDistance(float screenDistance) { _screenDistance = screenDistance; _dirty = true; }
/** Get the physical distance between the viewers eyes and the display system.*/
const float getScreenDistance() const { return _screenDistance; }
/** 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);
void adjustEyeOffsetForStereo(const osg::Vec3& offset);
/** Set up the OpenGL projection and model view matrices.*/
virtual void apply(State& state);
@ -312,8 +341,6 @@ class SG_EXPORT Camera: public osg::Referenced
Vec3 _center;
Vec3 _up;
double _fusionDistance;
TransformMode _attachedTransformMode;
ref_ptr<Matrix> _eyeToModelTransform;
ref_ptr<Matrix> _modelToEyeTransform;
@ -334,9 +361,12 @@ class SG_EXPORT Camera: public osg::Referenced
void calculateMatricesAndClippingVolume() const;
// used for offsetting camera to ajust for left and right stereo views.
bool _useEyeOffset;
osg::Vec3 _eyeOffset;
float _screenDistance;
bool _useEyeOffset;
osg::Vec3 _eyeOffset;
float _screenDistance;
FusionDistanceMode _fusionDistanceMode;
float _fusionDistanceRatio;
};

View File

@ -24,14 +24,15 @@ Camera::Camera()
_center.set(0.0f,0.0f,-1.0f);
_up.set(0.0f,1.0f,0.0f);
_fusionDistance = 1.0f;
_useNearClippingPlane = false;
_useFarClippingPlane = false;
_useEyeOffset = false;
_eyeOffset.set(0.0f,0.0f,0.0f);
_screenDistance = 1.0f;
_fusionDistanceMode = PROPORTIONAL_TO_LOOK_DISTANCE;
_fusionDistanceRatio = 1.0f;
}
Camera::Camera(const Camera& camera):Referenced()
@ -74,8 +75,6 @@ void Camera::copy(const Camera& camera)
_center = camera._center;
_up = camera._up;
_fusionDistance = camera._fusionDistance;
_attachedTransformMode = camera._attachedTransformMode;
_eyeToModelTransform = camera._eyeToModelTransform;
_modelToEyeTransform = camera._modelToEyeTransform;
@ -92,6 +91,14 @@ void Camera::copy(const Camera& camera)
_mp = camera._mp;
_inversemp = camera._inversemp;
_useEyeOffset = camera._useEyeOffset;
_eyeOffset = camera._eyeOffset;
_screenDistance = camera._screenDistance;
_fusionDistanceMode = camera._fusionDistanceMode;
_fusionDistanceRatio = camera._fusionDistanceRatio;
}
Camera::~Camera()
@ -333,10 +340,7 @@ void Camera::home()
_eye.set(0.0f,0.0f,0.0f);
_center.set(0.0f,0.0f,-1.0f);
_up.set(0.0f,1.0f,0.0f);
// need to set to appropriate values..
_fusionDistance = 1.0f;
_dirty = true;
}
@ -582,6 +586,16 @@ const ClippingVolume& Camera::getClippingVolume() const
return _clippingVolume;
}
const float Camera::getFusionDistance() const
{
switch(_fusionDistanceMode)
{
case(PROPORTIONAL_TO_SCREEN_DISTANCE): return _screenDistance*_fusionDistanceRatio;
case(PROPORTIONAL_TO_LOOK_DISTANCE):
default: return getLookDistance()*_fusionDistanceRatio;
}
}
void Camera::calculateMatricesAndClippingVolume() const
{
@ -695,7 +709,7 @@ void Camera::calculateMatricesAndClippingVolume() const
if (_useEyeOffset)
{
(*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::translate(-_eyeOffset*_fusionDistance/_screenDistance);
(*_modelViewMatrix) = (*_modelViewMatrix) * Matrix::translate(-_eyeOffset*(getFusionDistance()/_screenDistance));
}
@ -804,11 +818,10 @@ const bool Camera::unproject(const Vec3& win,const Viewport& viewport,Vec3& obj)
return false;
}
void Camera::adjustEyeOffsetForStereo(const osg::Vec3& offset,float screenDistance)
void Camera::adjustEyeOffsetForStereo(const osg::Vec3& offset)
{
_useEyeOffset = true;
_eyeOffset = offset;
_screenDistance = screenDistance;
_dirty = true;
}

View File

@ -353,6 +353,8 @@ bool DriveManipulator::calcMovement()
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
_camera->setFusionDistanceFunction(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE,1.0f);
float dt = _ga_t0->time()-_ga_t1->time();
if (dt<0.0f)

View File

@ -161,6 +161,8 @@ bool FlightManipulator::calcMovement()
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
_camera->setFusionDistanceFunction(osg::Camera::PROPORTIONAL_TO_SCREEN_DISTANCE,1.0f);
float dt = _ga_t0->time()-_ga_t1->time();
if (dt<0.0f)

View File

@ -293,9 +293,12 @@ void SceneView::draw()
RenderLeaf* previous = NULL;
if (_visualsSettings.valid() && _visualsSettings->getStereo())
{
_camera->setScreenDistance(_visualsSettings->getScreenDistance());
switch(_visualsSettings->getStereoMode())
{
case(osg::VisualsSettings::QUAD_BUFFER):
@ -304,10 +307,9 @@ void SceneView::draw()
osg::ref_ptr<osg::Camera> right_camera = new osg::Camera(*_camera);
float iod = _visualsSettings->getEyeSeperation();
float screenDistance = _visualsSettings->getEyeSeperation();
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);
left_camera->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f));
right_camera->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f));
glDrawBuffer(GL_BACK_LEFT);
_renderStage->setCamera(left_camera.get());
@ -326,10 +328,9 @@ void SceneView::draw()
osg::ref_ptr<osg::Camera> right_camera = new osg::Camera(*_camera);
float iod = _visualsSettings->getEyeSeperation();
float screenDistance = _visualsSettings->getScreenDistance();
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);
left_camera->adjustEyeOffsetForStereo(osg::Vec3(-iod*0.5,0.0f,0.0f));
right_camera->adjustEyeOffsetForStereo(osg::Vec3(iod*0.5,0.0f,0.0f));
osg::ColorMask* red = new osg::ColorMask;
osg::ColorMask* green = new osg::ColorMask;

View File

@ -175,12 +175,15 @@ void TrackballManipulator::addMouseEvent(const GUIEventAdapter& ea)
bool TrackballManipulator::calcMovement()
{
_camera->setFusionDistanceFunction(osg::Camera::PROPORTIONAL_TO_LOOK_DISTANCE,1.0f);
// return if less then two events have been added.
if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false;
float dx = _ga_t0->getX()-_ga_t1->getX();
float dy = _ga_t0->getY()-_ga_t1->getY();
// return if there is no movement.
if (dx==0 && dy==0) return false;