osg线碰撞检测

本文介绍了一种利用osgUtil::LineSegmentIntersector进行线碰撞检测的方法,通过连接小球当前位置与新位置形成的线段与盒子进行碰撞检测,确保小球在虚拟环境中移动时不会穿过障碍物。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

利用osgUtil::LineSegmentIntersector做的线碰撞检测,原理是把小球当前位置和新位置练成线与盒子做碰撞检测,如果有交点,则不准小球移动,记录于此备忘

代码

#include "../Common/Common.h"
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osgGA/GUIEventAdapter>

osg::ref_ptr<osg::MatrixTransform> CreateBall(osg::Vec3 &center, float radius)
{
    osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform;
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(center, radius)));
    trans->addChild(geode.get());
    trans->setName("ball");
    return trans;
}

class MoveShapeEventHandler : public osgGA::GUIEventHandler
{
public:
    MoveShapeEventHandler(osg::MatrixTransform *node, osg::Node *pnode)
    {
        tranBall = node;
        m_node = pnode;
    }

    virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
    {
        switch (ea.getEventType())
        {
        case osgGA::GUIEventAdapter::KEYDOWN:
            {
                osg::Matrix newMat = tranBall->getMatrix();
                osg::Vec3 newPos;
                if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)
                {
                    newMat = tranBall->getMatrix() * osg::Matrix::translate(0.0 ,0.0, 0.1);
                    newPos = newMat.getTrans();
                    newPos[2] += tranBall->getBound().radius()/2;
                }
                else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down)
                {
                    newMat = tranBall->getMatrix() * osg::Matrix::translate(0.0 ,0.0, -0.1);
                    newPos = newMat.getTrans();
                    newPos[2] -= tranBall->getBound().radius()/2;
                }
                else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)
                {
                    newMat = tranBall->getMatrix() * osg::Matrix::translate(-0.1 ,0.0, 0.0);
                    newPos = newMat.getTrans();
                    newPos[0] -= tranBall->getBound().radius()/2;
                }
                else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)
                {
                    newMat = tranBall->getMatrix() * osg::Matrix::translate(0.1 ,0.0, 0.0);
                    newPos = newMat.getTrans();
                    newPos[0] += tranBall->getBound().radius()/2;
                }
                else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_P)
                {
                    osg::Matrix mat = tranBall->getMatrix();
                    std::cout<< tranBall->getMatrix().getTrans().x()<< " "<<
                        tranBall->getMatrix().getTrans().y()<<" "<<
                        tranBall->getMatrix().getTrans().z()<<std::endl;
                }
                osg::Vec3 oldPos = tranBall->getBound().center();
                bool bMove = false;

                if (1)
                {
                    osgUtil::LineSegmentIntersector::Intersections intersections;
                    osg::ref_ptr<osgUtil::LineSegmentIntersector> ls = new osgUtil::LineSegmentIntersector(oldPos, newPos);
                    osg::ref_ptr<osgUtil::IntersectionVisitor> iv = new osgUtil::IntersectionVisitor(ls);
                    m_node->accept(*iv.get());

                    if (!ls->containsIntersections())
                    {
                        bMove = true;
                    }
                }

                if (bMove)
                {
                    tranBall->setMatrix(newMat);
                }

                break;
            }
        }
        return false;
    };

private:
    osg::ref_ptr<osg::MatrixTransform> tranBall;
    osg::ref_ptr<osg::Node> m_node;
};

osg::ref_ptr<osg::Geode> CreateBox()
{
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, -1.0), 5.0, 5.0, 0.2)));//buttom
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(-2.5, 0.0, 1.6), 0.2, 5.0, 5.0)));//left
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(2.5, 0.0, 1.6), 0.2, 5.0, 5.0)));//right
    geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 2.5, 1.6), 5.0, 0.2, 5.0)));//far
    geode->setName("box");

    return geode;
}

int main()
{
    osgDB::Registry::instance()->getDataFilePathList().push_back("D:\\doc\\osg\\osgDATA");
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
    osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("glider.osg");

    osg::ref_ptr<osg::MatrixTransform> tran = CreateBall(osg::Vec3(0.0, 0.0, 0.0), 0.2);

    osg::ref_ptr<osg::Group> group = new osg::Group;
    group->addChild(tran);
    group->addChild(node);

    osg::ref_ptr<osg::Node> box = CreateBox();

    group->addChild(box.get());
    group->setName("group");
    viewer->setSceneData(group);

    //viewer->setUpViewInWindow(200, 200, 800, 600);
    viewer->addEventHandler(new MoveShapeEventHandler(tran.get(), box.get()));
    viewer->addEventHandler(new osgViewer::WindowSizeHandler);
    viewer->addEventHandler(new osgViewer::StatsHandler());
    return viewer->run();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dancing_night

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值