I've attached an improved IntersectionVisitor that takes into account the model transform above the relative camera. Though, still not working properly when child camera view matrix is changed. :-(
Chris.

----- Original Message ----- From: "Chris Denham" <[EMAIL PROTECTED]> To: "Robert Osfield" <[EMAIL PROTECTED]>; "OpenSceneGraph Submissions" <[email protected]>
Sent: Friday, October 31, 2008 10:46 AM
Subject: Re: [osg-users] Problem with computeIntersections for nodes below post render camera


Oh rats! I've just discovered that my submission to fix this problem may be
incorrect or incomplete.
It seems that my change does not work for non-identy transforms on or above
the relative camera.
e.g  if I use camera->setViewMatrix or add the camera to a transform node.
I have attached a new version of osgpick to show the problem.

I think the root of the problem is that my attempt to transfer the logic of
CullVisitor::apply(Camera) into IntersectionVisitor::apply(Camera) is
incomplete. i.e. I used getViewMatrix in place of getModelViewMatrix.
arggggg.
And.... IntersectionVisitor::apply(Camera) still assumes an identity model
matrix.

I'm not really sure how to fix this because (CullStack::getModelViewMatrix
/ pushModelViewMatrix / popModelViewMatrix) are not available in
IntersectionVisitor, and I don't really understand enough of what is going
on to migrate that logic properly.

I'm wondering if my submission should be reverted until this has been
resolved in a better way?

Any thoughts on a better solution to the problem? It also occurred to me
that yet another can of worms may be opened if the relative camera has a
different viewport from the main camera... urgg...so... should
IntersectionVistor be traversing child cameras at all in that case?

Chris.


----- Original Message ----- From: "Chris Denham" <[EMAIL PROTECTED]>
To: "Robert Osfield" <[EMAIL PROTECTED]>; "OpenSceneGraph
Submissions" <[email protected]>
Sent: Monday, October 27, 2008 5:58 PM
Subject: Re: [osg-users] Problem with computeIntersections for nodes below
post render camera


Here's the modified osgpick example again with a command line option to
load
the test scene.
e.g. osgpick --relative-camera-scene
Chris.

----- Original Message ----- From: "Chris Denham" <[EMAIL PROTECTED]>
To: "Robert Osfield" <[EMAIL PROTECTED]>
Cc: "OpenSceneGraph Submissions"
<[email protected]>
Sent: Monday, October 27, 2008 5:18 PM
Subject: Re: [osg-users] Problem with computeIntersections for nodes below
post render camera


Thanks Robert,
I hadn't anticipated you checking also checking in the modified osgpick
example.
This may not be quite what you might intend, since the default scene used
to be "fountain.osg", but now has my rather disconcerting scene. Perhaps
my test scene would be better to be the default if the default
fountain.osg is not found.
I'll submit the osgpick.cpp file again if you think that is better.
Chris.



/* -*-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 <osgUtil/IntersectionVisitor>

#include <osg/PagedLOD>
#include <osg/Transform>
#include <osg/Projection>
#include <osg/Camera>
#include <osg/Geode>
#include <osg/Billboard>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/io_utils>

using namespace osgUtil;


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  IntersectorGroup
//

IntersectorGroup::IntersectorGroup()
{
}

void IntersectorGroup::addIntersector(Intersector* intersector)
{
   _intersectors.push_back(intersector);
}

void IntersectorGroup::clear()
{
   _intersectors.clear();
}

Intersector* IntersectorGroup::clone(osgUtil::IntersectionVisitor& iv)
{
   IntersectorGroup* ig = new IntersectorGroup;
// now copy across all intersectors that arn't disabled.
   for(Intersectors::iterator itr = _intersectors.begin();
       itr != _intersectors.end();
       ++itr)
   {
       if (!(*itr)->disabled())
       {
           ig->addIntersector( (*itr)->clone(iv) );
       }
   }

   return ig;
}

bool IntersectorGroup::enter(const osg::Node& node)
{
   if (disabled()) return false;
bool foundIntersections = false; for(Intersectors::iterator itr = _intersectors.begin();
       itr != _intersectors.end();
       ++itr)
   {
       if ((*itr)->disabled()) (*itr)->incrementDisabledCount();
       else if ((*itr)->enter(node)) foundIntersections = true;
       else (*itr)->incrementDisabledCount();
   }
if (!foundIntersections) {
       // need to call leave to clean up the DisabledCount's.
       leave();
       return false;
   }
// we have found at least one suitable intersector, so return true
   return true;
}

void IntersectorGroup::leave()
{
   for(Intersectors::iterator itr = _intersectors.begin();
       itr != _intersectors.end();
       ++itr)
   {
       if ((*itr)->disabled()) (*itr)->decrementDisabledCount();
   }
}

void IntersectorGroup::intersect(osgUtil::IntersectionVisitor& iv, 
osg::Drawable* drawable)
{
   if (disabled()) return;

   unsigned int numTested = 0;
   for(Intersectors::iterator itr = _intersectors.begin();
       itr != _intersectors.end();
       ++itr)
   {
       if (!(*itr)->disabled())
       {
           (*itr)->intersect(iv, drawable);
++numTested;
       }
   }
// osg::notify(osg::NOTICE)<<"Number testing "<<numTested<<std::endl;

}

void IntersectorGroup::reset()
{
   Intersector::reset();
for(Intersectors::iterator itr = _intersectors.begin();
       itr != _intersectors.end();
       ++itr)
   {
       (*itr)->reset();
   }
}

bool IntersectorGroup::containsIntersections()
{
   for(Intersectors::iterator itr = _intersectors.begin();
       itr != _intersectors.end();
       ++itr)
   {
       if ((*itr)->containsIntersections()) return true;
   }
   return false;
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  IntersectionVisitor
//

IntersectionVisitor::IntersectionVisitor(Intersector* intersector, 
ReadCallback* readCallback)
{
   // override the default node visitor mode.
   setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
_useKdTreesWhenAvailable = true;
   _dummyTraversal = false;

   setIntersector(intersector);
setReadCallback(readCallback);
}

void IntersectionVisitor::setIntersector(Intersector* intersector)
{
   // keep reference around just in case intersector is already in the 
_intersectorStack, otherwise the clear could delete it.
   osg::ref_ptr<Intersector> temp = intersector;

   _intersectorStack.clear();

   if (intersector) _intersectorStack.push_back(intersector);
}

void IntersectionVisitor::reset()
{
   if (!_intersectorStack.empty())
   {
       osg::ref_ptr<Intersector> intersector = _intersectorStack.front();
       intersector->reset();
_intersectorStack.clear();
       _intersectorStack.push_back(intersector);
   }
}

void IntersectionVisitor::apply(osg::Node& node)
{
   // osg::notify(osg::NOTICE)<<"apply(Node&)"<<std::endl;

   if (!enter(node)) return;

   // osg::notify(osg::NOTICE)<<"inside apply(Node&)"<<std::endl;

   traverse(node);

   leave();
}

void IntersectionVisitor::apply(osg::Group& group)
{
   if (!enter(group)) return;

   traverse(group);

   leave();
}

void IntersectionVisitor::apply(osg::Geode& geode)
{
   // osg::notify(osg::NOTICE)<<"apply(Geode&)"<<std::endl;

   if (!enter(geode)) return;

   // osg::notify(osg::NOTICE)<<"inside apply(Geode&)"<<std::endl;

   for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
   {
       intersect( geode.getDrawable(i) );
   }

   leave();
}

void IntersectionVisitor::apply(osg::Billboard& billboard)
{
   if (!enter(billboard)) return;

   for(unsigned int i=0; i<billboard.getNumDrawables(); ++i)
   {
       intersect( billboard.getDrawable(i) );
   }

   leave();
}

void IntersectionVisitor::apply(osg::LOD& lod)
{
   if (!enter(lod)) return;

   traverse(lod);

   leave();
}


void IntersectionVisitor::apply(osg::PagedLOD& plod)
{
   if (!enter(plod)) return;

   if (plod.getNumFileNames()>0)
   {
#if 1
       // Identify the range value for the highest res child
       float targetRangeValue;
       if( plod.getRangeMode() == osg::LOD::DISTANCE_FROM_EYE_POINT )
           targetRangeValue = 1e6; // Init high to find min value
       else
           targetRangeValue = 0; // Init low to find max value
const osg::LOD::RangeList rl = plod.getRangeList();
       osg::LOD::RangeList::const_iterator rit;
       for( rit = rl.begin();
            rit != rl.end();
            rit++ )
       {
           if( plod.getRangeMode() == osg::LOD::DISTANCE_FROM_EYE_POINT )
           {
               if( rit->first < targetRangeValue )
                   targetRangeValue = rit->first;
           }
           else
           {
               if( rit->first > targetRangeValue )
                   targetRangeValue = rit->first;
           }
       }

       // Perform an intersection test only on children that display
       // at the maximum resolution.
       unsigned int childIndex;
       for( rit = rl.begin(), childIndex = 0;
            rit != rl.end();
            rit++, childIndex++ )
       {
           if( rit->first != targetRangeValue )
               // This is not one of the highest res children
               continue;

           osg::ref_ptr<osg::Node> child( NULL );
           if( plod.getNumChildren() > childIndex )
               child = plod.getChild( childIndex );

           if( (!child.valid()) && (_readCallback.valid()) )
           {
               // Child is NULL; attempt to load it, if we have a 
readCallback...
               unsigned int validIndex( childIndex );
               if (plod.getNumFileNames() <= childIndex)
                   validIndex = plod.getNumFileNames()-1;

               child = _readCallback->readNodeFile( plod.getDatabasePath() + 
plod.getFileName( validIndex ) );
           }

           if ( !child.valid() && plod.getNumChildren()>0)
           {
               // Child is still NULL, so just use the one at the end of the 
list.
               child = plod.getChild( plod.getNumChildren()-1 );
           }

           if (child.valid())
           {
               child->accept(*this);
           }
       }
#else // older code than above block, that assumes that the PagedLOD is ordered correctly
       // i.e. low res children first, no duplicate ranges.
osg::ref_ptr<osg::Node> highestResChild;

       if (plod.getNumFileNames() != plod.getNumChildren() && 
_readCallback.valid())
       {
           highestResChild = _readCallback->readNodeFile( 
plod.getDatabasePath() + plod.getFileName(plod.getNumFileNames()-1) );
       }
if ( !highestResChild.valid() && plod.getNumChildren()>0)
       {
           highestResChild = plod.getChild( plod.getNumChildren()-1 );
       }

       if (highestResChild.valid())
       {
           highestResChild->accept(*this);
       }
#endif
   }

   leave();
}


void IntersectionVisitor::apply(osg::Transform& transform)
{
   if (!enter(transform)) return;

   osg::ref_ptr<osg::RefMatrix> matrix = _modelStack.empty() ? new 
osg::RefMatrix() : new osg::RefMatrix(*_modelStack.back());
   transform.computeLocalToWorldMatrix(*matrix,this);

   pushModelMatrix(matrix.get());

   // now push an new intersector clone transform to the new local coordinates
   push_clone();

   traverse(transform);
// pop the clone.
   pop_clone();
popModelMatrix();

   // tidy up an cached cull variables in the current intersector.
   leave();
}


void IntersectionVisitor::apply(osg::Projection& projection)
{
   if (!enter(projection)) return;

   pushProjectionMatrix(new osg::RefMatrix(projection.getMatrix()) );

   // now push an new intersector clone transform to the new local coordinates
   push_clone();

   traverse(projection);
// pop the clone.
   pop_clone();
popProjectionMatrix();

   leave();
}


void IntersectionVisitor::apply(osg::Camera& camera)
{
   // osg::notify(osg::NOTICE)<<"apply(Camera&)"<<std::endl;

   // note, commenting out right now because default Camera setup is with the 
culling active.  Should this be changed?
   // if (!enter(camera)) return;
// osg::notify(osg::NOTICE)<<"inside apply(Camera&)"<<std::endl;

   osg::RefMatrix* projection = NULL;
   osg::RefMatrix* view = NULL;
   osg::RefMatrix* model = NULL;

   if (camera.getReferenceFrame()==osg::Transform::RELATIVE_RF && getProjectionMatrix() 
&& getViewMatrix())
   {
       if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY)
       {
           projection = new 
osg::RefMatrix(*getProjectionMatrix()*camera.getProjectionMatrix());
           view = new osg::RefMatrix(*getViewMatrix()*camera.getViewMatrix());
       }
else // pre multiply {
           projection = new 
osg::RefMatrix(camera.getProjectionMatrix()*(*getProjectionMatrix()));
           view = new osg::RefMatrix(camera.getViewMatrix()*(*getViewMatrix()));
       }
       model = _modelStack.empty() ? new osg::RefMatrix() : new 
osg::RefMatrix(*_modelStack.back());
       camera.computeLocalToWorldMatrix(*model,this);
   } else {
       // an absolute reference frame
       projection = new osg::RefMatrix(camera.getProjectionMatrix());
       view = new osg::RefMatrix(camera.getViewMatrix());
       model =  new osg::RefMatrix();
   }

   if (camera.getViewport()) pushWindowMatrix( camera.getViewport() );
   pushProjectionMatrix(projection);
   pushViewMatrix(view);
   pushModelMatrix(model);

   // now push an new intersector clone transform to the new local coordinates
   push_clone();

   traverse(camera);
// pop the clone.
   pop_clone();
popModelMatrix();
   popViewMatrix();
   popProjectionMatrix();
   if (camera.getViewport()) popWindowMatrix();

   // leave();
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to