OpenWalnut  1.3.1
WGETexture.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 WGETEXTURE_H
26 #define WGETEXTURE_H
27 
28 #include <string>
29 
30 #include <boost/shared_ptr.hpp>
31 
32 #include <osg/Node>
33 #include <osg/StateSet>
34 #include <osg/Texture>
35 #include <osg/Texture1D>
36 #include <osg/Texture2D>
37 #include <osg/Texture3D>
38 
39 #include "callbacks/WGEFunctorCallback.h"
40 #include "../common/WBoundingBox.h"
41 #include "../common/WProperties.h"
42 #include "../common/WPropertyHelper.h"
43 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
44 
45 #include "WGETextureUtils.h"
46 
47 /**
48  * This calls serves a simple purpose: have a texture and its scaling information together which allows very easy binding of textures to nodes
49  * with associated shaders. When this texture gets bind using the bindTo methods, uniforms get added containing needed scaling information.
50  */
51 template < typename TextureType = osg::Texture >
52 class WGETexture: public TextureType
53 {
54 public:
55  //! We support only 8 textures because some known hardware does not support more texture coordinates.
56  static std::size_t const MAX_NUMBER_OF_TEXTURES = 8;
57 
58  //! The maximum texture dimension.
59  static std::size_t const MAX_TEXTURE_DIMENSION = 2048;
60 
61  /**
62  * Default constructor. Creates an empty instance of the texture.
63  *
64  * \param scale the scaling factor needed for de-scaling the texture values
65  * \param min the minimum value allowing negative values too.
66  */
67  WGETexture( double scale = 1.0, double min = 0.0 );
68 
69  /**
70  * Creates texture from given image. Scaling is set to identity.
71  *
72  * \param image the image to use as texture
73  * \param scale the scaling factor needed for de-scaling the texture values
74  * \param min the minimum value allowing negative values too.
75  */
76  WGETexture( osg::Image* image, double scale = 1.0, double min = 0.0 );
77 
78  /**
79  * Copy the texture.
80  *
81  * \param texture the texture to copy
82  * \param copyop
83  */
84  WGETexture( const WGETexture< TextureType >& texture, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY );
85 
86  /**
87  * Destructor.
88  */
89  virtual ~WGETexture();
90 
91  /**
92  * Returns the name property of the texture. You should set it if you create a texture.
93  *
94  * \return texture name property
95  */
96  WPropString name() const;
97 
98  /**
99  * Get the minimum in the de-scaled value space. The property can be changed. A change affects all colormaps using this texture. But be
100  * careful as the texture creating depends on these values.
101  *
102  * \return the minimum
103  */
104  WPropDouble minimum() const;
105 
106  /**
107  * Get the scaling factor for de-scaling the texture. The property can be changed. A change affects all colormaps using this texture. But be
108  * careful as the texture creating depends on these values.
109  *
110  * \return the scale
111  */
112  WPropDouble scale() const;
113 
114  /**
115  * Returns the alpha property. The property can be changed. A change affects all colormaps using this texture.
116  *
117  * \return alpha property
118  */
119  WPropDouble alpha() const;
120 
121  /**
122  * Returns the threshold property. The property can be changed. A change affects all colormaps using this texture.
123  *
124  * \return threshold property
125  */
126  WPropDouble threshold() const;
127 
128  /**
129  * Returns the property responsible for enabling threshold based clipping. If this is false, the threshold is ignored.
130  *
131  * \return threshold-enable property.
132  */
133  WPropBool thresholdEnabled() const;
134 
135  /**
136  * Returns the interpolation property. The property can be changed. A change affects all colormaps using this texture.
137  *
138  * \return interpolation property
139  */
140  WPropBool interpolation() const;
141 
142  /**
143  * Returns the colormap property. The property can be changed. A change affects all colormaps using this texture.
144  *
145  * \return colormap property
146  */
147  WPropSelection colormap() const;
148 
149  /**
150  * Returns the active property. The property can be changed. A change affects all colormaps using this texture.
151  *
152  * \return active property
153  */
154  WPropBool active() const;
155 
156  /**
157  * Returns the texture transformation matrix. The property can be changed. A change affects all colormaps using this texture. This matrix
158  * converts an world-space coordinate to an texture coordinate! This can be seen as a scaled inverse matrix of the grid's transformation.
159  *
160  * \return the matrix
161  */
162  WPropMatrix4X4 transformation() const;
163 
164  /**
165  * Binds the texture to the specified node and texture unit. It also adds two uniforms: u_textureXMin and u_textureXScale, where X
166  * is the unit number. This can be used in shaders to unscale it.
167  *
168  * \param node the node where to bind the texture to
169  * \param unit the unit, by default 0
170  */
171  void bind( osg::ref_ptr< osg::Node > node, size_t unit = 0 );
172 
173  /**
174  * Return a pointer to the properties object of the dataset. Add all the modifiable settings here. This allows the user to modify several
175  * properties of a dataset.
176  *
177  * \return the properties.
178  */
179  boost::shared_ptr< WProperties > getProperties() const;
180 
181  /**
182  * Return a pointer to the information properties object of the dataset. The dataset intends these properties to not be modified.
183  *
184  * \return the properties.
185  */
186  boost::shared_ptr< WProperties > getInformationProperties() const;
187 
188  /**
189  * Applies some custom uniforms to the specified state-set which directly relate to this texture
190  *
191  * \param prefix the prefix used for the uniforms
192  * \param states the state where to add the uniforms
193  */
194  virtual void applyUniforms( std::string prefix, osg::StateSet* states ) const;
195 
196  /**
197  * For all the lazy guys to set the filter MIN and MAG at once.
198  *
199  * \param mode the new mode for MIN_FILTER and MAG_FILTER.
200  */
201  void setFilterMinMag( osg::Texture::FilterMode mode );
202 
203  /**
204  * For all the lazy guys to set the wrapping for s,t and r directions at once.
205  *
206  * \param mode the new mode for WRAP_S, WRAP_T and WRAP_R.
207  */
208  void setWrapSTR( osg::Texture::WrapMode mode );
209 
210  /**
211  * Returns the texture's bounding box. This is const. Although there exists the transformation() property, it is an information property and
212  * can't be changed.
213  *
214  * \return the bounding box.
215  */
216  virtual WBoundingBox getBoundingBox() const;
217 
218 protected:
219  /**
220  * Handles all property updates. Called by m_propCondition.
221  */
222  virtual void handleUpdate();
223 
224  /**
225  * Creates the texture data. Overwrite this method if you want to provide a custom texture creation procedure.
226  */
227  virtual void create();
228 
229  /**
230  * This method implements an update callback which updates the texture image if needed and several other properties like texture matrix.
231  *
232  * \param state the state to update
233  */
234  virtual void updateCallback( osg::StateAttribute* state );
235 
236  /**
237  * Initialize the size of the texture properly according to real texture type (1D,2D,3D).
238  * \note This is needed because osg::Texture::setImage is not virtual and does not set the size from the image.
239  *
240  * \param texture the texture where to set the size
241  * \param width the new width
242  * \param height the new height
243  * \param depth the new depth
244  */
245  static void initTextureSize( osg::Texture1D* texture, int width, int height, int depth );
246 
247  /**
248  * Initialize the size of the texture properly according to real texture type (1D,2D,3D).
249  * \note This is needed because osg::Texture::setImage is not virtual and does not set the size from the image.
250  *
251  * \param texture the texture where to set the size
252  * \param width the new width
253  * \param height the new height
254  * \param depth the new depth
255  */
256  static void initTextureSize( osg::Texture2D* texture, int width, int height, int depth );
257 
258  /**
259  * Initialize the size of the texture properly according to real texture type (1D,2D,3D).
260  * \note This is needed because osg::Texture::setImage is not virtual and does not set the size from the image.
261  *
262  * \param texture the texture where to set the size
263  * \param width the new width
264  * \param height the new height
265  * \param depth the new depth
266  */
267  static void initTextureSize( osg::Texture3D* texture, int width, int height, int depth );
268 
269 private:
270  /**
271  * Creates and assigns all properties.
272  *
273  * \param min the min value of the texture
274  * \param scale the scale value of the texture
275  */
276  void setupProperties( double scale, double min );
277 
278  /**
279  * A condition used to notify about changes in several properties.
280  */
281  boost::shared_ptr< WCondition > m_propCondition;
282 
283  /**
284  * The property object for the dataset.
285  */
286  boost::shared_ptr< WProperties > m_properties;
287 
288  /**
289  * The property object for the dataset containing only props whose purpose is "PV_PURPOSE_INFORMNATION". It is useful to define some property
290  * to only be of informational nature. The GUI does not modify them. As it is a WProperties instance, you can use it the same way as
291  * m_properties.
292  */
293  boost::shared_ptr< WProperties > m_infoProperties;
294 
295  /**
296  * If true, the texture gets created. This is used to create texture on demand.
297  */
299 
300  /**
301  * The texture name. This might be useful to identify textures.
302  */
303  WPropString m_name;
304 
305  /**
306  * The minimum of each value in the texture in unscaled space.
307  */
308  WPropDouble m_min;
309 
310  /**
311  * The scaling factor to de-scale a [0-1] texture to original space.
312  */
313  WPropDouble m_scale;
314 
315  /**
316  * A list of color map selection types
317  */
318  boost::shared_ptr< WItemSelection > m_colorMapSelectionsList;
319 
320  /**
321  * Selection property for color map
322  */
323  WPropSelection m_colorMap;
324 
325  /**
326  * Alpha blending value.
327  */
328  WPropDouble m_alpha;
329 
330  /**
331  * Threshold for clipping areas.
332  */
333  WPropDouble m_threshold;
334 
335  /**
336  * Threshold-enable flag.
337  */
339 
340  /**
341  * True if interpolation should be used.
342  */
343  WPropBool m_interpolation;
344 
345  /**
346  * True if the texture is active.
347  */
348  WPropBool m_active;
349 
350  /**
351  * The texture transformation matrix.
352  */
353  WPropMatrix4X4 m_texMatrix;
354 };
355 
356 // Some convenience typedefs
357 
358 /**
359  * OSG's Texture1D with scaling features
360  */
362 
363 /**
364  * OSG's Texture2D with scaling features
365  */
367 
368 /**
369  * OSG's Texture3D with scaling features
370  */
372 
373 
374 template < typename TextureType >
375 WGETexture< TextureType >::WGETexture( double scale, double min ):
376  TextureType(),
377  m_propCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
378  m_properties( boost::shared_ptr< WProperties >( new WProperties( "Texture Properties", "Properties of a texture." ) ) ),
379  m_infoProperties( boost::shared_ptr< WProperties >( new WProperties( "Texture Info Properties", "Texture's information properties." ) ) ),
380  m_needCreate( true )
381 {
382  setupProperties( scale, min );
383 }
384 
385 template < typename TextureType >
386 WGETexture< TextureType >::WGETexture( osg::Image* image, double scale, double min ):
387  TextureType( image ),
388  m_propCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
389  m_properties( boost::shared_ptr< WProperties >( new WProperties( "Texture Properties", "Properties of a texture." ) ) ),
390  m_infoProperties( boost::shared_ptr< WProperties >( new WProperties( "Texture Info Properties", "Texture's information properties." ) ) ),
391  m_needCreate( true )
392 {
393  setupProperties( scale, min );
394  WGETexture< TextureType >::initTextureSize( this, image->s(), image->t(), image->r() );
395 }
396 
397 template < typename TextureType >
398 WGETexture< TextureType >::WGETexture( const WGETexture< TextureType >& texture, const osg::CopyOp& copyop ):
399  TextureType( texture, copyop ),
400  m_min( texture.m_min ),
401  m_scale( texture.m_scale )
402 {
403  // initialize members
404 }
405 
406 template < typename TextureType >
407 void WGETexture< TextureType >::setupProperties( double scale, double min )
408 {
409  m_propCondition->subscribeSignal( boost::bind( &WGETexture< TextureType >::handleUpdate, this ) );
410 
411  m_name = m_properties->addProperty( "Name", "The name of the texture.", std::string( "Unnamed" ) );
412 
413  // initialize members
414  m_min = m_properties->addProperty( "Minimum", "The minimum value in the original space.", min, true );
415  m_min->removeConstraint( m_min->getMin() );
416  m_min->removeConstraint( m_min->getMax() );
417 
418  m_scale = m_properties->addProperty( "Scale", "The scaling factor to un-scale the texture values to the original space.", scale, true );
419  m_scale->removeConstraint( m_scale->getMin() );
420  m_scale->removeConstraint( m_scale->getMax() );
421 
422  m_alpha = m_properties->addProperty( "Alpha", "The alpha blending value.", 1.0 );
423  m_alpha->setMin( 0.0 );
424  m_alpha->setMax( 1.0 );
425 
426  m_thresholdEnabled = m_properties->addProperty( "Enable Threshold",
427  "If enabled, threshold based clipping is used. If not, threshold is ignored.", false );
428 
429  m_threshold = m_properties->addProperty( "Threshold", "The threshold used to clip areas.", 0.0 );
430  m_threshold->setMin( min );
431  m_threshold->setMax( min + scale );
432 
433  m_interpolation = m_properties->addProperty( "Interpolate", "Interpolation of the volume data.", true, m_propCondition );
434 
435  m_colorMapSelectionsList = boost::shared_ptr< WItemSelection >( new WItemSelection() );
436  m_colorMapSelectionsList->addItem( "Grayscale", "" );
437  m_colorMapSelectionsList->addItem( "Rainbow", "" );
438  m_colorMapSelectionsList->addItem( "Hot iron", "" );
439  m_colorMapSelectionsList->addItem( "Negative to positive", "" );
440  m_colorMapSelectionsList->addItem( "Atlas", "" );
441  m_colorMapSelectionsList->addItem( "Blue-Green-Purple", "" );
442  m_colorMapSelectionsList->addItem( "Vector", "" );
443 
444  m_colorMap = m_properties->addProperty( "Colormap", "The colormap of this texture.", m_colorMapSelectionsList->getSelectorFirst() );
446 
447  m_active = m_properties->addProperty( "Active", "Can dis-enable a texture.", true );
448 
450  m_texMatrix = m_properties->addProperty( "Texture Transformation", "Usable to transform the texture.", m );
451  m_texMatrix->setPurpose( PV_PURPOSE_INFORMATION );
452 
453  TextureType::setResizeNonPowerOfTwoHint( false );
454  TextureType::setUpdateCallback( new WGEFunctorCallback< osg::StateAttribute >(
455  boost::bind( &WGETexture< TextureType >::updateCallback, this, _1 ) )
456  );
457 
458  // init filters
459  TextureType::setFilter( osg::Texture::MIN_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
460  TextureType::setFilter( osg::Texture::MAG_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
461 }
462 
463 template < typename TextureType >
465 {
466  // cleanup.
467 }
468 
469 template < typename TextureType >
470 boost::shared_ptr< WProperties > WGETexture< TextureType >::getProperties() const
471 {
472  return m_properties;
473 }
474 
475 template < typename TextureType >
476 boost::shared_ptr< WProperties > WGETexture< TextureType >::getInformationProperties() const
477 {
478  return m_infoProperties;
479 }
480 
481 template < typename TextureType >
482 inline WPropString WGETexture< TextureType >::name() const
483 {
484  return m_name;
485 }
486 
487 template < typename TextureType >
488 inline WPropDouble WGETexture< TextureType >::minimum() const
489 {
490  return m_min;
491 }
492 
493 template < typename TextureType >
494 inline WPropDouble WGETexture< TextureType >::scale() const
495 {
496  return m_scale;
497 }
498 
499 template < typename TextureType >
500 inline WPropDouble WGETexture< TextureType >::alpha() const
501 {
502  return m_alpha;
503 }
504 
505 template < typename TextureType >
506 inline WPropDouble WGETexture< TextureType >::threshold() const
507 {
508  return m_threshold;
509 }
510 
511 template < typename TextureType >
513 {
514  return m_thresholdEnabled;
515 }
516 
517 template < typename TextureType >
519 {
520  return m_interpolation;
521 }
522 
523 template < typename TextureType >
524 inline WPropSelection WGETexture< TextureType >::colormap() const
525 {
526  return m_colorMap;
527 }
528 
529 template < typename TextureType >
530 inline WPropBool WGETexture< TextureType >::active() const
531 {
532  return m_active;
533 }
534 
535 template < typename TextureType >
536 inline WPropMatrix4X4 WGETexture< TextureType >::transformation() const
537 {
538  return m_texMatrix;
539 }
540 
541 template < typename TextureType >
543 {
544  if( m_interpolation->changed() )
545  {
546  TextureType::setFilter( osg::Texture::MIN_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
547  TextureType::setFilter( osg::Texture::MAG_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
548  }
549 }
550 
551 template < typename TextureType >
552 void WGETexture< TextureType >::applyUniforms( std::string prefix, osg::StateSet* states ) const
553 {
554  states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Min", minimum() ) );
555  states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Scale", scale() ) );
556  states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Alpha", alpha() ) );
557  states->addUniform( new WGEPropertyUniform< WPropBool >( prefix + "ThresholdEnabled", thresholdEnabled() ) );
558  states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Threshold", threshold() ) );
559  states->addUniform( new WGEPropertyUniform< WPropSelection >( prefix + "Colormap", colormap() ) );
560  states->addUniform( new WGEPropertyUniform< WPropBool >( prefix + "Active", active() ) );
561 }
562 
563 template < typename TextureType >
564 void WGETexture< TextureType >::bind( osg::ref_ptr< osg::Node > node, size_t unit )
565 {
566  // let our utilities do the work
567  wge::bindTexture( node, osg::ref_ptr< WGETexture< TextureType > >( this ), unit ); // to avoid recursive stuff -> explicitly specify the type
568 }
569 
570 template < typename TextureType >
572 {
573  // do nothing. Derived classes may implement this.
574 }
575 
576 template < typename TextureType >
577 void WGETexture< TextureType >::updateCallback( osg::StateAttribute* /*state*/ )
578 {
579  // create if not done yet
580  if( m_needCreate )
581  {
582  m_needCreate = false;
583  create();
584  TextureType::dirtyTextureObject();
585  }
586 }
587 
588 template < typename TextureType >
589 void WGETexture< TextureType >::setFilterMinMag( osg::Texture::FilterMode mode )
590 {
591  this->setFilter( osg::Texture2D::MIN_FILTER, mode );
592  this->setFilter( osg::Texture2D::MAG_FILTER, mode );
593 }
594 
595 template < typename TextureType >
596 void WGETexture< TextureType >::setWrapSTR( osg::Texture::WrapMode mode )
597 {
598  this->setWrap( osg::Texture2D::WRAP_S, mode );
599  this->setWrap( osg::Texture2D::WRAP_T, mode );
600  this->setWrap( osg::Texture2D::WRAP_R, mode );
601 }
602 
603 template < typename TextureType >
604 void WGETexture< TextureType >::initTextureSize( osg::Texture1D* texture, int width, int /*height*/, int /*depth*/ )
605 {
606  texture->setTextureWidth( width );
607 }
608 
609 template < typename TextureType >
610 void WGETexture< TextureType >::initTextureSize( osg::Texture2D* texture, int width, int height, int /*depth*/ )
611 {
612  texture->setTextureSize( width, height );
613 }
614 
615 template < typename TextureType >
616 void WGETexture< TextureType >::initTextureSize( osg::Texture3D* texture, int width, int height, int depth )
617 {
618  texture->setTextureSize( width, height, depth );
619 }
620 
621 template < typename TextureType >
623 {
624  return WBoundingBox( 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
625 }
626 
627 #endif // WGETEXTURE_H
628