Commit d989572a by Sebastian Eichelbaum

[MERGE]

parents 76815167 7443b377
......@@ -24,6 +24,7 @@
#include <string>
#include <algorithm>
#include <utility>
#include <vector>
#include <iostream>
#include <boost/filesystem/fstream.hpp>
......@@ -48,13 +49,16 @@ WDataSetFibers::WDataSetFibers()
WDataSetFibers::WDataSetFibers( boost::shared_ptr< std::vector< float > >vertices,
boost::shared_ptr< std::vector< size_t > > lineStartIndexes,
boost::shared_ptr< std::vector< size_t > > lineLengths,
boost::shared_ptr< std::vector< size_t > > verticesReverse )
boost::shared_ptr< std::vector< size_t > > verticesReverse,
std::pair< wmath::WPosition, wmath::WPosition > boundingBox )
: WDataSet(),
m_vertices( vertices ),
m_localColors( boost::shared_ptr< std::vector< float > >() ),
m_lineStartIndexes( lineStartIndexes ),
m_lineLengths( lineLengths ),
m_verticesReverse( verticesReverse )
m_verticesReverse( verticesReverse ),
m_bbMin( boundingBox.first ),
m_bbMax( boundingBox.second )
{
m_tangents = boost::shared_ptr< std::vector< float > >( new std::vector<float>() );
......@@ -293,3 +297,8 @@ void WDataSetFibers::saveSelected( std::string filename, boost::shared_ptr< std:
ofs << vBuffer[i];
}
}
std::pair< wmath::WPosition, wmath::WPosition > WDataSetFibers::getBoundingBox() const
{
return std::make_pair( m_bbMin, m_bbMax );
}
......@@ -26,6 +26,7 @@
#define WDATASETFIBERS_H
#include <string>
#include <utility>
#include <vector>
#include <boost/shared_ptr.hpp>
......@@ -65,11 +66,13 @@ public:
* \param lineStartIndexes the index in which the fiber start (index of the 3D-vertex, not the index of the float in the vertices vector)
* \param lineLengths how many vertices belong to a fiber
* \param verticesReverse stores for each vertex the index of the corresponding fiber
* \param boundingBox The bounding box of the fibers (first minimum, secon maximum). If not given both are (0,0,0).
*/
WDataSetFibers( boost::shared_ptr< std::vector< float > >vertices,
boost::shared_ptr< std::vector< size_t > > lineStartIndexes,
boost::shared_ptr< std::vector< size_t > > lineLengths,
boost::shared_ptr< std::vector< size_t > > verticesReverse );
boost::shared_ptr< std::vector< size_t > > verticesReverse,
std::pair< wmath::WPosition, wmath::WPosition > boundingBox = std::make_pair( wmath::WPosition(), wmath::WPosition() ) );
/**
* Constructs a new set of WFibers. The constructed instance is not usable.
......@@ -171,6 +174,12 @@ public:
* \param active bitfield of the fiber selection
*/
void saveSelected( std::string filename, boost::shared_ptr< std::vector< bool > > active ) const;
/**
* Get the bounding box as pair of WPositions.
*/
std::pair< wmath::WPosition, wmath::WPosition > getBoundingBox() const;
protected:
/**
......@@ -216,6 +225,9 @@ private:
* Reverse lookup table for which point belongs to which fiber
*/
boost::shared_ptr< std::vector< size_t > > m_verticesReverse;
wmath::WPosition m_bbMin; //!< Minimum position of bounding box of all fibers.
wmath::WPosition m_bbMax; //!< Maximum position of bounding box of all fibers.
};
#endif // WDATASETFIBERS_H
......@@ -339,10 +339,17 @@ wmath::WVector3D WGridRegular3D::worldCoordToTexCoord( wmath::WPosition point )
{
wmath::WVector3D r( wmath::transformPosition3DWithMatrix4D( m_matrixInverse, point ) );
// Scale to [0,1]
r[0] = r[0] / m_nbPosX;
r[1] = r[1] / m_nbPosY;
r[2] = r[2] / m_nbPosZ;
// Correct the coordinates to have the position at the center of the texture voxel.
r[0] += 0.5 / m_nbPosX;
r[1] += 0.5 / m_nbPosY;
r[2] += 0.5 / m_nbPosZ;
return r;
}
......@@ -540,6 +547,134 @@ std::vector< size_t > WGridRegular3D::getNeighbours( size_t id ) const
return neighbours;
}
std::vector< size_t > WGridRegular3D::getNeighbours27( size_t id ) const
{
std::vector< size_t > neighbours;
size_t x = id % m_nbPosX;
size_t y = ( id / m_nbPosX ) % m_nbPosY;
size_t z = id / ( m_nbPosX * m_nbPosY );
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
{
std::stringstream ss;
ss << "This point: " << id << " is not part of this grid: ";
ss << " nbPosX: " << m_nbPosX;
ss << " nbPosY: " << m_nbPosY;
ss << " nbPosZ: " << m_nbPosZ;
throw WOutOfBounds( ss.str() );
}
// for every neighbour we must check if its not on the boundary, it will be skipped otherwise
if( x > 0 )
{
neighbours.push_back( id - 1 );
if( y > 0 )
{
neighbours.push_back( id - m_nbPosX - 1 );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( id + m_nbPosX - 1 );
}
}
if( x < m_nbPosX - 1 )
{
neighbours.push_back( id + 1 );
if( y > 0 )
{
neighbours.push_back( id - m_nbPosX + 1 );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( id + m_nbPosX + 1 );
}
}
if( y > 0 )
{
neighbours.push_back( id - m_nbPosX );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( id + m_nbPosX );
}
if( z > 0 )
{
int tempId = id - ( m_nbPosX * m_nbPosY );
neighbours.push_back( tempId );
if( x > 0 )
{
neighbours.push_back( tempId - 1 );
if( y > 0 )
{
neighbours.push_back( tempId - m_nbPosX - 1 );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( tempId + m_nbPosX - 1 );
}
}
if( x < m_nbPosX - 1 )
{
neighbours.push_back( tempId + 1 );
if( y > 0 )
{
neighbours.push_back( tempId - m_nbPosX + 1 );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( tempId + m_nbPosX + 1 );
}
}
if( y > 0 )
{
neighbours.push_back( tempId - m_nbPosX );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( tempId + m_nbPosX );
}
}
if( z < m_nbPosZ - 1 )
{
int tempId = id + ( m_nbPosX * m_nbPosY );
neighbours.push_back( tempId );
if( x > 0 )
{
neighbours.push_back( tempId - 1 );
if( y > 0 )
{
neighbours.push_back( tempId - m_nbPosX - 1 );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( tempId + m_nbPosX - 1 );
}
}
if( x < m_nbPosX - 1 )
{
neighbours.push_back( tempId + 1 );
if( y > 0 )
{
neighbours.push_back( tempId - m_nbPosX + 1 );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( tempId + m_nbPosX + 1 );
}
}
if( y > 0 )
{
neighbours.push_back( tempId - m_nbPosX );
}
if( y < m_nbPosY - 1 )
{
neighbours.push_back( tempId + m_nbPosX );
}
}
return neighbours;
}
bool WGridRegular3D::encloses( const wmath::WPosition& pos ) const
{
return getVoxelNum( pos ) != -1; // note this is an integer comparision, hence it should be numerical stable!
......
......@@ -407,6 +407,18 @@ public:
std::vector< size_t > getNeighbours( size_t id ) const;
/**
* Return the list of all neighbour voxels.
*
* \throw WOutOfBounds If the voxel id is outside of the grid.
*
* \param id Number of the voxel for which the neighbours should be computed
*
* \return Vector of voxel ids which are all neighboured
*/
std::vector< size_t > getNeighbours27( size_t id ) const;
/**
* Decides whether a certain position is inside this grid or not.
*
* \param pos Position to test
......
......@@ -30,6 +30,7 @@
#include <boost/shared_ptr.hpp>
#include "../../common/WIOTools.h"
#include "../../common/WLimits.h"
#include "../../common/WAssert.h"
#include "../../common/WLogger.h"
#include "../../common/WStringUtils.h"
......@@ -40,7 +41,9 @@
#include "WReaderFiberVTK.h"
WReaderFiberVTK::WReaderFiberVTK( std::string fname )
: WReader( fname )
: WReader( fname ),
m_bbMin( wmath::WPosition( wlimits::MAX_DOUBLE, wlimits::MAX_DOUBLE, wlimits::MAX_DOUBLE ) ),
m_bbMax( wmath::WPosition( -wlimits::MAX_DOUBLE, -wlimits::MAX_DOUBLE, -wlimits::MAX_DOUBLE ) )
{
}
......@@ -70,7 +73,8 @@ boost::shared_ptr< WDataSetFibers > WReaderFiberVTK::read()
boost::shared_ptr< WDataSetFibers > fibers = boost::shared_ptr< WDataSetFibers >( new WDataSetFibers( m_points,
m_fiberStartIndices,
m_fiberLengths,
m_pointFiberMapping ) );
m_pointFiberMapping,
std::make_pair( m_bbMin, m_bbMax ) ) );
fibers->setFileName( m_fname );
m_ifs->close();
......@@ -129,6 +133,16 @@ void WReaderFiberVTK::readPoints()
m_points = boost::shared_ptr< std::vector< float > >( new std::vector< float >( pointData, pointData + 3 * numPoints ) );
WAssert( m_points->size() % 3 == 0, "Number of floats for coordinates not dividable by three." );
for( size_t i = 0; i < m_points->size()/3; ++i )
{
m_bbMin[0] = m_bbMin[0] < ( *m_points )[i*3+0] ? m_bbMin[0] : ( *m_points )[i*3+0];
m_bbMin[1] = m_bbMin[1] < ( *m_points )[i*3+1] ? m_bbMin[1] : ( *m_points )[i*3+1];
m_bbMin[2] = m_bbMin[2] < ( *m_points )[i*3+2] ? m_bbMin[2] : ( *m_points )[i*3+2];
m_bbMax[0] = m_bbMax[0] > ( *m_points )[i*3+0] ? m_bbMax[0] : ( *m_points )[i*3+0];
m_bbMax[1] = m_bbMax[1] > ( *m_points )[i*3+1] ? m_bbMax[1] : ( *m_points )[i*3+1];
m_bbMax[2] = m_bbMax[2] > ( *m_points )[i*3+2] ? m_bbMax[2] : ( *m_points )[i*3+2];
}
delete[] pointData;
// since we know here the size of the vector we may allocate it right here
......
......@@ -122,6 +122,9 @@ private:
*/
std::string getLine( const std::string& desc );
wmath::WPosition m_bbMin; //!< Minimum position of bounding box of all fibers.
wmath::WPosition m_bbMax; //!< Maximum position of bounding box of all fibers.
/**
* Try to cast from the given string to the template value T. If the cast fails a
* WDHParseError is thrown.
......
......@@ -28,9 +28,10 @@
WGEZoomTrackballManipulator::WGEZoomTrackballManipulator():
TrackballManipulator(),
m_allowThrow( false )
m_zoom( 1.0 ),
m_allowThrow( false ),
m_paintMode( 0 )
{
m_zoom = 1.0;
setTrackballSize( .3 ); // changes the effect of a mouse move for rotation
WPreferences::getPreference( "ge.zoomTrackballManipulator.allowThrow", &m_allowThrow );
}
......@@ -135,12 +136,28 @@ bool WGEZoomTrackballManipulator::handle( const osgGA::GUIEventAdapter& ea, osgG
}
// NOTE: we need to ignore the right mouse-button drag! This manipulates the underlying Trackball Manipulator while, at the same time, is
// used for moving ROIS! Zooming is done using Scroll Wheel or +/- keys.
else if ( ( ea.getEventType() == osgGA::GUIEventAdapter::DRAG ) && ( ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON ) )
else if ( ( ea.getEventType() == osgGA::GUIEventAdapter::DRAG ) || ( ea.getEventType() == osgGA::GUIEventAdapter::PUSH ) )
{
return true;
if ( ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
{
return true;
}
else if ( ( ea.getButtonMask() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ) && ( m_paintMode == 1 ) )
{
return true;
}
else
{
return TrackballManipulator::handle( ea, us );
}
}
else
{
return TrackballManipulator::handle( ea, us );
}
}
void WGEZoomTrackballManipulator::setPaintMode( int mode )
{
m_paintMode = mode;
}
......@@ -88,6 +88,14 @@ public:
*/
void setZoom( double zoom );
/**
* setter for paint mode
* when set to something different from 0, a left drag should move the scene
*
* \param mode the mode
*/
void setPaintMode( int mode );
protected:
private:
......@@ -100,6 +108,8 @@ private:
double m_zoom; //!< Zoom factor.
bool m_allowThrow; //!< Do we want the auto-rotation thingy?
int m_paintMode; //!<paint mode
};
inline double WGEZoomTrackballManipulator::getZoom() const
......
......@@ -35,7 +35,9 @@ WPickHandler::WPickHandler()
m_startPick( WPickInfo() ),
m_shift( false ),
m_ctrl( false ),
m_viewerName( "" )
m_viewerName( "" ),
m_paintMode( 0 ),
m_mouseButton( WPickInfo::NOMOUSE )
{
}
......@@ -44,7 +46,9 @@ WPickHandler::WPickHandler( std::string viewerName )
m_startPick( WPickInfo() ),
m_shift( false ),
m_ctrl( false ),
m_viewerName( viewerName )
m_viewerName( viewerName ),
m_paintMode( 0 ),
m_mouseButton( WPickInfo::NOMOUSE )
{
}
......@@ -72,6 +76,16 @@ bool WPickHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAda
unsigned int buttonMask = ea.getButtonMask();
if( buttonMask == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
{
m_mouseButton = WPickInfo::MOUSE_RIGHT;
osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
if ( view )
{
pick( view, ea );
}
}
if( ( buttonMask == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON ) && ( m_paintMode == 1 ) )
{
m_mouseButton = WPickInfo::MOUSE_LEFT;
osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
if ( view )
{
......@@ -82,6 +96,7 @@ bool WPickHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAda
}
case osgGA::GUIEventAdapter::RELEASE : // Mousebutton released
{
m_mouseButton = WPickInfo::NOMOUSE;
osgViewer::View* view = static_cast< osgViewer::View* >( &aa );
if ( view )
{
......@@ -159,7 +174,7 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
{
WPickInfo pickInfo;
pickInfo = WPickInfo( "", m_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
m_startPick.getModifierKey(), m_startPick.getPickNormal() );
m_startPick.getModifierKey(), m_mouseButton, m_startPick.getPickNormal() );
m_hitResult = pickInfo;
// if nothing was picked before remember the currently picked.
......@@ -186,7 +201,7 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
{
std::string nodeName = extractSuitableName( hitr );
// now we skip everything that starts with an underscore
if( nodeName[0] == '_' )
if( nodeName[0] == '_' && ( m_paintMode == 0 ) )
{
++hitr;
}
......@@ -238,14 +253,15 @@ 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 ), m_viewerName, pickPos, std::make_pair( x, y ), WPickInfo::NONE, pickNormal );
pickInfo = WPickInfo( extractSuitableName( hitr ), m_viewerName, pickPos, std::make_pair( x, y ),
WPickInfo::NONE, m_mouseButton, 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_viewerName, m_startPick.getPickPosition(), std::make_pair( x, y ),
m_startPick.getModifierKey(), m_startPick.getPickNormal() );
m_startPick.getModifierKey(), m_mouseButton, m_startPick.getPickNormal() );
}
if( m_shift )
......@@ -260,3 +276,8 @@ void WPickHandler::pick( osgViewer::View* view, const osgGA::GUIEventAdapter& ea
m_pickSignal( getHitResult() );
}
void WPickHandler::setPaintMode( int mode )
{
m_paintMode = mode;
}
......@@ -100,6 +100,12 @@ public:
*/
boost::signals2::signal1< void, WPickInfo >* getPickSignal();
/**
* setter for paint mode
* \param mode the paint mode
*/
void setPaintMode( int mode );
protected:
/**
* Virtual destructor needed because of virtual function.
......@@ -117,6 +123,9 @@ protected:
bool m_shift; //!< is shift pressed?
bool m_ctrl; //!< is ctrl pressed?
std::string m_viewerName; //!< which viewer sends the signal
int m_paintMode; //!< the paint mode
WPickInfo::WMouseButton m_mouseButton; //!< stores mouse button that initiated the pick
private:
boost::signals2::signal1<void, WPickInfo > m_pickSignal; //!< One can register to this signal to receive pick events.
......
......@@ -32,6 +32,7 @@
#include "../common/math/WVector3D.h"
#include "WExportWGE.h"
/**
* Encapsulates info for pick action.
*/
......@@ -51,12 +52,27 @@ public:
};
/**
* Different types of mouse buttons.
*/
typedef enum
{
NOMOUSE,
MOUSE_LEFT,
MOUSE_RIGHT,
MOUSE_MIDDLE,
MOUSE4,
MOUSE5
}
WMouseButton;
/**
* Creates an object with the needed information.
* \param name name of picked object
* \param viewerName name of the viewer
* \param pickPosition position where object was hit
* \param pixelCoords pixel coordinates of the mouse
* \param modKey relevant modifier key pressed during the pick
* \param mButton mouse button that initiated the pick
* \param pickNormal normal at position where object was hit. (0,0,0) means not set.
*/
inline WPickInfo( std::string name,
......@@ -64,6 +80,7 @@ public:
wmath::WPosition pickPosition,
std::pair< float, float > pixelCoords,
modifierKey modKey,
WMouseButton mButton = WPickInfo::MOUSE_LEFT,
wmath::WVector3D pickNormal = wmath::WVector3D() );
/**
......@@ -77,12 +94,24 @@ public:
inline modifierKey getModifierKey() const;
/**
* Get the mouse button associated with the pick
*/
inline WMouseButton getMouseButton() const;
/**
* Set the modifier key associated with the pick
* \param modKey new modifier key
*/
inline void setModifierKey( const modifierKey& modKey );
/**
* Set the modifier key associated with the pick
* \param mButton new mouse button
*/
inline void setMouseButton( const WMouseButton& mButton );
/**
* Get name of picked object.
*/
inline std::string getName() const;
......@@ -127,6 +156,7 @@ private:
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
WMouseButton m_mouseButton; //!< which mouse button was used for the pick
wmath::WVector3D m_pickNormal; //!< normal at position where object was hit.
};
......@@ -135,12 +165,14 @@ WPickInfo::WPickInfo( std::string name,
wmath::WPosition pickPosition,
std::pair< float, float > pixelCoords,
modifierKey modKey,
WMouseButton mButton,
wmath::WVector3D pickNormal ) :
m_name( name ),
m_viewerName( viewerName ),
m_pickPosition( pickPosition ),
m_pixelCoords( pixelCoords ),
m_modKey( modKey ),
m_mouseButton( mButton ),
m_pickNormal( pickNormal )
{
}
......@@ -150,7 +182,8 @@ WPickInfo::WPickInfo() :
m_viewerName( "" ),
m_pickPosition( wmath::WPosition() ),
m_pixelCoords( std::make_pair( 0, 0 ) ),
m_modKey( WPickInfo::NONE )
m_modKey( WPickInfo::NONE ),
m_mouseButton( WPickInfo::MOUSE_LEFT )
{
}
......@@ -164,6 +197,15 @@ void WPickInfo::setModifierKey( const modifierKey& modKey )
m_modKey = modKey;
}
WPickInfo::WMouseButton WPickInfo::getMouseButton() const
{
return m_mouseButton;
}
void WPickInfo::setMouseButton( const WMouseButton& mButton )
{
m_mouseButton = mButton;
}
std::string WPickInfo::getName() const
{
......
......@@ -134,27 +134,70 @@ vec3 atlasColorMap ( in float value )
float r = 0.0;
float g = 0.0;
float b = 0.0;
float mult = 1.0;
if ( val == 0.0 )
{
return vec3( 0.0 );
}
if ( isBitSet( val, 0.0 ) )
r = 0.4;
b = 1.0;
if ( isBitSet( val, 1.0 ) )
g = 0.4;
g = 1.0;
if ( isBitSet( val, 2.0 ) )
b = 0.4;
r = 1.0;
if ( isBitSet( val, 3.0 ) )
b += 0.3;
{
mult -= 0.15;
if ( r < 1.0 && g < 1.0 && b < 1.0 )
{
r = 1.0;
g = 1.0;
}
}
if ( isBitSet( val, 4.0 ) )
r += 0.3;
{
mult -= 0.15;
if ( r < 1.0 && g < 1.0 && b < 1.0 )
{
b = 1.0;
g = 1.0;
}
}
if ( isBitSet( val, 5.0 ) )
g += 0.3;
{
mult -= 0.15;
if ( r < 1.0 && g < 1.0 && b < 1.0 )
{
r = 1.0;
b = 1.0;
}
}
if ( isBitSet( val, 6.0 ) )
r += 0.3;
{
mult -= 0.15;
if ( r < 1.0 && g < 1.0 && b < 1.0 )
{
g = 1.0;
}
}
if ( isBitSet( val, 7.0 ) )
b += 0.3;
{
mult -= 0.15;
if ( r < 1.0 && g < 1.0 && b < 1.0 )
{
r = 1.0;
}
}
r *= 1.5;
g *= 1.5;
b *= 1.5;
r *= mult;
g *= mult;
b *= mult;
clamp( r, 0., 1.);
clamp( g, 0., 1.);
......@@ -163,6 +206,8 @@ vec3 atlasColorMap ( in float value )
return vec3( r, g, b );
}
vec3 colorMap5( in float value )
{
vec4 color0 = vec4(255./255., 255./255., 217./255., 1.);
......
......@@ -29,6 +29,8 @@
#include "WKernel.h"
#include "../common/math/WLinearAlgebraFunctions.h"
#include "../graphicsEngine/WGEZoomTrackballManipulator.h"
#include "WSelectionManager.h"
using wmath::WVector3D;
......@@ -36,7 +38,10 @@ using wmath::WPosition;
using wmath::WMatrix;
WSelectionManager::WSelectionManager()
WSelectionManager::WSelectionManager() :
m_paintMode( PAINTMODE_NONE ),
m_textureOpacity( 1.0 ),
m_useTexture( false )
{
m_crosshair = boost::shared_ptr< WCrosshair >( new WCrosshair() );
}
......@@ -106,3 +111,63 @@ int WSelectionManager::getFrontSector()
}
return quadrant;
}
void WSelectionManager::setPaintMode( WPaintMode mode )
{
m_paintMode = mode;
osg::static_pointer_cast<WGEZoomTrackballManipulator>(
WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getCameraManipulator() )->setPaintMode( mode );
WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getPickHandler()->setPaintMode( mode );
}
WPaintMode WSelectionManager::getPaintMode()
{
return m_paintMode;