/*****************************************************************************
 * $LastChangedDate: 2010-03-09 14:51:12 -0500 (Tue, 09 Mar 2010) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Graph containing nodes that cast/receive shadows.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef GRAPH_SHADOW_SCENE_GRAPH_HH
#define GRAPH_SHADOW_SCENE_GRAPH_HH 1

// Whether to limit shadow casters to one or allow multiple shadow casters.
#ifndef LIMIT_SHADOW_CASTERS
#define LIMIT_SHADOW_CASTERS 1
#endif

#if ! DOXYGEN
namespace osgShadow { class ShadowedScene; class MinimalShadowMap; }
#endif // ! DOXYGEN
#include "graph/typedefs.hh"
#include "graph/base_scene_graph.hh"

namespace graph {

class NodeSort;

//------------------------------------------------------------------------------
namespace defs {

// Correlates to the shader uniform "uni_shadowMode".
enum
{
    SHADOW_MODE_DISABLED = 0,  ///< -no-shadows
    SHADOW_MODE_SAMPLE1  = 1,  ///< -fast-shadows
    SHADOW_MODE_SAMPLE4  = 2,  ///< -soft-shadows
    SHADOW_MODE_DEFAULT  = SHADOW_MODE_SAMPLE4,
};

} // namespace defs
//------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief Graph containing nodes that cast/receive shadows.
///
/// This is a facade over osgShadow::MinimalShadowMap.
/// osgShadow::ShadowedScene is a group node that defines the shadowed graph.
/// osgShadow::MinimalShadowMap is a shadow algorithm ("shadow technique").
/// This shadow algorithm was chosen because it prevents shadows spilling
/// onto back-facing polygons (aircraft casting shadows on undersides of carrier).
///
/// osgShadow::ShadowedScene -> ShadowSceneGraph::mShadowRootNode -> shadowCasters
///                                                                  shadowReceivers
///
/// The reason for this arrangement is to override the stock OSG shaders
/// attached to the osgShadow::ShadowedScene node.
/// mShadowRootNode will be the effective root node.
/// mShadowRootNode is operated on by the BaseSceneGraph methods.
///
class ShadowSceneGraph : public BaseSceneGraph
{
PREVENT_COPYING(ShadowSceneGraph);
private:
    CLASS_CONST uint SHADOW_TEXTURE_WIDTH = 1024;

public:
                                ShadowSceneGraph( void );
    virtual                     ~ShadowSceneGraph();
    virtual RefPtr<GroupNode>   GetRootNode( void );
    virtual void                AttachNode( RefPtr<Node> node, const NodeSort& nodeSort );
    virtual void                DetachNode( RefPtr<Node> node );
    CLASS_METHOD void           DisableShadows( RefPtr<Node> node );

private:
    RefPtr<osgShadow::ShadowedScene>    mShadowedScene;     ///< absolute root node
    RefPtr<GroupNode>                   mShadowRootNode;    ///< effective root node (child of ShadowedScene)
    RefPtr<osgShadow::MinimalShadowMap> mShadowMap;         ///< algorithm
#if LIMIT_SHADOW_CASTERS
    RefPtr<Node>                        mShadowCasterNode;  ///< if shadow caster is attached
#endif
};

} // namespace graph

#endif // GRAPH_SHADOW_SCENE_GRAPH_HH
