OpenWalnut  1.4.0
WGEColormapping.h
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 #ifndef WGECOLORMAPPING_H
26 #define WGECOLORMAPPING_H
27 
28 #include <map>
29 #include <string>
30 #include <algorithm>
31 #include <functional>
32 #include <vector>
33 
34 #include <boost/signals2/signal.hpp>
35 #include <boost/function.hpp>
36 
37 #include <osg/Node>
38 
39 #include "../common/WBoundingBox.h"
40 #include "../common/WSharedSequenceContainer.h"
41 #include "../common/WSharedAssociativeContainer.h"
42 
43 #include "callbacks/WGEFunctorCallback.h"
44 
45 #include "WGETexture.h"
46 #include "shaders/WGEShader.h"
47 
48 
49 /**
50  * Class implements a manager for multiple 3D textures. They can be applied to arbitrary osg::Node. This allows very comfortable use of dataset
51  * based colormapping. The only requirement is that your geometry/node needs to specify texture coordinates in Object Space. That means: the
52  * texture coordinates equal the regular 3D grid of the texture.
53  */
54 class WGEColormapping // NOLINT
55 {
56 public:
57  /**
58  * The alias for a shared container.
59  */
61 
62  /**
63  * Iterator to access the texture list.
64  */
66 
67  /**
68  * Const iterator to access the texture list.
69  */
71 
72  /**
73  * The type of handler used for being notified about added textures.
74  */
75  typedef boost::function< void ( osg::ref_ptr< WGETexture3D > ) > TextureRegisterHandler;
76 
77  /**
78  * The type of handler used for being notified about removed textures.
79  */
81 
82  /**
83  * The type of handler used for being notified about replaced textures.
84  */
85  typedef boost::function< void ( osg::ref_ptr< WGETexture3D >, osg::ref_ptr< WGETexture3D > ) > TextureReplaceHandler;
86 
87  /**
88  * The type of handler called whenever the texture list got resorted.
89  */
90  typedef boost::function< void ( void ) > TextureSortHandler;
91 
92  /**
93  * Destructor.
94  */
95  virtual ~WGEColormapping();
96 
97  /**
98  * Returns instance of the module factory to use to create modules.
99  *
100  * \return the running module factory.
101  */
102  static boost::shared_ptr< WGEColormapping > instance();
103 
104  /**
105  * a bunch of nodes.
106  */
107  typedef std::vector< osg::ref_ptr< osg::Node > > NodeList;
108 
109  /**
110  * Apply the colormapping to the specified node.
111  *
112  * \param node the node.
113  * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
114  * specified, a default shader is used.
115  * \param preTransform Transformation matrix getting applied to your texture coordinates before applying texture matrices. This allows you to
116  * specify any kind of texture coordinates as long as you use this matrix to transform them to the right space.
117  * \param startTexUnit the first texture unit allowed to be used
118  */
119  static void apply( osg::ref_ptr< osg::Node > node, WMatrix4d preTransform = WMatrix4d::identity(),
120  osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
121 
122  /**
123  * Apply the colormapping to a list of nodes using the same shader.
124  *
125  * \param nodes the node-list.
126  * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
127  * specified, a default shader is used.
128  * \param preTransform Transformation matrix getting applied to your texture coordinates before applying texture matrices. This allows you to
129  * specify any kind of texture coordinates as long as you use this matrix to transform them to the right space.
130  * \param startTexUnit the first texture unit allowed to be used
131  */
132  static void apply( NodeList nodes, WMatrix4d preTransform = WMatrix4d::identity(),
133  osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
134 
135  /**
136  * Apply the colormapping to the specified node.
137  *
138  * \param node the node.
139  * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
140  * specified, a default shader is used.
141  * \param startTexUnit the first texture unit allowed to be used
142  */
143  static void apply( osg::ref_ptr< osg::Node > node, osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
144 
145  /**
146  * Apply the colormapping to a list of nodes which all use the same shader.
147  *
148  * \param nodes the node list.
149  * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
150  * specified, a default shader is used.
151  * \param startTexUnit the first texture unit allowed to be used
152  */
153  static void apply( NodeList nodes,
154  osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
155 
156  /**
157  * Register the specified texture to the colormapper. The registered texture is the automatically applied to all users of WGEColormapping.
158  * The texture gets inserted at the beginning of the texture list.
159  *
160  * \param texture the texture to add
161  * \param name the name of the texture to add
162  */
163  static void registerTexture( osg::ref_ptr< WGETexture3D > texture, std::string name = "" );
164 
165  /**
166  * De-register the specified texture to the colormapper. The texture is the automatically removed from all users of WGEColormapping. If the
167  * texture is not in the list, nothing happens.
168  *
169  * \param texture the texture to remove
170  */
171  static void deregisterTexture( osg::ref_ptr< WGETexture3D > texture );
172 
173  /**
174  * Replaces the specified texture with the given new one. If the old texture does not exist, the new one gets inserted at the front of the
175  * list as \ref registerTexture does.
176  *
177  * \param old the texture to remove
178  * \param newTex the new texture to put at the position of the old one
179  * \param name the name of the texture.
180  */
181  static void replaceTexture( osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name = "" );
182 
183  /**
184  * Resorts the texture list using the specified comparator.
185  *
186  * \tparam Comparator the comparator type. Usually a boost::function or class providing the operator().
187  * \param comp the comparator
188  */
189  template < typename Comparator >
190  void sort( Comparator comp );
191 
192  /**
193  * Resorts the texture list using the specified comparator using a stable sorting algorithm.
194  *
195  * \tparam Comparator the comparator type. Usually a boost::function or class providing the operator().
196  * \param comp the comparator
197  */
198  template < typename Comparator >
199  void stableSort( Comparator comp );
200 
201  /**
202  * Sort the texture list by the indices that have been stored in each texture's sortIndex.
203  */
204  void sortByIndex();
205 
206  /**
207  * This function sets the index of a texture in the list to this texture's WGETexture::sortIndex(). This can be used later using
208  * sortByIndex().
209  */
210  void setSortIndices();
211 
212  /**
213  * Reset all sort indices. This can be useful when loading new project files with new sort indices.
214  */
215  void resetSortIndices();
216 
217  /**
218  * Move the specified texture up in the list, directly to the top. Causes the sort signal to fire.
219  *
220  * \param texture the texture swapped with its ascendant
221  * \return true if swap was successful. False if not (texture not found, texture already at beginning).
222  */
223  bool moveToTop( osg::ref_ptr< WGETexture3D > texture );
224 
225  /**
226  * Move the specified texture down in the list, directly to the bottom. Causes the sort signal to fire.
227  *
228  * \param texture the texture swapped with its descendant
229  * \return true if swap was successful. False if not (texture not found, texture already at end).
230  */
231  bool moveToBottom( osg::ref_ptr< WGETexture3D > texture );
232 
233  /**
234  * Move the specified texture one item up in the list. Causes the sort signal to fire.
235  *
236  * \param texture the texture swapped with its ascendant
237  * \return true if swap was successful. False if not (texture not found, texture already at beginning).
238  */
239  bool moveUp( osg::ref_ptr< WGETexture3D > texture );
240 
241  /**
242  * Move the specified texture one item down in the list. Causes the sort signal to fire.
243  *
244  * \param texture the texture swapped with its descendant
245  *
246  * \return true if swap was successful. False if not (texture not found, texture already at end).
247  */
248  bool moveDown( osg::ref_ptr< WGETexture3D > texture );
249 
250  /**
251  * Move the texture to the specified index. If the texture is not in the list, nothing happens.
252  *
253  * \param texture the texture to move
254  * \param idx the target index
255  *
256  * \return true if the operation was successful.
257  */
258  bool moveTo( osg::ref_ptr< WGETexture3D > texture, size_t idx );
259 
260  /**
261  * Counts the number of textures in the colormapper.
262  *
263  * \return the number of textures.
264  */
265  size_t size() const;
266 
267  /**
268  * Possible signals that can be subscribed for being notified about texture list changes.
269  */
270  typedef enum
271  {
272  Registered = 0, //!< texture got added
273  Deregistered, //!< texture got removed
274  Replaced, //!< texture got replaced
275  Sorted //!< texture list was resorted
276  }
278 
279  /**
280  * Subscribe to the specified signal. See \ref TextureListSignal for details about their meaning.
281  *
282  * \param signal the signal to subscribe
283  * \param notifier the notifier
284  *
285  * \return the connection. Keep this and disconnect it properly!
286  */
287  boost::signals2::connection subscribeSignal( TextureListSignal signal, TextureRegisterHandler notifier );
288 
289  /**
290  * Subscribe to the specified signal. See \ref TextureListSignal for details about their meaning.
291  *
292  * \param signal the signal to subscribe
293  * \param notifier the notifier
294  *
295  * \return the connection. Keep this and disconnect it properly!
296  */
297  boost::signals2::connection subscribeSignal( TextureListSignal signal, TextureReplaceHandler notifier );
298 
299  /**
300  * Subscribe to the specified signal. See \ref TextureListSignal for details about their meaning.
301  *
302  * \param signal the signal to subscribe
303  * \param notifier the notifier
304  *
305  * \return the connection. Keep this and disconnect it properly!
306  */
307  boost::signals2::connection subscribeSignal( TextureListSignal signal, TextureSortHandler notifier );
308 
309  /**
310  * Returns a read ticket to the texture array. Useful to iterate the textures.
311  *
312  * \return the read ticket
313  */
315 
316  /**
317  * This returns the bounding box of all the data textures. This is very useful if you implement an universal color-mapped exploration tool.
318  * It returns a copy of the current bounding box. Please note that this can change any moment.
319  *
320  * \return the bounding box.
321  */
323 
324  /**
325  * Returns the condition firing if the texture list changes (sort, replace, add or remove). If you are interested in a certain event only,
326  * use \ref subscribeSignal.
327  *
328  * \return the change condition
329  */
331 
332 protected:
333  /**
334  * Default constructor.
335  */
336  WGEColormapping();
337 
338  /**
339  * Apply the colormapping to the specified nodes.
340  *
341  * \param nodes the nodes.
342  * \param preTransform Transformation matrix getting applied to your texture coordinates before applying texture matrices. This allows you to
343  * specify any kind of texture coordinates as long as you use this matrix to transform them to the right space.
344  * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
345  * specified, a default shader is used.
346  * \param startTexUnit the first texture unit allowed to be used
347  */
348  void applyInst( NodeList nodes, WMatrix4d preTransform = WMatrix4d::identity(),
349  osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
350 
351  /**
352  * Register the specified texture to the colormapper. The registered texture is the automatically applied to all users of WGEColormapping.
353  *
354  * \param texture the texture to add
355  * \param name the name of the texture.
356  */
357  void registerTextureInst( osg::ref_ptr< WGETexture3D > texture, std::string name );
358 
359  /**
360  * De-register the specified texture to the colormapper. The texture is the automatically removed from all users of WGEColormapping.
361  *
362  * \param texture the texture to remove
363  */
364  void deregisterTextureInst( osg::ref_ptr< WGETexture3D > texture );
365 
366  /**
367  * Replaces the specified texture with the given new one. If the old texture does not exist, the new one gets inserted at the front of the
368  * list as \ref registerTexture does.
369  *
370  * \param old the texture to remove
371  * \param newTex the new texture to put at the position of the old one
372  * \param name the name of the texture.
373  */
374  void replaceTextureInst( osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name = "" );
375 
376  /**
377  * This callback handles all the updates needed. It is called by the callback instance every update cycle for each node using this
378  * WGEColormapping instance.
379  *
380  * \param node
381  */
382  void callback( osg::Node* node );
383 
384  /**
385  * Called whenever the texture list is updated.
386  */
387  void textureUpdate();
388 
389 private:
390  /**
391  * Singleton instance of WGEColormapping
392  */
393  static boost::shared_ptr< WGEColormapping > m_instance;
394 
395  /**
396  * The textures managed by this instance.
397  */
399 
400  /**
401  * Simple structure to store some additional node-related info like texture units and so on.
402  */
403  struct NodeInfo
404  {
405  bool m_rebind; //!< true if the node has not been callback'ed before
406  size_t m_texUnitStart; //!< the start index of the texture unit to use
407  WMatrix4d m_preTransform; //!< matrix used for transforming arbitrary texture coordinates to the proper space.
408  };
409 
410  /**
411  * The alias for a shared container with a set of node-nodeInfo pairs
412  */
414 
415  /**
416  * This map is needed to keep track of several node specific settings
417  */
419 
420  /**
421  * Called whenever a texture got registered.
422  */
423  boost::signals2::signal< void( osg::ref_ptr< WGETexture3D > ) > m_registerSignal;
424 
425  /**
426  * Called whenever a texture got removed.
427  */
428  boost::signals2::signal< void( osg::ref_ptr< WGETexture3D > ) > m_deregisterSignal;
429 
430  /**
431  * Called whenever a texture got replaced.
432  */
433  boost::signals2::signal< void( osg::ref_ptr< WGETexture3D >, osg::ref_ptr< WGETexture3D > ) > m_replaceSignal;
434 
435  /**
436  * Called whenever the texture list got resorted
437  */
438  boost::signals2::signal< void( void ) > m_sortSignal;
439 
440  /**
441  * The bounding box of all the textures.
442  */
444 
445  /**
446  * Updates the bounding box information. This is called for every write-update in m_textures.
447  */
448  void updateBounds();
449 };
450 
451 template < typename Comparator >
452 void WGEColormapping::sort( Comparator comp )
453 {
454  m_textures.sort< Comparator >( comp );
455 }
456 
457 template < typename Comparator >
458 void WGEColormapping::stableSort( Comparator comp )
459 {
460  m_textures.stableSort< Comparator >( comp );
461 }
462 
463 #endif // WGECOLORMAPPING_H
464