231 lines
10 KiB
C++
231 lines
10 KiB
C++
/* -*-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.
|
|
*
|
|
* ViewDependentShadow codes Copyright (C) 2008 Wojciech Lewandowski
|
|
* Thanks to to my company http://www.ai.com.pl for allowing me free this work.
|
|
*/
|
|
|
|
#ifndef OSGSHADOW_VIEWDEPENDENTSHADOWTECHINIQUE
|
|
#define OSGSHADOW_VIEWDEPENDENTSHADOWTECHINIQUE 1
|
|
|
|
#include <osgShadow/ShadowTechnique>
|
|
#include <map>
|
|
#include <osgShadow/Export>
|
|
|
|
namespace osgShadow {
|
|
/**
|
|
META_ViewDependentShadowTechniqueData macro defines initViewDependentData
|
|
method used by derived shadow techniques to initialize their specific
|
|
ViewData objects. initViewDependentData will be called from
|
|
ViewDependentShadowTechnique base class to init derived class
|
|
*/
|
|
#define META_ViewDependentShadowTechniqueData( ShadowTechnique, TechniqueData )\
|
|
virtual ViewDependentShadowTechnique::ViewData * initViewDependentData \
|
|
( osgUtil::CullVisitor *cv, ViewDependentShadowTechnique::ViewData * vd ) \
|
|
{ \
|
|
TechniqueData* td = dynamic_cast<TechniqueData*>( vd ); \
|
|
if ( !td ) td = new TechniqueData; \
|
|
td->init( this, cv ); \
|
|
return td; \
|
|
}
|
|
|
|
/**
|
|
ViewDependentShadowTechnique is a base class for all
|
|
View Dependent Shadow techniques. It defines fundamental object structure
|
|
and methods to manage separate shadow resources for each view of the scene.
|
|
By view we understand osg::View or SceneView instance and their associated
|
|
Camera. Typical osg application has one or more such views. View Dependent
|
|
Shadow techniques manage shadow generation for them.
|
|
|
|
View Dependent Shadow techniques are used to optimize shadow algorithms for
|
|
part of the scene seen on the view. If rest of the scene is behind view
|
|
frustum, there is no sense in computing shadows for it. Since in practice we
|
|
often use 3d databases extending far beyond current camera frustum View
|
|
Dependent Shadow approach may produce much better shadows.
|
|
|
|
The other goal is to provide framework for thread safe rendering of
|
|
the shadows. It allows to use shadows with different OSG threading models.
|
|
|
|
Conceptually ViewDependentShadowTechnique is similar to osgSim::OverlayNode.
|
|
Its a container class for number of ViewData (or ViewData derived) objects
|
|
doing actual shadow work for each of the scene views.
|
|
|
|
But ViewDependentShadowTechnique is intended as foundation layer for all
|
|
derived classes so in some way it extends osgSim::OverlayNode approach a bit.
|
|
|
|
HOW IT WORKS:
|
|
|
|
ViewDependendentShadowTechnique is derived from osgShadow::ShadowTechnique
|
|
and as such overrides virtual methods of osgShadow::ShadowTechnique.
|
|
But most of the shadow dirty work is done by ViewData objects,
|
|
ViewDependendentShadowTechnique::cull is the only osgShadow::ShadowTechnique
|
|
method where ViewDependendentShadowTechnique does something significant:
|
|
|
|
What ViewDependentShadowTechnique::cull( CullVisitor & cv ) does ?
|
|
It identifies View. CullVisitor ptr is used as View identificator.
|
|
In practice we do not check and interpret what are actual Views and SceneViews
|
|
set up by application. We focus on Camera and CullVisitors as a identificators
|
|
of views. We can safely do this because each such view will have associated
|
|
unique CullVisitor used to cull the scene in every frame.
|
|
|
|
Based on CullVisitor ptr passed to cull method, associated Technique::ViewData
|
|
object is created (if neccessary) and then seleced. Then control is passed to
|
|
this ViewData object. So, each view has its associated unique ViewData
|
|
(or derived) object performing dirty work of shadow resources management and
|
|
shadow generation for the view.
|
|
|
|
To support creation of classes derived from ViewDependentShadowTechnique it
|
|
was neccessary to provide mechanism to override ViewData and allow for
|
|
initialization of new derived ViewData objects. Creation and initialization
|
|
is performed when ViewDependendentShadowTechnique::cull gets called with
|
|
CullVistor ptr which does not yet have associated ViewData object. When it
|
|
happens, virtual initViewDependentData method is called to give
|
|
derived techniques a chance to allocate and iniitalize its specific
|
|
resources as new ViewData derived instance. In practice initViewDependentData
|
|
in derived techniques should look the same as in base class so as a convenience
|
|
it was defined as META_ViewDependentShadowTechnique macro. Derived techniques
|
|
use this macro to override initViewDependentData method for their usage.
|
|
|
|
After ViewData derived object is construted and selected, control is passed
|
|
to this object by call to virtual ViewData::cull method. The rest of work
|
|
is the done by this object. ViewDependentShadowTechnique::ViewData is intended
|
|
as a base class so it does nothing. In practice the rest of dirty work will
|
|
do new ViewData classes implemented in derived techniques.
|
|
*/
|
|
class OSGSHADOW_EXPORT ViewDependentShadowTechnique
|
|
: public osgShadow::ShadowTechnique
|
|
{
|
|
public:
|
|
/**
|
|
osgShadow::ShadowTechnique equivalent methods for view dependent techniques
|
|
*/
|
|
|
|
/** Classic OSG constructor */
|
|
ViewDependentShadowTechnique( void );
|
|
|
|
/** Classic OSG cloning constructor */
|
|
ViewDependentShadowTechnique(
|
|
const ViewDependentShadowTechnique& vdst,
|
|
const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY );
|
|
|
|
|
|
/** Declaration of standard OSG object methods */
|
|
META_Object( ViewDependentShadow, ViewDependentShadowTechnique );
|
|
|
|
/** Dirty view data bits and force update of view data resources */
|
|
virtual void dirty();
|
|
|
|
/** Initialize the ShadowedScene and some data structures.*/
|
|
virtual void init();
|
|
|
|
/** Run the update traversal of the ShadowedScene and update any local cached data structures.*/
|
|
virtual void update(osg::NodeVisitor& nv);
|
|
|
|
/** Run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/
|
|
virtual void cull(osgUtil::CullVisitor& cv);
|
|
|
|
/** Clean scene graph from any shadow technique specific nodes, state and drawables.*/
|
|
virtual void cleanSceneGraph();
|
|
|
|
/** Traverse shadow scene graph.*/
|
|
virtual void traverse(osg::NodeVisitor& nv);
|
|
|
|
protected:
|
|
/** Classic protected OSG destructor */
|
|
~ViewDependentShadowTechnique( void );
|
|
|
|
/**
|
|
Base container class for view dependent shadow resources.
|
|
Techniques based on ViewDependentShadowTechnique will usually define
|
|
similar struct and derive it from ViewData to contain their specufic resources.
|
|
*/
|
|
struct OSGSHADOW_EXPORT ViewData: public osg::Referenced
|
|
{
|
|
/**
|
|
Method called upon ViewData instance to initialize internal variables
|
|
*/
|
|
virtual void init
|
|
( ViewDependentShadowTechnique *st, osgUtil::CullVisitor *cv );
|
|
|
|
/**
|
|
Method called by ViewDependentShadowTechnique to allow ViewData
|
|
do the hard work computing shadows for its associated view
|
|
*/
|
|
virtual void cull();
|
|
|
|
/**
|
|
Dirty is called by parent ViewDependentShadowTechnique to force
|
|
update of resources after some of them were modified in parent technique
|
|
*/
|
|
virtual void dirty( bool flag );
|
|
|
|
/**
|
|
Simple constructor zeroing all variables.
|
|
*/
|
|
ViewData(): _dirty( true ), _cv( NULL ), _st( NULL ) { };
|
|
|
|
/**
|
|
Mutex used to guard _dirty flag from override in case when parent technique calls
|
|
dirty() simultaneously with ViewData while it is updating resources inside init method.
|
|
*/
|
|
OpenThreads::Mutex _mutex;
|
|
|
|
/**
|
|
Dirty flag tells this instance to update its resources
|
|
*/
|
|
bool _dirty;
|
|
|
|
/**
|
|
View's CullVisitor associated with this ViewData instance
|
|
*/
|
|
osg::observer_ptr< osgUtil::CullVisitor > _cv;
|
|
|
|
/**
|
|
Parent ViewDependentShadowTechnique
|
|
*/
|
|
osg::observer_ptr< ViewDependentShadowTechnique > _st;
|
|
|
|
};
|
|
|
|
/**
|
|
Map of view dependent data per view cull visitor (CVs are used as indices)
|
|
ViewDependentShadowTechnique uses this map to find VieData for each cull vitior
|
|
*/
|
|
|
|
typedef std::map< osg::ref_ptr< osgUtil::CullVisitor >,
|
|
osg::ref_ptr< ViewData > > ViewDataMap;
|
|
|
|
ViewDataMap _viewDataMap;
|
|
|
|
|
|
/**
|
|
Mutex used to serialize accesses to ViewDataMap
|
|
*/
|
|
OpenThreads::Mutex _viewDataMapMutex;
|
|
|
|
/** Return view dependent data for the cull visitor */
|
|
virtual ViewDependentShadowTechnique::ViewData * getViewDependentData( osgUtil::CullVisitor * cv );
|
|
|
|
/** Define view dependent data for the cull visitor */
|
|
virtual void setViewDependentData( osgUtil::CullVisitor * cv, ViewDependentShadowTechnique::ViewData * data );
|
|
|
|
/**
|
|
Declare standard initViewDependentData method.
|
|
*/
|
|
META_ViewDependentShadowTechniqueData( ViewDependentShadowTechnique, ViewData )
|
|
};
|
|
|
|
|
|
} // namespace osgShadow
|
|
|
|
#endif
|