【问题标题】:OBJ Parser with Boost Spirit - Ignoring comments带有 Boost Spirit 的 OBJ 解析器 - 忽略注释
【发布时间】:2013-12-30 15:31:28
【问题描述】:

我正在尝试使用 Boost Spirit 库编写一个基本的 OBJ 文件加载器。虽然我使用标准的 std::ifstreams 让它工作,但我想知道是否可以使用内存映射文件对整个文件执行短语解析,因为它似乎提供了 here 发布的最佳性能。

我有以下代码,它似乎运行良好,但是当文件中有注释时它会中断。所以,我的问题是如何使用 Spririt 忽略 OBJ 文件中以“#”开头的注释?

struct vertex {
    double x, y, z;
};

BOOST_FUSION_ADAPT_STRUCT(
                          vertex,
                          (double, x)
                          (double, y)
                          (double, z)
                          )
std::vector<vertex> b_vertices         
boost::iostreams::mapped_file mmap(
                                           path,
                                           boost::iostreams::mapped_file::readonly);
        const char* f = mmap.const_data();
        const char* l = f + mmap.size();


        using namespace boost::spirit::qi;

      bool ok = phrase_parse(f,l,(("v" >> double_ >> double_ >> double_) |
                               ("vn" >> double_ >> double_>> double_)) % eol ,
                               blank, b_vertices);

当没有 cmets 或除顶点/法线以外的任何其他数据时,上述代码运行良好。但是,当有不同类型的数据时,解析器会失败(因为它应该),我想知道是否有办法让它工作而无需重新解析每一行,因为它更慢(在我的测试中几乎是 2.5 倍) .谢谢!

【问题讨论】:

    标签: c++ parsing boost boost-spirit-qi wavefront


    【解决方案1】:

    想到的最简单的方法就是让 cmets 可跳过:

    bool ok = qi::phrase_parse(
            f,l,
             (
                   ("v"  >> qi::double_ >> qi::double_ >> qi::double_) |
                   ("vn" >> qi::double_ >> qi::double_ >> qi::double_)
              ) 
              % qi::eol,
            ('#' >> *(qi::char_ - qi::eol) >> qi::eol | qi::blank), b_vertices);
    

    请注意,如果# 出现在行内某处,这也会“识别”cmets。这可能很好(因为它会使解析失败,除非它是在其他有效输入行上尾随的注释)。

    Live on Coliru

    或者,使用一些凤凰魔法来处理“注释行”,就像处理“vn”或“v”行一样。

    【讨论】:

    • 太棒了!我想知道是否有一种方法可以将其扩展为不仅忽略 cmets,而且忽略除“v”或“vn”之外的任何内容?另外,如何优雅地处理注释行?我认为使用phrase_parse 输出到多种向量类型是不可能的。我能想到的唯一解决方案是使用 boost::variant。请耐心等待,因为我试图了解精神是如何运作的。再次感谢!
    • @rwb 其实这个问题之前也有人问过。只需扫描boost-spiritboost-spirit-qi 的答案,您就会发现完全正确,包括(几种)解析成不同向量的方法。
    • 谢谢!我无法完全找到我正在寻找的东西,或者我可能正在寻找错误的东西。你能给我任何链接,以便我进一步研究吗?
    • 这似乎相关:stackoverflow.com/a/17599370/85371,但我认为这个答案是我记得的:stackoverflow.com/a/17664148/85371
    【解决方案2】:

    我意识到我的评论/帖子不是直接相关的代码,但如果可能的话,我不打算重新发明轮子,我本来想了解这个库。我正在使用手写的 OBJ/Wavefront 加载器,但在我的研究中,我发现了这个库 Tiny Obj Loader。这个库是用 C++ 编写的,除了 C++ STL 之外没有依赖项。它可以很好地处理 Wavefront 规范的边缘情况,而且速度非常快。用户要做的就是将 Tiny OBJ 对象转换为他们的代码。 TinyObjLoader 也被很多项目采用。对于没有直接回答这个问题,我深表歉意,我的愿望是了解这个伟大的图书馆。

    【讨论】:

      猜你喜欢
      • 2012-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-17
      • 2015-01-25
      • 1970-01-01
      相关资源
      最近更新 更多