我们可以直接使用osgDB::readNodeFile("cow.osg")来读取不同格式的模型,osgDB库允许用户程序加载、使用和写入3D数据库,它采用插件管理的架构,可以支持大量常见的2D图形和3D图形文件格式。osgDB负责维护插件的信息注册表,并负责检查将要被载入的OSG插件接口的合法性。由于大型3D地形数据通常是多段数据块的组合体。因此,应用程序从文件中读取各部分数据库信息时,需要在不干扰当前渲染的前提下以后台线程的方式进行,osgDB::DatabaseParger提供了这样的功能。
1、自定义文件插件:
自定义文件插件主要是自定义一个插件读写类,继承osgDB::ReaderWriter类,然后根据需求重写如readNode等函数方法即可,如下,这些函数的返回值均为枚举变量。
virtual ReadResult readNode(std::istream& /*fin*/,const Options* =NULL) const { return ReadResult(ReadResult::NOT_IMPLEMENTED); }
在建立插件读写类时需要注意:
REGISTER_OSGPLUGIN是一个宏,在Registry.h中如下定义 #define REGISTER_OSGPLUGIN(ext, classname) \ extern "C" void osgdb_##ext(void) {} \ static osgDB::RegisterReaderWriterProxy<classname> g_proxy_##classname;
void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt) { _extAliasMap[mapExt] = toExt; }
主要的实现的代码是在ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor)函数中
ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor) { // first attempt to load the file from existing ReaderWriter's //看是否有可用的ReaderWriter,对当前的数据进行解析,如果解析成功,就返回结果 AvailableReaderWriterIterator itr(_rwList, _pluginMutex); for(;itr.valid();++itr) { ReaderWriter::ReadResult rr = readFunctor.doRead(*itr); if (readFunctor.isValid(rr)) return rr; else results.push_back(rr); } // now look for a plug-in to load the file. //根据文件名称创建新的动态库名称,然后加载动态库,增加_rwList对象个数 std::string libraryName = createLibraryNameForFile(readFunctor._filename); if (loadLibrary(libraryName)!=NOT_LOADED) { //重新遍历一下,使用新的ReaderWriter进行数据的解析 for(;itr.valid();++itr) { ReaderWriter::ReadResult rr = readFunctor.doRead(*itr); if (readFunctor.isValid(rr)) return rr; else results.push_back(rr); } } }接下去需要研究createLibraryNameForFile()。