osg--读写

本文详细介绍了osg库中的文件输入输出操作,包括命名规则、文件后缀与加载器的关联、使用方法以及自定义加载。重点讨论了osgDB::ReaderWriter类在读取和写入节点、图像时的角色,还展示了如何实现流加载和序列化osg格式的步骤。

文件I/O

命名规则

osgdb_xxx

比如:

osgdb_osg
osgdb_jpeg 

关联文件后缀和加载器

osgDB::Registry::instance()->addFileExtensionAlias( "jpeg", "jpeg" );
osgDB::Registry::instance()->addFileExtensionAlias( "jpg", "jpeg" );

使用

osg::Node* node = osgDB::readNodeFile( "cow.osg" );
osg::Image* image = osgDB::readImageFile( "Images/lz.rgb" );

说明

加载文件两个步骤

  1. osgDB::Registry
    • 单一实例
    • 管理着常用文件I/O插件列表
    • 逐一向下传递
  2. 外部共享模块

已支持

在这里插入图片描述

伪加载

并非实际的文件后缀

自定义加载

osgDB::ReaderWriter

  • supportsExtension

  • acceptsExtension

  • fileExists

  • readNode

      osgDB::ReaderWriter::ReadResult readNode(const std::string& file,const osgDB::Options* options) const
      {
          // Check if the file extension is recognizable and file exists
          bool recognizableExtension = …;
          bool fileExists = …;
          if (!recognizableExtension) return ReadResult::FILE_NOT_HANDLED;
          if (!fileExists) return ReadResult::FILE_NOT_FOUND;
          …
          // Construct the scene graph according to format specification
          osg::Node* root = …;
          …
          // In case there are fatal errors during the process,
          // return an invalid message; otherwise return the root node
          bool errorInParsing = …;
          if (!errorInParsing) return ReadResult::ERROR_IN_READING_FILE;
          return root;
      }
    
    • osgDB::ReaderWriter::ReadResult重载构造器
      • node
      • image
      • status enumeration
      • other special object
      • error message string
      • 方法
        • success
        • takeNode
    • osgDB::Options
      • setOptionString
      • getOptionString
      • 直接传入readNodeFile第二个参数
  • writeNode

  • readImage

  • writeImage

流加载

  1. 定义读写接口

     osgDB::ReaderWriter::ReadResult readNode(const std::string& file,const osgDB::Options* options) const
     {
         …
         osgDB::ifstream stream( file.c_str(), std::ios::binary );
         if ( !stream ) return ReadResult::ERROR_IN_READING_FILE;
         return readNode(stream, options);
     }
     
     osgDB::ReaderWriter::ReadResult readNode(std::istream& stream,const osgDB::Options* options) const
     {
         // Construct the scene graph according to format specification
         osg::Node* root = …;
         return root;
     }
    
  2. 利用已有读写器处理流

     osgDB::ReaderWriter* rw =osgDB::Registry::instance()->getReaderWriterForExtension("osg");
     if (rw)
     {
         osgDB::ReaderWriter::ReadResult rr = reader->readNode(stream);
         if ( rr.success() )
             node = rr.takeNode();
     }
    

示例

CMakeLists.txt

add_library( osgdb_tri SHARED readerwriter.cpp )

readerwriter.cpp

#include <osg/Geometry>
#include <osg/Geode>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <osgUtil/SmoothingVisitor>
#include <iostream>

class ReaderWriterTRI : public osgDB::ReaderWriter
{
public:
	ReaderWriterTRI();

	virtual ReadResult readNode(
		const std::string&, const osgDB::ReaderWriter::Options*)
		const;
	virtual ReadResult readNode(
		std::istream&, const osgDB::ReaderWriter::Options*) const;
};
ReaderWriterTRI::ReaderWriterTRI()
{
	supportsExtension("tri", "Triangle strip points");
}
ReaderWriterTRI::ReadResult ReaderWriterTRI::readNode(
	const std::string& file, const osgDB::ReaderWriter::Options* options)
	const
{
	std::string ext = osgDB::getLowerCaseFileExtension(file);
	if (!acceptsExtension(ext)) 
		return ReadResult::FILE_NOT_HANDLED; 
	std::string fileName = osgDB::findDataFile(file, options);
	if (fileName.empty()) 
		return ReadResult::FILE_NOT_FOUND;
	std::ifstream stream(fileName.c_str(), std::ios::in);
	if (!stream) 
		return ReadResult::ERROR_IN_READING_FILE;
	return readNode(stream, options);
}
ReaderWriterTRI::ReadResult ReaderWriterTRI::readNode(
	std::istream& stream, const osgDB::ReaderWriter::Options*) const
{
	unsigned int index = 0, numPoints = 0;
	stream >> numPoints;

	osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array;
	while (index<numPoints && !stream.eof() &&
		!(stream.rdstate()&std::istream::failbit))
	{
		osg::Vec3 point;
		stream >> point.x() >> point.y() >> point.z();
		va->push_back(point);
		index++;
	}


	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
	geom->setVertexArray(va.get());
	geom->addPrimitiveSet(
		new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, numPoints));


	osgUtil::SmoothingVisitor smoother;
	smoother.smooth(*geom);


	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
	geode->addDrawable(geom.get());
	return geode.release();
}
REGISTER_OSGPLUGIN(tri, ReaderWriterTRI);

使用

osgviewer example.tri

序列化osg格式

前提

  • 继承osg::Object
  • META_Object 正确定义命名空间和类名
  • 每一个成员变量需要有getter和setter方法

示例

#include <osg/Node>
#include <osgDB/ObjectWrapper>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <iostream>

namespace testNS {
class ExampleNode : public osg::Node
{
public:
    ExampleNode() : osg::Node(), _exampleID(0) {}
    
    ExampleNode(const ExampleNode& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
    : osg::Node(copy, copyop), _exampleID(copy._exampleID) {}
    

    META_Node(testNS, ExampleNode)
    

    void setExampleID( unsigned int id ) { _exampleID = id; }
    unsigned int getExampleID() const { return _exampleID; }
    

protected:
    unsigned int _exampleID;
};
}
REGISTER_OBJECT_WRAPPER( ExampleNode_Wrapper,new testNS::ExampleNode,testNS::ExampleNode,"osg::Object osg::Node testNS::ExampleNode" )
{
    ADD_UINT_SERIALIZER( ExampleID, 0 );
}
int main(int argc, char** argv)
{
	osg::ArgumentParser arguments( &argc, argv );
	unsigned int writingValue = 0;
	arguments.read( "-w", writingValue );
	
	if ( writingValue!=0 )
	{
		osg::ref_ptr<testNS::ExampleNode> node = new testNS::ExampleNode;
		node->setExampleID( writingValue );
		osgDB::writeNodeFile( *node, "examplenode.osgt" );
	}else
	{
		testNS::ExampleNode* node = dynamic_cast<testNS::ExampleNode*>(osgDB::readNodeFile("examplenode.osgt") );
		if ( node!=NULL )
		{
			std::cout << "Example ID: " << node->getExampleID() << std::endl;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值