From Chris Xennon, add support for billboard intersections + fix to addLineSegments.

Small addition from Robert Osfield of setLODSelectionMode(..) to control
the LOD selection behavior.
This commit is contained in:
Robert Osfield
2005-02-10 21:18:04 +00:00
parent d706e9e795
commit 7fb8dfe5ed
2 changed files with 71 additions and 3 deletions

View File

@@ -110,6 +110,28 @@ class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor
bool hits();
enum LODSelectionMode
{
USE_HEIGHEST_LEVEL_OF_DETAIL,
USE_SEGMENT_START_POINT_AS_EYE_POINT_FOR_LOD_LEVEL_SELECTION
};
void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; }
LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; }
/** Set the eye point in local coordinates.
* This is a pseudo-EyePoint for billboarding and LOD purposes.
* It is copied from the Start point of the most-recently-added segment
* of the intersection ray set (IntersectState::_segList). */
void setEyePoint(const osg::Vec3& eye) { _pseudoEyePoint = eye; }
virtual osg::Vec3 getEyePoint() const { return _pseudoEyePoint; }
/** Get the distance from a point to the eye point, distance value in local coordinate system.
* This is calculated using the pseudo-EyePoint (above) when doing LOD calculcations. */
virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const;
virtual void apply(osg::Node&);
virtual void apply(osg::Geode& node);
virtual void apply(osg::Billboard& node);
@@ -166,6 +188,9 @@ class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor
osg::NodePath _nodePath;
LineSegmentHitListMap _segHitList;
LODSelectionMode _lodSelectionMode;
osg::Vec3 _pseudoEyePoint;
};
}

View File

@@ -150,8 +150,15 @@ bool IntersectVisitor::IntersectState::isCulled(const BoundingBox& bb,LineSegmen
IntersectVisitor::IntersectVisitor()
{
// overide the default node visitor mode.
setTraversalMode(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
// Initialize eyepoint to 0,0,0
setEyePoint(Vec3(0.0f,0.0f,0.0f));
setLODSelectionMode(USE_HEIGHEST_LEVEL_OF_DETAIL); // orignal IntersectVisitor behavior
//setLODSelectionMode(USE_SEGMENT_START_POINT_AS_EYE_POINT_FOR_LOD_LEVEL_SELECTION);
reset();
}
@@ -174,6 +181,21 @@ void IntersectVisitor::reset()
}
float IntersectVisitor::getDistanceToEyePoint(const Vec3& pos, bool /*withLODScale*/) const
{
if (_lodSelectionMode==USE_SEGMENT_START_POINT_AS_EYE_POINT_FOR_LOD_LEVEL_SELECTION)
{
// LODScale is not available to IntersectVisitor, so we ignore the withLODScale argument
//if (withLODScale) return (pos-getEyePoint()).length()*getLODScale();
//else return (pos-getEyePoint()).length();
return (pos-getEyePoint()).length();
}
else
{
return 0.0f;
}
}
bool IntersectVisitor::hits()
{
@@ -198,16 +220,19 @@ void IntersectVisitor::addLineSegment(LineSegment* seg)
return;
}
IntersectState* cis = _intersectStateStack.back().get();
setEyePoint(seg->start()); // set start of line segment to be pseudo EyePoint for billboarding and LOD purposes
// first check to see if segment has already been added.
for(LineSegmentHitListMap::iterator itr = _segHitList.begin();
itr != _segHitList.end();
for(IntersectState::LineSegmentList::iterator itr = cis->_segList.begin();
itr != cis->_segList.end();
++itr)
{
if (itr->first == seg) return;
}
// create a new segment transformed to local coordintes.
IntersectState* cis = _intersectStateStack.back().get();
LineSegment* ns = new LineSegment;
if (cis->_inverse.valid()) ns->mult(*seg,*(cis->_inverse));
@@ -293,6 +318,7 @@ void IntersectVisitor::leaveNode()
}
void IntersectVisitor::apply(Node& node)
{
if (!enterNode(node)) return;
@@ -572,6 +598,23 @@ void IntersectVisitor::apply(Billboard& node)
{
if (!enterNode(node)) return;
// IntersectVisitor doesn't have getEyeLocal(), can we use NodeVisitor::getEyePoint()?
const Vec3& eye_local = getEyePoint();
for(unsigned int i = 0; i < node.getNumDrawables(); i++ )
{
const Vec3& pos = node.getPosition(i);
osg::ref_ptr<RefMatrix> billboard_matrix = new RefMatrix;
node.computeMatrix(*billboard_matrix,eye_local,pos);
pushMatrix(*billboard_matrix);
intersect(*node.getDrawable(i));
popMatrix();
}
leaveNode();
}