From bcbd50af3955b09e62008f8845a90e17328605f3 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 14 Aug 2008 14:22:39 +0000 Subject: [PATCH] Implemented a reference eye point and associated methods in support of intersecting billboards --- include/osgUtil/IntersectionVisitor | 59 ++++++++++++++---- src/osgUtil/IntersectionVisitor.cpp | 93 +++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 10 deletions(-) diff --git a/include/osgUtil/IntersectionVisitor b/include/osgUtil/IntersectionVisitor index f567a021a..7106f9833 100644 --- a/include/osgUtil/IntersectionVisitor +++ b/include/osgUtil/IntersectionVisitor @@ -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; }; } diff --git a/src/osgUtil/IntersectionVisitor.cpp b/src/osgUtil/IntersectionVisitor.cpp index f592e2e43..575c957e6 100644 --- a/src/osgUtil/IntersectionVisitor.cpp +++ b/src/osgUtil/IntersectionVisitor.cpp @@ -13,6 +13,7 @@ #include +#include #include #include @@ -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(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 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