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

« back to all changes in this revision

Viewing changes to src/modules/superquadricGlyphs/WMSuperquadricGlyphs.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-Leipzig and CNCF-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 <vector>
 
27
 
 
28
#include <osg/Geode>
 
29
#include <osg/Geometry>
 
30
#include <osg/StateSet>
 
31
#include <osg/StateAttribute>
 
32
#include <osg/PolygonMode>
 
33
#include <osg/LightModel>
 
34
 
 
35
#include "core/kernel/WKernel.h"
 
36
 
 
37
#include "core/graphicsEngine/WGEUtils.h"
 
38
#include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
 
39
 
 
40
#include "WMSuperquadricGlyphs.h"
 
41
#include "WMSuperquadricGlyphs.xpm"
 
42
 
 
43
// This line is needed by the module loader to actually find your module.
 
44
W_LOADABLE_MODULE( WMSuperquadricGlyphs )
 
45
 
 
46
WMSuperquadricGlyphs::WMSuperquadricGlyphs():
 
47
    WModule()
 
48
{
 
49
    // initialize members
 
50
}
 
51
 
 
52
WMSuperquadricGlyphs::~WMSuperquadricGlyphs()
 
53
{
 
54
    // Cleanup!
 
55
    removeConnectors();
 
56
}
 
57
 
 
58
boost::shared_ptr< WModule > WMSuperquadricGlyphs::factory() const
 
59
{
 
60
    // create prototype
 
61
    return boost::shared_ptr< WModule >( new WMSuperquadricGlyphs() );
 
62
}
 
63
 
 
64
const char** WMSuperquadricGlyphs::getXPMIcon() const
 
65
{
 
66
    return superquadricglyphs_xpm;
 
67
}
 
68
 
 
69
const std::string WMSuperquadricGlyphs::getName() const
 
70
{
 
71
    return "Superquadric Glyphs";
 
72
}
 
73
 
 
74
const std::string WMSuperquadricGlyphs::getDescription() const
 
75
{
 
76
    return "GPU based ray-tracing of second order, superquadric tensor glyphs.";
 
77
}
 
78
 
 
79
void WMSuperquadricGlyphs::connectors()
 
80
{
 
81
    // The input second order tensor dataset
 
82
    m_input = boost::shared_ptr< WModuleInputData< WDataSetDTI > >( new WModuleInputData< WDataSetDTI >( shared_from_this(),
 
83
        "tensor input", "An input set of 2nd-order tensors on a regular 3D-grid." )
 
84
    );
 
85
    addConnector( m_input );
 
86
 
 
87
    // call WModule's initialization
 
88
    WModule::connectors();
 
89
}
 
90
 
 
91
void WMSuperquadricGlyphs::properties()
 
92
{
 
93
    // The condition fires on property updates
 
94
    m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
 
95
 
 
96
    // The slice positions. These get update externally
 
97
    m_xPos           = m_properties->addProperty( "Sagittal position", "Slice X position.", 0, m_propCondition );
 
98
    m_yPos           = m_properties->addProperty( "Coronal position", "Slice Y position.", 0, m_propCondition );
 
99
    m_zPos           = m_properties->addProperty( "Axial position", "Slice Z position.", 0, m_propCondition );
 
100
    m_xPos->setMin( 0 );
 
101
    m_xPos->setMax( 1 );
 
102
    m_yPos->setMin( 0 );
 
103
    m_yPos->setMax( 1 );
 
104
    m_zPos->setMin( 0 );
 
105
    m_zPos->setMax( 1 );
 
106
 
 
107
    // Flags denoting whether the glyphs should be shown on the specific slice
 
108
    // NOTE: the showon* properties do not need to notify m_propCondition as they get handled by the slice's osg node.
 
109
    m_showonX        = m_properties->addProperty( "Show sagittal", "Show vectors on sagittal slice.", true );
 
110
    m_showonY        = m_properties->addProperty( "Show coronal", "Show vectors on coronal slice.", true );
 
111
    m_showonZ        = m_properties->addProperty( "Show axial", "Show vectors on axial slice.", true );
 
112
 
 
113
    // Thresholding for filtering glyphs
 
114
    m_evThreshold = m_properties->addProperty( "Eigenvalue threshold",
 
115
                                               "Clip Glyphs whose smallest eigenvalue is below the given threshold.", 0.01 );
 
116
    m_evThreshold->setMin( 0.0 );
 
117
    m_evThreshold->setMax( 1.0 );
 
118
    m_faThreshold = m_properties->addProperty( "FA threshold",
 
119
                                               "Clip Glyphs whose fractional anisotropy is below the given threshold.", 0.01 );
 
120
    m_faThreshold->setMin( 0.0 );
 
121
    m_faThreshold->setMax( 1.0 );
 
122
 
 
123
    m_gamma = m_properties->addProperty( "Gamma", "Sharpness Parameter of the SuperQuadrics.", 10.0 );
 
124
    m_gamma->setMin( 0.0 );
 
125
    m_gamma->setMax( 10.0 );
 
126
 
 
127
    m_scaling = m_properties->addProperty( "Scaling", "Scaling of Glyphs.", 0.5 );
 
128
    m_scaling->setMin( 0.0 );
 
129
    m_scaling->setMax( 2.0 );
 
130
}
 
131
 
 
132
inline void WMSuperquadricGlyphs::addGlyph( osg::Vec3 position, osg::ref_ptr< osg::Vec3Array > vertices, osg::ref_ptr< osg::Vec3Array > orientation )
 
133
{
 
134
    // Front Face
 
135
    vertices->push_back( position );
 
136
    orientation->push_back( osg::Vec3( -1.0, -1.0, -1.0 ) );
 
137
    vertices->push_back( position );
 
138
    orientation->push_back( osg::Vec3(  1.0, -1.0, -1.0 ) );
 
139
    vertices->push_back( position );
 
140
    orientation->push_back( osg::Vec3(  1.0,  1.0, -1.0 ) );
 
141
    vertices->push_back( position );
 
142
    orientation->push_back( osg::Vec3( -1.0,  1.0, -1.0 ) );
 
143
 
 
144
    // Back Face
 
145
    vertices->push_back( position );
 
146
    orientation->push_back( osg::Vec3( -1.0, -1.0, 1.0 ) );
 
147
    vertices->push_back( position );
 
148
    orientation->push_back( osg::Vec3(  1.0, -1.0, 1.0 ) );
 
149
    vertices->push_back( position );
 
150
    orientation->push_back( osg::Vec3(  1.0,  1.0, 1.0 ) );
 
151
    vertices->push_back( position );
 
152
    orientation->push_back( osg::Vec3( -1.0,  1.0, 1.0 ) );
 
153
 
 
154
    // Top Face
 
155
    vertices->push_back( position );
 
156
    orientation->push_back( osg::Vec3( -1.0,  1.0, -1.0 ) );
 
157
    vertices->push_back( position );
 
158
    orientation->push_back( osg::Vec3(  1.0,  1.0, -1.0 ) );
 
159
    vertices->push_back( position );
 
160
    orientation->push_back( osg::Vec3(  1.0,  1.0, 1.0 ) );
 
161
    vertices->push_back( position );
 
162
    orientation->push_back( osg::Vec3( -1.0,  1.0, 1.0 ) );
 
163
 
 
164
    // Bottom Face
 
165
    vertices->push_back( position );
 
166
    orientation->push_back( osg::Vec3( -1.0, -1.0, -1.0 ) );
 
167
    vertices->push_back( position );
 
168
    orientation->push_back( osg::Vec3(  1.0,  -1.0, -1.0 ) );
 
169
    vertices->push_back( position );
 
170
    orientation->push_back( osg::Vec3(  1.0,  -1.0, 1.0 ) );
 
171
    vertices->push_back( position );
 
172
    orientation->push_back( osg::Vec3( -1.0,  -1.0, 1.0 ) );
 
173
 
 
174
    // Left Face
 
175
    vertices->push_back( position );
 
176
    orientation->push_back( osg::Vec3( -1.0, -1.0, -1.0 ) );
 
177
    vertices->push_back( position );
 
178
    orientation->push_back( osg::Vec3(  -1.0, 1.0, -1.0 ) );
 
179
    vertices->push_back( position );
 
180
    orientation->push_back( osg::Vec3(  -1.0, 1.0, 1.0 ) );
 
181
    vertices->push_back( position );
 
182
    orientation->push_back( osg::Vec3( -1.0, -1.0, 1.0 ) );
 
183
 
 
184
    // Right Face
 
185
    vertices->push_back( position );
 
186
    orientation->push_back( osg::Vec3( 1.0, -1.0, -1.0 ) );
 
187
    vertices->push_back( position );
 
188
    orientation->push_back( osg::Vec3( 1.0, 1.0, -1.0 ) );
 
189
    vertices->push_back( position );
 
190
    orientation->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
 
191
    vertices->push_back( position );
 
192
    orientation->push_back( osg::Vec3( 1.0, -1.0, 1.0 ) );
 
193
}
 
194
 
 
195
void WMSuperquadricGlyphs::addTensor( size_t idx, osg::Vec3Array* diag, osg::Vec3Array* offdiag )
 
196
{
 
197
    osg::Vec3 d = osg::Vec3( m_dataSetValueSet->getScalarDouble( idx * 6 + 0 ),
 
198
                             m_dataSetValueSet->getScalarDouble( idx * 6 + 3 ),
 
199
                             m_dataSetValueSet->getScalarDouble( idx * 6 + 5 ) );
 
200
    osg::Vec3 o = osg::Vec3( m_dataSetValueSet->getScalarDouble( idx * 6 + 1 ),
 
201
                             m_dataSetValueSet->getScalarDouble( idx * 6 + 2 ),
 
202
                             m_dataSetValueSet->getScalarDouble( idx * 6 + 4 ) );
 
203
 
 
204
    // we need to add it for every vertex per glyph!
 
205
    for( size_t c = 0; c < 6 * 4; ++c )
 
206
    {
 
207
        diag->push_back( d );
 
208
        offdiag->push_back( o );
 
209
    }
 
210
}
 
211
 
 
212
void WMSuperquadricGlyphs::initOSG()
 
213
{
 
214
    // The Idea behind all this is to have fast updates when the navigation slices move. By presetting glyph vertex and tex coords -> fast change
 
215
    // of diag and offdiag tex arrays possible. The slices are moved using the transform nodes
 
216
 
 
217
    debugLog() << "Grid Size: " << m_maxX << "x" << m_maxY << "x" << m_maxZ;
 
218
    debugLog() << "Creating " << m_nbGlyphsX + m_nbGlyphsY + m_nbGlyphsZ << " glyphs.";
 
219
 
 
220
    // remove the old slices
 
221
    m_output->remove( m_xSlice );
 
222
    m_output->remove( m_ySlice );
 
223
    m_output->remove( m_zSlice );
 
224
 
 
225
    // create all the transformation nodes
 
226
    m_xSlice = new WGEManagedGroupNode( m_showonX );
 
227
    m_xSlice->setMatrix( osg::Matrixd::identity() );
 
228
    m_ySlice = new WGEManagedGroupNode( m_showonY );
 
229
    m_ySlice->setMatrix( osg::Matrixd::identity() );
 
230
    m_zSlice = new WGEManagedGroupNode( m_showonZ );
 
231
    m_zSlice->setMatrix( osg::Matrixd::identity() );
 
232
 
 
233
    // init the vertex arrays
 
234
    osg::ref_ptr< osg::Geode > geode;
 
235
    osg::ref_ptr< osg::Geometry > geometry;
 
236
    osg::ref_ptr< osg::DrawArrays > da;
 
237
 
 
238
    // NOTE: it would be nice to use one vertex and tex array for all the three but this disallows us to replace the tensor diag/offdiag arrays
 
239
    // for each slide separately.
 
240
    osg::ref_ptr< osg::Vec3Array > vertices;
 
241
    osg::ref_ptr< osg::Vec3Array > texcoords0;
 
242
 
 
243
    ///////////////
 
244
    // X Slice
 
245
 
 
246
    // fill the geode with glyph proxy geometry for a slice
 
247
    vertices = new osg::Vec3Array;
 
248
    vertices->reserve( m_nbGlyphsX * 6 * 4 );
 
249
    texcoords0 = new osg::Vec3Array;
 
250
    texcoords0->reserve( m_nbGlyphsX * 6 * 4 );
 
251
    geometry = new osg::Geometry();
 
252
    geometry->setDataVariance( osg::Object::DYNAMIC );
 
253
    geometry->setVertexArray( vertices );
 
254
    geometry->setUseVertexBufferObjects( true );
 
255
    geometry->setTexCoordArray( 0, texcoords0 );
 
256
    da = new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, m_nbGlyphsX * 6 * 4 );
 
257
    geometry->addPrimitiveSet( da );
 
258
 
 
259
    // create a new geode containing the glyphs proxy geometry
 
260
    geode = new osg::Geode();
 
261
    geode->addDrawable( geometry );
 
262
 
 
263
    // add a glyph at every position
 
264
    for( size_t z = 0; z < m_maxZ; ++z )
 
265
    {
 
266
        for( size_t y = 0; y < m_maxY; ++y )
 
267
        {
 
268
            addGlyph( osg::Vec3d( 0.0, y, z ), vertices, texcoords0 );
 
269
        }
 
270
    }
 
271
 
 
272
    // set some callbacks
 
273
    m_xSliceGlyphCallback = new GlyphGeometryNodeCallback( geometry );
 
274
    geometry->setUpdateCallback( m_xSliceGlyphCallback );
 
275
    m_xSlice->addUpdateCallback( new WGELinearTranslationCallback< WPropInt >( osg::Vec3( 1.0, 0.0, 0.0 ), m_xPos ) );
 
276
    m_xSlice->addChild( geode );
 
277
 
 
278
    ///////////////
 
279
    // Y Slice, sorry for code duplication.
 
280
 
 
281
    // fill the geode with glyph proxy geometry for a slice
 
282
    vertices = new osg::Vec3Array;
 
283
    vertices->reserve( m_nbGlyphsX * 6 * 4 );
 
284
    texcoords0 = new osg::Vec3Array;
 
285
    texcoords0->reserve( m_nbGlyphsX * 6 * 4 );
 
286
    geometry = new osg::Geometry();
 
287
    geometry->setDataVariance( osg::Object::DYNAMIC );
 
288
    geometry->setVertexArray( vertices );
 
289
    geometry->setUseVertexBufferObjects( true );
 
290
    geometry->setTexCoordArray( 0, texcoords0 );
 
291
    da = new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, m_nbGlyphsY * 6 * 4 );
 
292
    geometry->addPrimitiveSet( da );
 
293
 
 
294
    // create a new geode containing the glyphs proxy geometry
 
295
    geode = new osg::Geode();
 
296
    geode->addDrawable( geometry );
 
297
    // add a glyph at every position
 
298
    for( size_t z = 0; z < m_maxZ; ++z )
 
299
    {
 
300
        for( size_t x = 0; x < m_maxX; ++x )
 
301
        {
 
302
            addGlyph( osg::Vec3d( x, 0.0, z ), vertices, texcoords0 );
 
303
        }
 
304
    }
 
305
 
 
306
    // set some callbacks
 
307
    m_ySliceGlyphCallback = new GlyphGeometryNodeCallback( geometry );
 
308
    geometry->setUpdateCallback( m_ySliceGlyphCallback );
 
309
    m_ySlice->addUpdateCallback( new WGELinearTranslationCallback< WPropInt >( osg::Vec3( 0.0, 1.0, 0.0 ), m_yPos ) );
 
310
    m_ySlice->addChild( geode );
 
311
 
 
312
    ///////////////
 
313
    // Z Slice, sorry for code duplication.
 
314
 
 
315
    // fill the geode with glyph proxy geometry for a slice
 
316
    vertices = new osg::Vec3Array;
 
317
    vertices->reserve( m_nbGlyphsX * 6 * 4 );
 
318
    texcoords0 = new osg::Vec3Array;
 
319
    texcoords0->reserve( m_nbGlyphsX * 6 * 4 );
 
320
    geometry = new osg::Geometry();
 
321
    geometry->setDataVariance( osg::Object::DYNAMIC );
 
322
    geometry->setVertexArray( vertices );
 
323
    geometry->setUseVertexBufferObjects( true );
 
324
    geometry->setTexCoordArray( 0, texcoords0 );
 
325
    da = new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, m_nbGlyphsZ * 6 * 4 );
 
326
    geometry->addPrimitiveSet( da );
 
327
 
 
328
    // create a new geode containing the glyphs proxy geometry
 
329
    geode = new osg::Geode();
 
330
    geode->addDrawable( geometry );
 
331
    // add a glyph at every position
 
332
    for( size_t y = 0; y < m_maxY; ++y )
 
333
    {
 
334
        for( size_t x = 0; x < m_maxX; ++x )
 
335
        {
 
336
            addGlyph( osg::Vec3d( x, y, 0.0 ), vertices, texcoords0 );
 
337
        }
 
338
    }
 
339
 
 
340
    // set some callbacks
 
341
    m_zSliceGlyphCallback = new GlyphGeometryNodeCallback( geometry );
 
342
    geometry->setUpdateCallback( m_zSliceGlyphCallback );
 
343
    m_zSlice->addUpdateCallback( new WGELinearTranslationCallback< WPropInt >( osg::Vec3( 0.0, 0.0, 1.0 ), m_zPos ) );
 
344
    m_zSlice->addChild( geode );
 
345
 
 
346
    // add the transformation nodes to the output group
 
347
    m_output->insert( m_xSlice );
 
348
    m_output->insert( m_ySlice );
 
349
    m_output->insert( m_zSlice );
 
350
}
 
351
 
 
352
void WMSuperquadricGlyphs::GlyphGeometryNodeCallback::update( osg::NodeVisitor* /*nv*/, osg::Drawable* /*d*/ )
 
353
{
 
354
    if( m_dirty )
 
355
    {
 
356
        m_dirty = false;
 
357
 
 
358
        // update the tex array
 
359
        m_geometry->setTexCoordArray( 1, m_tensorDiag );
 
360
        m_geometry->setTexCoordArray( 2, m_tensorOffDiag );
 
361
    }
 
362
}
 
363
 
 
364
void WMSuperquadricGlyphs::GlyphGeometryNodeCallback::setNewTensorData( osg::ref_ptr< osg::Vec3Array > diag, osg::ref_ptr< osg::Vec3Array > offdiag )
 
365
{
 
366
    m_tensorDiag = diag;
 
367
    m_tensorOffDiag = offdiag;
 
368
 
 
369
    m_dirty = true;
 
370
}
 
371
 
 
372
void WMSuperquadricGlyphs::moduleMain()
 
373
{
 
374
    // use the m_input "data changed" flag
 
375
    m_moduleState.setResetable( true, true );
 
376
    m_moduleState.add( m_input->getDataChangedCondition() );
 
377
    // use property condition to wake up on property changes
 
378
    m_moduleState.add( m_propCondition );
 
379
 
 
380
    // signal ready state
 
381
    ready();
 
382
 
 
383
    // create all these geodes we need
 
384
    m_output = osg::ref_ptr< WGEManagedGroupNode > ( new WGEManagedGroupNode( m_active ) );
 
385
    WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_output );
 
386
    osg::ref_ptr< osg::StateSet > sset = m_output->getOrCreateStateSet();
 
387
    sset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
 
388
 
 
389
    // add shader
 
390
    m_shader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMSuperquadricGlyphs", m_localPath ) );
 
391
    m_shader->apply( m_output );
 
392
 
 
393
    // set uniform callbacks and uniforms
 
394
    osg::ref_ptr< osg::Uniform > evThreshold = new WGEPropertyUniform< WPropDouble >( "u_evThreshold", m_evThreshold );
 
395
    osg::ref_ptr< osg::Uniform > faThreshold = new WGEPropertyUniform< WPropDouble >( "u_faThreshold", m_faThreshold );
 
396
    osg::ref_ptr< osg::Uniform > scaling = new WGEPropertyUniform< WPropDouble >( "u_scaling", m_scaling );
 
397
    osg::ref_ptr< osg::Uniform > gamma = new WGEPropertyUniform< WPropDouble >( "u_gamma", m_gamma );
 
398
 
 
399
    sset->addUniform( evThreshold );
 
400
    sset->addUniform( faThreshold );
 
401
    sset->addUniform( scaling );
 
402
    sset->addUniform( gamma );
 
403
 
 
404
    bool initialTensorUpload = true;
 
405
 
 
406
    // loop until the module container requests the module to quit
 
407
    while( !m_shutdownFlag() )
 
408
    {
 
409
        m_moduleState.wait();
 
410
 
 
411
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
412
        // After waking up, the module has to check whether the shutdownFlag fired. If yes, simply quit the module.
 
413
 
 
414
        // woke up since the module is requested to finish
 
415
        if( m_shutdownFlag() )
 
416
        {
 
417
            break;
 
418
        }
 
419
 
 
420
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
421
        // Collect changes
 
422
 
 
423
        // has the data changes? And even more important: is it valid?
 
424
        boost::shared_ptr< WDataSetDTI > newDataSet = m_input->getData();
 
425
        bool dataChanged = ( m_dataSet != newDataSet );
 
426
        bool dataValid   = ( newDataSet );
 
427
 
 
428
        // if data is invalid, remove rendering
 
429
        if( !dataValid )
 
430
        {
 
431
            debugLog() << "Resetting.";
 
432
            m_output->clear();
 
433
            m_dataSet.reset();
 
434
            continue;
 
435
        }
 
436
 
 
437
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
438
        // Handle changes
 
439
 
 
440
        if( dataChanged && dataValid )
 
441
        {
 
442
            // The data is different. Copy it to our internal data variable:
 
443
            debugLog() << "Received Data.";
 
444
            initialTensorUpload = true;
 
445
 
 
446
            // also provide progress information
 
447
            boost::shared_ptr< WProgress > progress1 = boost::shared_ptr< WProgress >( new WProgress( "Building Glyph Geometry" ) );
 
448
            m_progress->addSubProgress( progress1 );
 
449
 
 
450
            // get pointers for the new data
 
451
            m_dataSet = newDataSet;
 
452
            m_dataSetGrid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
 
453
            WAssert( m_dataSetGrid, "Dataset does not have a regular 3D grid." );
 
454
            m_maxX = m_dataSetGrid->getNbCoordsX();
 
455
            m_maxY = m_dataSetGrid->getNbCoordsY();
 
456
            m_maxZ = m_dataSetGrid->getNbCoordsZ();
 
457
            m_dataSetValueSet = m_dataSet->getValueSet();
 
458
            m_nbGlyphsX = m_maxY * m_maxZ;
 
459
            m_nbGlyphsY = m_maxX * m_maxZ;
 
460
            m_nbGlyphsZ = m_maxX * m_maxY;
 
461
 
 
462
            // update properties
 
463
            m_xPos->setMax( m_maxX );
 
464
            m_xPos->set( m_maxX / 2 );
 
465
            m_yPos->setMax( m_maxY );
 
466
            m_yPos->set( m_maxY / 2 );
 
467
            m_zPos->setMax( m_maxZ );
 
468
            m_zPos->set( m_maxZ / 2 );
 
469
 
 
470
            m_output->setMatrix( static_cast< WMatrix4d >( m_dataSetGrid->getTransform() ) );
 
471
 
 
472
            // new data -> update OSG Stuff
 
473
            initOSG();
 
474
            progress1->finish();
 
475
        }
 
476
 
 
477
        if( dataValid && ( m_xPos->changed() || initialTensorUpload ) )
 
478
        {
 
479
            // also provide progress information
 
480
            boost::shared_ptr< WProgress > progress1 = boost::shared_ptr< WProgress >( new WProgress( "Building Glyph Geometry" ) );
 
481
            m_progress->addSubProgress( progress1 );
 
482
 
 
483
            // grab some mem
 
484
            osg::ref_ptr< osg::Vec3Array > diag = new osg::Vec3Array;
 
485
            diag->reserve( m_nbGlyphsX * 6 * 4 );
 
486
            osg::ref_ptr< osg::Vec3Array > offdiag = new osg::Vec3Array;
 
487
            offdiag->reserve( m_nbGlyphsX * 6 * 4 );
 
488
 
 
489
            // this updates the diag/offdiag texture coordinate arrays of the xSlice
 
490
            // x = const -> handle xPos property
 
491
            size_t fixedX = m_xPos->get( true );
 
492
            for( size_t z = 0; z < m_maxZ; ++z )
 
493
            {
 
494
                // Calculate the current position along the z direction
 
495
                size_t zPre = fixedX + z * m_maxX * m_maxY;
 
496
 
 
497
                for( size_t y = 0; y < m_maxY; ++y )
 
498
                {
 
499
                    // add glyph
 
500
                    addTensor( zPre + y * m_maxX, diag, offdiag );
 
501
                }
 
502
            }
 
503
 
 
504
            m_xSliceGlyphCallback->setNewTensorData( diag, offdiag );
 
505
            progress1->finish();
 
506
        }
 
507
 
 
508
        if( dataValid && ( m_yPos->changed() || initialTensorUpload ) )
 
509
        {
 
510
            // also provide progress information
 
511
            boost::shared_ptr< WProgress > progress1 = boost::shared_ptr< WProgress >( new WProgress( "Building Glyph Geometry" ) );
 
512
            m_progress->addSubProgress( progress1 );
 
513
 
 
514
            // grab some mem
 
515
            osg::ref_ptr< osg::Vec3Array > diag = new osg::Vec3Array;
 
516
            diag->reserve( m_nbGlyphsX * 6 * 4 );
 
517
            osg::ref_ptr< osg::Vec3Array > offdiag = new osg::Vec3Array;
 
518
            offdiag->reserve( m_nbGlyphsX * 6 * 4 );
 
519
 
 
520
            // y = const -> handle yPos property
 
521
            size_t fixedY = m_yPos->get( true );
 
522
            size_t fixedYOffset = fixedY * m_maxX;
 
523
            for( size_t z = 0; z < m_maxZ; ++z )
 
524
            {
 
525
                // Calculate current offset for value index
 
526
                size_t zPre = fixedYOffset + ( z * m_maxX * m_maxY );
 
527
 
 
528
                for( size_t x = 0; x < m_maxX; ++x )
 
529
                {
 
530
                    // add glyph
 
531
                    addTensor( zPre + x, diag, offdiag );
 
532
                }
 
533
            }
 
534
 
 
535
            m_ySliceGlyphCallback->setNewTensorData( diag, offdiag );
 
536
            progress1->finish();
 
537
        }
 
538
 
 
539
        if( dataValid && ( m_zPos->changed() || initialTensorUpload ) )
 
540
        {
 
541
            // also provide progress information
 
542
            boost::shared_ptr< WProgress > progress1 = boost::shared_ptr< WProgress >( new WProgress( "Building Glyph Geometry" ) );
 
543
            m_progress->addSubProgress( progress1 );
 
544
 
 
545
            // grab some mem
 
546
            osg::ref_ptr< osg::Vec3Array > diag = new osg::Vec3Array;
 
547
            diag->reserve( m_nbGlyphsX * 6 * 4 );
 
548
            osg::ref_ptr< osg::Vec3Array > offdiag = new osg::Vec3Array;
 
549
            offdiag->reserve( m_nbGlyphsX * 6 * 4 );
 
550
 
 
551
            // z = const -> handle zPos property
 
552
            size_t fixedZ = static_cast< size_t >( m_zPos->get( true ) );
 
553
            size_t fixedZOffset = fixedZ * m_maxX * m_maxY;
 
554
            for( size_t y = 0; y < m_maxY; ++y )
 
555
            {
 
556
                // Calculate current offset for value index
 
557
                size_t yPre = fixedZOffset + ( y * m_maxX );
 
558
 
 
559
                for( size_t x = 0; x < m_maxX; ++x )
 
560
                {
 
561
                    // add glyph
 
562
                    addTensor( yPre + x, diag, offdiag );
 
563
                }
 
564
            }
 
565
 
 
566
            m_zSliceGlyphCallback->setNewTensorData( diag, offdiag );
 
567
            progress1->finish();
 
568
        }
 
569
 
 
570
        initialTensorUpload = false;
 
571
    }
 
572
 
 
573
    // At this point, the container managing this module signalled to shutdown. The main loop has ended and you should clean up. Always remove
 
574
    // allocated memory and remove all OSG nodes.
 
575
    WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_output );
 
576
}
 
577