前言
我们接着昨天的继续,昨天主要是讲解了DatabasePager类中的特定的成员变量以及run函数的第一部分,对所要请求加载的数据按照是否是网络数据进行分类加载模式。今天我们就看看数据是怎们加载到osg环境中的。
还是在DatabasePager::DatabaseThread::run()函数中,首先我们保证了databaseRequest是线程安全的,因为run()函数是创建一个唯一的写入_loadedModel指针的线程。首先还是先依据前面的数据来源是否为网络来判断readFromFileCache是否为true来区分加载方式。我们进入从缓存中读取文件的方法ReaderWriter::ReadResult FileCache::readNode(),就会发现这个方法就是判断当前文件是为缓存文件,然后调用Registry::instance()->readNode()。而这个Registry::instance()->readNode()函数也就是当readFromFileCache为false(不是网络文件)时在DatabasePager::DatabaseThread::run()函数中调用的是同一个函数(Registry::instance()->readNode())。所以osg加载数据文件的原理就在这。那我们就深入探究一下osg到底是怎么加载模型文件的。
Registry注册机
首先我们先介绍一下Registry::instance()(单例模式—以后会统一的讲解一下osg中的设计模式)。这个Registry即是osg的插件注册的管理器。也就是说我们使用osg加载数据文件的时候,osg是通过某一种插件来进行加载的。我们通过观察osgDB::Registry类的构造函数就会发现osg是不是默认就会加载插件到环境中,为什么不加载呢,因为osg的插件非常的庞大大概有121种,如果osg启动的时候就要预加载这么多的插件就会导致osg的启动速度非常的缓慢,所以osg采用了职责链的设计模式以加载尽量少的插件。我们就来介绍一个osg是如果查找适合目前功能的插件的。也就是Registry::LoadStatus Registry::loadLibrary(const std::string& fileName)
1、 osg会先搜索已经注册的插件列表_dlList,判断插件是否已经被加载到环境中,如果osg找到了符合次格式的插件,getLibraryItr(fileName)
2、 如果osg没有在_ dlList中找到所需插件,那么osg就会根据文件的名称来去plugins文件夹下寻找(osgDB_+此文件的后缀 )同名的插件,load到环境中。DynamicLibrary* DynamicLibrary::loadLibrary(const std::string& libraryName)
3、 如果还是没有找到相应的插件,就代表此文件I/O的操作再次失败,OSG将返回失败信息。
注:通过查看 Registry ::addFileExtensionAlias成员变量,就可以知道我们平时加载的模型文件对应的插件名称。他们会被osg保存成一个map(_extAliasMap。)
而我们的osg读取文件的前期操作就是要进行插件的选择预加载,例如加载stl模型,osg会去plugins目录下查找osgDB_stl.dll插件进行加载。然后通过插件类集成的load函数来进行文件的读取加载操作。我们可以把读取过程总结为下面一张图片,请大家仔细理解
原文链接
http://www.3wwang.cn/blog/article.ftl?id=28
阅读(1031) | 评论(0) | 转发(0) |