OpenWalnut  1.5.0dev
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 <memory>
31 #include <shared_mutex>
32 #include <string>
33 
34 #include <boost/signals2.hpp>
35 
36 #include "../common/WLogger.h"
37 #include "../common/WProperties.h"
38 #include "../graphicsEngine/WGETexture.h"
39 #include "../graphicsEngine/WGETypeTraits.h"
40 #include "WGridRegular3D.h"
41 #include "WValueSetBase.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( std::shared_ptr< WValueSetBase > valueSet, std::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  std::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  std::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  std::unique_lock< std::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 
This class allows simple creation of WGETexture3D by using a specified grid and value-set.
WBoundingBox m_boundingBox
The bounding box of the underlying grid.
virtual WBoundingBox getBoundingBox() const
Returns the texture's bounding box.
osg::ref_ptr< osg::Image > createTexture(T *source, int components=1)
Creates a properly sized osg::Image from the specified source data.
std::shared_ptr< WValueSetBase > m_valueSet
The value set from which the texture gets created.
virtual ~WDataTexture3D()
Destructor.
WDataTexture3D(std::shared_ptr< WValueSetBase > valueSet, std::shared_ptr< WGridRegular3D > grid)
Constructor.
std::shared_mutex m_creationLock
The lock for securing createTexture.
virtual void create()
Creates the texture data.
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
Definition: WGETexture.h:53
WPropDouble scale() const
Get the scaling factor for de-scaling the texture.
Definition: WGETexture.h:621
WPropDouble minimum() const
Get the minimum in the de-scaled value space.
Definition: WGETexture.h:615
Class helping to adapt types specified as template parameter into the best matching OpenGL type.
Definition: WGETypeTraits.h:41
T Type
The best matching OpenGL type for the specified template parameter.
Definition: WGETypeTraits.h:46
Namespace provides some scaling functions for scaling data values to meet the OpenGL requirements.
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.
Extend the wge utils namespace with additional methods relating WDataTexture3D.
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.
WStreamedLogger debug(const std::string &source)
Logging a debug message.
Definition: WLogger.h:331
WStreamedLogger error(const std::string &source)
Logging an error message.
Definition: WLogger.h:298