OpenWalnut  1.4.0
WDataTexture3D.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WDATATEXTURE3D_H
26 #define WDATATEXTURE3D_H
27 
28 #include <algorithm>
29 #include <limits>
30 #include <string>
31 
32 #ifndef Q_MOC_RUN
33 #include <boost/shared_ptr.hpp>
34 #endif
35 #ifndef Q_MOC_RUN
36 #include <boost/signals2.hpp>
37 #endif
38 
39 #include "../graphicsEngine/WGETexture.h"
40 #include "../graphicsEngine/WGETypeTraits.h"
41 #include "../common/WProperties.h"
42 #include "../common/WLogger.h"
43 
44 #include "WValueSetBase.h"
45 #include "WGridRegular3D.h"
46 
47 /**
48  * Namespace provides some scaling functions for scaling data values to meet the OpenGL requirements.
49  */
51 {
52  /**
53  * 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
54  * problem.
55  *
56  * \param value the value to scale
57  * \param minimum the min value
58  * \param maximum the max value
59  * \param scaler the scaler
60  *
61  * \return the value scaled to [0,1]
62  *
63  * \note Most integral types need to be scaled. See WGETypeTraits.h for details.
64  */
65  template < typename T >
66  inline typename wge::GLType< T >::Type scaleInterval( T value, T minimum, T maximum, double scaler )
67  {
68  return static_cast< double >( std::min( std::max( value, minimum ), maximum ) - minimum ) / scaler;
69  }
70 
71  /**
72  * Byte data is transferred to texture mem as is without any scaling.
73  *
74  * \param value the value to scale
75  *
76  * \return the value
77  */
78  inline int8_t scaleInterval( int8_t value, int8_t /*minimum*/, int8_t /*maximum*/, double /*scaler*/ )
79  {
80  return value;
81  }
82 
83  /**
84  * Byte data is transferred to texture mem as is without any scaling.
85  *
86  * \param value the value to scale
87  *
88  * \return the value
89  */
90  inline uint8_t scaleInterval( uint8_t value, uint8_t /*minimum*/, uint8_t /*maximum*/, double /*scaler*/ )
91  {
92  return value;
93  }
94 }
95 
96 /**
97  * This class allows simple creation of WGETexture3D by using a specified grid and value-set. One advantage: the
98  * first call to the texture's update callback ensures texture creation. It is not created earlier.
99  */
101 {
102 public:
103  /**
104  * Constructor. Creates the texture. Just run it after graphics engine was initialized.
105  *
106  * \param valueSet the value set to use
107  * \param grid the grid to use
108  */
109  WDataTexture3D( boost::shared_ptr< WValueSetBase > valueSet, boost::shared_ptr< WGridRegular3D > grid );
110 
111  /**
112  * Destructor.
113  */
114  virtual ~WDataTexture3D();
115 
116  /**
117  * Returns the texture's bounding box. This is const. Although there exists the transformation() property, it is an information property and
118  * can't be changed. This represents the underlying grid.
119  *
120  * \return the bounding box.
121  */
122  virtual WBoundingBox getBoundingBox() const;
123 
124 protected:
125  /**
126  * Creates the texture data. This method creates the texture during the first update traversal using the value set and grid.
127  */
128  virtual void create();
129 
130 private:
131  /**
132  * The value set from which the texture gets created.
133  */
134  boost::shared_ptr< WValueSetBase > m_valueSet;
135 
136  /**
137  * The bounding box of the underlying grid.
138  */
140 
141  /**
142  * The lock for securing createTexture.
143  */
144  boost::shared_mutex m_creationLock;
145 
146  /**
147  * Creates a properly sized osg::Image from the specified source data.
148  *
149  * \param source the source data
150  * \param components number of components
151  * \tparam T the type of source data
152  *
153  * \return
154  */
155  template < typename T >
156  osg::ref_ptr< osg::Image > createTexture( T* source, int components = 1 );
157 };
158 
159 /**
160  * Extend the wge utils namespace with additional methods relating WDataTexture3D.
161  */
162 namespace wge
163 {
164  /**
165  * Binds the specified texture to the specified unit. It automatically adds several uniforms which then can be utilized in the shader:
166  * - u_textureXUnit: the unit number (useful for accessing correct gl_TexCoord and so on)
167  * - u_textureXSampler: the needed sampler
168  * - u_textureXSizeX: width of the texture in pixels
169  * - u_textureXSizeY: height of the texture in pixels
170  * - u_textureXSizeZ: depth of the texture in pixels
171  * If the specified texture is a WGETexture, it additionally adds u_textureXMin and u_textureXScale for unscaling.
172  *
173  * \param node where to bind
174  * \param unit the unit to use
175  * \param texture the texture to use.
176  * \param prefix if specified, defines the uniform name prefix. (Sampler, Unit, Sizes, ...)
177  * \tparam T the type of texture. Usually osg::Texture3D or osg::Texture2D.
178  */
179  void bindTexture( osg::ref_ptr< osg::Node > node, osg::ref_ptr< WDataTexture3D > texture,
180  size_t unit = 0, std::string prefix = "" );
181 }
182 
183 template < typename T >
184 osg::ref_ptr< osg::Image > WDataTexture3D::createTexture( T* source, int components )
185 {
186  // get lock
187  boost::unique_lock< boost::shared_mutex > lock( m_creationLock );
188 
189  // get the current scaling info
190  T min = static_cast< T >( minimum()->get() );
191  double scaler = scale()->get();
192  T max = min + static_cast< T >( scaler );
193 
194  typedef typename wge::GLType< T >::Type TexType;
195  GLenum type = wge::GLType< T >::TypeEnum;
196 
197  wlog::debug( "WDataTexture3D" ) << "Resolution: " << getTextureWidth() << "x" << getTextureHeight() << "x" << getTextureDepth();
198  wlog::debug( "WDataTexture3D" ) << "Channels: " << components;
199  // NOTE: the casting is needed as if T == uint8_t -> it will be interpreted as ASCII code -> bad.
200  wlog::debug( "WDataTexture3D" ) << "Value Range: [" << static_cast< float >( min ) << "," << static_cast< float >( max ) <<
201  "] - Scaler: " << scaler;
202  osg::ref_ptr< osg::Image > ima = new osg::Image;
203 
204  size_t nbVoxels = getTextureWidth() * getTextureHeight() * getTextureDepth();
205 
206  if( components == 1)
207  {
208  // OpenGL just supports float textures
209  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_LUMINANCE_ALPHA, type );
210  TexType* data = reinterpret_cast< TexType* >( ima->data() );
211 
212  // Copy the data pixel wise and convert to float
213  for( unsigned int i = 0; i < nbVoxels; ++i )
214  {
215  data[ 2 * i ] = WDataTexture3DScalers::scaleInterval( source[i], min, max, scaler );
216  // NOTE: this is done to avoid ugly black borders when interpolation is active.
217  data[ ( 2 * i ) + 1] = wge::GLType< T >::FullIntensity() * ( source[i] != min );
218  }
219  }
220  else if( components == 2)
221  {
222  // OpenGL just supports float textures
223  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
224  ima->setInternalTextureFormat( GL_RGBA );
225  TexType* data = reinterpret_cast< TexType* >( ima->data() );
226 
227  // Copy the data pixel wise and convert to float
228  for( unsigned int i = 0; i < nbVoxels; ++i )
229  {
230  data[ ( 4 * i ) ] = WDataTexture3DScalers::scaleInterval( source[ ( 2 * i ) ], min, max, scaler );
231  data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 2 * i ) + 1 ], min, max, scaler );
232  data[ ( 4 * i ) + 2 ] = 0;
233  data[ ( 4 * i ) + 3 ] = wge::GLType< T >::FullIntensity();
234  }
235  }
236  else if( components == 3)
237  {
238  // OpenGL just supports float textures
239  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
240  ima->setInternalTextureFormat( GL_RGBA );
241  TexType* data = reinterpret_cast< TexType* >( ima->data() );
242 
243  // Copy the data pixel wise and convert to float
244  for( unsigned int i = 0; i < nbVoxels; ++i )
245  {
246  data[ ( 4 * i ) ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) ], min, max, scaler );
247  data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) + 1 ], min, max, scaler );
248  data[ ( 4 * i ) + 2 ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) + 2 ], min, max, scaler );
249  data[ ( 4 * i ) + 3 ] = wge::GLType< T >::FullIntensity();
250  }
251  }
252  else if( components == 4)
253  {
254  // OpenGL just supports float textures
255  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
256  ima->setInternalTextureFormat( GL_RGBA );
257  TexType* data = reinterpret_cast< TexType* >( ima->data() );
258 
259  // Copy the data pixel wise and convert to float
260  for( unsigned int i = 0; i < nbVoxels; ++i )
261  {
262  data[ ( 4 * i ) ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) ], min, max, scaler );
263  data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 1 ], min, max, scaler );
264  data[ ( 4 * i ) + 2 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 2 ], min, max, scaler );
265  data[ ( 4 * i ) + 3 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 3 ], min, max, scaler );
266  }
267  }
268  else
269  {
270  wlog::error( "WDataTexture3D" ) << "Did not handle dataset ( components != 1,2,3 or 4 ).";
271  }
272 
273  // done, unlock
274  lock.unlock();
275 
276  return ima;
277 }
278 
279 #endif // WDATATEXTURE3D_H
280 
WStreamedLogger error(const std::string &source)
Logging an error message.
Definition: WLogger.h:302
boost::shared_ptr< WValueSetBase > m_valueSet
The value set from which the texture gets created.
Class helping to adapt types specified as template parameter into the best matching OpenGL type...
Definition: WGETypeTraits.h:40
osg::ref_ptr< osg::Image > createTexture(T *source, int components=1)
Creates a properly sized osg::Image from the specified source data.
virtual ~WDataTexture3D()
Destructor.
virtual WBoundingBox getBoundingBox() const
Returns the texture's bounding box.
T Type
The best matching OpenGL type for the specified template parameter.
Definition: WGETypeTraits.h:46
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
Definition: WGETexture.h:55
WBoundingBox m_boundingBox
The bounding box of the underlying grid.
Extend the wge utils namespace with additional methods relating WDataTexture3D.
virtual void create()
Creates the texture data.
WPropDouble minimum() const
Get the minimum in the de-scaled value space.
Definition: WGETexture.h:585
WDataTexture3D(boost::shared_ptr< WValueSetBase > valueSet, boost::shared_ptr< WGridRegular3D > grid)
Constructor.
WPropDouble scale() const
Get the scaling factor for de-scaling the texture.
Definition: WGETexture.h:591
wge::GLType< T >::Type scaleInterval(T value, T minimum, T maximum, double scaler)
Scales the specified value to the interval [0,1] using m_min and m_scale.
This class allows simple creation of WGETexture3D by using a specified grid and value-set.
boost::shared_mutex m_creationLock
The lock for securing createTexture.
void bindTexture(osg::ref_ptr< osg::Node > node, osg::ref_ptr< WDataTexture3D > texture, size_t unit=0, std::string prefix="")
Binds the specified texture to the specified unit.
Namespace provides some scaling functions for scaling data values to meet the OpenGL requirements...
WStreamedLogger debug(const std::string &source)
Logging a debug message.
Definition: WLogger.h:335