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 #include <boost/shared_ptr.hpp>
33 #include <boost/signals2.hpp>
34 
35 #include "../graphicsEngine/WGETexture.h"
36 #include "../graphicsEngine/WGETypeTraits.h"
37 #include "../common/WProperties.h"
38 #include "../common/WLogger.h"
39 
40 #include "WValueSetBase.h"
41 #include "WGridRegular3D.h"
42 
43 /**
44  * Namespace provides some scaling functions for scaling data values to meet the OpenGL requirements.
45  */
47 {
48  /**
49  * 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
50  * problem.
51  *
52  * \param value the value to scale
53  * \param minimum the min value
54  * \param maximum the max value
55  * \param scaler the scaler
56  *
57  * \return the value scaled to [0,1]
58  *
59  * \note Most integral types need to be scaled. See WGETypeTraits.h for details.
60  */
61  template < typename T >
62  inline typename wge::GLType< T >::Type scaleInterval( T value, T minimum, T maximum, double scaler )
63  {
64  return static_cast< double >( std::min( std::max( value, minimum ), maximum ) - minimum ) / scaler;
65  }
66 
67  /**
68  * Byte data is transferred to texture mem as is without any scaling.
69  *
70  * \param value the value to scale
71  *
72  * \return the value
73  */
74  inline int8_t scaleInterval( int8_t value, int8_t /*minimum*/, int8_t /*maximum*/, double /*scaler*/ )
75  {
76  return value;
77  }
78 
79  /**
80  * Byte data is transferred to texture mem as is without any scaling.
81  *
82  * \param value the value to scale
83  *
84  * \return the value
85  */
86  inline uint8_t scaleInterval( uint8_t value, uint8_t /*minimum*/, uint8_t /*maximum*/, double /*scaler*/ )
87  {
88  return value;
89  }
90 }
91 
92 /**
93  * This class allows simple creation of WGETexture3D by using a specified grid and value-set. One advantage: the
94  * first call to the texture's update callback ensures texture creation. It is not created earlier.
95  */
97 {
98 public:
99  /**
100  * Constructor. Creates the texture. Just run it after graphics engine was initialized.
101  *
102  * \param valueSet the value set to use
103  * \param grid the grid to use
104  */
105  WDataTexture3D( boost::shared_ptr< WValueSetBase > valueSet, boost::shared_ptr< WGridRegular3D > grid );
106 
107  /**
108  * Destructor.
109  */
110  virtual ~WDataTexture3D();
111 
112  /**
113  * Returns the texture's bounding box. This is const. Although there exists the transformation() property, it is an information property and
114  * can't be changed. This represents the underlying grid.
115  *
116  * \return the bounding box.
117  */
118  virtual WBoundingBox getBoundingBox() const;
119 
120 protected:
121  /**
122  * Creates the texture data. This method creates the texture during the first update traversal using the value set and grid.
123  */
124  virtual void create();
125 
126 private:
127  /**
128  * The value set from which the texture gets created.
129  */
130  boost::shared_ptr< WValueSetBase > m_valueSet;
131 
132  /**
133  * The bounding box of the underlying grid.
134  */
136 
137  /**
138  * The lock for securing createTexture.
139  */
140  boost::shared_mutex m_creationLock;
141 
142  /**
143  * Creates a properly sized osg::Image from the specified source data.
144  *
145  * \param source the source data
146  * \param components number of components
147  * \tparam T the type of source data
148  *
149  * \return
150  */
151  template < typename T >
152  osg::ref_ptr< osg::Image > createTexture( T* source, int components = 1 );
153 };
154 
155 /**
156  * Extend the wge utils namespace with additional methods relating WDataTexture3D.
157  */
158 namespace wge
159 {
160  /**
161  * Binds the specified texture to the specified unit. It automatically adds several uniforms which then can be utilized in the shader:
162  * - u_textureXUnit: the unit number (useful for accessing correct gl_TexCoord and so on)
163  * - u_textureXSampler: the needed sampler
164  * - u_textureXSizeX: width of the texture in pixels
165  * - u_textureXSizeY: height of the texture in pixels
166  * - u_textureXSizeZ: depth of the texture in pixels
167  * If the specified texture is a WGETexture, it additionally adds u_textureXMin and u_textureXScale for unscaling.
168  *
169  * \param node where to bind
170  * \param unit the unit to use
171  * \param texture the texture to use.
172  * \param prefix if specified, defines the uniform name prefix. (Sampler, Unit, Sizes, ...)
173  * \tparam T the type of texture. Usually osg::Texture3D or osg::Texture2D.
174  */
175  void bindTexture( osg::ref_ptr< osg::Node > node, osg::ref_ptr< WDataTexture3D > texture,
176  size_t unit = 0, std::string prefix = "" );
177 }
178 
179 template < typename T >
180 osg::ref_ptr< osg::Image > WDataTexture3D::createTexture( T* source, int components )
181 {
182  // get lock
183  boost::unique_lock< boost::shared_mutex > lock( m_creationLock );
184 
185  // get the current scaling info
186  T min = static_cast< T >( minimum()->get() );
187  double scaler = scale()->get();
188  T max = min + static_cast< T >( scaler );
189 
190  typedef typename wge::GLType< T >::Type TexType;
191  GLenum type = wge::GLType< T >::TypeEnum;
192 
193  wlog::debug( "WDataTexture3D" ) << "Resolution: " << getTextureWidth() << "x" << getTextureHeight() << "x" << getTextureDepth();
194  wlog::debug( "WDataTexture3D" ) << "Channels: " << components;
195  // NOTE: the casting is needed as if T == uint8_t -> it will be interpreted as ASCII code -> bad.
196  wlog::debug( "WDataTexture3D" ) << "Value Range: [" << static_cast< float >( min ) << "," << static_cast< float >( max ) <<
197  "] - Scaler: " << scaler;
198  osg::ref_ptr< osg::Image > ima = new osg::Image;
199 
200  size_t nbVoxels = getTextureWidth() * getTextureHeight() * getTextureDepth();
201 
202  if( components == 1)
203  {
204  // OpenGL just supports float textures
205  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_LUMINANCE_ALPHA, type );
206  TexType* data = reinterpret_cast< TexType* >( ima->data() );
207 
208  // Copy the data pixel wise and convert to float
209  for( unsigned int i = 0; i < nbVoxels; ++i )
210  {
211  data[ 2 * i ] = WDataTexture3DScalers::scaleInterval( source[i], min, max, scaler );
212  // NOTE: this is done to avoid ugly black borders when interpolation is active.
213  data[ ( 2 * i ) + 1] = wge::GLType< T >::FullIntensity() * ( source[i] != min );
214  }
215  }
216  else if( components == 2)
217  {
218  // OpenGL just supports float textures
219  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
220  ima->setInternalTextureFormat( GL_RGBA );
221  TexType* data = reinterpret_cast< TexType* >( ima->data() );
222 
223  // Copy the data pixel wise and convert to float
224  for( unsigned int i = 0; i < nbVoxels; ++i )
225  {
226  data[ ( 4 * i ) ] = WDataTexture3DScalers::scaleInterval( source[ ( 2 * i ) ], min, max, scaler );
227  data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 2 * i ) + 1 ], min, max, scaler );
228  data[ ( 4 * i ) + 2 ] = 0;
229  data[ ( 4 * i ) + 3 ] = wge::GLType< T >::FullIntensity();
230  }
231  }
232  else if( components == 3)
233  {
234  // OpenGL just supports float textures
235  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
236  ima->setInternalTextureFormat( GL_RGBA );
237  TexType* data = reinterpret_cast< TexType* >( ima->data() );
238 
239  // Copy the data pixel wise and convert to float
240  for( unsigned int i = 0; i < nbVoxels; ++i )
241  {
242  data[ ( 4 * i ) ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) ], min, max, scaler );
243  data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) + 1 ], min, max, scaler );
244  data[ ( 4 * i ) + 2 ] = WDataTexture3DScalers::scaleInterval( source[ ( 3 * i ) + 2 ], min, max, scaler );
245  data[ ( 4 * i ) + 3 ] = wge::GLType< T >::FullIntensity();
246  }
247  }
248  else if( components == 4)
249  {
250  // OpenGL just supports float textures
251  ima->allocateImage( getTextureWidth(), getTextureHeight(), getTextureDepth(), GL_RGBA, type );
252  ima->setInternalTextureFormat( GL_RGBA );
253  TexType* data = reinterpret_cast< TexType* >( ima->data() );
254 
255  // Copy the data pixel wise and convert to float
256  for( unsigned int i = 0; i < nbVoxels; ++i )
257  {
258  data[ ( 4 * i ) ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) ], min, max, scaler );
259  data[ ( 4 * i ) + 1 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 1 ], min, max, scaler );
260  data[ ( 4 * i ) + 2 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 2 ], min, max, scaler );
261  data[ ( 4 * i ) + 3 ] = WDataTexture3DScalers::scaleInterval( source[ ( 4 * i ) + 3 ], min, max, scaler );
262  }
263  }
264  else
265  {
266  wlog::error( "WDataTexture3D" ) << "Did not handle dataset ( components != 1,2,3 or 4 ).";
267  }
268 
269  // done, unlock
270  lock.unlock();
271 
272  return ima;
273 }
274 
275 #endif // WDATATEXTURE3D_H
276 
WStreamedLogger error(const std::string &source)
Logging an error message.
Definition: WLogger.h:298
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:53
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:583
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:589
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:331