Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/TrackballManipulator.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
00005 /*                                                                                    */
00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
00007 /*  All rights reserved.                                                              */
00008 /*                                                                                    */
00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
00010 /*  are permitted provided that the following conditions are met:                     */
00011 /*                                                                                    */
00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
00013 /*  list of conditions and the following disclaimer.                                  */
00014 /*                                                                                    */
00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
00017 /*  other materials provided with the distribution.                                   */
00018 /*                                                                                    */
00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
00029 /*                                                                                    */
00030 /**************************************************************************************/
00031 
00032 #include <vlGraphics/TrackballManipulator.hpp>
00033 #include <vlGraphics/OpenGLContext.hpp>
00034 #include <vlGraphics/Actor.hpp>
00035 #include <vlGraphics/SceneManager.hpp>
00036 #include <vlGraphics/Rendering.hpp>
00037 
00038 using namespace vl;
00039 
00040 //-----------------------------------------------------------------------------
00041 void TrackballManipulator::mouseDownEvent(EMouseButton btn, int x, int y)
00042 {
00043   if ( camera() == NULL )
00044     return;
00045 
00046   // if already busy ignore the event
00047   if (mode() != NoMode)
00048     return;
00049 
00050   // enter new mode
00051   if (btn == rotationButton())
00052     mMode = RotationMode;
00053   else
00054   if (btn == translationButton())
00055     mMode = TranslationMode;
00056   else
00057   if (btn == zoomButton())
00058     mMode = ZoomMode;
00059 
00060   VL_CHECK(openglContext()->framebuffer())
00061 
00062   // set x/y relative to the viewport
00063   x -= camera()->viewport()->x();
00064   y -= openglContext()->framebuffer()->height() - 1 - (camera()->viewport()->y() + camera()->viewport()->height() -1);
00065 
00066   // check that the click is in the viewport
00067   int w = camera()->viewport()->width();
00068   int h = camera()->viewport()->height();
00069 
00070   if (x<0 || y<0 || x>=w || y>=h)
00071     return;
00072 
00073   mMouseStart.x() = x;
00074   mMouseStart.y() = y;
00075 
00076   if (mTransform)
00077   {
00078     mStartMatrix = mTransform->localMatrix();
00079     mPivot = mStartMatrix.getT();
00080   }
00081   else
00082     mStartMatrix = camera()->modelingMatrix();
00083 
00084   mStartCameraPos = camera()->modelingMatrix().getT();
00085   mStartPivot = mPivot;
00086 }
00087 //-----------------------------------------------------------------------------
00088 void TrackballManipulator::mouseUpEvent(EMouseButton btn, int /*x*/, int /*y*/)
00089 {
00090   if ( camera() == NULL )
00091     return;
00092 
00093   // if the trackball is not doing anything ignore the event
00094   if (mode() == NoMode)
00095     return;
00096 
00097   // leave the mode
00098   if (btn == rotationButton() && mMode == RotationMode)
00099     mMode = NoMode;
00100   else
00101   if (btn == translationButton() && mMode == TranslationMode)
00102     mMode = NoMode;
00103   else
00104   if (btn == zoomButton() && mMode == ZoomMode)
00105     mMode = NoMode;
00106 }
00107 //-----------------------------------------------------------------------------
00108 void TrackballManipulator::mouseMoveEvent(int x, int y)
00109 {
00110   if ( camera() == NULL )
00111     return;
00112 
00113   // ignore the event if the trackball is not in any mode
00114   if (mode() == NoMode)
00115     return;
00116 
00117   VL_CHECK(openglContext()->framebuffer())
00118   // set x/y relative to the top/left cornder of the viewport
00119   x -= camera()->viewport()->x();
00120   y -= openglContext()->framebuffer()->height() - 1 - (camera()->viewport()->y() + camera()->viewport()->height() -1);
00121 
00122   if (mode() == RotationMode)
00123   {
00124     if (mTransform)
00125     {
00126       mTransform->setLocalMatrix( mat4::getTranslation(mPivot) * trackballRotation(x,y) * mat4::getTranslation(-mPivot) * mStartMatrix );
00127       mTransform->computeWorldMatrix();
00128       mStartMatrix = mTransform->localMatrix();
00129     }
00130     else
00131     {
00132       camera()->setModelingMatrix( mat4::getTranslation(mPivot) * trackballRotation(x,y) * mat4::getTranslation(-mPivot) * mStartMatrix );
00133       mStartMatrix = camera()->modelingMatrix();
00134     }
00135 
00136     mMouseStart.x() = x;
00137     mMouseStart.y() = y;
00138   }
00139   else
00140   if (mode() == ZoomMode)
00141   {
00142     float t = (y-mMouseStart.y()) / 200.0f;
00143     t *= zoomSpeed();
00144     real distance = (mStartCameraPos - mPivot).length();
00145     vec3 camera_pos = mStartCameraPos - camera()->modelingMatrix().getZ()*t*distance;
00146     mat4 m = camera()->modelingMatrix();
00147     m.setT(camera_pos);
00148     camera()->setModelingMatrix(m);
00149   }
00150   else
00151   if (mode() == TranslationMode)
00152   {
00153     float tx = (mMouseStart.x() - x)  / 400.0f;
00154     float ty = -(mMouseStart.y() - y) / 400.0f;
00155     tx *= translationSpeed();
00156     ty *= translationSpeed();
00157     real distance = (mStartCameraPos - mPivot).length();
00158     vec3 up    = camera()->modelingMatrix().getY();
00159     vec3 right = camera()->modelingMatrix().getX();
00160     mat4 m = camera()->modelingMatrix();
00161     m.setT(mStartCameraPos + up*distance*ty + right*distance*tx);
00162     camera()->setModelingMatrix(m);
00163     mPivot = mStartPivot + up*distance*ty + right*distance*tx;
00164   }
00165 
00166   // update the view
00167   openglContext()->update();
00168 }
00169 //-----------------------------------------------------------------------------
00170 mat4 TrackballManipulator::trackballRotation(int x, int y)
00171 {
00172   if( x==mMouseStart.x()  && y==mMouseStart.y() )
00173     return mat4();
00174 
00175   VL_CHECK(camera())
00176   vec3 a = computeVector(mMouseStart.x(), mMouseStart.y());
00177   vec3 b = computeVector(x, y);
00178   vec3 n = cross(a, b);
00179   n.normalize();
00180   a.normalize();
00181   b.normalize();
00182   real dot_a_b = dot(a,b);
00183   dot_a_b = clamp(dot_a_b,(real)-1.0,(real)+1.0);
00184   real alpha = acos(dot_a_b) * (mTransform ? 1 : -1);
00185   alpha = alpha * rotationSpeed();
00186   vec3 nc =  camera()->modelingMatrix().get3x3() * n;
00187   if (mTransform && mTransform->parent())
00188     nc = mTransform->parent()->getComputedWorldMatrix().getInverse() * nc;
00189   nc.normalize();
00190   return mat4::getRotation(alpha*(real)dRAD_TO_DEG, nc);
00191 }
00192 //-----------------------------------------------------------------------------
00193 vec3 TrackballManipulator::computeVector(int x, int y)
00194 {
00195   vec3 c(camera()->viewport()->width() / 2.0f, camera()->viewport()->height() / 2.0f, 0);
00196 
00197   float sphere_x = camera()->viewport()->width()  * 0.5f;
00198   float sphere_y = camera()->viewport()->height() * 0.5f;
00199 
00200   VL_CHECK(camera())
00201   vec3 v((real)x,(real)y,0);
00202   v -= c;
00203   v.x() /= sphere_x;
00204   v.y() /= sphere_y;
00205   v.y() = -v.y();
00206   //if (v.length() > 1.0f)
00207   //  v.normalize();
00208 
00209   real z2 = 1.0f - v.x()*v.x() - v.y()*v.y();
00210   if (z2 < 0) 
00211     z2 = 0;
00212   v.z() = sqrt( z2 );
00213   v.normalize();
00214   return v;
00215 }
00216 //-----------------------------------------------------------------------------
00217 void TrackballManipulator::adjustView(const AABB& aabb, const vec3& dir, const vec3& up, real bias)
00218 {
00219   VL_CHECK(camera())
00220   VL_CHECK(!aabb.isNull())
00221   /*setTransform(NULL);*/
00222   setPivot( aabb.center() );
00223   camera()->adjustView(aabb, dir, up, bias);
00224 }
00225 //-----------------------------------------------------------------------------
00226 void TrackballManipulator::adjustView(ActorCollection& actors, const vec3& dir, const vec3& up, real bias)
00227 {
00228   AABB aabb;
00229   for(int i=0; i<actors.size(); ++i)
00230   {
00231     if (actors.at(i)->transform())
00232     {
00233       actors.at(i)->transform()->computeWorldMatrix();
00234     }
00235     actors.at(i)->computeBounds();
00236     aabb += actors.at(i)->boundingBox();
00237   }
00238   adjustView(aabb, dir, up, bias);
00239 }
00240 //-----------------------------------------------------------------------------
00241 void TrackballManipulator::adjustView(SceneManager* scene, const vec3& dir, const vec3& up, real bias)
00242 {
00243   ActorCollection actors;
00244   scene->extractActors(actors);
00245   adjustView(actors, dir, up, bias);
00246 }
00247 //-----------------------------------------------------------------------------
00248 void TrackballManipulator::adjustView(Rendering* rendering, const vec3& dir, const vec3& up, real bias)
00249 {
00250   ActorCollection actors;
00251   for(int i=0; i<rendering->sceneManagers()->size(); ++i)
00252     rendering->sceneManagers()->at(i)->extractActors(actors);
00253   adjustView(actors, dir, up, bias);
00254 }
00255 //-----------------------------------------------------------------------------
00256 void TrackballManipulator::enableEvent(bool enabled)
00257 { 
00258   if (enabled)
00259   {
00260     mMode = NoMode;
00261     if ( openglContext() )
00262     {
00263       openglContext()->setMouseVisible(true);
00264       openglContext()->setContinuousUpdate(false);
00265     }
00266   }
00267 }
00268 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:42.
Permission is granted to use this page to write and publish articles regarding Visualization Library.