首页 > 其他分享 >osg三维场景中拾取鼠标在模型表面的点击点

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

时间:2024-11-19 21:18:35浏览次数:1  
标签:const 鼠标 ea 拾取 osgUtil new include 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();
}

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

 

 

 

 

 

 

 

 

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

标签:const,鼠标,ea,拾取,osgUtil,new,include,osg
From: https://www.cnblogs.com/herd/p/18555625

相关文章

  • xtable鼠标划上出提示框
     renderHeader:function(h,{column}){  returnh(   "span",   {    slot:"content",    class:"table-header-flex",   },   [    h(     "el-tooltip",     {     ......
  • OSG开发笔记(三十二):深入理解相机视口、制作支持与主视图同步变换旋转的相机HUD
    前言  深入理解相机视口,摸索相机视口旋转功能,背景透明或者不透明。  本篇,实现了一个左下角旋转HUD且背景透明的相机视口。 Demo           HUD相机的坐标  抬头HUD就是通过投影矩阵来实现,具体可参看《OSG开发笔记(二十):OSG使用HUD......
  • Unity实现鼠标框选功能
    usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.UI;publicclassDrawRect:MonoBehaviour{publicstaticDrawRectInstance;publicDrawRect(){Instance=this;}......
  • 【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
    需求说明结合前篇,仓库管理和获取鼠标点击的世界坐标位置两篇内容,已经实现了:鼠标或键盘控制玩家移动;玩家触碰物体后,将物体放入仓库;鼠标点击仓库栏中的物体,任意放在空间中的功能。接下来想要实现:鼠标点击仓库栏的物体之后,物体会跟随鼠标移动;键盘控制待放置的......
  • CSS3 超实用属性:pointer-events(可穿透图层的鼠标事件)
    1、是什么pointer-events 直译为指针事件,该属性指定在什么情况下某个DOM可以成为鼠标事件的target。简而言之,就是允许/禁止DOM的鼠标事件(click事件、hover事件、mouse事件等鼠标事件)2、具体属性分析用法分析:pointer-events:auto|none|visiblePainted|visibleFill|......
  • MDK 的编译过程及文件类型全解——好记性不如烂鼠标
    本文是学习野火的指南针开发板过程的学习笔记,可能有误,详细请看B站野火官方配套视频教程(这个教程真的讲的很详细,给官方三连吧)引言:     我们用MDK编写源代码,然后编译生成机器码,再把机器码下载到STM32芯片上运行,但是这个编译、下载的过程MDK究竟做了什么工作?它编译后......
  • 《Java核心技术 卷I》用户图形界面鼠标事件
    鼠标事件        如果只希望用户能够点击按钮或菜单,那么就不需要显式地处理鼠标事件,鼠标操作将由用户界面中的各种组件内部处理,不过,如果希望用户能使用鼠标画图,就需要捕获鼠标移动,点击和拖动事件。本节,我们将展示一个简单的图形编辑器应用,它允许用户在画布上放置、移......
  • 【Unity】鼠标点击获取世界坐标位置:物体移动至鼠标点击的位置
    需求说明鼠标点击3D场景时,可以获取其所在的世界坐标;鼠标点击3D物体时,可以获取该物体;鼠标点击3D物体时,可以让玩家移动至该物体;成果展示Scene部分关于仓库栏的设置,物体如何进入仓库内容【查看此篇】能够被获取的物体,必须需要是一个碰撞体,即绑定了碰撞体组件。Mouse3D需要......
  • 【Unity】仓库逻辑:拾取物体进仓库和扔掉物品
    需求说明目标:实现玩家移动过程中,拾取物体,物体被放入仓库;点击仓库中物体,重新扔回3D场景中逻辑。逻辑分析:需要玩家可以移动;需要检测玩家和物体的碰撞,并摧毁物体;需要识别物体的类别;新物体直接新建,已有的物体增加数量;需要记录仓库的物体详情列表,并响应列表的变化;需要仓库的UI......
  • GIS融合之路(八)-如何用Cesium直接加载OSGB文件(不用转换成3dtiles)
    系列传送门:山海鲸可视化:GIS融合之路(一)技术选型CesiumJS/loaders.gl/iTowns?山海鲸可视化:GIS融合之路(二)CesiumJS和ThreeJS深度缓冲区整合山海鲸可视化:GIS融合之路(三)CesiumJS和ThreeJS相机同步山海鲸可视化:GIS融合之路(四)如何用CesiumJS做出CesiumForUnreal的效果山海鲸可视化......