1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-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
//---------------------------------------------------------------------------
28
#include <osg/ShapeDrawable>
31
#include <osg/Material>
32
#include <osg/StateAttribute>
33
#include <osg/MatrixTransform>
34
#include <osg/Projection>
36
#include "core/kernel/WKernel.h"
37
#include "core/dataHandler/WDataTexture3D.h"
38
#include "core/common/WColor.h"
39
#include "core/common/WBoundingBox.h"
40
#include "core/graphicsEngine/WGEUtils.h"
41
#include "core/graphicsEngine/WGEGeodeUtils.h"
42
#include "core/graphicsEngine/shaders/WGEShader.h"
43
#include "core/graphicsEngine/callbacks/WGEShaderAnimationCallback.h"
45
#include "WMSurfaceParameterAnimator.h"
46
#include "WMSurfaceParameterAnimator.xpm"
48
// This line is needed by the module loader to actually find your module.
49
W_LOADABLE_MODULE( WMSurfaceParameterAnimator )
51
WMSurfaceParameterAnimator::WMSurfaceParameterAnimator():
53
m_rootNode( new WGEGroupNode() )
58
WMSurfaceParameterAnimator::~WMSurfaceParameterAnimator()
63
boost::shared_ptr< WModule > WMSurfaceParameterAnimator::factory() const
65
return boost::shared_ptr< WModule >( new WMSurfaceParameterAnimator() );
68
const char** WMSurfaceParameterAnimator::getXPMIcon() const
70
return surfaceBars_xpm;
73
const std::string WMSurfaceParameterAnimator::getName() const
75
// Specify your module name here. This name must be UNIQUE!
76
return "Surface Parameter Animator";
79
const std::string WMSurfaceParameterAnimator::getDescription() const
81
// Specify your module description here. Be detailed. This text is read by the user.
82
return "This module can show parameters defined on surfaces using various types of animation.";
85
void WMSurfaceParameterAnimator::connectors()
87
// needs one input: the scalar dataset
88
m_input = boost::shared_ptr< WModuleInputData < WDataSetSingle > >(
89
new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The scalar dataset shown whose surface gets used for animation." )
92
// As properties, every connector needs to be added to the list of connectors.
93
addConnector( m_input );
95
// and the fiber directions inside the volume
96
m_tracesInput = boost::shared_ptr< WModuleInputData < WDataSetSingle > >(
97
new WModuleInputData< WDataSetSingle >( shared_from_this(), "traces", "The voxelized fiber traces for each voxel in the input \"in\"." )
100
// As properties, every connector needs to be added to the list of connectors.
101
addConnector( m_tracesInput );
103
// call WModules initialization
104
WModule::connectors();
107
void WMSurfaceParameterAnimator::properties()
109
// Initialize the properties
110
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
112
m_isoValue = m_properties->addProperty( "Isovalue", "The Isovalue used whenever the Isosurface Mode is turned on.",
114
m_stepCount = m_properties->addProperty( "Step count", "The number of steps to walk along the ray during raycasting. A low value"
115
"may cause artifacts whilst a high value slows down rendering.", 250 );
116
m_stepCount->setMin( 1 );
117
m_stepCount->setMax( 1000 );
119
m_alpha = m_properties->addProperty( "Opacity %", "The opacity in %. Transparency = 100 - Opacity.", 100 );
121
m_isoColor = m_properties->addProperty( "Iso color", "The color to blend the isosurface with.", WColor( 0.0, 0.0, 0.0, 1.0 ),
123
m_saturation = m_properties->addProperty( "Saturation %", "The saturation in %.", 100 );
124
m_size1 = m_properties->addProperty( "Beam1 size", "The relative size of the first beam. A value of 0 gets mapped to the "
125
"smallest size, whilst 100 gets mapped to the largest. This is typically "
126
"one third of the size of the voxelized surface.", 10 );
127
m_size2 = m_properties->addProperty( "Beam2 size", "The relative size of the second beam. A value of 0 gets mapped to the "
128
"smallest size, whilst 100 gets mapped to the largest. This is typically "
129
"one third of the size of the voxelized surface.", 50 );
130
m_speed1 = m_properties->addProperty( "Beam1 speed", "The relative speed of the beam. This speed relates to the clock used.", 25 );
131
m_speed2 = m_properties->addProperty( "Beam2 speed", "The relative speed of the beam. This speed relates to the clock used.", 25 );
132
m_parameterScale = m_properties->addProperty( "Parameter scale", "Scaling the parameter space on the fly creates consistently sized and fast "
133
"beams over multiple WMSurfaceParameterAnimator instances.", 1.0 );
135
WModule::properties();
138
osg::ref_ptr< osg::Node > WMSurfaceParameterAnimator::renderSurface( const WBoundingBox& bbox )
140
// use the OSG Shapes, create unit cube
141
osg::ref_ptr< osg::Node > cube = wge::generateSolidBoundingBoxNode( bbox, m_isoColor->get( true ) );
142
cube->addUpdateCallback( new SafeUpdateCallback( this ) );
143
cube->asTransform()->getChild( 0 )->setName( "DVR Proxy Cube" ); // Be aware that this name is used in the pick handler.
144
m_shader->apply( cube );
146
// bind the texture to the node
147
osg::StateSet* rootState = cube->getOrCreateStateSet();
149
osg::ref_ptr< WGETexture3D > texture3D = m_dataSet->getTexture();
150
osg::ref_ptr< WGETexture3D > tracesTexture3D = m_tracesDataSet->getTexture();
151
texture3D->bind( cube, 0 );
152
tracesTexture3D->bind( cube, 1 );
154
// enable transparency
155
rootState->setMode( GL_BLEND, osg::StateAttribute::ON );
157
////////////////////////////////////////////////////////////////////////////////////////////////////
158
// setup all those uniforms
159
////////////////////////////////////////////////////////////////////////////////////////////////////
161
osg::ref_ptr< osg::Uniform > isovalue = new osg::Uniform( "u_isovalue", static_cast< float >( m_isoValue->get() / 100.0 ) );
162
isovalue->setUpdateCallback( new SafeUniformCallback( this ) );
164
osg::ref_ptr< osg::Uniform > steps = new osg::Uniform( "u_steps", m_stepCount->get() );
165
steps->setUpdateCallback( new SafeUniformCallback( this ) );
167
osg::ref_ptr< osg::Uniform > alpha = new osg::Uniform( "u_alpha", static_cast< float >( m_alpha->get() / 100.0 ) );
168
alpha->setUpdateCallback( new SafeUniformCallback( this ) );
170
osg::ref_ptr< osg::Uniform > animationTime = new osg::Uniform( "u_animationTime", 0 );
171
animationTime->setUpdateCallback( new WGEShaderAnimationCallback() );
173
osg::ref_ptr< osg::Uniform > size1 = new osg::Uniform( "u_size1", 0 );
174
osg::ref_ptr< osg::Uniform > size2 = new osg::Uniform( "u_size2", 0 );
175
size1->setUpdateCallback( new SafeUniformCallback( this ) );
176
size2->setUpdateCallback( new SafeUniformCallback( this ) );
178
osg::ref_ptr< osg::Uniform > speed1 = new osg::Uniform( "u_speed1", 0 );
179
osg::ref_ptr< osg::Uniform > speed2 = new osg::Uniform( "u_speed2", 0 );
180
speed1->setUpdateCallback( new SafeUniformCallback( this ) );
181
speed2->setUpdateCallback( new SafeUniformCallback( this ) );
183
osg::ref_ptr< osg::Uniform > paramScale = new osg::Uniform( "u_parameterScale", 1.0f );
184
paramScale->setUpdateCallback( new SafeUniformCallback( this ) );
186
osg::ref_ptr< osg::Uniform > saturation = new osg::Uniform( "u_saturation", 1.0f );
187
saturation->setUpdateCallback( new SafeUniformCallback( this ) );
189
rootState->addUniform( isovalue );
190
rootState->addUniform( steps );
191
rootState->addUniform( alpha );
192
rootState->addUniform( animationTime );
193
rootState->addUniform( size1 );
194
rootState->addUniform( size2 );
195
rootState->addUniform( speed1 );
196
rootState->addUniform( speed2 );
197
rootState->addUniform( paramScale );
198
rootState->addUniform( saturation );
203
void WMSurfaceParameterAnimator::moduleMain()
205
m_shader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMSurfaceParameterAnimator-Beams", m_localPath ) );
207
// let the main loop awake if the data changes or the properties changed.
208
m_moduleState.setResetable( true, true );
209
m_moduleState.add( m_input->getDataChangedCondition() );
210
m_moduleState.add( m_tracesInput->getDataChangedCondition() );
211
m_moduleState.add( m_propCondition );
213
// Signal ready state.
216
// add this module's group node
217
m_rootNode->setNodeMask( m_active->get() ? 0xFFFFFFFF : 0x0 );
218
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
221
while( !m_shutdownFlag() )
223
m_moduleState.wait();
225
// woke up since the module is requested to finish
226
if( m_shutdownFlag() )
231
// has the data changed?
232
boost::shared_ptr< WDataSetSingle > newDataSet = m_input->getData();
233
boost::shared_ptr< WDataSetSingle > newTracesDataSet = m_tracesInput->getData();
235
bool dataChanged = ( m_dataSet != newDataSet ) || ( m_tracesDataSet != newTracesDataSet );
236
bool dataValid = ( newDataSet && newTracesDataSet );
238
// valid data available?
241
debugLog() << "Resetting.";
243
// reset internal refs to data
245
m_tracesDataSet.reset();
251
// As the data has changed, we need to recreate the texture.
252
if( dataChanged && dataValid )
254
m_dataSet = newDataSet;
255
m_tracesDataSet = newTracesDataSet;
257
debugLog() << "Data changed. Uploading new data as texture.";
259
// First, grab the grid
260
boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
263
errorLog() << "The dataset does not provide a regular grid. Ignoring dataset.";
267
// attach the geometry to the first FBO
268
osg::ref_ptr< osg::Node > cube = renderSurface( grid->getBoundingBox() );
270
// **********************************************************************************************
272
// **********************************************************************************************
275
debugLog() << "Adding new rendering.";
277
m_rootNode->insert( cube );
281
// At this point, the container managing this module signalled to shutdown. The main loop has ended and you should clean up. Always remove
282
// allocated memory and remove all OSG nodes.
283
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
286
void WMSurfaceParameterAnimator::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
288
// update material info
289
if( m_module->m_isoColor->changed() || m_initialUpdate )
291
// Set the diffuse color and material:
292
osg::ref_ptr< osg::Material > mat = new osg::Material();
293
mat->setDiffuse( osg::Material::FRONT, m_module->m_isoColor->get( true ) );
294
node->getOrCreateStateSet()->setAttribute( mat, osg::StateAttribute::ON );
296
m_initialUpdate = false;
299
traverse( node, nv );
302
void WMSurfaceParameterAnimator::SafeUniformCallback::operator()( osg::Uniform* uniform, osg::NodeVisitor* /* nv */ )
304
// update some uniforms:
305
if( m_module->m_isoValue->changed() && ( uniform->getName() == "u_isovalue" ) )
307
uniform->set( static_cast< float >( m_module->m_isoValue->get( true ) ) / 100.0f );
309
if( m_module->m_stepCount->changed() && ( uniform->getName() == "u_steps" ) )
311
uniform->set( m_module->m_stepCount->get( true ) );
313
if( m_module->m_alpha->changed() && ( uniform->getName() == "u_alpha" ) )
315
uniform->set( static_cast< float >( m_module->m_alpha->get( true ) / 100.0 ) );
317
if( m_module->m_alpha->changed() && ( uniform->getName() == "u_size1" ) )
319
uniform->set( static_cast< float >( m_module->m_alpha->get( true ) / 100.0 ) );
321
if( m_module->m_size1->changed() && ( uniform->getName() == "u_size1" ) )
323
uniform->set( m_module->m_size1->get( true ) );
325
if( m_module->m_size2->changed() && ( uniform->getName() == "u_size2" ) )
327
uniform->set( m_module->m_size2->get( true ) );
329
if( m_module->m_speed1->changed() && ( uniform->getName() == "u_speed1" ) )
331
uniform->set( m_module->m_speed1->get( true ) );
333
if( m_module->m_speed2->changed() && ( uniform->getName() == "u_speed2" ) )
335
uniform->set( m_module->m_speed2->get( true ) );
337
if( m_module->m_parameterScale->changed() && ( uniform->getName() == "u_parameterScale" ) )
339
uniform->set( static_cast< float >( m_module->m_parameterScale->get( true ) ) );
341
if( m_module->m_saturation->changed() && ( uniform->getName() == "u_saturation" ) )
343
uniform->set( static_cast< float >( m_module->m_saturation->get( true ) ) / 100.0f );
347
void WMSurfaceParameterAnimator::activate()
349
// Activate/Deactivate the rendering
352
if( m_active->get() )
354
m_rootNode->setNodeMask( 0xFFFFFFFF );
358
m_rootNode->setNodeMask( 0x0 );
362
// Always call WModule's activate!