详解osgb的顶点,纹理,索引,UV读取与存储

virtual void apply(osg::Geode& node) {for (int i = 0; i < node.getNumDrawables(); i++){osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(node.getDrawable(i));if (geometry){//apply(*g);//***********************************************//解析顶点osg::Array* vertexArray = geometry->getVertexArray();if (vertexArray == NULL)return;//顶点数组osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(vertexArray);long lVertNum = verts->size();std::vector<osg::Vec3 >::iterator iter_ver = verts->begin();//遍历顶点值for (; iter_ver != verts->end(); iter_ver++){double x = iter_ver->x();double y = iter_ver->y();double z = iter_ver->z();  }//纹理osg::Texture2D* tex2D = dynamic_cast<osg::Texture2D*>(geometry->getStateSet()->getTextureAttribute(0, osg::StateAttribute::TEXTURE));osg::Image* image = tex2D->getImage();osgDB::writeImageFile(*image, "abc.jpg");int width = image->s();int height = image->t();/*osg::Vec2 color;osg::Vec4 c = image->getColor(color);*///UVosg::Array* uvArry = geometry->getTexCoordArray(0);osg::Vec2Array* vertsUV = dynamic_cast<osg::Vec2Array*>(uvArry);std::vector<osg::Vec2 >::iterator iter_verUV = vertsUV->begin();std::vector<int> greenPointIndices;int i = 0;for (; iter_verUV != vertsUV->end(); iter_verUV++){double u = iter_verUV->x();double v = iter_verUV->y();osg::Vec2 color(u, v);osg::Vec4 c = image->getColor(color);float r = c.r() * 255;float g = c.g() * 255;float b = c.b() * 255;if (r < 100 && g < 100 && b < 100 )greenPointIndices.push_back(i);i++;}//索引int numP = geometry->getNumPrimitiveSets();osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLES);for (unsigned int ipr = 0; ipr < numP; ipr++){osg::PrimitiveSet* prset = geometry->getPrimitiveSet(ipr);unsigned int ncnt = prset->getNumIndices();for (unsigned int ic = 0; ic * 3 < prset->getNumIndices(); ic++){unsigned int iIndex0 = prset->index(ic * 3);unsigned int iIndex1 = prset->index(ic * 3 + 1);unsigned int iIndex2 = prset->index(ic * 3 + 2);bool find = false;for (int i = 0; i < greenPointIndices.size(); i++){if (greenPointIndices[i] == iIndex0 || greenPointIndices[i] == iIndex1 || greenPointIndices[i] == iIndex2){find = true;break;}}if (find)continue;else{drawElemUInt->push_back(prset->index(ic * 3));drawElemUInt->push_back(prset->index(ic * 3 + 1));drawElemUInt->push_back(prset->index(ic * 3 + 2));}}}osg::ref_ptr<osg::Geometry> geometry_new = new osg::Geometry();geometry_new->setVertexArray(verts);geometry_new->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex2D, osg::StateAttribute::ON);geometry_new->setTexCoordArray(0, uvArry);geometry_new->addPrimitiveSet(drawElemUInt);osg::Geode* pGeode_new = new osg::Geode;pGeode_new->removeDrawables(0, pGeode_new->getNumDrawables());pGeode_new->addDrawable(geometry_new);osgDB::writeNodeFile(*pGeode_new, "test.osgb", new osgDB::Options("WriteImageHint=IncludeData Compressor=zlib"));//***********************************************}}}

参考博主:osgb的顶点,纹理,索引,UV读取与存储_osgb获取顶点-CSDN博客

作为C++小白看这段代码的详细解读

这段代码是用 C++ 编写的,并使用了 OpenSceneGraph (OSG) —— 一个开源的高性能 3D 图形引擎,广泛用于地理信息系统、仿真、可视化等领域。

这段代码定义了一个虚函数 apply(osg::Geode& node),该函数的作用是:遍历一个三维模型,识别纹理上颜色较暗的区域,剔除那些区域对应的三角形网格,然后将剩余的“亮色”区域导出为一个新的 3D 模型文件

一、逐行详细解析

开始遍历Geode下的Drawable对象(通常是Geometry)

for (int i = 0; i < node.getNumDrawables(); i++)

遍历Geode中所有的Drawable(通常是osg::Geometry类型)

处理每个Geometry

osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(node.getDrawable(i));

尝试将 Drawable 转为 osg::Geometry 类型,如果转换成功,表示该对象是几何体。

解析顶点信息

osg::Array* vertexArray = geometry->getVertexArray();
osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(vertexArray);

获取顶点数组并强制转换为三维坐标数组(Vec3Array)

vert存储所有顶点坐标

for (; iter_ver != verts->end(); iter_ver++)
{double x = iter_ver->x();double y = iter_ver->y();double z = iter_ver->z();  
}

遍历每个顶点,获取其三维坐标(这里没做实际操作)

提取纹理图像

osg::Texture2D* tex2D = dynamic_cast<osg::Texture2D*>(geometry->getStateSet()->getTextureAttribute(0, ...));
osg::Image* image = tex2D->getImage();
osgDB::writeImageFile(*image, "abc.jpg");

获取贴在模型上的纹理(Texture2D)

提取出其中的图像(osg::Image)

保存图像为JPG文件(调试用途)

读取UV坐标+获取纹理颜色

osg::Array* uvArry = geometry->getTexCoordArray(0);
osg::Vec2Array* vertsUV = dynamic_cast<osg::Vec2Array*>(uvArry);

获取纹理坐标(UV)数组

for (; iter_verUV != vertsUV->end(); iter_verUV++)
{double u = iter_verUV->x();double v = iter_verUV->y();osg::Vec2 color(u, v);osg::Vec4 c = image->getColor(color);...
}

遍历每个顶点对应的纹理坐标(u,v)

从image图像中获取对应像素颜色c

判断颜色是否“偏暗”,若R、G、B分量都小于100(即为暗色或黑色点)

if (r < 100 && g < 100 && b < 100)greenPointIndices.push_back(i);

这些“暗黑点”会被记录到greenPointIndices中

处理索引,剔除包含暗黑点的三角面

osg::DrawElementsUInt* drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLES);

新建一个DrawElementsUInt类型的三角形集合,保存有效三角面索引。

for (ipr ...)
{for (ic ...){unsigned int iIndex0 = prset->index(ic * 3);...if (任意一个顶点是暗色点)continue;elsedrawElemUInt->push_back(三个顶点索引);}
}

遍历所有原始三角形

若三角形中有任意一个顶点在greenPointIndices中(即暗点),跳过不加入新网格。

其他三角面则加入drawElemUInt

构建新Geometry并导出为OSGB文件

osg::Geometry* geometry_new = new osg::Geometry();
geometry_new->setVertexArray(verts);
...
geometry_new->addPrimitiveSet(drawElemUInt);

构建一个新几何体,复用原始顶点和纹理坐标,仅替换三角面为“亮色区域”

osg::Geode* pGeode_new = new osg::Geode;
pGeode_new->addDrawable(geometry_new);
osgDB::writeNodeFile(*pGeode_new, "test.osgb", ...);

将新的几何体写入.osgb文件(OpenSceneGraph二进制模式格式)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS闯关指南:从手写地狱到“类”积木之旅|得物技术

一、背景 在Web开发网页设计中&#xff0c;CSS&#xff08;层叠样式表&#xff09;扮演着至关重要的角色&#xff0c;它用于控制网页的布局、外观和视觉效果。CSS不仅可以美化网页的视觉表现&#xff0c;还可以提高网页的可访问性、可维护性和响应式设计。在我们进行网页开发的…

【大模型应用开发】Qwen2.5-VL-3B识别视频

0. 编写代码并尝试运行 克隆以下代码 git clone https://gitee.com/ai-trailblazer/qwen-vl-hello.git 尝试运行qwen-vl-hello.py&#xff0c;报错原因缺少modelscope&#xff1a; 1. 安装qwen-vl-utils工具包 pip install qwen-vl-utils[decord]0.0.8 尝试运行&#xff0c;…

MySQL 窗口函数深度解析:语法、应用场景与性能优化

一、窗口函数核心概念 ​​本质​​&#xff1a;对一组与当前行相关联的行执行计算&#xff0c;​​不改变原表行数​​ ​​与聚合函数的区别​​&#xff1a; SELECT department, AVG(salary) -- 普通聚合&#xff1a;每个部门一行 FROM employees GROUP BY department;SE…

新版Chrome浏览器加载eDrawings 3D Viewer控件网页查看DWG、DXF

eDrawings是一款由达索系统&#xff08;DASSAULT SYSTMES&#xff09;开发的免费跨平台CAD看图工具&#xff0c;专注于3D模型和2D工程图的查看、协作与共享。其核心功能包括多格式支持、动态模型展示、跨平台适配及轻量化操作体验&#xff0c;适用于工程设计、教育培训等领域。…

阿姆斯特朗数

阿姆斯特朗数也就是俗称的水仙花数&#xff0c;是指一个n位数&#xff0c;其各位数字的n次方之和等于该数本身。例如&#xff0c;153是一个水仙花数&#xff0c;因为153&#xff1d;13&#xff0b;53&#xff0b;33。请问100-10000所有水仙花数有哪些。 采用穷举法对范围之间的…

vmvare 虚拟机内存不足

centos 扩展物理卷df -hT / sudo du -hx --max-depth1 / | sort -rh | head -n 20 // 查看前20个的大文件 # 清理旧日志&#xff08;保留最近7天&#xff09; sudo find /var/log -type f -mtime 7 -delete sudo journalctl --vacuum-time7d # 清理yum缓存 sudo yum clean …

C++?继承!!!

一、引言 代码的复用对于代码的质量以及程序员的代码设计上都是非常重要的&#xff0c;C中的许多特性都体现了这一点&#xff0c;从函数复用、模板的引入到今天我们将一起学习的&#xff1a;继承 二、什么是继承&#xff1f; 1、继承的概念 继承(inheritance)机制是面向对象程…

Android设置界面层级为最上层实现

Android设置界面层级为最上层实现 文章目录 Android设置界面层级为最上层实现一、前言二、Android设置界面层级为最上层实现1、主要代码2、后遗症 三、其他1、Android设置界面层级为最上层小结2、悬浮框的主要代码悬浮框 注意事项&#xff08;1&#xff09;权限限制&#xff08…

Linux 了解篇

一、GNU 项目与 GPL 许可 &#xff08;一&#xff09;GNU 项目 GNU &#xff1a;GNU 是一个递归缩写&#xff0c;代表 "GNUs Not Unix"。GNU 项目旨在开发一个完全自由的操作系统&#xff0c;该操作系统基于 Unix 的设计理念但不包含 Unix 的代码。GNU 项目提供了大…

word 如何让公式居中,公式编号右对齐

问题&#xff1a; 如何让输入的公式居中&#xff0c;公式编号右对齐&#xff1f; 解决方法&#xff1a; 方法一&#xff1a;使用制表符 1、输入内容&#xff1a;先按一次“Tab”键&#xff08;制表符&#xff09;&#xff0c;然后键入公式&#xff0c;然后再按一次“Tab”键…

华为OD机试真题——最小循环子数组 (2025B卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 B卷 100分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…

OpenCv高阶(十七)——dlib库安装、dlib人脸检测

文章目录 前言一、dlib库简介二、dlib库安装1、本地安装&#xff08;离线&#xff09;2、线上安装 三、dlib人脸检测原理1、HOG 特征提取2、 SVM 分类器训练3、 滑动窗口搜索4、非极大值抑制&#xff08;NMS&#xff09; 四、dlib人脸检测代码1、导入OpenCV计算机视觉库和dlib机…

AD-PCB--AD20软件安装及中英文切换 DAY 2

1.软件安装 1.1 软件包下载 给你一个捷径&#xff1a; 1.2 安装过程&#xff08;安装过的人跳过就好&#xff0c;一般很多都支持懒人安装&#xff09; 双击其中的exe文件 点击下一步 选择中文 接受用户协议 下面这个弹窗有的没有。 建议勾选导入导出 安装目录&#xff0c…

单向循环链表与双向链表

单向循环链表的原理与应用 思考&#xff1a;对于单向链表而言&#xff0c;想要遍历链表&#xff0c;则必须从链表的首结点开始进行遍历&#xff0c;请问有没有更简单的方案实现链表中的数据的增删改查&#xff1f; 回答&#xff1a;是有的&#xff0c;可以使用单向循环的链表进…

Windows鼠标掉帧测试与修复

前言 这两天突然发现鼠标似乎有掉帧&#xff0c;但是掉的又不太明显&#xff0c;用着感觉似乎快速移动的时候会有一瞬间卡一下&#xff0c;但是眼睛又看不清楚&#xff0c;不太确定是不是自己的心理作用&#xff0c;非常难受。 如何判断鼠标是否掉帧 根据我的经验&#xff0…

U 盘数据恢复全攻略

目录 &#x1f4be; U盘数据误删怎么办&#xff1f;两款实用工具助你找回丢失文件&#xff01;1️⃣ Recover My Files&#xff1a;数据恢复的得力助手&#x1f4cc; 主要特点&#x1f6e0; 使用步骤详解1. 下载与安装2. 启动软件并选择恢复类型3. 选择U盘所在分区4. 选择文件恢…

HarmonyOS NEXT~鸿蒙系统运维:全面解析与最佳实践

HarmonyOS NEXT&#xff5e;鸿蒙系统运维&#xff1a;全面解析与最佳实践 摘要 本文深入探讨鸿蒙(HarmonyOS)系统的运维管理&#xff0c;从架构特点到日常维护操作&#xff0c;全面分析这一全场景分布式操作系统的运维要点。文章将介绍鸿蒙系统特有的分布式能力运维管理、性能…

基于 STM32 的智慧农业温室控制系统设计与实现

摘要 本文提出一种基于 STM32 微控制器的智慧农业温室控制系统设计方案,通过集成多类型环境传感器、执行机构及无线通信模块,实现对温室内温湿度、光照、土壤湿度等参数的实时监测与自动调控。文中详细阐述硬件选型、电路连接及软件实现流程,并附关键代码示例,为智慧农业领…

Appium+python自动化(五)- 模拟器

简介 Appium是做安卓自动化的一个比较流行的工具&#xff0c;对于想要学习该工具但是又局限于没 android 手机来说&#xff0c;可以通过安卓模拟器来解决该问题&#xff0c;下面就讲解使用appium连接安卓模拟器的操作步骤。而是由于手机数据线问题&#xff0c;也只好先用模拟器…

汽车充电桩专用ASCP210系列电气防火限流式保护器

1.概述汽车充电桩专用电气防火限流式保护器 电气防火限流式保护器可有效克服传统断路器、空气开关和监控设备存在的短路电流大、切断短路电流时间长、短路时产生的电弧火花大&#xff0c;以及使用寿命短等弊端&#xff0c;发生短路故障时&#xff0c;能以微秒级速度快速限制短…