简介
利用osgUtil::LineSegmentIntersector做的线碰撞检测,原理是把小球当前位置和新位置练成线与盒子做碰撞检测,如果有交点,则不准小球移动,记录于此备忘
代码
#include "../Common/Common.h"
#include <osg/ShapeDrawable>
#include <osg/Shape>
#include <osgGA/GUIEventAdapter>
osg::ref_ptr<osg::MatrixTransform> CreateBall(osg::Vec3 ¢er, 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();
}