OSG绘制视锥体

最近要来实现一个相机位姿态可视化的需求,不想使用pangolin,不好集成,想用osg来做可视化。以下是demo效果。

代码实现:

// Cone_of_vision.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <osgViewer/Viewer>
#include <osg/Camera>
#include <osg/Geode>
#include <osg/Geometry>

// 在创建相机视锥体时计算视锥体顶点和设置边线
osg::ref_ptr<osg::Geode> createCameraFrustum(osg::Camera* camera) {
	osg::ref_ptr<osg::Geode> geode = new osg::Geode();
	osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();

	// 获取相机的投影矩阵和视图矩阵
	osg::Matrixd projectionMatrix = camera->getProjectionMatrix();
	osg::Matrixd viewMatrix = camera->getViewMatrix();

	// 计算视锥体顶点坐标
	osg::Vec3Array* vertices = new osg::Vec3Array(9);
	double nearPlane, farPlane;
	// 获取近和远裁剪平面的值
	double fovY = 1;
	double aspectRatio = 0.5;
	projectionMatrix.getPerspective(fovY, aspectRatio, nearPlane, farPlane);
	farPlane = 1.9;
	double tanFovY = tan(fovY * 0.5);
	double tanFovX = tanFovY * aspectRatio;

	// 近裁剪平面的四个顶点
	(*vertices)[0] = osg::Vec3(0.0, 0.0, 0.0);
	(*vertices)[1] = osg::Vec3(tanFovX * nearPlane, tanFovY * nearPlane, -nearPlane);
	(*vertices)[2] = osg::Vec3(-tanFovX * nearPlane, tanFovY * nearPlane, -nearPlane);
	(*vertices)[3] = osg::Vec3(-tanFovX * nearPlane, -tanFovY * nearPlane, -nearPlane);
	(*vertices)[4] = osg::Vec3(tanFovX * nearPlane, -tanFovY * nearPlane, -nearPlane);

	// 远裁剪平面的四个顶点
	(*vertices)[5] = osg::Vec3(tanFovX * farPlane, tanFovY * farPlane, -farPlane);
	(*vertices)[6] = osg::Vec3(-tanFovX * farPlane, tanFovY * farPlane, -farPlane);
	(*vertices)[7] = osg::Vec3(-tanFovX * farPlane, -tanFovY * farPlane, -farPlane);
	(*vertices)[8] = osg::Vec3(tanFovX * farPlane, -tanFovY * farPlane, -farPlane);

	// 设置视锥体的边线
	osg::ref_ptr<osg::DrawElementsUInt> edges = new osg::DrawElementsUInt(osg::PrimitiveSet::LINES, 24);
	// 给edges数组添加顶点索引来定义边线
	edges->push_back(0); 
	edges->push_back(1);
	edges->push_back(0); 
	edges->push_back(2);
	edges->push_back(0);
	edges->push_back(3);
	edges->push_back(0);
	edges->push_back(4);

	edges->push_back(1);
	edges->push_back(2);
	edges->push_back(3);
	edges->push_back(4);

	edges->push_back(1);
	edges->push_back(4);
	edges->push_back(2);
	edges->push_back(3);


	edges->push_back(0 );
	edges->push_back(1 + 4);
	edges->push_back(0 );
	edges->push_back(2 + 4);
	edges->push_back(0 );
	edges->push_back(3 + 4);
	edges->push_back(0 );
	edges->push_back(4 + 4);
	edges->push_back(1 + 4);
	edges->push_back(2 + 4);
	edges->push_back(3 + 4);
	edges->push_back(4 + 4);

	edges->push_back(1 + 4);
	edges->push_back(4 + 4);
	edges->push_back(2 + 4);
	edges->push_back(3 + 4);

	/*edges->push_back(0);
	edges->push_back(7);
	edges->push_back(0);
	edges->push_back(8);*/

	// 其他边线的索引添加类似的操作...

	// 设置几何体属性
	geometry->setVertexArray(vertices);
	geometry->addPrimitiveSet(edges);

	geode->addDrawable(geometry);

	return geode;
}

osg::ref_ptr<osg::Geode> createPyramid() {
	osg::ref_ptr<osg::Geode> geode = new osg::Geode();
	osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();

	// 顶点数组
	osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
	vertices->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));  // 顶点
	vertices->push_back(osg::Vec3(1.0f, 0.0f, -1.0f)); // 底面顶点1
	vertices->push_back(osg::Vec3(-1.0f, 0.0f, -1.0f)); // 底面顶点2
	vertices->push_back(osg::Vec3(0.0f, 1.0f, 0.0f)); // 底面顶点3
	vertices->push_back(osg::Vec3(0.0f, -1.0f, 0.0f)); // 底面顶点4

	// 设置几何体的顶点
	geometry->setVertexArray(vertices.get());

	// 底面索引数组
	osg::ref_ptr<osg::DrawElementsUInt> baseIndices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
	baseIndices->push_back(1);
	baseIndices->push_back(2);
	baseIndices->push_back(3);

	baseIndices->push_back(2);
	baseIndices->push_back(1);
	baseIndices->push_back(4);

	baseIndices->push_back(3);
	baseIndices->push_back(2);
	baseIndices->push_back(4);

	baseIndices->push_back(1);
	baseIndices->push_back(3);
	baseIndices->push_back(4);

	// 侧面索引数组
	osg::ref_ptr<osg::DrawElementsUInt> sideIndices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
	sideIndices->push_back(0);
	sideIndices->push_back(1);
	sideIndices->push_back(2);

	sideIndices->push_back(0);
	sideIndices->push_back(2);
	sideIndices->push_back(3);

	sideIndices->push_back(0);
	sideIndices->push_back(3);
	sideIndices->push_back(4);

	sideIndices->push_back(0);
	sideIndices->push_back(4);
	sideIndices->push_back(1);

	// 添加底面和侧面索引
	geometry->addPrimitiveSet(baseIndices.get());
	geometry->addPrimitiveSet(sideIndices.get());

	geode->addDrawable(geometry.get());

	return geode;
}

osg::ref_ptr <osg::Geode > cteateQuad()
{
	//创建一个叶节点对象
	osg::ref_ptr <osg::Geode > geode = new osg::Geode();
	//创建一个几何体对象
	osg::ref_ptr <osg::Geometry >geom = new osg::Geometry();
	//添加顶点数据 注意顶点的添加顺序是逆时针
	osg::ref_ptr <osg::Vec3Array >v = new osg::Vec3Array();
	//添加数据
	v->push_back(osg::Vec3(0, 0, 0));
	v->push_back(osg::Vec3(1, 0, 0));
	v->push_back(osg::Vec3(1, 0, 1));
	v->push_back(osg::Vec3(0, 0, 1));

	//设置顶点数据
	geom->setVertexArray(v.get());

	//创建纹理订点数据
	osg::ref_ptr <osg::Vec2Array >vt = new osg::Vec2Array();
	//添加纹理坐标
	vt->push_back(osg::Vec2(0, 0));
	vt->push_back(osg::Vec2(1, 0));
	vt->push_back(osg::Vec2(1, 1));
	vt->push_back(osg::Vec2(0, 1));

	//设置纹理坐标
	geom->setTexCoordArray(0, vt.get());

	//创建颜色数组
	osg::ref_ptr <osg::Vec4Array >vc = new osg::Vec4Array();
	//添加数据
	vc->push_back(osg::Vec4(1, 0, 0, 1));
	vc->push_back(osg::Vec4(0, 1, 0, 1));
	vc->push_back(osg::Vec4(0, 0, 1, 1));
	vc->push_back(osg::Vec4(1, 1, 0, 1));

	//设置颜色数组
	geom->setColorArray(vc.get());
	//设置颜色的绑定方式为单个顶点
	geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);

	//创建法线数组
	osg::ref_ptr <osg::Vec3Array >nc = new osg::Vec3Array();
	//添加法线
	nc->push_back(osg::Vec3(0, -1, 0));
	//设置法线
	geom->setNormalArray(nc.get());
	//设置法绑定为全部顶点
	geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
	//添加图元
	geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

	//添加到叶子节点
	geode->addDrawable(geom.get());

	return geode.get();
}


int main() {
	// 创建场景图和视图器
	osg::ref_ptr<osg::Group> root = new osg::Group();
	osgViewer::Viewer viewer;

	// 创建四棱锥体几何体
	osg::ref_ptr<osg::Geode> pyramid = createCameraFrustum(viewer.getCamera());
	// 将四棱锥体添加到场景图中
	root->addChild(pyramid);

	// 设置场景图到视图器并运行
	viewer.setSceneData(root);
	return viewer.run();
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/280265.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为hcia之ipv6实验手册

R3: dhcp enable ipv6 dhcpv6 pool test address prefix 2000:23::/64 excluded-address 2000:23::2 dns-server 2000:23::2 interface GigabitEthernet0/0/0 ipv6 enable ipv6 address 2000:12::2/64 ipv6 address auto link-local undo ipv6 nd ra halt //无状态配置 inter…

Vue中的默认插槽详解

Vue中的默认插槽详解 在 Vue 中&#xff0c;插槽&#xff08;Slot&#xff09;是一种非常强大且灵活的机制&#xff0c;用于在组件中插入内容。Vue 提供了两种类型的插槽&#xff1a;默认插槽&#xff08;Default Slot&#xff09;和具名插槽&#xff08;Named Slot&#xff09…

递归详解之青蛙跳台阶和汉诺塔问题

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

GroundingDINO-根据文本提示检测任意目标

1. 背景介绍 GroundingDINO是一种新的SOTA零样本物体检测模型。在这篇文章中&#xff0c;我们将讨论Grounding DINO模型的优势&#xff0c;分析其具体的模型架构&#xff0c;并提供真实的测试样例。 闲话少说&#xff0c;我们直接开始吧&#xff01; 2.零样本目标检测 大多…

第七课:计算机网络、互联网及万维网(WWW)

第七课&#xff1a;计算机网络、互联网及万维网&#xff08;WWW&#xff09; 第二十八章&#xff1a;计算机网络1、局域网 Local Area Networks - LAN2、媒体访问控制地址 Media Access Control address - MAC3、载波侦听多路访问 Carrier Sense Multiple Access - CSMA4、指数…

海凌科HLK-V2语音识别模块更新词条

简介 HLK-V20 是海凌科的离线语音识别模块, 中英文不同时支持, 只支持中文/英文, 具体识别看每次的SDK更新设置;资料下载 可以在微信公众包搜索海凌科或HI-LINK, 下载资料 感知模块->HLK-V20 模块限制 中英文被限制, 需要根据你在官网设置的SDK信息进行确定;可以仅设置3…

Vue: 事件修饰符, 键盘事件, 鼠标事件,计算属性

目录 事件修饰符 阻止默认事件 阻止冒泡 允许触发一次 捕获模式 self passive 键盘事件 keyup & keydown 按键别名 注意tab 注意系统按键 自定义按键 鼠标事件 简介 鼠标焦点事件 计算属性 差值语法实现 methods实现 computed实现 get() set() 总…

听GPT 讲Rust源代码--src/tools(38)

File: rust/src/tools/clippy/clippy_dev/src/lib.rs rust/src/tools/clippy/clippy_dev/src/lib.rs文件是Clippy开发工具的入口文件&#xff0c;其作用是提供Clippy开发过程中所需的功能和工具。Clippy是一个Rust代码的静态分析工具&#xff0c;用于提供各种有用的代码规范、编…

Linux网络编程学习心得.5

1.libevent编写tcp服务器流程 创建套接字 绑定 监听 创建event_base根节点 初始化上树节点 lfd 上树 循环监听 收尾 普通的event事件 文件描述符 事件(底层缓冲区的读事件或者写事件) 触发 回调 高级的event事件 bufferevent事件 核心: 一个文件描述符 两…

攻防技术-单包攻击防范:扫描、畸形、特殊(HCIP)

单包攻击类型介绍 一、扫描窥探攻击 1、地址扫描攻击防范 攻击介绍 运用ping程序探测目标地址&#xff0c;确定目标系统是否存活。也可使用TCP/UDP报文对目标系统发起探测&#xff08;如TCP ping&#xff09;。 防御方法 检测进入防火墙的ICMP、TCP和UDP报文&#xff0c;根…

性能优化-如何提高cache命中率

本文主要介绍性能优化领域常见的cache的命中率问题&#xff0c;旨在全面的介绍提高cache命中率的方法&#xff0c;以供大家编写出性能友好的代码&#xff0c;并且可以应对性能优化领域的面试问题。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &am…

PHP序列化总结1--序列化和反序列化的基础知识

序列化和反序列化的作用 1.序列化&#xff1a;将对象转化成数组或者字符串的形式 2.反序列化&#xff1a;将数组或字符串的形式转化为对象 为什么要进行序列化 这种数据形式中间会有很多空格&#xff0c;不同人有不同的书写情况&#xff0c;可能还会出现换行的情况 为此为了…

【C++】STL 容器 - set 集合容器 ⑦ ( 查找元素 - set#find 函数 | 获取元素个数 - set#count 函数 )

文章目录 一、查找元素 - set#find 函数1、函数原型 简介2、代码示例 - set#find 函数 二、获取元素个数 - set#count 函数1、函数原型 简介2、代码示例 - set#find 函数 一、查找元素 - set#find 函数 1、函数原型 简介 在 C 语言的 STL 标准模板库 , std::set 集合容器 是一个…

软件测试/测试开发丨Python 内置库 OS 学习笔记分享

os 概述 os: Operating System os 使用 导入 os 模块 查看 os 模块使用文档 help(os)dir(os) import os# 查看os模块说明文档 help(os)# 查看os模块的属性和方法 print(dir(os))os 操作系统相关 os.name&#xff1a;获取系统名称os.environ&#xff1a;获取系统环境变量信…

西北工业大学计算机组成原理实验报告——verilog后两次

在单周期CPU的基础上开发实现流水线CPU 说明&#xff1a; 1. 该PDF带有大纲功能&#xff0c;点击大纲中的对应标题&#xff0c;可以快速跳转。 2. 目录层级为&#xff1a; 一、一级标题 &#xff08;二&#xff09;二级标题 &#xff08;3&#xff09;三级标题 4.四级标…

Stable Diffusion Webui在Linux服务器第一次运行不能连接huggingface

第一次运行stable-diffusion-webui出现了如下错误 (MaxRetryError("HTTPSConnectionPool(hosthuggingface.co, port443): Max retries exceeded with url: /openai/clip-vit-large-patch14/resolve/main/vocab.json (Caused by ConnectTimeoutError(<urllib3.connecti…

亚信安慧AntDB数据库两项目分别入选2023“星河”标杆、优秀案例

近日&#xff0c;由中国信息通信研究院、中国通信标准化协会大数据技术标准推进委员会&#xff08;CCSA TC601&#xff09;共同组织的第七届大数据“星河&#xff08;Galaxy&#xff09;”案例评选结果公示&#xff0c;亚信安慧AntDB数据库两项目入选&#xff0c;其中“基于Ant…

C单片机数据类型与格式化

C语言数据类型 关键字位数表示范围stdint关键字ST关键字举例unsigned char80 ~ 255uint8_tu8u8 data 128char8-128 ~ 127int8_ts8s8 temperature 25unsigned short160 ~ 65535uint16_tu16u16 counter 5000short16-32768 ~ 32767int16_ts16s16 position 32767unsigned int3…

基于C#串口通信的智能仪表充电管理系统

基于C#串口通信的智能仪表充电管理系统 谁要源码的话加入群聊收费50元。提供代码&#xff0c;加QQ66987475。 一、 系统描述 该系统管理矿用检测仪器的充电、领取、归还、考勤等基本功能&#xff0c;一套系统拓补图如下&#xff1a; 由上位机、打印机、大屏幕、人脸识别仪…

腾讯云轻量应用服务器是什么?详细介绍

腾讯云轻量应用服务器开箱即用、运维简单的轻量级云服务器&#xff0c;CPU内存带宽配置高并且价格特别便宜&#xff0c;大带宽&#xff0c;但是限制月流量。轻量2核2G3M带宽62元一年、2核2G4M优惠价118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;756元3年、…