/*********************************************************************** * Copyright 2011-2013 Computer Graphics Group RWTH Aachen University. * * All rights reserved. * * Distributed under the terms of the MIT License (see LICENSE.TXT). * **********************************************************************/ #pragma once #include #include #include #include "CameraBase.hh" #include "MoveableObject.hh" /* * What you definitly want to set: * - a position in 3D space (a vec3) * - a viewing direction, this can be defined by: * - roll/pitch/jaw rotations * - up/left/forward vectors * - the aspect ratio (width/height) * * What you maybe want to change: * - a lookAtDistance, this is internaly only used for the orthographic * projection, can be be used externaly e.g. for field of view effects * (if no focal distance is given, a default will be used, but often this * value is not used at all), also a lookAt point can be calculated with this * - Stereo settings: * - the eyedistance * - the StereoMode * - Horizontal/Vertical FoV * - near- and far-clipping plane * * A Camera can calculate: * - a ViewMatrix * - a ProjectionMatrix for Mono view * - ProjectionMatrices for Stereo view * - etc. * * * Note: To get from world to camera space, the translation is applied first, then the * rotation. getViewMatrix() provides one matrix for this. * Other camera models rotate first and translate later (e.g. bundler)! The rotation * is the same, the translation differs. * * TODO: support more stereo modes! */ namespace ACGL{ namespace Scene{ class GenericCamera : public CameraBase, public MoveableObject { public: /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Helping enums: // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// enum ProjectionMode { ISOMETRIC_PROJECTION = 0, PERSPECTIVE_PROJECTION }; enum StereoMode { MONO = 0, PARALLEL_SHIFT, OFF_AXIS, TOE_IN }; enum Eye { EYE_LEFT = 0, EYE_RIGHT }; /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Constructor / Destructor / save&store // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Default Constructor of a camera. */ GenericCamera(); /** * Constructs a camera from a string which holds all camera parameters. Note that this sets the viewport which * might not fix the currect screen! */ GenericCamera( const std::string &_state ); /** * Destructor of a camera. */ ~GenericCamera() {} /// Writes all internal state to one string std::string storeStateToString() const; /// Sets all internal state from a string void setStateFromString( const std::string &_state ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set / Get basic camera properties: // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Set the distance between the pupils (only needed for stereo rendering). * @param _interpupillaryDistance Inter pupil distance in meter(!) (distance between the centers of the eyes) */ void setInterpupillaryDistance( float _interpupillaryDistance ) { mInterpupillaryDistance = _interpupillaryDistance; } float getInterpupillaryDistance() const { return mInterpupillaryDistance; } /** * Set the projection mode of the camera. * @param _projection New projection mode of the camera. */ void setProjectionMode( ProjectionMode _projection ) { mProjectionMode = _projection; } ProjectionMode getProjectionMode() const { return mProjectionMode; } /** * Set the stereo mode of the camera. In mode MONO the set eye will get ignored (see below). * @param _stereoMode New stereo mode of the camera. */ void setStereoMode( StereoMode _stereoMode ) { mStereoMode = _stereoMode; } StereoMode getStereoMode() const { return mStereoMode; } /** * Sets the currently active eye. In stereo mode MONO this setting is ignored. * In the stereo modes (PARALLEL_SHIFT, OFF_AXIS, TOE_IN) it is used to * define the default eye that is assumed for the generic get*Matrix() functions. * (Matrices for specific eyes can still get queried directly without setting the * eye explicitly before each call). */ void setEye( Eye _eye ) { mCurrentEye = _eye; } Eye getEye() const { return mCurrentEye; } /** * Set the horizontal field of view of the camera in degree. * vertical FoV will get (implicitly) changed! * @param _fovh New horizontal field of view of the camera. */ void setHorizontalFieldOfView( float _fovh ); float getHorizontalFieldOfView() const { return mHorizontalFieldOfView; } /** * Set the vertical field of view of the camera in degree. * Horizontal FoV will get changed! * @param _fovv New vertical field of view of the camera. */ void setVerticalFieldOfView( float _fovv ); float getVerticalFieldOfView() const; /** * Set the aspect ratio of the camera. The horizontal FoV stays the same, the * vertical FoV gets updated. * @param aspectRatio New aspect ratio (width/height) */ void setAspectRatio( float _aspectRatio ) { mAspectRatio = _aspectRatio; } float getAspectRatio() const { return mAspectRatio; } /** * Set the near clipping plane of the camera. * The plane is defined only by a distance from the camera. * @param _plane New near clipping plane of the camera. */ void setNearClippingPlane( float _plane ); /// Gets the near clip distance float getNearClippingPlane() const { return mNearClippingPlane; } /** * Set the far clipping plane of the camera. * The plane is defined only by a distance from the camera. * @param _plane New far clipping plane of the camera. */ void setFarClippingPlane( float _plane ); /// Gets the far clip distance float getFarClippingPlane() const { return mFarClippingPlane; } /// Gets size of the viewport virtual glm::uvec2 getViewportSize() const { return mViewportSize; } /// Gets width of the viewport unsigned int getViewportWidth() const { return mViewportSize.x; } /// Gets height of the viewport unsigned int getViewportHeight() const { return mViewportSize.y; } /// Sets size of the viewport. NOTE: DOES NOT CHANGE THE ASPECT RATIO! Use resize() if you want to change that as well! void setViewportSize( glm::uvec2 _size ) { mViewportSize = _size; } /// Sets size of the viewport. NOTE: DOES NOT CHANGE THE ASPECT RATIO! Use resize() if you want to change that as well! void setViewportSize( unsigned int _width, unsigned int _height ) { setViewportSize(glm::uvec2(_width, _height)); } /// Sets new viewport size and calculates new aspect ratio void resize(int _newWidth, int _newHeight) { setViewportSize(_newWidth, _newHeight); setAspectRatio(_newWidth / (float)_newHeight); } /// The focal length is coupled to the sensor size in real cameras. As this camera does not model a /// sensor size in mm, the focal length is given in pixels and is in relation to the viewports resolution. /// This model is also used by bundler. /// Note that this gives only useful results if the viewports aspect ratio is the same as the /// projections aspect ratio! float getFocalLenghtInPixel() const; /// Sets the focal length in pixel relative to the viewport dimension. This will change the FoV. /// See getFocalLenghtInPixel() for more information. void setFocalLengthInPixel( float _focalLengthInPixel ); /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set / Get the matrices: // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// // // Generic rotation and translation matrices: In mono rendering these represent the camera. // In stereo rendering these represent the virtual camera position between the two cameras // actually used. // /// forward to MovableObject to implement the full CameraBase interface: glm::vec3 getPosition() const { return MoveableObject::getPosition(); } /////////////////////////////////////////////////////////////////////////////////////////// // // Generic view and projection matrices. These obey the set stereo/eye settings. // (When in doubt, use these!) // /// Gets the currently active view matrix (depends on stereo mode and current eye) virtual glm::mat4 getViewMatrix() const; /// Gets the currently active view matrix (depends on stereo mode and current eye) glm::mat4 getInverseViewMatrix() const; /// Gets the currently active projection matrix (depends on stereo mode and current eye) virtual glm::mat4 getProjectionMatrix() const; /////////////////////////////////////////////////////////////////////////////////////////// // // Explicit view and projection matrices. These DON'T obey the set stereo/eye settings. // /// Gets the view matrix for non-stereo rendering EVEN IF A STEREO MODE IS SET! glm::mat4 getMonoViewMatrix() const; glm::mat4 getMonoInverseViewMatrix() const; /** * Compute a camera view matrix for stereo rendering. * In stereo mode, the view matrix is the mono view matrix but also the shift * by half the eye distance to the left/right and a small rotation inwards in * case of toe in mode. * * These methods get the stereo matrix independent of the set mode for this camera. */ glm::mat4 getStereoViewMatrix( bool _leftEye, StereoMode _stereoMode = OFF_AXIS ) const; glm::mat4 getLeftStereoViewMatrix() const { return getStereoViewMatrix(true, mStereoMode); } glm::mat4 getRightStereoViewMatrix()const { return getStereoViewMatrix(false, mStereoMode); } glm::mat4 getLeftParallelShiftStereoViewMatrix() const { return getStereoViewMatrix(true, PARALLEL_SHIFT); } glm::mat4 getRightParallelShiftStereoViewMatrix()const { return getStereoViewMatrix(false, PARALLEL_SHIFT); } glm::mat4 getLeftOffAxisStereoViewMatrix() const { return getStereoViewMatrix(true, OFF_AXIS); } glm::mat4 getRightOffAxisStereoViewMatrix() const { return getStereoViewMatrix(false, OFF_AXIS); } glm::mat4 getLeftToeInStereoViewMatrix() const { return getStereoViewMatrix(true, TOE_IN); } glm::mat4 getRightToeInStereoViewMatrix() const { return getStereoViewMatrix(false, TOE_IN); } /// Gets the projection matrix for non-stereo rendering EVEN IF A STEREO MODE IS SET! glm::mat4 getMonoProjectionMatrix() const; /** * Compute a camera projection matrix for stereo rendering. * In stereo mode, the Cameras position is the point in the middle between the two eyes. * So we just need one additional info to calculate two matrices: */ glm::mat4 getStereoProjectionMatrix( bool _leftEye, StereoMode _stereoMode = OFF_AXIS ) const; glm::mat4 getLeftStereoProjectionMatrix() const { return getStereoProjectionMatrix(true, mStereoMode); } glm::mat4 getRightStereoProjectionMatrix() const { return getStereoProjectionMatrix(false, mStereoMode); } glm::mat4 getLeftParallelShiftStereoProjectionMatrix() const { return getStereoProjectionMatrix(true, PARALLEL_SHIFT); } glm::mat4 getRightParallelShiftStereoProjectionMatrix()const { return getStereoProjectionMatrix(false, PARALLEL_SHIFT); } glm::mat4 getLeftOffAxisStereoProjectionMatrix() const { return getStereoProjectionMatrix(true, OFF_AXIS); } glm::mat4 getRightOffAxisStereoProjectionMatrix() const { return getStereoProjectionMatrix(false, OFF_AXIS); } glm::mat4 getLeftToeInStereoProjectionMatrix() const { return getStereoProjectionMatrix(true, TOE_IN); } glm::mat4 getRightToeInStereoProjectionMatrix() const { return getStereoProjectionMatrix(false, TOE_IN); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set / Get properties that move the camera around (or rotate etc.) // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** * Look around with a mouse, works like a FPS camera: * No roll possible. * Up/down is limited to 90 degree. * This method assumes there is no roll in the current camera rotation, if * there is a roll component, it will get destroyed -> don't mix this * way to stear with other, more flexible methods! * @param _deltaX How much the mouse moved on the viewport (0..1, 1 = full viewport width) * @param _deltaY How much the mouse moved on the viewport (0..1, 1 = full viewport height) */ void FPSstyleLookAround( float _deltaX, float _deltaY ); private: /// /// States: update the storeStateToString() & setStateFromString() functions whenever adding a new state! /// /// Current camera projection mode ProjectionMode mProjectionMode; /// stereo view mode StereoMode mStereoMode; /// Current eye Eye mCurrentEye; /// Current camera horizontal field of view float mHorizontalFieldOfView; /// Current aspect ratio: width/height. float mAspectRatio; /// Distance of the eyes for stereo projection. In that case, the left eye is 0.5*InterpupillaryDistance /// shifted to the left of position and the right eye is 0.5*InterpupillaryDistance to the right shifted. /// We assume that 1 unit equals 1 meter. The mean eye distance is 6.5 cm == 0.065 units float mInterpupillaryDistance; /// Current camera near clipping plane float mNearClippingPlane; /// Current camera far clipping plane float mFarClippingPlane; /// viewport in pixel: glm::uvec2 mViewportSize; }; ACGL_SMARTPOINTER_TYPEDEFS(GenericCamera) } // Scene } // ACGL