OpenWalnut  1.5.0dev
WMSuperquadricGlyphs.cpp
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 <memory>
26 #include <string>
27 #include <vector>
28 
29 #include <osg/Geode>
30 #include <osg/Geometry>
31 #include <osg/LightModel>
32 #include <osg/PolygonMode>
33 #include <osg/StateAttribute>
34 #include <osg/StateSet>
35 
36 #include "WMSuperquadricGlyphs.h"
37 #include "WMSuperquadricGlyphs.xpm"
38 #include "core/graphicsEngine/WGEUtils.h"
39 #include "core/graphicsEngine/postprocessing/WGEPostprocessingNode.h"
40 #include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
41 #include "core/kernel/WKernel.h"
42 
43 // This line is needed by the module loader to actually find your module.
44 W_LOADABLE_MODULE( WMSuperquadricGlyphs )
45 
47  WModule()
48 {
49  // initialize members
50 }
51 
53 {
54  // Cleanup!
56 }
57 
58 std::shared_ptr< WModule > WMSuperquadricGlyphs::factory() const
59 {
60  // create prototype
61  return std::shared_ptr< WModule >( new WMSuperquadricGlyphs() );
62 }
63 
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 
80 {
81  // The input second order tensor dataset
82  m_input = std::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  );
86 
87  // call WModule's initialization
89 }
90 
92 {
93  // The condition fires on property updates
94  m_propCondition = std::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  m_directionalColoring = m_properties->addProperty( "Directional Color", "Color glyphs by main direction.", true );
132 }
133 
134 inline void WMSuperquadricGlyphs::addGlyph( osg::Vec3 position, osg::ref_ptr< osg::Vec3Array > vertices, osg::ref_ptr< osg::Vec3Array > orientation )
135 {
136  // Front Face
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  vertices->push_back( position );
144  orientation->push_back( osg::Vec3( -1.0, 1.0, -1.0 ) );
145 
146  // Back Face
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  vertices->push_back( position );
154  orientation->push_back( osg::Vec3( -1.0, 1.0, 1.0 ) );
155 
156  // Top Face
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  vertices->push_back( position );
164  orientation->push_back( osg::Vec3( -1.0, 1.0, 1.0 ) );
165 
166  // Bottom Face
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  vertices->push_back( position );
174  orientation->push_back( osg::Vec3( -1.0, -1.0, 1.0 ) );
175 
176  // Left Face
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  vertices->push_back( position );
184  orientation->push_back( osg::Vec3( -1.0, -1.0, 1.0 ) );
185 
186  // Right Face
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  vertices->push_back( position );
194  orientation->push_back( osg::Vec3( 1.0, -1.0, 1.0 ) );
195 }
196 
197 void WMSuperquadricGlyphs::addTensor( size_t idx, osg::Vec3Array* diag, osg::Vec3Array* offdiag )
198 {
199  osg::Vec3 d = osg::Vec3( m_dataSetValueSet->getScalarDouble( idx * 6 + 0 ),
200  m_dataSetValueSet->getScalarDouble( idx * 6 + 3 ),
201  m_dataSetValueSet->getScalarDouble( idx * 6 + 5 ) );
202  osg::Vec3 o = osg::Vec3( m_dataSetValueSet->getScalarDouble( idx * 6 + 1 ),
203  m_dataSetValueSet->getScalarDouble( idx * 6 + 2 ),
204  m_dataSetValueSet->getScalarDouble( idx * 6 + 4 ) );
205 
206  // we need to add it for every vertex per glyph!
207  for( size_t c = 0; c < 6 * 4; ++c )
208  {
209  diag->push_back( d );
210  offdiag->push_back( o );
211  }
212 }
213 
215 {
216  // The Idea behind all this is to have fast updates when the navigation slices move. By presetting glyph vertex and tex coords -> fast change
217  // of diag and offdiag tex arrays possible. The slices are moved using the transform nodes
218 
219  debugLog() << "Grid Size: " << m_maxX << "x" << m_maxY << "x" << m_maxZ;
220  debugLog() << "Creating " << m_nbGlyphsX + m_nbGlyphsY + m_nbGlyphsZ << " glyphs.";
221 
222  // remove the old slices
223  m_output->remove( m_xSlice );
224  m_output->remove( m_ySlice );
225  m_output->remove( m_zSlice );
226 
227  // create all the transformation nodes
229  m_xSlice->setMatrix( osg::Matrixd::identity() );
231  m_ySlice->setMatrix( osg::Matrixd::identity() );
233  m_zSlice->setMatrix( osg::Matrixd::identity() );
234 
235  // init the vertex arrays
236  osg::ref_ptr< osg::Geode > geode;
237  osg::ref_ptr< osg::Geometry > geometry;
238  osg::ref_ptr< osg::DrawArrays > da;
239 
240  // 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
241  // for each slide separately.
242  osg::ref_ptr< osg::Vec3Array > vertices;
243  osg::ref_ptr< osg::Vec3Array > texcoords0;
244 
245  ///////////////
246  // X Slice
247 
248  // fill the geode with glyph proxy geometry for a slice
249  vertices = new osg::Vec3Array;
250  vertices->reserve( m_nbGlyphsX * 6 * 4 );
251  texcoords0 = new osg::Vec3Array;
252  texcoords0->reserve( m_nbGlyphsX * 6 * 4 );
253  geometry = new osg::Geometry();
254  geometry->setDataVariance( osg::Object::DYNAMIC );
255  geometry->setVertexArray( vertices );
256  geometry->setUseVertexBufferObjects( true );
257  geometry->setTexCoordArray( 0, texcoords0 );
258  da = new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, m_nbGlyphsX * 6 * 4 );
259  geometry->addPrimitiveSet( da );
260 
261  // create a new geode containing the glyphs proxy geometry
262  geode = new osg::Geode();
263  geode->addDrawable( geometry );
264 
265  // add a glyph at every position
266  for( size_t z = 0; z < m_maxZ; ++z )
267  {
268  for( size_t y = 0; y < m_maxY; ++y )
269  {
270  addGlyph( osg::Vec3d( 0.0, y, z ), vertices, texcoords0 );
271  }
272  }
273 
274  // set some callbacks
276  geometry->setUpdateCallback( m_xSliceGlyphCallback );
277  m_xSlice->addUpdateCallback( new WGELinearTranslationCallback< WPropInt >( osg::Vec3( 1.0, 0.0, 0.0 ), m_xPos ) );
278  m_xSlice->addChild( geode );
279 
280  ///////////////
281  // Y Slice, sorry for code duplication.
282 
283  // fill the geode with glyph proxy geometry for a slice
284  vertices = new osg::Vec3Array;
285  vertices->reserve( m_nbGlyphsX * 6 * 4 );
286  texcoords0 = new osg::Vec3Array;
287  texcoords0->reserve( m_nbGlyphsX * 6 * 4 );
288  geometry = new osg::Geometry();
289  geometry->setDataVariance( osg::Object::DYNAMIC );
290  geometry->setVertexArray( vertices );
291  geometry->setUseVertexBufferObjects( true );
292  geometry->setTexCoordArray( 0, texcoords0 );
293  da = new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, m_nbGlyphsY * 6 * 4 );
294  geometry->addPrimitiveSet( da );
295 
296  // create a new geode containing the glyphs proxy geometry
297  geode = new osg::Geode();
298  geode->addDrawable( geometry );
299  // add a glyph at every position
300  for( size_t z = 0; z < m_maxZ; ++z )
301  {
302  for( size_t x = 0; x < m_maxX; ++x )
303  {
304  addGlyph( osg::Vec3d( x, 0.0, z ), vertices, texcoords0 );
305  }
306  }
307 
308  // set some callbacks
310  geometry->setUpdateCallback( m_ySliceGlyphCallback );
311  m_ySlice->addUpdateCallback( new WGELinearTranslationCallback< WPropInt >( osg::Vec3( 0.0, 1.0, 0.0 ), m_yPos ) );
312  m_ySlice->addChild( geode );
313 
314  ///////////////
315  // Z Slice, sorry for code duplication.
316 
317  // fill the geode with glyph proxy geometry for a slice
318  vertices = new osg::Vec3Array;
319  vertices->reserve( m_nbGlyphsX * 6 * 4 );
320  texcoords0 = new osg::Vec3Array;
321  texcoords0->reserve( m_nbGlyphsX * 6 * 4 );
322  geometry = new osg::Geometry();
323  geometry->setDataVariance( osg::Object::DYNAMIC );
324  geometry->setVertexArray( vertices );
325  geometry->setUseVertexBufferObjects( true );
326  geometry->setTexCoordArray( 0, texcoords0 );
327  da = new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, m_nbGlyphsZ * 6 * 4 );
328  geometry->addPrimitiveSet( da );
329 
330  // create a new geode containing the glyphs proxy geometry
331  geode = new osg::Geode();
332  geode->addDrawable( geometry );
333  // add a glyph at every position
334  for( size_t y = 0; y < m_maxY; ++y )
335  {
336  for( size_t x = 0; x < m_maxX; ++x )
337  {
338  addGlyph( osg::Vec3d( x, y, 0.0 ), vertices, texcoords0 );
339  }
340  }
341 
342  // set some callbacks
344  geometry->setUpdateCallback( m_zSliceGlyphCallback );
345  m_zSlice->addUpdateCallback( new WGELinearTranslationCallback< WPropInt >( osg::Vec3( 0.0, 0.0, 1.0 ), m_zPos ) );
346  m_zSlice->addChild( geode );
347 
348  // add the transformation nodes to the output group
349  m_output->insert( m_xSlice );
350  m_output->insert( m_ySlice );
351  m_output->insert( m_zSlice );
352 }
353 
354 void WMSuperquadricGlyphs::GlyphGeometryNodeCallback::update( osg::NodeVisitor* /*nv*/, osg::Drawable* /*d*/ )
355 {
356  if( m_dirty )
357  {
358  m_dirty = false;
359 
360  // update the tex array
361  m_geometry->setTexCoordArray( 1, m_tensorDiag );
362  m_geometry->setTexCoordArray( 2, m_tensorOffDiag );
363  }
364 }
365 
366 void WMSuperquadricGlyphs::GlyphGeometryNodeCallback::setNewTensorData( osg::ref_ptr< osg::Vec3Array > diag, osg::ref_ptr< osg::Vec3Array > offdiag )
367 {
368  m_tensorDiag = diag;
369  m_tensorOffDiag = offdiag;
370 
371  m_dirty = true;
372 }
373 
375 {
376  // use the m_input "data changed" flag
377  m_moduleState.setResetable( true, true );
378  m_moduleState.add( m_input->getDataChangedCondition() );
379  // use property condition to wake up on property changes
381 
382  // signal ready state
383  ready();
384 
385  // postproc node
386  osg::ref_ptr< WGEPostprocessingNode > postNode = new WGEPostprocessingNode(
387  WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getCamera()
388  );
389  postNode->addUpdateCallback( new WGENodeMaskCallback( m_active ) ); // disable the postNode with m_active
390  // provide the properties of the post-processor to the user
391  m_properties->addProperty( postNode->getProperties() );
392  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( postNode );
393 
394  // create all these geodes we need
395  m_output = osg::ref_ptr< WGEManagedGroupNode > ( new WGEManagedGroupNode( m_active ) );
396  osg::ref_ptr< osg::StateSet > sset = m_output->getOrCreateStateSet();
397  sset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
398 
399 
400  // add shader and postproc
401  m_shader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMSuperquadricGlyphs", m_localPath ) );
402  m_shader->apply( m_output );
403  postNode->insert( m_output, m_shader );
404 
405  // set uniform callbacks and uniforms
406  osg::ref_ptr< osg::Uniform > evThreshold = new WGEPropertyUniform< WPropDouble >( "u_evThreshold", m_evThreshold );
407  osg::ref_ptr< osg::Uniform > faThreshold = new WGEPropertyUniform< WPropDouble >( "u_faThreshold", m_faThreshold );
408  osg::ref_ptr< osg::Uniform > scaling = new WGEPropertyUniform< WPropDouble >( "u_scaling", m_scaling );
409  osg::ref_ptr< osg::Uniform > gamma = new WGEPropertyUniform< WPropDouble >( "u_gamma", m_gamma );
410 
411  sset->addUniform( evThreshold );
412  sset->addUniform( faThreshold );
413  sset->addUniform( scaling );
414  sset->addUniform( gamma );
415 
416  m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
417  new WGEShaderPropertyDefineOptions< WPropBool >( m_directionalColoring, "DIRECTIONALCOLORING_DISABLED", "DIRECTIONALCOLORING_ENABLED" ) )
418  );
419 
420  bool initialTensorUpload = true;
421 
422  // loop until the module container requests the module to quit
423  while( !m_shutdownFlag() )
424  {
426 
427  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
428  // After waking up, the module has to check whether the shutdownFlag fired. If yes, simply quit the module.
429 
430  // woke up since the module is requested to finish
431  if( m_shutdownFlag() )
432  {
433  break;
434  }
435 
436  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
437  // Collect changes
438 
439  // has the data changes? And even more important: is it valid?
440  std::shared_ptr< WDataSetDTI > newDataSet = m_input->getData();
441  bool dataChanged = ( m_dataSet != newDataSet );
442  bool dataValid = ( newDataSet != NULL );
443 
444  // if data is invalid, remove rendering
445  if( !dataValid )
446  {
447  debugLog() << "Resetting.";
448  m_output->clear();
449  m_dataSet.reset();
450  continue;
451  }
452 
453  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
454  // Handle changes
455 
456  if( dataChanged && dataValid )
457  {
458  // The data is different. Copy it to our internal data variable:
459  debugLog() << "Received Data.";
460  initialTensorUpload = true;
461 
462  // also provide progress information
463  std::shared_ptr< WProgress > progress1( new WProgress( "Building Glyph Geometry" ) );
464  m_progress->addSubProgress( progress1 );
465 
466  // get pointers for the new data
467  m_dataSet = newDataSet;
468  m_dataSetGrid = std::dynamic_pointer_cast< WGridRegular3D >( m_dataSet->getGrid() );
469  WAssert( m_dataSetGrid, "Dataset does not have a regular 3D grid." );
470  m_maxX = m_dataSetGrid->getNbCoordsX();
471  m_maxY = m_dataSetGrid->getNbCoordsY();
472  m_maxZ = m_dataSetGrid->getNbCoordsZ();
473  m_dataSetValueSet = m_dataSet->getValueSet();
477 
478  // update properties
479  m_xPos->setMax( m_maxX );
480  m_xPos->set( m_maxX / 2 );
481  m_yPos->setMax( m_maxY );
482  m_yPos->set( m_maxY / 2 );
483  m_zPos->setMax( m_maxZ );
484  m_zPos->set( m_maxZ / 2 );
485 
486  m_output->setMatrix( static_cast< WMatrix4d >( m_dataSetGrid->getTransform() ) );
487 
488  // new data -> update OSG Stuff
489  initOSG();
490  progress1->finish();
491  }
492 
493  if( dataValid && ( m_xPos->changed() || initialTensorUpload ) )
494  {
495  // also provide progress information
496  std::shared_ptr< WProgress > progress1( new WProgress( "Building Glyph Geometry" ) );
497  m_progress->addSubProgress( progress1 );
498 
499  // grab some mem
500  osg::ref_ptr< osg::Vec3Array > diag = new osg::Vec3Array;
501  diag->reserve( m_nbGlyphsX * 6 * 4 );
502  osg::ref_ptr< osg::Vec3Array > offdiag = new osg::Vec3Array;
503  offdiag->reserve( m_nbGlyphsX * 6 * 4 );
504 
505  // this updates the diag/offdiag texture coordinate arrays of the xSlice
506  // x = const -> handle xPos property
507  size_t fixedX = m_xPos->get( true );
508  for( size_t z = 0; z < m_maxZ; ++z )
509  {
510  // Calculate the current position along the z direction
511  size_t zPre = fixedX + z * m_maxX * m_maxY;
512 
513  for( size_t y = 0; y < m_maxY; ++y )
514  {
515  // add glyph
516  addTensor( zPre + y * m_maxX, diag, offdiag );
517  }
518  }
519 
520  m_xSliceGlyphCallback->setNewTensorData( diag, offdiag );
521  progress1->finish();
522  }
523 
524  if( dataValid && ( m_yPos->changed() || initialTensorUpload ) )
525  {
526  // also provide progress information
527  std::shared_ptr< WProgress > progress1( new WProgress( "Building Glyph Geometry" ) );
528  m_progress->addSubProgress( progress1 );
529 
530  // grab some mem
531  osg::ref_ptr< osg::Vec3Array > diag = new osg::Vec3Array;
532  diag->reserve( m_nbGlyphsX * 6 * 4 );
533  osg::ref_ptr< osg::Vec3Array > offdiag = new osg::Vec3Array;
534  offdiag->reserve( m_nbGlyphsX * 6 * 4 );
535 
536  // y = const -> handle yPos property
537  size_t fixedY = m_yPos->get( true );
538  size_t fixedYOffset = fixedY * m_maxX;
539  for( size_t z = 0; z < m_maxZ; ++z )
540  {
541  // Calculate current offset for value index
542  size_t zPre = fixedYOffset + ( z * m_maxX * m_maxY );
543 
544  for( size_t x = 0; x < m_maxX; ++x )
545  {
546  // add glyph
547  addTensor( zPre + x, diag, offdiag );
548  }
549  }
550 
551  m_ySliceGlyphCallback->setNewTensorData( diag, offdiag );
552  progress1->finish();
553  }
554 
555  if( dataValid && ( m_zPos->changed() || initialTensorUpload ) )
556  {
557  // also provide progress information
558  std::shared_ptr< WProgress > progress1( new WProgress( "Building Glyph Geometry" ) );
559  m_progress->addSubProgress( progress1 );
560 
561  // grab some mem
562  osg::ref_ptr< osg::Vec3Array > diag = new osg::Vec3Array;
563  diag->reserve( m_nbGlyphsX * 6 * 4 );
564  osg::ref_ptr< osg::Vec3Array > offdiag = new osg::Vec3Array;
565  offdiag->reserve( m_nbGlyphsX * 6 * 4 );
566 
567  // z = const -> handle zPos property
568  size_t fixedZ = static_cast< size_t >( m_zPos->get( true ) );
569  size_t fixedZOffset = fixedZ * m_maxX * m_maxY;
570  for( size_t y = 0; y < m_maxY; ++y )
571  {
572  // Calculate current offset for value index
573  size_t yPre = fixedZOffset + ( y * m_maxX );
574 
575  for( size_t x = 0; x < m_maxX; ++x )
576  {
577  // add glyph
578  addTensor( yPre + x, diag, offdiag );
579  }
580  }
581 
582  m_zSliceGlyphCallback->setNewTensorData( diag, offdiag );
583  progress1->finish();
584  }
585 
586  initialTensorUpload = false;
587  }
588 
589  // At this point, the container managing this module signalled to shutdown. The main loop has ended and you should clean up. Always remove
590  // allocated memory and remove all OSG nodes.
591  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( postNode );
592 }
593 
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
This class is an OSG Callback which allows simple linear translation of a matrix transform node along...
This class adds some convenience methods to WGEGroupNode.
This callback is useful to en-/disable nodes using the node mask based on properties.
This class enables you to add arbitrary nodes that get post-processed in screen space.
Class implementing a uniform which can be controlled by a property instance.
std::shared_ptr< WGEShaderPreprocessor > SPtr
Shared pointer for this class.
This is a WGEShaderDefineOptions class which additionally uses a property to automatically control th...
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
Definition: WGEShader.h:48
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
Definition: WKernel.cpp:122
Node callback to handle updates in the glyph tensor data.
virtual void update(osg::NodeVisitor *nv, osg::Drawable *d)
This operator gets called by OSG every update cycle.
osg::Geometry * m_geometry
The geometry node to handle here.
osg::ref_ptr< osg::Vec3Array > m_tensorOffDiag
Off-diagonal tensor elements in texture coordinate array.
osg::ref_ptr< osg::Vec3Array > m_tensorDiag
Diagonal tensor elements in texture coordinate array.
void setNewTensorData(osg::ref_ptr< osg::Vec3Array > diag, osg::ref_ptr< osg::Vec3Array > offdiag)
Updates the tensor data in the glyph slice.
Rendering of GPU bases Superquadric Glyphs.
virtual void properties()
Initialize the properties for this module.
size_t m_nbGlyphsZ
Number of glyphs on Z Plane.
osg::ref_ptr< WGEManagedGroupNode > m_output
The Geode containing all the glyphs.
WMSuperquadricGlyphs()
Constructor.
size_t m_maxY
Number of cells in Y direction.
osg::ref_ptr< WGEManagedGroupNode > m_xSlice
The transformation node moving the X slice through the dataset space if the sliders are used.
osg::ref_ptr< GlyphGeometryNodeCallback > m_zSliceGlyphCallback
The update callback of m_zSlice glphs.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
WPropInt m_zPos
z position of the slice
std::shared_ptr< WModuleInputData< WDataSetDTI > > m_input
The input dataset.
size_t m_maxX
Number of cells in X direction.
WPropDouble m_evThreshold
The eigenvalue threshold to filter glyphs.
WPropDouble m_faThreshold
The FA threshold to filter glyphs.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
osg::ref_ptr< GlyphGeometryNodeCallback > m_ySliceGlyphCallback
The update callback of m_ySlice glphs.
WPropDouble m_gamma
Sharpness of the glyphs.
virtual ~WMSuperquadricGlyphs()
Destructor.
WPropInt m_yPos
y position of the slice
WPropDouble m_scaling
Scaling of the glyphs.
void addTensor(size_t idx, osg::Vec3Array *diag, osg::Vec3Array *offdiag)
Adds a tensor to two arrays.
osg::ref_ptr< GlyphGeometryNodeCallback > m_xSliceGlyphCallback
The update callback of m_xSlice glphs.
WPropInt m_xPos
x position of the slice
virtual const std::string getDescription() const
Gives back a description of this module.
WPropBool m_showonY
indicates whether the vector should be shown on slice Y
WPropBool m_showonZ
indicates whether the vector should be shown on slice Z
size_t m_nbGlyphsX
Number of glyphs on X Plane.
std::shared_ptr< WGridRegular3D > m_dataSetGrid
The current tensor dataset's grid.
void initOSG()
Initializes the needed geodes, transformations and vertex arrays.
std::shared_ptr< WValueSetBase > m_dataSetValueSet
The current tensor dataset's valueset.
osg::ref_ptr< WGEShader > m_shader
the shader actually doing the glyph raytracing
WPropBool m_showonX
indicates whether the vector should be shown on slice X
osg::ref_ptr< WGEManagedGroupNode > m_zSlice
The transformation node moving the Z slice through the dataset space if the sliders are used.
osg::ref_ptr< WGEManagedGroupNode > m_ySlice
The transformation node moving the Y slice through the dataset space if the sliders are used.
std::shared_ptr< const WDataSetDTI > m_dataSet
The current tensor dataset.
virtual void connectors()
Initialize the connectors this module is using.
size_t m_maxZ
Number of cells in Z direction.
virtual const std::string getName() const
Gives back the name of this module.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual void moduleMain()
Entry point after loading the module.
size_t m_nbGlyphsY
Number of glyphs on Y Plane.
WPropBool m_directionalColoring
Color glyphs by direction?
void addGlyph(osg::Vec3 position, osg::ref_ptr< osg::Vec3Array > vertices, osg::ref_ptr< osg::Vec3Array > orientation)
Adds a cube to the vertex array.
Class offering an instantiate-able data connection between modules.
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
boost::filesystem::path m_localPath
The path where the module binary resides in.
Definition: WModule.h:734
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
void removeConnectors()
Removes all connectors properly.
Definition: WModule.cpp:194
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
Definition: WModule.cpp:108
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
WPropBool m_active
True whenever the module should be active.
Definition: WModule.h:723
std::shared_ptr< WProgressCombiner > m_progress
Progress indicator used as parent for all progress' of this module.
Definition: WModule.h:652
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
Class managing progress inside of modules.
Definition: WProgress.h:42
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.