Commit 05409210 authored by schurade's avatar schurade

[CHANGE] improved the texture painting

parent ba8c0b46
......@@ -39,7 +39,9 @@ using wmath::WMatrix;
WSelectionManager::WSelectionManager() :
m_paintMode( PAINTMODE_NONE )
m_paintMode( PAINTMODE_NONE ),
m_textureOpacity( 1.0 ),
m_useTexture( false )
{
m_crosshair = boost::shared_ptr< WCrosshair >( new WCrosshair() );
}
......@@ -124,3 +126,48 @@ WPaintMode WSelectionManager::getPaintMode()
return m_paintMode;
}
void WSelectionManager::setTexture( osg::ref_ptr< osg::Texture3D > texture, boost::shared_ptr< WGridRegular3D >grid )
{
m_texture = texture;
m_textureGrid = grid;
}
osg::ref_ptr< osg::Texture3D > WSelectionManager::getTexture()
{
return m_texture;
}
boost::shared_ptr< WGridRegular3D >WSelectionManager::getGrid()
{
return m_textureGrid;
}
void WSelectionManager::setUseTexture( bool flag )
{
m_useTexture = flag;
}
bool WSelectionManager::getUseTexture()
{
return m_useTexture;
}
float WSelectionManager::getTextureOpacity()
{
return m_textureOpacity;
}
void WSelectionManager::setTextureOpacity( float value )
{
if ( value < 0.0 )
{
value = 0.0;
}
if ( value > 1.0 )
{
value = 1.0;
}
m_textureOpacity = value;
}
......@@ -80,11 +80,76 @@ public:
*/
WPaintMode getPaintMode();
/**
* setter for texture and grid
*
* \param texture
* \param grid
*/
void setTexture( osg::ref_ptr< osg::Texture3D > texture, boost::shared_ptr< WGridRegular3D >grid );
/**
* getter
* \return texture
*/
osg::ref_ptr< osg::Texture3D > getTexture();
/**
* getter
* \return grid
*/
boost::shared_ptr< WGridRegular3D >getGrid();
/**
* setter
* \param flag
*/
void setUseTexture( bool flag = true );
/**
* getter
* \return flag
*/
bool getUseTexture();
/**
* getter
* \return the opacity
*/
float getTextureOpacity();
/**
* setter
* \param value the new opacity to use with the texture
*/
void setTextureOpacity( float value );
protected:
private:
boost::shared_ptr< WCrosshair >m_crosshair; //!< stores pointer to crosshair
WPaintMode m_paintMode; //!< stores the currently selected paint mode
/**
* stores a pointer to a texture 3d, this is used to provide a faster texture generation process
* than creating a new dataset for every texture change
*/
osg::ref_ptr< osg::Texture3D > m_texture;
/**
* stores a pointer to the grid to be used together with the texture
*/
boost::shared_ptr< WGridRegular3D >m_textureGrid;
/**
* the texture opacity
*/
float m_textureOpacity;
/**
* flag indicating if this additional texture should be used.
*/
bool m_useTexture;
};
#endif // WSELECTIONMANAGER_H
......@@ -581,6 +581,20 @@ osg::ref_ptr<osg::Geometry> WMNavSlices::createGeometry( int slice )
sliceGeometry->setVertexArray( sliceVertices );
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
osg::Vec3Array* texCoords = new osg::Vec3Array;
for( size_t i = 0; i < nbVerts; ++i )
{
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
}
sliceGeometry->setTexCoordArray( c, texCoords );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();
......@@ -610,6 +624,20 @@ osg::ref_ptr<osg::Geometry> WMNavSlices::createGeometry( int slice )
sliceGeometry->setVertexArray( sliceVertices );
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
osg::Vec3Array* texCoords = new osg::Vec3Array;
for( size_t i = 0; i < nbVerts; ++i )
{
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
}
sliceGeometry->setTexCoordArray( c, texCoords );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();
......@@ -639,6 +667,20 @@ osg::ref_ptr<osg::Geometry> WMNavSlices::createGeometry( int slice )
sliceGeometry->setVertexArray( sliceVertices );
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
osg::Vec3Array* texCoords = new osg::Vec3Array;
for( size_t i = 0; i < nbVerts; ++i )
{
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
}
sliceGeometry->setTexCoordArray( c, texCoords );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();
......@@ -817,6 +859,26 @@ void WMNavSlices::updateTextures()
// for each texture -> apply
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
osg::ref_ptr<osg::Texture3D> texture3D = WKernel::getRunningKernel()->getSelectionManager()->getTexture();
m_typeUniforms[c]->set( W_DT_UNSIGNED_CHAR );
m_thresholdUniforms[c]->set( 0.0f );
m_alphaUniforms[c]->set( WKernel::getRunningKernel()->getSelectionManager()->getTextureOpacity() );
m_cmapUniforms[c]->set( 4 );
texture3D->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
texture3D->setFilter( osg::Texture::MAG_FILTER, osg::Texture::NEAREST );
rootState->setTextureAttributeAndModes( c, texture3D, osg::StateAttribute::ON );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
osg::ref_ptr<osg::Texture3D> texture3D = ( *iter )->getTexture();
......
......@@ -283,6 +283,21 @@ void WMArbitraryPlane::updatePlane()
std::vector< boost::shared_ptr< WDataTexture3D > > tex = WDataHandler::getDefaultSubject()->getDataTextures( true );
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
osg::Vec3Array* texCoords = new osg::Vec3Array;
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( v0 ) ) );
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( v1 ) ) );
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( v2 ) ) );
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( v3 ) ) );
planeGeometry->setTexCoordArray( c, texCoords );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();
......@@ -357,6 +372,25 @@ void WMArbitraryPlane::updateTextures()
// for each texture -> apply
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
osg::ref_ptr<osg::Texture3D> texture3D = WKernel::getRunningKernel()->getSelectionManager()->getTexture();
m_typeUniforms[c]->set( W_DT_UNSIGNED_CHAR );
m_thresholdUniforms[c]->set( 0.0f );
m_alphaUniforms[c]->set( WKernel::getRunningKernel()->getSelectionManager()->getTextureOpacity() );
m_cmapUniforms[c]->set( 4 );
texture3D->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
texture3D->setFilter( osg::Texture::MAG_FILTER, osg::Texture::NEAREST );
rootState->setTextureAttributeAndModes( c, texture3D, osg::StateAttribute::ON );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
osg::ref_ptr<osg::Texture3D> texture3D = ( *iter )->getTexture();
......
......@@ -586,6 +586,37 @@ void WMMarchingCubes::updateGraphics()
// for each texture -> apply
int c = 0;
//////////////////////////////////////////////////////////////////////////////////////////////////
if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
{
boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
osg::ref_ptr< osg::Geometry > surfaceGeometry = m_surfaceGeode->getDrawable( 0 )->asGeometry();
osg::Vec3Array* texCoords = new osg::Vec3Array;
for( size_t i = 0; i < m_triMesh->vertSize(); ++i )
{
osg::Vec3 vertPos = m_triMesh->getVertex( i );
texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( wmath::WPosition( vertPos[0], vertPos[1], vertPos[2] ) ) ) );
}
surfaceGeometry->setTexCoordArray( c, texCoords );
osg::ref_ptr<osg::Texture3D> texture3D = WKernel::getRunningKernel()->getSelectionManager()->getTexture();
m_typeUniforms[c]->set( W_DT_UNSIGNED_CHAR );
m_thresholdUniforms[c]->set( 0.0f );
m_alphaUniforms[c]->set( WKernel::getRunningKernel()->getSelectionManager()->getTextureOpacity() );
m_cmapUniforms[c]->set( 4 );
texture3D->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST );
texture3D->setFilter( osg::Texture::MAG_FILTER, osg::Texture::NEAREST );
rootState->setTextureAttributeAndModes( c, texture3D, osg::StateAttribute::ON );
++c;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
{
if( localTextureChangedFlag )
......
......@@ -29,6 +29,7 @@
#include "../../kernel/WKernel.h"
#include "../../dataHandler/WDataHandler.h"
#include "../../dataHandler/WDataTexture3D.h"
#include "../../dataHandler/WSubject.h"
#include "../../common/WPropertyHelper.h"
......@@ -86,6 +87,9 @@ void WMPaintTexture::properties()
{
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
// use this callback for the other properties
WPropertyBase::PropertyChangeNotifierType propertyCallback = boost::bind( &WMPaintTexture::propertyChanged, this, _1 );
m_painting = m_properties->addProperty( "Paint", "If active, left click in the scene with pressed ctrl key"
" will paint something.", false, m_propCondition );
......@@ -100,15 +104,8 @@ void WMPaintTexture::properties()
m_paintIndex->setMin( 0 );
m_paintIndex->setMax( 255 );
// these are taken from WMData
m_interpolation = m_properties->addProperty( "Interpolation",
"If active, the boundaries of single voxels"
" will not be visible in colormaps. The transition between"
" them will be smooth by using interpolation then.",
false,
m_propCondition );
m_opacity = m_properties->addProperty( "Opacity %", "The opacity of this data in colormaps combining"
" values from several data sets.", 100, m_propCondition );
" values from several data sets.", 100, propertyCallback );
m_opacity->setMax( 100 );
m_opacity->setMin( 0 );
......@@ -125,6 +122,18 @@ void WMPaintTexture::properties()
m_queueAdded = m_properties->addProperty( "Something paint", "", false, m_propCondition );
m_queueAdded->setHidden();
m_buttonUpdateOutput = m_properties->addProperty( "Update output", "Updates the output connector",
WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
}
void WMPaintTexture::propertyChanged( boost::shared_ptr< WPropertyBase > property )
{
if ( property == m_opacity )
{
WKernel::getRunningKernel()->getSelectionManager()->setTextureOpacity( m_opacity->get( true ) / 100.0 );
WDataHandler::getDefaultSubject()->getChangeCondition()->notify();
}
}
void WMPaintTexture::moduleMain()
......@@ -159,29 +168,11 @@ void WMPaintTexture::moduleMain()
WAssert( m_dataSet, "" );
WAssert( m_dataSet->getValueSet(), "" );
if( m_outData )
{
WDataHandler::deregisterDataSet( m_outData );
}
m_outData = createNewOutTexture();
createTexture();
if( m_outData )
{
setOutputProps();
m_outData->setFileName( std::string( "painted" ) );
WDataHandler::registerDataSet( m_outData );
updateOutDataset();
}
m_output->updateData( m_outData );
}
else
{
if( m_outData )
{
setOutputProps();
}
}
if ( m_painting->changed() )
{
if ( m_painting->get( true ) )
......@@ -197,99 +188,58 @@ void WMPaintTexture::moduleMain()
else // case !dataValid
{
if( m_outData )
{
WDataHandler::deregisterDataSet( m_outData );
}
m_outData = boost::shared_ptr< WDataSetScalar >();
m_output->updateData( m_outData );
}
if ( m_queueAdded->changed() && m_queueAdded->get( true ) )
{
boost::shared_ptr< WDataSetScalar > old;
if( m_outData )
{
old = m_outData;
doPaint();
}
m_outData = doPaint();
WDataHandler::registerDataSet( m_outData );
WDataHandler::deregisterDataSet( old );
m_output->updateData( m_outData );
if ( m_buttonUpdateOutput->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED )
{
updateOutDataset();
m_buttonUpdateOutput->set( WPVBaseTypes::PV_TRIGGER_READY, false );
}
}
debugLog() << "Shutting down...";
if( m_outData )
{
WDataHandler::deregisterDataSet( m_outData );
}
WKernel::getRunningKernel()->getSelectionManager()->setUseTexture( false );
WDataHandler::getDefaultSubject()->getChangeCondition()->notify();
debugLog() << "Finished! Good Bye!";
}
void WMPaintTexture::activate()
{
if( m_outData )
{
m_outData->getTexture()->setGloballyActive( m_active->get() );
}
WModule::activate();
}
void WMPaintTexture::setOutputProps()
{
if( m_outData )
{
m_outData->getTexture()->setThreshold( 0 );
m_outData->getTexture()->setOpacity( m_opacity->get() );
m_outData->getTexture()->setInterpolation( m_interpolation->get() );
m_outData->getTexture()->setSelectedColormap( m_colorMapSelection->get( true ).getItemIndexOfSelected( 0 ) );
}
}
boost::shared_ptr< WDataSetScalar > WMPaintTexture::createNewOutTexture()
{
WAssert( m_dataSet, "" );
WAssert( m_dataSet->getValueSet(), "" );
WAssert( m_dataSet->getGrid(), "" );
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
WAssert( grid, "" );
m_values.resize( m_dataSet->getGrid()->size(), 0 );
m_values[0] = 255;
boost::shared_ptr< WValueSet< unsigned char > > vs =
boost::shared_ptr< WValueSet< unsigned char > >( new WValueSet< unsigned char >( 0, 1, m_values, W_DT_UINT8 ) );
return boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
}
boost::shared_ptr< WDataSetScalar > WMPaintTexture::doPaint()
void WMPaintTexture::doPaint()
{
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_outData->getGrid() );
unsigned char* data = m_texture->getImage()->data();
while ( !m_paintQueue.empty() )
{
wmath::WPosition paintPosition = m_paintQueue.front();
m_paintQueue.pop();
int voxelNum = grid->getVoxelNum( paintPosition );
int voxelNum = m_grid->getVoxelNum( paintPosition );
if ( voxelNum != -1 )
{
switch ( m_pencilSelection->get( true ).getItemIndexOfSelected( 0 ) )
{
case 0:
m_values[ voxelNum ] = m_paintIndex->get();
data[ voxelNum ] = m_paintIndex->get();
break;
case 1:
{
m_values[ voxelNum ] = m_paintIndex->get();
std::vector< size_t > ids = grid->getNeighbours27( voxelNum );
data[ voxelNum ] = m_paintIndex->get();
std::vector< size_t > ids = m_grid->getNeighbours27( voxelNum );
for ( size_t i = 0; i < ids.size(); ++i )
{
m_values[ ids[i] ] = m_paintIndex->get();
data[ ids[i] ] = m_paintIndex->get();
}
break;
}
......@@ -300,10 +250,7 @@ boost::shared_ptr< WDataSetScalar > WMPaintTexture::doPaint()
}
m_queueAdded->set( false );
boost::shared_ptr< WValueSet< unsigned char > > vs =
boost::shared_ptr< WValueSet< unsigned char > >( new WValueSet< unsigned char >( 0, 1, m_values, W_DT_UINT8 ) );
return boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
m_texture->dirtyTextureObject();
}
void WMPaintTexture::queuePaint( WPickInfo pickInfo )
......@@ -318,14 +265,17 @@ void WMPaintTexture::queuePaint( WPickInfo pickInfo )
void WMPaintTexture::createTexture()
{
osg::ref_ptr< osg::Image > ima = new osg::Image;
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
m_grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
ima->allocateImage( grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ(), GL_LUMINANCE, GL_UNSIGNED_BYTE );
m_values.resize( m_grid->size(), 0 );
m_values[0] = 255;
osg::ref_ptr< osg::Image > ima = new osg::Image;
ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_LUMINANCE, GL_UNSIGNED_BYTE );
unsigned char* data = ima->data();
for ( unsigned int i = 0; i < grid->getNbCoordsX() * grid->getNbCoordsY() * grid->getNbCoordsZ(); ++i )
for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ(); ++i )
{
data[i] = m_values[i];
}
......@@ -338,4 +288,32 @@ void WMPaintTexture::createTexture()
m_texture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_BORDER );
m_texture->setImage( ima );
m_texture->setResizeNonPowerOfTwoHint( false );
WKernel::getRunningKernel()->getSelectionManager()->setTexture( m_texture, m_grid );
WKernel::getRunningKernel()->getSelectionManager()->setUseTexture( true );
WDataHandler::getDefaultSubject()->getChangeCondition()->notify();
}
void WMPaintTexture::updateOutDataset()
{
WAssert( m_dataSet, "" );
WAssert( m_dataSet->getValueSet(), "" );
WAssert( m_dataSet->getGrid(), "" );
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
WAssert( grid, "" );
unsigned char* data = m_texture->getImage()->data();
for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ(); ++i )
{
m_values[i] = data[i];
}
boost::shared_ptr< WValueSet< unsigned char > > vs =
boost::shared_ptr< WValueSet< unsigned char > >( new WValueSet< unsigned char >( 0, 1, m_values, W_DT_UINT8 ) );
m_outData = boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, grid ) );
m_output->updateData( m_outData );
}
......@@ -113,15 +113,10 @@ protected:
private:
/**
* Write property values to output dataset.
*/
void setOutputProps();
/**
* this function listens to the pick handler, if the paint flag is true it will write into the out texture
*/
boost::shared_ptr< WDataSetScalar > doPaint();
void doPaint();
/**
* this function listens to the pick handler, if the paint flag is true it will add the paint position to the
......@@ -132,17 +127,21 @@ private:
void queuePaint( WPickInfo pickInfo );