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