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

Camera.cpp

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.cpp
00017 //Joe Kniss
00018 
00019 #pragma warning(disable:4786) //dissable stl identifier too long warnings
00020 
00021 #include "Camera.h"
00022 #include <iostream>
00023 #include <math.h>
00024 #include <serialize/SerializeUtil.h>
00025 #include "../eventGutz/mouseEvent.h"
00026 
00027 #ifdef KONG
00028 #include <KokoBuffer.h>
00029 #endif
00030 
00031 #ifndef M_PI
00032 #define M_PI 3.141592654f
00033 #endif
00034 
00035 #define m_PI 3.141592654f
00036 
00037 
00038 using namespace gutz;
00039 using namespace std;
00040 
00041 //=========================================================================
00042 //  Construction / Destruction
00043 //=========================================================================
00044 /// Construtor intiallizes class reasonably, but needs window dimensions. 
00045 ///
00046 /// Intiallized values: Near Clip = 1.0, Far Clip = 100.0, Win size = (0,0),
00047 /// Camera Matrix = identity, Object Matrix = identity, Eye pos = (0,0,20),
00048 /// Lookat = (0,0,0), Up = (0,1,0), Frustum = (-1,1,-1,1), 
00049 /// Left Mouse = Object rotation, Right mouse = Dolly
00050 ///
00051 Camera::Camera()
00052 :   BaseManip(),
00053     _clips(1.0f, 1000.0f),
00054     _screen(0,0),
00055     _cm(mat4f_id),
00056     _pm(mat4f_id),
00057     _eyePos(0,0,20),
00058     _lookat(0,0,0),
00059     _upvec(0,1,0),
00060     _camtrackquat(0,0,0,1),
00061     _swivtrackquat(0,0,0,1),
00062     _camquat(0,0,0,1),
00063     _ortho(false)
00064 {
00065 
00066    // Default setup for camera =
00067    //_keymap[GUTZ_LEFT_MOUSE]   = CAM_ROT;
00068    //_speedmap[GUTZ_LEFT_MOUSE] = 1.0;
00069 
00070    //_keymap[GUTZ_RIGHT_MOUSE] = CAM_DOLLY;
00071    //_speedmap[GUTZ_RIGHT_MOUSE] = 0.02f;
00072 
00073    _setViewMatrix(look_at(_eyePos, _lookat, _upvec));
00074    setFrustum(-1, 1, -1, 1);
00075 
00076 }
00077 
00078 Camera::Camera(const Camera &cam)
00079 :
00080    BaseManip(cam),
00081    _clips(cam._clips),
00082    _screen(cam._screen),
00083    _cm(cam._cm),
00084    _pm(cam._pm),
00085    _eyePos(cam._eyePos),
00086    _lookat(cam._lookat),
00087    _upvec(cam._upvec),
00088    _camtrackquat(cam._camtrackquat),
00089    _swivtrackquat(cam._swivtrackquat),
00090    _camquat(cam._camquat),
00091    _ortho(cam._ortho),
00092    _keymap(cam._keymap),
00093    _speedmap(cam._speedmap)
00094 {
00095 
00096 }
00097 
00098 
00099 Camera::~Camera()
00100 {
00101 
00102 }
00103 
00104 
00105 //=========================================================================
00106 //  Get Event
00107 //=========================================================================
00108 unsigned int  Camera::getEvent(const MouseEvent &me) const
00109 {
00110    if(!me.isButtonDown()) return 0;
00111    return _keymap[me.getButton()];
00112 }
00113 
00114 //=========================================================================
00115 //  Get Speed
00116 //=========================================================================
00117 float         Camera::getSpeed(const MouseEvent &me) const
00118 {
00119    return _speedmap[me.getButton()];
00120 }
00121 
00122 
00123 //=========================================================================
00124 //  Set Matricies
00125 //=========================================================================
00126 
00127 /// get the viewport matrix
00128 mat4f Camera::getViewportMatrix() const
00129 {
00130    return mat4f(_screen[0]/2.0f, 0, 0, 0, 
00131                 0, _screen[1]/2.0f, 0, 0,
00132                 0, 0, .5, 0,
00133                 _screen[0]/2.0f, 
00134                 _screen[1]/2.0f,
00135                 .5, 1);
00136 }
00137 
00138 mat4f Camera::getInvViewportMatrix() const
00139 {
00140    return mat4f(2.0f/_screen[0], 0, 0, 0,
00141                 0, 2.0f/_screen[1], 0, 0,
00142                 0, 0, 2.0f, 0,
00143                 -1, -1, -1, 1);
00144 }
00145 
00146 /// external set projection
00147 void Camera::setProjectMatrix(const mat4f &m)
00148 {
00149    _setProjectMatrix(m);
00150 }
00151 
00152 /// internal set projection
00153 void Camera::_setProjectMatrix(const mat4f &m)
00154 {
00155    _pm = m;
00156    _pinv = _pm.inv();
00157 }
00158 
00159 /// external set view, takes a guess at eye/at/up but probably a bad one
00160 void Camera::setViewMatrix(const mat4f &m)
00161 {
00162    _setViewMatrix(m);
00163    _eyePos = -vec3f( m[12], m[13], m[14]);
00164    _upvec  = vec3f(  m[4],  m[5],  m[6]);
00165    _lookat = vec3f(  m[8],  m[9],  m[10]) + _eyePos;
00166    _camquat.set(_cm.rot());
00167 }
00168 
00169 /// internal set view
00170 void Camera::_setViewMatrix(const mat4f &m)
00171 {
00172    _cm = m;
00173    _cinv = _cm.inv();
00174 }
00175 
00176 
00177 
00178 ////////////////////////////////////////////////////////////
00179 // Serialization.
00180 // write.
00181 const string DATA_STR("Data{");
00182 const string END_SECTION_STR("\n}\n");
00183 const string EVENT_MAP_STR("EventMap{");
00184 const string PARAM_MAP_STR("ParamMap{");
00185 
00186 //=========================================================================
00187 //  Uber Serialize
00188 //=========================================================================
00189 bool Camera::serialize(std::ostream &os, const std::string indent)
00190 {
00191    string ind = indent;
00192    ind += "   ";
00193 
00194    serialState(os,indent);
00195 
00196    /// serial data
00197    os << indent << DATA_STR << " \n";
00198    serialData(os, ind);
00199    os << indent << END_SECTION_STR;
00200 
00201    bool status = false;
00202 
00203    return status;
00204 
00205 }
00206 
00207 //=========================================================================
00208 //  Uber Unserialize
00209 //=========================================================================
00210 // read.
00211 bool Camera::unserialize(std::istream &is)
00212 {
00213    string tstr;
00214 
00215    bool status = false;
00216 
00217    unserialState(is);
00218 
00219    /// unserial data
00220    is >> tstr;
00221    if(unserialKeyCheck(DATA_STR, tstr, "baseManip, data")) return true;   
00222    if(unserialData(is)) return true;
00223    is >> tstr;
00224    if(unserialKeyCheck(END_SECTION_STR,tstr,"baseManip, data")) return true;
00225 
00226    status = status || is.eof() || is.fail();
00227    return status;
00228 }
00229 
00230 //=========================================================================
00231 //  Serialize State
00232 //=========================================================================
00233 bool Camera::serialState(std::ostream &os, const std::string indent)
00234 {
00235    string ind = indent;
00236    ind += "   ";
00237    
00238    /// serial event map
00239    os << indent << EVENT_MAP_STR << " \n";
00240    serialEventMap(os, ind);
00241    os << indent << END_SECTION_STR;
00242 
00243    /// serial param map
00244    os << indent << PARAM_MAP_STR << " \n";
00245    serialParamMap(os, ind);
00246    os << indent << END_SECTION_STR;
00247 
00248    return false;
00249 }
00250 
00251 //=========================================================================
00252 //  UnSerialize State
00253 //=========================================================================
00254 bool Camera::unserialState(std::istream &is)
00255 {
00256    string tstr;
00257    
00258    /// unserial event map
00259    is >> tstr;
00260    if(unserialKeyCheck(EVENT_MAP_STR, tstr, "BaseManip, event map")) return true;
00261    if(unserialEventMap(is)) return true;
00262    is >> tstr;
00263    if(unserialKeyCheck(END_SECTION_STR, tstr, "BaseManip, event map")) return true;
00264 
00265    /// unserial param map
00266    is >> tstr;
00267    if(unserialKeyCheck(PARAM_MAP_STR, tstr, "BaseManip, param map")) return true;
00268    if(unserialParamMap(is)) return true;
00269    is >> tstr;
00270    if(unserialKeyCheck(END_SECTION_STR, tstr, "BaseManip, param map")) return true;
00271 
00272    return is.eof() || is.fail();   
00273 }
00274 
00275 //=========================================================================
00276 //  Serialize Event Map
00277 //=========================================================================
00278 bool Camera::serialEventMap(std::ostream &os, const std::string indent)
00279 {
00280    os << indent << _keymap.size() << " \n";
00281    EventKeyMap::iterator mi = _keymap.begin();
00282    while(mi != _keymap.end())
00283    {
00284       os << indent << (*mi).first << " " << (*mi).second << " ";
00285       ++mi;
00286    }
00287    return false;
00288 }
00289 
00290 //=========================================================================
00291 //  Serialize Param Map
00292 //=========================================================================
00293 bool Camera::serialParamMap(std::ostream &os, const std::string indent)
00294 {
00295    os << indent << _keymap.size() << " \n";
00296    EventParamMap::iterator mi = _speedmap.begin();
00297    while(mi != _speedmap.end())
00298    {
00299       os << indent << (*mi).first << " " << (*mi).second << " ";
00300       ++mi;
00301    }
00302    return false;
00303 }
00304 
00305 //=========================================================================
00306 //  Unserialize Event Map
00307 //=========================================================================
00308 bool Camera::unserialEventMap(std::istream &is)
00309 {
00310    _keymap = EventKeyMap();
00311    
00312    int keymapsize;
00313    is >> keymapsize;
00314    for(int i=0; i<keymapsize; ++i)
00315    {
00316       EventKeyMap::value_type mi;
00317       int key, value;
00318       is >> key;
00319       is >> value;
00320       _keymap[key] = value;
00321    }  
00322    return is.eof() || is.fail();
00323 }
00324 
00325 //=========================================================================
00326 //  Unserialize Param Map
00327 //=========================================================================
00328 bool Camera::unserialParamMap(std::istream &is)
00329 {
00330    _speedmap = EventParamMap();
00331    
00332    int parammapsize;
00333    is >> parammapsize;
00334    for(int i=0; i<parammapsize; ++i)
00335    {
00336       EventParamMap::value_type mi;
00337       int key;
00338       float value;
00339       is >> key;
00340       is >> value;
00341       _speedmap[key] = value;
00342    }  
00343    return is.eof() || is.fail();
00344 }
00345 
00346 //=========================================================================
00347 //  Serialize Data
00348 //=========================================================================
00349 // these, the frustum (baseManip), and clips (baseManip) are all we 
00350 // really need to save.
00351 const string EYE_POS_STR("EyePos: ");
00352 const string LOOK_AT_STR("LookAt: ");
00353 const string UP_VEC_STR("UpVector: ");
00354 
00355 bool Camera::serialData(std::ostream &os, const std::string indent)
00356 {
00357    BaseManip::serialData(os,indent);
00358    
00359    os << indent << EYE_POS_STR << _eyePos << "\n";
00360    os << indent << LOOK_AT_STR << _lookat << "\n";
00361    os << indent << UP_VEC_STR  << _upvec  << "\n";
00362    
00363    return false;
00364 }
00365 
00366 //=========================================================================
00367 //  UnSerialize Data
00368 //=========================================================================
00369 bool Camera::unserialData(std::istream &is)
00370 {
00371    if(BaseManip::unserialData(is)) return true;
00372    
00373    string tstr;
00374    
00375    /// Eye
00376    is >> tstr;
00377    if(unserialKeyCheck(EYE_POS_STR, tstr, "Camera, eyepos")) return true;
00378    is >> _eyePos;
00379    
00380    /// AT
00381    is >> tstr;
00382    if(unserialKeyCheck(LOOK_AT_STR, tstr, "Camera, lookat")) return true;
00383    is >> _lookat;
00384 
00385    /// Up
00386    is >> tstr;
00387    if(unserialKeyCheck(UP_VEC_STR, tstr, "Camera, upvector")) return true;
00388    is >> _upvec;
00389 
00390    setEyePos(_eyePos);
00391    setLookAt(_lookat);
00392    setUpVec(_upvec);
00393    setFrustum(_frustum[FRUST_LEFT], _frustum[FRUST_RIGHT], 
00394               _frustum[FRUST_BOTTOM], _frustum[FRUST_TOP]);
00395 
00396    return is.eof() || is.fail();
00397 
00398 }
00399 
00400 
00401 //=========================================================================
00402 //  Clipping planes
00403 //=========================================================================
00404 
00405 void  Camera::setClips(float nearClip, float farClip)
00406 {
00407    _clips = vec2f(nearClip, farClip);
00408    setFrustum(_frustum[FRUST_LEFT],   _frustum[FRUST_RIGHT],
00409               _frustum[FRUST_BOTTOM], _frustum[FRUST_TOP]);
00410 }
00411 
00412 float Camera::getNearClip() const 
00413 {
00414    return _clips[0];
00415 }
00416 
00417 float Camera::getFarClip() const
00418 {
00419    return _clips[1];
00420 }
00421 
00422 //=========================================================================
00423 //  Screen Size
00424 //=========================================================================
00425 void  Camera::setScreen(unsigned int x, unsigned int y)
00426 {
00427    _screen = vec2ui(x,y);
00428 }
00429 
00430 //=========================================================================
00431 //  The LOOK AT : Eye Position, look at, up vector
00432 //=========================================================================
00433 void Camera::setEyePos(vec3f eyePos)
00434 {
00435    _eyePos=eyePos;
00436    _setViewMatrix( look_at(_eyePos, _lookat, _upvec) );
00437 }
00438 
00439 void Camera::setLookAt(vec3f lookat)
00440 {
00441    _lookat = lookat;
00442    _setViewMatrix( look_at(_eyePos, _lookat, _upvec) );
00443 }
00444 
00445 void Camera::setUpVec(vec3f upvec)
00446 {
00447    _upvec = upvec;
00448    _setViewMatrix( look_at(_eyePos, _lookat, _upvec) );
00449 }
00450 
00451 //=========================================================================
00452 //=========================================================================
00453 //  Event Handling
00454 //=========================================================================
00455 //=========================================================================
00456 
00457 //=========================================================================
00458 //  Mouse up/down
00459 //=========================================================================
00460 bool Camera::mouse(const gutz::MouseEvent &me)
00461 {
00462    if( (_currentMode = getEvent(me)) == 0) {
00463      return false;
00464    }
00465 
00466    _currentSpeed  = getSpeed(me);
00467    _camtrackquat  = quatf_id;
00468    _swivtrackquat = quatf_id;
00469    _lastEyePos    = _eyePos;
00470    _lastLookat    = _lookat;
00471 
00472    if(isMouse(me.getButton()))
00473    {    
00474       return true;
00475    }
00476 
00477    else if(isArrow(me.getButton()))
00478    {
00479      vec3f pos(_screen[0]/2.0f, _screen[1]/2.0f, 0.0f);
00480      vec3f last(_screen[0]/2.0f, _screen[1]/2.0f, 0.0f);
00481       MouseMoveEvent mme(pos, last,
00482                          me.isButtonDown(), me.getButton());
00483 
00484       if(me.getButton() & GUTZ_UP_ARROW)
00485       {
00486          mme.setPos( mme.getPos() - vec3f_y );
00487       }
00488       else if(me.getButton() & GUTZ_DOWN_ARROW)
00489       {
00490          mme.setPos( mme.getPos() + vec3f_y );
00491       }
00492       else if(me.getButton() & GUTZ_RIGHT_ARROW)
00493       {
00494          mme.setPos( mme.getPos() + vec3f_x );
00495       }
00496       else if(me.getButton() & GUTZ_LEFT_ARROW)
00497       {
00498          mme.setPos( mme.getPos() - vec3f_x );
00499       }
00500 
00501       if( handleCamera(mme) )
00502       {
00503          _pinv = _pm.inv();
00504          _cinv = _cm.inv();
00505       }
00506    }
00507 
00508    return false;
00509 }
00510 
00511 //=========================================================================
00512 //  Move mouse
00513 //=========================================================================
00514 bool Camera::move(const gutz::MouseMoveEvent &mme)
00515 {
00516    if( handleCamera(mme) )
00517    {
00518       _pinv = _pm.inv();
00519       _cinv = _cm.inv();
00520       return true;
00521    }
00522    return false;
00523 }
00524 
00525 //=========================================================================
00526 //  Set Perspective
00527 //=========================================================================
00528 void Camera::setPerspective(float fov)
00529 {
00530    _ortho = false;
00531    _frustum[FRUST_TOP]    = _clips[0] * tanf(fov * m_PI/180.0f * 0.5f);
00532    _frustum[FRUST_BOTTOM] = -_frustum[FRUST_TOP];  
00533    _frustum[FRUST_LEFT]   = _frustum[FRUST_BOTTOM] * _screen[0]/(float)_screen[1];
00534    _frustum[FRUST_RIGHT]  = _frustum[FRUST_TOP] * _screen[0]/(float)_screen[1];
00535 
00536    _setProjectMatrix( frustum(_frustum[FRUST_LEFT],   _frustum[FRUST_RIGHT], 
00537                               _frustum[FRUST_BOTTOM], _frustum[FRUST_TOP], 
00538                               _clips[0], _clips[1]) );
00539 }
00540 
00541 //=========================================================================
00542 //  Set Frustum
00543 //=========================================================================
00544 void Camera::setFrustum(float left, float right, float bottom, float top)
00545 {
00546    _ortho = false;
00547    _frustum[FRUST_LEFT]   = left;
00548    _frustum[FRUST_RIGHT]  = right;
00549    _frustum[FRUST_BOTTOM] = bottom;
00550    _frustum[FRUST_TOP]    = top;
00551 
00552    _setProjectMatrix( frustum(left, right, bottom, top, _clips[0], _clips[1]) );
00553 
00554 }
00555 
00556 void Camera::setOrtho(float left, float right, float bottom, float top)
00557 {
00558    _ortho = true;
00559    _frustum[FRUST_LEFT]   = left;
00560    _frustum[FRUST_RIGHT]  = right;
00561    _frustum[FRUST_BOTTOM] = bottom;
00562    _frustum[FRUST_TOP]    = top;
00563 
00564    _setProjectMatrix( ortho(left,right,bottom,top,_clips[0],_clips[1]) );
00565 }
00566 
00567 
00568 //=========================================================================
00569 //  Tumble
00570 //=========================================================================
00571 void Camera::tumble(float speed)
00572 {
00573    if(!_tumble) return;
00574    if(1 >= _lastd) return;
00575 
00576    if((quatf_id != _camtrackquat) && (CAM_ROT != _currentMode))
00577    {
00578       //reset the track quaternion to the right speed
00579       float thet = _camtrackquat[3];
00580       thet = acos(thet);
00581       vec3f axis(_camtrackquat[0]/sin(thet),_camtrackquat[1]/sin(thet),_camtrackquat[2]/sin(thet));
00582       thet*=speed*2;
00583       quatf track(thet, axis);
00584 
00585       _camquat = _camquat.mult(track);//_camquatSav;
00586 
00587       mat3f tmpm3(_camquat);          //camera basis matrix
00588       _upvec = vec3f(tmpm3[3], tmpm3[4], tmpm3[5]); //up
00589       vec3f tmpv2(tmpm3[6], tmpm3[7], tmpm3[8]);  //Z
00590       vec3f tmpv = _lastEyePos - _lookat;                 //-view dir
00591       float tmpf = tmpv.norm();                           //lookat dist
00592       tmpv2  *= tmpf;                               //new view dir
00593       _eyePos = tmpv2 + _lookat;                    //new eye point
00594 
00595       _setViewMatrix( look_at(_eyePos, _lookat, _upvec) );
00596    }
00597 
00598    if((quatf_id != _swivtrackquat) && (CAM_SWIVEL != _currentMode))
00599    {
00600       //reset the track quaternion to the right speed
00601       float thet = _swivtrackquat[3];
00602       thet = acos(thet);
00603       vec3f axis(_swivtrackquat[0]/sin(thet),_swivtrackquat[1]/sin(thet),_swivtrackquat[2]/sin(thet));
00604       thet*=speed*2;
00605       quatf track(thet, axis);
00606 
00607       _camquat = _camquat.mult(track);//_camquatSav;
00608 
00609       mat3f tmpm3(_camquat);          //camera basis matrix
00610       _upvec = vec3f(tmpm3[3], tmpm3[4], tmpm3[5]); //up
00611       vec3f tmpv2(tmpm3[6], tmpm3[7], tmpm3[8]);  //Z
00612 
00613       vec3f tmpv = _lastLookat - _eyePos;                 //-view dir
00614       float tmpf = tmpv.norm();                           //lookat dist
00615       tmpv2  *= -tmpf;                               //new view dir
00616       _lookat = tmpv2 + _eyePos;                    //new lookat point
00617 
00618       _setViewMatrix( look_at( _eyePos, _lookat, _upvec) );
00619    }
00620 }
00621 
00622 //=========================================================================
00623 //  Handle Camera
00624 //=========================================================================
00625 bool Camera::handleCamera(const gutz::MouseMoveEvent &mme)
00626 {
00627    if(getEvent(mme) == CAM_MODE_NONE) return false;
00628 
00629    bool ret = true;
00630 
00631    switch(getEvent(mme))
00632    {
00633       //--------------------------------------------------------
00634    case CAM_ROT:   //rotate around lookat point
00635       cameraRot(mme);
00636       break;
00637       //--------------------------------------------------------
00638    case CAM_ZOOM:
00639       cameraZoom(mme);
00640       break;
00641       //--------------------------------------------------------
00642    case CAM_DOLLY:
00643       cameraTrans(mme, vec3f_zero, vec3f_z);
00644       break;
00645       //--------------------------------------------------------
00646    case CAM_TRANS_XY:
00647       cameraTrans(mme, vec3f_x, vec3f_y);
00648       break;
00649       //--------------------------------------------------------
00650    case CAM_TRANS_XZ:
00651       cameraTrans(mme, vec3f_x, vec3f_z);
00652       break;
00653       //--------------------------------------------------------
00654    case CAM_TRANS_ZY:
00655       cameraTrans(mme, vec3f_z, vec3f_y);
00656       break;
00657       //--------------------------------------------------------
00658    case CAM_ROLL:
00659       //rotate about cameras z axis
00660       cameraRotAxis(mme, vec3f_z, vec3f_zero);
00661       break;
00662       //--------------------------------------------------------
00663    case CAM_PITCH:
00664       //rotate about cameras x axis
00665       cameraRotAxis(mme, vec3f_zero, vec3f_x);
00666       break;
00667       //--------------------------------------------------------
00668    case CAM_YAW:
00669       // rotate about y axis
00670       cameraRotAxis(mme, vec3f_neg_y, vec3f_zero);
00671       break;  
00672       //--------------------------------------------------------
00673    case CAM_SWIVEL:
00674       cameraSwivel(mme);
00675       break;
00676    default:
00677       ret = false;
00678       break;
00679    }
00680 
00681    /// last delta, for deciding if we should tumble
00682    _lastd = g_max( g_abs(mme.getDel().x), g_abs(mme.getDel().y) );
00683 
00684    return ret;
00685 }
00686 
00687 
00688 //=========================================================================
00689 //  Interactor functions
00690 //=========================================================================
00691 
00692 
00693 void Camera::cameraZoom(const gutz::MouseMoveEvent &mme)
00694 {
00695    /// scale is equal to the total move (dx + dy)
00696    float scale = 1 + (   ( mme.getDel().x  )/float(_screen[0])  
00697                        + ( -mme.getDel().y )/float(_screen[1]) )/2.0f;
00698    /// compute current frustum's width
00699    vec2f fwidth(_frustum[FRUST_RIGHT] - _frustum[FRUST_LEFT],
00700                 _frustum[FRUST_TOP] - _frustum[FRUST_BOTTOM]);
00701    /// compute the center of current frustum
00702    vec2f fcent(_frustum[FRUST_LEFT]   + fwidth.x/2.0f,
00703                _frustum[FRUST_BOTTOM] + fwidth.y/2.0f );
00704    /// compute new width (old width * scale) and divide by two
00705    vec2f fwidthN = fwidth * scale/2.0f;
00706    
00707    /// orthographic projection frustum... or:
00708    if(_ortho)
00709    {
00710       setOrtho(fcent.x - fwidthN.x, fcent.x + fwidthN.x, 
00711                fcent.y - fwidthN.y, fcent.y + fwidthN.y);
00712    }
00713    else /// perspective frustum
00714    {
00715       setFrustum(fcent.x - fwidthN.x, fcent.x + fwidthN.x, 
00716                  fcent.y - fwidthN.y, fcent.y + fwidthN.y);
00717    }
00718 
00719 }
00720 
00721 //camera rotate ===========================================================
00722 
00723 void Camera::cameraRot(const gutz::MouseMoveEvent &mme)
00724 {
00725    /// scale and bias pick points (on screen) to (-1,1) range
00726    ///  pt = (2*pt - sz)/sz
00727    vec2f pt1(( 2.0f * mme.getLast().x - _screen[0]) / (float)_screen[0], 
00728              ( _screen[1] - 2.0f * mme.getLast().y) / (float)_screen[1]);
00729    vec2f pt2(( 2.0f * mme.getPos().x  - _screen[0]) / (float)_screen[0],
00730              ( _screen[1] - 2.0f * mme.getPos().y ) / (float)_screen[1]);
00731 
00732    quatf tmpquat = trackball(pt1, pt2, .8f).conj(); //trackball quaternion
00733    _camtrackquat = tmpquat;                         //tumble amount
00734    _camquat = _camquat.mult(tmpquat);               //_camquatSav;
00735 
00736    const mat3f tmpm3(_camquat);                     //camera basis matrix
00737    _upvec = vec3f(tmpm3[3], tmpm3[4], tmpm3[5]);    //upvector changed!
00738    const vec3f zvec(tmpm3[6], tmpm3[7], tmpm3[8]);  //Z (direction eye<-lookat)
00739    _eyePos = _lookat + zvec * getFocalLength();     //new eye point
00740 
00741    _setViewMatrix( look_at( _eyePos, _lookat, _upvec) );
00742 }
00743 
00744 //camera translate ========================================================
00745 
00746 void Camera::cameraTrans(const gutz::MouseMoveEvent &mme, 
00747                          vec3f dxAxis, vec3f dyAxis)
00748 {
00749 
00750    quatf cam_rot(_cm.rot());
00751    cam_rot = cam_rot.conj();
00752    vec3f vecdx(cam_rot.rot(dxAxis));
00753    vec3f vecdy(cam_rot.rot(dyAxis));
00754 
00755    vecdx *= mme.getDel(). x * _currentSpeed;
00756    vecdy *= -mme.getDel().y * _currentSpeed;
00757 
00758    _eyePos = _eyePos + vecdx + vecdy;      //move eye
00759    _lookat = _lookat + vecdx + vecdy;      //move lookat
00760 
00761    _setViewMatrix( look_at(_eyePos, _lookat, _upvec) );//update camera
00762 
00763 }
00764 
00765 //rotate camera about axis ===============================================
00766 
00767 void Camera::cameraRotAxis(const gutz::MouseMoveEvent &mme, 
00768                            vec3f dxAxis, vec3f dyAxis)
00769 {
00770    if(vec3f_zero != dxAxis)
00771    {
00772       dxAxis.normalize();
00773       quatf dxrot((mme.getDel().x*_currentSpeed/180.0f) * float(M_PI), dxAxis);
00774       _camquat = _camquat.mult(dxrot);
00775    }
00776    if(vec3f_zero != dyAxis)
00777    {
00778       dyAxis.normalize();
00779       quatf dyrot((-mme.getDel().y*_currentSpeed/180.0f) * float(M_PI), dyAxis);
00780       _camquat = _camquat.mult(dyrot);
00781    }
00782 
00783    mat3f basis(_camquat);                              //get basis
00784    _upvec = vec3f(basis[3], basis[4], basis[5]);       //up
00785    vec3f    zaxis(basis[6], basis[7], basis[8]);       //Z
00786    float zdist = (_lookat - _eyePos).norm();           //lookat dist
00787    _lookat = _eyePos - zaxis * zdist;                  //lookat
00788    _setViewMatrix( look_at(_eyePos, _lookat, _upvec) );             //update camera
00789 
00790 }
00791 
00792 //camera swivel =========================================================
00793 
00794 void Camera::cameraSwivel(const gutz::MouseMoveEvent &mme)
00795 {
00796    vec2f pt1(( 2.0f * mme.getLast().x - _screen[0])  / (float)_screen[0], 
00797              ( _screen[1] - 2.0f * mme.getLast().y ) / (float)_screen[1]);
00798    vec2f pt2(( 2.0f * mme.getPos().x - _screen[0])   / (float)_screen[0], 
00799              ( _screen[1] - 2.0f * mme.getPos().y)  / (float)_screen[1]);
00800 
00801    quatf tmpquat = trackball(pt1, pt2, 1.8f);    
00802    tmpquat = tmpquat.conj();
00803    _swivtrackquat = tmpquat;                     //tumble amount
00804    _camquat = _camquat.mult(tmpquat);   
00805 
00806    mat3f basis(_camquat);                        //camera basis matrix
00807    _upvec = vec3f(basis[3], basis[4], basis[5]); //up
00808    vec3f    zaxis(basis[6], basis[7], basis[8]); //Z
00809 
00810    vec3f  vdir(_lastLookat - _eyePos);           //view dir
00811    float  dist = vdir.norm();                    //lookat dist
00812    zaxis  *= -dist;                              //new view dir
00813    _lookat = zaxis + _eyePos;                    //new lookat point
00814 
00815    _setViewMatrix( look_at( _eyePos, _lookat, _upvec) );
00816 
00817 }
00818 
00819 #ifdef KONG
00820 // camera pack and unpack methods =======================================
00821 
00822 // ----------------
00823 // --- packSize ---
00824 // ----------------
00825 //
00826 unsigned int Camera::packSize(void)
00827 {
00828   // How big of a buffer do we need to make a packed version
00829   // of the camera?
00830   return( sizeof(vec2f) + sizeof(mat4f) * 2 + sizeof(vec3f) * 3);
00831 }
00832 
00833 // ------------
00834 // --- pack ---
00835 // ------------
00836 //
00837 void Camera::pack(KokoBuffer &kbuf, bool reset)
00838 {
00839   if (reset)
00840     kbuf.Pack();  // Put the buffer in pack mode. 
00841   kbuf.Pack((unsigned char *)&_clips,  sizeof(vec2f));      // clips
00842   kbuf.Pack((unsigned char *)&_cm,     sizeof(mat4f));      // camera matrix.
00843   kbuf.Pack((unsigned char *)&_pm,     sizeof(mat4f));      // proj. matrix.
00844   kbuf.Pack((unsigned char *)&_eyePos, sizeof(vec3f));      // eye position.
00845   kbuf.Pack((unsigned char *)&_lookat, sizeof(vec3f));      // look at point.
00846   kbuf.Pack((unsigned char *)&_upvec,  sizeof(vec3f));      // up vector. 
00847 }
00848 
00849 
00850 // --------------
00851 // --- unpack ---
00852 // --------------
00853 //
00854 void Camera::unpack(KokoBuffer &kbuf, bool reset) 
00855 {
00856   if (reset)
00857     kbuf.Unpack();  // Put the buffer in extraction mode.
00858   kbuf.Unpack((unsigned char *)&_clips,  sizeof(vec2f));     // clips
00859   kbuf.Unpack((unsigned char *)&_cm,     sizeof(mat4f));     // camera matrix.
00860   kbuf.Unpack((unsigned char *)&_pm,     sizeof(mat4f));     // proj. matrix.
00861   kbuf.Unpack((unsigned char *)&_eyePos, sizeof(vec3f));     // eye position.
00862   kbuf.Unpack((unsigned char *)&_lookat, sizeof(vec3f));     // look at point.
00863   kbuf.Unpack((unsigned char *)&_upvec,  sizeof(vec3f));     // up vector. 
00864   //look_at(_cm, _eyePos, _lookat, _upvec);
00865   _setViewMatrix(look_at(_eyePos, _lookat, _upvec));
00866   _camquat.set(_cm.rot());  
00867 }
00868 
00869 #endif

Send questions, comments, and bug reports to:
jmk