OpenWalnut
1.4.0
|
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 #include "shaders/WGEShader.h" 00035 00036 #include "WROIBox.h" 00037 #include "WGraphicsEngine.h" 00038 #include "WGEUtils.h" 00039 #include "WGEGeodeUtils.h" 00040 00041 size_t WROIBox::maxBoxId = 0; 00042 00043 WROIBox::WROIBox( WPosition minPos, WPosition maxPos ) : 00044 WROI(), 00045 boxId( maxBoxId++ ), 00046 m_pickNormal( WVector3d() ), 00047 m_oldPixelPosition( WVector2d::zero() ), 00048 m_oldScrollWheel( 0 ), 00049 m_color( osg::Vec4( 0.391f, 0.594f, 0.828f, 0.5f ) ), 00050 m_notColor( osg::Vec4( 0.828f, 0.391f, 0.391f, 0.5f ) ) 00051 { 00052 m_propGrp = m_properties->addPropertyGroup( "ROI Box", "Properties of this ROI Box" ); 00053 m_minPos = m_propGrp->addProperty( "Min Position", "When a box is described by its diagonal, this is the lower, left, front corner of it.", 00054 minPos, boost::bind( &WROIBox::boxPropertiesChanged, this, _1 ) ); 00055 m_maxPos = m_propGrp->addProperty( "Max Position", "When a box is described by its diagonal, this is the upper, right, back corner of it.", 00056 maxPos, boost::bind( &WROIBox::boxPropertiesChanged, this, _1 ) ); 00057 00058 boost::shared_ptr< WGraphicsEngine > ge = WGraphicsEngine::getGraphicsEngine(); 00059 assert( ge ); 00060 boost::shared_ptr< WGEViewer > viewer = ge->getViewerByName( "Main View" ); 00061 assert( viewer ); 00062 m_viewer = viewer; 00063 m_pickHandler = m_viewer->getPickHandler(); 00064 m_pickHandler->getPickSignal()->connect( boost::bind( &WROIBox::registerRedrawRequest, this, _1 ) ); 00065 00066 std::stringstream ss; 00067 ss << "ROIBox" << boxId; 00068 setName( ss.str() ); 00069 00070 osg::StateSet* state = getOrCreateStateSet(); 00071 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); 00072 00073 osg::LineWidth* linewidth = new osg::LineWidth(); 00074 linewidth->setWidth( 2.0f ); 00075 state->setAttributeAndModes( linewidth, osg::StateAttribute::ON ); 00076 00077 osg::ref_ptr< osg::LightModel > lightModel = new osg::LightModel(); 00078 lightModel->setTwoSided( true ); 00079 //state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON ); 00080 state->setMode( GL_BLEND, osg::StateAttribute::ON ); 00081 00082 // add a simple default lighting shader 00083 m_lightShader = new WGEShader( "WGELighting" ); 00084 00085 m_not->set( false ); 00086 00087 assert( WGraphicsEngine::getGraphicsEngine() ); 00088 WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( this ); 00089 00090 setUserData( this ); 00091 setUpdateCallback( osg::ref_ptr<ROIBoxNodeCallback>( new ROIBoxNodeCallback ) ); 00092 00093 m_lightShader->apply( this ); 00094 00095 m_needVertexUpdate = true; 00096 setDirty(); 00097 } 00098 00099 WROIBox::~WROIBox() 00100 { 00101 } 00102 00103 WPosition WROIBox::getMinPos() const 00104 { 00105 return m_minPos->get(); 00106 } 00107 00108 WPosition WROIBox::getMaxPos() const 00109 { 00110 return m_maxPos->get(); 00111 } 00112 00113 WPropPosition WROIBox::getMinPosProperty() 00114 { 00115 return m_minPos; 00116 } 00117 00118 WPropPosition WROIBox::getMaxPosProperty() 00119 { 00120 return m_maxPos; 00121 } 00122 00123 void WROIBox::registerRedrawRequest( WPickInfo pickInfo ) 00124 { 00125 boost::unique_lock< boost::shared_mutex > lock; 00126 lock = boost::unique_lock< boost::shared_mutex >( m_updateLock ); 00127 00128 m_pickInfo = pickInfo; 00129 00130 lock.unlock(); 00131 } 00132 00133 void WROIBox::boxPropertiesChanged( boost::shared_ptr< WPropertyBase > /* property */ ) 00134 { 00135 m_needVertexUpdate = true; 00136 } 00137 00138 void WROIBox::updateGFX() 00139 { 00140 boost::unique_lock< boost::shared_mutex > lock; 00141 lock = boost::unique_lock< boost::shared_mutex >( m_updateLock ); 00142 00143 std::stringstream ss; 00144 ss << "ROIBox" << boxId << ""; 00145 if( m_pickInfo.getName() == ss.str() ) 00146 { 00147 WVector2d newPixelPos( m_pickInfo.getPickPixel() ); 00148 if( m_isPicked ) 00149 { 00150 osg::Vec3 in( newPixelPos.x(), newPixelPos.y(), 0.0 ); 00151 osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() ); 00152 00153 // we want the vector pointing into the screen in world coordinates 00154 // NOTE: set w = 0 to use it as vector and ignore translation 00155 osg::Vec4 toDepth = wge::unprojectFromScreen( osg::Vec4( 0.0, 0.0, 1.0, 0.0 ), m_viewer->getCamera() ); 00156 toDepth.normalize(); 00157 WPosition toDepthWorld( toDepth[0], toDepth[1], toDepth[2] ); 00158 00159 float depthMove = m_pickInfo.getScrollWheel() - m_oldScrollWheel; 00160 00161 WPosition newPixelWorldPos( world[0], world[1], world[2] ); 00162 WPosition oldPixelWorldPos; 00163 if( m_oldPixelPosition.x() == 0 && m_oldPixelPosition.y() == 0 ) 00164 { 00165 oldPixelWorldPos = newPixelWorldPos; 00166 } 00167 else 00168 { 00169 osg::Vec3 in( m_oldPixelPosition.x(), m_oldPixelPosition.y(), 0.0 ); 00170 osg::Vec3 world = wge::unprojectFromScreen( in, m_viewer->getCamera() ); 00171 oldPixelWorldPos = WPosition( world[0], world[1], world[2] ); 00172 } 00173 00174 WVector3d moveVec = newPixelWorldPos - oldPixelWorldPos; 00175 00176 // resize Box 00177 if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT ) 00178 { 00179 if( m_pickNormal[0] <= 0 && m_pickNormal[1] <= 0 && m_pickNormal[2] <= 0 ) 00180 { 00181 m_maxPos->set( m_maxPos->get() + ( m_pickNormal * dot( moveVec, m_pickNormal ) ) ); 00182 } 00183 if( m_pickNormal[0] >= 0 && m_pickNormal[1] >= 0 && m_pickNormal[2] >= 0 ) 00184 { 00185 m_minPos->set( m_minPos->get() + ( m_pickNormal * dot( moveVec, m_pickNormal ) ) ); 00186 } 00187 // NOTE: this sets m_needVertexUpdate 00188 } 00189 00190 // move Box 00191 if( m_pickInfo.getModifierKey() == WPickInfo::NONE ) 00192 { 00193 m_minPos->set( m_minPos->get() + moveVec + ( 2.0 * toDepthWorld * depthMove ) ); 00194 m_maxPos->set( m_maxPos->get() + moveVec + ( 2.0 * toDepthWorld * depthMove ) ); 00195 // NOTE: this sets m_needVertexUpdate 00196 } 00197 } 00198 else 00199 { 00200 m_pickNormal = m_pickInfo.getPickNormal(); 00201 // color for moving box 00202 if( m_pickInfo.getModifierKey() == WPickInfo::NONE ) 00203 { 00204 if( m_not->get() ) 00205 { 00206 updateColor( m_notColor ); 00207 } 00208 else 00209 { 00210 updateColor( m_color ); 00211 } 00212 } 00213 if( m_pickInfo.getModifierKey() == WPickInfo::SHIFT ) 00214 { 00215 updateColor( osg::Vec4( 0.0f, 1.0f, 0.0f, 0.4f ) ); 00216 } 00217 00218 m_oldScrollWheel = m_pickInfo.getScrollWheel(); 00219 } 00220 m_oldPixelPosition = newPixelPos; 00221 setDirty(); 00222 m_isPicked = true; 00223 m_oldScrollWheel = m_pickInfo.getScrollWheel(); 00224 } 00225 if( m_isPicked && m_pickInfo.getName() == "unpick" ) 00226 { 00227 // Perform all actions necessary for finishing a pick 00228 if( m_not->get() ) 00229 { 00230 updateColor( m_notColor ); 00231 } 00232 else 00233 { 00234 updateColor( m_color ); 00235 } 00236 00237 m_pickNormal = WVector3d(); 00238 m_isPicked = false; 00239 } 00240 00241 if( m_needVertexUpdate ) 00242 { 00243 removeDrawable( m_surfaceGeometry ); 00244 00245 WPosition pos = getMinPos(); 00246 WPosition size = getMaxPos() - getMinPos(); 00247 00248 // create a new geometry 00249 m_surfaceGeometry = wge::createCube( pos, size, WColor( 1.0, 1.0, 1.0, 1.0 ) ); 00250 00251 // create nice outline 00252 m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 0, 4 ) ); 00253 m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 4, 4 ) ); 00254 m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 8, 4 ) ); 00255 m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 12, 4 ) ); 00256 m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 16, 4 ) ); 00257 m_surfaceGeometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_LOOP, 20, 4 ) ); 00258 00259 // name it and add to geode 00260 m_surfaceGeometry->setDataVariance( osg::Object::DYNAMIC ); 00261 m_surfaceGeometry->setName( ss.str() ); 00262 00263 addDrawable( m_surfaceGeometry ); 00264 00265 // NOTE: as we set the roi dirty, we ensure the color gets set properly in the next if-statement. 00266 setDirty(); 00267 m_needVertexUpdate = false; 00268 } 00269 00270 if( m_dirty->get() ) 00271 { 00272 if( m_not->get() ) 00273 { 00274 updateColor( m_notColor ); 00275 } 00276 else 00277 { 00278 updateColor( m_color ); 00279 } 00280 } 00281 00282 lock.unlock(); 00283 } 00284 00285 void WROIBox::setColor( osg::Vec4 color ) 00286 { 00287 m_color = color; 00288 } 00289 00290 void WROIBox::setNotColor( osg::Vec4 color ) 00291 { 00292 m_notColor = color; 00293 } 00294 00295 void WROIBox::updateColor( osg::Vec4 color ) 00296 { 00297 osg::ref_ptr<osg::Vec4Array> colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array ); 00298 colors->push_back( color ); 00299 00300 WColor outline( 0.0, 0.0, 0.0, 1.0 ); 00301 // NOTE: also add a black color for the solid outlines 00302 colors->push_back( outline ); 00303 colors->push_back( outline ); 00304 colors->push_back( outline ); 00305 colors->push_back( outline ); 00306 colors->push_back( outline ); 00307 colors->push_back( outline ); 00308 m_surfaceGeometry->setColorArray( colors ); 00309 m_surfaceGeometry->setColorBinding( osg::Geometry::BIND_PER_PRIMITIVE_SET ); 00310 }