Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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 if ( ! actors.empty() ) { 00229 AABB aabb; 00230 for(int i=0; i<actors.size(); ++i) 00231 { 00232 if (actors.at(i)->transform()) 00233 { 00234 actors.at(i)->transform()->computeWorldMatrix(); 00235 } 00236 actors.at(i)->computeBounds(); 00237 aabb += actors.at(i)->boundingBox(); 00238 } 00239 adjustView(aabb, dir, up, bias); 00240 } 00241 } 00242 //----------------------------------------------------------------------------- 00243 void TrackballManipulator::adjustView(SceneManager* scene, const vec3& dir, const vec3& up, real bias) 00244 { 00245 ActorCollection actors; 00246 scene->extractActors(actors); 00247 adjustView(actors, dir, up, bias); 00248 } 00249 //----------------------------------------------------------------------------- 00250 void TrackballManipulator::adjustView(Rendering* rendering, const vec3& dir, const vec3& up, real bias) 00251 { 00252 ActorCollection actors; 00253 for(int i=0; i<rendering->sceneManagers()->size(); ++i) 00254 rendering->sceneManagers()->at(i)->extractActors(actors); 00255 adjustView(actors, dir, up, bias); 00256 } 00257 //----------------------------------------------------------------------------- 00258 void TrackballManipulator::enableEvent(bool enabled) 00259 { 00260 if (enabled) 00261 { 00262 mMode = NoMode; 00263 if ( openglContext() ) 00264 { 00265 openglContext()->setMouseVisible(true); 00266 openglContext()->setContinuousUpdate(false); 00267 } 00268 } 00269 } 00270 //-----------------------------------------------------------------------------