OpenWalnut 1.3.1
WGETexture.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WGETEXTURE_H
00026 #define WGETEXTURE_H
00027 
00028 #include <string>
00029 
00030 #include <boost/shared_ptr.hpp>
00031 
00032 #include <osg/Node>
00033 #include <osg/StateSet>
00034 #include <osg/Texture>
00035 #include <osg/Texture1D>
00036 #include <osg/Texture2D>
00037 #include <osg/Texture3D>
00038 
00039 #include "callbacks/WGEFunctorCallback.h"
00040 #include "../common/WBoundingBox.h"
00041 #include "../common/WProperties.h"
00042 #include "../common/WPropertyHelper.h"
00043 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
00044 
00045 #include "WGETextureUtils.h"
00046 
00047 /**
00048  * This calls serves a simple purpose: have a texture and its scaling information together which allows very easy binding of textures to nodes
00049  * with associated shaders. When this texture gets bind using the bindTo methods, uniforms get added containing needed scaling information.
00050  */
00051 template < typename TextureType = osg::Texture >
00052 class WGETexture: public TextureType
00053 {
00054 public:
00055     //! We support only 8 textures because some known hardware does not support more texture coordinates.
00056     static std::size_t const MAX_NUMBER_OF_TEXTURES = 8;
00057 
00058     //! The maximum texture dimension.
00059     static std::size_t const MAX_TEXTURE_DIMENSION = 2048;
00060 
00061     /**
00062      * Default constructor. Creates an empty instance of the texture.
00063      *
00064      * \param scale the scaling factor needed for de-scaling the texture values
00065      * \param min the minimum value allowing negative values too.
00066      */
00067     WGETexture( double scale = 1.0, double min = 0.0 );
00068 
00069     /**
00070      * Creates texture from given image. Scaling is set to identity.
00071      *
00072      * \param image the image to use as texture
00073      * \param scale the scaling factor needed for de-scaling the texture values
00074      * \param min the minimum value allowing negative values too.
00075      */
00076     WGETexture( osg::Image* image, double scale = 1.0, double min = 0.0 );
00077 
00078     /**
00079      * Copy the texture.
00080      *
00081      * \param texture the texture to copy
00082      * \param copyop
00083      */
00084     WGETexture( const WGETexture< TextureType >& texture, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY );
00085 
00086     /**
00087      * Destructor.
00088      */
00089     virtual ~WGETexture();
00090 
00091     /**
00092      * Returns the name property of the texture. You should set it if you create a texture.
00093      *
00094      * \return texture name property
00095      */
00096     WPropString name() const;
00097 
00098     /**
00099      * Get the minimum in the de-scaled value space. The property can be changed. A change affects all colormaps using this texture. But be
00100      * careful as the texture creating depends on these values.
00101      *
00102      * \return the minimum
00103      */
00104     WPropDouble minimum() const;
00105 
00106     /**
00107      * Get the scaling factor for de-scaling the texture. The property can be changed. A change affects all colormaps using this texture. But be
00108      * careful as the texture creating depends on these values.
00109      *
00110      * \return the scale
00111      */
00112     WPropDouble scale() const;
00113 
00114     /**
00115      * Returns the alpha property. The property can be changed. A change affects all colormaps using this texture.
00116      *
00117      * \return alpha property
00118      */
00119     WPropDouble alpha() const;
00120 
00121     /**
00122      * Returns the threshold property. The property can be changed. A change affects all colormaps using this texture.
00123      *
00124      * \return threshold property
00125      */
00126     WPropDouble threshold() const;
00127 
00128     /**
00129      * Returns the property responsible for enabling threshold based clipping. If this is false, the threshold is ignored.
00130      *
00131      * \return threshold-enable property.
00132      */
00133     WPropBool thresholdEnabled() const;
00134 
00135     /**
00136      * Returns the interpolation property. The property can be changed. A change affects all colormaps using this texture.
00137      *
00138      * \return interpolation property
00139      */
00140     WPropBool interpolation() const;
00141 
00142     /**
00143      * Returns the colormap property. The property can be changed. A change affects all colormaps using this texture.
00144      *
00145      * \return colormap property
00146      */
00147     WPropSelection colormap() const;
00148 
00149     /**
00150      * Returns the active property. The property can be changed. A change affects all colormaps using this texture.
00151      *
00152      * \return active property
00153      */
00154     WPropBool active() const;
00155 
00156     /**
00157      * Returns the texture transformation matrix. The property can be changed. A change affects all colormaps using this texture. This matrix
00158      * converts an world-space coordinate to an texture coordinate! This can be seen as a scaled inverse matrix of the grid's transformation.
00159      *
00160      * \return the matrix
00161      */
00162     WPropMatrix4X4 transformation() const;
00163 
00164     /**
00165      * Binds the texture to the specified node and texture unit. It also adds two uniforms: u_textureXMin and u_textureXScale, where X
00166      * is the unit number. This can be used in shaders to unscale it.
00167      *
00168      * \param node the node where to bind the texture to
00169      * \param unit the unit, by default 0
00170      */
00171     void bind( osg::ref_ptr< osg::Node > node, size_t unit = 0 );
00172 
00173     /**
00174      * Return a pointer to the properties object of the dataset. Add all the modifiable settings here. This allows the user to modify several
00175      * properties of a dataset.
00176      *
00177      * \return the properties.
00178      */
00179     boost::shared_ptr< WProperties > getProperties() const;
00180 
00181     /**
00182      * Return a pointer to the information properties object of the dataset. The dataset intends these properties to not be modified.
00183      *
00184      * \return the properties.
00185      */
00186     boost::shared_ptr< WProperties > getInformationProperties() const;
00187 
00188     /**
00189      * Applies some custom uniforms to the specified state-set which directly relate to this texture
00190      *
00191      * \param prefix the prefix used for the uniforms
00192      * \param states the state where to add the uniforms
00193      */
00194     virtual void applyUniforms( std::string prefix, osg::StateSet* states ) const;
00195 
00196     /**
00197      * For all the lazy guys to set the filter MIN and MAG at once.
00198      *
00199      * \param mode the new mode for MIN_FILTER and MAG_FILTER.
00200      */
00201     void setFilterMinMag( osg::Texture::FilterMode mode );
00202 
00203     /**
00204      * For all the lazy guys to set the wrapping for s,t and r directions at once.
00205      *
00206      * \param mode the new mode for WRAP_S, WRAP_T and WRAP_R.
00207      */
00208     void setWrapSTR( osg::Texture::WrapMode mode );
00209 
00210     /**
00211      * Returns the texture's bounding box. This is const. Although there exists the transformation() property, it is an information property and
00212      * can't be changed.
00213      *
00214      * \return the bounding box.
00215      */
00216     virtual WBoundingBox getBoundingBox() const;
00217 
00218 protected:
00219     /**
00220      * Handles all property updates. Called by m_propCondition.
00221      */
00222     virtual void handleUpdate();
00223 
00224     /**
00225      * Creates the texture data. Overwrite this method if you want to provide a custom texture creation procedure.
00226      */
00227     virtual void create();
00228 
00229     /**
00230      * This method implements an update callback which updates the texture image if needed and several other properties like texture matrix.
00231      *
00232      * \param state the state to update
00233      */
00234     virtual void updateCallback( osg::StateAttribute* state );
00235 
00236     /**
00237      * Initialize the size of the texture properly according to real texture type (1D,2D,3D).
00238      * \note This is needed because osg::Texture::setImage is not virtual and does not set the size from the image.
00239      *
00240      * \param texture the texture where to set the size
00241      * \param width the new width
00242      * \param height the new height
00243      * \param depth the new depth
00244      */
00245     static void initTextureSize( osg::Texture1D* texture, int width, int height, int depth );
00246 
00247     /**
00248      * Initialize the size of the texture properly according to real texture type (1D,2D,3D).
00249      * \note This is needed because osg::Texture::setImage is not virtual and does not set the size from the image.
00250      *
00251      * \param texture the texture where to set the size
00252      * \param width the new width
00253      * \param height the new height
00254      * \param depth the new depth
00255      */
00256     static void initTextureSize( osg::Texture2D* texture, int width, int height, int depth );
00257 
00258     /**
00259      * Initialize the size of the texture properly according to real texture type (1D,2D,3D).
00260      * \note This is needed because osg::Texture::setImage is not virtual and does not set the size from the image.
00261      *
00262      * \param texture the texture where to set the size
00263      * \param width the new width
00264      * \param height the new height
00265      * \param depth the new depth
00266      */
00267     static void initTextureSize( osg::Texture3D* texture, int width, int height, int depth );
00268 
00269 private:
00270     /**
00271      * Creates and assigns all properties.
00272      *
00273      * \param min the min value of the texture
00274      * \param scale the scale value of the texture
00275      */
00276     void setupProperties( double scale, double min );
00277 
00278     /**
00279      * A condition used to notify about changes in several properties.
00280      */
00281     boost::shared_ptr< WCondition > m_propCondition;
00282 
00283     /**
00284      * The property object for the dataset.
00285      */
00286     boost::shared_ptr< WProperties > m_properties;
00287 
00288     /**
00289      * The property object for the dataset containing only props whose purpose is "PV_PURPOSE_INFORMNATION". It is useful to define some property
00290      * 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
00291      * m_properties.
00292      */
00293     boost::shared_ptr< WProperties > m_infoProperties;
00294 
00295     /**
00296      * If true, the texture gets created. This is used to create texture on demand.
00297      */
00298     bool m_needCreate;
00299 
00300     /**
00301      * The texture name. This might be useful to identify textures.
00302      */
00303     WPropString m_name;
00304 
00305     /**
00306      * The minimum of each value in the texture in unscaled space.
00307      */
00308     WPropDouble m_min;
00309 
00310     /**
00311      * The scaling factor to de-scale a [0-1] texture to original space.
00312      */
00313     WPropDouble m_scale;
00314 
00315     /**
00316      * A list of color map selection types
00317      */
00318     boost::shared_ptr< WItemSelection > m_colorMapSelectionsList;
00319 
00320     /**
00321      * Selection property for color map
00322      */
00323     WPropSelection m_colorMap;
00324 
00325     /**
00326      * Alpha blending value.
00327      */
00328     WPropDouble m_alpha;
00329 
00330     /**
00331      * Threshold for clipping areas.
00332      */
00333     WPropDouble m_threshold;
00334 
00335     /**
00336      * Threshold-enable flag.
00337      */
00338     WPropBool m_thresholdEnabled;
00339 
00340     /**
00341      * True if interpolation should be used.
00342      */
00343     WPropBool m_interpolation;
00344 
00345     /**
00346      * True if the texture is active.
00347      */
00348     WPropBool m_active;
00349 
00350     /**
00351      * The texture transformation matrix.
00352      */
00353     WPropMatrix4X4 m_texMatrix;
00354 };
00355 
00356 // Some convenience typedefs
00357 
00358 /**
00359  * OSG's Texture1D with scaling features
00360  */
00361 typedef WGETexture< osg::Texture1D > WGETexture1D;
00362 
00363 /**
00364  * OSG's Texture2D with scaling features
00365  */
00366 typedef WGETexture< osg::Texture2D > WGETexture2D;
00367 
00368 /**
00369  * OSG's Texture3D with scaling features
00370  */
00371 typedef WGETexture< osg::Texture3D > WGETexture3D;
00372 
00373 
00374 template < typename TextureType >
00375 WGETexture< TextureType >::WGETexture( double scale, double min ):
00376     TextureType(),
00377     m_propCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
00378     m_properties( boost::shared_ptr< WProperties >( new WProperties( "Texture Properties", "Properties of a texture." ) ) ),
00379     m_infoProperties( boost::shared_ptr< WProperties >( new WProperties( "Texture Info Properties", "Texture's information properties." ) ) ),
00380     m_needCreate( true )
00381 {
00382     setupProperties( scale, min );
00383 }
00384 
00385 template < typename TextureType >
00386 WGETexture< TextureType >::WGETexture( osg::Image* image, double scale, double min ):
00387     TextureType( image ),
00388     m_propCondition( boost::shared_ptr< WCondition >( new WCondition() ) ),
00389     m_properties( boost::shared_ptr< WProperties >( new WProperties( "Texture Properties", "Properties of a texture." ) ) ),
00390     m_infoProperties( boost::shared_ptr< WProperties >( new WProperties( "Texture Info Properties", "Texture's information properties." ) ) ),
00391     m_needCreate( true )
00392 {
00393     setupProperties( scale, min );
00394     WGETexture< TextureType >::initTextureSize( this, image->s(), image->t(), image->r() );
00395 }
00396 
00397 template < typename TextureType >
00398 WGETexture< TextureType >::WGETexture( const WGETexture< TextureType >& texture, const osg::CopyOp& copyop ):
00399     TextureType( texture, copyop ),
00400     m_min( texture.m_min ),
00401     m_scale( texture.m_scale )
00402 {
00403     // initialize members
00404 }
00405 
00406 template < typename TextureType >
00407 void WGETexture< TextureType >::setupProperties( double scale, double min )
00408 {
00409     m_propCondition->subscribeSignal( boost::bind( &WGETexture< TextureType >::handleUpdate, this ) );
00410 
00411     m_name = m_properties->addProperty( "Name", "The name of the texture.", std::string( "Unnamed" ) );
00412 
00413     // initialize members
00414     m_min = m_properties->addProperty( "Minimum", "The minimum value in the original space.", min, true );
00415     m_min->removeConstraint( m_min->getMin() );
00416     m_min->removeConstraint( m_min->getMax() );
00417 
00418     m_scale = m_properties->addProperty( "Scale", "The scaling factor to un-scale the texture values to the original space.", scale, true );
00419     m_scale->removeConstraint( m_scale->getMin() );
00420     m_scale->removeConstraint( m_scale->getMax() );
00421 
00422     m_alpha = m_properties->addProperty( "Alpha", "The alpha blending value.", 1.0 );
00423     m_alpha->setMin( 0.0 );
00424     m_alpha->setMax( 1.0 );
00425 
00426     m_thresholdEnabled = m_properties->addProperty( "Enable Threshold",
00427                                                     "If enabled, threshold based clipping is used. If not, threshold is ignored.", false );
00428 
00429     m_threshold = m_properties->addProperty( "Threshold", "The threshold used to clip areas.", 0.0 );
00430     m_threshold->setMin( min );
00431     m_threshold->setMax( min + scale );
00432 
00433     m_interpolation = m_properties->addProperty( "Interpolate", "Interpolation of the volume data.", true, m_propCondition );
00434 
00435     m_colorMapSelectionsList = boost::shared_ptr< WItemSelection >( new WItemSelection() );
00436     m_colorMapSelectionsList->addItem( "Grayscale", "" );
00437     m_colorMapSelectionsList->addItem( "Rainbow", "" );
00438     m_colorMapSelectionsList->addItem( "Hot iron", "" );
00439     m_colorMapSelectionsList->addItem( "Negative to positive", "" );
00440     m_colorMapSelectionsList->addItem( "Atlas", "" );
00441     m_colorMapSelectionsList->addItem( "Blue-Green-Purple", "" );
00442     m_colorMapSelectionsList->addItem( "Vector", "" );
00443 
00444     m_colorMap = m_properties->addProperty( "Colormap", "The colormap of this texture.", m_colorMapSelectionsList->getSelectorFirst() );
00445     WPropertyHelper::PC_SELECTONLYONE::addTo( m_colorMap );
00446 
00447     m_active = m_properties->addProperty( "Active", "Can dis-enable a texture.", true );
00448 
00449     WMatrix4d m = WMatrix4d::identity();
00450     m_texMatrix = m_properties->addProperty( "Texture Transformation", "Usable to transform the texture.", m );
00451     m_texMatrix->setPurpose( PV_PURPOSE_INFORMATION );
00452 
00453     TextureType::setResizeNonPowerOfTwoHint( false );
00454     TextureType::setUpdateCallback( new WGEFunctorCallback< osg::StateAttribute >(
00455         boost::bind( &WGETexture< TextureType >::updateCallback, this, _1 ) )
00456     );
00457 
00458     // init filters
00459     TextureType::setFilter( osg::Texture::MIN_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
00460     TextureType::setFilter( osg::Texture::MAG_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
00461 }
00462 
00463 template < typename TextureType >
00464 WGETexture< TextureType >::~WGETexture()
00465 {
00466     // cleanup.
00467 }
00468 
00469 template < typename TextureType >
00470 boost::shared_ptr< WProperties > WGETexture< TextureType >::getProperties() const
00471 {
00472     return m_properties;
00473 }
00474 
00475 template < typename TextureType >
00476 boost::shared_ptr< WProperties > WGETexture< TextureType >::getInformationProperties() const
00477 {
00478     return m_infoProperties;
00479 }
00480 
00481 template < typename TextureType >
00482 inline WPropString WGETexture< TextureType >::name() const
00483 {
00484     return m_name;
00485 }
00486 
00487 template < typename TextureType >
00488 inline WPropDouble WGETexture< TextureType >::minimum() const
00489 {
00490     return m_min;
00491 }
00492 
00493 template < typename TextureType >
00494 inline WPropDouble WGETexture< TextureType >::scale() const
00495 {
00496     return m_scale;
00497 }
00498 
00499 template < typename TextureType >
00500 inline WPropDouble WGETexture< TextureType >::alpha() const
00501 {
00502     return m_alpha;
00503 }
00504 
00505 template < typename TextureType >
00506 inline WPropDouble WGETexture< TextureType >::threshold() const
00507 {
00508     return m_threshold;
00509 }
00510 
00511 template < typename TextureType >
00512 inline WPropBool WGETexture< TextureType >::thresholdEnabled() const
00513 {
00514     return m_thresholdEnabled;
00515 }
00516 
00517 template < typename TextureType >
00518 inline WPropBool WGETexture< TextureType >::interpolation() const
00519 {
00520     return m_interpolation;
00521 }
00522 
00523 template < typename TextureType >
00524 inline WPropSelection WGETexture< TextureType >::colormap() const
00525 {
00526     return m_colorMap;
00527 }
00528 
00529 template < typename TextureType >
00530 inline WPropBool WGETexture< TextureType >::active() const
00531 {
00532     return m_active;
00533 }
00534 
00535 template < typename TextureType >
00536 inline WPropMatrix4X4 WGETexture< TextureType >::transformation() const
00537 {
00538     return m_texMatrix;
00539 }
00540 
00541 template < typename TextureType >
00542 void  WGETexture< TextureType >::handleUpdate()
00543 {
00544     if( m_interpolation->changed() )
00545     {
00546         TextureType::setFilter( osg::Texture::MIN_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
00547         TextureType::setFilter( osg::Texture::MAG_FILTER, m_interpolation->get( true ) ? osg::Texture::LINEAR : osg::Texture::NEAREST );
00548     }
00549 }
00550 
00551 template < typename TextureType >
00552 void  WGETexture< TextureType >::applyUniforms( std::string prefix, osg::StateSet* states ) const
00553 {
00554     states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Min", minimum() ) );
00555     states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Scale", scale() ) );
00556     states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Alpha", alpha() ) );
00557     states->addUniform( new WGEPropertyUniform< WPropBool >( prefix + "ThresholdEnabled", thresholdEnabled() ) );
00558     states->addUniform( new WGEPropertyUniform< WPropDouble >( prefix + "Threshold", threshold() ) );
00559     states->addUniform( new WGEPropertyUniform< WPropSelection >( prefix + "Colormap", colormap() ) );
00560     states->addUniform( new WGEPropertyUniform< WPropBool >( prefix + "Active", active() ) );
00561 }
00562 
00563 template < typename TextureType >
00564 void WGETexture< TextureType >::bind( osg::ref_ptr< osg::Node > node, size_t unit )
00565 {
00566     // let our utilities do the work
00567     wge::bindTexture( node, osg::ref_ptr< WGETexture< TextureType > >( this ), unit ); // to avoid recursive stuff -> explicitly specify the type
00568 }
00569 
00570 template < typename TextureType >
00571 void WGETexture< TextureType >::create()
00572 {
00573     // do nothing. Derived classes may implement this.
00574 }
00575 
00576 template < typename TextureType >
00577 void WGETexture< TextureType >::updateCallback( osg::StateAttribute* /*state*/ )
00578 {
00579     // create if not done yet
00580     if( m_needCreate )
00581     {
00582         m_needCreate = false;
00583         create();
00584         TextureType::dirtyTextureObject();
00585     }
00586 }
00587 
00588 template < typename TextureType >
00589 void WGETexture< TextureType >::setFilterMinMag( osg::Texture::FilterMode mode )
00590 {
00591     this->setFilter( osg::Texture2D::MIN_FILTER, mode );
00592     this->setFilter( osg::Texture2D::MAG_FILTER, mode );
00593 }
00594 
00595 template < typename TextureType >
00596 void WGETexture< TextureType >::setWrapSTR( osg::Texture::WrapMode mode )
00597 {
00598     this->setWrap( osg::Texture2D::WRAP_S, mode );
00599     this->setWrap( osg::Texture2D::WRAP_T, mode );
00600     this->setWrap( osg::Texture2D::WRAP_R, mode );
00601 }
00602 
00603 template < typename TextureType >
00604 void WGETexture< TextureType >::initTextureSize( osg::Texture1D* texture, int width, int /*height*/, int /*depth*/ )
00605 {
00606     texture->setTextureWidth( width );
00607 }
00608 
00609 template < typename TextureType >
00610 void WGETexture< TextureType >::initTextureSize( osg::Texture2D* texture, int width, int height, int /*depth*/ )
00611 {
00612     texture->setTextureSize( width, height );
00613 }
00614 
00615 template < typename TextureType >
00616 void WGETexture< TextureType >::initTextureSize( osg::Texture3D* texture, int width, int height, int depth )
00617 {
00618     texture->setTextureSize( width, height, depth );
00619 }
00620 
00621 template < typename TextureType >
00622 WBoundingBox WGETexture< TextureType >::getBoundingBox() const
00623 {
00624     return WBoundingBox( 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 );
00625 }
00626 
00627 #endif  // WGETEXTURE_H
00628