1. osgDB库
(1)提供了读取二维图像和三维模型的接口,同时,也管理着第三方插件系统(支持的文件格式非常多,每个插件负责一种或多种文件格式的读写),以实现对不同格式文件的读取。
(2)负责维护插件的信息注册表,并负责检查将要被载入的OSG插件接口的合法性;
1. 插件信息注册表是osgDB内部维护的一个核心数据结构,存储所有已注册插件的名称、支持的文件扩展名以及对应的读写函数指针,当调用osgDB::readNodeFile("model.obj")时,osgDB会查询注册表,找到支持.obj格式的插件,然后调用该插件的读取函数来加载模型;也可以添加新的插件到注册表中,让osgDB支持新的文件格式;
(3)应用程序从文件中读取各部分数据库信息时,需要在不干扰当前渲染的前提下以后台线程的方式进行,osgDB::DatabasePager提供了这样的功能;
【DatabasePager主要用于超大规模地形/场景的分页数据库动态调度,使用osgDB::readNodeFile在后台线程读取后,需通过回调或信号将节点加入主场景图,以避免线程安全问题。】
(4)读取文件参数可以是绝对路径,也可以是相对路径(从数据路径列表中搜索文件,有两种方式:);
1. 添加环境变量OSG_FILE_PATH,优先级高于程序当前工作目录;
2. 使用osgDB::Registry::instance()->getDataFilePathList().emplace_back(newpath),优先级高于OSG_FILE_PATH环境变量;
2. OSG支持两种本地文件格式:
(1).osg文件:标准的ASCII文本(一种文本文件),它并不是一种可以实现高效存储和读取的数据结构,但它是一种极好的调试工具。在应用程序开发时,如果遇到了意料不到的渲染结果,可以将渲染结果保存为.osg文件,然后对其进行手动修改;
(2).ive文件:为性能而生,把场景树存成二进制文件,支持将模型数据和所有依赖的纹理文件(如.rgb等图片)嵌入到同一个.ive文件中,用户只需拿到一个.ive文件,程序就能直接加载,无需单独分发纹理文件,避免了文件丢失或路径错误;
(3)另外还有.osgt(文本)和.osgb(二进制),它们是.osg和.ive的通用替代格式,通常更推荐;
3. 文件的读取:文件读取失败的原因有很多,可以设置调试信息NOTIFY来确定,很多时候可能是因为找不到插件或者文件不存在造成的;
4. 文件的保存:文件保存失败的原因也很多,也可以通过设置调试信息NOTIFY来确定,很多时候可能是因为找不到插件或者扩展名不支持造成的;
【插件加载失败的调试:在程序启动时调用osgDB::Registry::instance()->getLibraryRefList()可以打印所有已加载的插件列表,快速确认目标插件是否被找到。】
5. 插件的工作机制
(1)插件的搜索和注册
1. OSG插件是一组动态链接库,每个库都实现了osgDB::ReaderWriter定义的统一接口;
2. 插件所在目录必须在系统路径(例如Windows的PATH)中,或者通过OSG_LIBRARY_PATH环境变量指定,这样OSG才能找到它们;
3. 插件的命名规则:Windows平台的命名格式(osgdb_<name>.dll);<name>通常对应文件扩展名,例如osgdb_gif.dll,但一个插件可以支持多种文件扩展名,为了处理这种情况,osgDB::Registry维护了一张扩展名映射表,存储「文件格式别名 → 标准格式标识」;
4. osgDB::Registry:是OSG插件系统的核心单例类:
① 记录所有已经加载的插件,避免重复加载;
② 维护扩展名映射表;
③ 构造函数中预先注册一些核心插件,避免启动时加载所有插件,减少开销;
5. OSG不会在启动时加载所有插件(否则启动会极慢),而是用职责链设计模式,实现“按需加载”,当调用osgDB::readNodeFile("model.osg"),OSG会按以下步骤查找插件:
① 先在Registry的已注册插件列表中,查找支持.osg格式的插件,如果找到,直接用这个插件执行读写操作,成功则返回数据;
② 如果已注册列表中没有支持该格式的插件,或读写失败,OSG会根据命名规则生成插件名(如osgdb_osg.dll),尝试从系统路径中加载这个插件,如果加载成功,就把它加入已注册插件列表;
③ 加载新插件后,回到第一步,再次查找支持该格式的插件(现在插件已经在列表里了),如果再次失败,就返回读写错误信息。
6. 读写中文文件名及中文路径问题
(1)根本原因:OSG的底层文件操作依赖C/C++标准库,这些库默认使用ANSI/多字节编码处理字符串,而Windows系统的文件路径默认使用Unicode宽字符编码,直接把中文路径传给OSG函数时,会被当成乱码,导致“文件不存在”或读取失败;
(2)解决方法:
1. setlocale是C标准库函数,用于配置程序的本地化信息,核心作用是让C库的文件操作函数能正确解析非ASCII字符(C库的文件操作函数会将传入的中文路径从Unicode宽字符转换为GBK多字节编码,从而被OSG底层正确识别),例如:setlocale(LC_ALL, "chs"); // 或 "Chinese-simplified"、".936";
2. 使用宽字符路径,OSG会自动处理(L"中文路径" 仅在 OSG 3.4 及以上版本完善支持):
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(L"D:/模型/中文模型.osg");
【osgArchive读写流程(将多个模型、纹理文件打包成一个文件.osga)和自定义文件插件(需要自定义文件格式,如加密格式,保护自己的模型、纹理资源)以及osgExp导出工具(是 3ds Max 到 OSG 的直接导出桥梁,能最大程度保留模型、材质、动画信息)暂未记录】



