OverlayNode 8.02 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGSIM_OVERLAYNODE
#define OSGSIM_OVERLAYNODE 1

#include <osg/buffered_value>
#include <osg/Camera>
#include <osg/Texture2D>
#include <osg/TexGenNode>
#include <osg/Geode>

#include <osgUtil/CullVisitor>

#include <osgSim/Export>

namespace osgSim {

/** OverlayNode is for creating texture overlays on scenes, with the overlay texture being generated
  * by pre rendering an Overlay Subgraph to a texture, then projecting this resulting texture on the scene.*/
class OSGSIM_EXPORT OverlayNode : public osg::Group
{
    public :

        enum OverlayTechnique
        {
            OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY,
            VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY,
            VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY
        };

        OverlayNode(OverlayTechnique technique=OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY);

        OverlayNode(const OverlayNode& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
            
        META_Node(osgSim, OverlayNode);
        
        virtual void traverse(osg::NodeVisitor& nv);


        void setOverlayTechnique(OverlayTechnique technique);
        OverlayTechnique getOverlayTechnique() const { return _overlayTechnique; }

        /** Set the implementation to be used when creating the overlay texture. */
        void setRenderTargetImplementation(osg::Camera::RenderTargetImplementation impl);

        /** Set the overlay subgraph which will be rendered to texture.*/
        void setOverlaySubgraph(osg::Node* node);
        
        /** Get the overlay subgraph which will be rendered to texture.*/
        osg::Node* getOverlaySubgraph() { return _overlaySubgraph.get(); }

        /** Get the const overlay subgraph which will be render to texture.*/
        const osg::Node* getOverlaySubgraph() const { return _overlaySubgraph.get(); }
        

        /** Inform the OverlayNode that the overlay texture needs to be updated.*/
        void dirtyOverlayTexture();
        
        /** Set whether the OverlayNode should update the overlay texture on every frame.*/
        void setContinuousUpdate(bool update) { _continuousUpdate = update; }

        /** Get whether the OverlayNode should update the overlay texture on every frame.*/
        bool getContinuousUpdate() const { return _continuousUpdate; }

        /** Set the base height that the overlay subgraph will be projected down to.
          * Normally you'll set this to just below ground level, if you set it too high
          * then the overlay texture can end up being clipped in certain viewing directions,
          * while if its too low then there will be a limit to how close you can get to the
          * terrain before pixaltion becomes an issue.*/
        void setOverlayBaseHeight(double baseHeight) { _overlayBaseHeight = baseHeight; }

        /** Get the base height that the overlay subgraph will be projected down to.*/
        double getOverlayBaseHeight() const { return _overlayBaseHeight; }

        /** Set the clear color to use when rendering the overlay subgraph.*/
        void setOverlayClearColor(const osg::Vec4& color) { _overlayClearColor = color; }

        /** Get the clear color to use when rendering the overlay subgraph.*/
        const osg::Vec4& getOverlayClearColor() const { return _overlayClearColor; }

        /** Set the TexEnv mode used to combine the overlay texture with the base color/texture of the OverlayNode's decorate subgraph.*/
        void setTexEnvMode(GLenum mode);
        
        /** Get the TexEnv mode used to combine the overlay texture with the base color/texture of the OverlayNode's decorate subgraph.*/
        GLenum getTexEnvMode() const { return _texEnvMode; }

        /** Set the texture unit that the texture should be assigned to.*/
        void setOverlayTextureUnit(unsigned int unit);

        /** Get the texture unit that the texture should be assigned to.*/
        unsigned int getOverlayTextureUnit() const { return _textureUnit; }
        
        /** Set the texture size hint. The size hint is used to request a texture of specified size.*/
        void setOverlayTextureSizeHint(unsigned int size);

        /** Get the texture size hint.*/
        unsigned int getOverlayTextureSizeHint() const { return _textureSizeHint; }
        
        
        /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
        virtual void setThreadSafeRefUnref(bool threadSafe);

        /** Resize any per context GLObject buffers to specified size. */
        virtual void resizeGLObjectBuffers(unsigned int /*maxSize*/);

        /** If State is non-zero, this function releases any associated OpenGL objects for
           * the specified graphics context. Otherwise, releases OpenGL objexts
           * for all graphics contexts. */
        virtual void releaseGLObjects(osg::State* = 0) const;

    protected :

        virtual ~OverlayNode() {}
        
        void init();
        void init_OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY();
        void init_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY();
        void init_VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY();
        
        void traverse_OBJECT_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(osg::NodeVisitor& nv);
        void traverse_VIEW_DEPENDENT_WITH_ORTHOGRAPHIC_OVERLAY(osg::NodeVisitor& nv);
        void traverse_VIEW_DEPENDENT_WITH_PERSPECTIVE_OVERLAY(osg::NodeVisitor& nv);


        void updateMainSubgraphStateSet();

        typedef osg::buffered_value< int > TextureObjectValidList;
        
        mutable TextureObjectValidList _textureObjectValidList;

        OverlayTechnique _overlayTechnique;


        // overlay subgraph is render to a texture
        osg::ref_ptr<osg::Node>         _overlaySubgraph;

        osg::ref_ptr<osg::StateSet>     _overlayStateSet;
        osg::ref_ptr<osg::StateSet>     _mainStateSet;
        
        // texture to render to, and to read from.
        GLenum                          _texEnvMode;
        unsigned int                    _textureUnit;
        unsigned int                    _textureSizeHint;
        osg::Vec4                       _overlayClearColor;

        bool                            _continuousUpdate;
        double                          _overlayBaseHeight;
        bool                            _updateCamera;
        
        osg::Camera::RenderTargetImplementation _renderTargetImpl;

        struct OverlayData : public osg::Referenced
        {

            void setThreadSafeRefUnref(bool threadSafe);
            void resizeGLObjectBuffers(unsigned int maxSize);
            void releaseGLObjects(osg::State* state= 0) const;

            osg::ref_ptr<osg::Camera>       _camera;
            osg::ref_ptr<osg::StateSet>     _overlayStateSet;
            osg::ref_ptr<osg::StateSet>     _mainSubgraphStateSet;
            osg::ref_ptr<osg::TexGenNode>   _texgenNode;
            osg::ref_ptr<osg::Texture2D>    _texture;
            osg::Polytope                   _textureFrustum;
            osg::ref_ptr<osg::Geode>        _geode;

            osg::ref_ptr<osg::Program>      _mainSubgraphProgram;
            
            osg::ref_ptr<osg::Uniform>      _y0;
            osg::ref_ptr<osg::Uniform>      _lightingEnabled;
        };
        
        typedef std::map<osgUtil::CullVisitor*, osg::ref_ptr<OverlayData> > OverlayDataMap;
        
        OpenThreads::Mutex              _overlayDataMapMutex;
        OverlayDataMap                  _overlayDataMap;
        
        OverlayNode::OverlayData* getOverlayData(osgUtil::CullVisitor* cv);
        
};

}

#endif