当前位置: 首页 > news >正文

场景交互与场景漫游-交运算与对象选取(8-1)

交运算与对象选取

        在面对大规模的场景管理时,场景图形的交运算图形对象的拾取变成了一项基本工作。OSG作为一个场景管理系统,自然也实现了场景图形的交运算,交运算主要封装在osgUtil 工具中在OSG中,osgUtil是一个非常强有力的工具,集合了场图形处理、几何体修改工具及高层次的遍历几个功能。

交运算

        交运算(Intersection)本身是一个非常复杂的立体几何问题。当在阅读这一部分源代码时,读者会发现如果有非常丰富的立体几何思想见解,将能够很快理解源代码,如果没有的话,即使笔者在这里分析源代码也是没有用的。当然,作为一个应用者没有必要去过多关注底层是如何实现的。

        关于交运算,OSG本身的实现也是比较局限的,但是对于普通应用已经足够了,可以用一个继承关系图表示出来,如图8-21所示。

图8-21 osgUtil::Intersector 的继承关系及派生图

从继承关系图中可以看出,所有的交运算都共用一个父类osgUtil::Intersector类。下面对这个类的作用逐一说明。

  • osgUtil::Intersector:是一个纯虚类它定义了相交测试的接口osgUtil库从osgUtil::Intersection继承了多个类,适用于各种类型的几何体(如线段、多边形等)。执行相交测试时,应用程序将继承自osgUtil::Intersector的某个类实例化,再将其传递给 osgUtil::IntersectionVisitor 的实例,并请求该实例返回数据以获取交运算的结果。
  • osgUtil::LineSegmentIntersector继承自osgUtil::Intersector 类,用于检测指定线段和场景图形之间的相交情况,并向程序提供查询相交测试结果的函数。该类提供了一种定义射线的方法。它包括两个osg::Vec3实例,一个用于定义线段的起点,另一个用于定义终点。当交集测试被触发时,它将检测射线的相交情况并执行相应的操作。这个在示例显示位置及拾取示例中会用到,可以根据鼠标的位置初始化一个osgUtil::LineSegmentIntersector类的对象可以指定一个特定的线段来执行相交检测,在构造函数中即可初始化。
// 创建一个线段交集检测对象
osgUtil::LineSegmentIntersector::Intersections intersections:
viewer->computelntersections(x,y,intersections)

        通过相交运算,更多的是希望得到相交的点,可以通过申请一个迭代器来实现,代码如下:

// 得到相交交集的交点for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();hitr!=intersections.end();++hitr)
{// 输入流cout<<”Mouse in world X:”<<hitr->getWorldIntersectPoint().x()<<” Y:”<<hitr->getWorldIntersectPoint().y()<<” Z:”<<hitr->getWorldIntersectPoint().z()<<endl;
}
  • osgUtil::PolytopeIntersector与osgUtil::LineSegmentIntersector类似,不过,该类用于检测由一系列平面构成的多面体的相交运算。当鼠标单击场景图形中某一区域,希望拾取到鼠标位置附近的一个封闭多面体区域时,osgUtil::PolytopeIntersector类最实用。
  • osgUtil::PlaneIntersector,与osgUtil::LineSegmentIntersector类似,用于检测出一系列平面构成的平面的相交运算。

        osgUtil::IntersectionVisitor是一个比较特殊的类,它不直接继承自osgUtil::Intersector,继承关系图如图8-22所示。

图8-22 osgUtil::IntersectionVisitor 的继承关系图

        从继承关系图可以看出,它继承自osg::NodeVisitor,创建和触发机制与osg::NodeVisitor 实例大致相似。访问器需要维护一个进行交集测试的线段列表,而对于其中的每一条线段,访问器都会创建一个交点列表(osgUtil::IntersectVisitor::HitList 实例),它主要用于搜索场景图形中与指定几何体相交的节点。而最后相交测试的工作将在osgUtil::Intersector 的继承类中完成。在前面的自定义漫游操作器中,碰掩检测就是采用该类,最后的检测工作在osgUtil::LineSegmentIntersector 中完成,创建的过程如下:

// 创建一个交集访问器
osgUtil::IntersectVisitor ivXY;
// 根据新的位置得到两条线段检测
osg::ref_ptr<LineSegment> lineXY = new osg::LineSegment(newPos, m_vPosition);
osg::ref_ptr<osg::LineSegment> lineZ = new osg::LineSegment(newPos1 + osg::Vec3(0.0,0.0,10.0), newPos1 - osg::Vec3(0.0,0.0,-10.0));
// 添加两条线段
ivXY.addLineSegment(lineZ.get());
ivXY.addLineSegment(lineXY.get());// 开启交集检测
m_pHowViewer->getSceneData()->accept(ivXY);

        交点列表(osgUtil::IntersectVisitor:HitList)的作用为:一条单一的线段可能与场景中的多个几何体实例(或者多次与同一个几何体)产生交集。对于每一条参与交集测试的线段,系统均会产生一个列表,这个列表包含了所有交集测试产生的 Hit 实例。如果没有监测到任何交集,该列表保持为空。

显示位置及拾取示例

        显示位置及拾取示例的代码如程序清单 8-10所示

/******************************************* 显示位置及拾取示例 *************************************/
// pick 事件处理器
class CPickHandler:public osgGA::GUIEventHandler
{
public:// 构造函数CPickHandler(osg::ref_ptr<osgText::Text> updateText) :_updateText(updateText){}// 析构函数~CPickHandler(){}// 事件处理bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa);// pickvirtual void pick(osg::ref_ptr<osgViewer::Viewer> viewer, const osgGA::GUIEventAdapter &ea);// 设置显示内容void setLabel(const std::string &name){_updateText->setText(name);}
protected:// 得到当前视图矩阵osg::Vec3 position;osg::Vec3 center;osg::Vec3 up;// 传递一个文字对象osg::ref_ptr<osgText::Text> _updateText;
};// HUD
class CreateHUD
{
public:CreateHUD(){}~CreateHUD(){}// 创建HUDosg::ref_ptr<osg::Node> createHUD(osg::ref_ptr<osgText::Text> updateText){// 创建一个相机osg::ref_ptr<osg::Camera> hudCamera = new osg::Camera;// 设置绝对帧引用hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);// 设置正投影矩阵2DhudCamera->setProjectionMatrixAsOrtho2D(0, 1280, 0, 1024);// 设置视图矩阵hudCamera->setViewMatrix(osg::Matrix::identity());// 设置渲染顺序为POSThudCamera->setRenderOrder(osg::Camera::POST_RENDER);// 清除深度缓存hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);// 设置字体string timesFont = "D:\\WorkAndStudy\\SDK\\VS2013\\OSG\\Data\\font\\cour.ttf";// 设置位置osg::Vec3 position(700, 900, 0.0);osg::ref_ptr<osg::Geode> geode = new osg::Geode();osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();// 关闭光照stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);//关闭深度测试stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);geode->addDrawable(updateText.get());hudCamera->addChild(geode.get());updateText->setCharacterSize(20.0f);updateText->setFont(timesFont);updateText->setColor(osg::Vec4(1.0f, 1.0, 1.0, 1.0));updateText->setText("");updateText->setPosition(position);// 设置数据变量为DYNAMICupdateText->setDataVariance(osg::Object::DYNAMIC);return hudCamera.get();}
};/* 显示位置及拾取示例 */
void pickLineSegment_8_10(const string &strDataFolder);/******************************************* 显示位置及拾取示例 *************************************/
// 事件处理函数
bool CPickHandler::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa)
{switch (ea.getEventType()){// 每一帧case(osgGA::GUIEventAdapter::FRAME) :{osg::ref_ptr<osgViewer::Viewer> viewer = dynamic_cast<osgViewer::Viewer*>(&aa);// 得到视图矩阵viewer->getCamera()->getViewMatrixAsLookAt(position, center, up);if (viewer){// 执行PICK动作pick(viewer.get(), ea);}return false;}default:return false;}
}// PICK动作
void CPickHandler::pick(osg::ref_ptr<osgViewer::Viewer> viewer, const osgGA::GUIEventAdapter &ea)
{// 创建一个线段交集检测对象osgUtil::LineSegmentIntersector::Intersections intersections;std::string gdlist = "";// 申请一个流std::ostringstream os;// 得到鼠标的位置float x = ea.getX();float y = ea.getY();// 如果没有发生交集运算及鼠标没有点中物体if (viewer->computeIntersections(x, y, intersections)){// 得到相交交集的交点for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin(); hitr != intersections.end(); ++hitr){// 输入流os << "Mouse in World X:" << hitr->getWorldIntersectPoint().x() << "  Y:" << hitr->getWorldIntersectPoint().y() << "  Z:" << hitr->getWorldIntersectPoint().z() << endl;}}// 输入流os << "Viewer Position X:" << position[0] << " Y:" << position[1] << " Z:" << position[2] << endl;gdlist += os.str();// 设置显示内容setLabel(gdlist);
}void pickLineSegment_8_10(const string &strDataFolder)
{// 创建Viewer对象,场景浏览器osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();// 读取地形模型string strDataPath = strDataFolder + "lz.osg";osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);osg::ref_ptr<osgText::Text> updateText = new osgText::Text();CreateHUD *hudText = new CreateHUD();// 添加到场景root->addChild(node);root->addChild(hudText->createHUD(updateText));// 添加PICK事件处理器viewer->addEventHandler(new CPickHandler(updateText));// 优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root);viewer->setSceneData(root);viewer->realize();viewer->run();
}

        运行程序,截图如图 8-23 所示。

图8-23显示位置及拾取示例截图

相关文章:

场景交互与场景漫游-交运算与对象选取(8-1)

交运算与对象选取 在面对大规模的场景管理时&#xff0c;场景图形的交运算和图形对象的拾取变成了一项基本工作。OSG作为一个场景管理系统&#xff0c;自然也实现了场景图形的交运算&#xff0c;交运算主要封装在osgUtil 工具中在OSG中&#xff0c;osgUtil是一个非常强有力的工…...

Vue中动态Class实战

效果展示 需求 想实现一个假如有5个div块&#xff0c;默认都是灰色&#xff0c;鼠标悬浮到哪个div上&#xff0c;那个div就显示为黑色。 具体的实现业务逻辑可根据这个进行演变 设计 通过动态 class 类名来实现&#xff0c;实现鼠标悬浮到div时动态绑定class 版本 Vue 3.…...

B站短视频如何去水印?一键解析下载B站视频!

在浏览B站视频时&#xff0c;我们有时会遇到带有水印的场景。这些水印可能会干扰我们对视频内容的观看体验&#xff0c;特别是在全屏观看时。此外&#xff0c;当我们想要保存或分享这些视频时&#xff0c;水印也会成为一种障碍。因此&#xff0c;去除水印的需求就变得非常迫切。…...

最大子段和(分治法+动态规划法)

求最大子段和 此类问题通常是求数列中连续子段和的最大值&#xff0c;经典的股票问题就是考察的这个思想及拓展。 例题&#xff1a; AcWing:1054. 股票买卖 Leetcode:53. 最大子数组和 分治法O(nlogn) 此类问题时分适合采用分治思想&#xff0c;因为所有子区间 [ s t a r t …...

内置函数和消息传递API

消息传递范式 消息函数、聚合函数与更新函数 消息函数接受一个参数 edges&#xff0c;这是一个 EdgeBatch 的实例&#xff0c; 在消息传递时&#xff0c;它被DGL在内部生成以表示一批边。edges 有 src、 dst 和 data 共3个成员属性&#xff0c; 分别用于访问源节点、目标节点…...

不标年份的葡萄酒质量好吗?

我们在葡萄酒标上经常看到生产年份&#xff0c;也就是指全部葡萄采摘的年份。旧世界葡萄酒产国认为葡萄酒年份对他们的影响较大&#xff0c;而新世界葡萄酒&#xff0c;年份的意义就稍微小些。甚至有一部分葡萄酒酒标上没有年份。在酒标上没有标注年份的葡萄酒&#xff0c;被称…...

2023年【高处安装、维护、拆除】模拟考试题及高处安装、维护、拆除模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【高处安装、维护、拆除】模拟考试题及高处安装、维护、拆除模拟考试题库&#xff0c;包含高处安装、维护、拆除模拟考试题答案和解析及高处安装、维护、拆除模拟考试题库练习。安全生产模拟考试一点通结合国家…...

简单模拟 Spring 创建的动态代理类(解释一种@Transactional事务失效的场景)

模拟 Spring 创建的动态代理类 本文主要目的是从父类和子类继承的角度去分析为什么在 Service 标注的业务类中使用 this 调用方法会造成事务失效。解释在这种情况下 this 为什么是原始类对象而不是代理类对象。 问题描述 在 Service 标注的业务类中&#xff0c;如果调用本类…...

万户OA upload任意文件上传漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品&#xff0c;统一的基础管理平台&#xff0c;实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台&#xff0c;将外网信息…...

如何写好一篇软文?怎样写软文比较有吸引力?

软文&#xff0c;即柔性广告&#xff0c;是一种通过文字、图片等形式&#xff0c;将广告信息融入到内容中&#xff0c;以达到宣传、推广、营销目的的文章。企业和品牌每天都会在互联网上投放大量软文&#xff0c;软文起到润物细无声的作用&#xff0c;可以在无形中影响用户心智…...

从0开始学习JavaScript--JavaScript中的对象

JavaScript中的对象是一种重要的数据结构&#xff0c;它不仅是语言的基石&#xff0c;还提供了丰富的功能和灵活性。本文将深入研究JavaScript对象的创建、属性访问、方法定义&#xff0c;以及实际应用中的技巧&#xff0c;通过丰富的示例代码&#xff0c;帮助读者更全面地了解…...

【LeetCode刷题】--7.整数反转

7.整数反转 注意&#xff1a;在推入数字之前&#xff0c;需要判断MIN_VALUE< res*10digit<MAX_VALUE&#xff0c;不满足就返回0 class Solution {public int reverse(int x) {int res 0;while(x!0){//需要判断MIN_VALUE< res*10digit<MAX_VALUEif(res < Integ…...

Genio 500_MT8385安卓核心板:功能强大且高效

Genio 500(MT8385)安卓核心板是一款功能强大且高效的AIoT平台&#xff0c;内置的AI处理器(APU)工作频率可达500MHz&#xff0c;支持深度学习、神经网络加速和计算机视觉应用。配合高达2500万像素的摄像头&#xff0c;可以为AI相机应用提供清晰、精确的图像&#xff0c;如人脸识…...

idea导入javaweb变成灰色

解决办法&#xff1a; 如果这时候src是蓝色&#xff0c;其余都是灰色文件夹&#xff0c;这时候要先把src文件夹变成灰色&#xff0c;否则之后会报错 src文件变成灰色方法&#xff0c;右键src,选择make direcory as 选择unmark 如果src不是蓝色&#xff0c;就是灰色&#xff0…...

SpringBoot集成Memcached

SpringBoot集成Memcached 1、Memcached 介绍 Memcached 是一个高性能的分布式内存对象缓存系统&#xff0c;用于动态Web应用以减轻数据库负载。它通过在内存中 缓存数据和对象来减少读取数据库的次数&#xff0c;从而提高动态、数据库驱动网站的速度。Memcached基于一个存储…...

git基本操作(配图超详细讲解)

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 创建git本地仓库 配置仓库 认识工作区&#xff0c;暂存区&#xff0c;版本库 修改文件 版本回退 撤销修改 删除文件 创建git本地仓库 要提前说的是&#xff0c;仓库是进⾏版本控制的⼀个⽂件⽬录。我们要想对⽂…...

【网络通信】浅析UDP与TCP协议的奥秘

在现代互联网中&#xff0c;UDP&#xff08;用户数据报协议&#xff09;和TCP&#xff08;传输控制协议&#xff09;是两种最常用的传输协议&#xff0c;它们被广泛应用于网络数据传输。尽管这两种协议都可以用来在网络上传输数据&#xff0c;但它们在设计目标、特点和适用场景…...

C#核心笔记——(二)C#语言基础

一、C#程序 1.1 基础程序 using System; //引入命名空间namespace CsharpTest //将以下类定义在CsharpTest命名空间中 {internal class TestProgram //定义TestProgram类{public void Test() { }//定义Test方法} }方法是C#中的诸多种类的函数之一。另一种函数*&#xff0c;还…...

C++ 删除无头链上所有指定值为x的节点。

C 删除无头链上所有指定值为x的节点。 #include<stdio.h> #include<ctype.h> #include<stdlib.h> typedef struct app {int data;struct app* next; }APP; int main() {int n;int node;int x;while (scanf("%d", &n) ! EOF){APP* head NULL, …...

linux基本指令以及热键

基本指令 ♥clear ♥whoami ♥who ♥pwd ♥ls指令&#xff08;重点&#xff09; ls -a&#xff1a; ls -l ♥mkdir ♥cd指令 ♥touch指令 ♥stat指令 ♥rmdir指令 && rm 指令 ♥man指令 ♥nano指令 ♥cp指令 ♥mv指令 ♥cat指令 &#x1f5e1;输出/输出重定向 &#x1…...

AI如何重塑移动App开发:从功能交付到智能服务的范式跃迁

1. 项目概述&#xff1a;当手机App开发不再只是“写代码”&#xff0c;而变成一场数据驱动的智能进化“How AI and ML are Turning the Mobile App Development Industry into a Smart Industry?”——这个标题不是一句空泛的行业口号&#xff0c;而是我过去三年深度参与17个中…...

SHE 密钥注入的“通配符魔法”:从 UID 通配到 AUTOSAR 分层落地

想象一下&#xff0c;你是一家汽车电子工厂的技术员&#xff0c;需要为成千上万个 ECU 刷写密钥。每个 ECU 都有一个独一无二的 ID&#xff08;UID&#xff09;。如果每次刷写都要读取这个 UID&#xff0c;再根据 UID 计算出专属的密钥数据&#xff0c;那产线的效率会大打折扣。…...

在 LangGraph 里做动态路由:意图分类+置信度阈值+回退链路

LangGraph 生产级动态路由实战:意图分类+置信度校准+多级回退链路全栈实现 关键词 LangGraph, 大语言模型Agent, 动态路由, 意图分类, 置信度阈值校准, 多级回退机制, 可控Agent架构 摘要 当前大模型Agent开发已从玩具级Demo走向生产级落地,静态路由的固定执行逻辑无法适…...

森林The Forest - 服务器开服

对于想要自建游戏服务器的玩家&#xff0c;云鸢互联是一个不错的专业联机平台选择。它提供稳定、低延迟且724小时在线的服务器环境&#xff0c;助你轻松打造专属游戏世界。平台主打极致的新手友好——全图形化控制面板&#xff0c;无需编写代码&#xff0c;也无需掌握Linux命令…...

中性点不接地系统或中性点经消弧线圈接地系统的小电流接地故障仿真研究(Simulink仿真实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 &#x1f381…...

实力入选丨全知科技荣登嘶吼2026网络安全产业图谱

近日&#xff0c;嘶吼安全产业研究院正式发布《嘶吼2026网络安全产业图谱》。全知科技凭借在数据安全赛道的长期深耕积淀、持续技术创新能力与规模化行业落地实践&#xff0c;成功入选图谱数据安全核心板块&#xff0c;强势入围开发与应用安全、数据安全两大核心板块&#xff0…...

Tokenizer与Embedding

Transformers 系列文章目录 第一章 Transformers 简介 第二章 Transformers 模型推理&#xff1b; 第三章 Tokenizer 与 Embedding 文章目录Transformers 系列文章目录前言Tokenizer与Embedding一、Tokenizer&#xff08;分词器&#xff09;和Embedding&#xff08;词嵌入&a…...

2026年AI论文平台盘点:12款神器助你高效完成选题大纲、撰稿和降重

随着 AI 技术的持续突破&#xff0c;2026 年的论文写作工具市场已迈入“智能化、精细化、合规化”的新阶段。从本科生的课程论文到研究生的学位论文&#xff0c;再到科研人员的期刊投稿&#xff0c;AI 工具正以前所未有的专业度覆盖各类学术场景。无论是选题构思、文献检索、初…...

2026年京东云OpenClaw/Hermes Agent配置Token Plan详细搭建教程

2026年京东云OpenClaw/Hermes Agent配置Token Plan详细搭建教程。OpenClaw是开源的个人AI助手&#xff0c;Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主流 AI 工具&…...

ChatGPT网络错误自救流程图(2024新版):从浏览器控制台Network面板抓包→识别ERR_CONNECTION_RESET本质→绕过运营商深度包检测(附可执行Shell脚本)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ChatGPT网络错误自救流程图&#xff08;2024新版&#xff09;概述 当访问 ChatGPT 时遭遇“Network Error”、“Failed to fetch”、“504 Gateway Timeout”或“Connection refused”等提示&#xff0…...