OSG:幼儿园篇 第六章 碰撞检测类

一.简介

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(相交访问器)

 

posted @ 2019-09-10 18:35  言午丶  阅读(2001)  评论(0编辑  收藏  举报