OpenWalnut
1.4.0
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <algorithm> 00026 #include <vector> 00027 00028 #include <boost/random.hpp> 00029 00030 #include "../common/exceptions/WPreconditionNotMet.h" 00031 00032 #include "WGETexture.h" 00033 00034 #include "WGETextureUtils.h" 00035 00036 void wge::unbindTexture( osg::ref_ptr< osg::Node > node, size_t unit, size_t count ) 00037 { 00038 for( size_t i = unit; i < unit + count; ++i ) 00039 { 00040 node->getOrCreateStateSet()->removeTextureAttribute( i, osg::StateAttribute::TEXTURE ); 00041 node->getOrCreateStateSet()->removeTextureAttribute( i, osg::StateAttribute::TEXMAT ); 00042 } 00043 } 00044 00045 size_t wge::getMaxTexUnits() 00046 { 00047 // GLint ret; 00048 // glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ret ); 00049 // 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 00050 // texture coordinate attributes. 00051 return 8; 00052 } 00053 00054 osg::ref_ptr< WGETexture< osg::Texture1D > > wge::genWhiteNoiseTexture( size_t sizeX, size_t channels ) 00055 { 00056 // put it into an texture 00057 osg::ref_ptr< WGETexture1D > randTexture = new WGETexture1D( genWhiteNoiseImage( sizeX, 1, 1, channels ) ); 00058 randTexture->setTextureWidth( sizeX ); 00059 randTexture->setFilter( osg::Texture1D::MIN_FILTER, osg::Texture1D::NEAREST ); 00060 randTexture->setFilter( osg::Texture1D::MAG_FILTER, osg::Texture1D::NEAREST ); 00061 randTexture->setWrap( osg::Texture1D::WRAP_S, osg::Texture1D::REPEAT ); 00062 00063 return randTexture; 00064 } 00065 00066 osg::ref_ptr< WGETexture< osg::Texture2D > > wge::genWhiteNoiseTexture( size_t sizeX, size_t sizeY, size_t channels ) 00067 { 00068 osg::ref_ptr< WGETexture2D > randTexture = new WGETexture2D( genWhiteNoiseImage( sizeX, sizeY, 1, channels ) ); 00069 randTexture->setTextureWidth( sizeX ); 00070 randTexture->setTextureHeight( sizeY ); 00071 randTexture->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST ); 00072 randTexture->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST ); 00073 randTexture->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 00074 randTexture->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 00075 00076 return randTexture; 00077 } 00078 00079 osg::ref_ptr< WGETexture< osg::Texture3D > > wge::genWhiteNoiseTexture( size_t sizeX, size_t sizeY, size_t sizeZ, size_t channels ) 00080 { 00081 osg::ref_ptr< WGETexture3D > randTexture = new WGETexture3D( genWhiteNoiseImage( sizeX, sizeY, sizeZ, channels ) ); 00082 randTexture->setTextureWidth( sizeX ); 00083 randTexture->setTextureHeight( sizeY ); 00084 randTexture->setTextureDepth( sizeZ ); 00085 randTexture->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST ); 00086 randTexture->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST ); 00087 randTexture->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT ); 00088 randTexture->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT ); 00089 randTexture->setWrap( osg::Texture2D::WRAP_R, osg::Texture2D::REPEAT ); 00090 00091 return randTexture; 00092 } 00093 00094 osg::ref_ptr< osg::Image > wge::genWhiteNoiseImage( size_t sizeX, size_t sizeY, size_t sizeZ, size_t channels ) 00095 { 00096 WPrecond( ( channels == 1 ) || ( channels == 3 ) || ( channels == 4 ), "Invalid number of channels. Valid are: 1, 3 and 4." ); 00097 00098 // create an osg::Image at first. 00099 std::srand( time( 0 ) ); 00100 osg::ref_ptr< osg::Image > randImage = new osg::Image(); 00101 GLenum type = GL_LUMINANCE; 00102 if( channels == 3 ) 00103 { 00104 type = GL_RGB; 00105 } 00106 else if( channels == 4 ) 00107 { 00108 type = GL_RGBA; 00109 } 00110 randImage->allocateImage( sizeX, sizeY, sizeZ, type, GL_UNSIGNED_BYTE ); 00111 unsigned char *randomLuminance = randImage->data(); // should be 4 megs 00112 for( size_t i = 0; i < channels * sizeX * sizeY * sizeZ; ++i ) 00113 { 00114 // - stylechecker says "use rand_r" but I am not sure about portability. 00115 unsigned char r = static_cast< unsigned char >( std::rand() % 255 ); // NOLINT - no we want std::rand instead of rand_r 00116 randomLuminance[ i ] = r; 00117 } 00118 00119 return randImage; 00120 } 00121 00122 osg::ref_ptr< WGETexture< osg::Texture3D > > wge::genTuringNoiseTexture( std::size_t sizeX, std::size_t sizeY, 00123 std::size_t sizeZ, std::size_t channels ) 00124 { 00125 WPrecond( channels == 1 || channels == 3 || channels == 4, "Invalid number of channels. Valid are: 1, 3 and 4." ); 00126 00127 // some constants, maybe change to parameters 00128 float const spotIrregularity = 0.05f; // 0.0 - 1.0 00129 std::size_t const iterations = 200; 00130 float const spotSize = 0.5; 00131 float const spotFactor = ( 0.02f + 0.58f * ( 1.0f - spotSize ) ) / 15.0f; 00132 float const d1 = 0.125f; 00133 float const d2 = 0.03125f; 00134 float const speed = 1.0f; 00135 00136 osg::ref_ptr< osg::Image > img = new osg::Image; 00137 GLenum type = GL_LUMINANCE; 00138 if( channels == 3 ) 00139 { 00140 type = GL_RGB; 00141 } 00142 else if( channels == 4 ) 00143 { 00144 type = GL_RGBA; 00145 } 00146 00147 std::vector< float > concentration1( sizeX * sizeY * sizeZ, 4.0 ); 00148 std::vector< float > concentration2( sizeX * sizeY * sizeZ, 4.0 ); 00149 std::vector< float > delta1( sizeX * sizeY * sizeZ, 0.0 ); 00150 std::vector< float > delta2( sizeX * sizeY * sizeZ, 0.0 ); 00151 std::vector< float > noise( sizeX * sizeY * sizeZ ); 00152 00153 boost::mt19937 generator( std::time( 0 ) ); 00154 00155 float noiseRange = 0.1f + 4.9f * spotIrregularity; 00156 00157 boost::uniform_real< float > dist( 12.0 - noiseRange, 12.0 + noiseRange ); 00158 boost::variate_generator< boost::mt19937&, boost::uniform_real< float > > rand( generator, dist ); 00159 00160 // initialization step 00161 for( std::size_t i = 0; i < sizeX; ++i ) 00162 { 00163 for( std::size_t j = 0; j < sizeY; ++j ) 00164 { 00165 for( std::size_t k = 0; k < sizeZ; ++k ) 00166 { 00167 std::size_t idx = i + j * sizeX + k * sizeX * sizeY; 00168 noise[ idx ] = rand(); 00169 } 00170 } 00171 } 00172 00173 // iteration 00174 for( std::size_t iter = 0; iter < iterations; ++iter ) 00175 { 00176 std::cout << "iterations: " << iter << std::endl; 00177 00178 for( std::size_t i = 0; i < sizeX; ++i ) 00179 { 00180 std::size_t iNext = ( i + 1 ) % sizeX; 00181 std::size_t iPrev = ( i + sizeX - 1 ) % sizeX; 00182 00183 for( std::size_t j = 0; j < sizeY; ++j ) 00184 { 00185 std::size_t jNext = ( j + 1 ) % sizeY; 00186 std::size_t jPrev = ( j + sizeY - 1 ) % sizeY; 00187 00188 for( std::size_t k = 0; k < sizeZ; ++k ) 00189 { 00190 std::size_t kNext = ( k + 1 ) % sizeZ; 00191 std::size_t kPrev = ( k + sizeZ - 1 ) % sizeZ; 00192 00193 std::size_t idx = i + j * sizeX + k * sizeX * sizeY; 00194 00195 // estimate change in concentrations 00196 // we use a 3d laplace filter here instead of the 2d filter as in Eichelbaum et al. 00197 float dc1 = 0.0; 00198 dc1 += concentration1[ iPrev + j * sizeX + k * sizeX * sizeY ]; 00199 dc1 += concentration1[ iNext + j * sizeX + k * sizeX * sizeY ]; 00200 dc1 += concentration1[ i + jPrev * sizeX + k * sizeX * sizeY ]; 00201 dc1 += concentration1[ i + jNext * sizeX + k * sizeX * sizeY ]; 00202 dc1 += concentration1[ i + j * sizeX + kPrev * sizeX * sizeY ]; 00203 dc1 += concentration1[ i + j * sizeX + kNext * sizeX * sizeY ]; 00204 dc1 -= 6.0f * concentration1[ idx ]; 00205 00206 float dc2 = 0.0; 00207 dc2 += concentration2[ iPrev + j * sizeX + k * sizeX * sizeY ]; 00208 dc2 += concentration2[ iNext + j * sizeX + k * sizeX * sizeY ]; 00209 dc2 += concentration2[ i + jPrev * sizeX + k * sizeX * sizeY ]; 00210 dc2 += concentration2[ i + jNext * sizeX + k * sizeX * sizeY ]; 00211 dc2 += concentration2[ i + j * sizeX + kPrev * sizeX * sizeY ]; 00212 dc2 += concentration2[ i + j * sizeX + kNext * sizeX * sizeY ]; 00213 dc2 -= 6.0f * concentration2[ idx ]; 00214 00215 // diffusion 00216 delta1[ idx ] = spotFactor * ( 16.0f - concentration1[ idx ] * concentration2[ idx ] ) + d1 * dc1; 00217 delta2[ idx ] = spotFactor * ( concentration1[ idx ] * concentration2[ idx ] - concentration2[ idx ] - noise[ idx ] ) + d2 * dc2; 00218 } 00219 } 00220 } 00221 00222 for( std::size_t i = 0; i < sizeX; ++i ) 00223 { 00224 for( std::size_t j = 0; j < sizeY; ++j ) 00225 { 00226 for( std::size_t k = 0; k < sizeZ; ++k ) 00227 { 00228 std::size_t idx = i + j * sizeX + k * sizeX * sizeY; 00229 00230 concentration1[ idx ] += speed * delta1[ idx ]; 00231 concentration2[ idx ] += speed * delta2[ idx ]; 00232 } 00233 } 00234 } 00235 } 00236 00237 img->allocateImage( sizeX, sizeY, sizeZ, type, GL_UNSIGNED_BYTE ); 00238 00239 // find min and max 00240 float c1min = *std::min_element( concentration1.begin(), concentration1.end() ); 00241 float c1max = *std::max_element( concentration1.begin(), concentration1.end() ); 00242 00243 // copy to image 00244 for( std::size_t i = 0; i < sizeX; ++i ) 00245 { 00246 for( std::size_t j = 0; j < sizeY; ++j ) 00247 { 00248 for( std::size_t k = 0; k < sizeZ; ++k ) 00249 { 00250 std::size_t idx = i + j * sizeX + k * sizeX * sizeY; 00251 img->data()[ idx ] = 255.0f * ( concentration1[ idx ] - c1min ) / ( c1max - c1min ); 00252 } 00253 } 00254 } 00255 00256 return osg::ref_ptr< WGETexture< osg::Texture3D > >( new WGETexture< osg::Texture3D >( img ) ); 00257 } 00258