【OBJ/OSGB文件简化代码】亲测可用,利用osgUtil::Simplifier进行OBJ/OSGB文件简化

在OSG中,利用osgUtil::Simplifier进行OBJ/OSGB文件简化压缩代码

对于倾斜摄影模型(OBJ/OSGB)来说,存在节点多、数据量大、渲染处理速度慢等问题,因此对其进行简化压缩是一个不可为避免的问题。本文以OBJ数据为例,在C++中配置好OSG引擎的前提下,利用osgUtil::Simplifier类对单一OBJ文件进行压缩,并输出压缩后的OBJ文件。

osgUtil::Simplifier simplifier(sampleRatio, maxError);

osgUtil::Simplifier 类继承自osg::NodeVisitor类,以访问器的方式遍历几何体并对其进行简化处理。osgUtil::Simplifier类采用QEM(Quadric Error Metrics),即基于二次误差度量的边塌陷算法(参考文献可私我要),通过合并顶点的方式进行三角面片的简化,实现原始OBJ文件大小的压缩,同时保持每个顶点伴随的纹理属性不变。
具体代码如下:

//#include "stdafx.h"
#include <string>
#include <iostream>
#include <osgViewer/Viewer> 
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osg/Node>  //节点类
#include <osg/Geode> //是个几何节点,可以说是一个几何Group节点,一般的可绘制几何体都是通过它来传向root进行渲染,是OSG几何绘制的最高管理节点
#include <osg/Group> //对节点起到组织作用,一般作为父节点或者根节点出现
#include <osg/PositionAttitudeTransform> //位置变换节点类,提供模型的位置变换、大小缩放、原点位置的设置、坐标系的变换
#include <osg/Material>
#include <osgViewer/ViewerEventHandlers> //事件监听
#include <osgGA/StateSetManipulator> //事件响应类,对渲染状态进行控制
#include <osgUtil/Optimizer> //优化器
#include <osgUtil/Simplifier> //简化几何体
#include <osgDB/ReaderWriter>

using namespace std;
//读取模型
osg::Node* readModel()
{
	string rpath = "D:/测区OBJ/Tile_+651_+443/Tile_+651_+443.obj";    //输入OBJ文件
	//设置文件读取不旋转
	osg::ref_ptr<osgDB::Options> options = new osgDB::Options("noRotation");
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(rpath, options);
	cout << "reading done!" << endl;
	return node.release();
}

//深拷贝并简化新模型
osg::Node* deepCopy(osg::Node* node)
{
	/*
	创建简化对象
	simplifier(sampleRatio, maxError)
	参数:样本比率、点的误差或边的长度  样本简化比率
	样本比率<1 设置点的误差
	样本比率>1 设置边的长度限制
	比率越大,简化越少
	使用的是边塌陷算法
	*/
	float sampleRatio = 0.1f;//0.3f
	float maxError = 4.0f;
	osgUtil::Simplifier simplifier(sampleRatio, maxError);

	//深拷贝
	osg::ref_ptr<osg::Node> deepnode = (osg::Node*)(node->clone(osg::CopyOp::DEEP_COPY_ALL));
	//创建一个位置变换节点,将之设置为新位置,将深拷贝的模型移到新位置
	osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();
	pat->setPosition(osg::Vec3(120.0f, 0.0f, 0.0f));  //(10.0f, 0.0f, 0.0f)) (右方,后方,上方) 视点沿Y轴向后  对比简化前后效果
	pat->addChild(deepnode);
	pat->accept(simplifier);
	return pat.release();
}

int main()
{
	//创建一个叶节点对象并添加节点 
	osg::ref_ptr<osg::Group> root = new osg::Group();
	osg::ref_ptr<osg::Node> node1 = readModel();
	osg::ref_ptr<osg::Node> node2 = deepCopy(node1);
	root->addChild(node1);
	root->addChild(node2);

	//优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	//显示模型
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	//切换网格模式,方便比较
	viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
	viewer->setSceneData(root.get());
	viewer->realize();

	osg::ref_ptr<osgDB::ReaderWriter::Options> options = new osgDB::ReaderWriter::Options;
	//options->setOptionString("Compressor=zlib"); //设置压缩格式为zlib WriteImageHint = IncludeFile
	string wpath = "D:/测区OBJ/Tile_+651_+443/Tile_+651_+443_01f.obj"; //输出OBJ文件位置
	osgDB::writeNodeFile(*(node2.get()), wpath); //使用zlib压缩写入新osgb文件
	cout << "done" << endl;

	return viewer->run(); //return代表程序结束,后面的语句不执行了
}

上述代码亲测可用,数据处理前后对比结果展示如下:

实验结果可以看出,能够在不影响三维场景显示效果的前提下,减少模型和三角面片的数量,从而实现OBJ文件的压缩,同时纹理得以完好保存;
此外,设置三角面简化比例在R=0.1条件下,大概可达到41%左右的简化率,文件所占内存得以大大减小。因此,可以认为,本方法具有不错的效果。如果有用的话,帮忙点个赞吧,非常感谢哈哈!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
网页导入3D模型(Obj/mtl)文件的过程相对简单。首先,我们需要准备一个具有3D功能的网页环境,比如使用Three.js或Babylon.js这样的库。接下来,需要将模型文件(通常是.obj文件)和其关联的材质文件(.mtl文件)上传至服务器或者在项目中引用这些文件。 然后,我们可以使用JavaScript代码来加载这些模型和材质文件。首先,我们需要创建一个场景(scene)来承载模型,然后在场景中创建一个加载器(loader)以加载模型文件和材质文件。 对于.obj文件,我们需要使用对应的ObjLoader(loader)来加载。加载器将从服务器或者本地文件系统中加载模型文件,并将其解析成可以在网页上显示的数据结构。加载完成后,我们可以通过遍历模型的顶点、纹理坐标和面信息来创建3D网格。 对于.mtl文件,我们需要使用对应的MtlLoader(loader)来加载。加载器将读取.mtl文件的内容,并为每个材质创建一个材质对象。这些材质对象将与3D网格的面信息关联起来,以确定每个面应该使用哪个材质。 最后,我们需要将3D网格添加到场景中并设置相机(camera)的位置和视角,以便用户能够在网页上正确地查看和交互模型。通过设置合适的光照和材质属性,我们可以增强模型的视觉效果。 总之,导入3D模型(Obj/mtl)文件到网页中需要使用3D库和相应的加载器来处理模型和材质文件。通过以上步骤,我们可以将3D模型成功加载到网页,并实现与之交互的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值