00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <algorithm>
00026 #include <iostream>
00027 #include <sstream>
00028 #include <string>
00029
00030 #include "../common/WLogger.h"
00031 #include "WGETextureUtils.h"
00032 #include "exceptions/WGESignalSubscriptionFailed.h"
00033
00034 #include "WGEColormapping.h"
00035
00036
00037 boost::shared_ptr< WGEColormapping > WGEColormapping::m_instance = boost::shared_ptr< WGEColormapping >();
00038
00039
00040
00041
00042
00043
00044
00045 void setDefines( osg::ref_ptr< WGEShader > shader, size_t start = 0 )
00046 {
00047
00048 for( size_t unit = 0; unit < wge::getMaxTexUnits(); ++unit )
00049 {
00050
00051 if( unit < wge::getMaxTexUnits() - start )
00052 {
00053 shader->setDefine( "Colormap" + boost::lexical_cast< std::string >( unit ) + "Enabled", true );
00054 shader->setDefine( "Colormap" + boost::lexical_cast< std::string >( unit ) + "Unit", start + unit );
00055 }
00056 }
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066 void setPreTransform( osg::ref_ptr< WGEShader > shader, osg::Matrixd preTransform )
00067 {
00068 std::ostringstream out;
00069 out << "mat4( ";
00070 const osg::Matrixd::value_type* m = preTransform.ptr();
00071
00072 out.precision( 10 );
00073 out.setf( std::ios::fixed, std::ios::floatfield );
00074
00075
00076 for( size_t i = 0; i < 15; ++i )
00077 {
00078 out << m[ i ] << ", ";
00079 }
00080 out << m[ 15 ] << " )";
00081
00082
00083 shader->setDefine( "ColormapPreTransform", out.str() );
00084 }
00085
00086 WGEColormapping::WGEColormapping():
00087 m_callback( new WGEFunctorCallback< osg::Node >( boost::bind( &WGEColormapping::callback, this, _1 ) ) )
00088 {
00089
00090 m_textures.getChangeCondition()->subscribeSignal( boost::bind( &WGEColormapping::textureUpdate, this ) );
00091 m_boundingBox.getWriteTicket()->get().set( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
00092 }
00093
00094 WGEColormapping::~WGEColormapping()
00095 {
00096
00097 }
00098
00099 boost::shared_ptr< WGEColormapping > WGEColormapping::instance()
00100 {
00101 if( !m_instance )
00102 {
00103 m_instance = boost::shared_ptr< WGEColormapping >( new WGEColormapping() );
00104 }
00105
00106 return m_instance;
00107 }
00108
00109 void WGEColormapping::apply( osg::ref_ptr< osg::Node > node, osg::ref_ptr< WGEShader > shader, size_t startTexUnit )
00110 {
00111 instance()->applyInst( NodeList( 1, node ), WMatrix4d( WMatrix4d::identity() ), shader, startTexUnit );
00112 }
00113
00114 void WGEColormapping::apply( osg::ref_ptr< osg::Node > node, WMatrix4d preTransform, osg::ref_ptr< WGEShader > shader,
00115 size_t startTexUnit )
00116 {
00117 instance()->applyInst( NodeList( 1, node ), preTransform, shader, startTexUnit );
00118 }
00119
00120 void WGEColormapping::apply( NodeList nodes, WMatrix4d preTransform, osg::ref_ptr< WGEShader > shader, size_t startTexUnit )
00121 {
00122 instance()->applyInst( nodes, preTransform, shader, startTexUnit );
00123 }
00124
00125 void WGEColormapping::apply( NodeList nodes, osg::ref_ptr< WGEShader > shader, size_t startTexUnit )
00126 {
00127 instance()->applyInst( nodes, WMatrix4d( WMatrix4d::identity() ), shader, startTexUnit );
00128 }
00129
00130 void WGEColormapping::registerTexture( osg::ref_ptr< WGETexture3D > texture, std::string name )
00131 {
00132 instance()->registerTextureInst( texture, name );
00133 }
00134
00135 void WGEColormapping::deregisterTexture( osg::ref_ptr< WGETexture3D > texture )
00136 {
00137 instance()->deregisterTextureInst( texture );
00138 }
00139
00140 void WGEColormapping::replaceTexture( osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name )
00141 {
00142 instance()->replaceTextureInst( old, newTex, name );
00143 }
00144
00145 void WGEColormapping::applyInst( NodeList nodes, WMatrix4d preTransform, osg::ref_ptr< WGEShader > shader,
00146 size_t startTexUnit )
00147 {
00148
00149 osg::ref_ptr< WGEShader > s = shader;
00150 if( !s )
00151 {
00152
00153 s = new WGEShader( "WGEDefaultColormapper" );
00154 }
00155 setDefines( s, startTexUnit );
00156 setPreTransform( s, preTransform );
00157
00158
00159 for( NodeList::const_iterator i = nodes.begin(); i != nodes.end(); ++i )
00160 {
00161
00162 NodeInfo* info = new NodeInfo;
00163 info->m_rebind = true;
00164 info->m_texUnitStart = startTexUnit;
00165 info->m_preTransform = preTransform;
00166 m_nodeInfo.insert( std::make_pair( *i, info ) );
00167
00168 ( *i )->addUpdateCallback( m_callback );
00169
00170
00171 s->apply( *i );
00172 }
00173 }
00174
00175 void WGEColormapping::registerTextureInst( osg::ref_ptr< WGETexture3D > texture, std::string name )
00176 {
00177 wlog::debug( "WGEColormapping" ) << "Registering texture.";
00178 if( !m_textures.count( texture ) )
00179 {
00180 if( !name.empty() )
00181 {
00182 texture->name()->set( name );
00183 }
00184 m_textures.push_front( texture );
00185 updateBounds();
00186 m_registerSignal( texture );
00187 }
00188 }
00189
00190 void WGEColormapping::deregisterTextureInst( osg::ref_ptr< WGETexture3D > texture )
00191 {
00192 wlog::debug( "WGEColormapping" ) << "De-registering texture.";
00193 if( m_textures.count( texture ) )
00194 {
00195 m_textures.remove( texture );
00196 updateBounds();
00197 m_deregisterSignal( texture );
00198 }
00199 }
00200
00201 void WGEColormapping::replaceTextureInst( osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name )
00202 {
00203 wlog::debug( "WGEColormapping" ) << "Replacing texture.";
00204 if( !name.empty() )
00205 {
00206 newTex->name()->set( name );
00207 }
00208
00209
00210 if( m_textures.count( old ) )
00211 {
00212 m_textures.replace( old, newTex );
00213 updateBounds();
00214 m_replaceSignal( old, newTex );
00215 }
00216 else
00217 {
00218 registerTextureInst( newTex, name );
00219 }
00220 }
00221
00222 void WGEColormapping::updateBounds()
00223 {
00224 TextureContainerType::ReadTicket r = m_textures.getReadTicket();
00225 WSharedObject< WBoundingBox >::WriteTicket bbw = m_boundingBox.getWriteTicket();
00226
00227 bool first = true;
00228 for( TextureContainerType::ConstIterator iter = r->get().begin(); iter != r->get().end(); ++iter )
00229 {
00230 if( first )
00231 {
00232 bbw->get() = ( *iter )->getBoundingBox();
00233 first = false;
00234 }
00235 else
00236 {
00237 bbw->get().expandBy( ( *iter )->getBoundingBox() );
00238 }
00239 }
00240 }
00241
00242 WBoundingBox WGEColormapping::getBoundingBox() const
00243 {
00244 return m_boundingBox.getReadTicket()->get();
00245 }
00246
00247 void WGEColormapping::textureUpdate()
00248 {
00249 NodeInfoContainerType::WriteTicket w = m_nodeInfo.getWriteTicket();
00250 for( NodeInfoContainerType::Iterator iter = w->get().begin(); iter != w->get().end(); ++iter )
00251 {
00252 iter->second->m_rebind = true;
00253 }
00254 }
00255
00256 void WGEColormapping::callback( osg::Node* node )
00257 {
00258
00259 NodeInfoContainerType::ReadTicket r = m_nodeInfo.getReadTicket();
00260 NodeInfoContainerType::ConstIterator infoItem = r->get().find( node );
00261 if( infoItem == r->get().end() )
00262 {
00263 return;
00264 }
00265 r.reset();
00266
00267 NodeInfo* info = infoItem->second;
00268
00269
00270 if( info->m_rebind )
00271 {
00272 info->m_rebind = false;
00273
00274 size_t maxTexUnits = wge::getMaxTexUnits();
00275 wge::unbindTexture( node, info->m_texUnitStart, maxTexUnits - info->m_texUnitStart );
00276
00277 TextureContainerType::ReadTicket rt = m_textures.getReadTicket();
00278
00279
00280 size_t unit = info->m_texUnitStart;
00281 for( TextureContainerType::ConstIterator iter = rt->get().begin();
00282 ( unit < maxTexUnits ) && ( iter != rt->get().end() );
00283 ++iter )
00284 {
00285 wge::bindTexture( node, *iter, unit, "u_colormap" + boost::lexical_cast< std::string >( unit - info->m_texUnitStart ) );
00286 unit++;
00287 }
00288
00289 rt.reset();
00290 }
00291 }
00292
00293 bool WGEColormapping::moveDown( osg::ref_ptr< WGETexture3D > texture )
00294 {
00295 TextureContainerType::WriteTicket w = m_textures.getWriteTicket();
00296
00297
00298 TextureContainerType::Iterator iter = std::find( w->get().begin(), w->get().end(), texture );
00299 if( iter == w->get().end() )
00300 {
00301 return false;
00302 }
00303
00304
00305 if( iter + 1 == w->get().end() )
00306 {
00307 return false;
00308 }
00309
00310
00311 std::iter_swap( iter, iter + 1 );
00312
00313
00314 w.reset();
00315 m_sortSignal();
00316
00317 return true;
00318 }
00319
00320 bool WGEColormapping::moveUp( osg::ref_ptr< WGETexture3D > texture )
00321 {
00322 TextureContainerType::WriteTicket w = m_textures.getWriteTicket();
00323
00324
00325 TextureContainerType::Iterator iter = std::find( w->get().begin(), w->get().end(), texture );
00326 if( iter == w->get().end() )
00327 {
00328 return false;
00329 }
00330
00331
00332 if( iter == w->get().begin() )
00333 {
00334 return false;
00335 }
00336
00337
00338 std::iter_swap( iter, iter - 1 );
00339
00340
00341 w.reset();
00342 m_sortSignal();
00343
00344 return true;
00345 }
00346
00347 size_t WGEColormapping::size() const
00348 {
00349 return m_textures.size();
00350 }
00351
00352 boost::signals2::connection WGEColormapping::subscribeSignal( TextureListSignal signal, TextureRegisterHandler notifier )
00353 {
00354 switch( signal )
00355 {
00356 case Registered:
00357 return m_registerSignal.connect( notifier );
00358 case Deregistered:
00359 return m_deregisterSignal.connect( notifier );
00360 default:
00361 throw new WGESignalSubscriptionFailed( std::string( "Could not register TextureRegisterHandler to sort signal." ) );
00362 }
00363 }
00364
00365 boost::signals2::connection WGEColormapping::subscribeSignal( TextureListSignal signal, TextureReplaceHandler notifier )
00366 {
00367 switch( signal )
00368 {
00369 case Replaced:
00370 return m_replaceSignal.connect( notifier );
00371 default:
00372 throw new WGESignalSubscriptionFailed( std::string( "Could not register TextureReplaceHandler to signal." ) );
00373 }
00374 }
00375
00376 boost::signals2::connection WGEColormapping::subscribeSignal( TextureListSignal signal, TextureSortHandler notifier )
00377 {
00378 switch( signal )
00379 {
00380 case Sorted:
00381 return m_sortSignal.connect( notifier );
00382 default:
00383 throw new WGESignalSubscriptionFailed( std::string( "Could not register TextureSortHandler to register/deregister signal." ) );
00384 }
00385 }
00386
00387 WGEColormapping::TextureContainerType::ReadTicket WGEColormapping::getReadTicket()
00388 {
00389 return m_textures.getReadTicket();
00390 }
00391
00392 WCondition::SPtr WGEColormapping::getChangeCondition() const
00393 {
00394 return m_textures.getChangeCondition();
00395 }
00396