第2节 数据读取

Viewer的初始化完成之后,就是setSceneData(osgDB::readNodeFile(“glider.osg”));这句了,其中setSceneData是osgViewer::View类的成员函数。记录了要设置进场景的数据。那么关键是osgDB::readNodeFile是怎么工作的?

readNodeFile走到第一句最关键的话是:Registry.cpp中的Registry::read(const ReadFunctor& readFunctor)函数,它调用了createLibraryNameForFile来根据输入的文件名(本例是glider.osg)来构造dll文件名,然后来加载dll,它是怎么构造的呢?

从代码中可以看到,它首先会查询使用addFileExtensionAlias添加的别名,这些调用在Registry::Registry()初始化函数中,比如:

addFileExtensionAlias("gl",   "glsl");  
addFileExtensionAlias("vert", "glsl");  
addFileExtensionAlias("frag", "glsl");  
addFileExtensionAlias("geom", "glsl");  
addFileExtensionAlias("tctrl", "glsl");  
addFileExtensionAlias("teval", "glsl");  
addFileExtensionAlias("compute", "glsl");  
addFileExtensionAlias("vs", "glsl");  
addFileExtensionAlias("fs", "glsl");  
addFileExtensionAlias("cs", "glsl");  
addFileExtensionAlias("gs", "glsl");  

比如我们输入的是test.gl文件,那么它会查询发现其文件的扩展名为glsl,随后就会构造出来一个osgdb_glsl.dll的文件,然后加载。假如一个扩展名没有在addFileExtensionAlias中添加。那么会直接使用文件的扩展名构造比如test.gl,则会构造出osgdb_gl.dll,osgPlugins-3.6.5目录下并没有这个文件,因此加载失败就会报一个最常见的错误:Could not find plugin to read objects from file ***

在正确的加载了dll之后,本例是加载osgdb_osgd.dll,然后就开始调用插件代码中的readNode函数来进行读取。

随便找一个简单的插件,比如Plugins rot,很容易就能仿制一个自己的文件格式的读写插件。如果这个文件的名称与dll的名称不一致,比如文件名是a.bt,需要使用osgdb_abc.dll读取,则需要在读取前调用addFileExtensionAlias(“bt”, “abc”);

本例中是glider.osg,直接就使用osgdb_osgd.dll进行读取了。寻找文件的时候会在环境变量:OSG_FILE_PATH定义的路径下寻找,也会在当前路径下寻找。

加载osg文件会进入到Plugins osg中调用readNode,osg文件是名文,一个字段一个字段的判断写法上肯定不是最高效的。osg又使用了以下办法来易于扩展。

osgdb_osg.dll会加载Plugins osg deprecated osg插件osgdb_deprecated_osg.dll,其中定义了每个osg明文支持的字段用哪个方法来读取,比如glider.osg(用写字板打开)里是一个Geode,其中前面的字段是Geode的父类Object类的,因此会先调用osgWrappers \\deprecated-dotosg \\osg \\ Object.cpp中的Object_readLocalData来进行读取,然后会依次调用这个文件夹里的Geode.cpp,每个类的名字只读它自己定义的字段,它从父类继承的要从父类来读。

也就是我们要想自己定义一个node的类型,或者在现有的node里添加一个什么字段,比如在Geode里加一个字段,这个字段想要序列化和反序列化(序列化就是写入到osg文件中,反序列化就是支持从osg文件中读取该字段)这就涉及到读写文件的问题。就会涉及到上面的Plugins osg deprecated osg插件。

© 版权声明
THE END
喜欢就支持一下吧
点赞1 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片