OpenWalnut 1.3.1
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <algorithm> 00026 #include <string> 00027 #include <utility> 00028 00029 #include <osg/LineWidth> 00030 #include <osg/LightModel> 00031 #include <osg/Geometry> 00032 00033 #include "../common/WLogger.h" 00034 00035 #include "WROIBox.h" 00036 #include "WGraphicsEngine.h" 00037 #include "WGEUtils.h" 00038 00039 size_t WROIBox::maxBoxId = 0; 00040 00041 void buildFacesFromPoints( osg::DrawElementsUInt* surfaceElements ) 00042 { 00043 surfaceElements->push_back( 0 ); 00044 surfaceElements->push_back( 2 ); 00045 surfaceElements->push_back( 3 ); 00046 surfaceElements->push_back( 1 ); 00047 00048 surfaceElements->push_back( 2 ); 00049 surfaceElements->push_back( 6 ); 00050 surfaceElements->push_back( 7 ); 00051 surfaceElements->push_back( 3 ); 00052 00053 surfaceElements->push_back( 6 ); 00054 surfaceElements->push_back( 4 ); 00055 surfaceElements->push_back( 5 ); 00056 surfaceElements->push_back( 7 ); 00057 00058 surfaceElements->push_back( 4 ); 00059 surfaceElements->push_back( 0 ); 00060 surfaceElements->push_back( 1 ); 00061 surfaceElements->push_back( 5 ); 00062 00063 surfaceElements->push_back( 1 ); 00064 surfaceElements->push_back( 3 ); 00065 surfaceElements->push_back( 7 ); 00066 surfaceElements->push_back( 5 ); 00067 00068 surfaceElements->push_back( 0 ); 00069 surfaceElements->push_back( 4 ); 00070 surfaceElements->push_back( 6 ); 00071 surfaceElements->push_back( 2 ); 00072 } 00073 00074 void buildLinesFromPoints( osg::DrawElementsUInt* surfaceElements ) 00075 { 00076 surfaceElements->push_back( 0 ); 00077 surfaceElements->push_back( 2 ); 00078 surfaceElements->push_back( 2 ); 00079 surfaceElements->push_back( 3 ); 00080 surfaceElements->push_back( 3 ); 00081 surfaceElements->push_back( 1 ); 00082 surfaceElements->push_back( 1 ); 00083 surfaceElements->push_back( 0 ); 00084 00085 surfaceElements->push_back( 6 ); 00086 surfaceElements->push_back( 4 ); 00087 surfaceElements->push_back( 4 ); 00088 surfaceElements->push_back( 5 ); 00089 surfaceElements->push_back( 5 ); 00090 surfaceElements->push_back( 7 ); 00091 surfaceElements->push_back( 7 ); 00092 surfaceElements->push_back( 6 ); 00093 00094 surfaceElements->push_back( 2 ); 00095 surfaceElements->push_back( 6 ); 00096 surfaceElements->push_back( 7 ); 00097 surfaceElements->push_back( 3 ); 00098 00099 surfaceElements->push_back( 4 ); 00100 surfaceElements->push_back( 0 ); 00101 surfaceElements->push_back( 1 ); 00102 surfaceElements->push_back( 5 ); 00103 } 00104 00105 void setVertices( osg::Vec3Array* vertices, WPosition minPos, WPosition maxPos ) 00106 { 00107 vertices->push_back( osg::Vec3( minPos[0], minPos[1], minPos[2] ) ); 00108 vertices->push_back( osg::Vec3( minPos[0], minPos[1], maxPos[2] ) ); 00109 vertices->push_back( osg::Vec3( minPos[0], maxPos[1], minPos[2] ) ); 00110 vertices->push_back( osg::Vec3( minPos[0], maxPos[1], maxPos[2] ) ); 00111 vertices->push_back( osg::Vec3( maxPos[0], minPos[1], minPos[2] ) ); 00112 vertices->push_back( osg::Vec3( maxPos[0], minPos[1], maxPos[2] ) ); 00113 vertices->push_back( osg::Vec3( maxPos[0], maxPos[1], minPos[2] ) ); 00114 vertices->push_back( osg::Vec3( maxPos[0], maxPos[1], maxPos[2] ) ); 00115 } 00116 00117 WROIBox::WROIBox( WPosition minPos, WPosition maxPos ) : 00118 WROI(), 00119 boxId( maxBoxId++ ), 00120 m_pickNormal( WVector3d() ), 00121 m_oldPixelPosition( WVector2d::zero() ), 00122 m_oldScrollWheel( 0 ), 00123 m_color( osg::Vec4( 0.f, 1.f, 1.f, 0.4f ) ), 00124 m_notColor( osg::Vec4( 1.0f, 0.0f, 0.0f, 0.4f ) ) 00125 { 00126 m_minPos = minPos; 00127 m_maxPos = maxPos; 00128 00129 boost::shared_ptr< WGraphicsEngine > ge = WGraphicsEngine::getGraphicsEngine(); 00130 assert( ge ); 00131 boost::shared_ptr< WGEViewer > viewer = ge->getViewerByName( "Main View" ); 00132 assert( viewer ); 00133 m_viewer = viewer; 00134 m_pickHandler = m_viewer->getPickHandler(); 00135 m_pickHandler->getPickSignal()->connect( boost::bind( &WROIBox::registerRedrawRequest, this, _1 ) ); 00136 00137 m_surfaceGeometry = osg::ref_ptr<osg::Geometry>( new osg::Geometry() ); 00138 m_surfaceGeometry->setDataVariance( osg::Object::DYNAMIC ); 00139 00140 std::stringstream ss; 00141 ss << "ROIBox" << boxId; 00142 00143 setName( ss.str() ); 00144 m_surfaceGeometry->setName( ss.str() ); 00145 00146 osg::ref_ptr<osg::Vec3Array> vertices = osg::ref_ptr<osg::Vec3Array>( new osg::Vec3Array ); 00147 setVertices( vertices, minPos, maxPos ); 00148 m_surfaceGeometry->setVertexArray( vertices ); 00149 00150 osg::DrawElementsUInt* surfaceElements; 00151 surfaceElements = new osg::DrawElementsUInt( osg::PrimitiveSet::QUADS, 0 ); 00152 buildFacesFromPoints( surfaceElements ); 00153 00154 osg::DrawElementsUInt* lineElements; 00155 lineElements = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 ); 00156 buildLinesFromPoints( lineElements ); 00157 00158 m_surfaceGeometry->addPrimitiveSet( surfaceElements ); 00159 m_surfaceGeometry->addPrimitiveSet( lineElements ); 00160 addDrawable( m_surfaceGeometry ); 00161 osg::StateSet* state = getOrCreateStateSet(); 00162 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); 00163 00164 osg::LineWidth* linewidth = new osg::LineWidth(); 00165 linewidth->setWidth( 2.f ); 00166 state->setAttributeAndModes( linewidth, osg::StateAttribute::ON ); 00167 00168 // ------------------------------------------------ 00169 // colors 00170 osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00171 00172 colors->push_back( osg::Vec4( 0.0f, 0.0f, 1.0f, 0.5f ) ); 00173 m_surfaceGeometry->setColorArray( colors ); 00174 m_surfaceGeometry->setColorBinding( osg::Geometry::BIND_OVERALL ); 00175 00176 osg::ref_ptr< osg::LightModel > lightModel = new osg::LightModel(); 00177 lightModel->setTwoSided( true ); 00178 state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON ); 00179 state->setMode( GL_BLEND, osg::StateAttribute::ON ); 00180 00181 m_not->set( false ); 00182 00183 assert( WGraphicsEngine::getGraphicsEngine() ); 00184 WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( this ); 00185 00186 setUserData( this ); 00187 setUpdateCallback( osg::ref_ptr<ROIBoxNodeCallback>( new ROIBoxNodeCallback ) ); 00188 00189 setDirty(); 00190 } 00191 00192 WROIBox::~WROIBox() 00193 { 00194 } 00195 00196 WPosition WROIBox::getMinPos() const 00197 { 00198 return m_minPos; 00199 } 00200 00201 WPosition WROIBox::getMaxPos() const 00202 { 00203 return m_maxPos; 00204 } 00205 00206 void WROIBox::registerRedrawRequest( WPickInfo pickInfo ) 00207 { 00208 boost::unique_lock< boost::shared_mutex > lock; 00209 lock = boost::unique_lock< boost::shared_mutex >( m_updateLock ); 00210 00211 m_pickInfo = pickInfo; 00212 00213 lock.unlock(); 00214 } 00215 00216 void WROIBox::updateGFX() 00217 { 00218 boost::unique_lock< boost::shared_mutex > lock; 00219 lock = boost::unique_lock< boost::shared_mutex >( m_updateLock ); 00220 00221 std::stringstream ss; 00222 ss << "ROIBox" << boxId << ""; 00223 if( m_pickInfo.getName() == ss.str() ) 00224 { 00225 WVector2d newPixelPos( m_pickInfo.getPickPixel() ); 00226 if( m_isPicked ) 00227 { 00228 osg::Vec3 in( newPixelPos.x(), newPixelPos.y(), 0.0 ); 00229 osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() ); 00230 00231 // we want the vector pointing into the screen in world coordinates 00232 // NOTE: set w = 0 to use it as vector and ignore translation 00233 osg::Vec4 toDepth = wge::unprojectFromScreen( osg::Vec4( 0.0, 0.0, 1.0, 0.0 ), m_viewer->getCamera() ); 00234 toDepth.normalize(); 00235 WPosition toDepthWorld( toDepth[0], toDepth[1], toDepth[2] ); 00236 00237 float depthMove = m_pickInfo.getScrollWheel() - m_oldScrollWheel; 00238 00239 WPosition newPixelWorldPos( world[0], world[1], world[2] ); 00240 WPosition oldPixelWorldPos; 00241 if( m_oldPixelPosition.x() == 0 && m_oldPixelPosition.y() == 0 ) 00242 { 00243 oldPixelWorldPos = newPixelWorldPos; 00244 } 00245 else 00246 { 00247 osg::Vec3 in( m_oldPixelPosition.x(), m_oldPixelPosition.y(), 0.0 ); 00248 osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() ); 00249 oldPixelWorldPos = WPosition( world[0], world[1], world[2] ); 00250 } 00251 00252 WVector3d moveVec = newPixelWorldPos - oldPixelWorldPos; 00253 00254 osg::ref_ptr<osg::Vec3Array> vertices = osg::ref_ptr<osg::Vec3Array>( new osg::Vec3Array ); 00255 00256 // resize Box 00257 if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT ) 00258 { 00259 if( m_pickNormal[0] <= 0 && m_pickNormal[1] <= 0 && m_pickNormal[2] <= 0 ) 00260 { 00261 m_maxPos += m_pickNormal * dot( moveVec, m_pickNormal ); 00262 } 00263 if( m_pickNormal[0] >= 0 && m_pickNormal[1] >= 0 && m_pickNormal[2] >= 0 ) 00264 { 00265 m_minPos += m_pickNormal * dot( moveVec, m_pickNormal ); 00266 } 00267 00268 setVertices( vertices, m_minPos, m_maxPos ); 00269 m_surfaceGeometry->setVertexArray( vertices ); 00270 } 00271 00272 // move Box 00273 if( m_pickInfo.getModifierKey() == WPickInfo::NONE ) 00274 { 00275 m_minPos += moveVec; 00276 m_maxPos += moveVec; 00277 00278 m_minPos += 2.0 * toDepthWorld * depthMove; 00279 m_maxPos += 2.0 * toDepthWorld * depthMove; 00280 setVertices( vertices, m_minPos, m_maxPos ); 00281 m_surfaceGeometry->setVertexArray( vertices ); 00282 } 00283 } 00284 else 00285 { 00286 m_pickNormal = m_pickInfo.getPickNormal(); 00287 // color for moving box 00288 if( m_pickInfo.getModifierKey() == WPickInfo::NONE ) 00289 { 00290 osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00291 if( m_not->get() ) 00292 { 00293 colors->push_back( m_notColor ); 00294 } 00295 else 00296 { 00297 colors->push_back( m_color ); 00298 } 00299 m_surfaceGeometry->setColorArray( colors ); 00300 } 00301 if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT ) 00302 { 00303 osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00304 colors->push_back( osg::Vec4( 0.0f, 1.0f, 0.0f, 0.4f ) ); 00305 m_surfaceGeometry->setColorArray( colors ); 00306 } 00307 00308 m_oldScrollWheel = m_pickInfo.getScrollWheel(); 00309 } 00310 m_oldPixelPosition = newPixelPos; 00311 setDirty(); 00312 m_isPicked = true; 00313 m_oldScrollWheel = m_pickInfo.getScrollWheel(); 00314 00315 signalRoiChange(); 00316 } 00317 if( m_isPicked && m_pickInfo.getName() == "unpick" ) 00318 { 00319 // Perform all actions necessary for finishing a pick 00320 00321 osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00322 if( m_not->get() ) 00323 { 00324 colors->push_back( m_notColor ); 00325 } 00326 else 00327 { 00328 colors->push_back( m_color ); 00329 } 00330 m_surfaceGeometry->setColorArray( colors ); 00331 m_pickNormal = WVector3d(); 00332 m_isPicked = false; 00333 } 00334 00335 if( m_dirty->get() ) 00336 { 00337 osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00338 if( m_not->get() ) 00339 { 00340 colors->push_back( m_notColor ); 00341 } 00342 else 00343 { 00344 colors->push_back( m_color ); 00345 } 00346 m_surfaceGeometry->setColorArray( colors ); 00347 } 00348 00349 lock.unlock(); 00350 } 00351 00352 void WROIBox::setColor( osg::Vec4 color ) 00353 { 00354 m_color = color; 00355 } 00356 00357 void WROIBox::setNotColor( osg::Vec4 color ) 00358 { 00359 m_notColor = color; 00360 }