include/cinder/Camera.h
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, The Barbarian Group
00003  All rights reserved.
00004  
00005  Portions of this code (C) Paul Houx
00006  All rights reserved.
00007 
00008  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00009  the following conditions are met:
00010 
00011     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00012     the following disclaimer.
00013     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00014     the following disclaimer in the documentation and/or other materials provided with the distribution.
00015 
00016  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00017  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00018  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00019  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00020  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00021  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00022  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00023  POSSIBILITY OF SUCH DAMAGE.
00024 */
00025 
00026 #pragma once
00027 
00028 #include "cinder/Vector.h"
00029 #include "cinder/Matrix.h"
00030 #include "cinder/Quaternion.h"
00031 #include "cinder/Ray.h"
00032 
00033 namespace cinder {
00034 
00035 // By default the camera is looking down -Z
00036 class Camera {
00037   public:
00038     Camera() : mModelViewCached(false), mProjectionCached(false), mInverseModelViewCached( false ), mWorldUp( Vec3f::yAxis() ) {}
00039     virtual ~Camera() {}
00040 
00041     Vec3f       getEyePoint() const { return mEyePoint; }
00042     void        setEyePoint( const Vec3f &aEyePoint );
00043     
00044     float       getCenterOfInterest() const { return mCenterOfInterest; }
00045     void        setCenterOfInterest( float aCenterOfInterest ) { mCenterOfInterest = aCenterOfInterest; }
00046     
00047     Vec3f       getCenterOfInterestPoint() const { return mEyePoint + mViewDirection * mCenterOfInterest; }
00048     void        setCenterOfInterestPoint( const Vec3f &centerOfInterestPoint );
00049         
00050     Vec3f       getWorldUp() const { return mWorldUp; }
00051     void        setWorldUp( const Vec3f &aWorldUp );
00052 
00053     void        lookAt( const Vec3f &target );
00054     void        lookAt( const Vec3f &aEyePoint, const Vec3f &target );
00055     void        lookAt( const Vec3f &aEyePoint, const Vec3f &target, const Vec3f &aUp );
00056     Vec3f       getViewDirection() const { return mViewDirection; }
00057     void        setViewDirection( const Vec3f &aViewDirection );
00058 
00059     Quatf       getOrientation() const { return mOrientation; }
00060     void        setOrientation( const Quatf &aOrientation );
00061 
00062     float   getFov() const { return mFov; }
00063     void    setFov( float aFov ) { mFov = aFov;  mProjectionCached = false; }
00064     float   getAspectRatio() const { return mAspectRatio; }
00065     void    setAspectRatio( float aAspectRatio ) { mAspectRatio = aAspectRatio; mProjectionCached = false; }
00066     float   getNearClip() const { return mNearClip; }
00067     void    setNearClip( float aNearClip ) { mNearClip = aNearClip; mProjectionCached = false; }
00068     float   getFarClip() const { return mFarClip; }
00069     void    setFarClip( float aFarClip ) { mFarClip = aFarClip; mProjectionCached = false; }
00070 
00071     virtual void    getNearClipCoordinates( Vec3f *topLeft, Vec3f *topRight, Vec3f *bottomLeft, Vec3f *bottomRight ) const;
00072     virtual void    getFarClipCoordinates( Vec3f *topLeft, Vec3f *topRight, Vec3f *bottomLeft, Vec3f *bottomRight ) const;
00073 
00075     void    getFrustum( float *left, float *top, float *right, float *bottom, float *near, float *far ) const;
00077     virtual bool isPersp() const = 0;
00078     
00079     virtual const Matrix44f&    getProjectionMatrix() const { if( ! mProjectionCached ) calcProjection(); return mProjectionMatrix; }
00080     virtual const Matrix44f&    getModelViewMatrix() const { if( ! mModelViewCached ) calcModelView(); return mModelViewMatrix; }
00081     virtual const Matrix44f&    getInverseModelViewMatrix() const { if( ! mInverseModelViewCached ) calcInverseModelView(); return mInverseModelViewMatrix; }
00082 
00083     Ray     generateRay( float u, float v, float imagePlaneAspectRatio ) const;
00084     void    getBillboardVectors( Vec3f *right, Vec3f *up ) const;
00085 
00087     Vec2f worldToScreen( const Vec3f &worldCoord, float screenWidth, float screenHeight ) const;
00089     Vec3f worldToEye( const Vec3f &worldCoord ) { return getModelViewMatrix().transformPointAffine( worldCoord ); }
00091     float worldToEyeDepth( const Vec3f &worldCoord ) const { return getModelViewMatrix().m[2] * worldCoord.x + getModelViewMatrix().m[6] * worldCoord.y + getModelViewMatrix().m[10] * worldCoord.z + getModelViewMatrix().m[14]; }
00093     Vec3f worldToNdc( const Vec3f &worldCoord ) { Vec3f eye = getModelViewMatrix().transformPointAffine( worldCoord ); return getProjectionMatrix().transformPoint( eye ); }
00094 
00095 
00096     float   getScreenRadius( const class Sphere &sphere, float screenWidth, float screenHeight ) const;
00097 
00098   protected:
00099     Vec3f   mEyePoint;
00100     Vec3f   mViewDirection;
00101     Quatf   mOrientation;
00102     float   mCenterOfInterest;
00103     Vec3f   mWorldUp;
00104 
00105     float   mFov;
00106     float   mAspectRatio;
00107     float   mNearClip;      
00108     float   mFarClip;
00109 
00110     mutable Vec3f       mU; // Right vector
00111     mutable Vec3f       mV; // Readjust up-vector
00112     mutable Vec3f       mW; // Negative view direction
00113 
00114     mutable Matrix44f   mProjectionMatrix, mInverseProjectionMatrix;
00115     mutable bool        mProjectionCached;
00116     mutable Matrix44f   mModelViewMatrix;
00117     mutable bool        mModelViewCached;
00118     mutable Matrix44f   mInverseModelViewMatrix;
00119     mutable bool        mInverseModelViewCached;
00120     
00121     mutable float       mFrustumLeft, mFrustumRight, mFrustumTop, mFrustumBottom;
00122 
00123     inline void     calcMatrices() const;
00124 
00125     virtual void    calcModelView() const;
00126     virtual void    calcInverseModelView() const;
00127     virtual void    calcProjection() const = 0;
00128 };
00129 
00130 class CameraPersp : public Camera {
00131   public:
00132     CameraPersp();
00133     CameraPersp( int pixelWidth, int pixelHeight, float fov ); // constructs screen-aligned camera
00134     CameraPersp( int pixelWidth, int pixelHeight, float fov, float nearPlane, float farPlane ); // constructs screen-aligned camera
00135     
00136     void    setPerspective( float horizFovDegrees, float aspectRatio, float nearPlane, float farPlane );
00137     
00141     void    getLensShift( float *horizontal, float *vertical ) const { *horizontal = mLensShift.x; *vertical = mLensShift.y; }
00145     Vec2f   getLensShift() const { return Vec2f( mLensShift.x, mLensShift.y ); }
00149     void    setLensShift( float horizontal, float vertical );
00153     void    setLensShift( const Vec2f &shift ) { setLensShift( shift.x, shift.y ); }
00155     float   getLensShiftHorizontal() const { return mLensShift.x; }
00158     void    setLensShiftHorizontal( float horizontal ) { setLensShift( horizontal, mLensShift.y ); }
00160     float   getLensShiftVertical() const { return mLensShift.y; }
00163     void    setLensShiftVertical( float vertical ) { setLensShift( mLensShift.x, vertical ); }
00164     
00165     virtual bool    isPersp() const { return true; }
00166 
00167     CameraPersp getFrameSphere( const class Sphere &worldSpaceSphere, int maxIterations = 20 ) const;
00168 
00169   protected:
00170     Vec2f   mLensShift;
00171 
00172     virtual void    calcProjection() const;
00173 };
00174 
00175 class CameraOrtho : public Camera {
00176   public:
00177     CameraOrtho();
00178     CameraOrtho( float left, float right, float bottom, float top, float nearPlane, float farPlane );
00179 
00180     void setOrtho( float left, float right, float bottom, float top, float nearPlane, float farPlane );
00181 
00182     virtual bool    isPersp() const { return false; }
00183     
00184   protected:
00185     virtual void    calcProjection() const;
00186 };
00187 
00188 class CameraStereo : public CameraPersp {
00189   public:
00190     CameraStereo() 
00191         : mConvergence(1.0f), mEyeSeparation(0.05f), mIsStereo(false), mIsLeft(true) {}
00192     CameraStereo( int pixelWidth, int pixelHeight, float fov )
00193         : CameraPersp( pixelWidth, pixelHeight, fov ), 
00194         mConvergence(1.0f), mEyeSeparation(0.05f), mIsStereo(false), mIsLeft(true) {} // constructs screen-aligned camera
00195     CameraStereo( int pixelWidth, int pixelHeight, float fov, float nearPlane, float farPlane )
00196         : CameraPersp( pixelWidth, pixelHeight, fov, nearPlane, farPlane ), 
00197         mConvergence(1.0f), mEyeSeparation(0.05f), mIsStereo(false), mIsLeft(true) {} // constructs screen-aligned camera
00198 
00200     float           getConvergence() const { return mConvergence; }
00202     void            setConvergence( float distance, bool adjustEyeSeparation=false ) { 
00203         mConvergence = distance; mProjectionCached = false;
00204 
00205         if(adjustEyeSeparation) 
00206             mEyeSeparation = mConvergence / 30.0f;
00207     }
00209     float           getEyeSeparation() const { return mEyeSeparation; }
00211     void            setEyeSeparation( float distance ) { mEyeSeparation = distance; mModelViewCached = false; mProjectionCached = false; }
00213     Vec3f           getEyePointShifted() const;
00214     
00216     void            enableStereoLeft() { mIsStereo = true; mIsLeft = true; }
00217     bool            isStereoLeftEnabled() const { return mIsStereo && mIsLeft; }
00219     void            enableStereoRight() { mIsStereo = true; mIsLeft = false; }
00220     bool            isStereoRightEnabled() const { return mIsStereo && !mIsLeft; }
00222     void            disableStereo() { mIsStereo = false; }
00223     bool            isStereoEnabled() const { return mIsStereo; }
00224 
00225     virtual void    getNearClipCoordinates( Vec3f *topLeft, Vec3f *topRight, Vec3f *bottomLeft, Vec3f *bottomRight ) const;
00226     virtual void    getFarClipCoordinates( Vec3f *topLeft, Vec3f *topRight, Vec3f *bottomLeft, Vec3f *bottomRight ) const;
00227     
00228     virtual const Matrix44f&    getProjectionMatrix() const;
00229     virtual const Matrix44f&    getModelViewMatrix() const;
00230     virtual const Matrix44f&    getInverseModelViewMatrix() const;
00231 
00232   protected:
00233     mutable Matrix44f   mProjectionMatrixLeft, mInverseProjectionMatrixLeft;
00234     mutable Matrix44f   mProjectionMatrixRight, mInverseProjectionMatrixRight;
00235     mutable Matrix44f   mModelViewMatrixLeft, mInverseModelViewMatrixLeft;
00236     mutable Matrix44f   mModelViewMatrixRight, mInverseModelViewMatrixRight;
00237 
00238     virtual void    calcModelView() const;
00239     virtual void    calcInverseModelView() const;
00240     virtual void    calcProjection() const;
00241   private:
00242     bool            mIsStereo;
00243     bool            mIsLeft;
00244 
00245     float           mConvergence;
00246     float           mEyeSeparation;
00247 };
00248 
00249 } // namespace cinder