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/FlatManipulator.hpp> 00033 #include <vlGraphics/OpenGLContext.hpp> 00034 00035 using namespace vl; 00036 00037 FlatManipulator::FlatManipulator(): mMode(NoMode), 00038 mTranslationButton(MiddleButton), mZoomButton(RightButton), 00039 mZoomSpeed(1.0f) 00040 { 00041 VL_DEBUG_SET_OBJECT_NAME() 00042 } 00043 00044 //----------------------------------------------------------------------------- 00045 void FlatManipulator::setCamera(Camera* camera) 00046 { 00047 mCamera = camera; 00048 } 00049 //----------------------------------------------------------------------------- 00050 void FlatManipulator::mouseDownEvent(EMouseButton btn, int x, int y) 00051 { 00052 if ( camera() == NULL ) 00053 return; 00054 00055 // if already busy ignore the event, wadda heck! 00056 if (mode() != NoMode) 00057 return; 00058 00059 //if the rodent is out of cage, kisses and bye-bye 00060 int vx, vy; 00061 if(mouseInViewport(x, y, vx, vy) == false) 00062 return; 00063 //store the rodent's position in the cage 00064 mMouseStart = vec2(x,y); 00065 00066 // enter new mode 00067 if (btn == translationButton()) 00068 {//we need world pixel size only in translation mode 00069 mMode = TranslationMode; 00070 //now let's find the pixel size, assuming an orthographic projection 00071 mPixelSize.x() = 2.0/camera()->projectionMatrix().e(0,0)/ 00072 camera()->viewport()->width(); 00073 mPixelSize.y() = 2.0/camera()->projectionMatrix().e(1,1)/ 00074 camera()->viewport()->height(); 00075 } 00076 else 00077 if (btn == zoomButton()) 00078 { 00079 mMode = ZoomMode; 00080 } 00081 00082 VL_CHECK(openglContext()->framebuffer()) 00083 00084 } 00085 //----------------------------------------------------------------------------- 00086 void FlatManipulator::mouseMoveEvent(int x, int y) 00087 { 00088 if ( camera() == NULL ) 00089 return; 00090 00091 // ignore the event if the manipulator is not in any mode 00092 if (mode() == NoMode) 00093 return; 00094 00095 VL_CHECK(openglContext()->framebuffer()) 00096 00097 if (mode() == ZoomMode) 00098 { 00099 float scale = 1.0-(y - mMouseStart.y())*zoomSpeed()/100.0; 00100 camera()->setViewMatrix( 00101 mat4::getScaling(scale, scale,1.0)* 00102 camera()->viewMatrix()); 00103 mMouseStart = vec2(x,y); 00104 } 00105 else 00106 if (mode() == TranslationMode) 00107 { 00108 vec2 shift = (vec2(x,y) - mMouseStart)*mPixelSize; 00109 camera()->setViewMatrix( 00110 mat4::getTranslation(shift.x(), -shift.y(),0)* 00111 camera()->viewMatrix()); 00112 mMouseStart = vec2(x,y); 00113 } 00114 00115 // update the view 00116 openglContext()->update(); 00117 } 00118 //----------------------------------------------------------------------------- 00119 void FlatManipulator::mouseUpEvent(EMouseButton btn, int /*x*/, int /*y*/) 00120 { 00121 if ( camera() == NULL ) 00122 return; 00123 00124 // if the manipulator is not doing anything ignore the event 00125 if (mode() == NoMode) 00126 return; 00127 00128 // leave the mode 00129 if (btn == translationButton() && mMode == TranslationMode) 00130 mMode = NoMode; 00131 else 00132 if (btn == zoomButton() && mMode == ZoomMode) 00133 mMode = NoMode; 00134 } 00135 //----------------------------------------------------------------------------- 00136 void FlatManipulator::enableEvent(bool enabled) 00137 { 00138 if (enabled) 00139 { 00140 mMode = NoMode; 00141 if ( openglContext() ) 00142 { 00143 openglContext()->setMouseVisible(true); 00144 openglContext()->setContinuousUpdate(false); 00145 } 00146 } 00147 } 00148 //----------------------------------------------------------------------------- 00149 bool FlatManipulator::mouseInViewport(int mx, int my, int& vx, int& vy) 00150 { 00151 vx = mx - camera()->viewport()->x(); 00152 vy = openglContext()->height() - my - camera()->viewport()->y(); 00153 00154 //if outside camera's viewport, return false 00155 if (vx<0 || vy<0 || 00156 vx >= camera()->viewport()->width() || 00157 vy >= camera()->viewport()->height()) 00158 { 00159 return false; 00160 } 00161 return true; 00162 } 00163 //----------------------------------------------------------------------------- 00164 vl::ref<vl::Geometry> makeScales(bool X, bool Y, bool Z, int numArmTicks, float mmStep, float mmTickSize) 00165 { 00166 vl::ref<vl::Geometry> scales = new vl::Geometry(); 00167 int numRulers = (X?1:0)+(Y?1:0)+(Z?1:0); 00168 if(numRulers == 0) return scales; 00169 00170 vl::ref<vl::ArrayFloat3> points(new vl::ArrayFloat3()); 00171 vl::ref<vl::ArrayFloat3> scalesPoints(new vl::ArrayFloat3()); 00172 00173 //the length of one arm of scales 00174 const float mmArmLength = numArmTicks*mmStep; 00175 00176 //calculate the number of points, having marks at every 10 mm 00177 int numAxisPoints = ( 2*numArmTicks + 1)*2; 00178 00179 //resize the array to accomodate a ruler 00180 points->resize(numAxisPoints); 00181 //room for up to three orthogonal rulers 00182 scalesPoints->resize(numRulers*points->size()); 00183 00184 float xpos = mmStep; 00185 int t; 00186 //generate the X ruler 00187 for(t = 0; t < numArmTicks; t++) 00188 { 00189 float height = mmTickSize; 00190 00191 if((t+1)%10 == 0)//takes priority over '5' 00192 height *= 2; 00193 else 00194 if((t+1)%5 == 0) 00195 height *= 1.5; 00196 00197 points->at(4*t) = vl::fvec3(-xpos, -height,0); 00198 points->at(4*t+1) = vl::fvec3(-xpos, +height,0); 00199 points->at(4*t+2) = vl::fvec3(xpos, -height,0); 00200 points->at(4*t+3) = vl::fvec3(xpos, +height,0); 00201 00202 xpos += mmStep; 00203 } 00204 //now add the axis line 00205 points->at(4*t) = vl::fvec3(-mmArmLength, 0.0,0); 00206 points->at(4*t+1) = vl::fvec3(mmArmLength, 0.0,0); 00207 00208 int i=0; 00209 00210 if(X)//transfer the X ruler into the main array 00211 { 00212 for(size_t p=0; p < points->size(); i++, p++) 00213 { 00214 scalesPoints->at(i) = points->at(p); 00215 } 00216 } 00217 if(Y)//transfer the Y ruler into the main array 00218 { 00219 //rotate the generic ruler around Z axis to create the Y ruler 00220 points->transform(vl::fmat4::getRotation(90, 0, 0, 1)); 00221 00222 //copy the Y ruler into the scales array 00223 for(size_t p=0; p < points->size(); i++, p++) 00224 { 00225 scalesPoints->at(i) = points->at(p); 00226 } 00227 } 00228 if(Z)//transfer the Z ruler into the main array 00229 { 00230 //rotate the ruler based on the last rotation 00231 vl::fvec3 rotaxis = Y ? vl::fvec3(1,0,0) : vl::fvec3(0,1,0); 00232 points->transform(vl::fmat4::getRotation(90,rotaxis)); 00233 00234 //copy the Y ruler into the scales array 00235 for(size_t p=0; p < points->size(); i++, p++) 00236 { 00237 scalesPoints->at(i) = points->at(p); 00238 } 00239 } 00240 scales->setVertexArray(scalesPoints.get()); 00241 //every consecutive pair of points make a line 00242 scales->drawCalls()->push_back( new vl::DrawArrays( vl::PT_LINES, 0, numRulers*points->size() ) ); 00243 return scales; 00244 }