/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2012 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLGeom/src/SceneMouseHandler.cpp ** ** Module : ICLGeom ** ** Authors: Christof Elbrechter, Erik Weitnauer, Daniel Dornbusch ** ** ** ** ** ** Commercial License ** ** ICL can be used commercially, please refer to our website ** ** www.iclcv.org for more details. ** ** ** ** GNU General Public License Usage ** ** Alternatively, this file may be used under the terms of the ** ** GNU General Public License version 3.0 as published by the ** ** Free Software Foundation and appearing in the file LICENSE.GPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the GNU General Public License ** ** version 3.0 requirements will be met: ** ** http://www.gnu.org/copyleft/gpl.html. ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** *********************************************************************/ #include #include #include #include namespace icl{ namespace geom{ #ifdef HAVE_QT SceneMouseHandler::SceneMouseHandler( const int pCameraIndex, Scene* pParentScene ) : mParentScene( pParentScene ), mCameraIndex( pCameraIndex ), mKeyboardModifiersBackup( 0 ) { // clear mouse mapping table (2^6 = 64) memset( mMouseMappingTable, 0, sizeof( MouseMappingTableEntry ) * ( MAX_MOUSE_EVENT + 1 ) * 64 ); // mouse sensitivities setSensitivities( 10.0, 1.0, 1.0, 0.001, 10.0 ); // default mouse mappings setMouseMappings(); } // namespace geom } SceneMouseHandler& SceneMouseHandler::operator=( const SceneMouseHandler& pSceneMouseHandler ) { // copy mouse mapping table (2^6 = 64) memcpy( mMouseMappingTable, pSceneMouseHandler.mMouseMappingTable, sizeof( MouseMappingTableEntry ) * ( MAX_MOUSE_EVENT + 1 ) * 64 ); // copy mouse sensitivity settings for ( unsigned int i(0); i < MAX_MOUSE_SENSITIVITY + 1; ++i ) mMouseSensitivities[i] = pSceneMouseHandler.mMouseSensitivities[i]; mCameraBackup = pSceneMouseHandler.mCameraBackup; mAnchor = pSceneMouseHandler.mAnchor; mParentScene = pSceneMouseHandler.mParentScene; mCameraIndex = pSceneMouseHandler.mCameraIndex; mKeyboardModifiersBackup = pSceneMouseHandler.mKeyboardModifiersBackup; return *this; } void SceneMouseHandler::setSensitivities( const float pTranslation, const float pRotation, const float pMouse, const float pWheel, const float pModifier ) { // check translation input if ( pTranslation == 0.0 ) { setSensitivities( 10.0, pRotation, pMouse, pWheel, pModifier ); WARNING_LOG( "pTranslation was 0.0. That is not allowed. Changed to 10.0. \n" << "Please add objects to scene before calling setSensitivities." ); return; } // check modifier input if ( pModifier == 0.0 ) { setSensitivities( pTranslation, pRotation, pMouse, pWheel, 10.0 ); WARNING_LOG( "pModifier was 0.0. That is not allowed. Changed to 10.0." ); return; } // calculate low sensitivites mMouseSensitivities[LowMouseSensitivity].mTranslation = pTranslation; mMouseSensitivities[LowMouseSensitivity].mRotation = pRotation; mMouseSensitivities[LowMouseSensitivity].mMouse = pMouse / pModifier; mMouseSensitivities[LowMouseSensitivity].mWheel = pWheel / pModifier; // calculate normal sensitivites mMouseSensitivities[NormalMouseSensitivity].mTranslation = pTranslation; mMouseSensitivities[NormalMouseSensitivity].mRotation = pRotation; mMouseSensitivities[NormalMouseSensitivity].mMouse = pMouse; mMouseSensitivities[NormalMouseSensitivity].mWheel = pWheel; // calculate high sensitivites mMouseSensitivities[HighMouseSensitivity].mTranslation = pTranslation; mMouseSensitivities[HighMouseSensitivity].mRotation = pRotation; mMouseSensitivities[HighMouseSensitivity].mMouse = pMouse * pModifier; mMouseSensitivities[HighMouseSensitivity].mWheel = pWheel * pModifier; } void SceneMouseHandler::setMouseMappings() { // Mapping: // mouse event type // mouse button: left, right, middle // keyboard modifier: shift, control, alt // function to call // additional data // left mouse button: free view setMouseMapping( MouseDragEvent, true, false, false, false, false, false, &freeView, &mMouseSensitivities[NormalMouseSensitivity] ); setMouseMapping( MouseDragEvent, true, false, false, true, false, false, &freeView, &mMouseSensitivities[LowMouseSensitivity] ); setMouseMapping( MouseDragEvent, true, false, false, false, true, false, &freeView, &mMouseSensitivities[HighMouseSensitivity] ); // middle mouse button: strafe setMouseMapping( MouseDragEvent, false, true, false, false, false, false, &strafe, &mMouseSensitivities[NormalMouseSensitivity] ); setMouseMapping( MouseDragEvent, false, true, false, true, false, false, &strafe, &mMouseSensitivities[LowMouseSensitivity] ); setMouseMapping( MouseDragEvent, false, true, false, false, true, false, &strafe, &mMouseSensitivities[HighMouseSensitivity] ); // right mouse button: rotate around origin setMouseMapping( MouseDragEvent, false, false, true, false, false, false, &rotateAroundOrigin, &mMouseSensitivities[NormalMouseSensitivity] ); setMouseMapping( MouseDragEvent, false, false, true, true, false, false, &rotateAroundOrigin, &mMouseSensitivities[LowMouseSensitivity] ); setMouseMapping( MouseDragEvent, false, false, true, false, true, false, &rotateAroundOrigin, &mMouseSensitivities[HighMouseSensitivity] ); // mouse wheel: roll and distance setMouseMapping( MouseWheelEvent, false, false, false, false, false, false, &rollAndDistance, &mMouseSensitivities[NormalMouseSensitivity] ); setMouseMapping( MouseWheelEvent, false, false, false, true, false, false, &rollAndDistance, &mMouseSensitivities[LowMouseSensitivity] ); setMouseMapping( MouseWheelEvent, false, false, false, false, true, false, &rollAndDistance, &mMouseSensitivities[HighMouseSensitivity] ); // left + right mouse button: roll and distance setMouseMapping( MouseDragEvent, true, false, true, false, false, false, &rollAndDistance, &mMouseSensitivities[NormalMouseSensitivity] ); setMouseMapping( MouseDragEvent, true, false, true, true, false, false, &rollAndDistance, &mMouseSensitivities[LowMouseSensitivity] ); setMouseMapping( MouseDragEvent, true, false, true, false, true, false, &rollAndDistance, &mMouseSensitivities[HighMouseSensitivity] ); } void SceneMouseHandler::setMouseMapping( const MouseEventType pMouseEventType, const bool pLeftMouseButton, const bool pMiddleMouseButton, const bool pRightMouseButton, const bool pShift, const bool pControl, const bool pAlt, MouseActionCallback pMouseActionCallback, void* pData ) { // set callback function mMouseMappingTable[pMouseEventType] [pLeftMouseButton] [pMiddleMouseButton] [pRightMouseButton] [pShift] [pControl] [pAlt].mMouseAction = pMouseActionCallback; // set additional data mMouseMappingTable[pMouseEventType] [pLeftMouseButton] [pMiddleMouseButton] [pRightMouseButton] [pShift] [pControl] [pAlt].mData = pData; } void SceneMouseHandler::freeView( const MouseEvent& pMouseEvent, const Point32f& pCurrentMousePosition, const Point32f& pDeltaMousePosition, Camera& pCamera, void* pData, bool pInverseX, bool pInverseY ) { // sensitivities given by additional data pointer MouseSensitivities* tMouseSensitivities = (MouseSensitivities*) pData; ICLASSERT( tMouseSensitivities ); // factors float tRotationFactor = tMouseSensitivities->mRotation; float tDeviceFactor = ( pMouseEvent.isWheelEvent() ) ? tMouseSensitivities->mWheel : tMouseSensitivities->mMouse; float tInverseXFactor = pInverseX ? -1.0 : 1.0; float tInverseYFactor = pInverseY ? -1.0 : 1.0; // rotate norm around up (by -pDeltaMousePosition.x) Vec tNorm = pCamera.getNorm(); Vec tUp = pCamera.getUp(); tNorm = rotate_vector( tUp, -tInverseXFactor * tRotationFactor * tDeviceFactor * pDeltaMousePosition.x, tNorm ); // rotate norm and up around horz (by delta.y) tNorm = rotate_vector( pCamera.getHoriz(), tInverseYFactor * tRotationFactor * tDeviceFactor * pDeltaMousePosition.y, tNorm ); tUp = rotate_vector( pCamera.getHoriz(), tInverseYFactor * tRotationFactor * tDeviceFactor * pDeltaMousePosition.y, tUp ); // adjust camera pCamera.setNorm( tNorm ); pCamera.setUp( tUp ); } void SceneMouseHandler::rotateAroundOrigin( const MouseEvent& pMouseEvent, const Point32f& pCurrentMousePosition, const Point32f& pDeltaMousePosition, Camera& pCamera, void* pData ) { // sensitivities given by additional data pointer MouseSensitivities* tMouseSensitivities = (MouseSensitivities*) pData; ICLASSERT( tMouseSensitivities ); // factors float tRotationFactor = 2.0 * tMouseSensitivities->mRotation; float tDeviceFactor = ( pMouseEvent.isWheelEvent() ) ? tMouseSensitivities->mWheel : -tMouseSensitivities->mMouse; // get camera parameters Vec tPosition = pCamera.getPosition(); Vec tNorm = pCamera.getNorm(); Vec tUp = pCamera.getUp(); Vec tHoriz = pCamera.getHoriz(); // rotate camera around origin tPosition = rotate_vector( tUp, -tRotationFactor * tDeviceFactor * pDeltaMousePosition.x, tPosition ); tPosition = rotate_vector( tHoriz, tRotationFactor * tDeviceFactor * pDeltaMousePosition.y, tPosition ); // adjust pitch and yaw tNorm = rotate_vector( tHoriz, tRotationFactor * tDeviceFactor * pDeltaMousePosition.y, tNorm ); tUp = rotate_vector( tHoriz, tRotationFactor * tDeviceFactor * pDeltaMousePosition.y, tUp ); tNorm = rotate_vector( tUp, -tRotationFactor * tDeviceFactor * pDeltaMousePosition.x, tNorm ); // adjust camera pCamera.setPosition( tPosition ); pCamera.setNorm( tNorm ); pCamera.setUp( tUp ); } void SceneMouseHandler::strafe( const MouseEvent& pMouseEvent, const Point32f& pCurrentMousePosition, const Point32f& pDeltaMousePosition, Camera& pCamera, void* pData ) { // sensitivities given by additional data pointer MouseSensitivities* tMouseSensitivities = (MouseSensitivities*) pData; ICLASSERT( tMouseSensitivities ); // factors float tTranslationFactor = tMouseSensitivities->mTranslation; float tDeviceFactor = ( pMouseEvent.isWheelEvent() ) ? tMouseSensitivities->mWheel : tMouseSensitivities->mMouse; // strafe camera Vec tTranslationVector = pCamera.getUp() * ( -tTranslationFactor * tDeviceFactor * pDeltaMousePosition.y ) + pCamera.getHoriz() * ( -tTranslationFactor * tDeviceFactor * pDeltaMousePosition.x ); tTranslationVector[3] = 0; // adjust camera pCamera.translate( tTranslationVector ); } void SceneMouseHandler::rollAndDistance( const MouseEvent& pMouseEvent, const Point32f& pCurrentMousePosition, const Point32f& pDeltaMousePosition, Camera& pCamera, void* pData ) { // sensitivities given by additional data pointer MouseSensitivities* tMouseSensitivities = (MouseSensitivities*) pData; ICLASSERT( tMouseSensitivities ); // factors float tRotationFactor = tMouseSensitivities->mRotation; float tTranslationFactor = tMouseSensitivities->mTranslation; float tDeviceFactor = ( pMouseEvent.isWheelEvent() ) ? tMouseSensitivities->mWheel : -tMouseSensitivities->mMouse; // rotate up around norm (by pDeltaMousePosition.x) Vec tUp = pCamera.getUp(); tUp = rotate_vector( pCamera.getNorm(), tRotationFactor * tDeviceFactor * pDeltaMousePosition.x, tUp ); pCamera.setUp( tUp ); // move camera along norm vector Vec tTranslationVector = pCamera.getNorm() * ( tTranslationFactor * tDeviceFactor * pDeltaMousePosition.y ); tTranslationVector[3] = 0; // adjust camera pCamera.translate( tTranslationVector ); } void SceneMouseHandler::process( const MouseEvent &pMouseEvent ) { Camera &tCamera = mParentScene->getCamera( mCameraIndex ); int tKeyboardModifiers = pMouseEvent.getKeyboardModifiers(); // get mouse mapping MouseMappingTableEntry tMouseMappingTableEntry = mMouseMappingTable[pMouseEvent.getType()] [pMouseEvent.isLeft()] [pMouseEvent.isMiddle()] [pMouseEvent.isRight()] [pMouseEvent.isModifierActive(ShiftModifier)] [pMouseEvent.isModifierActive(ControlModifier)] [pMouseEvent.isModifierActive(AltModifier)]; MouseActionCallback tMouseActionCallback = tMouseMappingTableEntry.mMouseAction; void* tData = tMouseMappingTableEntry.mData; // if dragging is started or keyboard modifiers changed, save anchor point and camera parameters if ( ( pMouseEvent.isPressEvent() ) || ( tKeyboardModifiers != mKeyboardModifiersBackup ) ) { mAnchor = pMouseEvent.getRelPos(); mCameraBackup = tCamera; } // mouse drag events if ( pMouseEvent.isDragEvent() ) { Point32f tDeltaMousePosition = pMouseEvent.getRelPos() - mAnchor; tCamera = mCameraBackup; if ( tMouseActionCallback ) tMouseActionCallback( pMouseEvent, pMouseEvent.getRelPos(), tDeltaMousePosition, tCamera, tData ); } // mouse wheel events if ( pMouseEvent.isWheelEvent() ) { Point32f tDeltaMousePosition = pMouseEvent.getWheelDelta(); if ( tMouseActionCallback ) tMouseActionCallback( pMouseEvent, pMouseEvent.getRelPos(), tDeltaMousePosition, tCamera, tData ); } // save keyboard modifiers for later comparison mKeyboardModifiersBackup = tKeyboardModifiers; } #endif }