OSG开发笔记(二十九):OSG加载模型文件、加载3DMax三维型文件Demo_osgearth加载3dtiles-程序员宅基地

技术标签: osg  Qt三维开发  osg加载3ds模型  Qt+OSG  Qt开发  osg三维开发2  


若该文为原创文章,未经允许不得转载
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/134064988
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…

OSG开发专栏(点击传送门)

上一篇:《OSG开发笔记(二十八):OSG模型固定路径动画
下一篇: 持续补充中…



前言

  Osg深入之后需要打开模型文件,这些模型文件是已有的模型文件,加载入osg之后可以在常见中展示模型文件,该节点可以操作,多个逼真的模型的节点就实现了基本的场景构建。


Demo

  请添加图片描述


说明

  三维模型文件一般是由专业的三维建模人员完成,可以去buy通用模型,但是定制模型的费用就相对不便宜了,几十几百几千几万的都有,三维项目一定要了解清楚前期建模,也有很多是由甲方自行提供,因为只有甲方才能知道模型效果是什么样。


Osg读取文件库:OsgDB库

  osg、osgEarth所有文件都是通过osgDB库来读取,通过Registry来查找文件拓展名对应的osg库,根据一定规则拼接成完成的osg库名并加载,通过ReaderWriter对象来完成节点的读取(ReaderWriter是读写节点的基类,可通过派生此类重写读写方法实现自己的读写格式)。
  在这里插入图片描述

  然后,查看我们的osg库名称:
  在这里插入图片描述

  发现支持的格式还真不少,然后我们进行大致归类:

三维格式

.3dc

  3DC文件是三维建模软件3DCrafter建的三维场景,用于存储和加载3D模型和场景。3DC文件包括场景的几何形状、形状、材质和灯光效果,用于创建3 图像和动画。

.3ds

  3DS(3D Studio)文件是一种用于 3D 图形模型的文件格式,它是 Autodesk 3ds Max 软件的主要文件格式之一。是一种常见的 3D 模型文件格式,用于存储和传输 3D 对象、材质、动画和变形等数据。可以被许多 3D 图形软件读取和编辑。它广泛应用于游戏开发、动画制作、虚拟现实等领域。

.bvh

  BVH文件包含角色的骨骼和肢体关节旋转数据。BVH 是一种通用的人体特征动画文件格式,,广泛地被当今流行的各种动画制作软件支持。通常可从记录人类行为运动的运动捕获硬件获得。

.Ive

  OpenSceneGraph 二进制三维文件。

.lwo

  由LightWave 3D创建的三维对象文件,该程序用于三维建模、动画和渲染;包含描述对象形状和外观的点、多边形和曲面;还可以包含对用于对象纹理的图像文件的引用。

.lws

  LightWave 3D Scene File 文件是最常用的文件类型,带有 LWS 文件扩展名,最初由 NewTek开发LightWave 3D。

.osc

  当前这种OSC格式是一种GIS地理信息文件,是由OpenStreetMap研发,作为一种 OpenStreetMap更改文件使用,此文件流行程度是 50 分(0-100满分)。

.osg(osgb)

  OSG场景数据格式,可以记录场景书结构的所有节点及其属性信息。它属于文本文件类型,不需要专门的编辑器。osgb是osg的二进制格式,osgb是倾斜摄影的格式,osg可以直接读取osgb文件。

.osga

  osgArchive 数据归档器 为众多 OSG 文件以及 IVE 文件打包提供了一个工具 它所生成的 OSGA 文件是整个文件,可以为海量数据的存放提供良好的支持

.md2

  MD2是Quake2中使用的模型文件格式,由于其比较简单,容易实现,所以应用很广,是一种经典的动画模型格式。该文件格式由2部分组成:一部分是文件头,包含了文件ID号、版本号和有关模型的各种数据的起始地址等;另一部分是文件的主体,包含了有关模型的各种数据,如顶点数据、纹理数据、法向量数据等。

.obj

  obj可以指一种3D模型格式的文件,也可以指一种程序编译中间代码文件。obj3D模型文件是一种文本文件,可以直接用写字板打开进行查看和编辑修改,里面不包含动画、材质特性、贴图路径、动力学、粒子等信息,但是可包含纹理信息,而对纹理进行轻量化压缩可以减小文件大小和提高加载性能。。obj目标文件一般是程序编译后的二进制文件,再通过链接器和资源文件链接就成可执行文件了。

.openflight(FLT)

  FLY (OpenFlight) 格式(通常使用 .flt 文件扩展名)是一种用于表示三维场景和模型的文件格式。OpenFlight 最初由Multigen-Paradigm公司开发,用于航空模拟和虚拟环境的创建。后来,这个格式被移交给了Presagis公司继续开发和维护。

.shp

  shp是“空间数据开放”格式的文件。shp全称“ESRI Shapefile”,是美国环境系统研究所公司开发的一种空间数据开放格式,是一种矢量图形格式,该格式文件主要用于描述几何体对象(点,折线与多边形),能够保存几何图形的位置及相关属性。

.stl

  3d打印一般用stl格式的3d文件,3d打印机识别STL格式的文件

dxf

  DXF(Drawing Exchange Format)是一种用于图形交换的文件格式,由AutoDesk公司开发。DXF文件可以包含2D或3D图形数据,可以被多个CAD程序所支持。

图像格式

.bmp

  BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。

.dds

  DDS是一种图片格式,是DirectDraw Surface的缩写,它是DirectX纹理压缩(DirectX Texture Compression,简称DXTC)的产物。由NVIDIA公司开发。大部分3D游戏引擎都可以使用DDS格式的图片用作贴图,也可以制作法线贴图。通过安装DDS插件后可以在

.jpeg

  JPEG格式是最常用的图像文件格式,后缀名为.jpg或.jpeg。

.tga

  tga是由美国Truevision公司为其显示卡开发的一种图像文件格式,

.pic

  pic是一种图像文件格式,以图像文件格式是记录和存储影像信息的格式。对数字图像进行存储、处理、传播,必须采用一定的图像格式,也就是把图像的像素按照一定的方式进行组织和存储,把图像数据存储成文件就得到图像文件。

.rgb

  .rgb文件是SGI图像文件格式的24位RGB彩色位图图像文件。

.png

  PNG,全称Portable Network Graphics,是一种无损压缩的图像文件格式,广泛应用于互联网上的图像文件。

.pnm

  PNM(Portable Any Map)格式是一系列用于便携式图像的图像文件格式,这些图像是像素值的映射,可以表示灰度或彩色数据。

其他

.dot

  DOT文件扩展名信息一种Microsoft Word文档模板。

.dw

  DW格式文件是Dreamweaver的特有文件,它通常包括HTML代码和网页相关的资源(如图像、Flash、JavaScript、CSS等)。

.ktx

  KTX(Khronos Texture)是一个轻量级的纹理容器,用于OpenGL、Vulkan和其他GPU API。KTX文件包含纹理加载所需的所有参数。

.lua

  lua是一个简洁、轻量、可扩展的脚本语言,该语言的设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

.mdl

  MDL文件是一个文件包,里面包含模型,贴图,所有动作,以及脚本。

.osgjs

  osgjs是osjjs框架支持的格式,其实是json格式的文本类型。 要把自己建的模型转换成这个格式,首先要将3ds格式转换为osg格式,然后再osg中转成json格式。

.p3d

  panda3D打包系统中的完整文件;用于打包应用程序以供分发;类似于.MF 文件,但专门用于保存Panda3D应用程序而不是其他项;保存运行应用程序所需的所有内容,包括:Python代码、模型、纹理和已编译的.DLL 文件。

.ply

  PLY是一种电脑档案格式,全名为多边形档案(Polygon File Format)或斯坦福三角形档案(Stanford Triangle Format)。

.pov

  POV 文件扩展是POV-Ray Raytracing Format为 Pov-Ray 软件程序开发的 The POV-Team文件类型。

.pvr

  PVR文件扩展名来自POWERVR Texture File。该文件的开发由Imagination Technologies完成。该文件属于二进制格式,是光栅相关文件。

.rot

  rot文件扩展是Homeworld 2 Graphics File 文件,最初由Sierra Entertainment 为 Homeworld 2开发。 Annoymous用户数据统计推断,ROT 文件在China和使用Windows 10 设备的用户中最受欢迎。 这些用户中的大多数正在运行Google Chrome web浏览器。

.tf

  该格式是一种类似DOC格式的文件格式。tf是通常所说的富文本格式,也叫作多文本格式,常用来存储文档、图片信息。在不同的操作系统下创建的tf格式文档可以在其它操作系统和应用软件之间互相查看、传输,十分的方便。

.txf

  TXF是一种字体文件格式,用于保存税务数据,如收入和支出标准的基于文本的格式。它可以用于勒斯蒂亚、宇宙模拟和可视化程序的字体文件,也可以用于语言翻译和本地化程序创建的翻译文件。

.txp

  TXP是编辑浏览格式,最简单的例子,把网络上的小说储存到移动设备上(比如手机、MP4等等),有些情况就要将原文转换成.TXP

.vtf

  VTF(Valve Textures File)Valve贴图文件,是由VALVE独创的图象格式,由TGA格式演变而来,其优点是能很好的体现和展示TGA所具有的通道效果。

.x

  这是DirectX一种专用格式.。


自定义文件插件

  自定义文件插件主要是自定义一个插件读写类,继承osgDB::ReaderWriter类,然后根据需求重写如readNode等函数方法即可。
  在建立插件读写类时注意:
  需要建立一个dll项目工程,输出的dll必须为osgdb_扩展名.dll或osgdb_扩展名d.dll的形式为了实现插件注册,需要定义全局变量,方法如下REGISTER_OSGPLUGIN(VR, ReaderWriterVR),在该全局变量的初始化过程中,会使用Registery::addReaderWriter函数自动注册插件所对应的扩展名。
  在应用程序使用中,需要注册插件,方法如下 osgDB::Registry::instance->addFileExtensionAlias(“VR”, “VR”)
  其实我们不是做引擎没必要做插件,还是直接转换三维模型文件格式好一些。


测试加载模型文件

  选择obj格式最合适,但是又不带纹理等贴图格式,还需要配上贴图格式。
  在这里插入图片描述

步骤一:加载obj

  加载了obj文件,没有纹理,打开obj,发现需要一个mtllib的xxx.mtl作为纹理文件,拿到的模型是没有的。
  在这里插入图片描述

  mtllib:此前缀后指定了此OBJ文件所使用的材质库文件(*.mtl)的文件路径

步骤二:加载3ds文件

  加载了3ds文件,确实显示出来了,效果还不错,测试了拽托缩放完美流畅效果不错,达到预期。
  在这里插入图片描述


关键代码

初始化场景代码

osg::ref_ptr<osg::Node> OsgWidget::getModel3DMaxFile()
{
    
    // 隐藏整个demo全局的按钮面板
    ui->groupBox_pannel->setVisible(false);
    ui->label_cursor->setVisible(false);
    ui->label_cursor_2->setVisible(false);
    ui->label_msg->setVisible(false);
    ui->label_state->setVisible(false);

    // 正式开始
    osg::ref_ptr<osg::Group> pGroup = new osg::Group;
    osg::ref_ptr<osg::Camera> pCamera = 0;
    osg::ref_ptr<osg::Geode> pGeode = 0;
    osg::ref_ptr<osg::Node> pNode = 0;

    // 添加模型
    {
    
//        osgDB::Options* a = new osgDB::Options(std::string("noTriStripPolygons"));
//        osg::ref_ptr<osg::Node> node1 = osgDB::readNodeFile("D:/qtProject/osgDemo/modelData/grass.obj", a);
//        osg::ref_ptr<osg::Node> node1 = osgDB::readNodeFile("D:/qtProject/osgDemo/modelData/grass.obj");
        pNode = osgDB::readNodeFile("D:/qtProject/osgDemo/modelData/grass.3ds");
    }
    // 创建背景相机(相机需要配合几何题图,可以理解为相机是最后得,相机中有一个全屏的图,这个图是个元素节点,这样图节点在相机中就成为了背景图)
    {
    
        // 步骤一:创建相机
        pCamera = new osg::Camera();
        // 步骤二:设置矩阵  显示得界面边坐标      左    右  下    上
        pCamera->setProjectionMatrixAsOrtho2D(0, 1920, 0, 1080);
        // 步骤三:设置视图矩阵
        pCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
        // 步骤四:不受父类矩阵影响
        pCamera->setViewMatrix(osg::Matrix::identity());
        // 步骤五:清除深度缓存
        pCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
        // 步骤六:设置为不接受事件,让其得不到焦点
        pCamera->setAllowEventFocus(false);
        // 步骤七:设置渲染顺序
//        pCamera->setRenderOrder(osg::Camera::PRE_RENDER);       // 不显示了
        pCamera->setRenderOrder(osg::Camera::NESTED_RENDER);    // 显示为背景HUD
//        pCamera->setRenderOrder(osg::Camera::POST_RENDER);      // 显示为前景HUD
        // 步骤八:关闭光照,通过osg::StateSet设置
        pGeode = new osg::Geode();
        osg::ref_ptr<osg::StateSet> pStateSet = pGeode->getOrCreateStateSet();
        pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
        // 步骤九:关闭深度测试
        pStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
    }

    // 创建铺满窗口的方形(窗口形状),并贴背景纹理图
    {
    
        // 步骤一:创建几何信息对象
        osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
        // 步骤二:绑定顶点
        osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
        pGeometry->setVertexArray(pVec3Array);
#if 0
        pVec3Array->push_back(osg::Vec3( 300.0, 100.0, 0.0));
        pVec3Array->push_back(osg::Vec3( 600.0, 100.0, 0.0));
        pVec3Array->push_back(osg::Vec3( 600.0, 200.0, 0.0));
        pVec3Array->push_back(osg::Vec3( 300.0, 200.0, 0.0));
#else
        pVec3Array->push_back(osg::Vec3(   0,    0, 0));
        pVec3Array->push_back(osg::Vec3(1920,    0, 0));
        pVec3Array->push_back(osg::Vec3(1920, 1080, 0));
        pVec3Array->push_back(osg::Vec3(   0, 1080, 0));
#endif
        // 步骤三:读取图片(用于贴纹理)
        osg::ref_ptr<osg::Image> pImage = new osg::Image;
        pImage = osgDB::readImageFile(QString("D:/qtProject/osgDemo/osgDemo/modules/osgWidget/image/background2.png").toStdString());
        if(!pImage->valid())
        {
    
            LOG_WARN(QString("Failed to open image file: %1").arg(QString::fromStdString(pImage->getFileName())));
            return 0;

        }
        // 步骤四:创建纹理
        osg::ref_ptr<osg::Texture2D> pTexture2D = new osg::Texture2D();
        pTexture2D->setImage(pImage);
        pTexture2D->setUnRefImageDataAfterApply(true);
        // 步骤五:绑定纹理映射顶点
        osg::ref_ptr<osg::Vec2Array> pVec2Array = new osg::Vec2Array();
        pGeometry->setTexCoordArray(0, pVec2Array.get());
        pVec2Array->push_back(osg::Vec2(0.0, 0.0));
        pVec2Array->push_back(osg::Vec2(1.0, 0.0));
        pVec2Array->push_back(osg::Vec2(1.0, 1.0));
        pVec2Array->push_back(osg::Vec2(0.0, 1.0));
        // 步骤六:设置纹理环境
//        osg::ref_ptr<osg::TexEnv> pTexEnv=new osg::TexEnv;
//        pTexEnv->setMode(osg::TexEnv::Mode::BLEND);
//        pTexEnv->setColor(osg::Vec4(1.0,0.0,0.0,1.0));
        // 步骤七:关联纹理状态(包括纹理和纹理环境),通过osg::StateSet
        osg::ref_ptr<osg::StateSet> pStateSet = pGeometry->getOrCreateStateSet();
        pStateSet->setTextureAttributeAndModes(0, pTexture2D.get(), osg::StateAttribute::ON);
//        pStateSet->setTextureAttributeAndModes(0, pTexEnv.get(), osg::StateAttribute::ON);
        // 步骤八:为唯一的法线创建一个数组    法线: normal
        osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
        pGeometry->setNormalArray(pVec3ArrayNormal.get());
        pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
        pVec3ArrayNormal->push_back(osg::Vec3(0.0, 1.0, 0.0));
        // 步骤九:由保存的数据绘制四个顶点的多边形
        pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
        // 步骤十:将图形添加进几何节点
        pGeode->addDrawable(pGeometry.get());

    }
    pCamera->addChild(pGeode);  // 几何背景贴图为底图
    pGroup->addChild(pCamera);
    pGroup->addChild(pNode);    // 插入草地
//    pGroup->addChild(pGeode);   // 几何背景又插入一次中间作为元素
    // 设置漫游器,并禁止拽拖自动旋转
    osg::ref_ptr<osgGA::TrackballManipulator> pManipulator = new osgGA::TrackballManipulator;
    pManipulator->setAllowThrow(false);

    return pGroup.get();
} 

工程模板:对应版本号v1.31.0

  (中间有几个版本号是预言项目的,后面再回头说26~30版本的)
  在这里插入图片描述


上一篇:《OSG开发笔记(二十八):OSG模型固定路径动画
下一篇: 持续补充中…


本文章博客地址:https://blog.csdn.net/qq21497936/article/details/134064988

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq21497936/article/details/134064988

智能推荐

JWT(Json Web Token)实现无状态登录_无状态token登录-程序员宅基地

文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录

SDUT OJ逆置正整数-程序员宅基地

文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.

年终奖盲区_年终奖盲区表-程序员宅基地

文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表

matlab 提取struct结构体中某个字段所有变量的值_matlab读取struct类型数据中的值-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值

Android fragment的用法_android reader fragment-程序员宅基地

文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment

FFT of waveIn audio signals-程序员宅基地

文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals

随便推点

Awesome Mac:收集的非常全面好用的Mac应用程序、软件以及工具_awesomemac-程序员宅基地

文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac

java前端技术---jquery基础详解_简介java中jquery技术-程序员宅基地

文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术

Ant Design Table换滚动条的样式_ant design ::-webkit-scrollbar-corner-程序员宅基地

文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;amp;::-webkit-scrollbar { height: 5px; } &amp;amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner

javaWeb毕设分享 健身俱乐部会员管理系统【源码+论文】-程序员宅基地

文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!

论文开题报告怎么写?_开题报告研究难点-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点

原生JS 与 VUE获取父级、子级、兄弟节点的方法 及一些DOM对象的获取_获取子节点的路径 vue-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue

推荐文章

热门文章

相关标签