参考:http://blog.sina.com.cn/s/blog_7cdaf8b60102uzu3.html

http://blog.csdn.net/wang15061955806/article/details/51011466

  osgDB机制概述

  osgDB库允许用户程序加载、使用和写入3D数据库,它采用插件管理的架构,可以支持大量常见的2D图形和3D图形文件格式。osgDB负责维护插件的信息注册表,并负责检查将要被载入的OSG插件接口的合法性。由于大型3D地形数据通常是多段数据块的组合体。因此,应用程序从文件中读取各部分数据库信息时,需要在不干扰当前渲染的前提下以后台线程的方式进行,osgDB::DatabaseParger提供了这样的功能。

  插件的不足之处在于,其设计过程中只能遵循固定的格式和工作模式进行编程,它的一切行为都无法超出主系统所提供的公共接口规范。

  osg插件是一组动态链接库,其中实现了osgDB头文件ReaderWriter定义的接口。OSG不可能查找并加载所有的插件以获取它们支持的文件格式,这样,在程序启动时将会是一个很大的开销。因此,OSG使用职责链(Chain of Responsibility)的设计模式,以加载尽量少的插件。当用户程序尝试使用osgDB读取或写入文件时,OSG将按照如下步骤来查找合适的插件:

  1.OSG搜索已注册的插件列表,查找支持文件格式的插件。开始时已注册插件列表仅包含了Registry类构造函数中注册的插件。如果OSG找到了可以支持此文件格式的插件,并成功执行了I/O操作,那么它将返回相应的数据。

  2.如果没有发现可以支持此格式的已注册插件,或者I/0操作失败,那么OSG将根据前面所述的文件命名规则创建插件文件的名称,并尝试读取相应的插件库。如果读取成功,OSG将添加此插件到已注册插件列表中。

  3.OSG将重复步骤(1),如果文件I/O的操作再次失败,OSG将返回失败信息。

  用3DS插件做说明:

  先就3ds格式模型做一个简要说明,在加载3ds模型时,会根据模型格式在电脑的所有环境变量中找到对应的dll文件(osgdb_3ds.dll),并试着读取osgdb_3ds.dll,加载并成功执行osgdb_3ds.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(ReadNodeFuncto(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);
}
}
}

最新文章

  1. CustomEvent自定义事件
  2. 利用Babel来转化你的ES2015脚本初步
  3. mac 日式键盘反斜线\
  4. C#将Enum枚举映射到文本字符串
  5. 最简单的PHP socket echo server。
  6. cocos2d-x在android中响应返回键编译报错的bug分析
  7. UVA 11059
  8. Js处理数据——前端分页工具
  9. Android编译错误——undefined reference to
  10. 深入浅出数据结构C语言版(7)——特殊的表:队列与栈
  11. shopping_cart
  12. python-opencv aplpha混合
  13. JS通过decodeURIComponent函数解码
  14. org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [/Users/lonecloud/tomcat/apache-tomcat-7.0.70 2/webapps/myproject/WEB-INF/classes/cn/lone
  15. RPA简介
  16. Maximum Sum Circular Subarray LT918
  17. MII接口简介
  18. OC学习3——C语言特性之指针
  19. blfs(systemd版本)学习笔记-配置远程访问和管理lfs系统
  20. [Spark][Python]RDD flatMap 操作例子

热门文章

  1. Andorid- 反序列化,采用pull解析 xml 文件
  2. PHP概率算法---砸金蛋示例
  3. MDK软件仿真常见问题
  4. lampp and testrail
  5. Supermarket---poj456(贪心并查集优化)
  6. 用virtualenv建立多个Python独立开发环境(转)
  7. 人人网张铁安:Feed系统架构分析(转)
  8. CentOS7.0安装Nginx 1.10.0
  9. (2)Mac环境搭建
  10. vim tab设置为4个空格