2

I'm trying to write a basic OBJ file loader using the Boost Spirit library. Although I got it working using the standard std::ifstreams, I'm wondering if it's possible to do a phrase_parse on the entire file using a memory mapped file, since it seems to provide the best performance as posted here.

I have the following code, which seems to work well, but it breaks when there is a comment in the file. So, my question is how do you ignore a comment that starts with a '#' in the OBJ file using Spririt?

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);

The above code works well when there are no comments or any other data except vertices/normals. But when there is a different type of data the parser fails (as it should) and I'm wondering if there is a way to make it work without going back to parsing every line as it is slower (almost 2.5x in my tests). Thank you!

Community
  • 1
  • 1
rwb
  • 621
  • 1
  • 12
  • 21

2 Answers2

3

The simplest way that comes to mind is to simply make comments skippable:

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);

Note that this also 'recognizes' comments if # appears somewhere inside the line. This is probably just fine (as it would make the parsing fail, unless it was a comment trailing on an otherwise valid input line).

See it Live on Coliru

Alternatively, use some phoenix magic to handle "comment lines" just as you handle a "vn" or "v" line.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Wonderful! I'm wondering if there is a way to extend this to ignore not just comments but anything other than 'v' or 'vn'? Also, how to elegantly handle the comment lines? I don't think it's possible to output to multiple vector types using phrase_parse. The only solution I can think is using boost::variant. Please bear with me since I'm trying to understand how spirit works. Thanks again! – rwb Dec 30 '13 at 21:58
  • @rwb In fact, this question has been asked before. Just scan the [tag:boost-spirit] and [tag:boost-spirit-qi] answers and you'll find **exactly** that, including (several) ways to parse into different vectors. – sehe Dec 30 '13 at 22:16
  • Thanks! I couldn't exactly find what I was looking for or may be I'm searching for the wrong thing. Can you give me any links so I could look into it further? – rwb Dec 30 '13 at 22:40
  • 1
    This seems related: http://stackoverflow.com/a/17599370/85371, but I think this answer is what I remembered: http://stackoverflow.com/a/17664148/85371 – sehe Dec 30 '13 at 22:51
0

I realize that my comment/post is not directly related code but I'm for not reinventing the wheel if possible and I would have wanted to know about this library. I was working with a handwritten OBJ/Wavefront loader but in my research I found this library Tiny Obj Loader. This library is written C++ with no dependencies excetp C++ STL. It handles the edge cases for the Wavefront spec fairly well and it is very fast. The thing that the user has to do is convert the Tiny OBJ objects into their code. TinyObjLoader has been adopted by quite a number of projects as well. I do apologize for not directly answering the question and my desire is to get knowledge about this great library out.

DannyK
  • 1,342
  • 16
  • 23