Updates to the support for stereo in osg::Camera, osgUtil::SceneView and
the CameraManipulators.
This commit is contained in:
parent
9365f0e3b1
commit
734be18471
@ -126,14 +126,7 @@ 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;
|
||||
@ -338,6 +365,9 @@ class SG_EXPORT Camera: public osg::Referenced
|
||||
osg::Vec3 _eyeOffset;
|
||||
float _screenDistance;
|
||||
|
||||
FusionDistanceMode _fusionDistanceMode;
|
||||
float _fusionDistanceRatio;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
@ -334,9 +341,6 @@ void Camera::home()
|
||||
_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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user