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:
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user