使用OpenSceneGraph生成3D数据格式文件

OpenSceneGraph (OSG) 提供了多种方式来生成和导出3D数据格式文件。以下是详细的生成方法和示例代码:

一、基本文件生成方法

1. 使用osgDB::writeNodeFile函数

这是最直接的生成方式,支持多种格式:

#include <osgDB/WriteFile>osg::ref_ptr<osg::Node> scene = createScene(); // 创建你的场景图// 导出为不同格式
bool success;
success = osgDB::writeNodeFile(*scene, "output.osgt");  // OSG文本格式
success = osgDB::writeNodeFile(*scene, "output.osgb");  // OSG二进制格式
success = osgDB::writeNodeFile(*scene, "output.obj");   // Wavefront OBJ
success = osgDB::writeNodeFile(*scene, "output.dae");   // COLLADA
success = osgDB::writeNodeFile(*scene, "output.fbx");   // FBX(需插件支持)

2. 支持的导出格式

格式类型文件扩展名说明
OSG原生.osgt, .osgb, .osgx文本/二进制/XML格式
通用3D.obj, .stl, .ply静态网格格式
场景格式.dae, .fbx, .3ds支持完整场景
地形数据.ive, .lwo, .txp优化格式

二、编程生成场景并导出

1. 创建简单几何体并导出

#include <osg/Geode>
#include <osg/Geometry>
#include <osgDB/WriteFile>osg::Geode* createCube() {osg::ref_ptr<osg::Geode> geode = new osg::Geode;osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;// 定义8个顶点(立方体)osg::Vec3Array* vertices = new osg::Vec3Array;vertices->push_back(osg::Vec3(-1.0f, -1.0f,  1.0f)); // 前左下vertices->push_back(osg::Vec3( 1.0f, -1.0f,  1.0f)); // 前右下vertices->push_back(osg::Vec3( 1.0f,  1.0f,  1.0f)); // 前右上vertices->push_back(osg::Vec3(-1.0f,  1.0f,  1.0f)); // 前左上vertices->push_back(osg::Vec3(-1.0f, -1.0f, -1.0f)); // 后左下vertices->push_back(osg::Vec3( 1.0f, -1.0f, -1.0f)); // 后右下vertices->push_back(osg::Vec3( 1.0f,  1.0f, -1.0f)); // 后右上vertices->push_back(osg::Vec3(-1.0f,  1.0f, -1.0f)); // 后左上geometry->setVertexArray(vertices);// 定义法线osg::Vec3Array* normals = new osg::Vec3Array;normals->push_back(osg::Vec3( 0.0f,  0.0f,  1.0f)); // 前normals->push_back(osg::Vec3( 0.0f,  0.0f, -1.0f)); // 后normals->push_back(osg::Vec3( 1.0f,  0.0f,  0.0f)); // 右normals->push_back(osg::Vec3(-1.0f,  0.0f,  0.0f)); // 左normals->push_back(osg::Vec3( 0.0f,  1.0f,  0.0f)); // 上normals->push_back(osg::Vec3( 0.0f, -1.0f,  0.0f)); // 下geometry->setNormalArray(normals, osg::Array::BIND_PER_PRIMITIVE);// 定义6个面(12个三角形)osg::DrawElementsUInt* faces = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);// 前面faces->push_back(0); faces->push_back(1); faces->push_back(2);faces->push_back(2); faces->push_back(3); faces->push_back(0);// 后面faces->push_back(5); faces->push_back(4); faces->push_back(7);faces->push_back(7); faces->push_back(6); faces->push_back(5);// 右面faces->push_back(1); faces->push_back(5); faces->push_back(6);faces->push_back(6); faces->push_back(2); faces->push_back(1);// 左面faces->push_back(4); faces->push_back(0); faces->push_back(3);faces->push_back(3); faces->push_back(7); faces->push_back(4);// 上面faces->push_back(3); faces->push_back(2); faces->push_back(6);faces->push_back(6); faces->push_back(7); faces->push_back(3);// 下面faces->push_back(4); faces->push_back(5); faces->push_back(1);faces->push_back(1); faces->push_back(0); faces->push_back(4);geometry->addPrimitiveSet(faces);geode->addDrawable(geometry);return geode.release();
}int main() {osg::ref_ptr<osg::Node> scene = createCube();osgDB::writeNodeFile(*scene, "box.osgb");return 0;
}

 2. 生成带纹理的模型

osg::Node* createTexturedQuad() {osg::ref_ptr<osg::Geode> geode = new osg::Geode;osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;// 顶点osg::Vec3Array* vertices = new osg::Vec3Array;vertices->push_back(osg::Vec3(-1,0,-1));vertices->push_back(osg::Vec3(1,0,-1));vertices->push_back(osg::Vec3(1,0,1));vertices->push_back(osg::Vec3(-1,0,1));geom->setVertexArray(vertices);// 纹理坐标osg::Vec2Array* texcoords = new osg::Vec2Array;texcoords->push_back(osg::Vec2(0,0));texcoords->push_back(osg::Vec2(1,0));texcoords->push_back(osg::Vec2(1,1));texcoords->push_back(osg::Vec2(0,1));geom->setTexCoordArray(0, texcoords);// 加载纹理osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;texture->setImage(osgDB::readImageFile("texture.jpg"));// 创建状态集osg::ref_ptr<osg::StateSet> stateset = geom->getOrCreateStateSet();stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));geode->addDrawable(geom);return geode.release();
}

三、高级导出选项

1. 使用osg::Options控制导出

osg::ref_ptr<osgDB::Options> options = new osgDB::Options;
options->setOptionString("WriteImageHint=IncludeFile");  // 包含纹理引用osgDB::writeNodeFile(*scene, "textured_model.osgt", options.get());

2. 常用导出选项

选项字符串功能描述
"WriteImageHint=IncludeFile"包含纹理文件引用
"Compressor=zlib"使用压缩格式
"Precision=15"设置浮点精度
"OutputTextureFiles"导出纹理文件

3. 批量导出多个LOD级别

void exportLODs(osg::Node* model, const std::string& basename) {osg::ref_ptr<osg::LOD> lod = new osg::LOD;// 创建不同细节级别的模型osg::Node* highRes = createSimplifiedModel(model, 1.0f);osg::Node* medRes = createSimplifiedModel(model, 0.5f);osg::Node* lowRes = createSimplifiedModel(model, 0.2f);lod->addChild(highRes, 0, 50);lod->addChild(medRes, 50, 200);lod->addChild(lowRes, 200, FLT_MAX);osgDB::writeNodeFile(*lod, basename + "_lod.osgb");
}// 辅助函数:创建简化模型
osg::Node* createSimplifiedModel(osg::Node* original, float ratio) {osgUtil::Simplifier simplifier(ratio);osg::ref_ptr<osg::Node> copy = dynamic_cast<osg::Node*>(original->clone(osg::CopyOp::DEEP_COPY_ALL));copy->accept(simplifier);return copy.release();
}

四、处理导出问题

1. 检查插件支持

// 列出所有支持的写入格式
osgDB::Registry::instance()->getWriterExtensions();// 检查特定格式是否支持
if (osgDB::Registry::instance()->getReaderWriterForExtension("fbx")) {// FBX导出可用
}

2. 错误处理

bool result = osgDB::writeNodeFile(*node, "output.fbx");
if (!result) {OSG_WARN << "Failed to export FBX file. Make sure FBX plugin is installed." << std::endl;// 尝试回退格式osgDB::writeNodeFile(*node, "output.obj");
}

五、实际应用示例

1. 生成地形并导出

osg::Node* createTerrain() {osg::ref_ptr<osg::HeightField> hf = new osg::HeightField;hf->allocate(64, 64); // 64x64网格// 填充高度数据for (unsigned int r=0; r<hf->getNumRows(); ++r) {for (unsigned int c=0; c<hf->getNumColumns(); ++c) {float height = sin(c/10.0f) * cos(r/10.0f) * 10.0f;hf->setHeight(c, r, height);}}osg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(new osg::ShapeDrawable(hf.get()));return geode.release();
}// 导出为OpenFlight格式
osgDB::writeNodeFile(*createTerrain(), "terrain.flt");

2. 动画模型导出

osg::AnimationPath* createAnimationPath() {osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;path->setLoopMode(osg::AnimationPath::LOOP);float time = 0.0f;float delta = 1.0f/30.0f; // 30fpsfor (unsigned int i=0; i<60; ++i) {osg::Vec3 pos(sin(time), cos(time), 0.0f);path->insert(time, osg::AnimationPath::ControlPoint(pos));time += delta;}return path.release();
}osg::Node* createAnimatedModel() {osg::ref_ptr<osg::MatrixTransform> animNode = new osg::MatrixTransform;animNode->setUpdateCallback(new osg::AnimationPathCallback(createAnimationPath()));// 添加你的模型animNode->addChild(createSimpleBox());return animNode.release();
}// 导出动画模型
osgDB::writeNodeFile(*createAnimatedModel(), "animated.dae");

 

 

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

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

相关文章

JMeter接口性能测试从入门到精通

前言&#xff1a; 本文主要介绍了如何利用jmter进行接口的性能测试 1.在测试计划中添加线程组 1.1.线程组界面中元素含义 如果点击循环次数为永远&#xff1a; 2.添加HTTP取样器 2.1.填写登录接口的各个参数 2.2.在线程组下面增加查看结果树 请求成功的情况&#xff1a; 请求…

C++抽卡模拟器

近日在学校无聊&#xff0c;写了个抽卡模拟器供大家娱乐。 代码实现以下功能&#xff1a;抽卡界面&#xff0c;抽卡判定、动画播放、存档。 1.抽卡界面及判定 技术有限&#xff0c;不可能做的和原神一样精致。代码如下&#xff08;注&#xff1a;这不是完整代码&#xff0c;…

详解相机的内参和外参,以及内外参的标定方法

1 四个坐标系 要想深入搞清楚相机的内参和外参含义&#xff0c; 首先得清楚以下4个坐标系的定义&#xff1a; 世界坐标系&#xff1a; 名字看着很唬人&#xff0c; 其实没什么大不了的&#xff0c; 这个就是你自己定义的某一个坐标系。 比如&#xff0c; 你把房间的某一个点定…

学透Spring Boot — 011. 一篇文章学会Spring Test

系列文章目录 这是学透Spring Boot的第11篇文章。更多系列文章请关注 CSDN postnull 用户的专栏 文章目录 系列文章目录Spring Test的依赖Spring Test的核心功能SpringBootTest 加载Spring上下文依赖注入有问题时Spring配置有问题时 WebMvcTest 测试Web层&#xff08;Controll…

Mysql 数据库编程技术01

一、数据库基础 1.1 认识数据库 为什么学习数据库 瞬时数据&#xff1a;比如内存中的数据&#xff0c;是不能永久保存的。持久化数据&#xff1a;比如持久化至数据库中或者文档中&#xff0c;能够长久保存。 数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长…

新一代AI架构实践:数字大脑AI+智能调度MCP+领域执行APP的黄金金字塔体系

新一代AI架构实践&#xff1a;数字大脑智能调度领域执行的黄金金字塔体系 一、架构本质的三层穿透性认知 1.1 核心范式转变&#xff08;CPS理论升级&#xff09; 传统算法架构&#xff1a;数据驱动 → 特征工程 → 模型训练 → 业务应用 新一代AI架构&#xff1a;物理规律建…

macOS可视化桌面配置docker加速器

macOS可视化桌面配置docker加速器 在镜像settings->docker Engine改为国内镜像修改为国内镜像重启docker(可视化界面启动或者使用命令行)使用命令重启可视化界面重启 在镜像settings->docker Engine改为国内镜像 修改为国内镜像 {"registry-mirrors": ["…

Nginx 基础使用(2025)

一、Nginx目录结构 [rootlocalhost ~]# tree /usr/local/nginx /usr/local/nginx ├── client_body_temp # POST 大文件暂存目录 ├── conf # Nginx所有配置文件的目录 │ ├── fastcgi.conf # fastcgi相…

用spring-webmvc包实现AI(Deepseek)事件流(SSE)推送

前后端&#xff1a; Spring Boot Angular spring-webmvc-5.2.2包 代码片段如下&#xff1a; 控制层&#xff1a; GetMapping(value "/realtime/page/ai/sse", produces MediaType.TEXT_EVENT_STREAM_VALUE)ApiOperation(value "获取告警记录进行AI分析…

基于Python的招聘推荐数据可视化分析系统

【Python】基于Python的招聘推荐数据可视化分析系统&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 &#x1f680;&#x1f31f; 基于Python的招聘推荐数据可视化分析系统&#xff01;&#x1…

使用注解开发springMVC

引言 在学习过第一个springMVC项目建造过后&#xff0c;让我们直接进入真实开发中所必需的注解开发&#xff0c; 是何等的简洁高效&#xff01;&#xff01; 注&#xff1a;由于Maven可能存在资源过滤的问题&#xff0c;在maven依赖中加入 <build><resources>&l…

linux专题3-----禁止SSH的密码登录

要在linux系统中禁止密码登录&#xff0c;您可以通过修改 SSH 配置来实现。请按照以下步骤操作(此处以 Ubuntu为例)&#xff1a; 1、SSH 登录到您的服务器&#xff08;或直接在命令行模式下&#xff09;。 2、备份 SSH 配置文件&#xff1a; 在终端中运行以下命令以备份现有的…

基于LangChain和通义(Tongyi)实现NL2SQL的智能检索(无需训练)

在数据驱动的时代,如何高效地从数据库中获取信息成为了一个重要的挑战。自然语言到SQL(NL2SQL)技术提供了一种便捷的解决方案,使用户能够用自然语言查询数据库,而无需深入了解SQL语法。本文将探讨如何利用LangChain和通义(Tongyi)实现NL2SQL的智能检索,具体步骤如下: …

深度学习处理文本(10)

保存自定义层 在编写自定义层时&#xff0c;一定要实现get_config()方法&#xff1a;这样我们可以利用config字典将该层重新实例化&#xff0c;这对保存和加载模型很有用。该方法返回一个Python字典&#xff0c;其中包含用于创建该层的构造函数的参数值。所有Keras层都可以被序…

机器视觉3D中激光偏镜的优点

机器视觉的3D应用中,激光偏镜(如偏振片、波片、偏振分束器等)通过其独特的偏振控制能力,显著提升了系统的测量精度、抗干扰能力和适应性。以下是其核心优点: 1. 提升3D成像精度 抑制环境光干扰:偏振片可滤除非偏振的环境杂光(如日光、室内照明),仅保留激光偏振信号,大…

线程同步的学习与应用

1.多线程并发 1).多线程并发引例 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <assert.h> #include <pthread.h>int wg0; void *fun(void *arg) {for(int i0;i<1000;i){wg;printf("wg%d\n",wg);} } i…

写.NET可以指定运行SUB MAIN吗?调用任意一个里面的类时,如何先执行某段初始化代码?

VB.NET 写.NET可以指定运行SUB MAIN吗?调用任意一个里面的类时,如何先执行某段初始化代码? 分享 1. 在 VB.NET 中指定运行 Sub Main 在 VB.NET 里&#xff0c;你能够指定 Sub Main 作为程序的入口点。下面为你介绍两种实现方式&#xff1a; 方式一&#xff1a;在项目属性…

【AI插件开发】Notepad++ AI插件开发实践(代码篇):从Dock窗口集成到功能菜单实现

一、引言 上篇文章已经在Notepad的插件开发中集成了选中即问AI的功能&#xff0c;这一篇文章将在此基础上进一步集成&#xff0c;支持AI对话窗口以及常见的代码功能菜单&#xff1a; 显示AI的Dock窗口&#xff0c;可以用自然语言向 AI 提问或要求执行任务选中代码后使用&…

关联容器-模板类pair数对

关联容器 关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。 关联容器支持高效的关键字查找和访问。 两个主要的关联容器(associative-container),set和map。 set 中每个元素只包…

京东运维面试题及参考答案

目录 OSPF 实现原理是什么? 请描述 TCP 三次握手的过程。 LVS 的原理是什么? 阐述 Nginx 七层负载均衡的原理。 Nginx 与 Apache 有什么区别? 如何查看监听在 8080 端口的是哪个进程(可举例:netstat -tnlp | grep 8080)? OSI 七层模型是什么,请写出各层的协议。 …