30 #include <boost/random.hpp>
31 #include <core/common/exceptions/WPreconditionNotMet.h>
33 #include "WTuringTextureCreator.h"
36 : m_numIterations( 100 ),
37 m_spotIrregularity( 0.1 ),
40 WPrecond( numThreads > 0,
"" );
42 for( std::size_t k = 0; k < numThreads; ++k )
54 WPrecond( iter > 0,
"Invalid number of iterations!" );
61 WPrecond( irr >= 0.0f && irr <= 1.0f,
"Spot irregularity must be in [0,1]!" );
68 WPrecond( size >= 0.0f && size <= 1.0f,
"Spot size must be in [0,1]!" );
76 float const spotFactor = ( 0.02f + 0.58f * ( 1.0f -
m_spotSize ) ) / 15.0f;
77 float const d1 = 0.125f;
78 float const d2 = 0.03125f;
79 float const speed = 1.0f;
81 std::vector< float > concentration1( sizeX * sizeY * sizeZ, 4.0f );
82 std::vector< float > concentration2( sizeX * sizeY * sizeZ, 4.0f );
83 std::vector< float > delta1( sizeX * sizeY * sizeZ, 0.0f );
84 std::vector< float > delta2( sizeX * sizeY * sizeZ, 0.0f );
85 std::vector< float > noise( sizeX * sizeY * sizeZ );
87 boost::mt19937 generator( std::time( 0 ) );
91 boost::uniform_real< float > dist( 12.0f - noiseRange, 12.0f + noiseRange );
92 boost::variate_generator< boost::mt19937&, boost::uniform_real< float > > rand( generator, dist );
95 for( std::size_t k = 0; k < sizeX * sizeY * sizeZ; ++k )
103 std::cout <<
"iteration: " << iter << std::endl;
106 for( std::size_t k = 0; k <
m_threads.size(); ++k )
108 m_threads[ k ]->setTextureSize( sizeX, sizeY, sizeZ );
109 m_threads[ k ]->setSpotFactor( spotFactor );
110 m_threads[ k ]->setDiffusionConstants( d1, d2 );
111 m_threads[ k ]->setBufferPointers( &concentration1, &concentration2, &noise, &delta1, &delta2 );
115 for( std::size_t k = 0; k <
m_threads.size(); ++k )
121 for( std::size_t k = 0; k < sizeX * sizeY * sizeZ; ++k )
123 concentration1[ k ] += speed * delta1[ k ];
124 concentration2[ k ] += speed * delta2[ k ];
129 osg::ref_ptr< osg::Image > img =
new osg::Image;
130 img->allocateImage( sizeX, sizeY, sizeZ, GL_LUMINANCE, GL_UNSIGNED_BYTE );
133 float c1min = *std::min_element( concentration1.begin(), concentration1.end() );
134 float c1max = *std::max_element( concentration1.begin(), concentration1.end() );
137 for( std::size_t k = 0; k < sizeX * sizeY * sizeZ; ++k )
139 img->data()[ k ] = 255.0f * ( concentration1[ k ] - c1min ) / ( c1max - c1min );
153 m_diffusionConstant1( 0.5 ),
154 m_diffusionConstant2( 0.5 )
164 WPrecond( d1 >= 0.0 && d1 <= 1.0,
"" );
165 WPrecond( d2 >= 0.0 && d2 <= 1.0,
"" );
167 m_diffusionConstant1 = d1;
168 m_diffusionConstant2 = d2;
173 WPrecond( spotFactor > 0.0,
"" );
175 m_spotFactor = spotFactor;
180 WPrecond( sizeX > 0,
"" );
181 WPrecond( sizeY > 0,
"" );
182 WPrecond( sizeZ > 0,
"" );
191 WPrecond( m_concentration1 != 0,
"Invalid pointer!" );
192 WPrecond( m_concentration2 != 0,
"Invalid pointer!" );
193 WPrecond( m_noise != 0,
"Invalid pointer!" );
194 WPrecond( m_delta1 != 0,
"Invalid pointer!" );
195 WPrecond( m_delta2 != 0,
"Invalid pointer!" );
197 std::size_t
const numVoxels = m_sizeX * m_sizeY * m_sizeZ;
199 std::size_t start = m_id * ( numVoxels / m_maxThreads );
200 std::size_t end = ( m_id + 1 ) * ( numVoxels / m_maxThreads );
202 if( m_id == m_maxThreads - 1 )
207 for( std::size_t idx = start; idx < end; ++idx )
209 std::size_t i = idx % m_sizeX;
210 std::size_t j = ( idx / m_sizeX ) % m_sizeY;
211 std::size_t k = ( idx / m_sizeX ) / m_sizeY;
213 std::size_t iNext = ( i + 1 ) % m_sizeX;
214 std::size_t iPrev = ( i + m_sizeX - 1 ) % m_sizeX;
216 std::size_t jNext = ( j + 1 ) % m_sizeY;
217 std::size_t jPrev = ( j + m_sizeY - 1 ) % m_sizeY;
219 std::size_t kNext = ( k + 1 ) % m_sizeZ;
220 std::size_t kPrev = ( k + m_sizeZ - 1 ) % m_sizeZ;
224 dc1 += ( *m_concentration1 )[ iPrev + j * m_sizeX + k * m_sizeX * m_sizeY ];
225 dc1 += ( *m_concentration1 )[ iNext + j * m_sizeX + k * m_sizeX * m_sizeY ];
226 dc1 += ( *m_concentration1 )[ i + jPrev * m_sizeX + k * m_sizeX * m_sizeY ];
227 dc1 += ( *m_concentration1 )[ i + jNext * m_sizeX + k * m_sizeX * m_sizeY ];
228 dc1 += ( *m_concentration1 )[ i + j * m_sizeX + kPrev * m_sizeX * m_sizeY ];
229 dc1 += ( *m_concentration1 )[ i + j * m_sizeX + kNext * m_sizeX * m_sizeY ];
230 dc1 -= 6.0f * ( *m_concentration1 )[ idx ];
233 dc2 += ( *m_concentration2 )[ iPrev + j * m_sizeX + k * m_sizeX * m_sizeY ];
234 dc2 += ( *m_concentration2 )[ iNext + j * m_sizeX + k * m_sizeX * m_sizeY ];
235 dc2 += ( *m_concentration2 )[ i + jPrev * m_sizeX + k * m_sizeX * m_sizeY ];
236 dc2 += ( *m_concentration2 )[ i + jNext * m_sizeX + k * m_sizeX * m_sizeY ];
237 dc2 += ( *m_concentration2 )[ i + j * m_sizeX + kPrev * m_sizeX * m_sizeY ];
238 dc2 += ( *m_concentration2 )[ i + j * m_sizeX + kNext * m_sizeX * m_sizeY ];
239 dc2 -= 6.0f * ( *m_concentration2 )[ idx ];
242 ( *m_delta1 )[ idx ] = m_spotFactor * ( 16.0f - ( *m_concentration1 )[ idx ] * ( *m_concentration2 )[ idx ] ) + m_diffusionConstant1 * dc1;
243 ( *m_delta2 )[ idx ] = m_spotFactor *
244 ( ( *m_concentration1 )[ idx ] * ( *m_concentration2 )[ idx ]
245 - ( *m_concentration2 )[ idx ] - ( *m_noise )[ idx ] )
246 + m_diffusionConstant2 * dc2;
251 std::vector< float >
const* concentration2,
252 std::vector< float >
const* noise,
253 std::vector< float >* delta1,
254 std::vector< float >* delta2 )
256 WPrecond( concentration1 != 0,
"Invalid pointer!" );
257 WPrecond( concentration2 != 0,
"Invalid pointer!" );
258 WPrecond( noise != 0,
"Invalid pointer!" );
259 WPrecond( delta1 != 0,
"Invalid pointer!" );
260 WPrecond( delta2 != 0,
"Invalid pointer!" );
262 m_concentration1 = concentration1;
263 m_concentration2 = concentration2;
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
Base class for all classes needing to be executed in a separate thread.
The thread calculating the Turing concentration diffusion in a given range.
TextureThread(std::size_t id, std::size_t max)
Create a calculation thread.
~TextureThread()
Destructor.
void setDiffusionConstants(float d1, float d2)
Diffusion constants according to Turing Reaction Diffusion algorithm.
virtual void threadMain()
The actual thread function running the algorithm.
void setBufferPointers(std::vector< float > const *concentration1, std::vector< float > const *concentration2, std::vector< float > const *noise, std::vector< float > *delta1, std::vector< float > *delta2)
Define the memory to work in.
void setTextureSize(std::size_t sizeX, std::size_t sizeY, std::size_t sizeZ)
Target texture size.
void setSpotFactor(float spotFactor)
The factor influencing size and shape of a spot.
WTuringTextureCreator(std::size_t numThreads=boost::thread::hardware_concurrency())
Constructor.
void setSpotIrregularity(float irr)
The irregularity of the spots.
~WTuringTextureCreator()
Destructor.
void setNumIterations(std::size_t iter)
The number of iterations to use for calculating the texture.
std::vector< std::shared_ptr< TextureThread > > m_threads
The thread pool.
float m_numIterations
Number of iterations.
float m_spotSize
Spot size.
void setSpotSize(float size)
Define the size of the spots inside the texture.
float m_spotIrregularity
Spot irregularity.
osg::ref_ptr< WGETexture3D > create(std::size_t sizeX, std::size_t sizeY, std::size_t sizeZ)
Create the Turing noise texture of arbitrary size.