osgDB.ReaderWriter是OpenSceneGraph(以下简称OSG)的一个重要组件,用于读取和写入场景数据。这个组件是一个接口类,它定义了所有OSG支持的文件格式的读写操作。
Inheritance Hierarchy: osg::Object -> osgDB::ReaderWriter
一个ReaderWriter是一个用于读写的插件,它能够读取和写入特定的场景数据格式。OSG通过添加ReaderWriter插件来扩展自己的支持文件格式。插件是通过继承 osgDB::ReaderWriter而创建的。
一个ReaderWriter插件应该实现如下方法:
class ReaderWriter {
public:
virtual ~ReaderWriter() {}
virtual bool acceptsExtension(const std::string& extension) const = 0;
virtual ReadResult readObject(const std::string& filename, const Options* options = nullptr) const = 0;
virtual ReadResult readObject(std::istream& fin, const Options* options = nullptr) const { return ReadResult(); }
virtual WriteResult writeObject(const Object& /*obj*/, const std::string& /*fileName*/, const Options* = nullptr) const { return WriteResult(); }
virtual WriteResult writeObject(const Object& /*obj*/, std::ostream& /*out*/, const Options* = nullptr) const { return WriteResult(); }
};
acceptsExtension()
:判断该插件是否能够处理某个扩展名的文件。readObject()
:从文件中读取特定格式的场景数据,并返回osgDB::ReaderWriter::ReadResult对象。该Result中包含了读取出来的场景数据,或者读取失败的详细信息。writeObject()
:将一个场景数据写入到指定的文件或流中。食用方式:
在使用之前需要先注册该插件.
osgDB::ReaderWriter::Registry::instance()->addReaderWriter(new osgDB::myReaderWriter());
要在程序退出之前移除。
osgDB::ReaderWriter::Registry::instance()->removeReaderWriter (new osgDB::myReaderWriter());
支持压缩(zip)格式,可以通过.zip
扩展名来识别。
OpenSceneGraph是通过.osg
二进制文件存储数据的,可以通过如下方式读取二进制文件并创建场景.
osgDB::Registry::instance()->getDataFilePathList().push_back("./");
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("test.osg");
viewer.setSceneData(node.get());
其中 Registry::instance()->getDataFilePathList().push_back("./")
将在读取文件时添加相对路径,再次强调请勿忽略。
osgDB::ReaderWriter框架并不支持所有OSG预定义节点的写入。在某些情况下,您可能需要在场景数据中添加自定义节点。然而,这些自定义节点可能不可用于osgDB::Registry::writeNode()。
以下是一个简单的示例程序,演示了如何使用脚本创建自定义场景并将其保存到本地磁盘中。
#include <osgDB/ReaderWriter>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/Registry>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/Image>
class MyReaderWriter : public osgDB::ReaderWriter {
public:
virtual const char* className() const {
return "MyReaderWriter";
}
virtual bool acceptsExtension(const std::string& extension) const {
return (extension == "myformat");
}
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& filename, const osgDB::ReaderWriter::Options* options) const {
return osgDB::ReaderWriter::ReadResult();
}
virtual osgDB::ReaderWriter::WriteResult writeNode(const osg::Node& node, const std::string& filename, const osgDB::ReaderWriter::Options* options) const {
osg::ref_ptr<osg::Group> root = new osg::Group;
// An example custom texture
unsigned char texels[] = { 255,0,0, 255,0,0, 0,0,255, 0,0,255 };
int texWidth = 2, texHeight = 2, texDepth = 1;
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setDataVariance(osg::Object::DYNAMIC);
texture->setImage(new osg::Image(texWidth, texHeight, texDepth, GL_RGB, GL_UNSIGNED_BYTE, texels), osg::Texture::NO_DELETE);
// An example custom geometry
osg::Geometry* geom = new osg::Geometry;
geom->setVertexArray(new osg::Vec3Array);
osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(geom->getVertexArray());
osg::Vec2Array* texcoords = new osg::Vec2Array;
geom->setTexCoordArray(0, texcoords);
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(geom);
root->addChild(geode);
verts->push_back(osg::Vec3(0, 0, 0));
verts->push_back(osg::Vec3(1, 0, 0));
verts->push_back(osg::Vec3(1, 1, 0));
osg::drawElementsUByte(osg::PrimitiveSet::TRIANGLES, 0, 3, *geom->getOrCreateDrawElementsUByte(osg::PrimitiveSet::TRIANGLES))->setCount(3);
texcoords->push_back(osg::Vec2(0, 0));
texcoords->push_back(osg::Vec2(1, 0));
texcoords->push_back(osg::Vec2(1, 1));
geom->getOrCreateTextureStateAttribute()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
// Write the scene graph to file
osgDB::Registry::instance()->writeNode(node, filename, options);
return osgDB::ReaderWriter::WriteResult(osgDB::ReaderWriter::WriteResult::FILE_SAVED);
}
};
创建一个MyReaderWriter实例:
osg::ref_ptr<MyReaderWriter> myReaderWriter = new MyReaderWriter;
osgDB::Registry::instance()->addReaderWriter(myReaderWriter.get());
将场景保存为本地文件:
osgDB::writeNodeFile(*root, "output.osg", new osgDB::Options);
osgDB.ReaderWriter是一个重要的OpenSceneGraph组件,提供了读写不同格式场景数据的能力. 可以将其看作是一种插件模型。它允许不同的场景文件格式通过不同的插件来进行读写。osgDB.ReaderWriter的读写操作非常高效,它读写的文件可以是ASCII文本,也可以是二进制文件,而且它支持的文件格式非常广泛。osgDB.ReaderWriter的灵活性和扩展性使其成为OpenSceneGraph这个3D引擎体系的重要组成部分。