OpenWalnut  1.4.0
WGEColormapping.h
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 #ifndef WGECOLORMAPPING_H
00026 #define WGECOLORMAPPING_H
00027 
00028 #include <map>
00029 #include <string>
00030 #include <algorithm>
00031 #include <functional>
00032 #include <vector>
00033 
00034 #include <boost/signals2/signal.hpp>
00035 #include <boost/function.hpp>
00036 
00037 #include <osg/Node>
00038 
00039 #include "../common/WBoundingBox.h"
00040 #include "../common/WSharedSequenceContainer.h"
00041 #include "../common/WSharedAssociativeContainer.h"
00042 
00043 #include "callbacks/WGEFunctorCallback.h"
00044 
00045 #include "WGETexture.h"
00046 #include "shaders/WGEShader.h"
00047 
00048 
00049 /**
00050  * Class implements a manager for multiple 3D textures. They can be applied to arbitrary osg::Node. This allows very comfortable use of dataset
00051  * based colormapping. The only requirement is that your geometry/node needs to specify texture coordinates in Object Space. That means: the
00052  * texture coordinates equal the regular 3D grid of the texture.
00053  */
00054 class WGEColormapping // NOLINT
00055 {
00056 public:
00057     /**
00058      * The alias for a shared container.
00059      */
00060     typedef WSharedSequenceContainer< std::vector< osg::ref_ptr< WGETexture3D > > > TextureContainerType;
00061 
00062     /**
00063      * Iterator to access the texture list.
00064      */
00065     typedef TextureContainerType::Iterator TextureIterator;
00066 
00067     /**
00068      * Const iterator to access the texture list.
00069      */
00070     typedef TextureContainerType::ConstIterator TextureConstIterator;
00071 
00072     /**
00073      * The type of handler used for being notified about added textures.
00074      */
00075     typedef boost::function< void ( osg::ref_ptr< WGETexture3D > ) > TextureRegisterHandler;
00076 
00077     /**
00078      * The type of handler used for being notified about removed textures.
00079      */
00080     typedef TextureRegisterHandler TextureDeregisterHandler;
00081 
00082     /**
00083      * The type of handler used for being notified about replaced textures.
00084      */
00085     typedef boost::function< void ( osg::ref_ptr< WGETexture3D >, osg::ref_ptr< WGETexture3D > ) > TextureReplaceHandler;
00086 
00087     /**
00088      * The type of handler called whenever the texture list got resorted.
00089      */
00090     typedef boost::function< void ( void ) > TextureSortHandler;
00091 
00092     /**
00093      * Destructor.
00094      */
00095     virtual ~WGEColormapping();
00096 
00097     /**
00098      * Returns instance of the module factory to use to create modules.
00099      *
00100      * \return the running module factory.
00101      */
00102     static boost::shared_ptr< WGEColormapping > instance();
00103 
00104     /**
00105      * a bunch of nodes.
00106      */
00107     typedef std::vector< osg::ref_ptr< osg::Node > > NodeList;
00108 
00109     /**
00110      * Apply the colormapping to the specified node.
00111      *
00112      * \param node the node.
00113      * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
00114      * specified, a default shader is used.
00115      * \param preTransform Transformation matrix getting applied to your texture coordinates before applying texture matrices. This allows you to
00116      * specify any kind of texture coordinates as long as you use this matrix to transform them to the right space.
00117      * \param startTexUnit the first texture unit allowed to be used
00118      */
00119     static void apply( osg::ref_ptr< osg::Node > node, WMatrix4d preTransform = WMatrix4d::identity(),
00120                        osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
00121 
00122     /**
00123      * Apply the colormapping to a list of nodes using the same shader.
00124      *
00125      * \param nodes the node-list.
00126      * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
00127      * specified, a default shader is used.
00128      * \param preTransform Transformation matrix getting applied to your texture coordinates before applying texture matrices. This allows you to
00129      * specify any kind of texture coordinates as long as you use this matrix to transform them to the right space.
00130      * \param startTexUnit the first texture unit allowed to be used
00131      */
00132     static void apply( NodeList nodes, WMatrix4d preTransform = WMatrix4d::identity(),
00133                        osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
00134 
00135     /**
00136      * Apply the colormapping to the specified node.
00137      *
00138      * \param node the node.
00139      * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
00140      * specified, a default shader is used.
00141      * \param startTexUnit the first texture unit allowed to be used
00142      */
00143     static void apply( osg::ref_ptr< osg::Node > node, osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
00144 
00145     /**
00146      * Apply the colormapping to a list of nodes which all use the same shader.
00147      *
00148      * \param nodes the node list.
00149      * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
00150      * specified, a default shader is used.
00151      * \param startTexUnit the first texture unit allowed to be used
00152      */
00153     static void apply( NodeList nodes,
00154                        osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
00155 
00156     /**
00157      * Register the specified texture to the colormapper. The registered texture is the automatically applied to all users of WGEColormapping.
00158      * The texture gets inserted at the beginning of the texture list.
00159      *
00160      * \param texture the texture to add
00161      * \param name the name of the texture to add
00162      */
00163     static void registerTexture( osg::ref_ptr< WGETexture3D > texture, std::string name = "" );
00164 
00165     /**
00166      * De-register the specified texture to the colormapper. The texture is the automatically removed from all users of WGEColormapping. If the
00167      * texture is not in the list, nothing happens.
00168      *
00169      * \param texture the texture to remove
00170      */
00171     static void deregisterTexture( osg::ref_ptr< WGETexture3D > texture );
00172 
00173     /**
00174      * Replaces the specified texture with the given new one. If the old texture does not exist, the new one gets inserted at the front of the
00175      * list as \ref registerTexture does.
00176      *
00177      * \param old the texture to remove
00178      * \param newTex the new texture to put at the position of the old one
00179      * \param name the name of the texture.
00180      */
00181     static void replaceTexture( osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name = "" );
00182 
00183     /**
00184      * Resorts the texture list using the specified comparator.
00185      *
00186      * \tparam Comparator the comparator type. Usually a boost::function or class providing the operator().
00187      * \param comp the comparator
00188      */
00189     template < typename Comparator >
00190     void sort( Comparator comp );
00191 
00192     /**
00193      * Resorts the texture list using the specified comparator using a stable sorting algorithm.
00194      *
00195      * \tparam Comparator the comparator type. Usually a boost::function or class providing the operator().
00196      * \param comp the comparator
00197      */
00198     template < typename Comparator >
00199     void stableSort( Comparator comp );
00200 
00201     /**
00202      * Sort the texture list by the indices that have been stored in each texture's sortIndex.
00203      */
00204     void sortByIndex();
00205 
00206     /**
00207      * This function sets the index of a texture in the list to this texture's WGETexture::sortIndex(). This can be used later using
00208      * sortByIndex().
00209      */
00210     void setSortIndices();
00211 
00212     /**
00213      * Reset all sort indices. This can be useful when loading new project files with new sort indices.
00214      */
00215     void resetSortIndices();
00216 
00217     /**
00218      * Move the specified texture up in the list, directly to the top. Causes the sort signal to fire.
00219      *
00220      * \param texture the texture swapped with its ascendant
00221      * \return true if swap was successful. False if not (texture not found, texture already at beginning).
00222      */
00223     bool moveToTop( osg::ref_ptr< WGETexture3D > texture );
00224 
00225     /**
00226      * Move the specified texture down in the list, directly to the bottom. Causes the sort signal to fire.
00227      *
00228      * \param texture the texture swapped with its descendant
00229      * \return true if swap was successful. False if not (texture not found, texture already at end).
00230      */
00231     bool moveToBottom( osg::ref_ptr< WGETexture3D > texture );
00232 
00233     /**
00234      * Move the specified texture one item up in the list. Causes the sort signal to fire.
00235      *
00236      * \param texture the texture swapped with its ascendant
00237      * \return true if swap was successful. False if not (texture not found, texture already at beginning).
00238      */
00239     bool moveUp( osg::ref_ptr< WGETexture3D > texture );
00240 
00241     /**
00242      * Move the specified texture one item down in the list. Causes the sort signal to fire.
00243      *
00244      * \param texture the texture swapped with its descendant
00245      *
00246      * \return true if swap was successful. False if not (texture not found, texture already at end).
00247      */
00248     bool moveDown( osg::ref_ptr< WGETexture3D > texture );
00249 
00250     /**
00251      * Move the texture to the specified index. If the texture is not in the list, nothing happens.
00252      *
00253      * \param texture the texture to move
00254      * \param idx the target index
00255      *
00256      * \return true if the operation was successful.
00257      */
00258     bool moveTo( osg::ref_ptr< WGETexture3D > texture, size_t idx );
00259 
00260     /**
00261      * Counts the number of textures in the colormapper.
00262      *
00263      * \return the number of textures.
00264      */
00265     size_t size() const;
00266 
00267     /**
00268      * Possible signals that can be subscribed for being notified about texture list changes.
00269      */
00270     typedef enum
00271     {
00272         Registered = 0, //!< texture got added
00273         Deregistered,   //!< texture got removed
00274         Replaced,       //!< texture got replaced
00275         Sorted          //!< texture list was resorted
00276     }
00277     TextureListSignal;
00278 
00279     /**
00280      * Subscribe to the specified signal. See \ref TextureListSignal for details about their meaning.
00281      *
00282      * \param signal the signal to subscribe
00283      * \param notifier the notifier
00284      *
00285      * \return the connection. Keep this and disconnect it properly!
00286      */
00287     boost::signals2::connection subscribeSignal( TextureListSignal signal, TextureRegisterHandler notifier );
00288 
00289     /**
00290      * Subscribe to the specified signal. See \ref TextureListSignal for details about their meaning.
00291      *
00292      * \param signal the signal to subscribe
00293      * \param notifier the notifier
00294      *
00295      * \return the connection. Keep this and disconnect it properly!
00296      */
00297     boost::signals2::connection subscribeSignal( TextureListSignal signal, TextureReplaceHandler notifier );
00298 
00299     /**
00300      * Subscribe to the specified signal. See \ref TextureListSignal for details about their meaning.
00301      *
00302      * \param signal the signal to subscribe
00303      * \param notifier the notifier
00304      *
00305      * \return the connection. Keep this and disconnect it properly!
00306      */
00307     boost::signals2::connection subscribeSignal( TextureListSignal signal, TextureSortHandler notifier );
00308 
00309     /**
00310      * Returns a read ticket to the texture array. Useful to iterate the textures.
00311      *
00312      * \return the read ticket
00313      */
00314     TextureContainerType::ReadTicket getReadTicket();
00315 
00316     /**
00317      * This returns the bounding box of all the data textures. This is very useful if you implement an universal color-mapped exploration tool.
00318      * It returns a copy of the current bounding box. Please note that this can change any moment.
00319      *
00320      * \return the bounding box.
00321      */
00322     WBoundingBox getBoundingBox() const;
00323 
00324     /**
00325      * Returns the condition firing if the texture list changes (sort, replace, add or remove). If you are interested in a certain event only,
00326      * use \ref subscribeSignal.
00327      *
00328      * \return the change condition
00329      */
00330     WCondition::SPtr getChangeCondition() const;
00331 
00332 protected:
00333     /**
00334      * Default constructor.
00335      */
00336     WGEColormapping();
00337 
00338     /**
00339      * Apply the colormapping to the specified nodes.
00340      *
00341      * \param nodes the nodes.
00342      * \param preTransform Transformation matrix getting applied to your texture coordinates before applying texture matrices. This allows you to
00343      * specify any kind of texture coordinates as long as you use this matrix to transform them to the right space.
00344      * \param shader the shader to use for colormapping. Provide your own shader here to let WGEColormap set some defines needed. If not
00345      * specified, a default shader is used.
00346      * \param startTexUnit the first texture unit allowed to be used
00347      */
00348     void applyInst( NodeList nodes, WMatrix4d preTransform = WMatrix4d::identity(),
00349                     osg::ref_ptr< WGEShader > shader = osg::ref_ptr< WGEShader >(), size_t startTexUnit = 0 );
00350 
00351     /**
00352      * Register the specified texture to the colormapper. The registered texture is the automatically applied to all users of WGEColormapping.
00353      *
00354      * \param texture the texture to add
00355      * \param name the name of the texture.
00356      */
00357     void registerTextureInst( osg::ref_ptr< WGETexture3D > texture, std::string name );
00358 
00359     /**
00360      * De-register the specified texture to the colormapper. The texture is the automatically removed from all users of WGEColormapping.
00361      *
00362      * \param texture the texture to remove
00363      */
00364     void deregisterTextureInst( osg::ref_ptr< WGETexture3D > texture );
00365 
00366     /**
00367      * Replaces the specified texture with the given new one. If the old texture does not exist, the new one gets inserted at the front of the
00368      * list as \ref registerTexture does.
00369      *
00370      * \param old the texture to remove
00371      * \param newTex the new texture to put at the position of the old one
00372      * \param name the name of the texture.
00373      */
00374     void replaceTextureInst( osg::ref_ptr< WGETexture3D > old, osg::ref_ptr< WGETexture3D > newTex, std::string name = "" );
00375 
00376     /**
00377      * This callback handles all the updates needed. It is called by the callback instance every update cycle for each node using this
00378      * WGEColormapping instance.
00379      *
00380      * \param node
00381      */
00382     void callback( osg::Node* node );
00383 
00384     /**
00385      * Called whenever the texture list is updated.
00386      */
00387     void textureUpdate();
00388 
00389 private:
00390     /**
00391      * Singleton instance of WGEColormapping
00392      */
00393     static boost::shared_ptr< WGEColormapping > m_instance;
00394 
00395     /**
00396      * The textures managed by this instance.
00397      */
00398     TextureContainerType m_textures;
00399 
00400     /**
00401      * Simple structure to store some additional node-related info like texture units and so on.
00402      */
00403     struct NodeInfo
00404     {
00405         bool   m_rebind;        //!< true if the node has not been callback'ed before
00406         size_t m_texUnitStart;  //!< the start index of the texture unit to use
00407         WMatrix4d m_preTransform; //!< matrix used for transforming arbitrary texture coordinates to the proper space.
00408     };
00409 
00410     /**
00411      * The alias for a shared container with a set of node-nodeInfo pairs
00412      */
00413     typedef WSharedAssociativeContainer< std::map< osg::Node*, NodeInfo*, std::less< osg::Node* > > > NodeInfoContainerType;
00414 
00415     /**
00416      * This map is needed to keep track of several node specific settings
00417      */
00418     NodeInfoContainerType m_nodeInfo;
00419 
00420     /**
00421      * Called whenever a texture got registered.
00422      */
00423     boost::signals2::signal< void( osg::ref_ptr< WGETexture3D > ) > m_registerSignal;
00424 
00425     /**
00426      * Called whenever a texture got removed.
00427      */
00428     boost::signals2::signal< void( osg::ref_ptr< WGETexture3D > ) > m_deregisterSignal;
00429 
00430     /**
00431      * Called whenever a texture got replaced.
00432      */
00433     boost::signals2::signal< void( osg::ref_ptr< WGETexture3D >, osg::ref_ptr< WGETexture3D > ) > m_replaceSignal;
00434 
00435     /**
00436      * Called whenever the texture list got resorted
00437      */
00438     boost::signals2::signal< void( void ) > m_sortSignal;
00439 
00440     /**
00441      * The bounding box of all the textures.
00442      */
00443     WSharedObject< WBoundingBox > m_boundingBox;
00444 
00445     /**
00446      * Updates the bounding box information. This is called for every write-update in m_textures.
00447      */
00448     void updateBounds();
00449 };
00450 
00451 template < typename Comparator >
00452 void WGEColormapping::sort( Comparator comp )
00453 {
00454     m_textures.sort< Comparator >( comp );
00455 }
00456 
00457 template < typename Comparator >
00458 void WGEColormapping::stableSort( Comparator comp )
00459 {
00460     m_textures.stableSort< Comparator >( comp );
00461 }
00462 
00463 #endif  // WGECOLORMAPPING_H
00464