~ubuntu-branches/ubuntu/precise/openwalnut/precise

« back to all changes in this revision

Viewing changes to src/modules/surfaceParameterAnimator/WMSurfaceParameterAnimator.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Eichelbaum
  • Date: 2011-06-21 10:26:54 UTC
  • Revision ID: james.westby@ubuntu.com-20110621102654-rq0zf436q949biih
Tags: upstream-1.2.5
ImportĀ upstreamĀ versionĀ 1.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//---------------------------------------------------------------------------
 
2
//
 
3
// Project: OpenWalnut ( http://www.openwalnut.org )
 
4
//
 
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
 
6
// For more information see http://www.openwalnut.org/copying
 
7
//
 
8
// This file is part of OpenWalnut.
 
9
//
 
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.
 
14
//
 
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.
 
19
//
 
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/>.
 
22
//
 
23
//---------------------------------------------------------------------------
 
24
 
 
25
#include <string>
 
26
#include <utility>
 
27
 
 
28
#include <osg/ShapeDrawable>
 
29
#include <osg/Group>
 
30
#include <osg/Geode>
 
31
#include <osg/Material>
 
32
#include <osg/StateAttribute>
 
33
#include <osg/MatrixTransform>
 
34
#include <osg/Projection>
 
35
 
 
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"
 
44
 
 
45
#include "WMSurfaceParameterAnimator.h"
 
46
#include "WMSurfaceParameterAnimator.xpm"
 
47
 
 
48
// This line is needed by the module loader to actually find your module.
 
49
W_LOADABLE_MODULE( WMSurfaceParameterAnimator )
 
50
 
 
51
WMSurfaceParameterAnimator::WMSurfaceParameterAnimator():
 
52
    WModule(),
 
53
    m_rootNode( new WGEGroupNode() )
 
54
{
 
55
    // Initialize members
 
56
}
 
57
 
 
58
WMSurfaceParameterAnimator::~WMSurfaceParameterAnimator()
 
59
{
 
60
    // Cleanup!
 
61
}
 
62
 
 
63
boost::shared_ptr< WModule > WMSurfaceParameterAnimator::factory() const
 
64
{
 
65
    return boost::shared_ptr< WModule >( new WMSurfaceParameterAnimator() );
 
66
}
 
67
 
 
68
const char** WMSurfaceParameterAnimator::getXPMIcon() const
 
69
{
 
70
    return surfaceBars_xpm;
 
71
}
 
72
 
 
73
const std::string WMSurfaceParameterAnimator::getName() const
 
74
{
 
75
    // Specify your module name here. This name must be UNIQUE!
 
76
    return "Surface Parameter Animator";
 
77
}
 
78
 
 
79
const std::string WMSurfaceParameterAnimator::getDescription() const
 
80
{
 
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.";
 
83
}
 
84
 
 
85
void WMSurfaceParameterAnimator::connectors()
 
86
{
 
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." )
 
90
    );
 
91
 
 
92
    // As properties, every connector needs to be added to the list of connectors.
 
93
    addConnector( m_input );
 
94
 
 
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\"." )
 
98
    );
 
99
 
 
100
    // As properties, every connector needs to be added to the list of connectors.
 
101
    addConnector( m_tracesInput );
 
102
 
 
103
    // call WModules initialization
 
104
    WModule::connectors();
 
105
}
 
106
 
 
107
void WMSurfaceParameterAnimator::properties()
 
108
{
 
109
    // Initialize the properties
 
110
    m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
 
111
 
 
112
    m_isoValue      = m_properties->addProperty( "Isovalue",         "The Isovalue used whenever the Isosurface Mode is turned on.",
 
113
                                                                      50 );
 
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 );
 
118
 
 
119
    m_alpha         = m_properties->addProperty( "Opacity %",        "The opacity in %. Transparency = 100 - Opacity.", 100 );
 
120
 
 
121
    m_isoColor      = m_properties->addProperty( "Iso color",        "The color to blend the isosurface with.", WColor( 0.0, 0.0, 0.0, 1.0 ),
 
122
                      m_propCondition );
 
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 );
 
134
 
 
135
    WModule::properties();
 
136
}
 
137
 
 
138
osg::ref_ptr< osg::Node > WMSurfaceParameterAnimator::renderSurface( const WBoundingBox& bbox )
 
139
{
 
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 );
 
145
 
 
146
    // bind the texture to the node
 
147
    osg::StateSet* rootState = cube->getOrCreateStateSet();
 
148
 
 
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 );
 
153
 
 
154
    // enable transparency
 
155
    rootState->setMode( GL_BLEND, osg::StateAttribute::ON );
 
156
 
 
157
    ////////////////////////////////////////////////////////////////////////////////////////////////////
 
158
    // setup all those uniforms
 
159
    ////////////////////////////////////////////////////////////////////////////////////////////////////
 
160
 
 
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 ) );
 
163
 
 
164
    osg::ref_ptr< osg::Uniform > steps = new osg::Uniform( "u_steps", m_stepCount->get() );
 
165
    steps->setUpdateCallback( new SafeUniformCallback( this ) );
 
166
 
 
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 ) );
 
169
 
 
170
    osg::ref_ptr< osg::Uniform > animationTime = new osg::Uniform( "u_animationTime", 0 );
 
171
    animationTime->setUpdateCallback( new WGEShaderAnimationCallback() );
 
172
 
 
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 ) );
 
177
 
 
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 ) );
 
182
 
 
183
    osg::ref_ptr< osg::Uniform > paramScale = new osg::Uniform( "u_parameterScale", 1.0f );
 
184
    paramScale->setUpdateCallback( new SafeUniformCallback( this ) );
 
185
 
 
186
    osg::ref_ptr< osg::Uniform > saturation = new osg::Uniform( "u_saturation", 1.0f );
 
187
    saturation->setUpdateCallback( new SafeUniformCallback( this ) );
 
188
 
 
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 );
 
199
 
 
200
    return cube;
 
201
}
 
202
 
 
203
void WMSurfaceParameterAnimator::moduleMain()
 
204
{
 
205
    m_shader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMSurfaceParameterAnimator-Beams", m_localPath ) );
 
206
 
 
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 );
 
212
 
 
213
    // Signal ready state.
 
214
    ready();
 
215
 
 
216
    // add this module's group node
 
217
    m_rootNode->setNodeMask( m_active->get() ? 0xFFFFFFFF : 0x0 );
 
218
    WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
 
219
 
 
220
    // Now wait for data
 
221
    while( !m_shutdownFlag() )
 
222
    {
 
223
        m_moduleState.wait();
 
224
 
 
225
        // woke up since the module is requested to finish
 
226
        if( m_shutdownFlag() )
 
227
        {
 
228
            break;
 
229
        }
 
230
 
 
231
        // has the data changed?
 
232
        boost::shared_ptr< WDataSetSingle > newDataSet = m_input->getData();
 
233
        boost::shared_ptr< WDataSetSingle > newTracesDataSet = m_tracesInput->getData();
 
234
 
 
235
        bool dataChanged = ( m_dataSet != newDataSet ) || ( m_tracesDataSet != newTracesDataSet );
 
236
        bool dataValid =   ( newDataSet && newTracesDataSet );
 
237
 
 
238
        // valid data available?
 
239
        if( !dataValid )
 
240
        {
 
241
            debugLog() << "Resetting.";
 
242
 
 
243
            // reset internal refs to data
 
244
            m_dataSet.reset();
 
245
            m_tracesDataSet.reset();
 
246
 
 
247
            // remove renderings
 
248
            m_rootNode->clear();
 
249
        }
 
250
 
 
251
        // As the data has changed, we need to recreate the texture.
 
252
        if( dataChanged && dataValid )
 
253
        {
 
254
            m_dataSet = newDataSet;
 
255
            m_tracesDataSet = newTracesDataSet;
 
256
 
 
257
            debugLog() << "Data changed. Uploading new data as texture.";
 
258
 
 
259
            // First, grab the grid
 
260
            boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
 
261
            if( !grid )
 
262
            {
 
263
                errorLog() << "The dataset does not provide a regular grid. Ignoring dataset.";
 
264
                continue;
 
265
            }
 
266
 
 
267
            // attach the geometry to the first FBO
 
268
            osg::ref_ptr< osg::Node > cube = renderSurface( grid->getBoundingBox() );
 
269
 
 
270
            // **********************************************************************************************
 
271
            // Update scene
 
272
            // **********************************************************************************************
 
273
 
 
274
            // update node
 
275
            debugLog() << "Adding new rendering.";
 
276
            m_rootNode->clear();
 
277
            m_rootNode->insert( cube );
 
278
        }
 
279
    }
 
280
 
 
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 );
 
284
}
 
285
 
 
286
void WMSurfaceParameterAnimator::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
 
287
{
 
288
    // update material info
 
289
    if( m_module->m_isoColor->changed() || m_initialUpdate )
 
290
    {
 
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 );
 
295
 
 
296
        m_initialUpdate = false;
 
297
    }
 
298
 
 
299
    traverse( node, nv );
 
300
}
 
301
 
 
302
void WMSurfaceParameterAnimator::SafeUniformCallback::operator()( osg::Uniform* uniform, osg::NodeVisitor* /* nv */ )
 
303
{
 
304
    // update some uniforms:
 
305
    if( m_module->m_isoValue->changed()  && ( uniform->getName() == "u_isovalue" ) )
 
306
    {
 
307
        uniform->set( static_cast< float >( m_module->m_isoValue->get( true ) ) / 100.0f );
 
308
    }
 
309
    if( m_module->m_stepCount->changed() && ( uniform->getName() == "u_steps" ) )
 
310
    {
 
311
        uniform->set( m_module->m_stepCount->get( true ) );
 
312
    }
 
313
    if( m_module->m_alpha->changed() && ( uniform->getName() == "u_alpha" ) )
 
314
    {
 
315
        uniform->set( static_cast< float >( m_module->m_alpha->get( true ) / 100.0 ) );
 
316
    }
 
317
    if( m_module->m_alpha->changed() && ( uniform->getName() == "u_size1" ) )
 
318
    {
 
319
        uniform->set( static_cast< float >( m_module->m_alpha->get( true ) / 100.0 ) );
 
320
    }
 
321
    if( m_module->m_size1->changed() && ( uniform->getName() == "u_size1" ) )
 
322
    {
 
323
        uniform->set( m_module->m_size1->get( true ) );
 
324
    }
 
325
    if( m_module->m_size2->changed() && ( uniform->getName() == "u_size2" ) )
 
326
    {
 
327
        uniform->set( m_module->m_size2->get( true ) );
 
328
    }
 
329
    if( m_module->m_speed1->changed() && ( uniform->getName() == "u_speed1" ) )
 
330
    {
 
331
        uniform->set( m_module->m_speed1->get( true ) );
 
332
    }
 
333
    if( m_module->m_speed2->changed() && ( uniform->getName() == "u_speed2" ) )
 
334
    {
 
335
        uniform->set( m_module->m_speed2->get( true ) );
 
336
    }
 
337
    if( m_module->m_parameterScale->changed() && ( uniform->getName() == "u_parameterScale" ) )
 
338
    {
 
339
        uniform->set( static_cast< float >( m_module->m_parameterScale->get( true ) ) );
 
340
    }
 
341
    if( m_module->m_saturation->changed() && ( uniform->getName() == "u_saturation" ) )
 
342
    {
 
343
        uniform->set( static_cast< float >( m_module->m_saturation->get( true ) ) / 100.0f );
 
344
    }
 
345
}
 
346
 
 
347
void WMSurfaceParameterAnimator::activate()
 
348
{
 
349
    // Activate/Deactivate the rendering
 
350
    if( m_rootNode )
 
351
    {
 
352
        if( m_active->get() )
 
353
        {
 
354
            m_rootNode->setNodeMask( 0xFFFFFFFF );
 
355
        }
 
356
        else
 
357
        {
 
358
            m_rootNode->setNodeMask( 0x0 );
 
359
        }
 
360
    }
 
361
 
 
362
    // Always call WModule's activate!
 
363
    WModule::activate();
 
364
}
 
365