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 ¢er); 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