Commit eea0f2b4 authored by ledig's avatar ledig
Browse files

[ADD] red cross in Nav Views, moveable through right clicking, also fixed the...

[ADD] red cross in Nav Views, moveable through right clicking, also fixed the aspect ratio and view matrix off nav slices
parent 8402ca8e
......@@ -63,14 +63,16 @@ WGEViewer::WGEViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int
switch( projectionMode )
{
case( WGECamera::ORTHOGRAPHIC ):
m_pickHandler = new WPickHandler( name );
m_View->addEventHandler( m_pickHandler );
if ( name != std::string( "main" ) )
break;
case( WGECamera::PERSPECTIVE ):
// camera manipulator
m_View->setCameraManipulator( new WGEZoomTrackballManipulator() );
m_View->setLightingMode( osg::View::HEADLIGHT ); // this is the default anyway
m_pickHandler = new WPickHandler();
m_View->addEventHandler( m_pickHandler );
break;
case( WGECamera::TWO_D ):
// no manipulators nor gui handlers
......
......@@ -33,9 +33,19 @@
WPickHandler::WPickHandler()
: m_hitResult( WPickInfo() ),
m_startPick( WPickInfo() ),
m_shift( false )
m_shift( false ),
m_viewerName( "" )
{
}
WPickHandler::WPickHandler( std::string viewerName )
: m_hitResult( WPickInfo() ),
m_startPick( WPickInfo() ),
m_shift( false ),
m_viewerName( viewerName )
{
}
WPickHandler::~WPickHandler()
{
}
......@@ -110,7 +120,7 @@ void WPickHandler::unpick( )
{
if( m_hitResult != WPickInfo() )
{
m_hitResult = WPickInfo( "unpick", wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
m_hitResult = WPickInfo( "unpick", m_viewerName, wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
m_startPick = WPickInfo();
}
m_pickSignal( getHitResult() );
......@@ -137,6 +147,22 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
float x = ea.getX(); // pixel position in x direction
float y = ea.getY(); // pixel position in x direction
// if we are in another viewer than the main view we just need the pixel position
if ( m_viewerName != "" && m_viewerName != "main" )
{
WPickInfo pickInfo;
pickInfo = WPickInfo( "", m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
m_startPick.getModifierKey(), m_startPick.getPickNormal() );
m_hitResult = pickInfo;
// if nothing was picked before remember the currently picked.
m_startPick = pickInfo;
m_pickSignal( getHitResult() );
return;
}
bool intersetionsExist = view->computeIntersections( x, y, intersections );
// if something is picked, get the right thing from the list, because it might be hidden.
......@@ -158,7 +184,7 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
{
while( ( hitr != intersections.end() ) && !startPickIsStillInList )
{
WPickInfo pickInfoTmp( extractSuitableName( hitr ), wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
WPickInfo pickInfoTmp( extractSuitableName( hitr ), m_viewerName, wmath::WPosition(), std::make_pair( 0, 0 ), WPickInfo::NONE );
startPickIsStillInList |= ( pickInfoTmp.getName() == m_startPick.getName() );
if( !startPickIsStillInList ) // if iteration not finished yet go on in list
......@@ -183,13 +209,13 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
pickNormal[0] = hitr->getWorldIntersectNormal()[0];
pickNormal[1] = hitr->getWorldIntersectNormal()[1];
pickNormal[2] = hitr->getWorldIntersectNormal()[2];
pickInfo = WPickInfo( extractSuitableName( hitr ), pickPos, std::make_pair( x, y ), WPickInfo::NONE, pickNormal );
pickInfo = WPickInfo( extractSuitableName( hitr ), m_viewerName, pickPos, std::make_pair( x, y ), WPickInfo::NONE, pickNormal );
}
// Use the old PickInfo with updated pixel info if we have previously picked something but the old is not in list anymore
if( !startPickIsStillInList && m_startPick.getName() != "" && m_startPick.getName() != "unpick" )
{
pickInfo = WPickInfo( m_startPick.getName(), m_startPick.getPickPosition(), std::make_pair( x, y ),
pickInfo = WPickInfo( m_startPick.getName(), m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
m_startPick.getModifierKey(), m_startPick.getPickNormal() );
}
......
......@@ -57,10 +57,15 @@ class WPickHandler: public osgGA::GUIEventHandler
public:
/**
* Constructor that initalizes members with sensible defaults.
*/
* Constructor that initalizes members with sensible defaults.
*/
WPickHandler();
/**
* Constructor that initalizes members with sensible defaults and sets the name of the viewer
*/
explicit WPickHandler( std::string viewerName );
/**
* Deals with the events found by the osg.
* \param ea Event class for storing Keyboard, mouse and window events.
......@@ -105,6 +110,7 @@ protected:
WPickInfo m_hitResult; //!< Textual representation of the result of a pick.
WPickInfo m_startPick; //!< indicates what was first picked. Should be "" after unpick.
bool m_shift; //!< is shift pressed?
std::string m_viewerName; //!< which viewer sends the signal
private:
boost::signals2::signal1<void, WPickInfo > m_pickSignal; //!< One can register to this signal to receive pick events.
......
......@@ -53,11 +53,12 @@ public:
* Creates an object with the needed information.
* \param name name of picked object
* \param pickPosition position where object was hit
* \param pixelCoords pixel coordinates fo the mouse
* \param pixelCoords pixel coordinates of the mouse
* \param modKey relevant modifier key pressed during the pick
* \param pickNormal normal at position where object was hit. (0,0,0) means not set.
*/
inline WPickInfo( std::string name,
std::string viewerName,
wmath::WPosition pickPosition,
std::pair< float, float > pixelCoords,
modifierKey modKey,
......@@ -80,10 +81,15 @@ public:
inline void setModifierKey( const modifierKey& modKey );
/**
* Get name of picked object.
*/
* Get name of picked object.
*/
inline std::string getName() const;
/**
* Get name of the viewer.
*/
inline std::string getViewerName() const;
/**
* Get position where object was hit.
*/
......@@ -115,6 +121,7 @@ protected:
private:
std::string m_name; //!< name of picked object.
std::string m_viewerName; //!< name of the viewer
wmath::WPosition m_pickPosition; //!< position where object was hit.
std::pair< float, float > m_pixelCoords; //!< Pixel coordinates of the mouse.
modifierKey m_modKey; //!< modifier key associated with the pick
......@@ -122,11 +129,13 @@ private:
};
WPickInfo::WPickInfo( std::string name,
std::string viewerName,
wmath::WPosition pickPosition,
std::pair< float, float > pixelCoords,
modifierKey modKey,
wmath::WVector3D pickNormal ) :
m_name( name ),
m_viewerName( viewerName ),
m_pickPosition( pickPosition ),
m_pixelCoords( pixelCoords ),
m_modKey( modKey ),
......@@ -136,6 +145,7 @@ WPickInfo::WPickInfo( std::string name,
WPickInfo::WPickInfo() :
m_name( "" ),
m_viewerName( "" ),
m_pickPosition( wmath::WPosition() ),
m_pixelCoords( std::make_pair( 0, 0 ) ),
m_modKey( WPickInfo::NONE )
......@@ -158,6 +168,11 @@ std::string WPickInfo::getName() const
return m_name;
}
std::string WPickInfo::getViewerName() const
{
return m_viewerName;
}
wmath::WPosition WPickInfo::getPickPosition() const
{
return m_pickPosition;
......
......@@ -62,43 +62,6 @@ WQtNavGLWidget::WQtNavGLWidget( QString title, QWidget* parent, std::string slid
m_glWidget->getViewer()->getView()->requestContinuousUpdate( false );
m_glWidget->getViewer()->setScene( m_scene );
if( title == QString( "axial" ) )
{
osg::Matrix m;
m.makeRotate( 90.0, 1.0, 0.0, 0.0 );
osg::Matrix tm;
//tm.makeTranslate( osg::Vec3( 20.0, 0.0, 60.0 ) );
m *= tm;
osg::Matrix sm;
sm.makeScale( 1.2, 1.2, 1.2 );
m *= sm;
m_scene->setMatrix( m );
}
if( title == QString( "coronal" ) )
{
osg::Matrix m;
m.makeIdentity();
osg::Matrix tm;
//tm.makeTranslate( osg::Vec3( 20.0, 0.0, 30.0 ) );
m *= tm;
osg::Matrix sm;
sm.makeScale( 1.2, 1.2, 1.2 );
m *= sm;
m_scene->setMatrix( m );
}
if( title == QString( "sagittal" ) )
{
osg::Matrix m;
m.makeRotate( 90.0, 0.0, 0.0, 1.0 );
osg::Matrix tm;
tm.makeTranslate( osg::Vec3( 200.0, 0.0, 0.0 ) );
m *= tm;
osg::Matrix sm;
sm.makeScale( 1.2, 1.2, 1.2 );
m *= sm;
m_scene->setMatrix( m );
}
m_layout->addWidget( m_glWidget.get() );
panel->setLayout( m_layout );
......
......@@ -133,7 +133,6 @@ void WTubeDrawable::drawFibers( osg::RenderInfo& renderInfo ) const //NOLINT
state.setVertexPointer( 3, GL_FLOAT , 0, &( *verts )[0] );
state.setColorPointer( 3 , GL_FLOAT , 0, &( *colors )[0] );
state.setNormalPointer( GL_FLOAT , 0, &( *tangents )[0] );
for ( size_t i = 0; i < active->size(); ++i )
{
if ( (*active)[i] )
......
......@@ -52,7 +52,7 @@ boost::shared_ptr<WTriangleMesh2>WSphereCreator::createSphere( int resolution, f
boost::shared_ptr<WTriangleMesh2>WSphereCreator::createIcosahedronSphere( int iterations )
{
float t = ( 1 + sqrt( 5 ) ) / 2;
float t = ( 1 + sqrt( 5.0 ) ) / 2;
float tau = t / sqrt( 1 + t * t );
float one = 1 / sqrt( 1 + t * t );
......
......@@ -197,7 +197,8 @@ void WMHud::init()
// connect updateGFX with picking
boost::shared_ptr< WGEViewer > viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
WAssert( viewer, "Requested viewer (main) not found." );
viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMHud::updatePickText, this, _1 ) );
if (viewer->getPickHandler() )
viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMHud::updatePickText, this, _1 ) );
}
void WMHud::updatePickText( WPickInfo pickInfo )
......
......@@ -34,6 +34,7 @@
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/LineWidth>
#include "../../common/WAssert.h"
#include "../../common/math/WVector3D.h"
......@@ -157,6 +158,20 @@ void WMNavSlices::moduleMain()
WAssert( m_viewer, "Requested viewer not found." );
m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
m_viewer = ge->getViewerByName( "axial" );
WAssert( m_viewer, "Requested viewer not found." );
m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
m_viewer = ge->getViewerByName( "sagittal" );
WAssert( m_viewer, "Requested viewer not found." );
m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
m_viewer = ge->getViewerByName( "coronal" );
WAssert( m_viewer, "Requested viewer not found." );
m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
m_viewer = ge->getViewerByName( "main" );
// signal ready state
ready();
......@@ -183,21 +198,24 @@ void WMNavSlices::moduleMain()
if( viewer )
{
viewer->getScene()->remove( m_zSliceNode );
viewer->getScene()->remove( m_zCrossNode );
}
viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "sagittal" );
if( viewer )
{
viewer->getScene()->remove( m_ySliceNode );
viewer->getScene()->remove( m_xSliceNode );
viewer->getScene()->remove( m_xCrossNode );
}
viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "coronal" );
if( viewer )
{
viewer->getScene()->remove( m_xSliceNode );
viewer->getScene()->remove( m_ySliceNode );
viewer->getScene()->remove( m_yCrossNode );
}
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_slicesNode );
// deregister from WSubject's change condition
con.disconnect();
......@@ -206,6 +224,7 @@ void WMNavSlices::moduleMain()
void WMNavSlices::create()
{
m_rootNode = osg::ref_ptr< WGEGroupNode >( new WGEGroupNode() );
m_slicesNode = osg::ref_ptr< WGEGroupNode >( new WGEGroupNode() );
m_xSliceNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
m_xSliceNode->setName( "Sagittal Slice" );
......@@ -218,50 +237,165 @@ void WMNavSlices::create()
m_ySliceNode->addDrawable( createGeometry( 1 ) );
m_zSliceNode->addDrawable( createGeometry( 2 ) );
m_rootNode->insert( m_xSliceNode );
m_rootNode->insert( m_ySliceNode );
m_rootNode->insert( m_zSliceNode );
m_xCrossNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
m_yCrossNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
m_zCrossNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
m_xCrossNode->addDrawable( createCrossGeometry( 0 ) );
m_yCrossNode->addDrawable( createCrossGeometry( 1 ) );
m_zCrossNode->addDrawable( createCrossGeometry( 2 ) );
m_rootNode->insert( m_xCrossNode );
m_rootNode->insert( m_yCrossNode );
m_rootNode->insert( m_zCrossNode );
m_rootNode->insert( m_slicesNode );
m_shader->apply( m_rootNode );
m_slicesNode->insert( m_xSliceNode );
m_slicesNode->insert( m_ySliceNode );
m_slicesNode->insert( m_zSliceNode );
m_shader->apply( m_slicesNode );
m_shader->apply( m_xSliceNode );
m_shader->apply( m_ySliceNode );
m_shader->apply( m_zSliceNode );
osg::StateSet* rootState = m_rootNode->getOrCreateStateSet();
osg::StateSet* rootState = m_slicesNode->getOrCreateStateSet();
initUniforms( rootState );
rootState->setMode( GL_BLEND, osg::StateAttribute::ON );
m_rootNode->setUserData( this );
m_slicesNode->setUserData( this );
m_xSliceNode->setUserData( this );
m_ySliceNode->setUserData( this );
m_zSliceNode->setUserData( this );
m_rootNode->addUpdateCallback( new sliceNodeCallback );
m_xCrossNode->setUserData( this );
m_yCrossNode->setUserData( this );
m_zCrossNode->setUserData( this );
m_slicesNode->addUpdateCallback( new sliceNodeCallback );
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_slicesNode );
// Please, please always check for NULL
boost::shared_ptr< WGEViewer > viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "axial" );
if( viewer )
{
viewer->getScene()->insert( m_zSliceNode );
viewer->getScene()->insert( m_zCrossNode );
viewer->setCameraManipulator( 0 );
}
viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "sagittal" );
if( viewer )
{
viewer->getScene()->insert( m_xSliceNode );
viewer->getScene()->insert( m_xCrossNode );
viewer->setCameraManipulator( 0 );
}
viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "coronal" );
if( viewer )
{
viewer->getScene()->insert( m_ySliceNode );
viewer->getScene()->insert( m_yCrossNode );
viewer->setCameraManipulator( 0 );
}
}
void WMNavSlices::setSlicePosFromPick( WPickInfo pickInfo )
{
// handle the pick information on the slice views
if ( pickInfo.getViewerName() != "main" && pickInfo.getViewerName() != "" )
{
// this uses fixed windows size of 150x150 pixel
boost::unique_lock< boost::shared_mutex > lock;
lock = boost::unique_lock< boost::shared_mutex >( m_updateLock );
float x = pickInfo.getPickPixelPosition().first;
float y = pickInfo.getPickPixelPosition().second;
float xPos;
float yPos;
float width;
float height;
// z slice
if ( pickInfo.getViewerName() == "axial" )
{
width = m_bb.second[0] - m_bb.first[0];
height = m_bb.second[1] - m_bb.first[1];
if ( width > height )
{
xPos = ( x / 150 ) * width;
yPos = ( y / 150 ) * width - ( width - height ) / 2;
}
else
{
xPos = ( x / 150 ) * height - ( height - width ) / 2;
yPos = ( y / 150 ) * height;
}
xPos = xPos < m_bb.first[0] ? m_bb.first[0] : xPos;
xPos = xPos > m_bb.second[0] ? m_bb.second[0] : xPos;
yPos = yPos < m_bb.first[1] ? m_bb.first[1] : yPos;
yPos = yPos > m_bb.second[1] ? m_bb.second[1] : yPos;
m_sagittalPos->set( xPos );
m_coronalPos->set( yPos );
}
// x slice
if ( pickInfo.getViewerName() == "sagittal" )
{
width = m_bb.second[1] - m_bb.first[1];
height = m_bb.second[2] - m_bb.first[2];
if ( width > height )
{
xPos = ( x / 150 ) * width;
yPos = ( y / 150 ) * width - ( width - height ) / 2;
}
else
{
xPos = ( x / 150 ) * height - ( height - width ) / 2;
yPos = ( y / 150 ) * height;
}
xPos = m_bb.second[1] - xPos;
xPos = xPos < m_bb.first[1] ? m_bb.first[1] : xPos;
xPos = xPos > m_bb.second[1] ? m_bb.second[1] : xPos;
yPos = yPos < m_bb.first[2] ? m_bb.first[2] : yPos;
yPos = yPos > m_bb.second[2] ? m_bb.second[2] : yPos;
m_coronalPos->set( xPos );
m_axialPos->set( yPos );
}
// y slice
if ( pickInfo.getViewerName() == "coronal" )
{
width = m_bb.second[0] - m_bb.first[0];
height = m_bb.second[2] - m_bb.first[2];
if ( width > height )
{
xPos = ( x / 150 ) * width;
yPos = ( y / 150 ) * width - ( width - height ) / 2;
}
else
{
xPos = ( x / 150 ) * height - ( height - width ) / 2;
yPos = ( y / 150 ) * height;
}
xPos = xPos < m_bb.first[0] ? m_bb.first[0] : xPos;
xPos = xPos > m_bb.second[0] ? m_bb.second[0] : xPos;
yPos = yPos < m_bb.first[2] ? m_bb.first[2] : yPos;
yPos = yPos > m_bb.second[2] ? m_bb.second[2] : yPos;
m_sagittalPos->set( xPos );
m_axialPos->set( yPos );
}
return;
}
if ( pickInfo.getName() == "Axial Slice"
|| pickInfo.getName() == "Coronal Slice"
|| pickInfo.getName() == "Sagittal Slice" )
......@@ -341,6 +475,7 @@ void WMNavSlices::setMaxMinFromBoundingBox()
if ( tex.size() > 0 )
{
std::pair< wmath::WPosition, wmath::WPosition > bb = tex[0]->getGrid()->getBoundingBox();
for( size_t i = 1; i < tex.size(); ++i )
{
std::pair< wmath::WPosition, wmath::WPosition > bbTmp = tex[i]->getGrid()->getBoundingBox();
......@@ -416,6 +551,7 @@ osg::ref_ptr<osg::Geometry> WMNavSlices::createGeometry( int slice )
sliceGeometry->setTexCoordArray( c, texCoords );
++c;
}
break;
}
case 1:
......@@ -491,17 +627,102 @@ osg::ref_ptr<osg::Geometry> WMNavSlices::createGeometry( int slice )
return sliceGeometry;
}
osg::ref_ptr<osg::Geometry> WMNavSlices::createCrossGeometry( int slice )
{
float xSlice = static_cast< float >( m_sagittalPos->get( true ) );
float ySlice = static_cast< float >( m_coronalPos->get( true ) );
float zSlice = static_cast< float >( m_axialPos->get( true ) );
float xPos = xSlice + 0.5f;
float yPos = ySlice + 0.5f;
float zPos = zSlice + 0.5f;
osg::ref_ptr<osg::Geometry> geometry = osg::ref_ptr<osg::Geometry>( new osg::Geometry() );
osg::Vec3Array* crossVertices = new osg::Vec3Array;
osg::Vec3Array* colorArray = new osg::Vec3Array;
float minx = m_bb.first[0];
float miny = m_bb.first[1];
float minz = m_bb.first[2];
float maxx = m_bb.second[0];
float maxy = m_bb.second[1];
float maxz = m_bb.second[2];
std::vector< wmath::WPosition > vertices;
switch ( slice )
{
case 0:
{
vertices.push_back( wmath::WPosition( xPos - 0.5f, miny, zPos ) );
vertices.push_back( wmath::WPosition( xPos - 0.5f, maxy, zPos ) );
vertices.push_back( wmath::WPosition( xPos - 0.5f, yPos, minz ) );
vertices.push_back( wmath::WPosition( xPos - 0.5f, yPos, maxz ) );
break;
}
case 1:
{
vertices.push_back( wmath::WPosition( minx, yPos - 0.5f, zPos ) );
vertices.push_back( wmath::WPosition( maxx, yPos - 0.5f, zPos ) );
vertices.push_back( wmath::WPosition( xPos, yPos - 0.5f, minz ) );
vertices.push_back( wmath::WPosition( xPos, yPos - 0.5f, maxz ) );
break;
}
case 2:
{
vertices.push_back( wmath::WPosition( minx, yPos, zPos + 0.5f ) );
vertices.push_back( wmath::WPosition( maxx, yPos, zPos + 0.5f ) );
vertices.push_back( wmath::WPosition( xPos, miny, zPos + 0.5f ) );
vertices.push_back( wmath::WPosition( xPos, maxy, zPos + 0.5f ) );
break;
}
}
for( size_t i = 0; i < 4; ++i )
{
crossVertices->push_back( wge::wv3D2ov3( vertices[i] ) );
}
colorArray->push_back( osg::Vec3( 1.0f, 0.0f, 0.0f ) );
geometry->setColorArray( colorArray );
geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
geometry->setVertexArray( crossVertices );
unsigned int rawIndexData[] = { 0, 1, 2, 3 }; // NOLINT
std::vector< unsigned int > indexData( rawIndexData, rawIndexData + sizeof( rawIndexData ) / sizeof( unsigned int ) );
osg::DrawElementsUInt* lines = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, indexData.begin(), indexData.end() );
geometry->addPrimitiveSet( lines );
// disable light for this geode as lines can't be lit properly