Ran dos2unix on new shadow implemenations

This commit is contained in:
Robert Osfield
2008-10-06 08:53:25 +00:00
parent 5fe30854dd
commit 87e8f06522
8 changed files with 5474 additions and 5474 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,368 +1,368 @@
/* -*-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.
*/
#include <osgShadow/MinimalCullBoundsShadowMap>
#include <osgUtil/RenderLeaf>
#include <string.h>
#define IGNORE_OBJECTS_LARGER_THAN_HEIGHT 0
using namespace osgShadow;
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap(): BaseClass()
{
}
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap
(const MinimalCullBoundsShadowMap& copy, const osg::CopyOp& copyop) :
BaseClass(copy,copyop)
{
}
MinimalCullBoundsShadowMap::~MinimalCullBoundsShadowMap()
{
}
void MinimalCullBoundsShadowMap::ViewData::init
( ThisClass *st, osgUtil::CullVisitor *cv )
{
BaseClass::ViewData::init( st, cv );
}
void MinimalCullBoundsShadowMap::ViewData::aimShadowCastingCamera
( const osg::Light *light,
const osg::Vec4 &lightPos,
const osg::Vec3 &lightDir,
const osg::Vec3 &lightUp )
{
MinimalShadowMap::ViewData::aimShadowCastingCamera
( light, lightPos, lightDir, lightUp );
frameShadowCastingCamera
( _cv->getCurrentRenderBin()->getStage()->getCamera(), _camera.get() );
}
void MinimalCullBoundsShadowMap::ViewData::cullShadowReceivingScene( )
{
RenderLeafList rllOld, rllNew;
GetRenderLeaves( _cv->getRenderStage(), rllOld );
MinimalShadowMap::ViewData::cullShadowReceivingScene( );
GetRenderLeaves( _cv->getRenderStage(), rllNew );
RemoveOldRenderLeaves( rllNew, rllOld );
RemoveIgnoredRenderLeaves( rllNew );
osg::Matrix projectionToModelSpace =
osg::Matrix::inverse( *_modellingSpaceToWorldPtr *
*_cv->getModelViewMatrix() * *_cv->getProjectionMatrix() );
osg::BoundingBox bb;
if( *_cv->getProjectionMatrix() != _clampedProjection ) {
osg::Polytope polytope;
#if 1
polytope.setToUnitFrustum();
#else
polytope.add( osg::Plane( 0.0,0.0,-1.0,1.0 ) ); // only far plane
#endif
polytope.transformProvidingInverse( *_modellingSpaceToWorldPtr *
*_cv->getModelViewMatrix() * _clampedProjection );
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace, polytope );
} else {
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace );
}
cutScenePolytope( *_modellingSpaceToWorldPtr,
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
}
void MinimalCullBoundsShadowMap::ViewData::GetRenderLeaves
( osgUtil::RenderBin *rb, RenderLeafList & rll )
{
osgUtil::RenderBin::RenderBinList& bins = rb->getRenderBinList();
osgUtil::RenderBin::RenderBinList::const_iterator rbitr;
// scan pre render bins
for(rbitr = bins.begin(); rbitr!=bins.end() && rbitr->first<0; ++rbitr )
GetRenderLeaves( rbitr->second.get(), rll );
// scan fine grained ordering.
osgUtil::RenderBin::RenderLeafList& renderLeafList = rb->getRenderLeafList();
osgUtil::RenderBin::RenderLeafList::const_iterator rlitr;
for( rlitr= renderLeafList.begin(); rlitr!= renderLeafList.end(); ++rlitr )
{
rll.push_back( *rlitr );
}
// scan coarse grained ordering.
osgUtil::RenderBin::StateGraphList& stateGraphList = rb->getStateGraphList();
osgUtil::RenderBin::StateGraphList::const_iterator oitr;
for( oitr= stateGraphList.begin(); oitr!= stateGraphList.end(); ++oitr )
{
for( osgUtil::StateGraph::LeafList::const_iterator dw_itr =
(*oitr)->_leaves.begin(); dw_itr != (*oitr)->_leaves.end(); ++dw_itr)
{
rll.push_back( dw_itr->get() );
}
}
// scan post render bins
for(; rbitr!=bins.end(); ++rbitr )
GetRenderLeaves( rbitr->second.get(), rll );
}
class CompareRenderLeavesByMatrices {
public:
bool operator()( const osgUtil::RenderLeaf *a, const osgUtil::RenderLeaf *b )
{
if ( !a ) return false; // NULL render leaf goes last
return !b ||
a->_projection < b->_projection ||
a->_projection == b->_projection && a->_modelview < b->_modelview;
}
};
inline bool CheckAndMultiplyBoxIfWithinPolytope
( osg::BoundingBox & bb, osg::Matrix & m, osg::Polytope &p )
{
if( !bb.valid() ) return false;
osg::Vec3 o = bb._min * m, s[3];
for( int i = 0; i < 3; i ++ )
s[i] = osg::Vec3( m(i,0), m(i,1), m(i,2) ) * ( bb._max[i] - bb._min[i] );
for( osg::Polytope::PlaneList::iterator it = p.getPlaneList().begin();
it != p.getPlaneList().end();
++it )
{
float dist = it->distance( o ), dist_min = dist, dist_max = dist;
for( int i = 0; i < 3; i ++ ) {
dist = it->dotProductNormal( s[i] );
if( dist < 0 ) dist_min += dist; else dist_max += dist;
}
if( dist_max < 0 )
return false;
}
bb._max = bb._min = o;
#if 1
for( int i = 0; i < 3; i ++ )
for( int j = 0; j < 3; j ++ )
if( s[i][j] < 0 ) bb._min[j] += s[i][j]; else bb._max[j] += s[i][j];
#else
b.expandBy( o + s[0] );
b.expandBy( o + s[1] );
b.expandBy( o + s[2] );
b.expandBy( o + s[0] + s[1] );
b.expandBy( o + s[0] + s[2] );
b.expandBy( o + s[1] + s[2] );
b.expandBy( o + s[0] + s[1] + s[2] );
#endif
#if ( IGNORE_OBJECTS_LARGER_THAN_HEIGHT > 0 )
if( bb._max[2] - bb._min[2] > IGNORE_OBJECTS_LARGER_THAN_HEIGHT ) // ignore huge objects
return false;
#endif
return true;
}
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveOldRenderLeaves
( RenderLeafList &rllNew, RenderLeafList &rllOld )
{
unsigned count = 0;
std::sort( rllOld.begin(), rllOld.end() );
RenderLeafList::iterator itNew, itOld;
for( itNew = rllNew.begin(); itNew != rllNew.end() && rllOld.size(); ++itNew )
{
itOld = std::lower_bound( rllOld.begin(), rllOld.end(), *itNew );
if( itOld == rllOld.end() || *itOld != *itNew ) continue;
// found !
rllOld.erase( itOld ); //remove it from old range to speed up search
*itNew = NULL; //its not new = invalidate it among new render leaves
count ++;
}
return count;
}
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveIgnoredRenderLeaves
( RenderLeafList &rll )
{
unsigned count = 0;
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it )
{
if( !*it ) continue;
const char * name = (*it)->_drawable->className();
// Its a dirty but quick test (not very future proof)
if( !name || name[0] != 'L' ) continue;
if( !strcmp( name, "LightPointDrawable" ) ||
!strcmp( name, "LightPointSpriteDrawable" ) )
{
*it = NULL; //ignored = invalidate this in new render leaves list
count++;
}
}
return count;
}
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
( RenderLeafList &rll, osg::Matrix & projectionToWorld )
{
osg::BoundingBox bbResult;
if( rll.size() == 0 ) return bbResult;
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
osg::ref_ptr< osg::RefMatrix > modelview;
osg::ref_ptr< osg::RefMatrix > projection;
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
osg::BoundingBox bb;
// compute bounding boxes but skip old ones (placed at the end as NULLs)
for( RenderLeafList::iterator it = rll.begin(); ; ++it ) {
// we actually allow to pass one element behind end to flush bb queue
osgUtil::RenderLeaf *rl = ( it != rll.end() ? *it : NULL );
// Don't trust already computed bounds for cull generated drawables
// LightPointDrawable & LightPointSpriteDrawable are such examples
// they store wrong recorded bounds from very first pass
if( rl && rl->_modelview == NULL )
rl->_drawable->dirtyBound();
// Stay as long as possible in model space to minimize matrix ops
if( rl && rl->_modelview == modelview && rl->_projection == projection ){
bb.expandBy( rl->_drawable->getBound() );
} else {
if( bb.valid() ) {
// Conditions to avoid matrix multiplications
if( projection.valid() )
{
if( projection.get() != ptrProjection )
{
ptrProjection = projection.get();
viewToWorld = *ptrProjection * projectionToWorld;
}
ptrViewToWorld = &viewToWorld;
} else {
ptrViewToWorld = &projectionToWorld;
}
if( modelview.valid() )
{
modelToWorld = *modelview.get() * *ptrViewToWorld;
ptrModelToWorld = &modelToWorld;
} else {
ptrModelToWorld = ptrViewToWorld;
}
for( int i = 0; i < 8; i++ )
bbResult.expandBy( bb.corner( i ) * *ptrModelToWorld );
}
if( !rl ) break;
bb = rl->_drawable->getBound();
modelview = rl->_modelview;
projection = rl->_projection;
}
}
rll.clear();
return bbResult;
}
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
( RenderLeafList &rll, osg::Matrix & projectionToWorld, osg::Polytope & p )
{
osg::BoundingBox bbResult, bb;
if( rll.size() == 0 ) return bbResult;
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
osg::ref_ptr< osg::RefMatrix > modelview;
osg::ref_ptr< osg::RefMatrix > projection;
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
// compute bounding boxes but skip old ones (placed at the end as NULLs)
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it ) {
// we actually allow to pass one element behind end to flush bb queue
osgUtil::RenderLeaf *rl = *it;
if( !rl ) break;
// Don't trust already computed bounds for cull generated drawables
// LightPointDrawable & LightPointSpriteDrawable are such examples
// they store wrong recorded bounds from very first pass
if( rl && rl->_modelview == NULL )
rl->_drawable->dirtyBound();
bb = rl->_drawable->getBound();
if( !bb.valid() ) continue;
// Stay as long as possible in model space to minimize matrix ops
if( rl->_modelview != modelview || rl->_projection != projection ) {
projection = rl->_projection;
if( projection.valid() )
{
if( projection.get() != ptrProjection )
{
ptrProjection = projection.get();
viewToWorld = *ptrProjection * projectionToWorld;
}
ptrViewToWorld = &viewToWorld;
} else {
ptrViewToWorld = &projectionToWorld;
}
modelview = rl->_modelview;
if( modelview.valid() )
{
modelToWorld = *modelview.get() * *ptrViewToWorld;
ptrModelToWorld = &modelToWorld;
} else {
ptrModelToWorld = ptrViewToWorld;
}
}
if( CheckAndMultiplyBoxIfWithinPolytope( bb, *ptrModelToWorld, p ) )
bbResult.expandBy( bb );
}
rll.clear();
return bbResult;
}
/* -*-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.
*/
#include <osgShadow/MinimalCullBoundsShadowMap>
#include <osgUtil/RenderLeaf>
#include <string.h>
#define IGNORE_OBJECTS_LARGER_THAN_HEIGHT 0
using namespace osgShadow;
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap(): BaseClass()
{
}
MinimalCullBoundsShadowMap::MinimalCullBoundsShadowMap
(const MinimalCullBoundsShadowMap& copy, const osg::CopyOp& copyop) :
BaseClass(copy,copyop)
{
}
MinimalCullBoundsShadowMap::~MinimalCullBoundsShadowMap()
{
}
void MinimalCullBoundsShadowMap::ViewData::init
( ThisClass *st, osgUtil::CullVisitor *cv )
{
BaseClass::ViewData::init( st, cv );
}
void MinimalCullBoundsShadowMap::ViewData::aimShadowCastingCamera
( const osg::Light *light,
const osg::Vec4 &lightPos,
const osg::Vec3 &lightDir,
const osg::Vec3 &lightUp )
{
MinimalShadowMap::ViewData::aimShadowCastingCamera
( light, lightPos, lightDir, lightUp );
frameShadowCastingCamera
( _cv->getCurrentRenderBin()->getStage()->getCamera(), _camera.get() );
}
void MinimalCullBoundsShadowMap::ViewData::cullShadowReceivingScene( )
{
RenderLeafList rllOld, rllNew;
GetRenderLeaves( _cv->getRenderStage(), rllOld );
MinimalShadowMap::ViewData::cullShadowReceivingScene( );
GetRenderLeaves( _cv->getRenderStage(), rllNew );
RemoveOldRenderLeaves( rllNew, rllOld );
RemoveIgnoredRenderLeaves( rllNew );
osg::Matrix projectionToModelSpace =
osg::Matrix::inverse( *_modellingSpaceToWorldPtr *
*_cv->getModelViewMatrix() * *_cv->getProjectionMatrix() );
osg::BoundingBox bb;
if( *_cv->getProjectionMatrix() != _clampedProjection ) {
osg::Polytope polytope;
#if 1
polytope.setToUnitFrustum();
#else
polytope.add( osg::Plane( 0.0,0.0,-1.0,1.0 ) ); // only far plane
#endif
polytope.transformProvidingInverse( *_modellingSpaceToWorldPtr *
*_cv->getModelViewMatrix() * _clampedProjection );
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace, polytope );
} else {
bb = ComputeRenderLeavesBounds( rllNew, projectionToModelSpace );
}
cutScenePolytope( *_modellingSpaceToWorldPtr,
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
}
void MinimalCullBoundsShadowMap::ViewData::GetRenderLeaves
( osgUtil::RenderBin *rb, RenderLeafList & rll )
{
osgUtil::RenderBin::RenderBinList& bins = rb->getRenderBinList();
osgUtil::RenderBin::RenderBinList::const_iterator rbitr;
// scan pre render bins
for(rbitr = bins.begin(); rbitr!=bins.end() && rbitr->first<0; ++rbitr )
GetRenderLeaves( rbitr->second.get(), rll );
// scan fine grained ordering.
osgUtil::RenderBin::RenderLeafList& renderLeafList = rb->getRenderLeafList();
osgUtil::RenderBin::RenderLeafList::const_iterator rlitr;
for( rlitr= renderLeafList.begin(); rlitr!= renderLeafList.end(); ++rlitr )
{
rll.push_back( *rlitr );
}
// scan coarse grained ordering.
osgUtil::RenderBin::StateGraphList& stateGraphList = rb->getStateGraphList();
osgUtil::RenderBin::StateGraphList::const_iterator oitr;
for( oitr= stateGraphList.begin(); oitr!= stateGraphList.end(); ++oitr )
{
for( osgUtil::StateGraph::LeafList::const_iterator dw_itr =
(*oitr)->_leaves.begin(); dw_itr != (*oitr)->_leaves.end(); ++dw_itr)
{
rll.push_back( dw_itr->get() );
}
}
// scan post render bins
for(; rbitr!=bins.end(); ++rbitr )
GetRenderLeaves( rbitr->second.get(), rll );
}
class CompareRenderLeavesByMatrices {
public:
bool operator()( const osgUtil::RenderLeaf *a, const osgUtil::RenderLeaf *b )
{
if ( !a ) return false; // NULL render leaf goes last
return !b ||
a->_projection < b->_projection ||
a->_projection == b->_projection && a->_modelview < b->_modelview;
}
};
inline bool CheckAndMultiplyBoxIfWithinPolytope
( osg::BoundingBox & bb, osg::Matrix & m, osg::Polytope &p )
{
if( !bb.valid() ) return false;
osg::Vec3 o = bb._min * m, s[3];
for( int i = 0; i < 3; i ++ )
s[i] = osg::Vec3( m(i,0), m(i,1), m(i,2) ) * ( bb._max[i] - bb._min[i] );
for( osg::Polytope::PlaneList::iterator it = p.getPlaneList().begin();
it != p.getPlaneList().end();
++it )
{
float dist = it->distance( o ), dist_min = dist, dist_max = dist;
for( int i = 0; i < 3; i ++ ) {
dist = it->dotProductNormal( s[i] );
if( dist < 0 ) dist_min += dist; else dist_max += dist;
}
if( dist_max < 0 )
return false;
}
bb._max = bb._min = o;
#if 1
for( int i = 0; i < 3; i ++ )
for( int j = 0; j < 3; j ++ )
if( s[i][j] < 0 ) bb._min[j] += s[i][j]; else bb._max[j] += s[i][j];
#else
b.expandBy( o + s[0] );
b.expandBy( o + s[1] );
b.expandBy( o + s[2] );
b.expandBy( o + s[0] + s[1] );
b.expandBy( o + s[0] + s[2] );
b.expandBy( o + s[1] + s[2] );
b.expandBy( o + s[0] + s[1] + s[2] );
#endif
#if ( IGNORE_OBJECTS_LARGER_THAN_HEIGHT > 0 )
if( bb._max[2] - bb._min[2] > IGNORE_OBJECTS_LARGER_THAN_HEIGHT ) // ignore huge objects
return false;
#endif
return true;
}
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveOldRenderLeaves
( RenderLeafList &rllNew, RenderLeafList &rllOld )
{
unsigned count = 0;
std::sort( rllOld.begin(), rllOld.end() );
RenderLeafList::iterator itNew, itOld;
for( itNew = rllNew.begin(); itNew != rllNew.end() && rllOld.size(); ++itNew )
{
itOld = std::lower_bound( rllOld.begin(), rllOld.end(), *itNew );
if( itOld == rllOld.end() || *itOld != *itNew ) continue;
// found !
rllOld.erase( itOld ); //remove it from old range to speed up search
*itNew = NULL; //its not new = invalidate it among new render leaves
count ++;
}
return count;
}
unsigned MinimalCullBoundsShadowMap::ViewData::RemoveIgnoredRenderLeaves
( RenderLeafList &rll )
{
unsigned count = 0;
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it )
{
if( !*it ) continue;
const char * name = (*it)->_drawable->className();
// Its a dirty but quick test (not very future proof)
if( !name || name[0] != 'L' ) continue;
if( !strcmp( name, "LightPointDrawable" ) ||
!strcmp( name, "LightPointSpriteDrawable" ) )
{
*it = NULL; //ignored = invalidate this in new render leaves list
count++;
}
}
return count;
}
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
( RenderLeafList &rll, osg::Matrix & projectionToWorld )
{
osg::BoundingBox bbResult;
if( rll.size() == 0 ) return bbResult;
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
osg::ref_ptr< osg::RefMatrix > modelview;
osg::ref_ptr< osg::RefMatrix > projection;
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
osg::BoundingBox bb;
// compute bounding boxes but skip old ones (placed at the end as NULLs)
for( RenderLeafList::iterator it = rll.begin(); ; ++it ) {
// we actually allow to pass one element behind end to flush bb queue
osgUtil::RenderLeaf *rl = ( it != rll.end() ? *it : NULL );
// Don't trust already computed bounds for cull generated drawables
// LightPointDrawable & LightPointSpriteDrawable are such examples
// they store wrong recorded bounds from very first pass
if( rl && rl->_modelview == NULL )
rl->_drawable->dirtyBound();
// Stay as long as possible in model space to minimize matrix ops
if( rl && rl->_modelview == modelview && rl->_projection == projection ){
bb.expandBy( rl->_drawable->getBound() );
} else {
if( bb.valid() ) {
// Conditions to avoid matrix multiplications
if( projection.valid() )
{
if( projection.get() != ptrProjection )
{
ptrProjection = projection.get();
viewToWorld = *ptrProjection * projectionToWorld;
}
ptrViewToWorld = &viewToWorld;
} else {
ptrViewToWorld = &projectionToWorld;
}
if( modelview.valid() )
{
modelToWorld = *modelview.get() * *ptrViewToWorld;
ptrModelToWorld = &modelToWorld;
} else {
ptrModelToWorld = ptrViewToWorld;
}
for( int i = 0; i < 8; i++ )
bbResult.expandBy( bb.corner( i ) * *ptrModelToWorld );
}
if( !rl ) break;
bb = rl->_drawable->getBound();
modelview = rl->_modelview;
projection = rl->_projection;
}
}
rll.clear();
return bbResult;
}
osg::BoundingBox MinimalCullBoundsShadowMap::ViewData::ComputeRenderLeavesBounds
( RenderLeafList &rll, osg::Matrix & projectionToWorld, osg::Polytope & p )
{
osg::BoundingBox bbResult, bb;
if( rll.size() == 0 ) return bbResult;
std::sort( rll.begin(), rll.end(), CompareRenderLeavesByMatrices() );
osg::ref_ptr< osg::RefMatrix > modelview;
osg::ref_ptr< osg::RefMatrix > projection;
osg::Matrix viewToWorld, modelToWorld, *ptrProjection = NULL,
*ptrViewToWorld = &projectionToWorld, *ptrModelToWorld;
// compute bounding boxes but skip old ones (placed at the end as NULLs)
for( RenderLeafList::iterator it = rll.begin(); it != rll.end(); ++it ) {
// we actually allow to pass one element behind end to flush bb queue
osgUtil::RenderLeaf *rl = *it;
if( !rl ) break;
// Don't trust already computed bounds for cull generated drawables
// LightPointDrawable & LightPointSpriteDrawable are such examples
// they store wrong recorded bounds from very first pass
if( rl && rl->_modelview == NULL )
rl->_drawable->dirtyBound();
bb = rl->_drawable->getBound();
if( !bb.valid() ) continue;
// Stay as long as possible in model space to minimize matrix ops
if( rl->_modelview != modelview || rl->_projection != projection ) {
projection = rl->_projection;
if( projection.valid() )
{
if( projection.get() != ptrProjection )
{
ptrProjection = projection.get();
viewToWorld = *ptrProjection * projectionToWorld;
}
ptrViewToWorld = &viewToWorld;
} else {
ptrViewToWorld = &projectionToWorld;
}
modelview = rl->_modelview;
if( modelview.valid() )
{
modelToWorld = *modelview.get() * *ptrViewToWorld;
ptrModelToWorld = &modelToWorld;
} else {
ptrModelToWorld = ptrViewToWorld;
}
}
if( CheckAndMultiplyBoxIfWithinPolytope( bb, *ptrModelToWorld, p ) )
bbResult.expandBy( bb );
}
rll.clear();
return bbResult;
}

View File

@@ -1,406 +1,406 @@
/* -*-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.
*/
#include <osgShadow/MinimalDrawBoundsShadowMap>
#include <osgShadow/ConvexPolyhedron>
#include <osg/PolygonOffset>
#include <osgUtil/RenderLeaf>
#include <osgShadow/ShadowedScene>
#include <osg/FrameBufferObject>
#include <osg/BlendEquation>
#include <osg/Depth>
#include <osg/AlphaFunc>
#include <osg/Image>
#include <iostream>
#include <string.h>
#define ANALYSIS_DEPTH 1
#define USE_FLOAT_IMAGE 1
using namespace osgShadow;
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap(): BaseClass()
{
}
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap
(const MinimalDrawBoundsShadowMap& copy, const osg::CopyOp& copyop) :
BaseClass(copy,copyop)
{
}
MinimalDrawBoundsShadowMap::~MinimalDrawBoundsShadowMap()
{
}
void MinimalDrawBoundsShadowMap::ViewData::cullShadowReceivingScene( )
{
BaseClass::ViewData::cullShadowReceivingScene( );
ThisClass::ViewData::cullBoundAnalysisScene( );
}
void MinimalDrawBoundsShadowMap::ViewData::cullBoundAnalysisScene( )
{
_boundAnalysisCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
_boundAnalysisCamera->setViewMatrix( *_cv->getModelViewMatrix() );
_boundAnalysisCamera->setProjectionMatrix( _clampedProjection );
osg::Matrix::value_type l,r,b,t,n,f;
_boundAnalysisCamera->getProjectionMatrixAsFrustum( l,r,b,t,n,f );
_mainCamera = _cv->getRenderStage()->getCamera();
extendProjection( _boundAnalysisCamera->getProjectionMatrix(),
_boundAnalysisCamera->getViewport(), osg::Vec2( 2,2 ) );
// record the traversal mask on entry so we can reapply it later.
unsigned int traversalMask = _cv->getTraversalMask();
_cv->setTraversalMask( traversalMask &
_st->getShadowedScene()->getReceivesShadowTraversalMask() );
// do RTT camera traversal
_boundAnalysisCamera->accept(*_cv);
// reapply the original traversal mask
_cv->setTraversalMask( traversalMask );
}
void MinimalDrawBoundsShadowMap::ViewData::createDebugHUD( )
{
// _hudSize[0] *= 2;
_viewportSize[0] *= 2;
_orthoSize[0] *= 2;
MinimalShadowMap::ViewData::createDebugHUD( );
osg::Camera * camera = _cameraDebugHUD.get();
osg::Geode* geode = new osg::Geode;
camera->addChild( geode );
osg::Geometry* geometry = osg::createTexturedQuadGeometry
( osg::Vec3(_hudOrigin[0]+_hudSize[0],_hudOrigin[1],0),
osg::Vec3(_hudSize[0],0,0),
osg::Vec3(0,_hudSize[1],0) );
geode->addDrawable(geometry);
osg::StateSet* stateset = geometry->getOrCreateStateSet();
stateset->setTextureAttributeAndModes
(0, _boundAnalysisTexture.get(),osg::StateAttribute::ON );
#if ANALYSIS_DEPTH
osg::Program* program = new osg::Program;
program->addShader( _depthColorFragmentShader.get() );
stateset->setAttribute( program );
stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
#else
#endif
}
osg::BoundingBox MinimalDrawBoundsShadowMap::ViewData::scanImage
( const osg::Image * image, osg::Matrix m )
{
osg::BoundingBox bb, bbProj;
int components = osg::Image::computeNumComponents( image->getPixelFormat() );
if( image->getDataType() == GL_FLOAT ) {
float scale = 255.f / 254.f;
float * pf = (float *)image->data();
for( int y = 0; y < image->t(); y++ ) {
float fY = ( 0.5f + y ) / image->t();
for( int x = 0; x < image->s(); x++ ) {
float fX = ( 0.5f + x ) / image->s();
if( pf[0] < 1.0 ) {
float fMinZ = pf[0] * scale;
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
if( components > 1 ) {
float fMaxZ = scale * ( 1.f - pf[1] );
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
}
}
pf += components;
}
}
} else if( image->getDataType() == GL_UNSIGNED_BYTE ) {
unsigned char * pb = (unsigned char *)image->data();
float scale = 1.f / 254, bias = 0.5f;
for( int y = 0; y < image->t(); y++ ) {
float fY = ( 0.5f + y ) / image->t();
for( int x = 0; x < image->s(); x++ ) {
float fX = ( 0.5f + x ) / image->s();
if( pb[0] < 255 ) {
float fMinZ = scale * (pb[0] - 0.5f);
fMinZ = osg::clampTo( fMinZ, 0.f, 1.f );
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
if( components > 1 ) {
float fMaxZ = scale * (255 - pb[1] + 0.5f);
fMaxZ = osg::clampTo( fMaxZ, 0.f, 1.f );
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
}
}
pb += components;
}
}
}
return bb;
}
void MinimalDrawBoundsShadowMap::ViewData::performBoundAnalysis( const osg::Camera& camera )
{
if( !_projection.valid() )
return;
osg::Camera::BufferAttachmentMap & bam
= const_cast<osg::Camera&>( camera ).getBufferAttachmentMap();
#if ANALYSIS_DEPTH
osg::Camera::Attachment & attachment = bam[ osg::Camera::DEPTH_BUFFER ];
#else
osg::Camera::Attachment & attachment = bam[ osg::Camera::COLOR_BUFFER ];
#endif
const osg::ref_ptr< osg::Image > image = attachment._image.get();
if( !image.valid() )
return;
osg::Matrix m;
m.invert( *_modellingSpaceToWorldPtr *
camera.getViewMatrix() *
camera.getProjectionMatrix() );
m.preMult( osg::Matrix::scale( osg::Vec3( 2.f, 2.f, 2.f ) ) *
osg::Matrix::translate( osg::Vec3( -1.f, -1.f, -1.f ) ) );
osg::BoundingBox bb = scanImage( image.get(), m );
if( getDebugDraw() ) {
ConvexPolyhedron p;
p.setToBoundingBox( bb );
p.transform( *_modellingSpaceToWorldPtr,
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ) );
setDebugPolytope( "scan", p,
osg::Vec4( 0,0,0,1 ), osg::Vec4( 0,0,0,0.1 ) );
}
cutScenePolytope( *_modellingSpaceToWorldPtr,
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
frameShadowCastingCamera( _mainCamera.get(), _camera.get() );
_projection->set( _camera->getProjectionMatrix( ) );
BaseClass::ViewData::_texgen->setPlanesFromMatrix(
_camera->getProjectionMatrix() *
osg::Matrix::translate(1.0,1.0,1.0) *
osg::Matrix::scale(0.5,0.5,0.5) );
updateDebugGeometry( _mainCamera.get(), _camera.get() );
}
void MinimalDrawBoundsShadowMap::ViewData::recordShadowMapParams( )
{
const osgUtil::RenderStage * rs = _cv->getCurrentRenderBin()->getStage();
setShadowCameraProjectionMatrixPtr( _cv->getProjectionMatrix() );
if( !rs->getRenderBinList().empty() || rs->getBinNum() != 0 )
{
}
#if 0
MinimalShadowMap::RenderLeafList rll;
static unsigned pass = 0, c = 0;
pass++;
std::set< osg::ref_ptr< osg::RefMatrix > > projections;
MinimalShadowMap::GetRenderLeaves( , rll );
for( unsigned i =0; i < rll.size(); i++ ) {
if( rll[i]->_projection.get() != _projection.get() ) {
osg::RefMatrix * projection = rll[i]->_projection.get();
projections.insert( rll[i]->_projection );
c++;
}
}
if( projections.size() > 0 )
_projection = (*projections.begin()).get();
c = 0;
#endif
}
void MinimalDrawBoundsShadowMap::ViewData::init
( ThisClass *st, osgUtil::CullVisitor *cv )
{
BaseClass::ViewData::init( st, cv );
_camera->setCullCallback
( new CameraCullCallback( this, _camera->getCullCallback() ) );
_boundAnalysisTexture = new osg::Texture2D;
_boundAnalysisTexture->setTextureSize
( _boundAnalysisSize[0], _boundAnalysisSize[1] );
_boundAnalysisImage = new osg::Image;
#if ANALYSIS_DEPTH
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
_boundAnalysisSize[1], 1,
GL_DEPTH_COMPONENT, GL_FLOAT );
_boundAnalysisTexture->setInternalFormat(GL_DEPTH_COMPONENT);
// _boundAnalysisTexture->setShadowComparison(true);
_boundAnalysisTexture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
_boundAnalysisImage->setInternalTextureFormat( GL_DEPTH_COMPONENT );
_boundAnalysisTexture->setInternalFormat( GL_DEPTH_COMPONENT );
#else
#if USE_FLOAT_IMAGE
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
_boundAnalysisSize[1], 1,
GL_RGBA, GL_FLOAT );
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA16F_ARB );
_boundAnalysisTexture->setInternalFormat(GL_RGBA16F_ARB);
#else
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
_boundAnalysisSize[1], 1,
GL_RGBA, GL_UNSIGNED_BYTE );
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA );
_boundAnalysisTexture->setInternalFormat( GL_RGBA );
#endif
#endif
memset( _boundAnalysisImage->data(), 0, _boundAnalysisImage->getImageSizeInBytes() );
if( getDebugDraw() )
_boundAnalysisTexture->setImage(0, _boundAnalysisImage.get() );
_boundAnalysisTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
_boundAnalysisTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
// the shadow comparison should fail if object is outside the texture
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
// set up the render to texture camera.
// create the camera
_boundAnalysisCamera = new osg::Camera;
_boundAnalysisCamera->setName( "AnalysisCamera" );
_boundAnalysisCamera->setCullCallback( new BaseClass::CameraCullCallback(st) );
// _boundAnalysisCamera->setPreDrawCallback( _camera->getPreDrawCallback() );
_boundAnalysisCamera->setPostDrawCallback( new CameraPostDrawCallback(this) );
_boundAnalysisCamera->setClearColor( osg::Vec4(1,1,1,1) );
_boundAnalysisCamera->setClearMask(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
_boundAnalysisCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
// set viewport
_boundAnalysisCamera->setViewport
( 0, 0, _boundAnalysisSize[0], _boundAnalysisSize[1] );
// set the camera to render before the main camera.
_boundAnalysisCamera->setRenderOrder(osg::Camera::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
//_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
const int OVERRIDE_ON = osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON;
const int OVERRIDE_OFF = osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF;
osg::StateSet* stateset = _boundAnalysisCamera->getOrCreateStateSet();
stateset->setAttributeAndModes
( new osg::Depth( osg::Depth::LESS, 0.0, 254.f/255.f ), OVERRIDE_ON );
// stateset->setAttributeAndModes
// ( new osg::AlphaFunc( osg::AlphaFunc::EQUAL, 1.f ), OVERRIDE_ON );
stateset->setRenderBinDetails( 0, "RenderBin",
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
osg::Program* program = new osg::Program;
program->addShader( new osg::Shader( osg::Shader::FRAGMENT,
"uniform sampler2D texture; \n"
"void main(void) \n"
"{ \n"
#if ANALYSIS_DEPTH
" gl_FragColor = texture2D( texture, gl_TexCoord[0].xy ); \n"
#else
" gl_FragColor = vec4( gl_FragCoord.z, \n"
" 1.-gl_FragCoord.z, \n"
" 1., \n"
" texture2D( texture, gl_TexCoord[0].xy ).a ); \n"
#endif
"} \n"
) ); // program->addShader Fragment
program->addShader( new osg::Shader( osg::Shader::VERTEX,
"void main(void) \n"
"{ \n"
" gl_Position = ftransform(); \n"
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
"} \n"
) ); // program->addShader Vertex
stateset->setAttribute( program, OVERRIDE_ON );
// attach the texture and use it as the color buffer.
#if ANALYSIS_DEPTH
// _boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisTexture.get());
_boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisImage.get());
stateset->setMode( GL_BLEND, OVERRIDE_OFF );
#else
// _boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisTexture.get());
_boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisImage.get());
stateset->setAttributeAndModes
( new osg::BlendEquation( osg::BlendEquation::RGBA_MIN ), OVERRIDE_ON );
stateset->setMode( GL_DEPTH_TEST, OVERRIDE_OFF );
#endif
}
/* -*-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.
*/
#include <osgShadow/MinimalDrawBoundsShadowMap>
#include <osgShadow/ConvexPolyhedron>
#include <osg/PolygonOffset>
#include <osgUtil/RenderLeaf>
#include <osgShadow/ShadowedScene>
#include <osg/FrameBufferObject>
#include <osg/BlendEquation>
#include <osg/Depth>
#include <osg/AlphaFunc>
#include <osg/Image>
#include <iostream>
#include <string.h>
#define ANALYSIS_DEPTH 1
#define USE_FLOAT_IMAGE 1
using namespace osgShadow;
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap(): BaseClass()
{
}
MinimalDrawBoundsShadowMap::MinimalDrawBoundsShadowMap
(const MinimalDrawBoundsShadowMap& copy, const osg::CopyOp& copyop) :
BaseClass(copy,copyop)
{
}
MinimalDrawBoundsShadowMap::~MinimalDrawBoundsShadowMap()
{
}
void MinimalDrawBoundsShadowMap::ViewData::cullShadowReceivingScene( )
{
BaseClass::ViewData::cullShadowReceivingScene( );
ThisClass::ViewData::cullBoundAnalysisScene( );
}
void MinimalDrawBoundsShadowMap::ViewData::cullBoundAnalysisScene( )
{
_boundAnalysisCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF );
_boundAnalysisCamera->setViewMatrix( *_cv->getModelViewMatrix() );
_boundAnalysisCamera->setProjectionMatrix( _clampedProjection );
osg::Matrix::value_type l,r,b,t,n,f;
_boundAnalysisCamera->getProjectionMatrixAsFrustum( l,r,b,t,n,f );
_mainCamera = _cv->getRenderStage()->getCamera();
extendProjection( _boundAnalysisCamera->getProjectionMatrix(),
_boundAnalysisCamera->getViewport(), osg::Vec2( 2,2 ) );
// record the traversal mask on entry so we can reapply it later.
unsigned int traversalMask = _cv->getTraversalMask();
_cv->setTraversalMask( traversalMask &
_st->getShadowedScene()->getReceivesShadowTraversalMask() );
// do RTT camera traversal
_boundAnalysisCamera->accept(*_cv);
// reapply the original traversal mask
_cv->setTraversalMask( traversalMask );
}
void MinimalDrawBoundsShadowMap::ViewData::createDebugHUD( )
{
// _hudSize[0] *= 2;
_viewportSize[0] *= 2;
_orthoSize[0] *= 2;
MinimalShadowMap::ViewData::createDebugHUD( );
osg::Camera * camera = _cameraDebugHUD.get();
osg::Geode* geode = new osg::Geode;
camera->addChild( geode );
osg::Geometry* geometry = osg::createTexturedQuadGeometry
( osg::Vec3(_hudOrigin[0]+_hudSize[0],_hudOrigin[1],0),
osg::Vec3(_hudSize[0],0,0),
osg::Vec3(0,_hudSize[1],0) );
geode->addDrawable(geometry);
osg::StateSet* stateset = geometry->getOrCreateStateSet();
stateset->setTextureAttributeAndModes
(0, _boundAnalysisTexture.get(),osg::StateAttribute::ON );
#if ANALYSIS_DEPTH
osg::Program* program = new osg::Program;
program->addShader( _depthColorFragmentShader.get() );
stateset->setAttribute( program );
stateset->addUniform( new osg::Uniform( "texture" , 0 ) );
#else
#endif
}
osg::BoundingBox MinimalDrawBoundsShadowMap::ViewData::scanImage
( const osg::Image * image, osg::Matrix m )
{
osg::BoundingBox bb, bbProj;
int components = osg::Image::computeNumComponents( image->getPixelFormat() );
if( image->getDataType() == GL_FLOAT ) {
float scale = 255.f / 254.f;
float * pf = (float *)image->data();
for( int y = 0; y < image->t(); y++ ) {
float fY = ( 0.5f + y ) / image->t();
for( int x = 0; x < image->s(); x++ ) {
float fX = ( 0.5f + x ) / image->s();
if( pf[0] < 1.0 ) {
float fMinZ = pf[0] * scale;
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
if( components > 1 ) {
float fMaxZ = scale * ( 1.f - pf[1] );
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
}
}
pf += components;
}
}
} else if( image->getDataType() == GL_UNSIGNED_BYTE ) {
unsigned char * pb = (unsigned char *)image->data();
float scale = 1.f / 254, bias = 0.5f;
for( int y = 0; y < image->t(); y++ ) {
float fY = ( 0.5f + y ) / image->t();
for( int x = 0; x < image->s(); x++ ) {
float fX = ( 0.5f + x ) / image->s();
if( pb[0] < 255 ) {
float fMinZ = scale * (pb[0] - 0.5f);
fMinZ = osg::clampTo( fMinZ, 0.f, 1.f );
bbProj.expandBy( osg::Vec3( fX, fY, fMinZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMinZ ) * m );
if( components > 1 ) {
float fMaxZ = scale * (255 - pb[1] + 0.5f);
fMaxZ = osg::clampTo( fMaxZ, 0.f, 1.f );
bbProj.expandBy( osg::Vec3( fX, fY, fMaxZ ) );
bb.expandBy( osg::Vec3( fX, fY, fMaxZ ) * m );
}
}
pb += components;
}
}
}
return bb;
}
void MinimalDrawBoundsShadowMap::ViewData::performBoundAnalysis( const osg::Camera& camera )
{
if( !_projection.valid() )
return;
osg::Camera::BufferAttachmentMap & bam
= const_cast<osg::Camera&>( camera ).getBufferAttachmentMap();
#if ANALYSIS_DEPTH
osg::Camera::Attachment & attachment = bam[ osg::Camera::DEPTH_BUFFER ];
#else
osg::Camera::Attachment & attachment = bam[ osg::Camera::COLOR_BUFFER ];
#endif
const osg::ref_ptr< osg::Image > image = attachment._image.get();
if( !image.valid() )
return;
osg::Matrix m;
m.invert( *_modellingSpaceToWorldPtr *
camera.getViewMatrix() *
camera.getProjectionMatrix() );
m.preMult( osg::Matrix::scale( osg::Vec3( 2.f, 2.f, 2.f ) ) *
osg::Matrix::translate( osg::Vec3( -1.f, -1.f, -1.f ) ) );
osg::BoundingBox bb = scanImage( image.get(), m );
if( getDebugDraw() ) {
ConvexPolyhedron p;
p.setToBoundingBox( bb );
p.transform( *_modellingSpaceToWorldPtr,
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ) );
setDebugPolytope( "scan", p,
osg::Vec4( 0,0,0,1 ), osg::Vec4( 0,0,0,0.1 ) );
}
cutScenePolytope( *_modellingSpaceToWorldPtr,
osg::Matrix::inverse( *_modellingSpaceToWorldPtr ), bb );
frameShadowCastingCamera( _mainCamera.get(), _camera.get() );
_projection->set( _camera->getProjectionMatrix( ) );
BaseClass::ViewData::_texgen->setPlanesFromMatrix(
_camera->getProjectionMatrix() *
osg::Matrix::translate(1.0,1.0,1.0) *
osg::Matrix::scale(0.5,0.5,0.5) );
updateDebugGeometry( _mainCamera.get(), _camera.get() );
}
void MinimalDrawBoundsShadowMap::ViewData::recordShadowMapParams( )
{
const osgUtil::RenderStage * rs = _cv->getCurrentRenderBin()->getStage();
setShadowCameraProjectionMatrixPtr( _cv->getProjectionMatrix() );
if( !rs->getRenderBinList().empty() || rs->getBinNum() != 0 )
{
}
#if 0
MinimalShadowMap::RenderLeafList rll;
static unsigned pass = 0, c = 0;
pass++;
std::set< osg::ref_ptr< osg::RefMatrix > > projections;
MinimalShadowMap::GetRenderLeaves( , rll );
for( unsigned i =0; i < rll.size(); i++ ) {
if( rll[i]->_projection.get() != _projection.get() ) {
osg::RefMatrix * projection = rll[i]->_projection.get();
projections.insert( rll[i]->_projection );
c++;
}
}
if( projections.size() > 0 )
_projection = (*projections.begin()).get();
c = 0;
#endif
}
void MinimalDrawBoundsShadowMap::ViewData::init
( ThisClass *st, osgUtil::CullVisitor *cv )
{
BaseClass::ViewData::init( st, cv );
_camera->setCullCallback
( new CameraCullCallback( this, _camera->getCullCallback() ) );
_boundAnalysisTexture = new osg::Texture2D;
_boundAnalysisTexture->setTextureSize
( _boundAnalysisSize[0], _boundAnalysisSize[1] );
_boundAnalysisImage = new osg::Image;
#if ANALYSIS_DEPTH
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
_boundAnalysisSize[1], 1,
GL_DEPTH_COMPONENT, GL_FLOAT );
_boundAnalysisTexture->setInternalFormat(GL_DEPTH_COMPONENT);
// _boundAnalysisTexture->setShadowComparison(true);
_boundAnalysisTexture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
_boundAnalysisImage->setInternalTextureFormat( GL_DEPTH_COMPONENT );
_boundAnalysisTexture->setInternalFormat( GL_DEPTH_COMPONENT );
#else
#if USE_FLOAT_IMAGE
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
_boundAnalysisSize[1], 1,
GL_RGBA, GL_FLOAT );
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA16F_ARB );
_boundAnalysisTexture->setInternalFormat(GL_RGBA16F_ARB);
#else
_boundAnalysisImage->allocateImage( _boundAnalysisSize[0],
_boundAnalysisSize[1], 1,
GL_RGBA, GL_UNSIGNED_BYTE );
_boundAnalysisImage->setInternalTextureFormat( GL_RGBA );
_boundAnalysisTexture->setInternalFormat( GL_RGBA );
#endif
#endif
memset( _boundAnalysisImage->data(), 0, _boundAnalysisImage->getImageSizeInBytes() );
if( getDebugDraw() )
_boundAnalysisTexture->setImage(0, _boundAnalysisImage.get() );
_boundAnalysisTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST);
_boundAnalysisTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
// the shadow comparison should fail if object is outside the texture
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
_boundAnalysisTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
// set up the render to texture camera.
// create the camera
_boundAnalysisCamera = new osg::Camera;
_boundAnalysisCamera->setName( "AnalysisCamera" );
_boundAnalysisCamera->setCullCallback( new BaseClass::CameraCullCallback(st) );
// _boundAnalysisCamera->setPreDrawCallback( _camera->getPreDrawCallback() );
_boundAnalysisCamera->setPostDrawCallback( new CameraPostDrawCallback(this) );
_boundAnalysisCamera->setClearColor( osg::Vec4(1,1,1,1) );
_boundAnalysisCamera->setClearMask(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
_boundAnalysisCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
// set viewport
_boundAnalysisCamera->setViewport
( 0, 0, _boundAnalysisSize[0], _boundAnalysisSize[1] );
// set the camera to render before the main camera.
_boundAnalysisCamera->setRenderOrder(osg::Camera::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
//_boundAnalysisCamera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
const int OVERRIDE_ON = osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON;
const int OVERRIDE_OFF = osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF;
osg::StateSet* stateset = _boundAnalysisCamera->getOrCreateStateSet();
stateset->setAttributeAndModes
( new osg::Depth( osg::Depth::LESS, 0.0, 254.f/255.f ), OVERRIDE_ON );
// stateset->setAttributeAndModes
// ( new osg::AlphaFunc( osg::AlphaFunc::EQUAL, 1.f ), OVERRIDE_ON );
stateset->setRenderBinDetails( 0, "RenderBin",
osg::StateSet::OVERRIDE_RENDERBIN_DETAILS );
osg::Program* program = new osg::Program;
program->addShader( new osg::Shader( osg::Shader::FRAGMENT,
"uniform sampler2D texture; \n"
"void main(void) \n"
"{ \n"
#if ANALYSIS_DEPTH
" gl_FragColor = texture2D( texture, gl_TexCoord[0].xy ); \n"
#else
" gl_FragColor = vec4( gl_FragCoord.z, \n"
" 1.-gl_FragCoord.z, \n"
" 1., \n"
" texture2D( texture, gl_TexCoord[0].xy ).a ); \n"
#endif
"} \n"
) ); // program->addShader Fragment
program->addShader( new osg::Shader( osg::Shader::VERTEX,
"void main(void) \n"
"{ \n"
" gl_Position = ftransform(); \n"
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
"} \n"
) ); // program->addShader Vertex
stateset->setAttribute( program, OVERRIDE_ON );
// attach the texture and use it as the color buffer.
#if ANALYSIS_DEPTH
// _boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisTexture.get());
_boundAnalysisCamera->attach(osg::Camera::DEPTH_BUFFER, _boundAnalysisImage.get());
stateset->setMode( GL_BLEND, OVERRIDE_OFF );
#else
// _boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisTexture.get());
_boundAnalysisCamera->attach(osg::Camera::COLOR_BUFFER, _boundAnalysisImage.get());
stateset->setAttributeAndModes
( new osg::BlendEquation( osg::BlendEquation::RGBA_MIN ), OVERRIDE_ON );
stateset->setMode( GL_DEPTH_TEST, OVERRIDE_OFF );
#endif
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,127 +1,127 @@
/* -*-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.
*/
#include <osgShadow/ViewDependentShadowTechnique>
#include <osgShadow/ShadowedScene>
using namespace osgShadow;
ViewDependentShadowTechnique::ViewDependentShadowTechnique()
{
dirty();
}
ViewDependentShadowTechnique::ViewDependentShadowTechnique
(const ViewDependentShadowTechnique& copy, const osg::CopyOp& copyop):
ShadowTechnique(copy,copyop)
{
dirty();
}
ViewDependentShadowTechnique::~ViewDependentShadowTechnique(void)
{
}
void ViewDependentShadowTechnique::traverse(osg::NodeVisitor& nv)
{
osgShadow::ShadowTechnique::traverse(nv);
}
void ViewDependentShadowTechnique::dirty()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
osgShadow::ShadowTechnique::_dirty = true;
for( ViewDataMap::iterator mitr = _viewDataMap.begin();
mitr != _viewDataMap.end();
++mitr )
{
mitr->second->dirty( true );
}
}
void ViewDependentShadowTechnique::init()
{
//osgShadow::ShadowTechnique::init( );
osgShadow::ShadowTechnique::_dirty = false;
}
void ViewDependentShadowTechnique::update(osg::NodeVisitor& nv)
{
//osgShadow::ShadowTechnique::update( nv );
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(nv);
}
void ViewDependentShadowTechnique::cull(osgUtil::CullVisitor& cv)
{
//osgShadow::ShadowTechnique::cull( cv );
ViewData * vd = getViewDependentData( &cv );
if ( !vd || vd->_dirty || vd->_cv != &cv || vd->_st != this ) {
vd = initViewDependentData( &cv, vd );
setViewDependentData( &cv, vd );
}
if( vd ) {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(vd->_mutex);
vd->cull();
} else {
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(cv);
}
}
void ViewDependentShadowTechnique::cleanSceneGraph()
{
//osgShadow::ShadowTechnique::cleanSceneGraph( );
}
ViewDependentShadowTechnique::ViewData *
ViewDependentShadowTechnique::getViewDependentData( osgUtil::CullVisitor * cv )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
return _viewDataMap[ cv ].get();
}
void ViewDependentShadowTechnique::setViewDependentData
( osgUtil::CullVisitor * cv, ViewData * data )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
_viewDataMap[ cv ] = data;
}
void ViewDependentShadowTechnique::ViewData::dirty( bool flag )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
_dirty = flag;
}
void ViewDependentShadowTechnique::ViewData::init
( ViewDependentShadowTechnique *st, osgUtil::CullVisitor * cv )
{
_cv = cv;
_st = st;
dirty( false );
}
void ViewDependentShadowTechnique::ViewData::cull( void )
{
}
/* -*-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.
*/
#include <osgShadow/ViewDependentShadowTechnique>
#include <osgShadow/ShadowedScene>
using namespace osgShadow;
ViewDependentShadowTechnique::ViewDependentShadowTechnique()
{
dirty();
}
ViewDependentShadowTechnique::ViewDependentShadowTechnique
(const ViewDependentShadowTechnique& copy, const osg::CopyOp& copyop):
ShadowTechnique(copy,copyop)
{
dirty();
}
ViewDependentShadowTechnique::~ViewDependentShadowTechnique(void)
{
}
void ViewDependentShadowTechnique::traverse(osg::NodeVisitor& nv)
{
osgShadow::ShadowTechnique::traverse(nv);
}
void ViewDependentShadowTechnique::dirty()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
osgShadow::ShadowTechnique::_dirty = true;
for( ViewDataMap::iterator mitr = _viewDataMap.begin();
mitr != _viewDataMap.end();
++mitr )
{
mitr->second->dirty( true );
}
}
void ViewDependentShadowTechnique::init()
{
//osgShadow::ShadowTechnique::init( );
osgShadow::ShadowTechnique::_dirty = false;
}
void ViewDependentShadowTechnique::update(osg::NodeVisitor& nv)
{
//osgShadow::ShadowTechnique::update( nv );
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(nv);
}
void ViewDependentShadowTechnique::cull(osgUtil::CullVisitor& cv)
{
//osgShadow::ShadowTechnique::cull( cv );
ViewData * vd = getViewDependentData( &cv );
if ( !vd || vd->_dirty || vd->_cv != &cv || vd->_st != this ) {
vd = initViewDependentData( &cv, vd );
setViewDependentData( &cv, vd );
}
if( vd ) {
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(vd->_mutex);
vd->cull();
} else {
osgShadow::ShadowTechnique::_shadowedScene->osg::Group::traverse(cv);
}
}
void ViewDependentShadowTechnique::cleanSceneGraph()
{
//osgShadow::ShadowTechnique::cleanSceneGraph( );
}
ViewDependentShadowTechnique::ViewData *
ViewDependentShadowTechnique::getViewDependentData( osgUtil::CullVisitor * cv )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
return _viewDataMap[ cv ].get();
}
void ViewDependentShadowTechnique::setViewDependentData
( osgUtil::CullVisitor * cv, ViewData * data )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
_viewDataMap[ cv ] = data;
}
void ViewDependentShadowTechnique::ViewData::dirty( bool flag )
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
_dirty = flag;
}
void ViewDependentShadowTechnique::ViewData::init
( ViewDependentShadowTechnique *st, osgUtil::CullVisitor * cv )
{
_cv = cv;
_st = st;
dirty( false );
}
void ViewDependentShadowTechnique::ViewData::cull( void )
{
}