OpenWalnut  1.5.0dev
WMPointRenderer.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 <limits>
26 #include <memory>
27 #include <string>
28 
29 #include <osg/Geode>
30 
31 #include "WMPointRenderer.h"
32 #include "core/common/WLimits.h"
33 #include "core/common/math/WMath.h"
34 #include "core/dataHandler/WDataSetPoints.h"
35 #include "core/graphicsEngine/WGEColormapping.h"
36 #include "core/graphicsEngine/WGEGeodeUtils.h"
37 #include "core/graphicsEngine/WGEManagedGroupNode.h"
38 #include "core/graphicsEngine/WGEUtils.h"
39 #include "core/graphicsEngine/postprocessing/WGEPostprocessingNode.h"
40 #include "core/graphicsEngine/shaders/WGEShader.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( WMPointRenderer )
45 
47  WModule()
48 {
49 }
50 
52 {
53  // Cleanup!
54 }
55 
56 std::shared_ptr< WModule > WMPointRenderer::factory() const
57 {
58  // See "src/modules/template/" for an extensively documented example.
59  return std::shared_ptr< WModule >( new WMPointRenderer() );
60 }
61 
62 const char** WMPointRenderer::getXPMIcon() const
63 {
64  return NULL;
65 }
66 
67 const std::string WMPointRenderer::getName() const
68 {
69  // Specify your module name here. This name must be UNIQUE!
70  return "Point Renderer";
71 }
72 
73 const std::string WMPointRenderer::getDescription() const
74 {
75  return "Render a given point dataset.";
76 }
77 
79 {
80  // this input contains the triangle data
81  m_pointInput = WModuleInputData< WDataSetPoints >::createAndAdd( shared_from_this(), "points", "The data to display" );
82 
83  // call WModule's initialization
85 }
86 
88 {
89  // Info properties
90  m_nbVertices = m_infoProperties->addProperty( "Points", "The number of points in the visualized data set.", 0 );
91  m_nbVertices->setMax( std::numeric_limits< int >::max() );
92 
93  // some properties need to trigger an update
94  m_propCondition = std::shared_ptr< WCondition >( new WCondition() );
95 
96  // setup all the properties. See header file for their meaning and purpose.
97  m_size = m_properties->addProperty( "Point size", "The size of the points.", 1.0 );
98  m_size->setMin( 0.0001 );
99  m_size->setMax( 10.0 );
100 
101  m_useCorrectDepth = m_properties->addProperty( "Correct Depth", "If set, the depths of the sprites are calculated correctly. You can disable "
102  "this to get higher framerates at the cost of visual correctness.", true );
103 
104  m_useAttribute = m_properties->addProperty( "Use Attribute", "Decides whether attribute or uniform is used", false, true );
105 
106  // call WModule's initialization
108 }
109 
111 {
112  // let the main loop awake if the data changes.
113  m_moduleState.setResetable( true, true );
114  m_moduleState.add( m_pointInput->getDataChangedCondition() );
116 
117  ////////////////////////////////////////////////////////////////////////////////////////////////////
118  // setup the main graphics-node:
119  ////////////////////////////////////////////////////////////////////////////////////////////////////
120 
121  // create the post-processing node which actually does the nice stuff to the rendered image
122  osg::ref_ptr< WGEPostprocessingNode > postNode = new WGEPostprocessingNode(
123  WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getCamera()
124  );
125  postNode->addUpdateCallback( new WGENodeMaskCallback( m_active ) ); // disable the postNode with m_active
126  // provide the properties of the post-processor to the user
127  m_properties->addProperty( postNode->getProperties() );
128  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( postNode );
129 
130  // load the GLSL shader:
131  m_shader = new WGEShader( "WMPointRenderer", m_localPath );
132  // set geometry shader options
133  m_shader->setParameter( GL_GEOMETRY_VERTICES_OUT_EXT, 4 );
134  m_shader->setParameter( GL_GEOMETRY_INPUT_TYPE_EXT, GL_POINTS );
135  m_shader->setParameter( GL_GEOMETRY_OUTPUT_TYPE_EXT, GL_TRIANGLE_STRIP );
136 
137  // insert some uniforms and defines
138  postNode->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropDouble >( "u_pointSize", m_size ) );
139  m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
140  new WGEShaderPropertyDefineOptions< WPropBool >( m_useCorrectDepth, "DEPTHWRITE_DISABLED", "DEPTHWRITE_ENABLED" ) )
141  );
142  m_shader->addPreprocessor( WGEShaderPreprocessor::SPtr(
143  new WGEShaderPropertyDefineOptions< WPropBool >( m_useAttribute, "USE_ATTRIBUTE_DISABLED", "USE_ATTRIBUTE_ENABLED" ) )
144  );
145 
146  // register attribute
147  m_shader->addBindAttribLocation( "a_pointSize", 6 );
148 
149  // signal ready state. The module is now ready to be used.
150  ready();
151 
152  // loop until the module container requests the module to quit
153  while( !m_shutdownFlag() )
154  {
155  // Now, the moduleState variable comes into play. The module can wait for the condition, which gets fired whenever the input receives data
156  // or an property changes. The main loop now waits until something happens.
157  debugLog() << "Waiting ...";
159 
160  // woke up since the module is requested to finish
161  if( m_shutdownFlag() )
162  {
163  break;
164  }
165 
166  // Get data and check for invalid data.
167  WDataSetPoints::SPtr points = m_pointInput->getData();
168  if( !points )
169  {
170  debugLog() << "Invalid Data. Disabling.";
171  postNode->clear();
172  continue;
173  }
174 
175  m_nbVertices->set( points->size() );
176 
177  std::shared_ptr< WValueSet< float > > valueSet;
178  if( points->getData().type() == typeid( std::shared_ptr< WValueSet< float > > ) )
179  {
180  valueSet = std::any_cast< std::shared_ptr< WValueSet< float > > >( points->getData() );
181  }
182 
183  m_useAttribute->set( valueSet ? true : false );
184 
185  // we have valid data. Put this into a geode
186  osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry );
187  osg::ref_ptr< osg::Geode > geode( new osg::Geode() );
188 
189  osg::StateSet* state = geode->getOrCreateStateSet();
190  state->setMode( GL_BLEND, osg::StateAttribute::ON );
191 
192  // convert point arrays to osg vec3 arrays
193  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
194  osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
195  osg::ref_ptr< osg::FloatArray > sizes = osg::ref_ptr< osg::FloatArray >( new osg::FloatArray );
196 
197  WDataSetPoints::VertexArray pointVertices = points->getVertices();
198  WDataSetPoints::ColorArray pointColors = points->getColors();
199  for( size_t pointIdx = 0; pointIdx < points->size(); ++pointIdx )
200  {
201  osg::Vec3 vert = points->operator[]( pointIdx );
202  osg::Vec4 color = points->getColor( pointIdx );
203 
204  vertices->push_back( vert );
205  colors->push_back( color );
206 
207  if( valueSet )
208  {
209  sizes->push_back( valueSet->getScalar( pointIdx ) );
210  }
211  }
212 
213  // combine to geometry
214  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::POINTS, 0, vertices->size() ) );
215  geometry->setVertexArray( vertices );
216  geometry->setColorArray( colors );
217  geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
218  if( valueSet )
219  {
220  geometry->setVertexAttribArray( 6, sizes, osg::Array::BIND_PER_VERTEX );
221  }
222 
223  // add geometry to geode
224  geode->addDrawable( geometry );
225 
226  wge::enableTransparency( geode );
227 
228  // shader and colormapping
229  m_shader->apply( geode );
230 
231  // add geode to group
232  postNode->clear();
233  postNode->insert( geode, m_shader );
234 
235  debugLog() << "Bounding Box: " << points->getBoundingBox();
236  }
237 
238  // it is important to always remove the modules again
239  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( postNode );
240 }
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
std::shared_ptr< WDataSetPoints > SPtr
Pointer to dataset.
std::shared_ptr< std::vector< float > > ColorArray
Colors for each vertex in VertexArray.
std::shared_ptr< std::vector< float > > VertexArray
List of vertex coordinates in term of components of vertices.
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
This module renders the points in a point dataset.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
virtual const std::string getName() const
Gives back the name of this module.
WPropInt m_nbVertices
Info-property showing the number of vertices in the data set.
WPropBool m_useCorrectDepth
Slower but correct depth calculation.
virtual void connectors()
Initialize the connectors this module is using.
virtual const std::string getDescription() const
Gives back a description of this module.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
virtual void moduleMain()
Entry point after loading the module.
WMPointRenderer()
Constructor.
std::shared_ptr< WModuleInputData< WDataSetPoints > > m_pointInput
An input connector used to get points from other modules.
osg::ref_ptr< WGEShader > m_shader
The shader for the points.
WPropBool m_useAttribute
Invisible bool property that decides whether attribute or uniform is used.
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...
WPropDouble m_size
The size of a point on screen.
virtual void properties()
Initialize the properties for this module.
virtual ~WMPointRenderer()
Destructor.
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this in data connector with proper type and add it to ...
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
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
std::shared_ptr< WProperties > m_infoProperties
The property object for the module containing only module whose purpose is "PV_PURPOSE_INFORMNATION".
Definition: WModule.h:647
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
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Base Class for all value set types.
Definition: WValueSet.h:47
void enableTransparency(osg::ref_ptr< osg::Node > node)
Enable transparency for the given node.
Definition: WGEUtils.cpp:215