vulkanscenegraph显示倾斜模型(4)-数据读取

 前言

     本文在上篇文章的基础上,进一步深入探讨数据读取机制的实现细节。回顾 OpenSceneGraph (OSG),其通过 osgDB 库管理场景数据的读取和写入。常用的读取函数包括 osgDB::readNodeFile 和 osgDB::readImageFile,它们能够根据文件扩展名自动选择合适的插件进行加载。插件机制是 OSG 数据读取的核心,主要包括插件的注册、发现以及相关接口的定义(基类 osgDB::ReaderWriter 提供了这些接口的具体定义)。与此类似,VulkanSceneGraph (VSG) 也采用了插件化的数据读取机制。在 VSG 中,通过 vsg::read 函数读取数据,并由继承自 vsg::ReaderWriter 的子类负责具体的数据加载工作。


目录

  • 1 数据读取
  • 2 插件机制
  • 3 osg转vsg

1 数据读取

auto options = vsg::Options::create();
options->fileCache = vsg::getEnv("VSG_FILE_CACHE");
options->paths = vsg::getEnvPaths("VSG_FILE_PATH");

// add OpenSceneGraph's support for reading and writing 3rd party file formats
options->add(vsg::VSG::create());
options->add(vsg::spirv::create());
options->add(osg2vsg::OSG::create());

// load VulkanSceneGraph scene graph
auto vsg_scene = vsg::read_cast<vsg::Node>(filename, options);

     上述代码最后一行vsg::read_cast<vsg::Node>()会转调到vsg源码文件夹src\vsg\io下的read.cpp文件中的vsg::read(const&Path,ref_ptr<const Options>)函数,函数共包含两个逻辑:1) 当options中的sharedObjects不为空且其函数suitable传入文件路径返回true时,读取文件;2)直接读取文件,代码结构如下:

if (options && options->sharedObjects && options->sharedObjects->suitable(filename))
{
    ... 
}
else
{
    return read_file();
}

     本篇文章将重点分析if函数的第二个分支,而将第一个分支暂时搁置,留待后续探讨。我们可以将第一个分支命名为“sharedObjects非空时的读操作”。以下是第二个分支的具体代码:

    auto read_file = [&]() -> ref_ptr<Object> {
        if (options && !options->readerWriters.empty())
        {
            for (auto& readerWriter : options->readerWriters)
            {
                auto object = readerWriter->read(filename, options);
                if (object) return object;
            }
            return {};
        }

        auto ext = vsg::lowerCaseFileExtension(filename);

        if (ext == ".vsga" || ext == ".vsgt" || ext == ".vsgb")
        {
            VSG rw;
            return rw.read(filename, options);
        }
        else if (ext == ".spv")
        {
            spirv rw;
            return rw.read(filename, options);
        }
        else if (glsl::extensionSupported(ext))
        {
            glsl rw;
            return rw.read(filename, options);
        }
        else if (txt::extensionSupported(ext))
        {
            txt rw;
            return rw.read(filename, options);
        }
        else
        {
            // no means of loading file
            return {};
        }
    };

     read_file函数采用lamda表达式,首先找到合适的读取器(readWriter)读取数据,当返回数据为空时,采用默认的读取器(VSG、spirv、glsl、txt)读取数据,否则最后返回为空。

2 插件机制

     在 VulkanSceneGraph (VSG) 中,数据读取的插件机制是通过 vsg::ReaderWriter 类实现的。这个机制允许开发者扩展 VSG 的功能,通过重写read函数实现数据的读取。如上章描述所示,插件采用options传递和默认(VSG、spirv、glsl、txt)的方式读取数据。

     通过给options对象添加读取osg数据的读写器,从而支持解析osgb格式的数据。


options->add(osg2vsg::OSG::create());

3 osg转vsg

     osg2vsg::osg插件重写read函数,读取osgb格式的文件,本章主要关注倾斜模型对应的osgb格式(即仅包含三角网和纹理的模型)的读取。核心代码如下:

    osgDB::ReaderWriter::ReadResult rr = osgDB::Registry::instance()->readObject(filename.string(), osg_options.get());
    // if (!rr.success()) OSG_WARN << "Error reading file " << filename << ": " << rr.statusMessage() << std::endl;
    if (!rr.validObject()) return {};

    bool mapRGBtoRGBAHint = !options || options->mapRGBtoRGBAHint;

    osg::ref_ptr<osg::Object> object = rr.takeObject();
    if (osg::Node* osg_scene = object->asNode(); osg_scene != nullptr)
    {
        return osg2vsg::convert(*osg_scene, options);
    }

    上述代码利用osg引擎读取osgb文件,接着将osg节点转为vsg节点(osg2vsg::convert)。

    下图为vsg中节点继承关系图。

     接着具体分析函数osg2vsg::convert将osg::Node转换为vsg::Node的过程。

     如上图所示,代码回到convert.cpp(osg2vsg v0.1.0)的127行到131行,127行创建了一个osg访问器osg2vsg::ConvertToVsg,代码130行将osg::Node转换为vsg::Node。和osg库类似,其主要重写apply(osg::PagedLOD&)和apply(osg:Geometry&geometry)函数将osg的节点转换为对应的vsg节点,osg2vsg::ConvertToVsg访问器中,将osg::PagedLOD转换为了vsg::PagedLOD,而将osg::Geometry转换为了vsg::Command,具体的转换过程放在悬疑列表中,至此将osg转vsg的过程讲解完毕!

文末:通过研读18-31行代码(参照vulkanscenegraph显示倾斜模型-优快云博客 中对研读代码的划分),本篇文章深入探讨数据读取机制的实现细节,包含数据读取、插件机制、osg转vsg三个部分,并在悬疑列表中留下两个问题,sharedObjects非空时的读操作与osg::PagedLOD转vsg::PagedLOD和osg::Geometry转vsg::Command的具体细节。

悬疑列表:sharedObjects非空时的读操作、osg::PagedLOD转vsg::PagedLOD和osg::Geometry转vsg::Command的具体细节。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CHPCWWHSU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值