~ubuntu-branches/ubuntu/vivid/openwalnut/vivid-proposed

« back to all changes in this revision

Viewing changes to .pc/boost153/src/modules/isosurfaceRaytracer/WMIsosurfaceRaytracer.cpp

  • Committer: Package Import Robot
  • Author(s): Sebastian Eichelbaum
  • Date: 2014-03-19 17:46:12 UTC
  • mfrom: (3.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140319174612-e4mgtr1avbq3f7ph
Tags: 1.4.0~rc1+hg3a3147463ee2-1
* Major functionality and stability improvements.
* Several bug fixes
* Changed ttf-liberation dependency to fonts-liberation (Closes: #722405)
* OpenWalnut now works properly with OpenSceneGraph 3.2 (Closes: #718381)
* See http://www.openwalnut.org/versions/2

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/Geode>
29
 
#include <osg/Group>
30
 
#include <osg/Material>
31
 
#include <osg/ShapeDrawable>
32
 
#include <osg/StateAttribute>
33
 
 
34
 
#include "core/common/WColor.h"
35
 
#include "core/common/WPropertyHelper.h"
36
 
#include "core/dataHandler/WDataSetScalar.h"
37
 
#include "core/dataHandler/WDataSetVector.h"
38
 
#include "core/dataHandler/WDataTexture3D.h"
39
 
#include "core/graphicsEngine/WGEColormapping.h"
40
 
#include "core/graphicsEngine/WGEGeodeUtils.h"
41
 
#include "core/graphicsEngine/WGEManagedGroupNode.h"
42
 
#include "core/graphicsEngine/WGEUtils.h"
43
 
#include "core/graphicsEngine/WGETextureUtils.h"
44
 
#include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
45
 
#include "core/graphicsEngine/shaders/WGEShader.h"
46
 
#include "core/graphicsEngine/shaders/WGEShaderDefineOptions.h"
47
 
#include "core/graphicsEngine/shaders/WGEShaderPropertyDefineOptions.h"
48
 
#include "core/graphicsEngine/shaders/WGEShaderPropertyDefine.h"
49
 
#include "core/graphicsEngine/postprocessing/WGEPostprocessingNode.h"
50
 
#include "core/graphicsEngine/WGERequirement.h"
51
 
#include "core/graphicsEngine/callbacks/WGENodeMaskCallback.h"
52
 
#include "core/kernel/WKernel.h"
53
 
#include "WMIsosurfaceRaytracer.xpm"
54
 
#include "WMIsosurfaceRaytracer.h"
55
 
 
56
 
// This line is needed by the module loader to actually find your module.
57
 
W_LOADABLE_MODULE( WMIsosurfaceRaytracer )
58
 
 
59
 
WMIsosurfaceRaytracer::WMIsosurfaceRaytracer():
60
 
    WModule()
61
 
{
62
 
    // Initialize members
63
 
}
64
 
 
65
 
WMIsosurfaceRaytracer::~WMIsosurfaceRaytracer()
66
 
{
67
 
    // Cleanup!
68
 
}
69
 
 
70
 
boost::shared_ptr< WModule > WMIsosurfaceRaytracer::factory() const
71
 
{
72
 
    return boost::shared_ptr< WModule >( new WMIsosurfaceRaytracer() );
73
 
}
74
 
 
75
 
const char** WMIsosurfaceRaytracer::getXPMIcon() const
76
 
{
77
 
    return isosurfaceraytracer_xpm;
78
 
}
79
 
 
80
 
const std::string WMIsosurfaceRaytracer::getName() const
81
 
{
82
 
    // Specify your module name here. This name must be UNIQUE!
83
 
    return "Isosurface Raytracer";
84
 
}
85
 
 
86
 
const std::string WMIsosurfaceRaytracer::getDescription() const
87
 
{
88
 
    // Specify your module description here. Be detailed. This text is read by the user.
89
 
    return "This module shows a fast raytraced isosurface of the specified scalar dataset.";
90
 
}
91
 
 
92
 
void WMIsosurfaceRaytracer::connectors()
93
 
{
94
 
    // DVR needs one input: the scalar dataset
95
 
    m_input = boost::shared_ptr< WModuleInputData < WDataSetScalar  > >(
96
 
        new WModuleInputData< WDataSetScalar >( shared_from_this(), "in", "The scalar dataset shown using isosurface." )
97
 
    );
98
 
 
99
 
    // As properties, every connector needs to be added to the list of connectors.
100
 
    addConnector( m_input );
101
 
 
102
 
    // Optional: the gradient field
103
 
    m_gradients = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "gradients", "The gradient field of the dataset to display" );
104
 
 
105
 
    // call WModules initialization
106
 
    WModule::connectors();
107
 
}
108
 
 
109
 
void WMIsosurfaceRaytracer::properties()
110
 
{
111
 
    // Initialize the properties
112
 
    m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
113
 
 
114
 
    m_isoValue      = m_properties->addProperty( "Isovalue",         "The isovalue used whenever the isosurface Mode is turned on.",
115
 
                                                                      128.0 );
116
 
 
117
 
    m_isoColor      = m_properties->addProperty( "Iso color",        "The color to blend the isosurface with.", WColor( 1.0, 1.0, 1.0, 1.0 ),
118
 
                      m_propCondition );
119
 
 
120
 
    m_stepCount     = m_properties->addProperty( "Step count",       "The number of steps to walk along the ray during raycasting. A low value "
121
 
                                                                      "may cause artifacts whilst a high value slows down rendering.", 250 );
122
 
    m_stepCount->setMin( 1 );
123
 
    m_stepCount->setMax( 1000 );
124
 
 
125
 
    m_epsilon       = m_properties->addProperty( "Epsilon",           "The value defines the precision of iso-value checking. The lower the "
126
 
                                                                      "value, the higher the precision.", 0.1 );
127
 
    m_epsilon->setMin( 0.0 );
128
 
    m_epsilon->setMax( 1.0 );
129
 
 
130
 
    m_alpha         = m_properties->addProperty( "Opacity %",        "The opacity in %. Transparency = 1 - Opacity.", 1.0 );
131
 
    m_alpha->setMin( 0.0 );
132
 
    m_alpha->setMax( 1.0 );
133
 
 
134
 
    m_colormapRatio = m_properties->addProperty( "Colormap ratio",   "The intensity of the colormap in contrast to surface shading.", 0.5 );
135
 
    m_colormapRatio->setMin( 0.0 );
136
 
    m_colormapRatio->setMax( 1.0 );
137
 
 
138
 
    m_phongShading  = m_properties->addProperty( "Phong shading", "If enabled, Phong shading gets applied on a per-pixel basis.", true );
139
 
 
140
 
    m_cortexMode    = m_properties->addProperty( "Emphasize cortex", "Emphasize the cortex while inner parts ar not that well lighten.", false );
141
 
 
142
 
    m_stochasticJitter = m_properties->addProperty( "Stochastic jitter", "Improves image quality at low sampling rates but introduces slight "
143
 
                                                                         "noise effect.", true );
144
 
 
145
 
    m_borderClip = m_properties->addProperty( "Border clip", "If enabled, a certain area on the volume boundary can be clipped. This is useful "
146
 
                                                             "for noise and non-peeled data but will consume a lot of GPU power.", false );
147
 
 
148
 
    m_borderClipDistance = m_properties->addProperty( "Border clip distance", "The distance that should be ignored.", 0.05 );
149
 
    m_borderClipDistance->setMin( 0.0 );
150
 
    m_borderClipDistance->setMax( 0.1 );
151
 
 
152
 
    WModule::properties();
153
 
}
154
 
 
155
 
void WMIsosurfaceRaytracer::requirements()
156
 
{
157
 
    m_requirements.push_back( new WGERequirement() );
158
 
}
159
 
 
160
 
void WMIsosurfaceRaytracer::moduleMain()
161
 
{
162
 
    m_shader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMIsosurfaceRaytracer", m_localPath ) );
163
 
    m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
164
 
        new WGEShaderPropertyDefineOptions< WPropBool >( m_cortexMode, "CORTEXMODE_DISABLED", "CORTEXMODE_ENABLED" ) )
165
 
    );
166
 
    m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
167
 
        new WGEShaderPropertyDefineOptions< WPropBool >( m_stochasticJitter, "STOCHASTICJITTER_DISABLED", "STOCHASTICJITTER_ENABLED" ) )
168
 
    );
169
 
    m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
170
 
        new WGEShaderPropertyDefine< WPropDouble >( "ISO_EPSILON", m_epsilon ) )
171
 
    );
172
 
    m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
173
 
        new WGEShaderPropertyDefineOptions< WPropBool >( m_phongShading, "PHONGSHADING_DISABLED", "PHONGSHADING_ENABLED" ) )
174
 
    );
175
 
    WGEShaderDefineSwitch::SPtr gradTexEnableDefine = m_shader->setDefine( "GRADIENTTEXTURE_ENABLED" );
176
 
    m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
177
 
        new WGEShaderPropertyDefineOptions< WPropBool >( m_borderClip, "BORDERCLIP_DISABLED", "BORDERCLIP_ENABLED" ) )
178
 
    );
179
 
 
180
 
    // let the main loop awake if the data changes or the properties changed.
181
 
    m_moduleState.setResetable( true, true );
182
 
    m_moduleState.add( m_input->getDataChangedCondition() );
183
 
    m_moduleState.add( m_gradients->getDataChangedCondition() );
184
 
    m_moduleState.add( m_propCondition );
185
 
 
186
 
    // Signal ready state.
187
 
    ready();
188
 
    debugLog() << "Module is now ready.";
189
 
 
190
 
    // create the root node containing the transformation and geometry
191
 
    osg::ref_ptr< WGEGroupNode > rootNode = new WGEGroupNode();
192
 
 
193
 
    // create the post-processing node which actually does the nice stuff to the rendered image
194
 
    osg::ref_ptr< WGEPostprocessingNode > postNode = new WGEPostprocessingNode(
195
 
        WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getCamera()
196
 
    );
197
 
    postNode->addUpdateCallback( new WGENodeMaskCallback( m_active ) ); // disable the postNode with m_active
198
 
 
199
 
    // provide the properties of the post-processor to the user
200
 
    m_properties->addProperty( postNode->getProperties() );
201
 
 
202
 
    // insert it
203
 
    postNode->insert( rootNode, m_shader );
204
 
    bool postNodeInserted = false;
205
 
 
206
 
    // Normally, you will have a loop which runs as long as the module should not shutdown. In this loop you can react on changing data on input
207
 
    // connectors or on changed in your properties.
208
 
    debugLog() << "Entering main loop";
209
 
    while( !m_shutdownFlag() )
210
 
    {
211
 
        // Now, the moduleState variable comes into play. The module can wait for the condition, which gets fired whenever the input receives data
212
 
        // or an property changes. The main loop now waits until something happens.
213
 
        debugLog() << "Waiting ...";
214
 
        m_moduleState.wait();
215
 
 
216
 
        // quit if requested
217
 
        if( m_shutdownFlag() )
218
 
        {
219
 
            break;
220
 
        }
221
 
 
222
 
        // was there an update?
223
 
        bool dataUpdated = m_input->updated() || m_gradients->updated();
224
 
        boost::shared_ptr< WDataSetScalar > dataSet = m_input->getData();
225
 
        bool dataValid   = ( dataSet );
226
 
 
227
 
        // valid data available?
228
 
        if( !dataValid )
229
 
        {
230
 
            // remove renderings if no data is available anymore
231
 
            rootNode->clear();
232
 
        }
233
 
 
234
 
        // m_isoColor or shading changed
235
 
        if( m_isoColor->changed() )
236
 
        {
237
 
            // a new color requires the proxy geometry to be rebuild as we store it as color in this geometry
238
 
            dataUpdated = true;
239
 
        }
240
 
 
241
 
        // As the data has changed, we need to recreate the texture.
242
 
        if( dataUpdated && dataValid )
243
 
        {
244
 
            debugLog() << "Data changed. Uploading new data as texture.";
245
 
 
246
 
            m_isoValue->setMin( dataSet->getTexture()->minimum()->get() );
247
 
            m_isoValue->setMax( dataSet->getTexture()->scale()->get() + dataSet->getTexture()->minimum()->get() );
248
 
            m_isoValue->setRecommendedValue( dataSet->getTexture()->minimum()->get() + ( 0.5 * dataSet->getTexture()->scale()->get() ) );
249
 
 
250
 
            // First, grab the grid
251
 
            boost::shared_ptr< WGridRegular3D > grid = boost::shared_dynamic_cast< WGridRegular3D >( dataSet->getGrid() );
252
 
            if( !grid )
253
 
            {
254
 
                errorLog() << "The dataset does not provide a regular grid. Ignoring dataset.";
255
 
                continue;
256
 
            }
257
 
 
258
 
            // use the OSG Shapes, create unit cube
259
 
            WBoundingBox bb( WPosition( 0.0, 0.0, 0.0 ),
260
 
                WPosition( grid->getNbCoordsX() - 1, grid->getNbCoordsY() - 1, grid->getNbCoordsZ() - 1 ) );
261
 
            osg::ref_ptr< osg::Node > cube = wge::generateSolidBoundingBoxNode( bb, m_isoColor->get( true ) );
262
 
            cube->asTransform()->getChild( 0 )->setName( "_DVR Proxy Cube" ); // Be aware that this name is used in the pick handler.
263
 
                                                                              // because of the underscore in front it won't be picked
264
 
            // we also set the grid's transformation here
265
 
            rootNode->setMatrix( static_cast< WMatrix4d >( grid->getTransform() ) );
266
 
 
267
 
            // bind the texture to the node
268
 
            osg::StateSet* rootState = cube->getOrCreateStateSet();
269
 
 
270
 
            // enable transparency
271
 
            wge::enableTransparency( cube );
272
 
 
273
 
            // bind the data texture
274
 
            osg::ref_ptr< WGETexture3D > texture3D = dataSet->getTexture();
275
 
            texture3D->bind( cube );
276
 
 
277
 
            ////////////////////////////////////////////////////////////////////////////////////////////////////
278
 
            // setup all those uniforms and additional textures
279
 
            ////////////////////////////////////////////////////////////////////////////////////////////////////
280
 
 
281
 
            rootState->addUniform( new WGEPropertyUniform< WPropDouble >( "u_isovalue", m_isoValue ) );
282
 
            rootState->addUniform( new WGEPropertyUniform< WPropInt >( "u_steps", m_stepCount ) );
283
 
            rootState->addUniform( new WGEPropertyUniform< WPropDouble >( "u_alpha", m_alpha ) );
284
 
            rootState->addUniform( new WGEPropertyUniform< WPropDouble >( "u_colormapRatio", m_colormapRatio ) );
285
 
            rootState->addUniform( new WGEPropertyUniform< WPropDouble >( "u_borderClipDistance", m_borderClipDistance ) );
286
 
            // Stochastic jitter?
287
 
            const size_t size = 64;
288
 
            osg::ref_ptr< WGETexture2D > randTex = wge::genWhiteNoiseTexture( size, size, 1 );
289
 
            wge::bindTexture( cube, randTex, 1 );
290
 
 
291
 
            // if there is a gradient field available -> apply as texture too
292
 
            boost::shared_ptr< WDataSetVector > gradients = m_gradients->getData();
293
 
            if( gradients )
294
 
            {
295
 
                debugLog() << "Uploading specified gradient field.";
296
 
 
297
 
                // bind the texture to the node
298
 
                osg::ref_ptr< WDataTexture3D > gradTexture3D = gradients->getTexture();
299
 
                wge::bindTexture( cube, gradTexture3D, 2, "u_gradients" );
300
 
                gradTexEnableDefine->setActive( true );
301
 
            }
302
 
            else
303
 
            {
304
 
                gradTexEnableDefine->setActive( false ); // disable gradient texture
305
 
            }
306
 
            WGEColormapping::apply( cube, grid->getTransformationMatrix(), m_shader, 3 );
307
 
 
308
 
            // update node
309
 
            debugLog() << "Adding new rendering.";
310
 
            rootNode->clear();
311
 
            rootNode->insert( cube );
312
 
            // insert root node if needed. This way, we ensure that the root node gets added only if the proxy cube has been added AND the bbox
313
 
            // can be calculated properly by the OSG to ensure the proxy cube is centered in the scene if no other item has been added earlier.
314
 
            if( !postNodeInserted )
315
 
            {
316
 
                postNodeInserted = true;
317
 
                WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( postNode );
318
 
            }
319
 
        }
320
 
    }
321
 
 
322
 
    // At this point, the container managing this module signalled to shutdown. The main loop has ended and you should clean up. Always remove
323
 
    // allocated memory and remove all OSG nodes.
324
 
    WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( postNode );
325
 
}
326