OpenWalnut 1.3.1
WROIBox.cpp
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 }