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 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