/* -*-c++-*- */
/* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
* Copyright 2008-2012 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.Ov
*
* This program 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
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_OVERLAY_CLAMPING_BIN_TECHNIQUE
#define OSGEARTH_OVERLAY_CLAMPING_BIN_TECHNIQUE

#include <osgEarth/Common>
#include <osgEarth/OverlayDecorator>
#include <osg/TexGenNode>
#include <osg/Uniform>

#define OSGEARTH_CLAMPING_BIN "osgEarth::ClampingBin"

namespace osgEarth
{
    class TerrainEngineNode;

    /**
     * Clamps geometry to the terrain using the GPU.
     *
     * Uses the same technique for GPU clamping as the ClampingTechnique.
     * See that class's header for details.
     *
     * The difference is that this technique uses a custom RenderBin rather
     * than requiring the geometry be under a special overlay group; so,
     * rather than use a ClampableNode, you can simply say
     *
     *   stateSet->setRenderBinDetail(0, OSGEARTH_CLAMPING_BIN);
     *
     * Limitations
     *
     * This technique is not active yet. The issue is that the RTT camera
     * generator in OverlayDecorator needs to know the bounds of the overlay
     * geometry in order to make a minimum bounding polyhedron. This technique
     * does not provide that information (yet).
     */
    class OSGEARTH_EXPORT ClampingBinTechnique : public OverlayTechnique
    {
    public:
        ClampingBinTechnique();

        /**
         * The size (resolution in both directions) of the depth map texture. By
         * default, this defaults to 4096 or your hardware's maximum supported
         * texture size, whichever is less.
         */
        void setTextureSize( int texSize );
        int getTextureSize() const { return *_textureSize; }


    public: // OverlayTechnique

        virtual bool hasData(
            OverlayDecorator::TechRTTParams& params) const;

        void reestablish(
            TerrainEngineNode* engine );

        void preCullTerrain(
            OverlayDecorator::TechRTTParams& params,
            osgUtil::CullVisitor*            cv );

        void cullOverlayGroup(
            OverlayDecorator::TechRTTParams& params,
            osgUtil::CullVisitor*            cv );

        void onInstall( TerrainEngineNode* engine );

        void onUninstall( TerrainEngineNode* engine );


    protected:
        virtual ~ClampingBinTechnique() { }

    private:
        int                _textureUnit;
        optional<int>      _textureSize;
        TerrainEngineNode* _engine;
        Threading::PerObjectMap<osg::Camera*, osg::ref_ptr<osg::StateSet> > _perCameraStateSet;

    public:
        osg::StateSet* getStateSet(osg::Camera*);

    private:
        void setUpCamera(OverlayDecorator::TechRTTParams& params);
    };

} // namespace osgEarth

#endif //OSGEARTH_OVERLAY_CLAMPING_BIN_TECHNIQUE
