Hi Robert,
I've found a way to get it working by slightly modifying CullStack.cpp
and by also changing my cull callback. When pushing the CullingSet in
CullStack I have added updating the cull mask in the new CullingSet. I
needed to change both the cull visitors culling mode and the current
CullingSets mask in the callback, because I didn't find a way to
propagate the changed mode from the CullVisitor to the current CullingSet.
I'm cross posting to osg-submissions and have attached the modified
CullStack.cpp, I've also attached a modified osgscribe.cpp that shows
the problem. When zooming out one model should always be visible but the
other shall disappear when it gets less than 200 pixels in size.
Regards,
Per
Robert Osfield wrote:
Hi Per,
It sounds like you'll need to directly manipulator or push new
settings on the stack in CullVisitor.
Robert.
On Mon, Dec 15, 2008 at 10:12 AM, Per Fahlberg <[email protected]> wrote:
Hi Robert,
I've traced the problem down now and it seems the culling mode that the
CullVisitor uses is correct but the one in the CullingSet is incorrect. This
is due to the CullingSet being updated in CullStack::pushProjectionMatrix
which is called early on in culling, and when I change the culling mode in
my callback it only changes the mode in the CullVisitor and not the mode in
the CullingSet.
Since I'm not very familiar with the internals in the culling code I would
like to ask for some guidance before I dive in and try to code up a fix for
the problem. Do you know of a place in the code where the culling set might
be updated to reflect the changes in the CullVisitor/CullStack or should I
try to directly propagate the changes from the CullSettings::setCullingMode
down via CullStack to the CullingSet?
Regards,
Per
Robert Osfield wrote:
Hi Per,
On Tue, Dec 2, 2008 at 11:34 AM, Per Fahlberg <[email protected]> wrote:
Perhaps I wasn't clear in my question so I will try once more, is there a
way to disable small feature culling for just a subgraph not the entire
scene?
The only way is is use a cull callback to cache the previous setting,
set the new setting do the traverse and the restore the original
value. Your original callback does this, but I don't know why it
doesn't work. Note, I haven't tried it myself so I can't provide any
further direction, you'll just have to dig into the source code.
Robert.
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
/* -*-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.
*/
#include <osg/CullStack>
#include <osg/Timer>
#include <osg/Notify>
#include <osg/io_utils>
using namespace osg;
CullStack::CullStack()
{
_frustumVolume=-1.0f;
_bbCornerNear = 0;
_bbCornerFar = 7;
_currentReuseMatrixIndex=0;
_identity = new RefMatrix();
_index_modelviewCullingStack = 0;
_back_modelviewCullingStack = 0;
_referenceViewPoints.push_back(osg::Vec3(0.0f,0.0f,0.0f));
}
CullStack::CullStack(const CullStack& cs):
CullSettings(cs)
{
_frustumVolume=-1.0f;
_bbCornerNear = 0;
_bbCornerFar = 7;
_currentReuseMatrixIndex=0;
_identity = new RefMatrix();
_index_modelviewCullingStack = 0;
_back_modelviewCullingStack = 0;
_referenceViewPoints.push_back(osg::Vec3(0.0f,0.0f,0.0f));
}
CullStack::~CullStack()
{
reset();
}
void CullStack::reset()
{
//
// first unref all referenced objects and then empty the containers.
//
_projectionStack.clear();
_modelviewStack.clear();
_viewportStack.clear();
_referenceViewPoints.clear();
_referenceViewPoints.push_back(osg::Vec3(0.0f,0.0f,0.0f));
_eyePointStack.clear();
_viewPointStack.clear();
_clipspaceCullingStack.clear();
_projectionCullingStack.clear();
//_modelviewCullingStack.clear();
_index_modelviewCullingStack=0;
_back_modelviewCullingStack = 0;
osg::Vec3 lookVector(0.0,0.0,-1.0);
_bbCornerFar = (lookVector.x()>=0?1:0) |
(lookVector.y()>=0?2:0) |
(lookVector.z()>=0?4:0);
_bbCornerNear = (~_bbCornerFar)&7;
_currentReuseMatrixIndex=0;
}
void CullStack::pushCullingSet()
{
_MVPW_Stack.push_back(0L);
if (_index_modelviewCullingStack==0)
{
if (_modelviewCullingStack.empty())
_modelviewCullingStack.push_back(CullingSet());
_modelviewCullingStack[_index_modelviewCullingStack++].set(_projectionCullingStack.back());
}
else
{
const osg::Viewport& W = *_viewportStack.back();
const osg::Matrix& P = *_projectionStack.back();
const osg::Matrix& M = *_modelviewStack.back();
osg::Vec4 pixelSizeVector = CullingSet::computePixelSizeVector(W,P,M);
if (_index_modelviewCullingStack>=_modelviewCullingStack.size())
{
_modelviewCullingStack.push_back(CullingSet());
}
_modelviewCullingStack[_index_modelviewCullingStack++].set(_projectionCullingStack.back(),*_modelviewStack.back(),pixelSizeVector);
}
_back_modelviewCullingStack = &_modelviewCullingStack[_index_modelviewCullingStack-1];
_back_modelviewCullingStack->setCullingMask(_cullingMode);
_back_modelviewCullingStack->setSmallFeatureCullingPixelSize(_smallFeatureCullingPixelSize);
// const osg::Polytope& polytope = _modelviewCullingStack.back()->getFrustum();
// const osg::Polytope::PlaneList& pl = polytope.getPlaneList();
// std::cout <<"new cull stack"<<std::endl;
// for(osg::Polytope::PlaneList::const_iterator pl_itr=pl.begin();
// pl_itr!=pl.end();
// ++pl_itr)
// {
// std::cout << " plane "<<*pl_itr<<std::endl;
// }
}
void CullStack::popCullingSet()
{
_MVPW_Stack.pop_back();
--_index_modelviewCullingStack;
if (_index_modelviewCullingStack>0) _back_modelviewCullingStack = &_modelviewCullingStack[_index_modelviewCullingStack-1];
}
void CullStack::pushViewport(osg::Viewport* viewport)
{
_viewportStack.push_back(viewport);
_MVPW_Stack.push_back(0L);
}
void CullStack::popViewport()
{
_viewportStack.pop_back();
_MVPW_Stack.pop_back();
}
void CullStack::pushProjectionMatrix(RefMatrix* matrix)
{
_projectionStack.push_back(matrix);
_projectionCullingStack.push_back(osg::CullingSet());
osg::CullingSet& cullingSet = _projectionCullingStack.back();
// set up view frustum.
cullingSet.getFrustum().setToUnitFrustum(((_cullingMode&NEAR_PLANE_CULLING)!=0),((_cullingMode&FAR_PLANE_CULLING)!=0));
cullingSet.getFrustum().transformProvidingInverse(*matrix);
// set the culling mask ( There should be a more elegant way!) Nikolaus H.
cullingSet.setCullingMask(_cullingMode);
// set the small feature culling.
cullingSet.setSmallFeatureCullingPixelSize(_smallFeatureCullingPixelSize);
// set up the relevant occluders which a related to this projection.
for(ShadowVolumeOccluderList::iterator itr=_occluderList.begin();
itr!=_occluderList.end();
++itr)
{
//std::cout << " ** testing occluder"<<std::endl;
if (itr->matchProjectionMatrix(*matrix))
{
//std::cout << " ** activating occluder"<<std::endl;
cullingSet.addOccluder(*itr);
}
}
// need to recompute frustum volume.
_frustumVolume = -1.0f;
pushCullingSet();
}
void CullStack::popProjectionMatrix()
{
_projectionStack.pop_back();
_projectionCullingStack.pop_back();
// need to recompute frustum volume.
_frustumVolume = -1.0f;
popCullingSet();
}
void CullStack::pushModelViewMatrix(RefMatrix* matrix, Transform::ReferenceFrame referenceFrame)
{
osg::RefMatrix* originalModelView = _modelviewStack.empty() ? 0 : _modelviewStack.back().get();
_modelviewStack.push_back(matrix);
pushCullingSet();
osg::Matrix inv;
inv.invert(*matrix);
switch(referenceFrame)
{
case(Transform::RELATIVE_RF):
_eyePointStack.push_back(inv.getTrans());
_referenceViewPoints.push_back(getReferenceViewPoint());
_viewPointStack.push_back(getReferenceViewPoint() * inv);
break;
case(Transform::ABSOLUTE_RF):
_eyePointStack.push_back(inv.getTrans());
_referenceViewPoints.push_back(osg::Vec3(0.0,0.0,0.0));
_viewPointStack.push_back(_eyePointStack.back());
break;
case(Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT):
{
_eyePointStack.push_back(inv.getTrans());
osg::Vec3 referenceViewPoint = getReferenceViewPoint();
if (originalModelView)
{
osg::Matrix viewPointTransformMatrix;
viewPointTransformMatrix.invert(*originalModelView);
viewPointTransformMatrix.postMult(*matrix);
referenceViewPoint = referenceViewPoint * viewPointTransformMatrix;
}
_referenceViewPoints.push_back(referenceViewPoint);
_viewPointStack.push_back(getReferenceViewPoint() * inv);
break;
}
}
osg::Vec3 lookVector = getLookVectorLocal();
_bbCornerFar = (lookVector.x()>=0?1:0) |
(lookVector.y()>=0?2:0) |
(lookVector.z()>=0?4:0);
_bbCornerNear = (~_bbCornerFar)&7;
}
void CullStack::popModelViewMatrix()
{
_modelviewStack.pop_back();
_eyePointStack.pop_back();
_referenceViewPoints.pop_back();
_viewPointStack.pop_back();
popCullingSet();
osg::Vec3 lookVector(0.0f,0.0f,-1.0f);
if (!_modelviewStack.empty())
{
lookVector = getLookVectorLocal();
}
_bbCornerFar = (lookVector.x()>=0?1:0) |
(lookVector.y()>=0?2:0) |
(lookVector.z()>=0?4:0);
_bbCornerNear = (~_bbCornerFar)&7;
}
void CullStack::computeFrustumVolume()
{
osg::Matrix invP;
invP.invert(*getProjectionMatrix());
osg::Vec3 f1(-1,-1,-1); f1 = f1*invP;
osg::Vec3 f2(-1, 1,-1); f2 = f2*invP;
osg::Vec3 f3( 1, 1,-1); f3 = f3*invP;
osg::Vec3 f4( 1,-1,-1); f4 = f4*invP;
osg::Vec3 b1(-1,-1,1); b1 = b1*invP;
osg::Vec3 b2(-1, 1,1); b2 = b2*invP;
osg::Vec3 b3( 1, 1,1); b3 = b3*invP;
osg::Vec3 b4( 1,-1,1); b4 = b4*invP;
_frustumVolume = computeVolume(f1,f2,f3,b1,b2,b3)+
computeVolume(f2,f3,f4,b1,b3,b4);
}
/* OpenSceneGraph example, osgscribe.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osg/Geode>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Material>
#include <osg/PolygonOffset>
#include <osg/PolygonMode>
#include <osg/LineStipple>
#include <osg/PositionAttitudeTransform>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgViewer/Viewer>
#include <osgUtil/Optimizer>
class MyCullingCallback : public osg::NodeCallback
{
public:
MyCullingCallback() : osg::NodeCallback()
{}
virtual void operator() (osg::Node *node, osg::NodeVisitor *nv)
{
osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if(cv){
osg::CullSettings::CullingMode cullVisitorCullingMode = cv->getCullingMode();
osg::CullingSet &cs = cv->getCurrentCullingSet();
osg::CullingSet::Mask cullingSetMask = cs.getCullingMask();
cv->setCullingMode(cullVisitorCullingMode & ~osg::CullSettings::SMALL_FEATURE_CULLING);
cs.setCullingMask(cullingSetMask & ~osg::CullSettings::SMALL_FEATURE_CULLING);
traverse(node,nv);
cs.setCullingMask(cullingSetMask);
cv->setCullingMode(cullVisitorCullingMode);
}else
traverse(node,nv);
}
};
int main( int argc, char **argv )
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
// construct the viewer.
osgViewer::Viewer viewer;
osg::Camera *cam = viewer.getCamera();
if(cam){
cam->setCullingMode(osgUtil::CullVisitor::VIEW_FRUSTUM_CULLING | osgUtil::CullVisitor::SMALL_FEATURE_CULLING);
cam->setSmallFeatureCullingPixelSize(200);
}
// load the nodes from the commandline arguments.
osg::Node* loadedModel = osgDB::readNodeFiles(arguments);
// if not loaded assume no arguments passed in, try use default mode instead.
if (!loadedModel) loadedModel = osgDB::readNodeFile("cow.osg");
if (!loadedModel)
{
osg::notify(osg::NOTICE)<<"Please specifiy a model filename on the command line."<<std::endl;
return 1;
}
osg::Group* rootnode = new osg::Group;
rootnode->addChild(loadedModel);
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
pat->setPosition(osg::Vec3d(20, 0, 0));
osg::Group *tmp = new osg::Group;
tmp->setCullCallback(new MyCullingCallback);
tmp->setCullingActive(false);
tmp->addChild(pat);
rootnode->addChild(tmp);
pat->addChild(loadedModel);
// add a viewport to the viewer and attach the scene graph.
viewer.setSceneData( rootnode );
return viewer.run();
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org