| 1 | /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
|---|
| 2 | * |
|---|
| 3 | * This library is open source and may be redistributed and/or modified under |
|---|
| 4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|---|
| 5 | * (at your option) any later version. The full license is in LICENSE file |
|---|
| 6 | * included with this distribution, and on the openscenegraph.org website. |
|---|
| 7 | * |
|---|
| 8 | * This library is distributed in the hope that it will be useful, |
|---|
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | * OpenSceneGraph Public License for more details. |
|---|
| 12 | */ |
|---|
| 13 | |
|---|
| 14 | #ifndef OSGUTIL_INTERSECTVISITOR |
|---|
| 15 | #define OSGUTIL_INTERSECTVISITOR 1 |
|---|
| 16 | |
|---|
| 17 | #include <osg/NodeVisitor> |
|---|
| 18 | #include <osg/LineSegment> |
|---|
| 19 | #include <osg/Geode> |
|---|
| 20 | #include <osg/Matrix> |
|---|
| 21 | #include <osg/Transform> |
|---|
| 22 | |
|---|
| 23 | #include <osgUtil/Export> |
|---|
| 24 | |
|---|
| 25 | #include <map> |
|---|
| 26 | #include <set> |
|---|
| 27 | #include <vector> |
|---|
| 28 | |
|---|
| 29 | namespace osgUtil { |
|---|
| 30 | |
|---|
| 31 | |
|---|
| 32 | class OSGUTIL_EXPORT Hit |
|---|
| 33 | { |
|---|
| 34 | /** Deprecated */ |
|---|
| 35 | public: |
|---|
| 36 | |
|---|
| 37 | Hit(); |
|---|
| 38 | Hit(const Hit& hit); |
|---|
| 39 | ~Hit(); |
|---|
| 40 | |
|---|
| 41 | Hit& operator = (const Hit& hit); |
|---|
| 42 | |
|---|
| 43 | typedef std::vector<int> VecIndexList; |
|---|
| 44 | |
|---|
| 45 | bool operator < (const Hit& hit) const |
|---|
| 46 | { |
|---|
| 47 | if (_originalLineSegment<hit._originalLineSegment) return true; |
|---|
| 48 | if (hit._originalLineSegment<_originalLineSegment) return false; |
|---|
| 49 | return _ratio<hit._ratio; |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | |
|---|
| 53 | const osg::Vec3& getLocalIntersectPoint() const { return _intersectPoint; } |
|---|
| 54 | const osg::Vec3& getLocalIntersectNormal() const { return _intersectNormal; } |
|---|
| 55 | |
|---|
| 56 | const osg::Vec3 getWorldIntersectPoint() const { if (_matrix.valid()) return _intersectPoint*(*_matrix); else return _intersectPoint; } |
|---|
| 57 | const osg::Vec3 getWorldIntersectNormal() const ; |
|---|
| 58 | |
|---|
| 59 | float getRatio() const { return _ratio; } |
|---|
| 60 | const osg::LineSegment* getOriginalLineSegment() const { return _originalLineSegment.get(); } |
|---|
| 61 | const osg::LineSegment* getLocalLineSegment() const { return _localLineSegment.get(); } |
|---|
| 62 | osg::NodePath& getNodePath() { return _nodePath; } |
|---|
| 63 | const osg::NodePath& getNodePath() const { return _nodePath; } |
|---|
| 64 | osg::Geode* getGeode() { return _geode.get(); } |
|---|
| 65 | const osg::Geode* getGeode() const { return _geode.get(); } |
|---|
| 66 | osg::Drawable* getDrawable() { return _drawable.get(); } |
|---|
| 67 | const osg::Drawable* getDrawable() const { return _drawable.get(); } |
|---|
| 68 | const osg::RefMatrix* getMatrix() const { return _matrix.get(); } |
|---|
| 69 | const osg::RefMatrix* getInverseMatrix() const { return _inverse.get(); } |
|---|
| 70 | const VecIndexList& getVecIndexList() const { return _vecIndexList; } |
|---|
| 71 | int getPrimitiveIndex() const { return _primitiveIndex; } |
|---|
| 72 | |
|---|
| 73 | |
|---|
| 74 | float _ratio; |
|---|
| 75 | osg::ref_ptr<osg::LineSegment> _originalLineSegment; |
|---|
| 76 | osg::ref_ptr<osg::LineSegment> _localLineSegment; |
|---|
| 77 | osg::NodePath _nodePath; |
|---|
| 78 | osg::ref_ptr<osg::Geode> _geode; |
|---|
| 79 | osg::ref_ptr<osg::Drawable> _drawable; |
|---|
| 80 | osg::ref_ptr<osg::RefMatrix> _matrix; |
|---|
| 81 | osg::ref_ptr<osg::RefMatrix> _inverse; |
|---|
| 82 | |
|---|
| 83 | VecIndexList _vecIndexList; |
|---|
| 84 | int _primitiveIndex; |
|---|
| 85 | osg::Vec3 _intersectPoint; |
|---|
| 86 | osg::Vec3 _intersectNormal; |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | }; |
|---|
| 90 | |
|---|
| 91 | |
|---|
| 92 | /** Deprecated - use IntersectionVisitor instead.*/ |
|---|
| 93 | class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor |
|---|
| 94 | { |
|---|
| 95 | public: |
|---|
| 96 | |
|---|
| 97 | IntersectVisitor(); |
|---|
| 98 | virtual ~IntersectVisitor(); |
|---|
| 99 | |
|---|
| 100 | META_NodeVisitor("osgUtil","IntersectVisitor") |
|---|
| 101 | |
|---|
| 102 | void reset(); |
|---|
| 103 | |
|---|
| 104 | /** Add a line segment to use for intersection testing during scene traversal. |
|---|
| 105 | * Note, a maximum of 32 line segments can be added to a IntersectVistor, |
|---|
| 106 | * adding more than this will result in warning being emitted to the console |
|---|
| 107 | * and the excess segments being ignored.*/ |
|---|
| 108 | void addLineSegment(osg::LineSegment* seg); |
|---|
| 109 | |
|---|
| 110 | typedef std::vector<Hit> HitList; |
|---|
| 111 | typedef std::map<const osg::LineSegment*,HitList > LineSegmentHitListMap; |
|---|
| 112 | |
|---|
| 113 | HitList& getHitList(const osg::LineSegment* seg) { return _segHitList[seg]; } |
|---|
| 114 | |
|---|
| 115 | int getNumHits(const osg::LineSegment* seg) { return _segHitList[seg].size(); } |
|---|
| 116 | |
|---|
| 117 | LineSegmentHitListMap& getSegHitList() { return _segHitList; } |
|---|
| 118 | |
|---|
| 119 | bool hits(); |
|---|
| 120 | |
|---|
| 121 | enum LODSelectionMode |
|---|
| 122 | { |
|---|
| 123 | USE_HIGHEST_LEVEL_OF_DETAIL, |
|---|
| 124 | USE_SEGMENT_START_POINT_AS_EYE_POINT_FOR_LOD_LEVEL_SELECTION |
|---|
| 125 | }; |
|---|
| 126 | |
|---|
| 127 | void setLODSelectionMode(LODSelectionMode mode) { _lodSelectionMode = mode; } |
|---|
| 128 | LODSelectionMode getLODSelectionMode() const { return _lodSelectionMode; } |
|---|
| 129 | |
|---|
| 130 | /** Set the eye point in local coordinates. |
|---|
| 131 | * This is a pseudo-EyePoint for billboarding and LOD purposes. |
|---|
| 132 | * It is copied from the Start point of the most-recently-added segment |
|---|
| 133 | * of the intersection ray set (IntersectState::_segList). */ |
|---|
| 134 | void setEyePoint(const osg::Vec3& eye) { _pseudoEyePoint = eye; } |
|---|
| 135 | |
|---|
| 136 | virtual osg::Vec3 getEyePoint() const; |
|---|
| 137 | |
|---|
| 138 | |
|---|
| 139 | /** Get the distance from a point to the eye point, distance value in local coordinate system. |
|---|
| 140 | * This is calculated using the pseudo-EyePoint (above) when doing LOD calculcations. */ |
|---|
| 141 | virtual float getDistanceToEyePoint(const osg::Vec3& pos, bool withLODScale) const; |
|---|
| 142 | |
|---|
| 143 | virtual void apply(osg::Node&); |
|---|
| 144 | virtual void apply(osg::Geode& node); |
|---|
| 145 | virtual void apply(osg::Billboard& node); |
|---|
| 146 | |
|---|
| 147 | virtual void apply(osg::Group& node); |
|---|
| 148 | virtual void apply(osg::Transform& node); |
|---|
| 149 | virtual void apply(osg::Switch& node); |
|---|
| 150 | virtual void apply(osg::LOD& node); |
|---|
| 151 | |
|---|
| 152 | protected: |
|---|
| 153 | |
|---|
| 154 | class IntersectState : public osg::Referenced |
|---|
| 155 | { |
|---|
| 156 | public: |
|---|
| 157 | |
|---|
| 158 | IntersectState(); |
|---|
| 159 | |
|---|
| 160 | osg::ref_ptr<osg::RefMatrix> _view_matrix; |
|---|
| 161 | osg::ref_ptr<osg::RefMatrix> _view_inverse; |
|---|
| 162 | osg::ref_ptr<osg::RefMatrix> _model_matrix; |
|---|
| 163 | osg::ref_ptr<osg::RefMatrix> _model_inverse; |
|---|
| 164 | |
|---|
| 165 | typedef std::pair<osg::ref_ptr<osg::LineSegment>,osg::ref_ptr<osg::LineSegment> > LineSegmentPair; |
|---|
| 166 | typedef std::vector< LineSegmentPair > LineSegmentList; |
|---|
| 167 | LineSegmentList _segList; |
|---|
| 168 | |
|---|
| 169 | typedef unsigned int LineSegmentMask; |
|---|
| 170 | typedef std::vector<LineSegmentMask> LineSegmentMaskStack; |
|---|
| 171 | LineSegmentMaskStack _segmentMaskStack; |
|---|
| 172 | |
|---|
| 173 | bool isCulled(const osg::BoundingSphere& bs,LineSegmentMask& segMaskOut); |
|---|
| 174 | bool isCulled(const osg::BoundingBox& bb,LineSegmentMask& segMaskOut); |
|---|
| 175 | |
|---|
| 176 | void addLineSegment(osg::LineSegment* seg); |
|---|
| 177 | |
|---|
| 178 | protected: |
|---|
| 179 | |
|---|
| 180 | ~IntersectState(); |
|---|
| 181 | |
|---|
| 182 | }; |
|---|
| 183 | |
|---|
| 184 | bool intersect(osg::Drawable& gset); |
|---|
| 185 | |
|---|
| 186 | void pushMatrix(osg::RefMatrix* matrix, osg::Transform::ReferenceFrame rf); |
|---|
| 187 | void popMatrix(); |
|---|
| 188 | |
|---|
| 189 | bool enterNode(osg::Node& node); |
|---|
| 190 | void leaveNode(); |
|---|
| 191 | |
|---|
| 192 | typedef std::vector<osg::ref_ptr<IntersectState> > IntersectStateStack; |
|---|
| 193 | |
|---|
| 194 | IntersectStateStack _intersectStateStack; |
|---|
| 195 | |
|---|
| 196 | LineSegmentHitListMap _segHitList; |
|---|
| 197 | |
|---|
| 198 | LODSelectionMode _lodSelectionMode; |
|---|
| 199 | osg::Vec3 _pseudoEyePoint; |
|---|
| 200 | }; |
|---|
| 201 | |
|---|
| 202 | /** Picking intersection visitor specialises the IntersectVistor to allow more convinient handling of mouse picking.*/ |
|---|
| 203 | class OSGUTIL_EXPORT PickVisitor : public osgUtil::IntersectVisitor |
|---|
| 204 | { |
|---|
| 205 | public: |
|---|
| 206 | |
|---|
| 207 | PickVisitor(const osg::Viewport* viewport, const osg::Matrixd& proj, const osg::Matrixd& view, float mx, float my); |
|---|
| 208 | |
|---|
| 209 | void runNestedPickVisitor(osg::Node& node, const osg::Viewport* viewport, const osg::Matrix& proj, const osg::Matrix& view, float mx, float my); |
|---|
| 210 | |
|---|
| 211 | void apply(osg::Projection& projection); |
|---|
| 212 | |
|---|
| 213 | void apply(osg::Camera& camera); |
|---|
| 214 | |
|---|
| 215 | protected: |
|---|
| 216 | |
|---|
| 217 | float _mx; |
|---|
| 218 | float _my; |
|---|
| 219 | |
|---|
| 220 | osg::ref_ptr<const osg::Viewport> _lastViewport; |
|---|
| 221 | osg::Matrixd _lastProjectionMatrix; |
|---|
| 222 | osg::Matrixd _lastViewMatrix; |
|---|
| 223 | }; |
|---|
| 224 | |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | #endif |
|---|
| 228 | |
|---|