一.简介
osgUtil::LineSegmentIntersector 类继承自 osgUtil::Intersector 类,用于检测指定线段和场景图形之间相交情况,该类提供了一种定义
二.osgUtil::Intersector(相交类)
三.osgUtil::LineSegmentIntersector(线段相交类)
1.类定义
typedef std::vector< Node* > NodePath;
class OSGUTIL_EXPORT LineSegmentIntersector : public Intersector{
public:
//Intersection 线段是一个结构体 struct OSGUTIL_EXPORT Intersection
{
Intersection():ratio(-1.0),primitiveIndex(0) {}
bool operator < (const Intersection& rhs) const { return ratio < rhs.ratio; }
typedef std::vector<unsigned int> IndexList;
typedef std::vector<double> RatioList;
double ratio;
osg::NodePath nodePath;
osg::ref_ptr<osg::Drawable> drawable;
osg::ref_ptr<osg::RefMatrix> matrix;
osg::Vec3d localIntersectionPoint;
osg::Vec3 localIntersectionNormal;
IndexList indexList;
RatioList ratioList;
unsigned int primitiveIndex;
const osg::Vec3d& getLocalIntersectPoint() const { return localIntersectionPoint; }
osg::Vec3d getWorldIntersectPoint() const { return matrix.valid() ? localIntersectionPoint * (*matrix) : localIntersectionPoint; }
const osg::Vec3& getLocalIntersectNormal() const { return localIntersectionNormal; }
osg::Vec3 getWorldIntersectNormal() const { return matrix.valid() ? osg::Matrix::transform3x3(osg::Matrix::inverse(*matrix),localIntersectionNormal) : localIntersectionNormal; }
osg::Texture* getTextureLookUp(osg::Vec3& tc) const;
};
//Intersections 线段列表是一个集合
typedef std::multiset<Intersection> Intersections;
protectd:
LineSegmentIntersector* _parent;
osg::Vec3d _start;
osg::Vec3d _end;
Intersections _intersections;
};
class OSGUTIL_EXPORT LineSegmentIntersector : public Intersector { public: LineSegmentIntersector(const osg::Vec3d& start, const osg::Vec3d& end) LineSegmentIntersector(CoordinateFrame cf, const osg::Vec3d& start, const osg::Vec3d& end, LineSegmentIntersector* parent = NULL, osgUtil::Intersector::IntersectionLimit intersectionLimit = osgUtil::Intersector::NO_LIMIT); LineSegmentIntersector(CoordinateFrame cf, double x, double y); inline void insertIntersection(const Intersection& intersection) { getIntersections().insert(intersection); } inline Intersections& getIntersections() { return _parent ? _parent->_intersections : _intersections; } inline Intersection getFirstIntersection() { Intersections& intersectios = getIntersections(); return intersections.empty() ? Intersection() : *(intersections.begin()); }
inline void setStart(const osg::Vec3d& start) { _start = start; } inline const osg::Vec3d& getStart() const { return _start; } inline void setEnd(const osg::Vec3d& end) { _end = end; } inline const osg::Vec3d& getEnd() const { return _end; } public: virtual Intersector* clone(osgUtil::IntersectionVisitor& iv) virtual bool enter(const osg::Node& node) virtual void leave() virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) virtual void intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable, const osg::Vec3d& s, cosnt osg::Vec3d& e) virtual void set() virtual bool containsIntersections(){ return !getIntersections().empty(); } static osg::Matrix getTransformation(osgUtil::IntersectionVisitor& iv, CoordinateFrame cf) protected: bool intersects(const osg::BoundingSphere& bs) bool intersectAndClip(osg::Vec3d& s, osg::Vec3d& e, const osg::BoundingBox& bb) };
2.使用步骤
#include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osg/Group> #include <osgFX/Scribe> #include <osgGA/GUIEventHandler> #include <osgUtil/LineSegmentIntersector> class CPickHandler : public osgGA::GUIEventHandler { public: CPickHandler(osgViewer::Viewer* viewer):mViewer(viewer){} //重写虚函数处理器 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { switch(ea.getEventType()) { case (osgGA::GUIEventAdapter::PUSH): if(ea.getButton() == 1) { //输入当前鼠标点击位置 Pick(ea.getX(), ea.getY()); } return true; } return false; } protected: void Pick(float x, float y) { //点击位置是否发生射线交集,intersections里面存放了所有触碰到的节点 osgUtil::LineSegmentIntersector::Intersections intersections; if(mViewer->computeIntersections(x, y, intersections)) { //获取交集迭代器,begin是点击到距离我们最近的那个物体 osgUtil::LineSegmentIntersector::Intersections::iterator hitr; for(hitr = intersections.begin(); hitr != intersections.end(); ++hitr) { if(!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty())) { { //获取交集的节点路径 const osg::NodePath& np = hitr->nodePath; for(int i = np.size() - 1; i >= 0; --i) { osgFX::Scribe* sc = dynamic_cast<osgFX::Scribe*>(np[i]); if(sc != NULL) if(sc->getNodeMask() != 0) sc->setNodeMask(0); } } } } } } osgViewer::Viewer* mViewer; }; int main(int, char**) { osgViewer::Viewer viewer; osg::ref_ptr<osg::Group> root = new osg::Group(); root->addChild(osgDB::readNodeFile("cessna.osg")); osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg"); osg::ref_ptr<osgFX::Scribe> sc = new osgFX::Scribe(); sc->addChild(cow.get()); root->addChild(cow.get()); root->addChild(sc.get()); viewer.setSceneData(root.get()); viewer.addEventHandler(new CPickHandler(&viewer)); viewer.realize(); viewer.run(); return 0; }
四.osgUtil::IntersectionVisitor(相交访问器)