event_mouse_listener.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2000 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "std3d.h"
00025 
00026 #include "nel/3d/event_mouse_listener.h"
00027 #include "nel/misc/event_server.h"
00028 #include "nel/3d/camera.h"
00029 #include "nel/misc/time_nl.h"
00030 #include "nel/misc/quat.h"
00031 
00032 using namespace NLMISC;
00033 
00034 namespace NL3D
00035 {
00036 
00037 
00038 CEvent3dMouseListener::CEvent3dMouseListener() :  _CurrentModelRotationAxis(zAxis)
00039                                                   ,_XModelTranslateEnabled(true)
00040                                                   ,_YModelTranslateEnabled(true)
00041                                                   ,_ZModelTranslateEnabled(true)
00042 {
00043     _Matrix.identity();
00044     _ModelMatrix.identity() ;
00045     _EnableModelMatrixEdition = false ;
00046     _HotSpot.set (0,0,0);
00047     _Viewport.initFullScreen();
00048     _Frustrum.init (2.f, 2.f, -1.f, 1.f);
00049     _MouseMode=nelStyle;
00050     setSpeed (10.f);
00051     _LastTime=CTime::getLocalTime ();
00052     _TranslateXYInWorld= false;
00053 }
00054 
00055 
00056 
00057 void CEvent3dMouseListener::enableModelTranslationAxis(TAxis axis, bool enabled)
00058 {
00059     switch (axis)
00060     {
00061         case xAxis: _XModelTranslateEnabled = enabled ; break ;
00062         case yAxis: _YModelTranslateEnabled = enabled ; break ;
00063         case zAxis: _ZModelTranslateEnabled = enabled ; break ;
00064     }
00065 }
00066 
00067 bool CEvent3dMouseListener::isModelTranslationEnabled(TAxis axis)
00068 {
00069     switch (axis)
00070     {
00071         case xAxis: return _XModelTranslateEnabled ; break ;
00072         case yAxis: return _YModelTranslateEnabled ; break ;
00073         case zAxis: return _ZModelTranslateEnabled ; break ;
00074         default: return false ; break ;
00075     }
00076 }
00077 
00078 
00079 void CEvent3dMouseListener::truncateVect(CVector &v)
00080 {
00081     if (!_XModelTranslateEnabled) v.x = 0.f ;
00082     if (!_YModelTranslateEnabled) v.y = 0.f ;
00083     if (!_ZModelTranslateEnabled) v.z = 0.f ;
00084 }
00085 
00086 
00087 void CEvent3dMouseListener::operator ()(const CEvent& event)
00088 {
00089     CEventMouse* mouseEvent=(CEventMouse*)&event;
00090     if (event==EventMouseMoveId)
00091     {
00092         bool bRotate=false;
00093         bool bTranslateXY=false;
00094         bool bTranslateZ=false;
00095         bool bZoom=false;
00096 
00097 
00098         // Rotate Axis
00099         CVector axis;
00100 
00101         if (_MouseMode==nelStyle)
00102         {
00103             bRotate=(mouseEvent->Button==(ctrlButton|rightButton));
00104             bTranslateXY=(mouseEvent->Button==(ctrlButton|leftButton));
00105             bTranslateZ=(mouseEvent->Button==(ctrlButton|shiftButton|leftButton));
00106             bZoom=(mouseEvent->Button==(altButton|leftButton));
00107             axis=_HotSpot;
00108         }
00109         else if (_MouseMode==edit3d)
00110         {
00111             bRotate=(mouseEvent->Button==(altButton|middleButton)) || (mouseEvent->Button==(altButton|leftButton));
00112             bTranslateXY=(mouseEvent->Button==(ctrlButton|leftButton)) || (mouseEvent->Button==middleButton);
00113             bTranslateZ=(mouseEvent->Button==(ctrlButton|shiftButton|leftButton)) || (mouseEvent->Button==(ctrlButton|middleButton));
00114             bZoom=(mouseEvent->Button==(shiftButton|leftButton)) || (mouseEvent->Button==(ctrlButton|altButton|middleButton));
00115             axis=_HotSpot;
00116         }
00117         else // if (_MouseMode==firstPerson)
00118         {
00119             bRotate=(mouseEvent->Button&leftButton)!=0;
00120             bTranslateXY=false;
00121             bTranslateZ=false;
00122             bZoom=false;
00123             axis=_Matrix.getPos();
00124         }
00125 
00126         if (bRotate)
00127         {
00128             if (!_EnableModelMatrixEdition)
00129             {
00130                 // First in the hotSpot
00131                 CMatrix comeFromHotSpot=_Matrix;
00132                 comeFromHotSpot.setPos (axis);
00133 
00134                 // Then turn along the Z axis with X mouse
00135                 CMatrix turnZ;
00136                 turnZ.identity();
00137                 turnZ.rotateZ ((float) Pi*2.f*(_X-mouseEvent->X));
00138 
00139                 // Then turn along the X axis with Y mouse
00140                 CMatrix turnX;
00141                 turnX.identity();
00142                 turnX.rotateX ((float) Pi*2.f*(mouseEvent->Y-_Y));
00143 
00144                 // Then come back from hotspot
00145                 CMatrix goToHotSpot=comeFromHotSpot;
00146                 goToHotSpot.invert();
00147 
00148                 // Make the matrix
00149                 CMatrix negPivot, Pivot;
00150                 negPivot.identity();
00151                 negPivot.setPos (-axis);
00152                 Pivot.identity();
00153                 Pivot.setPos (axis);
00154 
00155                 // Make this transformation \\//
00156                 //_Matrix=Pivot*turnZ*negPivot*comeFromHotSpot*turnX*goToHotSpot*_Matrix;
00157                 Pivot*=turnZ;
00158                 Pivot*=negPivot;
00159                 Pivot*=comeFromHotSpot;
00160                 Pivot*=turnX;
00161                 Pivot*=goToHotSpot;
00162 
00163 
00164                 Pivot*=_Matrix;
00165                 _Matrix=Pivot;
00166                 // Normalize, too much transformation could give an ugly matrix..
00167                 _Matrix.normalize (CMatrix::XYZ);
00168 
00169             }
00170             else
00171             {
00172                 CVector pos = _ModelMatrix.getPos() ;
00173                 NLMISC::CQuat r ;
00174                 switch (_CurrentModelRotationAxis)
00175                 {
00176                     case xAxis : r = CQuat(CAngleAxis(_ModelMatrix.getI(), (float) Pi*2.f*(_X-mouseEvent->X))) ; break ;
00177                     case yAxis : r = CQuat(CAngleAxis(_ModelMatrix.getJ(), (float) Pi*2.f*(_X-mouseEvent->X))) ; break ;
00178                     case zAxis : r = CQuat(CAngleAxis(_ModelMatrix.getK(), (float) Pi*2.f*(_X-mouseEvent->X))) ; break ;
00179                 } ;
00180 
00181 
00182                 CMatrix rm ;
00183                 rm.rotate(r) ;
00184 
00185                 _ModelMatrix = rm * _ModelMatrix ;
00186                 _ModelMatrix.setPos(pos) ;
00187 
00188                 _ModelMatrix.normalize (CMatrix::XYZ);
00189             }
00190         }
00191 
00192 
00193         if (bTranslateXY||bTranslateZ||bZoom)
00194         {
00195             // Move in plane
00196 
00197             CPlane plane;
00198 
00199             // For precision problem, do all the compute local to the hotspot/model.
00200             CVector     decal;
00201 
00202             // Plane of the hotspot
00203             if (! _EnableModelMatrixEdition)
00204             {
00205                 decal= axis;
00206             }
00207             else
00208             {
00209                 decal= _ModelMatrix.getPos();
00210             }
00211             // Choose plane to move on
00212             if (bTranslateXY && _TranslateXYInWorld)
00213             {
00214                 plane.make (CVector::K, CVector::Null);
00215             }
00216             else
00217             {
00218                 plane.make (_Matrix.getJ(), CVector::Null);
00219             }
00220 
00221 
00222             // Get ray from mouse point
00223             CMatrix     localViewMatrix= _Matrix;
00224             localViewMatrix.setPos(_Matrix.getPos() - decal);
00225             CVector localPoint1, localPoint2;
00226             CVector pos, dir;
00227             _Viewport.getRayWithPoint (_X, _Y, pos, dir, localViewMatrix, _Frustrum);
00228             localPoint1=plane.intersect (pos, pos+dir);
00229             _Viewport.getRayWithPoint (mouseEvent->X, mouseEvent->Y, pos, dir, localViewMatrix, _Frustrum);
00230             localPoint2=plane.intersect (pos, pos+dir);
00231 
00232             // Move the camera
00233             if (bTranslateXY)
00234             {
00235                 if (! _EnableModelMatrixEdition)
00236                 {
00237                     _Matrix.setPos(_Matrix.getPos()+localPoint1-localPoint2);
00238                 }
00239                 else
00240                 {
00241                     CVector dir =  - localPoint1 + localPoint2 ;
00242                     // transform the translation as needed.
00243                     dir= _ModelMatrixTransformMove * dir;
00244                     truncateVect(dir) ;
00245                     _ModelMatrix.setPos(_ModelMatrix.getPos()+dir);
00246                 }
00247             }
00248             else if (bTranslateZ)
00249             {
00250                 CVector vect=localPoint1-localPoint2;
00251                 if (! _EnableModelMatrixEdition)
00252                 {
00253                     _Matrix.setPos(_Matrix.getPos()+_Matrix.getK()*(vect.x+vect.y+vect.z));
00254                 }
00255                 else
00256                 {
00257                     CVector dir = _Matrix.getK()*(vect.x+vect.y+vect.z) ;
00258                     // transform the translation as needed.
00259                     dir= _ModelMatrixTransformMove * dir;
00260                     truncateVect(dir) ;
00261                     _ModelMatrix.setPos(_ModelMatrix.getPos()+dir);
00262                 }
00263             }
00264             else if (bZoom)
00265             {
00266                 CVector vect=localPoint1-localPoint2;
00267                 CVector direc=axis-_Matrix.getPos();
00268                 direc.normalize();
00269                 if (! _EnableModelMatrixEdition)
00270                 {
00271                     _Matrix.setPos(_Matrix.getPos()+direc*(vect.x+vect.y+vect.z));
00272                 }
00273                 else
00274                 {
00275                     // transform the translation as needed.
00276                     direc= _ModelMatrixTransformMove * direc;
00277                     direc.normalize();
00278                     _ModelMatrix.setPos(_ModelMatrix.getPos()+direc*(vect.x+vect.y+vect.z));
00279                 }
00280             }
00281         }
00282 
00283 
00284         // Update mouse position
00285         _X=mouseEvent->X;
00286         _Y=mouseEvent->Y;
00287     }
00288     else if (event==EventMouseDownId)
00289     {
00290         // Update mouse position
00291         _X=mouseEvent->X;
00292         _Y=mouseEvent->Y;
00293     }
00294     else if (event==EventMouseUpId)
00295     {
00296         // Update mouse position
00297         _X=mouseEvent->X;
00298         _Y=mouseEvent->Y;
00299     }
00300     else if (event==EventMouseWheelId)
00301     {
00302         // Zoom..
00303         CEventMouseWheel* mouseEvent=(CEventMouseWheel*)&event;
00304 
00305         CVector direc=_HotSpot-_Matrix.getPos();
00306         if (! _EnableModelMatrixEdition)
00307         {
00308             _Matrix.setPos(_Matrix.getPos()+direc*(mouseEvent->Direction?0.1f:-0.1f));
00309         }
00310         else
00311         {
00312             CVector dir = direc*(mouseEvent->Direction?0.1f:-0.1f) ;
00313             // transform the translation as needed.
00314             dir= _ModelMatrixTransformMove * dir;
00315             truncateVect(dir) ;
00316             _ModelMatrix.setPos(_ModelMatrix.getPos() + dir);
00317         }
00318     }
00319 }
00320 
00321 void CEvent3dMouseListener::addToServer (CEventServer& server)
00322 {
00323     server.addListener (EventMouseMoveId, this);
00324     server.addListener (EventMouseDownId, this);
00325     server.addListener (EventMouseUpId, this);
00326     server.addListener (EventMouseWheelId, this);
00327     _AsyncListener.addToServer (server);
00328 }
00329 
00330 void CEvent3dMouseListener::removeFromServer (CEventServer& server)
00331 {
00332     server.removeListener (EventMouseMoveId, this);
00333     server.removeListener (EventMouseDownId, this);
00334     server.removeListener (EventMouseUpId, this);
00335     server.removeListener (EventMouseWheelId, this);
00336     _AsyncListener.removeFromServer (server);
00337 }
00338 
00339 const NLMISC::CMatrix& CEvent3dMouseListener::getViewMatrix ()
00340 {
00341     // Mode first person ?
00342     if (_MouseMode==firstPerson)
00343     {
00344         // CVector
00345         CVector dir (0,0,0);
00346         bool find=false;
00347 
00348         // Key pushed ?
00349         if (_AsyncListener.isKeyDown (KeyUP))
00350         {
00351             dir+=CVector (0, 1, 0);
00352             find=true;
00353         }
00354         if (_AsyncListener.isKeyDown (KeyDOWN))
00355         {
00356             dir+=CVector (0, -1, 0);
00357             find=true;
00358         }
00359         if (_AsyncListener.isKeyDown (KeyRIGHT))
00360         {
00361             dir+=CVector (1, 0, 0);
00362             find=true;
00363         }
00364         if (_AsyncListener.isKeyDown (KeyLEFT))
00365         {
00366             dir+=CVector (-1, 0, 0);
00367             find=true;
00368         }
00369         if (_AsyncListener.isKeyDown (KeyNEXT))
00370         {
00371             dir+=CVector (0, 0, -1);
00372             find=true;
00373         }
00374         if (_AsyncListener.isKeyDown (KeyPRIOR))
00375         {
00376             dir+=CVector (0, 0, 1);
00377             find=true;
00378         }
00379 
00380         // key found ?
00381         if (find)
00382         {
00383             // Time elapsed
00384             uint32 milli=(uint32)(CTime::getLocalTime ()-_LastTime);
00385 
00386             // Speed
00387             float dPos=_Speed*(float)milli/1000.f;
00388 
00389             // Good direction
00390             dir.normalize ();
00391             dir*=dPos;
00392 
00393             // Orientation
00394             dir=_Matrix.mulVector (dir);
00395 
00396             // New position
00397             _Matrix.setPos (_Matrix.getPos ()+dir);
00398         }
00399     }
00400 
00401     // Last time
00402     _LastTime=CTime::getLocalTime ();
00403 
00404 
00405     // Return the matrix
00406     return _Matrix;
00407 }
00408 
00409 
00410 void CEvent3dMouseListener::enableTranslateXYInWorld(bool enabled)
00411 {
00412     _TranslateXYInWorld= enabled;
00413 }
00414 
00415 void CEvent3dMouseListener::setModelMatrixTransformMove(const NLMISC::CMatrix& transModelMove)
00416 {
00417     _ModelMatrixTransformMove= transModelMove;
00418 }
00419 
00420 void CEvent3dMouseListener::getModelMatrixTransformMove(NLMISC::CMatrix& transModelMove) const
00421 {
00422     transModelMove= _ModelMatrixTransformMove;
00423 }
00424 
00425 
00426 }; // NL3D

Generated on Thu Jan 7 08:26:26 2010 for NeL by  doxygen 1.6.1