Implemented a reference eye point and associated methods in support of intersecting billboards
This commit is contained in:
@@ -70,7 +70,7 @@ class Intersector : public osg::Referenced
|
||||
|
||||
inline void decrementDisabledCount() { if (_disabledCount>0) --_disabledCount; }
|
||||
|
||||
protected:
|
||||
protected:
|
||||
|
||||
CoordinateFrame _coordinateFrame;
|
||||
unsigned int _disabledCount;
|
||||
@@ -170,27 +170,60 @@ class OSGUTIL_EXPORT IntersectionVisitor : public osg::NodeVisitor
|
||||
const ReadCallback* getReadCallback() const { return _readCallback.get(); }
|
||||
|
||||
|
||||
void pushWindowMatrix(osg::RefMatrix* matrix) { _windowStack.push_back(matrix); }
|
||||
void pushWindowMatrix(osg::Viewport* viewport) { _windowStack.push_back(new osg::RefMatrix( viewport->computeWindowMatrix()) ); }
|
||||
void popWindowMatrix() { _windowStack.pop_back(); }
|
||||
void pushWindowMatrix(osg::RefMatrix* matrix) { _windowStack.push_back(matrix); _eyePointDirty = true; }
|
||||
void pushWindowMatrix(osg::Viewport* viewport) { _windowStack.push_back(new osg::RefMatrix( viewport->computeWindowMatrix()) ); _eyePointDirty = true; }
|
||||
void popWindowMatrix() { _windowStack.pop_back(); _eyePointDirty = true; }
|
||||
osg::RefMatrix* getWindowMatrix() { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
|
||||
const osg::RefMatrix* getWindowMatrix() const { return _windowStack.empty() ? 0 : _windowStack.back().get(); }
|
||||
|
||||
void pushProjectionMatrix(osg::RefMatrix* matrix) { _projectionStack.push_back(matrix); }
|
||||
void popProjectionMatrix() { _projectionStack.pop_back(); }
|
||||
void pushProjectionMatrix(osg::RefMatrix* matrix) { _projectionStack.push_back(matrix); _eyePointDirty = true; }
|
||||
void popProjectionMatrix() { _projectionStack.pop_back(); _eyePointDirty = true; }
|
||||
osg::RefMatrix* getProjectionMatrix() { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
|
||||
const osg::RefMatrix* getProjectionMatrix() const { return _projectionStack.empty() ? 0 : _projectionStack.back().get(); }
|
||||
|
||||
void pushViewMatrix(osg::RefMatrix* matrix) { _viewStack.push_back(matrix); }
|
||||
void popViewMatrix() { _viewStack.pop_back(); }
|
||||
void pushViewMatrix(osg::RefMatrix* matrix) { _viewStack.push_back(matrix); _eyePointDirty = true; }
|
||||
void popViewMatrix() { _viewStack.pop_back(); _eyePointDirty = true; }
|
||||
osg::RefMatrix* getViewMatrix() { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
|
||||
const osg::RefMatrix* getViewMatrix() const { return _viewStack.empty() ? 0 : _viewStack.back().get(); }
|
||||
|
||||
void pushModelMatrix(osg::RefMatrix* matrix) { _modelStack.push_back(matrix); }
|
||||
void popModelMatrix() { _modelStack.pop_back(); }
|
||||
void pushModelMatrix(osg::RefMatrix* matrix) { _modelStack.push_back(matrix); _eyePointDirty = true; }
|
||||
void popModelMatrix() { _modelStack.pop_back(); _eyePointDirty = true; }
|
||||
osg::RefMatrix* getModelMatrix() { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
|
||||
const osg::RefMatrix* getModelMatrix() const { return _modelStack.empty() ? 0 : _modelStack.back().get(); }
|
||||
|
||||
|
||||
/** Set the reference eye point that is used for nodes that require an eye point to position themselves, such as billboards.*/
|
||||
void setReferenceEyePoint(const osg::Vec3& ep) { _referenceEyePoint = ep; _eyePointDirty = true; }
|
||||
|
||||
/** Get the reference eye point.*/
|
||||
const osg::Vec3& getReferenceEyePoint() const { return _referenceEyePoint; }
|
||||
|
||||
/** Set the coordinate frame of the reference eye point.*/
|
||||
void setReferenceEyePointCoordinateFrame(Intersector::CoordinateFrame cf) { _referenceEyePointCoordinateFrame = cf; }
|
||||
|
||||
/** Get the coordinate frame of the reference eye point.*/
|
||||
Intersector::CoordinateFrame getReferenceEyePointCoordinateFrame() const { return _referenceEyePointCoordinateFrame; }
|
||||
|
||||
|
||||
/** Get the eye point in the local coordinate frame a given traversal point.*/
|
||||
virtual osg::Vec3 getEyePoint() const;
|
||||
|
||||
enum LODSelectionMode
|
||||
{
|
||||
USE_HIGHEST_LEVEL_OF_DETAIL,
|
||||
USE_EYE_POINT_FOR_LOD_LEVEL_SELECTION
|
||||
};
|
||||
|
||||
/** Set the LOD selection scheme.*/
|
||||
void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; }
|
||||
|
||||
/** Get the LOD selection scheme.*/
|
||||
LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; }
|
||||
|
||||
/** 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;
|
||||
|
||||
public:
|
||||
|
||||
virtual void apply(osg::Node& node);
|
||||
@@ -225,6 +258,12 @@ class OSGUTIL_EXPORT IntersectionVisitor : public osg::NodeVisitor
|
||||
MatrixStack _viewStack;
|
||||
MatrixStack _modelStack;
|
||||
|
||||
osg::Vec3 _referenceEyePoint;
|
||||
Intersector::CoordinateFrame _referenceEyePointCoordinateFrame;
|
||||
LODSelectionMode _lodSelectionMode;
|
||||
|
||||
mutable bool _eyePointDirty;
|
||||
mutable osg::Vec3 _eyePoint;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
|
||||
#include <osgUtil/IntersectionVisitor>
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
|
||||
#include <osg/PagedLOD>
|
||||
#include <osg/Transform>
|
||||
@@ -157,6 +158,21 @@ IntersectionVisitor::IntersectionVisitor(Intersector* intersector, ReadCallback*
|
||||
|
||||
_useKdTreesWhenAvailable = true;
|
||||
_dummyTraversal = false;
|
||||
|
||||
_lodSelectionMode = USE_HIGHEST_LEVEL_OF_DETAIL;
|
||||
_eyePointDirty = true;
|
||||
|
||||
LineSegmentIntersector* ls = dynamic_cast<LineSegmentIntersector*>(intersector);
|
||||
if (ls)
|
||||
{
|
||||
setReferenceEyePoint(ls->getStart());
|
||||
setReferenceEyePointCoordinateFrame(ls->getCoordinateFrame());
|
||||
}
|
||||
else
|
||||
{
|
||||
setReferenceEyePoint(osg::Vec3(0.0f,0.0f,0.0f));
|
||||
setReferenceEyePointCoordinateFrame(Intersector::VIEW);
|
||||
}
|
||||
|
||||
setIntersector(intersector);
|
||||
|
||||
@@ -227,10 +243,39 @@ void IntersectionVisitor::apply(osg::Billboard& billboard)
|
||||
{
|
||||
if (!enter(billboard)) return;
|
||||
|
||||
#if 1
|
||||
// IntersectVisitor doesn't have getEyeLocal(), can we use NodeVisitor::getEyePoint()?
|
||||
osg::Vec3 eye_local = getEyePoint();
|
||||
|
||||
for(unsigned int i = 0; i < billboard.getNumDrawables(); i++ )
|
||||
{
|
||||
const osg::Vec3& pos = billboard.getPosition(i);
|
||||
osg::ref_ptr<osg::RefMatrix> billboard_matrix = _modelStack.empty() ?
|
||||
new osg::RefMatrix :
|
||||
new osg::RefMatrix(*_modelStack.back());
|
||||
|
||||
billboard.computeMatrix(*billboard_matrix,eye_local,pos);
|
||||
|
||||
pushModelMatrix(billboard_matrix.get());
|
||||
|
||||
// now push an new intersector clone transform to the new local coordinates
|
||||
push_clone();
|
||||
|
||||
intersect( billboard.getDrawable(i) );
|
||||
|
||||
// now push an new intersector clone transform to the new local coordinates
|
||||
pop_clone();
|
||||
|
||||
popModelMatrix();
|
||||
|
||||
}
|
||||
#else
|
||||
|
||||
for(unsigned int i=0; i<billboard.getNumDrawables(); ++i)
|
||||
{
|
||||
intersect( billboard.getDrawable(i) );
|
||||
}
|
||||
#endif
|
||||
|
||||
leave();
|
||||
}
|
||||
@@ -413,3 +458,51 @@ void IntersectionVisitor::apply(osg::Camera& camera)
|
||||
|
||||
// leave();
|
||||
}
|
||||
|
||||
osg::Vec3 IntersectionVisitor::getEyePoint() const
|
||||
{
|
||||
if (!_eyePointDirty) return _eyePoint;
|
||||
|
||||
osg::Matrix matrix;
|
||||
switch (_referenceEyePointCoordinateFrame)
|
||||
{
|
||||
case(Intersector::WINDOW):
|
||||
if (getWindowMatrix()) matrix.preMult( *getWindowMatrix() );
|
||||
if (getProjectionMatrix()) matrix.preMult( *getProjectionMatrix() );
|
||||
if (getViewMatrix()) matrix.preMult( *getViewMatrix() );
|
||||
if (getModelMatrix()) matrix.preMult( *getModelMatrix() );
|
||||
break;
|
||||
case(Intersector::PROJECTION):
|
||||
if (getProjectionMatrix()) matrix.preMult( *getProjectionMatrix() );
|
||||
if (getViewMatrix()) matrix.preMult( *getViewMatrix() );
|
||||
if (getModelMatrix()) matrix.preMult( *getModelMatrix() );
|
||||
break;
|
||||
case(Intersector::VIEW):
|
||||
if (getViewMatrix()) matrix.preMult( *getViewMatrix() );
|
||||
if (getModelMatrix()) matrix.preMult( *getModelMatrix() );
|
||||
break;
|
||||
case(Intersector::MODEL):
|
||||
if (getModelMatrix()) matrix = *getModelMatrix();
|
||||
break;
|
||||
}
|
||||
|
||||
osg::Matrix inverse;
|
||||
inverse.invert(matrix);
|
||||
|
||||
_eyePoint = _referenceEyePoint * inverse;
|
||||
_eyePointDirty = false;
|
||||
|
||||
return _eyePoint;
|
||||
}
|
||||
|
||||
float IntersectionVisitor::getDistanceToEyePoint(const osg::Vec3& pos, bool /*withLODScale*/) const
|
||||
{
|
||||
if (_lodSelectionMode==USE_EYE_POINT_FOR_LOD_LEVEL_SELECTION)
|
||||
{
|
||||
return (pos-getEyePoint()).length();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user