//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield //Distributed under the terms of the GNU Library General Public License (LGPL) //as published by the Free Software Foundation. #ifndef OSG_CAMERA #define OSG_CAMERA 1 #include #include #include #include #include #include #include namespace osg { /** Camera class for encapsulating the view position and orientation and * projection (lens) used. Creates a projection and modelview matrices * which can be used to set OpenGL's PROJECTION and MODELVIEW matrices * respectively. */ class SG_EXPORT Camera: public osg::Referenced { public: Camera(DisplaySettings* ds=NULL); Camera(const Camera&); Camera& operator=(const Camera&); virtual ~Camera(); /** Range of projection types. * ORTHO2D is a special case of ORTHO where the near and far planes * are equal to -1 and 1 respectively. * PERSPECTIVE is a special case of FRUSTUM where the left & right * and bottom and top and symmetrical.*/ enum ProjectionType { ORTHO, ORTHO2D, FRUSTUM, PERSPECTIVE }; /** Get the projection type set by setOtho,setOtho2D,setFrustum, * and set perspective methods.*/ const ProjectionType getProjectionType() const { return _projectionType; } /** Set a orthographic projection. See glOrtho for further details.*/ void setOrtho(const double left, const double right, const double bottom, const double top, const double zNear, const double zFar); /** Set a 2D orthographic projection. See gluOrtho2D for further details.*/ void setOrtho2D(const double left, const double right, const double bottom, const double top); /** Set a perspective projection. See glFrustum for further details.*/ void setFrustum(const double left, const double right, const double bottom, const double top, const double zNear, const double zFar); /** Set a symmetrical perspective projection, See gluPerspective for further details. * Aspect ratio is defined as width/height.*/ void setPerspective(const double fovy,const double aspectRatio, const double zNear, const double zFar); /** Set a sysmmetical perspective projection using field of view.*/ void setFOV(const double fovx,const double fovy, const double zNear, const double zFar); /** Set the near and far clipping planes.*/ void setNearFar(const double zNear, const double zFar); /** Use in combination with adjustAspectRatio, to control * the change in frustum clipping planes to account for * changes in windows aspect ratio,*/ enum AdjustAspectRatioMode { ADJUST_VERTICAL, ADJUST_HORIZONTAL, ADJUST_NONE }; /** Set the way that the vertical or horizontal dimensions of the window * are adjusted on a resize. */ void setAdjustAspectRatioMode(const AdjustAspectRatioMode aam) { _adjustAspectRatioMode = aam; } /** Get the way that the vertical or horizontal dimensions of the window * are adjusted on a resize. */ const AdjustAspectRatioMode getAdjustAspectRatioMode() const { return _adjustAspectRatioMode; } /** Adjust the clipping planes to account for a new window aspect ratio. * Typically used after resizing a window. Aspect ratio is defined as * width/height.*/ void adjustAspectRatio(const double newAspectRatio) { adjustAspectRatio(newAspectRatio,_adjustAspectRatioMode); } /** Adjust the clipping planes to account for a new window aspect ratio. * Typicall used after resizeing a window. Aspect ratio is defined as * width/height.*/ void adjustAspectRatio(const double newAspectRatio, const AdjustAspectRatioMode aa); const double left() const; const double right() const; const double top() const; const double bottom() const; const double zNear() const; const double zFar() const; /** Calculate and return the equivalent fovx for the current project setting. * This value is only valid for when a symmetric perspective projection exists. * i.e. getProjectionType()==PERSPECTIVE.*/ const double calc_fovy() const; /** Calculate and return the equivalent fovy for the current project setting. * This value is only valid for when a symmetric perspective projection exists. * i.e. getProjectionType()==PERSPECTIVE.*/ const double calc_fovx() const; /** Calculate and return the projection aspect ratio. * Aspect ratio is defined as width/height.*/ const double calc_aspectRatio() const; const Matrix& getProjectionMatrix() const; enum LookAtType { USE_HOME_POSITON, USE_EYE_AND_QUATERNION, USE_EYE_CENTER_AND_UP }; const LookAtType getLookAtType() const { return _lookAtType; } /** * hardwired home view for now, looking straight down the * Z axis at the origin, with 'up' being the y axis. */ void home(); /** * Set the View, the up vector should be orthogonal to the look vector. * setView is now mapped to setLookAt(eye,center,up), and is only * kept for backwards compatibility. */ void setView(const Vec3& eyePoint, const Vec3& lookPoint, const Vec3& upVector); /** set the position and orientation of the camera, using the same convention as * gluLookAt. */ void setLookAt(const Vec3& eye, const Vec3& center, const Vec3& up); /** set the position and orientation of the camera, using the same convention as * gluLookAt. */ void setLookAt(const double eyeX, const double eyeY, const double eyeZ, const double centerX, const double centerY, const double centerZ, const double upX, const double upY, const double upZ); /** post multiple the existing eye point and orientation by matrix. * note, does not affect any ModelTransforms that are applied.*/ void transformLookAt(const Matrix& matrix); void ensureOrthogonalUpVector(); /** get the eye point. */ inline const Vec3& getEyePoint() const { return _eye; } /** get the center point. */ inline const Vec3& getCenterPoint() const { return _center; } /** get the up vector */ inline const Vec3& getUpVector() const { return _up; } /** calculate look vector.*/ const Vec3 getLookVector() const; /** 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 { EYE_TO_MODEL, MODEL_TO_EYE, NO_ATTACHED_TRANSFORM }; /** Attach a transform matrix which is applied after the camera look at. * The attached matrix can work in two ways, either as transform of the eye * into the model coordinates - EYE_TO_MODEL, or as a transform of the * model to the eye - MODEL_TO_EYE. The former is equivalent to attaching * a camera internal to the scene graph. The later is equivalent to adding * a osg::Transform at root of the scene to move the scene to the eye point. * Typical used in conjunction with the LookAt position set to home, * in which case it is simply treated as a model view matrix. * If the same behavior as IRIS Performer's setViewMat is desired * then set the LookAt to be (0,0,0),(0,1,0),(0,0,1) since Performer's * default direction is along the y axis, unlike OpenGL and the default OSG. * If modelTransfor is NULL then do not use any model transform - just use the * basic LookAt values. * note: Camera internals maintains the both EYE_TO_MODEL and MODEL_TO_EYE * internally and ensures that they are the inverse of one another. However, * if you modify the attached transform then you must call dirtyTransform, to * allow the OSG to update matrices accordingly.*/ void attachTransform(const TransformMode mode, Matrix* modelTransform=0); /** must be called after you modify an attachedTransform. */ void dirtyTransform(); Matrix* getTransform(const TransformMode mode); const Matrix* getTransform(const TransformMode mode) const; const Vec3 getEyePoint_Model() const; const Vec3 getCenterPoint_Model() const; const Vec3 getLookVector_Model() const; const Vec3 getUpVector_Model() const; const Vec3 getSideVector_Model() const; /** Get the ModelView matrix. * If a ModelTransform is supplied then the ModelView matrix is * created by multiplying the current LookAt by ModelTransform. * Otherwise it is simply created by using the current LookAt, * equivalent to using gluLookAt.*/ const Matrix& getModelViewMatrix() const; /** Switch on/off the use of the near clipping plane which creating the * getClippingVolume(), uses the camera _znear value for the position of the * near clipping plane. By default this value is off.*/ void setUseNearClippingPlane(const bool use); /** get whether the ClippingVolume uses a near clipping plane.*/ const bool getUseNearClippingPlane() const { return _useNearClippingPlane; } /** Switch on/off the use of the far clipping plane which creating the * getClippingVolume(), uses the camera _zfar value for the position * of the far clipping plane. By default this value is off.*/ void setUseFarClippingPlane(const bool use); /** Get whether the ClippingVolume uses a far clipping plane.*/ const bool getUseFarClippingPlane() const { return _useFarClippingPlane; } /** get the view frustum clipping in model coordinates */ const ClippingVolume& getClippingVolume() const; /** Map object coordinates into windows coordinates. * Equivalent to gluProject(...). */ const bool project(const Vec3& obj,const Viewport& viewport,Vec3& win) const; /** Map window coordinates into object coordinates. * Equivalent to gluUnProject(...). */ const bool unproject(const Vec3& win,const Viewport& viewport,Vec3& obj) const; enum FusionDistanceMode { PROPORTIONAL_TO_LOOK_DISTANCE, PROPORTIONAL_TO_SCREEN_DISTANCE }; /** Set the mode of the fusion distance function which in use to calculate the * fusion distance used in stereo rendering. Default value is * PROPORTIONAL_TO_LOOK_DISTANCE. Use in conjunction with setFusionDistanceRatio(float).*/ void setFusionDistanceMode(FusionDistanceMode mode) { _fusionDistanceMode = mode; _dirty = true; } /** Get the mode of the fusion distance function.*/ FusionDistanceMode getFusionDistanceMode() const { return _fusionDistanceMode; } /** Set the ratio of the fusion distance function which in use to calculate the * fusion distance used in stereo rendering. Default value is 1.0f * Use in conjunction with setFusionDistanceMode(..).*/ void setFusionDistanceRatio(float ratio) { _fusionDistanceRatio = ratio; _dirty = true; } /** Get the ratio of the fusion distance function.*/ float getFusionDistanceRatio() const { return _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); /** Set up the OpenGL projection and model view matrices.*/ virtual void apply(State& state); protected: void copy(const Camera&); // projection details. ProjectionType _projectionType; // how the window dimensions should be altered during a window resize. AdjustAspectRatioMode _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. double _left; double _right; double _bottom; double _top; double _zNear; double _zFar; // look at details. LookAtType _lookAtType; Vec3 _eye; Vec3 _center; Vec3 _up; TransformMode _attachedTransformMode; ref_ptr _eyeToModelTransform; ref_ptr _modelToEyeTransform; // flags to determine if near and far clipping planes are required. bool _useNearClippingPlane; bool _useFarClippingPlane; // cached matrix and clipping volume derived from above settings. mutable bool _dirty; mutable ref_ptr _projectionMatrix; mutable ref_ptr _modelViewMatrix; mutable ClippingVolume _clippingVolume; mutable ref_ptr _mp; mutable ref_ptr _inversemp; void calculateMatricesAndClippingVolume() const; // used for offsetting camera to ajust for left and right stereo views. bool _useEyeOffset; osg::Vec3 _eyeOffset; float _screenDistance; FusionDistanceMode _fusionDistanceMode; float _fusionDistanceRatio; }; } # endif