OpenWalnut 1.2.5

WDataTexture3D.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 WDATATEXTURE3D_H
00026 #define WDATATEXTURE3D_H
00027 
00028 #include <algorithm>
00029 #include <limits>
00030 #include <string>
00031 
00032 #include <boost/shared_ptr.hpp>
00033 #include <boost/signals2.hpp>
00034 
00035 #include "../graphicsEngine/WGETexture.h"
00036 #include "../graphicsEngine/WGETypeTraits.h"
00037 #include "../common/WProperties.h"
00038 
00039 #include "WValueSetBase.h"
00040 #include "WGridRegular3D.h"
00041 
00042 #include "WExportDataHandler.h"
00043 
00044 /**
00045  * Namespace provides some scaling functions for scaling data values to meet the OpenGL requirements.
00046  */
00047 namespace WDataTexture3DScalers
00048 {
00049     /**
00050      * Scales the specified value to the interval [0,1] using m_min and m_scale. As the method is inline, the additional parameters are no
00051      * problem.
00052      *
00053      * \param value the value to scale
00054      * \param minimum the min value
00055      * \param maximum the max value
00056      * \param scaler the scaler
00057      *
00058      * \return the value scaled to [0,1]
00059      *
00060      * \note Most integral types need to be scaled. See WGETypeTraits.h for details.
00061      */
00062     template < typename T >
00063     inline typename wge::GLType< T >::Type scaleInterval( T value, T minimum, T maximum, double scaler )
00064     {
00065         return static_cast< double >( std::min( std::max( value, minimum ), maximum ) - minimum ) / scaler;
00066     }
00067 
00068     /**
00069      * Byte data is transferred to texture mem as is without any scaling.
00070      *
00071      * \param value the value to scale
00072      *
00073      * \return the value
00074      */
00075     inline int8_t scaleInterval( int8_t value, int8_t /*minimum*/, int8_t /*maximum*/, double /*scaler*/ )
00076     {
00077         return value;
00078     }
00079 
00080     /**
00081      * Byte data is transferred to texture mem as is without any scaling.
00082      *
00083      * \param value the value to scale
00084      *
00085      * \return the value
00086      */
00087     inline uint8_t scaleInterval( uint8_t value, uint8_t /*minimum*/, uint8_t /*maximum*/, double /*scaler*/ )
00088     {
00089         return value;
00090     }
00091 }
00092 
00093 /**
00094  * This class allows simple creation of WGETexture3D by using a specified grid and value-set. One advantage: the
00095  * first call to the texture's update callback ensures texture creation. It is not created earlier.
00096  */
00097 class OWDATAHANDLER_EXPORT WDataTexture3D: public WGETexture3D
00098 {
00099 public:
00100 
00101     /**
00102      * Constructor. Creates the texture. Just run it after graphics engine was initialized.
00103      *
00104      * \param valueSet  the value set to use
00105      * \param grid the grid to use
00106      */
00107      WDataTexture3D( boost::shared_ptr< WValueSetBase > valueSet, boost::shared_ptr< WGridRegular3D > grid );
00108 
00109     /**
00110      * Destructor.
00111      */
00112     virtual ~WDataTexture3D();
00113 
00114     /**
00115      * Returns the texture's bounding box. This is const. Although there exists the transformation() property, it is an information property and
00116      * can't be changed. This represents the underlying grid.
00117      *
00118      * \return the bounding box.
00119      */
00120     virtual WBoundingBox getBoundingBox() const;
00121 
00122 protected:
00123 
00124     /**
00125      * Creates the texture data. This method creates the texture during the first update traversal using the value set and grid.
00126      */
00127     virtual void create();
00128 
00129 private:
00130 
00131     /**
00132      * The value set from which the texture gets created.
00133      */
00134     boost::shared_ptr< WValueSetBase > m_valueSet;
00135 
00136     /**
00137      * The bounding box of the underlying grid.
00138      */
00139     WBoundingBox m_boundingBox;
00140 
00141     /**
00142      * The lock for securing createTexture.
00143      */
00144     boost::shared_mutex m_creationLock;
00145 
00146     /**
00147      * Creates a properly sized osg::Image from the specified source data.
00148      *
00149      * \param source the source data
00150      * \param components number of components
00151      * \tparam T the type of source data
00152      *
00153      * \return
00154      */
00155     template < typename T >
00156     osg::ref_ptr< osg::Image > createTexture( T* source, int components = 1 );
00157 };
00158 
00159 /**
00160  * Extend the wge utils namespace with additional methods relating WDataTexture3D.
00161  */
00162 namespace wge
00163 {
00164     /**
00165      * Binds the specified texture to the specified unit. It automatically adds several uniforms which then can be utilized in the shader:
00166      * - u_textureXUnit: the unit number (useful for accessing correct gl_TexCoord and so on)
00167      * - u_textureXSampler: the needed sampler
00168      * - u_textureXSizeX: width of the texture in pixels
00169      * - u_textureXSizeY: height of the texture in pixels
00170      * - u_textureXSizeZ: depth of the texture in pixels
00171      * If the specified texture is a WGETexture, it additionally adds u_textureXMin and u_textureXScale for unscaling.
00172      *
00173      * \param node where to bind
00174      * \param unit the unit to use
00175      * \param texture the texture to use.
00176      * \param prefix if specified, defines the uniform name prefix. (Sampler, Unit, Sizes, ...)
00177      * \tparam T the type of texture. Usually osg::Texture3D or osg::Texture2D.
00178      */
00179     void OWDATAHANDLER_EXPORT bindTexture( osg::ref_ptr< osg::Node > node, osg::ref_ptr< WDataTexture3D > texture,
00180                                            size_t unit = 0, std::string prefix = ""  );
00181 }
00182 
00183 template < typename T >
00184 osg::ref_ptr< osg::Image > WDataTexture3D::createTexture( T* source, int components )
00185 {
00186     // get lock
00187     boost::unique_lock< boost::shared_mutex > lock( m_creationLock );
00188 
00189     // get the current scaling info
00190     T min = static_cast< T >( minimum()->get() );
00191     double scaler = scale()->get();
00192     T max = min + static_cast< T >( scaler );
00193 
00194     typedef typename wge::GLType< T >::Type TexType;
00195     GLenum type = wge::GLType< T >::TypeEnum;
00196 
00197     wlog::debug( "WDataTexture3D" ) << "Resolution: " << getTextureWidth() << "x" << getTextureHeight() << "x" << getTextureDepth();
00198     wlog::debug( "WDataTexture3D" ) << "Channels: " << components;
00199     // NOTE: the casting is needed as if T == uint8_t -> it will be interpreted as ASCII code -> bad.
00200     wlog::debug( "WDataTexture3D" ) << "Value Range: [" << static_cast< float >( min ) << "," << static_cast< float >( max ) <<
00201                                                        "] - Scaler: " << scaler;
00202     osg::ref_ptr< osg::Image > ima = new osg::Image;
00203 
00204     size_t nbVoxels = getTextureWidth() * getTextureHeight() * getTextureDepth();
00205 
00206     if( components == 1)
00207     {
00208         // OpenGL just supports float textures
00209         ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_LUMINANCE_ALPHA, type );
00210         TexType* data = reinterpret_cast< TexType* >( ima->data() );
00211 
00212         // Copy the data pixel wise and convert to float
00213         for( unsigned int i = 0; i < nbVoxels; ++i )
00214         {
00215             data[ 2 * i ] = WDataTexture3DScalers::scaleInterval( source[i], min, max, scaler );
00216             // NOTE: this is done to avoid ugly black borders when interpolation is active.
00217             data[ ( 2 * i ) + 1] = wge::GLType< T >::FullIntensity() * ( source[i] != min );
00218         }
00219     }
00220     else if( components == 2)
00221     {
00222         // OpenGL just supports float textures
00223         ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
00224         ima->setInternalTextureFormat( GL_RGBA );
00225         TexType* data = reinterpret_cast< TexType* >( ima->data() );
00226 
00227         // Copy the data pixel wise and convert to float
00228         for( unsigned int i = 0; i < nbVoxels; ++i )
00229         {
00230             data[ ( 4 * i ) ]     = WDataTexture3DScalers::scaleInterval( source[ ( 2 * i ) ], min, max, scaler );
00231             data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 2 * i ) + 1 ], min, max, scaler );
00232             data[ ( 4 * i ) + 2 ] = 0;
00233             data[ ( 4 * i ) + 3 ] = wge::GLType< T >::FullIntensity();
00234         }
00235     }
00236     else if( components == 3)
00237     {
00238         // OpenGL just supports float textures
00239         ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
00240         ima->setInternalTextureFormat( GL_RGBA );
00241         TexType* data = reinterpret_cast< TexType* >( ima->data() );
00242 
00243         // Copy the data pixel wise and convert to float
00244         for( unsigned int i = 0; i < nbVoxels; ++i )
00245         {
00246             data[ ( 4 * i ) ]     = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) ], min, max, scaler );
00247             data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) + 1 ], min, max, scaler );
00248             data[ ( 4 * i ) + 2 ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) + 2 ], min, max, scaler );
00249             data[ ( 4 * i ) + 3 ] = wge::GLType< T >::FullIntensity();
00250         }
00251     }
00252     else if( components == 4)
00253     {
00254         // OpenGL just supports float textures
00255         ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
00256         ima->setInternalTextureFormat( GL_RGBA );
00257         TexType* data = reinterpret_cast< TexType* >( ima->data() );
00258 
00259         // Copy the data pixel wise and convert to float
00260         for( unsigned int i = 0; i < nbVoxels; ++i )
00261         {
00262             data[ ( 4 * i ) ]     = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) ], min, max, scaler );
00263             data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 1 ], min, max, scaler );
00264             data[ ( 4 * i ) + 2 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 2 ], min, max, scaler );
00265             data[ ( 4 * i ) + 3 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 3 ], min, max, scaler );
00266         }
00267     }
00268     else
00269     {
00270         wlog::error( "WDataTexture3D" ) << "Did not handle dataset ( components != 1,2,3 or 4 ).";
00271     }
00272 
00273     // done, unlock
00274     lock.unlock();
00275 
00276     return ima;
00277 }
00278 
00279 #endif  // WDATATEXTURE3D_H
00280 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends