OSG求交器(一)面求交器PlaneIntersector

OSG 碰撞检测 五个面的盒子 机器人整体与盒子的五个面求交集,盒子以一个Group 存在与场景中,这样便于移动。碰撞检测时,先获取盒子的包围盒,然后将包围盒裁剪成五个小包围盒 分别于机器人进行检测。机器人仿真运动时,将物体放到盒子里,需要对盒子的面 进行检测。... 阅读详情
AI摘要

本文详细介绍了OSG中的平面求交器使用方法及注意事项,包括如何构造求交器和平面,如何处理求交结果并将其转换为世界坐标系下的坐标。同时,通过一个示例展示了如何求出平面与地形的交线。

在三维场景中,经常会遇到需要与场景中模型进行交互的问题,最常见的方式是选择模型,对模型进行各种移动、高亮等操作,这些操作一般需要使用osg中提供的求交器来实现,在OSG中提供了如下的求交器(OSG 3.4.0版本)


包括:组求交器(IntersectorGroup),线段求交器(LineSegmentIntersector),平面求交器(PlaneIntersector),多面体求交器(PolytopeINtersector),射线求交器(RayIntersector),本文主要对平面求交器(PlaneIntersector)作一些介绍,后续会陆续补充其他求交器的内容

  • 平面求交器的使用场景
平面求交器的一个常用的使用场景是求与某些模型的交线,包括轮廓线、截面线(横断面、纵断面等),如下图所示,求平面与地形的交线:


  • 使用方式
在使用平面求交器前,需要使用一个平面构造出求交器,查看它的构造函数:

osg::Plane的构造方式有多种,简单来说就是立体解析几何中关于平面的构造方式都可以(比如平面的一般式、点法式、三点式等),之后可以传入第二个参数boundingPolytope,这个参数是用来对平面进行一些约束的。我们构造的平面事实上是无穷大的,利用这个参数就可以约束平面只在某个区域内与场景中的对象求交。这个参数的构造同样是有许多面构成。当构造完成之后就可以使用最常见的求交方式完成,如下所示:

osg::ref_ptr<osgUtil::PlaneIntersector> intersector = new osgUtil::PlaneIntersector(plane, boundingPolytope);
osgUtil::IntersectionVisitor intersectionVisitor;
intersectionVisitor.reset();
intersectionVisitor.setIntersector(intersector.get());
sceneNode->accept(intersectionVisitor);
在完成之后就可以从intersector对象中获取交到的内容了
osgUtil::PlaneIntersector::Intersections& intersections = intersector->getIntersections();
可以从交到的许多Intersection中得到交到的节点polyline,一般来说,求交得到的点坐标是在局部坐标之下的,需要经过变换得到世界坐标中的值,在intersection中已经记录了这个矩阵,于是可以通过下面的变化将所有坐标转到世界坐标系中:

osgUtil::PlaneIntersector::Intersections::iterator itr;
for (itr = intersections.begin();
	itr != intersections.end();
	++itr)
{
	osgUtil::PlaneIntersector::Intersection& intersection = *itr;

	if (intersection.matrix.valid())
	{
		// OSG_NOTICE<<"  transforming "<<std::endl;
		// transform points on polyline
		for (auto pitr = intersection.polyline.begin();
			pitr != intersection.polyline.end();
			++pitr)
		{
			*pitr = (*pitr) * (*intersection.matrix);
		}

		// matrix no longer needed.
		intersection.matrix = 0;
	}
}
另一个需要注意的地方:交到的polyline事实上坐标是混乱的,如果将这些点直接练成一段LINES_STRIP,会发现这些线交错在一起,因此在求交完成之后还需要我们对这些交到的结果进行处理,至于具体的处理方式依赖于实际的应用,本文中提供的求与地面交线的方式很简单,可以将这些交点按x值从小到大或者从大到小依次排列,剔除里面重复的x值即可(使用std::set就可以)
  • 示例
本文提供一个示例,简单的求出平面与一个由VPB生成地形的交线,主要代码如下:
//用来为顶点排序
bool compareVec3(const osg::Vec3d& p1, const osg::Vec3d& p2)
{
	return p1.x() < p2.x();
}

void computeIntersection()
{
	if (_controlPoints.size() < 1)
	{
		//获取求交平面的第一个点
		_firstPointX = x;
		_firstPointY = y;
		_firstPointZ = z;
	}
	else
	{
		//绘制求交线
		osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
		osg::ref_ptr<osg::Vec3Array> vertexArray = new osg::Vec3Array;
		
		
		osg::Plane plane;
		osg::Polytope boundingPolytope;
		//地形的法线(VPB生成的地形,如果是地球表面需要计算)
		osg::Vec3d upVector(0.0, 0.0, 1.0);
		
		//求交平面的起始点和终点
		osg::Vec3d endPoint = osg::Vec3(x, y, z);
		osg::Vec3d startPoint = osg::Vec3(_firstPointX,_firstPointY,_firstPointZ);

		// 构造求交平面(点法式)
		osg::Vec3d planeNormal = (endPoint - startPoint) ^ upVector;
		planeNormal.normalize();
		plane.set(planeNormal, startPoint);

		// 第一个约束面
		osg::Vec3d startPlaneNormal = upVector ^ planeNormal;
		startPlaneNormal.normalize();
		boundingPolytope.add(osg::Plane(startPlaneNormal, startPoint));

		// 第二个约束面
		osg::Vec3d endPlaneNormal = planeNormal ^ upVector;
		endPlaneNormal.normalize();
		boundingPolytope.add(osg::Plane(endPlaneNormal, endPoint));
		
		//构造平面求交器
		osg::ref_ptr<osgUtil::PlaneIntersector> intersector = new osgUtil::PlaneIntersector(plane, boundingPolytope);
		osgUtil::IntersectionVisitor intersectionVisitor;
		intersector->setRecordHeightsAsAttributes(true);
		intersectionVisitor.reset();
		intersectionVisitor.setIntersector(intersector.get());
		_viewer->getCamera()->accept(intersectionVisitor);

		osgUtil::PlaneIntersector::Intersections& intersections = intersector->getIntersections();
		//对结果进行变换(局部坐标转到世界坐标)
		osgUtil::PlaneIntersector::Intersections::iterator itr;
		for (itr = intersections.begin();
			itr != intersections.end();
			++itr)
		{
			osgUtil::PlaneIntersector::Intersection& intersection = *itr;

			if (intersection.matrix.valid())
			{
				for (auto pitr = intersection.polyline.begin();
					pitr != intersection.polyline.end();
					++pitr)
				{
					*pitr = (*pitr) * (*intersection.matrix);
				}
				// matrix no longer needed.
				intersection.matrix = 0;
			}
		}

		//剔除重复的x值以及对交点按x值进行排序
		std::set<osg::Vec3d, decltype(compareVec3)*>
			myVec3Array(compareVec3);

		osgUtil::PlaneIntersector::Intersections::iterator itrs;
		for (itrs = intersections.begin();
			itrs != intersections.end();
			++itrs)
		{
			osgUtil::PlaneIntersector::Intersection& intersection = *itrs;
				for (auto pitr = intersection.polyline.begin();
					pitr != intersection.polyline.end();
					++pitr)
				{
					myVec3Array.insert(*pitr);
				}
		}
		
		for (auto pitr = myVec3Array.begin(); pitr != myVec3Array.end(); ++pitr)
		{
			vertexArray->push_back(*pitr));
		}

		osg::ref_ptr<osg::Vec4Array> colorArray = new osg::Vec4Array();
		colorArray->push_back(osg::Vec4(255,0,0,0));
		geometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);
		osg::ref_ptr<osg::LineWidth> lineWidth = new osg::LineWidth();
		lineWidth->setWidth(2.0f);
		geometry->getOrCreateStateSet()->setAttributeAndModes(lineWidth, osg::StateAttribute::ON);
		geometry->setVertexArray(vertexArray);
		osg::ref_ptr<osg::DrawArrays> drawArray = new osg::DrawArrays(osg::DrawArrays::LINE_STRIP, 0, vertexArray->size());
		geometry->addPrimitiveSet(drawArray);
		_geode->addChild(geometry);
		_geode->dirtyBound();
	}
}


4-osg 拓展线段求交器(Expand LineSegmentIntersector拾取:点,线,面) 4-osg 拓展线段求交器(拾取:点,线,面) 实现功能 拓展:LineSegmentIntersector, 实现点,线,面的求交 ray: 根据near and far plane 求出frustum所截取的线段; kdTree, octree(oct tree 在LOD时再补): 加速搜索 intersection: select point, line, face and object hight light the selection object 实现思路 ray ray: 单击window 阅读详情

相关推荐

基于osgEarth的卫星瞬时覆盖绘制方法

分析了在OSG场景中绘制卫星覆盖范围时存在的2个问题,即圆锥面透明显示不稳定和地表覆盖范围线消隐不正确。给出了2个问题的解决方法:根据视点位置动态构造图元和绕过Z缓存直接计算覆盖线的可见性。

eyepeak的博客 2325

OSG入门_场景图形与OpenSceneGraph概述01

osgUtil库集合了许多用于场景图形处理和几何修改的工具; osgDB使用插件管理的架构,支持大量常见的2D图形和3D模型文件格式; osgViewer库定义了一些视口类,因而可以将OSG集成到许多视窗设计工具中。

部落阁 1820

osg--几何模型

osg与opengl管理数据存储的区别 opengl 即时模式:glBegin()和glEnd()之间的顶点 顶点数组模式:数组在内存 显示列表模式:顶点和像素数据编译后拷贝入显存,重复使用 顶点缓冲数组模式:数组在显存 osg 顶点数组模式 显示列表模式 快速绘制 示例 #include <osg/ShapeDrawable> #include <osg/Geo...

蓝蓝的天 568

OSG笔记:对线求交失败

使用以下两个求交器,对一根直线进行求交,但始终得不出结果。 直线求交器 osgUtil::LineSegmentIntersector 多面体求交器 osgUtil::PolytopeIntersector

憧憬,思考,奋斗,飞翔 1225

osg碰撞检测进阶

osg碰撞检测进阶 本文展示了一种 已知x,y平面坐标,求取其对应模型上z值的方法;进一步分析osgUtil::LineSegmentIntersector和osgUtil::IntersectionVisitor类,回答如下问题:1)osgUtil::LineSegmentIntersector,如何实现更精细的模型加载,然后进行碰撞检测;2)osgUtil::LineSegmentIntersector线段求交,控制参数分析;3)如何实现点云(无三角网信息)的碰撞检测。 目录 1 前言 2 os

CPWWHSU的博客 2655

OsgEarth中IntersectionPicker

osg碰撞检测进阶 osgUtil封装了RayIntersector、LineSegmentIntersector、PlaneIntersector求交器,分别用于三维空间射线、线段、平面与场景osg::Node的求交,本文主要分析三种求交器应用的代码、进而分析其内部实现的代码结构,同时分析其求交的特点及应用场景,并实现一种针对点云的碰撞检测求交器。 目录 1 平面求交器的应用及分析 2 osg实现点云的碰撞检测 内容 1 平面求交器的应用及分析 osg中求交...

CPWWHSU的博客 5055

OSG 碰撞检测之多面体求交器代码解读(PloytopeIntersector)

关于碰撞检测,始终是物理系统在图形学运用上的一个比较复杂的问题.碰撞检测做的好不好.完全决定一个场景漫游的逼真性.      这几天,在坐城市汽车仿真处理上,对于驱动汽车运动时候,对于汽车的碰撞检测问题困扰了我相当的久.始终没能做到很好.这当中我现在使用的汽车包围体对场景进行求交测试时候,用到了OSG中PolytopeIntersector.      对于一个Polytope 应当是多个平面

ximenchuixuezijin的专栏 4653

Android 的端智能学习路径

基础层:先补齐 Android 进阶(JNI / 性能优化)和 AI 基础概念,无需深入算法开发;核心层:掌握 TFLite 的模型加载、推理、量化,能完成基础端侧推理;落地层:聚焦实战场景(图像 / OCR / 语音),解决工程化问题(模型管理、异常处理);优化层:通过模型量化、硬件加速、工程优化,提升推理性能和用户体验。

hqiangtai的博客 344

OSG笔记:(转载)OSG 碰撞检测之多面体求交器代码解读(PloytopeIntersector)

osg的碰撞检查

憧憬,思考,奋斗,飞翔 546

KV Cache 详解:新手也能理解的 LLM 推理加速技巧

(Autoregressive)生成的,即每次生成一个 token,然后将其作为输入继续生成下一个 token。:如果序列太长,超过了 KV Cache 的存储限制,就需要丢弃最早的 tokens(类似滑动窗口)。时,每次只会生成一个新 token,然后再把这个 token 作为输入继续生成下一个 token。,只缓存计算过的 K,VK, V,每次只计算新 token 的 K,VK, V,从而提升推理效率。:如果输入的 prompt 发生变化,之前的 KV Cache 不能复用,必须重新计算。

Harry的博客 7358

Simulink+Simscape多体仿真:六自由度Stewart平台动力学建模全流程

本文详细介绍了使用Simulink和Simscape Multibody进行六自由度Stewart平台动力学建模的全流程,涵盖从CAD模型导入、运动学逆解计算到实时控制系统的设计。通过MATLAB/Simulink与Simscape的协同工作,实现高保真度的并联机器人仿真,适用于飞行模拟器、精密加工等高精度领域。

r2s3t4的博客 486

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

osg 场景解耦阿虎与场景漫游 ​​​​​​​显示位置及拾取示例

liangfei868的博客 1969

ISP一键下载电路分析+74HC1G66GW(信号图)

之前要不用的最小系统的开发板要不就是用的SWD调试口,没有注意过ISP一键下载电路是个怎么回事,因为需要就简单的看了一下野火的ISP一键下载电路。 默认情况一下,一般我们的程序都是从用户闪存也就是内部的FLASH启动的, 对于F103RCT6来说ROM的大小是512kb,启动地址位0x8000000,这个在IDE keil里可以看的到,如下图。 首先简单理解一下ISP是什么: 可以把他理解为芯片厂商出场时固化在ROM当中的一段程序,它的功能就是把你写的程序一点点的搬运到FLASH当中,它引出了两个引脚

lipengyu1363658871的博客 4861

OSG交运算、选取和碰撞

osg学习

qq_42491346的博客 2068

1、Ka频段双极化低剖面卫通相控阵天线

设计了双馈口叠层十字缝隙耦合天线,采用“双线极化天线 +旋转馈电 + 移相控制”架构,采用双馈口的叠层十字缝隙耦合天线,并以 2 x2 阵列为主体,旋转排布实现二次圆极化,同时极化可切换,通过多层 PCB 工艺实现天线层、控制/电源层功分网终层、芯片层一体化集成,研制出 64 阵元的圆极化可切换发射天线,测试结果表明:天线工作 频段为 27.5 ~31 GHz,可实现60°扫描,法向轴比

qq_43416206的博客 4369

11、基于STM32的智能药盒

当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化智能控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未有的速度被单片机智能控制系统所取代。嵌入式具有体积小、功能强、成本低、应用面广等优点,可以说,智能控制与自动控制的核心就是单片机。

行走的皮卡丘 6102

OSG拾取点和线当然面也能拾取

if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) { osg::ref_ptr&amp;lt;osgUtil::PolytopeIntersector&amp;gt; picker = new osgUtil::PolytopeIntersector(osgUtil::Intersector::WINDOW, ea.getX...

封狼居胥 2830

【WorkBuddy专栏52】Codex与WorkBuddy生态适配、用户争夺与未来走向(下)

【WorkBuddy专栏52】Codex与WorkBuddy在中国大陆的发展——生态适配、用户争夺与未来走向(下)

AI人人懂 679

osg的polytopeintersector-备忘录

中实现多面体和三角形的轮廓线(顶点存在src中)求交,凸台polytope存着6个平面plane,每个plane法向正向指向体内部,遍历每个平面,切割src轮廓线,dest中存着在plane正半空间的那部分轮廓,然后src和dest交换,接着下一个plane再切src轮廓线,留下正半空间中的轮廓线…OSG的osgUtil::PolytopeIntersector类实现凸多面体和点线段三角形求交器的实现,在pick中框选肯定是用一个四棱锥凸台几何体,单选其实也是一个四棱锥凸台。

yrcpp的博客 657

YOLO环境配置+项目启动全流程(Conda+PyCharm超详解)

YOLO(You Only Look Once)是一个基于深度学习的目标检测算法,广泛应用于智能识别领域。本篇保姆级教学将手把手教你如何从零开始运行一个YOLO项目,适合完全没有基础的新手。

一键难忘的博客 1540

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

OSG碰撞检测

OSG碰撞检测

mmqqyyqqyyq的博客 2206

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

osg 两个面求交线

面用osg::Matrix  来表示。 osg::Vec3 ptOri = osg::(0,0,0) * mat; (面的原点) osg::Vec3 vecX = mat.getRotate() * osg::X_AXIS ; (X轴) osg::Vec3 vecY = mat.getRotate() * osg::Y_AXIS ; (Y轴) 要求两个面的交线,首先要判断两个面是

TheDeaf的专栏 2837

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

osg 笔记一 (转)

场景图形采用一种自顶向下的,分层的树状数据结构来组织空间数据集,以提高渲染的效率   场景图形树结构的顶部是一个根节点,从根节点向下延伸,各个组节点中均包含了几何信息和用于控制其外观的渲染状态信息。根节点和各个组节点都可以有零个(实际上是没有执行任何操作)或多个子成员。在场景图形的最底部,各个叶节点包含了构成场景中物体的实际几何信息。   Osg程序使用组节点来组织和排列场景中的几何体。 ...

weixin_34342578的博客 418

osg_操作器、碰撞检测、上楼梯篇

一.  操作器 OSG经常用到的自带操作器为TrackBall, osgEarth经常用到的自带操作器为EarthManipulator 自己要写操作器应继承于osgGA::CameraManipulator 流程:1. 设置自定义操作器  2. viewer在帧绘制时候取操作器控制的矩阵,(矩阵控制一般重载getMatrix()和getInverseMatrix()函数),然后更新came

Scarlett_OHara的博客 3140

OSG实例(模型遍历,模型控制,粒子系统,碰撞检测)

OSG建立场景时,一般包含以下步骤: 1,建立模型根节点以及场景类; 2,加入模型; 3,加入模型场景; 4,建立摄像操作,加入场景类; 5,建立模型控制类,加入模型根节点; 6,运行场景。 如下的主函数包含所有的步骤: 其中MyOSGCamera为摄像机控制类;CMyNodeCallback为模型控制类;CMyHelpHandler为帮助显示类 MyOSGCamera控制摄像机的移动方向; CMyNodeCallback控制模型的前后左右移动; CMyHelpHandler按 H 键弹出帮助提示。 #in

qq_40004575的博客 1946

osg 不同节点间的碰撞检查

目标是,视图中有很多节点,当两个节点间有碰撞,那么能够检测出来。(其中不存在运动模型) 问题简化为检查两个节点是否碰撞。 解决思路是首先判断两个节点的包围盒(对象比较细长,不适合用包围球)是否有相交,如果没有相交,那么这两个节点肯定没有碰撞。如果包围盒有相交,然后用第一个节点上所有线段构成相交测试器(osgUtil::IntersectVisitor)与第二个节点进行相交测试,如果有相交,那么

TheDeaf的专栏 4268
上一篇: osg示例解析之osgcamera(1)
下一篇: OpenGL的列向量和OSG的行向量
csxiaoshui
博客等级 码龄16年 873粉丝 158原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值