arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

Camera.h

Go to the documentation of this file.
00001 ///////////////////////////////////////////////////////////////////////////
00002 //              _____________  ______________________    __   __  _____
00003 //             /  ________  |  |   ___   ________   /   |  \ /  \   |
00004 //            |  |       |  |_ |  |_ |  |       /  /    \__  |      |
00005 //            |  |  ___  |  || |  || |  |      /  /        | |      |
00006 //            |  | |   \ |  || |  || |  |     /  /      \__/ \__/ __|__
00007 //            |  | |_@  ||  || |  || |  |    /  /          Institute
00008 //            |  |___/  ||  ||_|  || |  |   /  /_____________________
00009 //             \_______/  \______/ | |__|  /___________________________
00010 //                        |  |__|  |
00011 //                         \______/
00012 //                    University of Utah       
00013 //                           2002
00014 ///////////////////////////////////////////////////////////////////////////
00015 
00016 //Camera.h
00017 // Joe Kniss
00018 
00019 #ifndef __GUTZ_CAMERA_DOT_H
00020 #define __GUTZ_CAMERA_DOT_H
00021 
00022 #include <mathGutz.h>
00023 #include <list>
00024 #include <vector>
00025 #include "baseManip.h"
00026 #include <iostream>
00027 
00028 #ifdef KONG
00029 class KokoBuffer;
00030 #endif
00031 
00032 namespace gutz {
00033 
00034 ////////////////////////////////////////////////////////////
00035 /// forward decls...
00036 
00037 ////////////////////////////////////////////////////////////
00038 /// Interaction Modes supported by the gutz::Camera manipulator
00039 
00040 enum{ //Supported modes, camera Actions
00041    CAM_MODE_NONE,          ///< Mode not mapped
00042    CAM_ROT,                ///< Camera rotates about lookat point
00043    CAM_ZOOM,               ///< Changes frustum, no movement
00044    CAM_DOLLY,              ///< Camera forward & backward
00045    CAM_TRANS_XY,           ///< Camera space up/down left/right 
00046    CAM_TRANS_XZ,           ///< Camera space left/right forward/back
00047    CAM_TRANS_ZY,           ///< Camera space up/down forward/back
00048    CAM_TRANS_Z,            ///< Move camera forward and back
00049    CAM_TRANS_Y,            ///< Move camera up and down
00050    CAM_TRANS_X,            ///< Move camera side to side
00051    CAM_ROLL,               ///< Roll, rotate around Z
00052    CAM_PITCH,              ///< Pitch, rotate around X
00053    CAM_YAW,                ///< Yaw, rotate around Y
00054    CAM_SWIVEL,             ///< Pitch & Yaw, rotate about eye point
00055    CAM_LAST_MODE
00056 };
00057 
00058 ////////////////////////////////////////////////////////////
00059 /// The "LOCAL" space for this manipulator is WORLD space. 
00060 /// This object maintains the Projection and View matricies.
00061 /// It also handles VIEWPORT transforms implicitly, you 
00062 /// can take SCREEN space points (0-SX)(0-SY)(0-1) and get
00063 /// them either in EYE space or WORLD space. Where:
00064 /// - SX = screen size x
00065 /// - SY = screen size y
00066 /// - (0-1) : 0 = nearClip, 1 = farClip
00067 ////////////////////////////////////////////////////////////
00068 class Camera : public BaseManip {
00069 public:
00070    Camera();
00071    Camera(const Camera &cam);
00072 
00073    virtual ~Camera();
00074 
00075    bool    isCamera() const  { return true;  }
00076    bool    isManip()  const  { return false; }
00077    /// cameras don't have cameras!!!
00078    Camera* getCamera()const  { return 0; }
00079 
00080    ////////////////////////////////////////////////////////////
00081    ///@name Transformations
00082    ///@{
00083    /// get the projection transform, PROJECTION<-LOCAL
00084    gutz::mat4f getProjectTransform() const  {  return _pm * _cm; }
00085    /// get the inverse projection transform, PROJECTION->LOCAL
00086    gutz::mat4f getInvProjectTransform() const { return _cinv * _pinv; }
00087    /// get the screen transform, SCREEN<-PROJECT
00088    ///  this is wierd because you must apply the Project transform,
00089    ///  then divide by w, then apply the screen transform.  
00090    gutz::mat4f getScreenTransform() const { return getViewportMatrix(); }
00091    /// get the inverse screen transform, SCREEN->LOCAL
00092    gutz::mat4f getInvScreenTransform() const { return getInvViewportMatrix(); }
00093    /// get the eye transform: EYE<-LOCAL,
00094    gutz::mat4f getEyeTransform() const { return _cm; }
00095    /// get the world transform: WORLD<-LOCAL (Identity)
00096    gutz::mat4f getWorldTransform() const { return mat4f(); }
00097    /// get the transform that this manipulator defines
00098    gutz::mat4f getLocalTransform() const { return _cm; }
00099    /// get the inverse eye transform: EYE->LOCAL
00100    gutz::mat4f getInvEyeTransform() const { return _cinv; }
00101    /// get the inverse world transform: WORLD->LOCAL (Identity)
00102    gutz::mat4f getInvWorldTransform() const { return mat4f(); }
00103    /// get the inverse transform that this manipulator defines
00104    gutz::mat4f getInvLocalTransform() const { return _cinv; }
00105    /// get the projection matrix currently associated with this transform chain
00106    gutz::mat4f getProjection() const { return _pm; }
00107    /// get the inverse projection matrix (inverse of getProjection())
00108    gutz::mat4f getInvProjection() const { return _pinv; }
00109    /// get the quaternion that expresses the total rotation in this chain
00110    ///gutz::quatf getEyeQuat() const { return _camquat; }
00111    gutz::quatf getEyeQuat() const { return quatf( _cm.rot() ); }
00112    /// get the inverse quaternion for rotation from EYE to this space
00113    gutz::quatf getInvEyeQuat() const { return getEyeQuat().conj(); }
00114    /// get the quaternion for rotation: WORLD<-LOCAL (Identity)
00115    gutz::quatf getWorldQuat() const { return quatf_id; }
00116    /// get the inverse quaternion for rotation: WORLD->LOCAL (Identity)
00117    gutz::quatf getInvWorldQuat() const { return quatf_id; }
00118    /// get the local quaternion for rotation
00119    gutz::quatf getLocalQuat() const { return _camquat; }
00120    /// get the inverse local quaterinion for rotation
00121    gutz::quatf getInvLocalQuat() const { return _camquat.inv(); }
00122    ///@}
00123    ////////////////////////////////////////////////////////////
00124 
00125    ////////////////////////////////////////////////////////////
00126    /// @name Get/Set Camera specific Matricies
00127    //@{ 
00128 
00129    /// transform from PROJECTION space to screen space (from device normalized coords)
00130    ///   right now this object does not own the viewport, so.. we are just using
00131    ///   the viewport (0,0,w,h), need to fix that!!!
00132    mat4f        getViewportMatrix() const;
00133    mat4f        getInvViewportMatrix() const;
00134    //TODO: need to add true viewport functionality to this!!
00135    // get the viewport (x,y,w,h)<->(start,size)
00136    //vec4ui       getViewport() const               { return _viewport; }
00137    // set the viewport
00138    //void         setViewport(const vec4ui vp)      { _viewport = vp; }
00139    const mat4f &getProjectMatrix() const          { return _pm;   }
00140    const mat4f &getInvProjectMatrix() const       { return _pinv; }
00141    void         setProjectMatrix(const mat4f &m);
00142    const mat4f &getViewMatrix() const             { return _cm;   }
00143    const mat4f &getInvViewMatrix() const          { return _cinv; }
00144    void         setViewMatrix(const mat4f &m);
00145    mat4f        getInvMatrix() const              { return _pinv * _cinv; }
00146    quatf        getCamQuat() const                { return _camquat; }
00147    //@}
00148 
00149    ////////////////////////////////////////////////////////////
00150    ///@name Position & orientation
00151    ///@{
00152    gutz::vec3f getLocalPos() const    { return _eyePos; }
00153    void        setLocalPos(const vec3f &pos)
00154    {  _cm[12] = pos.x; _cm[13] = pos.y; _cm[14] = pos.z; }
00155    gutz::mat3f getLocalOrient() const { return _cm.rot(); }
00156    /// TODO: implement this!!!
00157    void        setLocalQuat(const quatf &lq) {}
00158    ///@}
00159    ////////////////////////////////////////////////////////////
00160 
00161    ////////////////////////////////////////////////////////////
00162    ///@name Serialization.
00163    //@{
00164 
00165    /// write.
00166    virtual bool serialize(std::ostream &os, const std::string indent = std::string(""));
00167    /// read.
00168    virtual bool unserialize(std::istream &is);
00169    /// serialize specific parts
00170    /// state, first all of it, then the specific ones.
00171    /// serialState calls SerialEventMap & SerialParamMap & sets up tags
00172    virtual bool serialState(std::ostream &os, const std::string indent = std::string(""));
00173    virtual bool unserialState(std::istream &is);
00174    virtual bool serialEventMap(std::ostream &os, const std::string indent = std::string(""));
00175    virtual bool serialParamMap(std::ostream &os, const std::string indent = std::string(""));
00176    virtual bool unserialEventMap(std::istream &is);
00177    virtual bool unserialParamMap(std::istream &is);
00178    virtual bool serialData(std::ostream &os, const std::string indent = std::string(""));
00179    virtual bool unserialData(std::istream &is);
00180    ///@}
00181    ////////////////////////////////////////////////////////////
00182 
00183    ////////////////////////////////////////////////////////////
00184    ///@name Clipping planes,
00185    //@{
00186    /// Keep this current
00187    virtual void  setClips(float nearClip, float farClip);
00188    virtual gutz::vec2f getClips() const {return _clips;}
00189    virtual float getNearClip() const ;
00190    virtual float getFarClip() const ;
00191    //@}
00192    ////////////////////////////////////////////////////////////
00193 
00194    ////////////////////////////////////////////////////////////
00195    ///@name LookAt functions
00196    //@{
00197    virtual void          setEyePos(vec3f eyePos);
00198    virtual void          setLookAt(vec3f lookat);
00199    virtual void          setUpVec(vec3f upvec);
00200 
00201    virtual const vec3f & getEyePos() const          {return _eyePos;};
00202    virtual const vec3f & getLookAt() const          {return _lookat;};
00203    virtual const vec3f & getUpVec() const           {return _upvec;};
00204    virtual       vec3f   getXVec()  const           
00205    {vec3f z = _lookat - _eyePos; z.normalize(); return vec3f(_upvec.cross(z));}
00206    virtual       vec3f   getViewDir() const        
00207    {return getLookAt() - getEyePos(); }
00208    virtual       float   getFocalLength() const
00209    {  return (getEyePos() - getLookAt()).norm(); }
00210    //@}
00211    ////////////////////////////////////////////////////////////
00212 
00213    ////////////////////////////////////////////////////////////
00214    ///@name Screen size functions
00215    ///   Keep this current.
00216    //@{
00217    void           setScreen(unsigned int x, unsigned int y);
00218    gutz::vec2ui   getScreen()  const         {return _screen;}
00219    unsigned int   getScreenX() const         {return _screen[0];};
00220    unsigned int   getScreenY() const         {return _screen[1];};
00221    //@}
00222    ////////////////////////////////////////////////////////////
00223 
00224    ////////////////////////////////////////////////////////////
00225    ///@name Projection
00226    /// assumes you have set clips & screen first
00227    //@{
00228 
00229    /// Sets the projection matrix based on a field of view
00230    virtual void         setPerspective(float fov);
00231    /// Sets the frustum explicitly, perspective
00232    virtual void         setFrustum(float left, float right, float bottom, float top);
00233    /// Gets the current frustum, valid wether set via Perspective, Frustum, or Ortho
00234    gutz::vec4f          getFrustum() const { return _frustum; }
00235    /// Sets the projection matrix to Orthographic
00236    virtual void         setOrtho(float left, float right, float bottom, float top);
00237    /// check if we are orthographic
00238    bool                 isOrtho() const { return _ortho; }
00239    
00240    //@}
00241    ////////////////////////////////////////////////////////////
00242 
00243    ////////////////////////////////////////////////////////////
00244    ///@name Project, Unproject, & space conversions
00245    ///@{
00246 
00247    /// You have a point in WORLD space and now you want it in "this" (WORLD)
00248    ///   manipulators space. WORLD->WORLD space, identity transform. 
00249    gutz::vec3f getLocalPosWorld(const gutz::vec3f &wpos) const 
00250    {   return wpos;  }
00251    /// WORLD->LOCAL dir, You have a vector (direction) in WORLD, you want it in LOCAL
00252    gutz::vec3f getLocalDirWorld(const gutz::vec3f &wdir) const
00253    {   return wdir;  }
00254    /// You have a LOCAL point and you want it in WORLD space, identity
00255    /// WORLD<-WORLD
00256    gutz::vec3f getWorldPosLocal(const gutz::vec3f &lpos) const
00257    {   return lpos;  }
00258    /// WORLD<-LOCAL dir, You have a vector (direction) in WORLD, you want it in LOCAL
00259    gutz::vec3f getWorldDirLocal(const gutz::vec3f &ldir) const
00260    {   return ldir;  }
00261    /// You have an EYE space point and want it in LOCAL space
00262    /// EYE->LOCAL
00263    gutz::vec3f getLocalPosEye(const gutz::vec3f &epos) const
00264    {   return _cinv.tpoint(epos);  }
00265    /// You have a LOCAL space point and want it in EYE space
00266    /// EYE<-LOCAL
00267    gutz::vec3f getEyePosLocal(const gutz::vec3f &lpos) const 
00268    {   return _cm.tpoint(lpos);   }
00269    /// You have a point in SCREEN space and now you want it in LOCAL/WORLD space
00270    /// SCREEN->WORLD
00271    gutz::vec3f getLocalPosScreen(const gutz::vec3f &spos) const
00272    {   return _cinv.tpoint(getEyePosScreen(spos));  }
00273    /// You have a point in LOCAL space and want it in SCREEN space
00274    /// SCREEN<-LOCAL, you may have to flip the y pos (screenY - pos.y)
00275    gutz::vec3f getScreenPosLocal(const gutz::vec3f &lpos) const
00276    {
00277       gutz::vec4f ppos = _pm * (_cm * vec4f(lpos, 1));
00278       ppos /= ppos.w;
00279       ppos.x = (ppos.x + 1)/2.0f * _screen[0];
00280       ppos.y = (ppos.y + 1)/2.0f * _screen[1];
00281       ppos.z = (ppos.z + 1)/2.0f; 
00282       return ppos;
00283    }
00284    /// Get pick pos from SCREEN (x,y,z), return in EYE space
00285    /// z should be in [0,1] range: 0 = nearClip, 1 = farClip \n
00286    inline 
00287    gutz::vec3f getEyePosScreen(const gutz::vec3f &scrPos) const
00288    {
00289       vec4f tmp(scrPos.x/float(getScreenX()) *2.0f-1.0f,
00290                 (getScreenY() - scrPos.y - 1)/float(getScreenY()) *2.0f-1.0f,
00291                 scrPos.z *2.0f-1.0f,
00292                 1.0f);
00293       tmp = _pinv * tmp;
00294       return tmp/tmp.w;
00295    }
00296 
00297    ///////////////////////////////////////////////////////////
00298    /// Get pick pos, takes SCREEN space (x,y,z) and returns
00299    ///  the point in WORLD space,
00300    inline
00301    gutz::vec3f getPickPos(const gutz::vec3f &scrPos) const
00302    {
00303       return getLocalPosScreen(scrPos);
00304    }
00305 
00306    ////////////////////////////////////////////////////////////
00307    /// Get pick pos, takes SCREEN space (x,y) and returns point
00308    ///  on near clip in WORLD space,
00309    template<class T> inline
00310       gutz::vec3f  getPickPos(const T x, const T y) const
00311    {
00312       return getPickPos(gutz::vec3f(x,y,0.0f));
00313    }
00314 
00315    ////////////////////////////////////////////////////////////
00316    /// Get pick pos, takes SCREEN space (x,y) and returns point
00317    ///  on near clip in WORLD space, same as above
00318    template<class T> inline
00319       gutz::vec3f getPickPos(const gutz::vec2<T> &p) const
00320    {
00321       return getPickPos(gutz::vec3f(p.x,p.y,0.0f));
00322    }
00323 
00324    ////////////////////////////////////////////////////////////
00325    /// Get the ray from the eye pointing toward a point on the
00326    /// near clip. x,y given in SCREEN Space, returns ray in 
00327    /// WORLD space. Needed since there is an algorithmic difference
00328    ///  between ray computation with perspective and ortho projections,
00329    ///  and we could like to have algorithms that don't care what 
00330    ///  "kind" of camera it is.  
00331    inline
00332    gutz::ray3f  getRay(float x, float y) const
00333    {
00334       if(isOrtho()) return gutz::ray3f(getPickPos<float>(x,y), getViewDir());
00335       gutz::vec3f scrpt = getPickPos<float>(x,y);
00336       gutz::vec3f vdir  = scrpt - getEyePos();
00337       vdir.normalize();
00338       return gutz::ray3f(scrpt, vdir);
00339    }
00340    /// much like getRay, but for a world space point.
00341    ///  returns the ray from the eye through the given point
00342    inline
00343    gutz::ray3f  getRayWorld(gutz::vec3f pos) const
00344    {
00345       if(isOrtho()) return gutz::ray3f(pos, getViewDir());
00346       gutz::vec3f vdir = pos - getEyePos();
00347       vdir.normalize();
00348       return gutz::ray3f(pos, vdir);
00349    }
00350    ///@}
00351 
00352    /////////////////////////////////////////////////////////////
00353    ///@name Vectors
00354    ///  Simmilar to Projections, but rather than projecting a
00355    ///  point you are projecting/deriving a direction vector.
00356    ///@{
00357 
00358    /// get a LOCAL direction (ray) through a LOCAL point from the eye 
00359    gutz::vec3f getLocalEyeRayLocal(const gutz::vec3f &lpos) const
00360    {
00361       if(isOrtho()) return getViewDir();
00362       return lpos - getWorldPos();
00363    }
00364    /// get a LOCAL direction through a SCREEN point from the eye
00365    gutz::vec3f getLocalEyeRayScreen(const gutz::vec3f &spos) const
00366    {
00367       if(isOrtho()) return getViewDir();
00368       return getLocalPosScreen(spos) - getWorldPos();
00369    }
00370    /// get a World direction through a Screen point from the eye
00371    gutz::vec3f getWorldEyeRayScreen(const gutz::vec3f &spos) const
00372    { return getLocalEyeRayScreen(spos); }
00373    /// get a World direction through a World point from the eye
00374    gutz::vec3f getWorldEyeRayWorld(const gutz::vec3f &wpos) const
00375    { return getLocalEyeRayLocal(wpos); }
00376    /// get the View direction in LOCAL space
00377    gutz::vec3f getLocalViewDir() const { return getViewDir(); }
00378 
00379    ///@}
00380 
00381    ////////////////////////////////////////////////////////////
00382    ///@name Handle mouse events
00383    ///   returns false if there are no valid events.
00384    ///@{
00385    virtual void  mapEvent(unsigned int event, unsigned int button, float speed = 1.0f)
00386    {_keymap[button] = event; _speedmap[button] = speed;}
00387    unsigned int  getEvent(const MouseEvent &me) const;
00388    float         getSpeed(const MouseEvent &me) const;
00389 
00390    /// mouse up/down
00391    virtual bool mouse(const MouseEvent &me);
00392    /// move mouse
00393    virtual bool move(const MouseMoveEvent &mme);
00394    ///@}
00395 
00396 
00397    ////////////////////////////////////////////////////////////
00398    ///@name Tumble
00399    ///@{
00400 
00401    /// Update tumble "speed" steps
00402    virtual void tumble(float speed = 1); 
00403    ///@}
00404 
00405 #ifdef KONG
00406    ////////////////////////////////////////////////////////////
00407    /// Pack/unpack details for sending the important data values 
00408    /// in a camera over the wire.
00409    unsigned int packSize(void);   // How big of a buffer do we need?
00410    void pack(KokoBuffer &kbuf, bool reset=true);  // Pack the camera up.
00411    void unpack(KokoBuffer &kbuf, bool reset=true); // Unpack into Camera.
00412 #endif
00413 
00414 protected:
00415 
00416    void         _setProjectMatrix(const mat4f &m);
00417    void         _setViewMatrix(const mat4f &m);
00418 
00419 
00420    ///@name Behavior implementation
00421    ///@{
00422    virtual bool   handleCamera(const gutz::MouseMoveEvent &mme);
00423 
00424    virtual void   cameraRot(const gutz::MouseMoveEvent &mme);
00425    virtual void   cameraTrans(const gutz::MouseMoveEvent &mme, 
00426                               vec3f dxAxis, vec3f dyAxis);
00427    virtual void   cameraRotAxis(const gutz::MouseMoveEvent &mme,
00428                                 vec3f dxAxis, vec3f dyAxis);
00429    virtual void   cameraSwivel(const gutz::MouseMoveEvent &mme);
00430    virtual void   cameraZoom(const gutz::MouseMoveEvent &mme);
00431    ///@}
00432 
00433    gutz::vec2ui   _screen;   ///<screen size
00434    ///   right now this object does not own the viewport, so.. we are just using
00435    ///   the viewport (0,0,w,h), need to fix that!!!, should keep all info 
00436    ///   relative to the screen in this variable not _screen!!!!!!!!!!!!
00437    gutz::vec4ui   _viewport; ///<viewport
00438 
00439    /// index names of frustum entries
00440    enum { FRUST_LEFT=0, FRUST_RIGHT=1, FRUST_TOP=2, FRUST_BOTTOM=3 };
00441    gutz::vec4f        _frustum;         ///< view frustum
00442 
00443    gutz::vec2f    _clips;               ///< Clipping planes
00444 
00445    mat4f        _cm, _pm, _cinv, _pinv; ///< Camera & projection matrices
00446 
00447    vec3f        _eyePos,_lookat,_upvec; ///< Current Lookat parameters
00448 
00449    quatf        _camquat;               ///< Quaternions for rotation
00450 
00451    /// "temporary" vectors for events
00452    vec3f        _lastEyePos,_lastLookat;
00453    /// "temporary" quaternions for tumbling (track is a bad name joe!!)
00454    quatf        _camtrackquat, _swivtrackquat;
00455 
00456    bool         _ortho;                 ///< are we orthographic or perspective
00457 
00458    ////////////////////////////////////////////////////////////
00459    // key 2 action mapers
00460    EventKeyMap    _keymap;              ///< maps buttons/keys to events
00461    EventParamMap  _speedmap;            ///< speed for some event
00462 
00463 private:
00464 
00465 };
00466 
00467 ////////////////////////////////////////////////////////////////////////////
00468 ///  List of Cameras, typedefined for convenience
00469 ////////////////////////////////////////////////////////////////////////////
00470 
00471 typedef SmartPtr<Camera>              CameraSP;
00472 
00473 typedef std::list<Camera *>           CameraList;
00474 typedef std::list<Camera *>::iterator CameraListIter;
00475 
00476 typedef std::vector<Camera *>           CameraVec;
00477 typedef std::vector<Camera *>::iterator CameraVecIter;
00478 
00479 
00480 }//end namespace gutz
00481 
00482 #endif

Send questions, comments, and bug reports to:
jmk