osg三维场景中拾取鼠标在模型表面的点击点
#include <osg/Group> #include <osg/Geode> #include <osg/ShapeDrawable> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osgGA/GUIEventHandler> #include <osgGA/TrackballManipulator> #include <osg/Material> #include <osg/StateSet> #include <osgUtil/LineSegmentIntersector> #include <osgUtil/IntersectVisitor> #include <iostream> class PickHandler : public osgGA::GUIEventHandler { public: PickHandler() {} virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (!view) return false; // 检查是否为鼠标左键点击事件 if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) { performPick(ea, *view); return true; } return false; } osg::ref_ptr<osg::Geode> createRedSphere(const osg::Vec3f& position, float radius) { // 创建一个球体形状 osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(position, radius); // 创建一个形状绘制对象,并设置其颜色为红色 osg::ref_ptr<osg::ShapeDrawable> sphereDrawable = new osg::ShapeDrawable(sphere); sphereDrawable->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); // 红色(RGBA) // 创建一个地理节点(Geode),并将形状绘制对象添加到其中 osg::ref_ptr<osg::Geode> sphereGeode = new osg::Geode(); sphereGeode->addDrawable(sphereDrawable); return sphereGeode; } // private: void performPick(const osgGA::GUIEventAdapter& ea, osgViewer::View& view) { // 将鼠标位置转换为窗口坐标 int x = ea.getX(); int y = ea.getY(); // 创建一个射线相交检测器 //osgUtil::LineSegmentIntersector* intersector = new osgUtil::LineSegmentIntersector( // osgUtil::IntersectionVisitor::IntersectionType::FIRST, // 使用第一个相交点 // osg::Vec3(x, y, -1.0f), // 射线起点 // osg::Vec3(x, y, 1.0f) // 射线终点 // ); //osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::PROJECTION, x, y); // 执行相交检测 osgUtil::IntersectionVisitor iv; //bool computeIntersections(float x,float y, osgUtil::LineSegmentIntersector::Intersections& intersections,osg::Node::NodeMask traversalMask = 0xffffffff); // 存储相交结果的容器 osgUtil::LineSegmentIntersector::Intersections intersections; // 执行相交检测 if (view.computeIntersections(x, y, intersections)) { // 检查是否有相交点 if (!intersections.empty()) { // 获取第一个相交点 //const osgUtil::LineSegmentIntersector::Intersection& intersection = intersections[0]; for (const auto& intersection : intersections) { const osg::Vec3& point = intersection.getWorldIntersectPoint(); std::cout << "Intersection point: " << point.x() << " " << point.y() << " " << point.z() << std::endl; osg::ref_ptr<osg::Geode> redSphere = createRedSphere(point, 10.1f); // 半径为1的红色球体 view.getSceneData()->asGroup()->addChild(redSphere); break; // 只处理第一个相交点 } //const osg::Vec3& point = intersection.getWorldIntersectPoint(); //std::cout << "Intersection point: " << point << std::endl; } else { std::cout << "No intersection found." << std::endl; } } else { std::cout << "No intersection found." << std::endl; } // 清理资源 //delete intersector; } }; int main(int argc, char** argv) { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; // 加载场景 cow.osg excavator.OSGB library.OSGB osg::Node* root = osgDB::readNodeFile("library.OSGB"); if (!root) { std::cerr << "Error loading model" << std::endl; return 1; } viewer->setSceneData(root); // 添加鼠标拾取事件处理器 viewer->addEventHandler(new PickHandler()); // 开始运行 return viewer->run(); } ////////////////
#######################################
标签:const,鼠标,ea,拾取,osgUtil,new,include,osg From: https://www.cnblogs.com/herd/p/18555625