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