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.OSGBosg::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(); }////////////////
#######################################