# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

event_mouse_listener.cpp

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