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