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

Manip.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 //manip.h
00017 //Joe Kniss
00018 
00019 #ifndef __MANIP_DOT_H
00020 #define __MANIP_DOT_H
00021 
00022 #include <mathGutz.h>
00023 #include <signalGutz.h>
00024 #include <map>
00025 #include <list>
00026 #include "baseManip.h"
00027 #include "Camera.h"
00028 #include "ManipEventBase.h"
00029 
00030 #ifdef KONG
00031 class KokoBuffer;
00032 #endif
00033 
00034 namespace gutz {
00035 
00036 class Manip;
00037 typedef EventMap<Manip> ManipEventMap;
00038 
00039 //////////////////////////////////////////////////////////////
00040 /// Interaction Modes supported by this class, object actions
00041 //////////////////////////////////////////////////////////////
00042 enum{ //Supported modes, camera Actions
00043    OBJ_MODE_NONE = CAM_LAST_MODE + 1,       ///< Mode not mapped
00044    OBJ_CENT_ROT,        ///< Rotates object around its center
00045    OBJ_ABS_ROT,         ///< Rotates object around the origin of its space
00046    OBJ_STRANS_XY,       ///< Screen space object translate X,Y plane
00047    OBJ_STRANS_XZ,       ///< Screen space object translate X,Z plane
00048    OBJ_STRANS_ZY,       ///< Screen space object translate Y,Z plane
00049    OBJ_ATRANS_01,       ///< Translate in the plane defined by a custom vector 01
00050    OBJ_ATRANS_02,       ///< Translate in the plane defined by a custom vector 01
00051    OBJ_ATRANS_03,       ///< Translate in the plane defined by a custom vector 01
00052    OBJ_ATRANS_04,       ///< Translate in the plane defined by a custom vector 01
00053    OBJ_ATRANS_05,       ///< Translate in the plane defined by a custom vector 01
00054    OBJ_LAST_MODE
00055 };
00056 
00057 ////////////////////////////////////////////////////////////////////////////
00058 ///   A Manipulator interaction class. (include graphicsGutz.h)
00059 /// 
00060 ///   A Manipluator interaction class. Handles basic operations relating to
00061 ///   object manipulation.  The Camera is automatically set if the 
00062 ///   gutz::MouseEvent contains a valid camera, which it should if it was
00063 ///   correctly created. 
00064 ///   
00065 ///  Implementation notez (users of this class can ignore this stuff): \n
00066 ///    Manipulators are composed of 3 basic transforms, a "baked" transform (B)
00067 ///    representing all translation and rotation up to the current rotation (R)
00068 ///    around the "center of rotation" (C).  Here is how we generate the local 
00069 ///    transform (LM): \n
00070 ///    LM = B * C^{-1} * R * C \n
00071 ///    The matrix B is what I call the "baked" matrix, so called because
00072 ///    when the center of rotation changes, we "bake" the previous
00073 ///    C^{-1}*R*C into B, ie B = B*C^{-1}*R*C.  It is also key when the 
00074 ///    user sets the matrix, there may be no way to recover a pure rotation
00075 ///    about our current center of rotation. In this case we just set it to B
00076 ///    and set R to identity.  C is the transform that takes the local coordinate
00077 ///    frame to the center of rotation, ie -(minus)"center of rotation".  R is 
00078 ///    the rotation around that center of rotation; it is stored as a quaternion
00079 ///    accessed through getCenterQuat() and setCenterQuat().  \n
00080 ///
00081 ///  Events implementing rotation need to be aware of the relationships described
00082 ///   above.  Since B is applied before R, you need to do the appropriate 
00083 ///   change of basis to assign/modify R.  Remember that B includes rotation.  Right
00084 ///   now, rotations are generated with respect to the current view.  There is a 
00085 ///   function calld getCamQuat() that returns a quaternion representing all 
00086 ///   rotation from EYE space to this local coordinate frame, including rotations
00087 ///   in B, but not R.  This means that you can multiply R by another quaternion
00088 ///   Q (defined in EYE space) like this: \n
00089 ///   R' = CQ^{-1} * Q * CQ * R \n
00090 ///   Where CQ is the camera quaternion.  The part of the equation: \n
00091 ///   CQ^{-1} * Q * CQ \n
00092 ///   is the rotation Q in the local coordinate frame, it expresses the change of
00093 ///   basis to get Q into the local frame.  This quaternion can be stored and 
00094 ///   applied during tumbling.  Take a look at gutz::RotateManipEvent to see 
00095 ///   a reference implementation of this process.  
00096 ///
00097 ///  At some point, I want to lighten up this object; right now it is carying
00098 ///   a lot of data.  I am caching the matrix and its inverse since I assume
00099 ///   that the user should have access to these, and that it be very fast.
00100 ////////////////////////////////////////////////////////////////////////////
00101 
00102 class Manip : public BaseManip, public ManipEventMap {
00103 public:
00104    HAS_SLOTS;
00105 
00106    /// if a Camera is passed, the parent is automatically set to the camera
00107    Manip(Camera *cam = 0);
00108    /// copy constructor, copies everything, including the parent and events
00109    Manip(const Manip &m);
00110    /// assignment, copies everything but events, including the parent
00111    Manip &operator=(const Manip &m);
00112 
00113    virtual ~Manip(){}
00114 
00115    ///@name RTTI
00116    ///@{
00117    bool isCamera() const { return false; }
00118    bool isManip()  const { return true;  }
00119    ///@}
00120     
00121    ////////////////////////////////////////////////////////////
00122    ///@name Key Transform Parameters
00123    ///@{
00124    
00125    /// What is the center of rotation, defaults to (0,0,0), in LOCAL space
00126    vec3f  getCenter() const              { return _center; }
00127    /// Set the center of rotation, in LOCAL space
00128    void   setCenter(const vec3f &center);
00129    /// get the quaternion associated with rotation around the center
00130    gutz::quatf getCenterQuat() const          { return _currquat; }
00131    /// set the quaternion associated with rotation around the center
00132    void        setCenterQuat(const quatf &cq) { _currquat = cq; updateMatrix();}
00133    /// What is the radius of rotation, returns 0.0 if unset
00134    float  getRad() const { return _userRad; }
00135    /// Set the radius of rotation, set to 0.0 if you want default radius behavior
00136    void   setRad(float rad) { _userRad = rad; }
00137    /// Get the radius for an event, specifically this returns the 
00138    ///  default radius if we ONLY have screen position, and no depth,
00139    ///  if we have depth, and no user defined radius, we guess the radius based
00140    ///  on the pick point and center of rotation.  
00141    float  getRad(const gutz::MouseEvent &me);
00142 
00143    ///@}
00144 
00145    ////////////////////////////////////////////////////////////
00146    ///@name Transformations
00147    ///@{
00148    
00149    /// Get Matrix.
00150    /// Get the 4x4 homogenious transformation matrix, equiv to getLocalTransform()
00151    mat4f getMatrix() const         {return _om;}
00152    mat4f getInvMatrix() const      {return _oinv;}
00153    void  setMatrix(const gutz::mat4f &m); 
00154 
00155    /// get the projection transform, PROJECTION<-LOCAL
00156    virtual gutz::mat4f getProjectTransform() const
00157    { if(_parent) return _parent->getProjectTransform() * _om; return _om; }
00158    /// get the inverse projection transform, PROJECTION->LOCAL
00159    virtual gutz::mat4f getInvProjectTransform() const
00160    { if(_parent) return _oinv * _parent->getInvProjectTransform(); return _oinv; }
00161    /// get the screen transform, SCREEN<-PROJECT
00162    ///  this is wierd because you must apply the Project transform,
00163    ///  then divide by w, then apply the screen transform.  
00164    virtual gutz::mat4f getScreenTransform() const
00165    { if(_parent) return _parent->getScreenTransform(); return mat4f_id; }
00166    /// get the inverse screen transform, SCREEN->PROJECT
00167    virtual gutz::mat4f getInvScreenTransform() const
00168    { if(_parent) return _parent->getInvScreenTransform(); return mat4f_id; }
00169    /// get the eye transform, EYE<-LOCAL
00170    gutz::mat4f getEyeTransform() const
00171    { if(_parent) return _parent->getEyeTransform() * _om; return _om; }
00172    /// get the inverse eye transform: EYE->LOCAL
00173    gutz::mat4f getInvEyeTransform() const
00174    { if(_parent) return _oinv * _parent->getInvEyeTransform(); return _oinv; }
00175    /// get the inverse world transform: WORLD->LOCAL
00176    virtual gutz::mat4f getInvWorldTransform() const
00177    { if(_parent) return _oinv * _parent->getInvWorldTransform(); return _oinv; }
00178    /// get the world transform: WORLD<-LOCAL
00179    gutz::mat4f getWorldTransform() const
00180    { if(_parent) return _parent->getWorldTransform() * _om; return _om; }
00181    /// get the transform that this manipulator defines
00182    gutz::mat4f getLocalTransform() const { return _om; }
00183    /// get the inverse transform that this manipulator defines
00184    gutz::mat4f getInvLocalTransform() const { return _oinv; }
00185    /// get the projection matrix currently associated with this transform chain
00186    gutz::mat4f getProjection() const
00187    { if(_parent) return _parent->getProjection(); return mat4f_id; }
00188    /// get the inverse projection matrix (inverse of getProjection())
00189    gutz::mat4f getInvProjection() const
00190    { if(_parent) return _parent->getInvProjection(); return mat4f_id; }
00191    /// get the quaternion that expresses rotation: EYE<-LOCAL
00192    gutz::quatf getEyeQuat() const
00193    { if(_parent) return _parent->getEyeQuat().mult(getLocalQuat()); return getLocalQuat(); }
00194    /// get the inverse quaternion for rotation: EYE->LOCAL
00195    gutz::quatf getInvEyeQuat() const
00196    { 
00197       return getEyeQuat().conj();
00198    }
00199    /// get the quaternion for rotation: WORLD<-LOCAL
00200    gutz::quatf getWorldQuat() const
00201    { if(_parent) _parent->getWorldQuat().mult(getLocalQuat()); return getLocalQuat(); }
00202    /// get the inverse quaternion for rotation: WORLD->LOCAL
00203    gutz::quatf getInvWorldQuat() const
00204    { if(_parent) 
00205        return getInvLocalQuat().mult(_parent->getInvWorldQuat()); 
00206      return getInvLocalQuat();
00207    }
00208    /// get the local quaternion for rotation
00209    gutz::quatf getLocalQuat() const { return quatf( _om.rot() ); }
00210    /// get the inverse local quaterinion for rotation
00211    gutz::quatf getInvLocalQuat() const { return getLocalQuat().conj(); }
00212 
00213    ///@}
00214    ////////////////////////////////////////////////////////////
00215 
00216    ////////////////////////////////////////////////////////////
00217    ///@name Position & orientation
00218    ///@{
00219    gutz::vec3f getLocalPos() const    { return _om.trans(); }
00220    void        setLocalPos(const vec3f &pos);
00221    gutz::mat3f getLocalOrient() const { return _om.rot(); }
00222    void        setLocalQuat(const quatf &lq);
00223    ///@}
00224    ////////////////////////////////////////////////////////////
00225 
00226    ////////////////////////////////////////////////////////////
00227    ///@name Tranformation chains
00228    ///   Basically implements a linked list of manipulators that
00229    ///   can be strung together.  If you set your parent to be 0,
00230    ///   then you effectively nuke the chain above this manipulator.
00231    ///   Cameras are special, there can only be one, and it is always
00232    ///   at the very top of the chain.
00233    ///@{
00234    /// adds parent above this transformation (head of the transform chain)
00235    void        setParent(const BaseManipSP parent);
00236    BaseManipSP getParent() const { return _parent; }
00237    /// inserts parent just above this one
00238    void        insertParent(const BaseManipSP parent);
00239    /// replaces parent with our parent's parent.
00240    void        removeParent()
00241    { if(_parent) _parent = _parent->getParent(); else _parent = 0; }
00242    ///@}
00243    ////////////////////////////////////////////////////////////
00244 
00245    ////////////////////////////////////////////////////////////
00246    ///@name Set/Get Camera,
00247    /// Sets the camera so interactions are relative to the
00248    ///   current view.
00249    ///@{
00250    virtual void  setCamera(const gutz::CameraSP cam)
00251    { insertParent(BaseManipSP(cam)); }
00252    Camera       *getCamera() const;
00253 
00254    /// get Camera Quaternions, the camera is simply all rotations
00255    ///   above this object in the chain including any baked rotation: ROT_OF(EYE<-LOCAL).
00256    /// comes in handy for Events using trackballs, since this is all rotation up
00257    /// to the "centerQuat()".  
00258    quatf  getCamQuat()
00259    {
00260       if(_parent) return _parent->getEyeQuat().mult( quatf( _baked.rot() ));
00261       return quatf( _baked.rot() );
00262    }
00263    /// get Inverse Camera Quaternion, the camera is simply all 
00264    ///   rotation above this object in the chain: ROT_OF(EYE->LOCAL)
00265    quatf getInvCamQuat()
00266    {  
00267       return getCamQuat().conj();
00268    }
00269    ///@}
00270 
00271    ////////////////////////////////////////////////////////////
00272    /// @name Screen size functions
00273    //@{
00274    gutz::vec2ui getScreen()  const 
00275    { if(_parent) return _parent->getScreen(); return gutz::vec2ui(0,0);}
00276    unsigned int getScreenX() const 
00277    { if(_parent) return _parent->getScreenX(); return 0;}
00278    unsigned int getScreenY() const 
00279    { if(_parent) return _parent->getScreenY(); return 0;}
00280    //@}
00281 
00282    ////////////////////////////////////////////////////////////
00283    
00284    ////////////////////////////////////////////////////////////
00285    ///@name Projections
00286    ///   Given either a "SCREEN", "EYE", "WORLD", or "LOCAL" space pos
00287    ///@{
00288 
00289    /// You have a point in WORLD space and now you want it in LOCAL space
00290    /// WORLD->LOCAL
00291    gutz::vec3f getLocalPosWorld(const gutz::vec3f &wpos) const
00292    {
00293       if(_parent) return _oinv.tpoint(_parent->getLocalPosWorld(wpos));
00294       return _oinv.tpoint(wpos);
00295    }
00296    /// WORLD->LOCAL dir, You have a vector (direction) in WORLD, you want it in LOCAL
00297    gutz::vec3f getLocalDirWorld(const gutz::vec3f &wdir) const
00298    {
00299       if(_parent) return _oinv.tdir( _parent->getLocalDirWorld(wdir) );
00300       return _oinv.tdir( wdir );
00301    }
00302    /// You have a LOCAL point and you want it in WORLD space
00303    /// WORLD<-LOCAL
00304    gutz::vec3f getWorldPosLocal(const gutz::vec3f &lpos) const
00305    {
00306       if(_parent) return _parent->getWorldPosLocal( _om.tpoint(lpos) );
00307       return _om.tpoint(lpos);
00308    }
00309    /// WORLD<-LOCAL dir, You have a vector (direction) in WORLD, you want it in LOCAL
00310    gutz::vec3f getWorldDirLocal(const gutz::vec3f &ldir) const
00311    {
00312       if(_parent) return _parent->getWorldPosLocal( _om.tdir( ldir ) );
00313       return _om.tdir( ldir );
00314    }
00315    /// You have an EYE space point and want it in LOCAL space
00316    /// EYE->LOCAL
00317    gutz::vec3f getLocalPosEye(const gutz::vec3f &epos) const
00318    {
00319       if(_parent) return _oinv.tpoint(_parent->getLocalPosEye(epos));
00320       return _oinv.tpoint(epos);
00321    }
00322    /// You have a LOCAL space point and want it in EYE space
00323    /// EYE<-LOCAL
00324    gutz::vec3f getEyePosLocal(const gutz::vec3f &lpos) const
00325    {
00326       if(_parent) return _parent->getEyePosLocal(_om.tpoint(lpos));
00327       return _om.tpoint(lpos);
00328    }
00329    /// transform a SCREEN space pos to LOCAL pos (by the inv model view)
00330    /// SCREEN->LOCAL
00331    gutz::vec3f getLocalPosScreen(const gutz::vec3f &spos) const
00332    {
00333       if(_parent) return _oinv.tpoint(_parent->getLocalPosScreen(spos));
00334       return _oinv.tpoint(spos);
00335    }
00336    /// You have a point in LOCAL space and want it in SCREEN space
00337    /// SCREEN<-LOCAL
00338    gutz::vec3f getScreenPosLocal(const gutz::vec3f &lpos) const
00339    {
00340       if(_parent) return _parent->getScreenPosLocal( _om.tpoint(lpos) );
00341       return _om.tpoint(lpos);
00342    }
00343 
00344    ///@}
00345    ////////////////////////////////////////////////////////////
00346 
00347    /////////////////////////////////////////////////////////////
00348    ///@name Vectors
00349    ///  Simmilar to Projections, but rather than projecting a
00350    ///  point you are projecting/deriving a direction vector.
00351    ///@{
00352 
00353    /// get a LOCAL direction (ray) through a LOCAL point from the eye 
00354    gutz::vec3f getLocalEyeRayLocal(const gutz::vec3f &lpos) const
00355    { 
00356       if(_parent) 
00357         return _oinv.tdir( _parent->getLocalEyeRayLocal( _om.tpoint(lpos) ) );
00358       return lpos;
00359    }
00360    /// get a LOCAL direction through a SCREEN point from the eye
00361    gutz::vec3f getLocalEyeRayScreen(const gutz::vec3f &spos) const
00362    {
00363       if(_parent)
00364          return _oinv.tdir( _parent->getLocalEyeRayScreen( spos ) );
00365       return spos;
00366    }
00367    /// get a World direction through a Screen point from the eye
00368    gutz::vec3f getWorldEyeRayScreen(const gutz::vec3f &spos) const
00369    {  if(_parent) return _parent->getWorldEyeRayScreen(spos); return spos; }
00370    /// get a World direction through a World point from the eye
00371    gutz::vec3f getWorldEyeRayWorld(const gutz::vec3f &wpos) const
00372    {  if(_parent) return _parent->getWorldEyeRayWorld(wpos); return wpos; }
00373    /// get the View direction in LOCAL space
00374    gutz::vec3f getLocalViewDir() const 
00375    { if(_parent) return getInvEyeTransform().tdir(vec3f_z); 
00376      return vec3f_z;
00377    }
00378 
00379    ///@}
00380    /////////////////////////////////////////////////////////////
00381 
00382    ////////////////////////////////////////////////////////////
00383    ///@name Mouse Events
00384    ///@{
00385    virtual bool mouse(const MouseEvent &me);
00386    virtual bool move(const MouseMoveEvent &mme);
00387    ///@}
00388    ////////////////////////////////////////////////////////////
00389 
00390    ////////////////////////////////////////////////////////////
00391    ///@name Tumble
00392    ///  Update speed amount
00393    ///@{
00394    virtual void tumble(float speed = 1);
00395    ///@}
00396    ////////////////////////////////////////////////////////////
00397 
00398 #ifdef KONG
00399    ////////////////////////////////////////////////////////////
00400    /// Pack/unpack details for sending the important data values 
00401    /// in a camera over the wire.
00402    unsigned int packSize(void);   // How big of a buffer do we need?
00403    void pack(KokoBuffer &kbuf, bool reset=true);   // Pack the manip up.
00404    void unpack(KokoBuffer &kbuf, bool reset=true); // Unpack into manip.
00405    void print(void); 
00406 #endif
00407 
00408 
00409    ////////////////////////////////////////////////////////////
00410    /// Serialization.
00411    /// write.
00412    virtual bool serialize(std::ostream &os, const std::string indent = std::string(""));
00413    /// read.
00414    virtual bool unserialize(std::istream &is);
00415    /// serialize the data parts of this guy for momentos & transmission
00416    virtual bool serialData(std::ostream &os, const std::string indent = std::string(""));
00417    virtual bool unserialData(std::istream &is);
00418 
00419 
00420 
00421 protected:
00422 
00423    void   updateMatrix();
00424    mat4f  buildMatrix() const;
00425 
00426    ////////////////////////////////////////////////////////////
00427    // Protected data
00428 
00429    float                  _rad;
00430    float                  _userRad;
00431    vec3f                  _center;
00432    mat4f                  _baked;
00433 
00434    mat4f _om, _oinv; /// eventually we could nuke these, they are just cached
00435 
00436    quatf _currquat;
00437    quatf _objtrackquat; /// nuke this!!
00438 
00439    BaseManipSP _parent;   ///< who is above us in the transform chain?
00440 };
00441 
00442 typedef SmartPtr<Manip>     ManipSP;
00443 
00444 
00445 } //end namespace gutz
00446 
00447 
00448 #endif
00449 

Send questions, comments, and bug reports to:
jmk