使用OSG碰撞检测功能检测两点通视

来源:互联网 发布:淘宝号能买到吗 编辑:程序博客网 时间:2024/05/14 09:12

在三维场景中有时需要对两点求其是否可见,即两点之间有没有障碍物的遮挡。在OSG中则可使用碰撞检测完成此功能。
核心的碰撞检测代码为:

    // 创建需要进行检测的两点之间的线段    osg::ref_ptr<osg::LineSegment> line = new osg::LineSegment(point1,point2);    // 创建一个IV    osgUtil::IntersectVisitor iv;    // 把线段添加到IV中    iv.addLineSegment(line);    node->accept(iv);    // 最后可以对iv.hits()的返回值进行判断    if (iv.hits())    {        // 两点间有障碍    }    else    {    // 两点间无障碍    }    ```    完整的两点通视代码为:lineanalysis.h    ```c++class LineAnalysis : public HandleAdapter{public:    LineAnalysis(GraphicsView* view);    ~LineAnalysis();protected:    virtual void slotPicked(osg::Vec3d pos);    virtual void slotMoveing(osg::Vec3d pos);    virtual void slotRightHandle();private:    void analysis(osg::Vec3d pos);    osg::Vec3d getWorldCoord(osg::Vec3d pos);private:    osgEarth::Annotation::FeatureNode* m_pLine;    osg::Vec3d m_firstPoint;    osgEarth::Annotation::PlaceNode* m_pPlaceNode;    osgEarth::Symbology::Style m_lineStyle;    osgEarth::Symbology::Style m_textStyle;};
实现代码为:lineanalysis.cpp
LineAnalysis::LineAnalysis(GraphicsView* view): HandleAdapter(view){    m_pLine = NULL;    m_firstPoint = osg::Vec3d();    // init style    m_lineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()        ->stroke()->color() = osgEarth::Symbology::Color::Yellow;    m_lineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()        ->stroke()->width() = 2.0;    m_lineStyle.getOrCreate<osgEarth::Symbology::LineSymbol>()        ->tessellation() = 20.0;    m_lineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()        ->clamping() = osgEarth::Symbology::AltitudeSymbol::CLAMP_ABSOLUTE;    m_lineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()        ->technique() = osgEarth::Symbology::AltitudeSymbol::TECHNIQUE_MAP;    m_lineStyle.getOrCreate<osgEarth::Symbology::AltitudeSymbol>()        ->verticalOffset() = 0.1;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->alignment()        = osgEarth::Symbology::TextSymbol::ALIGN_LEFT_TOP;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->encoding()        = osgEarth::Symbology::TextSymbol::ENCODING_UTF8;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->declutter()        = true;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->halo()        = osgEarth::Symbology::Color::White;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->haloOffset() = 0.05;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->fill()->color()        = osg::Vec4(1, 0.5, 0, 1);    m_textStyle.getOrCreate<osgEarth::Symbology::RenderSymbol>()->lighting() = false;    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->font() = "simhei.ttf";    m_textStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->size() = 25.0;}LineAnalysis::~LineAnalysis(){}void LineAnalysis::slotPicked(osg::Vec3d pos){    m_firstPoint = pos;}void LineAnalysis::slotMoveing(osg::Vec3d pos){    analysis(pos);}void LineAnalysis::slotRightHandle(){    endHandle();}void LineAnalysis::analysis(osg::Vec3d pos){    if (m_firstPoint == osg::Vec3d())    {        return;    }    if (m_pLine == NULL)    {        osgEarth::Features::Feature* pFeature = new osgEarth::Features::Feature(            new osgEarth::Features::LineString,            m_pMap3D->getSRS(), m_lineStyle);        m_pLine = new osgEarth::Annotation::FeatureNode(m_pMap3D->getMapNode(), pFeature);        m_pPlaceNode = new osgEarth::Annotation::PlaceNode(            m_pMap3D->getMapNode(), osgEarth::GeoPoint::GeoPoint(), "", m_textStyle);        m_pLayerGroup->addChild(m_pLine);        m_pLayerGroup->addChild(m_pPlaceNode);    }    osgEarth::Symbology::Geometry* pGeom = m_pLine->getFeature()->getGeometry();    pGeom->clear();    m_pLine->setStyle(m_lineStyle);    pGeom->push_back(m_firstPoint);    pGeom->push_back(pos);    m_pLine->init();    // 碰撞检测    QString str;    osgUtil::IntersectVisitor iv;    osg::ref_ptr<osg::LineSegment> line = new osg::LineSegment(        getWorldCoord(osg::Vec3d(m_firstPoint.x(), m_firstPoint.y(), m_firstPoint.z() + 2)),        getWorldCoord(osg::Vec3d(pos.x(), pos.y(), pos.z() + 2)));    iv.addLineSegment(line);    m_pMap3D->getMapNode()->getTerrain()->accept(iv);    if (iv.hits())    {        str = QStringLiteral("两点不可见");    }    else    {        str = QStringLiteral("两点可见");    }    m_pPlaceNode->setText(str.toStdWString());    m_pPlaceNode->setPosition(        osgEarth::GeoPoint::GeoPoint(m_pMap3D->getSRS(), pos.x(), pos.y()));}osg::Vec3d LineAnalysis::getWorldCoord(osg::Vec3d pos){    osg::Vec3d world;    m_pMap3D->getSRS()->getEllipsoid()->convertLatLongHeightToXYZ(        osg::DegreesToRadians(pos.y()),        osg::DegreesToRadians(pos.x()),        pos.z(), world.x(), world.y(), world.z());    return world;}

附:本人以上代码以及前几篇关于OSG的代码均已上传github,传送门在此OSGDemo,欢迎各位!

1 0
原创粉丝点击