00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include "cinder/Vector.h" 00026 #include "cinder/Camera.h" 00027 00028 namespace cinder { 00029 00030 class MayaCamUI { 00031 public: 00032 MayaCamUI() { mInitialCam = mCurrentCam = CameraPersp(); } 00033 MayaCamUI( const CameraPersp &aInitialCam ) { mInitialCam = mCurrentCam = aInitialCam; } 00034 00035 void mouseDown( const Vec2i &mousePos ) 00036 { 00037 mInitialMousePos = mousePos; 00038 mInitialCam = mCurrentCam; 00039 mLastAction = ACTION_NONE; 00040 } 00041 00042 void mouseDrag( const Vec2i &mousePos, bool leftDown, bool middleDown, bool rightDown ) 00043 { 00044 int action; 00045 if( rightDown || ( leftDown && middleDown ) ) 00046 action = ACTION_ZOOM; 00047 else if( middleDown ) 00048 action = ACTION_PAN; 00049 else if( leftDown ) 00050 action = ACTION_TUMBLE; 00051 else 00052 return; 00053 00054 if( action != mLastAction ) { 00055 mInitialCam = mCurrentCam; 00056 mInitialMousePos = mousePos; 00057 } 00058 00059 mLastAction = action; 00060 00061 if( action == ACTION_ZOOM ) { // zooming 00062 int mouseDelta = ( mousePos.x - mInitialMousePos.x ) + ( mousePos.y - mInitialMousePos.y ); 00063 00064 float newCOI = powf( 2.71828183f, -mouseDelta / 500.0f ) * mInitialCam.getCenterOfInterest(); 00065 Vec3f oldTarget = mInitialCam.getCenterOfInterestPoint(); 00066 Vec3f newEye = oldTarget - mInitialCam.getViewDirection() * newCOI; 00067 mCurrentCam.setEyePoint( newEye ); 00068 mCurrentCam.setCenterOfInterest( newCOI ); 00069 } 00070 else if( action == ACTION_PAN ) { // panning 00071 float deltaX = ( mousePos.x - mInitialMousePos.x ) / 1000.0f * mInitialCam.getCenterOfInterest(); 00072 float deltaY = ( mousePos.y - mInitialMousePos.y ) / 1000.0f * mInitialCam.getCenterOfInterest(); 00073 Vec3f mW = mInitialCam.getViewDirection().normalized(); 00074 Vec3f mU = Vec3f::yAxis().cross( mW ).normalized(); 00075 Vec3f mV = mW.cross( mU ).normalized(); 00076 mCurrentCam.setEyePoint( mInitialCam.getEyePoint() + mU * deltaX + mV * deltaY ); 00077 } 00078 else { // tumbling 00079 float deltaY = ( mousePos.y - mInitialMousePos.y ) / 100.0f; 00080 float deltaX = ( mousePos.x - mInitialMousePos.x ) / -100.0f; 00081 Vec3f mW = mInitialCam.getViewDirection().normalized(); 00082 bool invertMotion = ( mInitialCam.getOrientation() * Vec3f::yAxis() ).y < 0.0f; 00083 Vec3f mU = Vec3f::yAxis().cross( mW ).normalized(); 00084 Vec3f mV = mW.cross( mU ).normalized(); 00085 00086 if( invertMotion ) { 00087 deltaX = -deltaX; 00088 deltaY = -deltaY; 00089 } 00090 00091 Vec3f rotatedVec = Quatf( mU, deltaY ) * ( mInitialCam.getEyePoint() - mInitialCam.getCenterOfInterestPoint() ); 00092 rotatedVec = Quatf( Vec3f::yAxis(), deltaX ) * rotatedVec; 00093 00094 mCurrentCam.setEyePoint( mInitialCam.getCenterOfInterestPoint() + rotatedVec ); 00095 mCurrentCam.setOrientation( mInitialCam.getOrientation() * Quatf( mU, deltaY ) * Quatf( Vec3f::yAxis(), deltaX ) ); 00096 } 00097 } 00098 00099 const CameraPersp& getCamera() const { return mCurrentCam; } 00100 void setCurrentCam( const CameraPersp &aCurrentCam ) { mCurrentCam = aCurrentCam; } 00101 00102 private: 00103 enum { ACTION_NONE, ACTION_ZOOM, ACTION_PAN, ACTION_TUMBLE }; 00104 00105 Vec2i mInitialMousePos; 00106 CameraPersp mCurrentCam, mInitialCam; 00107 int mLastAction; 00108 }; 00109 00110 }; // namespace cinder