1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
10
// OpenWalnut is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU Lesser General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
15
// OpenWalnut is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
// GNU Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public License
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
23
//---------------------------------------------------------------------------
29
#include "core/common/WPropertyHelper.h"
30
#include "core/graphicsEngine/WGEColormapping.h"
31
#include "core/graphicsEngine/WGEUtils.h"
32
#include "core/graphicsEngine/WROIArbitrary.h"
33
#include "core/kernel/WKernel.h"
34
#include "core/kernel/WROIManager.h"
35
#include "core/kernel/WSelectionManager.h"
36
#include "WMPaintTexture.h"
37
#include "WMPaintTexture.xpm"
39
// This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here.
40
W_LOADABLE_MODULE( WMPaintTexture )
42
WMPaintTexture::WMPaintTexture():
47
WMPaintTexture::~WMPaintTexture()
52
boost::shared_ptr< WModule > WMPaintTexture::factory() const
54
return boost::shared_ptr< WModule >( new WMPaintTexture() );
57
const char** WMPaintTexture::getXPMIcon() const
59
return paintTexture_xpm; // Please put a real icon here.
61
const std::string WMPaintTexture::getName() const
63
return "Paint Texture";
66
const std::string WMPaintTexture::getDescription() const
68
return "This module allows painting areas in a 3D texture";
71
void WMPaintTexture::connectors()
73
// the input dataset is just used as source for resolurtion and transformation matrix
74
m_input = boost::shared_ptr< WModuleInputData < WDataSetSingle > >(
75
new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The input dataset." ) );
76
addConnector( m_input );
78
m_output = boost::shared_ptr< WModuleOutputData < WDataSetScalar > >(
79
new WModuleOutputData< WDataSetScalar >( shared_from_this(), "out", "The extracted image." ) );
80
addConnector( m_output );
82
WModule::connectors();
85
void WMPaintTexture::properties()
87
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
89
m_painting = m_properties->addProperty( "Paint", "If active, left click in the scene with pressed ctrl key"
90
" will paint something.", false, m_propCondition );
92
m_pencilSelectionsList = boost::shared_ptr< WItemSelection >( new WItemSelection() );
93
m_pencilSelectionsList->addItem( "1x1", "" );
94
m_pencilSelectionsList->addItem( "3x3", "" );
95
m_pencilSelectionsList->addItem( "5x5", "" );
96
m_pencilSelectionsList->addItem( "3x1 (only works on orthogonal slices)", "" );
97
m_pencilSelectionsList->addItem( "5x1 (only works on orthogonal slices)", "" );
98
m_pencilSelection = m_properties->addProperty( "Pencil", "Pencil type.", m_pencilSelectionsList->getSelectorFirst() );
99
WPropertyHelper::PC_SELECTONLYONE::addTo( m_pencilSelection );
101
m_paintIndex = m_properties->addProperty( "Paint index", "Index we paint into the output texture", 1 );
102
m_paintIndex->setMin( 0 );
103
m_paintIndex->setMax( 255 );
105
m_colorMapSelectionsList = boost::shared_ptr< WItemSelection >( new WItemSelection() );
106
m_colorMapSelectionsList->addItem( "Grayscale", "" );
107
m_colorMapSelectionsList->addItem( "Rainbow", "" );
108
m_colorMapSelectionsList->addItem( "Hot iron", "" );
109
m_colorMapSelectionsList->addItem( "Red-Yellow", "" );
110
m_colorMapSelectionsList->addItem( "Atlas", "" );
111
m_colorMapSelectionsList->addItem( "Blue-Green-Purple", "" );
113
m_colorMapSelection = m_properties->addProperty( "Colormap", "Colormap type.", m_colorMapSelectionsList->getSelector( 4 ), m_propCondition );
114
WPropertyHelper::PC_SELECTONLYONE::addTo( m_colorMapSelection );
116
m_queueAdded = m_properties->addProperty( "Something paint", "", false, m_propCondition );
117
m_queueAdded->setHidden();
119
m_buttonCopyFromInput = m_properties->addProperty( "Copy from input", "Copies data from the input dataset into the paint texture",
120
WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
122
m_buttonUpdateOutput = m_properties->addProperty( "Update output", "Updates the output connector",
123
WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
124
m_buttonCreateRoi = m_properties->addProperty( "Create ROI", "Create a ROI from the currently selected paint value",
125
WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
127
WModule::properties();
130
void WMPaintTexture::moduleMain()
132
boost::signals2::connection con = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getPickHandler()->getPickSignal()->
133
connect( boost::bind( &WMPaintTexture::queuePaint, this, _1 ) );
135
m_moduleState.setResetable( true, true );
136
m_moduleState.add( m_input->getDataChangedCondition() );
137
m_moduleState.add( m_propCondition );
138
m_moduleState.add( m_active->getUpdateCondition() );
142
while( !m_shutdownFlag() )
144
m_moduleState.wait();
146
if( m_shutdownFlag() )
151
boost::shared_ptr< WDataSetSingle > newDataSet = m_input->getData();
152
bool dataChanged = ( m_dataSet != newDataSet );
153
bool dataValid = ( newDataSet );
159
m_dataSet = newDataSet;
160
WAssert( m_dataSet, "" );
161
WAssert( m_dataSet->getValueSet(), "" );
168
if( m_painting->changed() )
170
if( m_painting->get( true ) )
172
WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_PAINT );
176
WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_NONE );
180
if( m_active->changed() )
182
if( m_active->get( true ) )
184
if( m_painting->get( true ) )
186
WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_PAINT );
190
m_texture->active()->set( true );
195
m_texture->active()->set( false );
196
WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_NONE );
200
if( m_buttonCopyFromInput->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED )
203
m_buttonCopyFromInput->set( WPVBaseTypes::PV_TRIGGER_READY, false );
206
if( m_buttonCreateRoi->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED )
208
m_painting->set( false );
210
m_buttonCreateRoi->set( WPVBaseTypes::PV_TRIGGER_READY, false );
213
else // case !dataValid
216
m_outData = boost::shared_ptr< WDataSetScalar >();
217
m_output->updateData( m_outData );
219
if( m_queueAdded->changed() && m_queueAdded->get( true ) )
224
if( m_buttonUpdateOutput->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED )
227
m_buttonUpdateOutput->set( WPVBaseTypes::PV_TRIGGER_READY, false );
231
debugLog() << "Shutting down...";
233
WGEColormapping::deregisterTexture( m_texture );
234
WKernel::getRunningKernel()->getSelectionManager()->setPaintMode( PAINTMODE_NONE );
238
debugLog() << "Finished! Good Bye!";
241
void WMPaintTexture::activate()
246
void WMPaintTexture::doPaint()
248
unsigned char* data = m_texture->getImage()->data();
250
while( !m_paintQueue.empty() )
252
WPickInfo pickInfo = m_paintQueue.front();
253
WPosition paintPosition = pickInfo.getPickPosition();
256
int voxelNum = m_grid->getVoxelNum( paintPosition );
259
switch( m_pencilSelection->get( true ).getItemIndexOfSelected( 0 ) )
262
data[ voxelNum ] = m_paintIndex->get();
266
data[ voxelNum ] = m_paintIndex->get();
267
std::vector< size_t > ids = m_grid->getNeighbours27( voxelNum );
268
for( size_t i = 0; i < ids.size(); ++i )
270
data[ ids[i] ] = m_paintIndex->get();
276
data[ voxelNum ] = m_paintIndex->get();
277
std::vector< size_t > ids = m_grid->getNeighbours27( voxelNum );
278
for( size_t i = 0; i < ids.size(); ++i )
280
std::vector< size_t > allIds = m_grid->getNeighbours27( ids[i] );
281
for( size_t k = 0; k < allIds.size(); ++k )
283
data[ allIds[k] ] = m_paintIndex->get();
290
if( pickInfo.getName() == "Axial Slice" )
292
data[ voxelNum ] = m_paintIndex->get();
293
std::vector< size_t > ids = m_grid->getNeighbours9XY( voxelNum );
294
for( size_t i = 0; i < ids.size(); ++i )
296
data[ ids[i] ] = m_paintIndex->get();
299
if( pickInfo.getName() == "Coronal Slice" )
301
data[ voxelNum ] = m_paintIndex->get();
302
std::vector< size_t > ids = m_grid->getNeighbours9XZ( voxelNum );
303
for( size_t i = 0; i < ids.size(); ++i )
305
data[ ids[i] ] = m_paintIndex->get();
308
if( pickInfo.getName() == "Sagittal Slice" )
310
data[ voxelNum ] = m_paintIndex->get();
311
std::vector< size_t > ids = m_grid->getNeighbours9YZ( voxelNum );
312
for( size_t i = 0; i < ids.size(); ++i )
314
data[ ids[i] ] = m_paintIndex->get();
321
if( pickInfo.getName() == "Axial Slice" )
323
data[ voxelNum ] = m_paintIndex->get();
324
std::vector< size_t > ids = m_grid->getNeighbours9XY( voxelNum );
325
for( size_t i = 0; i < ids.size(); ++i )
327
std::vector< size_t > allIds = m_grid->getNeighbours9XY( ids[i] );
328
for( size_t k = 0; k < allIds.size(); ++k )
330
data[ allIds[k] ] = m_paintIndex->get();
334
if( pickInfo.getName() == "Coronal Slice" )
336
data[ voxelNum ] = m_paintIndex->get();
337
std::vector< size_t > ids = m_grid->getNeighbours9XZ( voxelNum );
338
for( size_t i = 0; i < ids.size(); ++i )
340
std::vector< size_t > allIds = m_grid->getNeighbours9XZ( ids[i] );
341
for( size_t k = 0; k < allIds.size(); ++k )
343
data[ allIds[k] ] = m_paintIndex->get();
347
if( pickInfo.getName() == "Sagittal Slice" )
349
data[ voxelNum ] = m_paintIndex->get();
350
std::vector< size_t > ids = m_grid->getNeighbours9YZ( voxelNum );
351
for( size_t i = 0; i < ids.size(); ++i )
353
std::vector< size_t > allIds = m_grid->getNeighbours9YZ( ids[i] );
354
for( size_t k = 0; k < allIds.size(); ++k )
356
data[ allIds[k] ] = m_paintIndex->get();
368
m_queueAdded->set( false );
370
m_texture->dirtyTextureObject();
375
void WMPaintTexture::queuePaint( WPickInfo pickInfo )
377
if( pickInfo.getModifierKey() == WPickInfo::SHIFT )
379
setColorFromPick( pickInfo );
383
if( !m_painting->get() || ( pickInfo.getMouseButton() != WPickInfo::MOUSE_LEFT ) || ( pickInfo.getName() == "unpick" ) )
388
m_paintQueue.push( pickInfo );
389
m_queueAdded->set( true );
392
void WMPaintTexture::setColorFromPick( WPickInfo pickInfo )
394
WPosition paintPosition = pickInfo.getPickPosition();
395
int voxelNum = m_grid->getVoxelNum( paintPosition );
399
unsigned char* data = m_texture->getImage()->data();
400
m_paintIndex->set( data[ voxelNum ] );
404
void WMPaintTexture::createTexture()
406
m_grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
408
osg::ref_ptr< osg::Image > ima = new osg::Image;
409
ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_LUMINANCE, GL_UNSIGNED_BYTE );
411
unsigned char* data = ima->data();
413
for( unsigned int i = 0; i < m_grid->size(); ++i )
418
m_texture = osg::ref_ptr< WGETexture3D >( new WGETexture3D( ima ) );
419
m_texture->setFilterMinMag( osg::Texture3D::LINEAR );
420
m_texture->setWrapSTR( osg::Texture::CLAMP_TO_BORDER );
421
m_texture->colormap()->set( m_texture->colormap()->get().newSelector( WItemSelector::IndexList( 1, 4 ) ) );
422
m_properties->addProperty( m_texture->alpha() );
424
WGEColormapping::registerTexture( m_texture, "Painted Texture" );
427
void WMPaintTexture::updateOutDataset()
429
WAssert( m_dataSet, "" );
430
WAssert( m_dataSet->getValueSet(), "" );
431
WAssert( m_dataSet->getGrid(), "" );
433
unsigned char* data = m_texture->getImage()->data();
434
boost::shared_ptr< std::vector< unsigned char > > values =
435
boost::shared_ptr< std::vector< unsigned char > >( new std::vector< unsigned char >( m_grid->size(), 0.0 ) );
437
for( unsigned int i = 0; i < m_grid->size(); ++i )
439
( *values )[i] = data[i];
442
boost::shared_ptr< WValueSet< unsigned char > > vs =
443
boost::shared_ptr< WValueSet< unsigned char > >( new WValueSet< unsigned char >( 0, 1, values, W_DT_UINT8 ) );
445
m_outData = boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, m_grid ) );
446
m_outData->getTexture()->interpolation()->set( false );
447
m_output->updateData( m_outData );
450
void WMPaintTexture::copyFromInput()
452
m_grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
454
unsigned char* data = m_texture->getImage()->data();
456
boost::shared_ptr< WValueSet< unsigned char > > vals;
457
vals = boost::shared_dynamic_cast< WValueSet< unsigned char > >( m_dataSet->getValueSet() );
459
for( unsigned int i = 0; i < m_grid->size(); ++i )
461
data[i] = vals->getScalar( i );
463
m_texture->dirtyTextureObject();
466
void WMPaintTexture::createROI()
469
std::vector<float>roiVals( m_grid->size(), 0 );
470
unsigned char index = m_paintIndex->get();
472
unsigned char* data = m_texture->getImage()->data();
474
for( size_t i = 0; i < m_grid->size(); ++i )
476
if( data[i] == index )
485
osg::ref_ptr< WROI > newRoi = osg::ref_ptr< WROI >(
486
new WROIArbitrary( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(),
487
m_grid->getTransformationMatrix(), roiVals, 1.0, wge::createColorFromIndex( index ) ) );
489
if( WKernel::getRunningKernel()->getRoiManager()->getSelectedRoi() == NULL )
491
WLogger::getLogger()->addLogMessage( " new roi without parent ", "WMPaintTexture", LL_DEBUG );
492
WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi );
496
WLogger::getLogger()->addLogMessage( " new roi with parent ", "WMPaintTexture", LL_DEBUG );
497
WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi, WKernel::getRunningKernel()->getRoiManager()->getSelectedRoi() );