osg_osgDB插件机制

最近研究了一段osg/osgDB插件读写机制,写出来,做个记录,方便查阅。

举例说明。例如加载cow.stl这个格式的模型

首先根据模型格式stl

找到对应的dll名称,osgdb_stl.dll

查找电脑的所有环境变量找到osgdb_stl.dll

试着读取osgdb_stl.dll

加载成功,并成功执行了osgdb_stl.dll的宏定义,然后解析文件成功,然会解析结果。

函数执行顺序:
osg::Node *node=osgDB::readNodeFile(某种类型的文件路径),这个语句是osg读取节点数据常用的函数,下面对这个函数进行跟踪,简单介绍下数据的处理过程,方面自己对osgDB的插件进行简单的修改,供自己进行简单的修改;


  osg::Node *readNodeFile(const std::string &filename)  //函数所在位置osgDB/ReadFile,该函数属于文件作用域,调用文件中的另一个函数
  {
     //函数所在位置osgDB/ReadFile,该函数只是在原来的基础上,调用了osgDB/Registry的文件中的一个Registry单例,获取的是option,默认为空
     return readNodeFile(filename,osgDB::Registry::instance()->getOptions());//osgDB/ReadFile ①
   }


//①的具体实现,该函数的作用是调用osgDB/Registry的单例,进行数据的解析,参数options默认为空.
Node* osgDB::readNodeFile(const std::string& filename,const Options* options)
{
    ReaderWriter::ReadResult rr = Registry::instance()->readNode(filename,options);②


}


//②的具体实现,由于options参数为空,并且_readFileCallback为空,所以函数直接执行③
    ReaderWriter::ReadResult readNode(const std::string& fileName,const Options* options, bool buildKdTreeIfRequired=true)
        {
             ReaderWriter::ReadResult result;
            
             result = readNodeImplementation(fileName,options);③
        }
//③的具体实现,直接执行函数④
ReaderWriter::ReadResult Registry::readNodeImplementation(const std::string& fileName,const Options* options)
{
    return readImplementation(ReadNodeFunctor(fileName, options),Options::CACHE_NODES);④                      
}
//④的具体实现,由于readFunctor的options为空,所以函数在中间没有做实际的数据处理,直接执行⑤
ReaderWriter::ReadResult Registry::readImplementation(const ReadFunctor& readFunctor,Options::CacheHintOptions cacheHint)
{
    std::string file(readFunctor._filename);


   ReaderWriter::ReadResult rr = read(readFunctor);⑤
   return rr;
    
}

//⑤的具体实现,这里是主要的实现,主要的思想是,先从_rwList查找是否可以解析当前类型的数据,如果能解析,直接返回解析结果

//如果不能解析,根据当前的文件名称,创建一个跟当前名称相关的动态库的名称,然后使用loadLibrary加载该动态库,加载成功后

_rwList这里面存储的对象的数目会增加,这个是个有诀窍的地方,在这个工程中没有发现有对_rwList做增加操作的代码,那么_rwList是怎么增加的

主要的关键点是,对于每一个dll中都有个宏调用,该宏是如下,这个宏生成了一个静态的对象osgDB::RegistryReaderWriterProxy,这个对象的作用就是

增加_rwList的对象数目,这是注册机制的关键。然后使用新增加的readerWrite完成对数据文件的读取

/////////////#define REGISTER_OSGPLUGIN(ext, classname) \
////////////extern "C" void osgdb_##ext(void) {} \
///////////  static osgDB::RegisterReaderWriterProxy g_proxy_##classname;

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;
     
    }


    //根据文件名称创建新的动态库名称,然后加载动态库,加载动态库,增加_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);
        }
    }

}


你可能感兴趣的:(osg)