osg三维场景中拾取鼠标在模型表面的点击点

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();
}

////////////////

 

 

 

 

 

 

 

 

#######################################

posted @ 2024-11-19 21:26  西北逍遥  阅读(4)  评论(0编辑  收藏  举报