OpenWalnut  1.5.0dev
WGETextureUtils.cpp
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 #include <algorithm>
26 #include <vector>
27 
28 #include <boost/random.hpp>
29 
30 #include "../common/exceptions/WPreconditionNotMet.h"
31 
32 #include "WGETexture.h"
33 
34 #include "WGETextureUtils.h"
35 
36 void wge::unbindTexture( osg::ref_ptr< osg::Node > node, size_t unit, size_t count )
37 {
38  for( size_t i = unit; i < unit + count; ++i )
39  {
40  node->getOrCreateStateSet()->removeTextureAttribute( i, osg::StateAttribute::TEXTURE );
41  node->getOrCreateStateSet()->removeTextureAttribute( i, osg::StateAttribute::TEXMAT );
42  }
43 }
44 
46 {
47  // GLint ret;
48  // glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ret );
49  // Why do we not use these glGet things here? The answer is simple: The GLSL 1.20 Standard does not define a way to access more than 8
50  // texture coordinate attributes.
51  return 8;
52 }
53 
54 osg::ref_ptr< WGETexture< osg::Texture1D > > wge::genWhiteNoiseTexture( size_t sizeX, size_t channels )
55 {
56  // put it into an texture
57  osg::ref_ptr< WGETexture1D > randTexture = new WGETexture1D( genWhiteNoiseImage( sizeX, 1, 1, channels ) );
58  randTexture->setTextureWidth( sizeX );
59  randTexture->setFilter( osg::Texture1D::MIN_FILTER, osg::Texture1D::NEAREST );
60  randTexture->setFilter( osg::Texture1D::MAG_FILTER, osg::Texture1D::NEAREST );
61  randTexture->setWrap( osg::Texture1D::WRAP_S, osg::Texture1D::REPEAT );
62 
63  return randTexture;
64 }
65 
66 osg::ref_ptr< WGETexture< osg::Texture2D > > wge::genWhiteNoiseTexture( size_t sizeX, size_t sizeY, size_t channels )
67 {
68  osg::ref_ptr< WGETexture2D > randTexture = new WGETexture2D( genWhiteNoiseImage( sizeX, sizeY, 1, channels ) );
69  randTexture->setTextureWidth( sizeX );
70  randTexture->setTextureHeight( sizeY );
71  randTexture->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST );
72  randTexture->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST );
73  randTexture->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT );
74  randTexture->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT );
75 
76  return randTexture;
77 }
78 
79 osg::ref_ptr< WGETexture< osg::Texture3D > > wge::genWhiteNoiseTexture( size_t sizeX, size_t sizeY, size_t sizeZ, size_t channels )
80 {
81  osg::ref_ptr< WGETexture3D > randTexture = new WGETexture3D( genWhiteNoiseImage( sizeX, sizeY, sizeZ, channels ) );
82  randTexture->setTextureWidth( sizeX );
83  randTexture->setTextureHeight( sizeY );
84  randTexture->setTextureDepth( sizeZ );
85  randTexture->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST );
86  randTexture->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST );
87  randTexture->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT );
88  randTexture->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT );
89  randTexture->setWrap( osg::Texture2D::WRAP_R, osg::Texture2D::REPEAT );
90 
91  return randTexture;
92 }
93 
94 osg::ref_ptr< osg::Image > wge::genWhiteNoiseImage( size_t sizeX, size_t sizeY, size_t sizeZ, size_t channels )
95 {
96  WPrecond( ( channels == 1 ) || ( channels == 3 ) || ( channels == 4 ), "Invalid number of channels. Valid are: 1, 3 and 4." );
97 
98  // create an osg::Image at first.
99  std::srand( time( 0 ) );
100  osg::ref_ptr< osg::Image > randImage = new osg::Image();
101  GLenum type = GL_LUMINANCE;
102  if( channels == 3 )
103  {
104  type = GL_RGB;
105  }
106  else if( channels == 4 )
107  {
108  type = GL_RGBA;
109  }
110  randImage->allocateImage( sizeX, sizeY, sizeZ, type, GL_UNSIGNED_BYTE );
111  unsigned char *randomLuminance = randImage->data(); // should be 4 megs
112  for( size_t i = 0; i < channels * sizeX * sizeY * sizeZ; ++i )
113  {
114  // - stylechecker says "use rand_r" but I am not sure about portability.
115  unsigned char r = static_cast< unsigned char >( std::rand() % 255 ); // NOLINT - no we want std::rand instead of rand_r
116  randomLuminance[ i ] = r;
117  }
118 
119  return randImage;
120 }
121 
122 osg::ref_ptr< WGETexture< osg::Texture3D > > wge::genTuringNoiseTexture( std::size_t sizeX, std::size_t sizeY,
123  std::size_t sizeZ, std::size_t channels )
124 {
125  WPrecond( channels == 1 || channels == 3 || channels == 4, "Invalid number of channels. Valid are: 1, 3 and 4." );
126 
127  // some constants, maybe change to parameters
128  float const spotIrregularity = 0.05f; // 0.0 - 1.0
129  std::size_t const iterations = 200;
130  float const spotSize = 0.5;
131  float const spotFactor = ( 0.02f + 0.58f * ( 1.0f - spotSize ) ) / 15.0f;
132  float const d1 = 0.125f;
133  float const d2 = 0.03125f;
134  float const speed = 1.0f;
135 
136  osg::ref_ptr< osg::Image > img = new osg::Image;
137  GLenum type = GL_LUMINANCE;
138  if( channels == 3 )
139  {
140  type = GL_RGB;
141  }
142  else if( channels == 4 )
143  {
144  type = GL_RGBA;
145  }
146 
147  std::vector< float > concentration1( sizeX * sizeY * sizeZ, 4.0 );
148  std::vector< float > concentration2( sizeX * sizeY * sizeZ, 4.0 );
149  std::vector< float > delta1( sizeX * sizeY * sizeZ, 0.0 );
150  std::vector< float > delta2( sizeX * sizeY * sizeZ, 0.0 );
151  std::vector< float > noise( sizeX * sizeY * sizeZ );
152 
153  boost::mt19937 generator( std::time( 0 ) );
154 
155  float noiseRange = 0.1f + 4.9f * spotIrregularity;
156 
157  boost::uniform_real< float > dist( 12.0 - noiseRange, 12.0 + noiseRange );
158  boost::variate_generator< boost::mt19937&, boost::uniform_real< float > > rand( generator, dist );
159 
160  // initialization step
161  for( std::size_t i = 0; i < sizeX; ++i )
162  {
163  for( std::size_t j = 0; j < sizeY; ++j )
164  {
165  for( std::size_t k = 0; k < sizeZ; ++k )
166  {
167  std::size_t idx = i + j * sizeX + k * sizeX * sizeY;
168  noise[ idx ] = rand();
169  }
170  }
171  }
172 
173  // iteration
174  for( std::size_t iter = 0; iter < iterations; ++iter )
175  {
176  std::cout << "iterations: " << iter << std::endl;
177 
178  for( std::size_t i = 0; i < sizeX; ++i )
179  {
180  std::size_t iNext = ( i + 1 ) % sizeX;
181  std::size_t iPrev = ( i + sizeX - 1 ) % sizeX;
182 
183  for( std::size_t j = 0; j < sizeY; ++j )
184  {
185  std::size_t jNext = ( j + 1 ) % sizeY;
186  std::size_t jPrev = ( j + sizeY - 1 ) % sizeY;
187 
188  for( std::size_t k = 0; k < sizeZ; ++k )
189  {
190  std::size_t kNext = ( k + 1 ) % sizeZ;
191  std::size_t kPrev = ( k + sizeZ - 1 ) % sizeZ;
192 
193  std::size_t idx = i + j * sizeX + k * sizeX * sizeY;
194 
195  // estimate change in concentrations
196  // we use a 3d laplace filter here instead of the 2d filter as in Eichelbaum et al.
197  float dc1 = 0.0;
198  dc1 += concentration1[ iPrev + j * sizeX + k * sizeX * sizeY ];
199  dc1 += concentration1[ iNext + j * sizeX + k * sizeX * sizeY ];
200  dc1 += concentration1[ i + jPrev * sizeX + k * sizeX * sizeY ];
201  dc1 += concentration1[ i + jNext * sizeX + k * sizeX * sizeY ];
202  dc1 += concentration1[ i + j * sizeX + kPrev * sizeX * sizeY ];
203  dc1 += concentration1[ i + j * sizeX + kNext * sizeX * sizeY ];
204  dc1 -= 6.0f * concentration1[ idx ];
205 
206  float dc2 = 0.0;
207  dc2 += concentration2[ iPrev + j * sizeX + k * sizeX * sizeY ];
208  dc2 += concentration2[ iNext + j * sizeX + k * sizeX * sizeY ];
209  dc2 += concentration2[ i + jPrev * sizeX + k * sizeX * sizeY ];
210  dc2 += concentration2[ i + jNext * sizeX + k * sizeX * sizeY ];
211  dc2 += concentration2[ i + j * sizeX + kPrev * sizeX * sizeY ];
212  dc2 += concentration2[ i + j * sizeX + kNext * sizeX * sizeY ];
213  dc2 -= 6.0f * concentration2[ idx ];
214 
215  // diffusion
216  delta1[ idx ] = spotFactor * ( 16.0f - concentration1[ idx ] * concentration2[ idx ] ) + d1 * dc1;
217  delta2[ idx ] = spotFactor * ( concentration1[ idx ] * concentration2[ idx ] - concentration2[ idx ] - noise[ idx ] ) + d2 * dc2;
218  }
219  }
220  }
221 
222  for( std::size_t i = 0; i < sizeX; ++i )
223  {
224  for( std::size_t j = 0; j < sizeY; ++j )
225  {
226  for( std::size_t k = 0; k < sizeZ; ++k )
227  {
228  std::size_t idx = i + j * sizeX + k * sizeX * sizeY;
229 
230  concentration1[ idx ] += speed * delta1[ idx ];
231  concentration2[ idx ] += speed * delta2[ idx ];
232  }
233  }
234  }
235  }
236 
237  img->allocateImage( sizeX, sizeY, sizeZ, type, GL_UNSIGNED_BYTE );
238 
239  // find min and max
240  float c1min = *std::min_element( concentration1.begin(), concentration1.end() );
241  float c1max = *std::max_element( concentration1.begin(), concentration1.end() );
242 
243  // copy to image
244  for( std::size_t i = 0; i < sizeX; ++i )
245  {
246  for( std::size_t j = 0; j < sizeY; ++j )
247  {
248  for( std::size_t k = 0; k < sizeZ; ++k )
249  {
250  std::size_t idx = i + j * sizeX + k * sizeX * sizeY;
251  img->data()[ idx ] = 255.0f * ( concentration1[ idx ] - c1min ) / ( c1max - c1min );
252  }
253  }
254  }
255 
256  return osg::ref_ptr< WGETexture< osg::Texture3D > >( new WGETexture< osg::Texture3D >( img ) );
257 }
258 
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
Definition: WGETexture.h:53
osg::ref_ptr< WGETexture< osg::Texture3D > > genTuringNoiseTexture(std::size_t sizeX, std::size_t sizeY, std::size_t sizeZ, std::size_t channels=1)
Generates a 3D turing noise texture.
osg::ref_ptr< WGETexture< osg::Texture1D > > genWhiteNoiseTexture(size_t sizeX, size_t channels)
This generates an 1D texture only containing white noise in its channels.
osg::ref_ptr< osg::Image > genWhiteNoiseImage(size_t sizeX, size_t sizeY, size_t sizeZ, size_t channels=1)
Generates an image only containing white noise in its channels.
size_t getMaxTexUnits()
Returns the maximum number of textures that can be bound to a node.
void unbindTexture(osg::ref_ptr< osg::Node > node, size_t unit, size_t count=1)
Removes the binding associated with the specified unit.