Russian Qt Forum
Ноябрь 23, 2024, 08:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Голосование
Вопрос: Хотите ли Вы в этом разбираться?
Да, хочу - 4 (22.2%)
Было бы полезно, но нет времени - 5 (27.8%)
Нет, это не окупает изучения - 4 (22.2%)
Та ну его нафиг! - 5 (27.8%)
Ваш вариант - 0 (0%)
Всего голосов: 11

Страниц: 1 ... 5 6 [7] 8   Вниз
  Печать  
Автор Тема: Хотите ли Вы в этом разбираться?  (Прочитано 51958 раз)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #90 : Апрель 27, 2014, 09:52 »

А вот решение с использованием boost.spirit:
Код
C++ (Qt)
#include <string>
#include <map>
#include <fstream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/operators.hpp>
 
using namespace std;
using namespace boost::spirit;
namespace ph = boost::phoenix;
namespace sn = boost::spirit::standard_wide;
 
// ===================================================================================
 
typedef string String;
typedef pair<String, String> Field;
typedef map<String, String> FieldList;
 
struct Entry
{
String type; // article, book, inbook, etc.
String citation_key; // for example: @article{citation_key, ...
FieldList fields; // tag = content
 
void dump()
{
cout << "-------------------------------------" << endl
<< "Type: " << type << endl
<< "Key : " << citation_key << endl;
for( auto v : fields )
cout << v.first << " = " << v.second << endl;
}
};
 
BOOST_FUSION_ADAPT_STRUCT(
Entry,
(String, type)
(String, citation_key)
(FieldList, fields)
)
 
// ===================================================================================
template <class ForwardIterator, class Skipper>
class Parser : public qi::grammar<ForwardIterator, Entry(), Skipper>
{
public:
Parser() : Parser::base_type( m_start, "Parser" )
{
// Документ может состоять из мусора и записей
m_start = m_junk >> m_entry;
 
// Мусор это любые символы кроме @
m_junk = *~qi::lit( '@' );
// Запись начинается с @ и содержит тип записи и тело, которое находится между {}
m_entry = '@' >>
m_type[ ph::at_c<0>( _val ) = _1 ] >>
'{' >> m_body[ ph::at_c<1>( _val ) = ph::at_c<0>( _1 ), ph::at_c<2>( _val ) = ph::at_c<1>( _1 ) ] >> '}';
 
// Тип это несколько букв и/или цифр
m_type = +sn::alnum;
// Тело содержит ключ и набор полей
m_body = m_citation_key >> ',' >> m_fields >> -qi::lit( ',' );
 
// Ключ это любые символы до запятой
m_citation_key = qi::lexeme[ +(~qi::char_( ',' ) - sn::space) ];
// Набор полей состояит из нескольких полей
m_fields = -( m_field % ',' );
 
// Поле содержит ключ и значение
m_field = m_key >> '=' >> m_value;
 
m_key = qi::lexeme[ +(~qi::char_( "=,})" ) - sn::space) ];
m_value = m_quoted | +~qi::char_( ",})#" );
 
m_quoted = qi::lexeme[ ( '"' >> *m_innerQuoteText >> '"' ) | ( '{' >> *m_innerBraceText >> '}' ) ]
[ _val = ph::accumulate(_1, ph::construct<std::string>()) ];
 
m_innerQuoteText %= qi::as_string[ qi::char_('{') >> *(m_innerQuoteText | m_escapedText) >> qi::char_('}') ] | m_quoteText;
m_innerBraceText %= qi::as_string[ qi::char_('{') >> *(m_innerBraceText | m_escapedText) >> qi::char_('}') ] | m_escapedText;
 
m_quoteText = +( m_escapedQuote | ~qi::char_("\"{}") );
m_escapedText = !qi::lit('{') >> +( m_escapedBrace | ~qi::char_("{}") );
 
m_escapedBrace.add
("\\{", '{')
("\\}", '}')
;
m_escapedQuote.add
("\\\"", '"')
;
}
 
private:
typedef boost::fusion::vector<String,FieldList> BodyParam;
 
qi::symbols<char, char> m_escapedBrace;
qi::symbols<char, char> m_escapedQuote;
 
qi::rule<ForwardIterator, Entry(), Skipper> m_start;
qi::rule<ForwardIterator, Skipper> m_junk;
qi::rule<ForwardIterator, Entry(), Skipper> m_entry;
qi::rule<ForwardIterator, String(), Skipper> m_type;
qi::rule<ForwardIterator, BodyParam(), Skipper> m_body;
qi::rule<ForwardIterator, String(), Skipper> m_citation_key;
qi::rule<ForwardIterator, FieldList(), Skipper> m_fields;
qi::rule<ForwardIterator, Field(), Skipper> m_field;
qi::rule<ForwardIterator, String(), Skipper> m_key;
qi::rule<ForwardIterator, String(), Skipper> m_value;
qi::rule<ForwardIterator, String(), Skipper> m_quoted;
qi::rule<ForwardIterator, String()> m_innerQuoteText;
qi::rule<ForwardIterator, String()> m_innerBraceText;
qi::rule<ForwardIterator, String()> m_quoteText;
qi::rule<ForwardIterator, String()> m_escapedText;
};
 
// ===================================================================================
 
template<class ForwardIterator, class Skipper, class Container>
inline bool read( ForwardIterator first, ForwardIterator last, Skipper& s, Container& e,
 boost::enable_if<boost::is_same<typename Container::value_type, Entry> >* /*dummy*/ = NULL )
{
Parser<ForwardIterator, Skipper> p;
return qi::phrase_parse(first, last, *p, s, e );
}
 
// ===================================================================================
 
int main( int argc, char *argv[] )
{
if( argc < 2 )
{
cerr << "Using: bibparser file.bib" << endl;
return 1;
}
 
string filename = argv[ 1 ];
cout << "Parsing file: " << filename << endl;
 
ifstream is( filename );
is.unsetf( ios_base::skipws );
if( !is )
{
cerr << "Error open source file" << endl;
return 1;
}
 
boost::spirit::istream_iterator beg( is );
boost::spirit::istream_iterator end;
 
deque<Entry> e;
 
auto space = sn::space | '%' >> *(qi::char_ - qi::eol) >> qi::eol;
 
cout << "result = " << read( beg, end, space, e ) << endl;
 
for( auto v : e )
v.dump();
 
return 0;
}
 
« Последнее редактирование: Апрель 27, 2014, 14:14 от Old » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #91 : Апрель 27, 2014, 13:13 »

Погонял у себя все три варианта: мой, old и igors.

Всё же на мой взгляд, решение с использованием Spirit самоё ёмкое и гибкое. Надо будет украсть его с небольшими переделками)

Что касается производительноти, то сделал три замера на время парсинга одного своего старого bib файла, где 126 записей.
Результаты такие:
Код
C++ (Qt)
int main()
{
 
   const char * filename = "bibliography.bib";
 
   std::ifstream in(filename);
   std::ostringstream oss;
   oss << in.rdbuf();
 
   std::string buff = oss.str();
   std::list<bibtex_entry> entrys;
 
   auto start = std::chrono::high_resolution_clock::now();
   bibtex_parser::parse(buff.cbegin(), buff.cend(), entrys);
   auto stop = std::chrono::high_resolution_clock::now();
   auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop-start).count();
 
   std::cout << "m_ax: parsing time, (ms) = " << duration << std::endl;
   std::cout << "number of entries = " << entrys.size() << std::endl << std::endl;
 
 
 
   std::vector<Entry> e;
 
   auto space = sn::space | '%' >> *(qi::char_ - qi::eol) >> qi::eol;
 
   start = std::chrono::high_resolution_clock::now();
   read( buff.cbegin(), buff.cend(), space, e );
   stop = std::chrono::high_resolution_clock::now();
   duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop-start).count();
 
   std::cout << "old: parsing time, (ms) = " << duration << std::endl;
   std::cout << "number of entries = " << e.size() << std::endl << std::endl;
 
 
 
   QFile bibFile(filename);
   if (!bibFile.open(QIODevice::ReadOnly))
       return -1;
 
   QList <CBibTag> theBib;
   CBibReader reader(bibFile);
 
   start = std::chrono::high_resolution_clock::now();
   while (reader.ReadLine()) {
       int type;
       QString citeKey;
       if (!reader.BibStart(type, citeKey)) continue;
 
       theBib.push_back(CBibTag(type, citeKey));
 
   }
   stop = std::chrono::high_resolution_clock::now();
   duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop-start).count();
 
   std::cout << "igors: parsing time, (ms) = " << duration << std::endl;
   std::cout << "number of entries = " << theBib.size() << std::endl << std::endl;
 
   return 0;
}
 

Код
Bash
m_ax: parsing time, (ms) = 26
number of entries = 126
 
old: parsing time, (ms) = 9
number of entries = 126
 
igors: parsing time, (ms) = 11
number of entries = 123
 
---------------------------------------------------------------------------
m_ax: parsing time, (ms) = 22
number of entries = 126
 
old: parsing time, (ms) = 5
number of entries = 126
 
igors: parsing time, (ms) = 10
number of entries = 123
 
---------------------------------------------------------------------------
m_ax: parsing time, (ms) = 20
number of entries = 126
 
old: parsing time, (ms) = 7
number of entries = 126
 
igors: parsing time, (ms) = 13
number of entries = 123
 
 

Пока не стал разбираться почему у igors выдаёт только 123 записи вместо 126..
Вечером ещё погоняю и отпишусь.)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #92 : Апрель 27, 2014, 14:15 »

Я бы не стал доверять замерам сделанным
 auto start = std::chrono::high_resolution_clock::now();



Недавеча только человек выкладывал в тырнетах вопрос:

два цикла делаеют одно и тоже. Первый цикл - сырые указатели. Второй - смартпоинтеры

Смартпоинтеры оказались быстрее..

Затем меняем местами циклы: сначала по смартам, потом по сырым - сырые оказались быстрее.

Проявляется стабильно.

Муть какая то.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #93 : Апрель 27, 2014, 16:52 »

Что касается производительноти, то ...
Здесь я, признаться, удивлен. Ожидал что мой вариант будет медленнее минимум на порядок - ведь QString довольно расходен/затратен.

Пока не стал разбираться почему у igors выдаёт только 123 записи вместо 126..
Наверняка это я где-то насвистел. Не суть, все требует отладки/тестирования, это нормально. Важно что показаны 3 разных подхода к решению одной задачи - и это интересно. Кстати - а где Ваш?

Я бы не стал доверять замерам сделанным
Ну чего Вы все о мелочах? Что язык Вы знаете изрядно - всем ясно. А вот во что это выливается.. Ваше "технологическое" решение не хотите показать?  Улыбающийся
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #94 : Апрель 27, 2014, 18:02 »

Цитировать
Наверняка это я где-то насвистел.
Конечно Вы)

Цитировать
Не суть, все требует отладки/тестирования, это нормально.
Да, а если отлаживать Ваш код придётся кому-нибудь другому? Или слегка изменить функциональность?
Вот здесь как нельзя кстатии задать этот вопрос, которой стал причиной этой темы..

Цитировать
Кстати - а где Ваш?

Свой я уже показывал:
Код
C++ (Qt)
#ifndef BIBTEX_PARSER_H
#define BIBTEX_PARSER_H
 
#include <string>
 
#include <boost/algorithm/string/trim.hpp>
#include <boost/regex.hpp>
#include <boost/xpressive/xpressive.hpp>
#include <boost/tokenizer.hpp>
 
#include "core/spec_token_functions.h"
#include "core/skipper_iterator.h"
#include "core/bibtex_entry.h"
 
namespace bibmake {
 
namespace core {
 
class bibtex_parser
{
public:
   typedef std::string string_type;
 
   template <class Iterator, class Container>
   static size_t parse(Iterator begin, Iterator end, Container & entry_list)
   {
       if (begin == end)
           return 0;
 
       using namespace boost::xpressive;
       basic_regex<Iterator> comment = (~as_xpr('\\') | bos) >> (s1 = ('%' >> *(~_n) >> (_n | eos)));
 
       boost::regex start_entry_regex("@(\\w+)[\\s\\t]*\\{");
 
       basic_regex<Iterator> field = *space >> (s1 = +_w) >> *space >> '=' >> (s2 = +_);
 
       quote_list<char> quotes('{', '}');
       quotes.add_quote('"', '"');
       quote_extractor<char> qextractor(quotes);
 
       skipper_iterator<Iterator> _begin(begin, end, comment);
       skipper_iterator<Iterator> _end(end, end, comment);
 
       boost::match_results<skipper_iterator<Iterator>> what;
       size_t counter(0);
       while (boost::regex_search(_begin, _end, what, start_entry_regex))
       {
           bibtex_entry entry;
           entry.set_type(what.str(1));
 
           _begin = what[1].second;
           string_type fields;
           if (!qextractor(_begin, _end, fields))
           {
               _begin = what[1].second;
               continue;
           }
 
           boost::tokenizer<spec_char_separator<char>> tok(fields, spec_char_separator<char>(",", "", quotes));
           auto it = tok.begin();
           if (it == tok.end())
                continue;
 
           entry.set_key(boost::algorithm::trim_copy(*it));
           ++it;
 
           for (; it != tok.end(); ++it)
           {
               smatch w;
               if (regex_search(*it, w, field))
               {
                   string_type tag = w.str(1);
                   string_type content = w.str(2);
                   auto first = w[2].first;
                   auto second = w[2].second;
                   if (!qextractor(first, second, content))
                       content = w.str(2);
                   boost::algorithm::trim(content);
                   if (!content.empty())
                       entry.add_field(tag, content);
               }
           }
           entry_list.push_back(entry);
           ++counter;
       }
 
       return counter;
   }
 
};
 
} /* namespace core */
 
} /* namespace bibmake */
 
#endif // BIBTEX_PARSER_H
 

Сейчас ещё поковыряю тесты..
« Последнее редактирование: Апрель 27, 2014, 18:11 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #95 : Апрель 27, 2014, 18:04 »

Я бы не стал доверять замерам сделанным
 auto start = std::chrono::high_resolution_clock::now();

Ну мне главное хотя бы по порядку величины время оценить)
Даже не само время, а то, как они соотносятся между разными реализациями, хотя бы примерно..   
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #96 : Апрель 27, 2014, 18:12 »

Свой я уже показывал:
Вы уверены что это весь код? Не вижу "приемника" - т.е. структур должны заполняться (получать считанные данные)
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #97 : Апрель 27, 2014, 18:21 »

Свой я уже показывал:
Вы уверены что это весь код? Не вижу "приемника" - т.е. структур должны заполняться (получать считанные данные)

Это код парсера. Плюс есть ещё bibtex_entry. Приёмник данных это любой контейнер (например std::list<bibtex_entry>) у которого есть метод push_back.
skipper_iterator Вы уже видели (изменилось только то, что сейчас он использует не regex, а xpressive), о расширениях boost::tokenizer мы уже тоже говорили в теме "разбор QString"

Вот bibtex_entry:
Код
C++ (Qt)
#ifndef BIBTEX_ENTRY_H
#define BIBTEX_ENTRY_H
 
#include <string>
#include <map>
#include <boost/algorithm/string/case_conv.hpp>
 
namespace bibmake {
 
namespace core {
 
class bibtex_entry
{
public:
   typedef std::string string_type;
   typedef std::map<string_type, string_type> fields_type;
   typedef typename fields_type::size_type size_type;
   typedef typename fields_type::const_iterator const_iterator;
 
   bibtex_entry() {}
 
   string_type key() const { return m_key; }
 
   string_type type() const { return m_type; }
 
   void set_type(const string_type & type)
   {
       m_type = boost::algorithm::to_lower_copy(type);
   }
 
   void set_key(const string_type & key)
   {
       m_key = key;
   }
 
   void add_field(const string_type & tag, const string_type & content)
   {
       m_fields[boost::algorithm::to_lower_copy(tag)] = content;
   }
 
   void erase(const string_type & tag)
   {
       m_fields.erase(boost::algorithm::to_lower_copy(tag));
   }
 
   string_type content(const string_type & tag) const
   {
       auto it = m_fields.find(boost::algorithm::to_lower_copy(tag));
       return (it != m_fields.end()) ? it->second : string_type();
   }
 
   bool is_contains(const string_type & tag) const
   {
       return (m_fields.find(boost::algorithm::to_lower_copy(tag)) != m_fields.end());
   }
 
   size_type size() const { return m_fields.size(); }
 
   bool empty() const { return m_fields.empty(); }
 
   const_iterator begin() const { return m_fields.begin(); }
 
   const_iterator end() const { return m_fields.end(); }
 
private:
   string_type m_key;
   string_type m_type;
   fields_type m_fields;
};
 
} /* namespace core */
 
} /* namespace bibmake */
 
#endif // BIBTEX_ENTRY_H
 
 

Или о каком приёмнике данных идёт речь?
« Последнее редактирование: Апрель 27, 2014, 18:24 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #98 : Апрель 27, 2014, 20:12 »

Немного наврал с результатами теста..
В предыдущем варианте у igors при парсенге я случайно убрал строчку
Код
C++ (Qt)
if (!reader.ReadBibTag(theBib.back()))
                   theBib.pop_back();
 
 
где происходит заполнение записи..

Сейчас результаты такие:
Код
Bash
m_ax: parsing time, (ms) = 18
number of entries = 126
 
old: parsing time, (ms) = 4
number of entries = 126
 
igors: parsing time, (ms) = 22
number of entries = 123
 
-------------------------------------------------------------------
m_ax: parsing time, (ms) = 20
number of entries = 126
 
old: parsing time, (ms) = 12
number of entries = 126
 
igors: parsing time, (ms) = 16
number of entries = 123
 
-------------------------------------------------------------------
m_ax: parsing time, (ms) = 18
number of entries = 126
 
old: parsing time, (ms) = 9
number of entries = 126
 
igors: parsing time, (ms) = 21
number of entries = 123
 
 

Во-вторых, igors, у Вас поля (content) содержатся внутри  цитат, а они должны быть извлечены из них { .. }
vмелочь, но тем не менее..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #99 : Апрель 27, 2014, 20:25 »

Ну раз пошла такая пьянка, то решил набросать парсер для 3d-файлов obj.
Весь парсер - это 40 строк кода!
Код
C++ (Qt)
template <class ForwardIterator, class Skipper>
class ObjParser : public qi::grammar<ForwardIterator, Skipper, ModelData()>
{
public:
ObjParser() : ObjParser::base_type( m_start )
{
using boost::phoenix::at_c;
 
m_start = *(
m_vertex_lst[ at_c<0>(_val) = _1 ] |
m_normal_lst[ at_c<1>(_val) = _1 ] |
m_texcoord_lst[ at_c<2>(_val) = _1 ] |
m_face_lst[ at_c<3>(_val) = _1 ]
) >> qi::eoi;
 
m_vertex_lst = m_vertex >> *m_vertex;
m_vertex = lit( "v" ) >> double_[ at_c<0>(_val) = _1 ] >> double_[ at_c<1>(_val) = _1 ] >> double_[ at_c<2>(_val) = _1 ] >> -double_[ at_c<3>(_val) = _1 ];
 
m_normal_lst = m_normal >> *m_normal;
m_normal = lit( "vn" ) >> double_[ at_c<0>(_val) = _1 ] >> double_[ at_c<1>(_val) = _1 ] >> double_[ at_c<2>(_val) = _1 ];
 
m_texcoord_lst = m_texcoord >> *m_texcoord;
m_texcoord = lit( "vt" ) >> double_[ at_c<0>(_val) = _1 ] >> double_[ at_c<1>(_val) = _1 ] >> -double_[ at_c<2>(_val) = _1 ];
 
m_face_lst = m_face >> *m_face;
m_face = lit( "f" ) >> m_index >> m_index >> m_index >> *m_index;
m_index = int_[ at_c<0>(_val) = _1 ] >> -( '/' >> -int_[ at_c<1>(_val) = _1 ] >> -( '/' >> int_[ at_c<2>(_val) = _1 ] ) );
}
 
private:
qi::rule<ForwardIterator, Skipper, ModelData()> m_start;
qi::rule<ForwardIterator, Skipper, VertexList()> m_vertex_lst;
qi::rule<ForwardIterator, Skipper, Vertex()> m_vertex;
qi::rule<ForwardIterator, Skipper, NormalList()> m_normal_lst;
qi::rule<ForwardIterator, Skipper, Normal()> m_normal;
qi::rule<ForwardIterator, Skipper, TexCoordList()> m_texcoord_lst;
qi::rule<ForwardIterator, Skipper, TexCoord()> m_texcoord;
qi::rule<ForwardIterator, Skipper, FaceList()> m_face_lst;
qi::rule<ForwardIterator, Skipper, Face()> m_face;
qi::rule<ForwardIterator, Skipper, Index()> m_index;
};
 

Парсер разбирает следующие блоки: вертексы, нормали, текстурные координаты, индексы поверхностей (учитывая необязательные поля).
Причем, индексы обрабатывает все: вертексов, нормалей и тестурных координат.
Нормально обрабатывает отсутствие каких-то индексов:
f 1 2 3
f 1/1 2/2 3/3
f 1/1/1 2/2/2 3/3/3
f 1//1 2//2 3//3
Точек в поверхности может быть больше трех.
Не надо говорить, что с комментариями тоже все в порядке. Улыбающийся

Этот парсер заполняет структуру ModelData:
Код
C++ (Qt)
struct Vertex
{
explicit Vertex() : x( 0. ), y( 0. ), z( 0. ), w( 1. ) {}
explicit Vertex( double vx, double vy, double vz, double vw = 1 ) : x( vx ), y( vy ), z( vz ), w( vw ) {}
 
double x;
double y;
double z;
double w;
};
 
struct Normal
{
explicit Normal() : x( 0. ), y( 0. ), z( 0. ) {}
explicit Normal( double vx, double vy, double vz ) : x( vx ), y( vy ), z( vz ) {}
 
double x;
double y;
double z;
};
 
struct TexCoord
{
explicit TexCoord() : u( 0. ), v( 0. ), w( 0. ) {}
explicit TexCoord( double vu, double vv, double vw = 0 ) : u( vu ), v( vv ), w( vw ) {}
 
double u;
double v;
double w;
};
 
struct Index
{
explicit Index() : v( -1 ), vn( -1 ), vt( -1 ) {}
explicit Index( int vv, int vvn, int vvt ) : v( vv ), vn( vvn ), vt( vvt ) {}
 
int v;
int vn;
int vt;
};
 
typedef deque<Vertex> VertexList;
typedef deque<Normal> NormalList;
typedef deque<TexCoord> TexCoordList;
typedef deque<Index> Face;
typedef deque<Face> FaceList;
 
struct ModelData
{
VertexList v;
NormalList vn;
TexCoordList vt;
FaceList f;
};
 

Если нужно обрабатывать другие данные из формата, то правила для них легко добавляются в разбор. /* Я хотел вначале показать разбор только вертексов, но остальное легко добавилось в процессе. Улыбающийся */
« Последнее редактирование: Апрель 27, 2014, 20:39 от Old » Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #100 : Апрель 27, 2014, 21:54 »

Да, Spirit рулит)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #101 : Апрель 28, 2014, 08:27 »

Причем, индексы обрабатывает все: вертексов, нормалей и тестурных координат.
Нормально обрабатывает отсутствие каких-то индексов:
Не вижу как - ведь должно быть 3 контейнера индексов (позиция, текстура, нормаль). Пара противных мелочей

1) строки могут быть склеены, напр полигон с 5 вертексами может быть записан так
Цитировать
f 1/1 2/2 3/3  \
4/6 6/7 5/4 

2) возможны такие индексы
Цитировать
f -1 -2 -3
Это значит "от текущего", напр на данный момент прочитано 100 позиций, значит реальные индексы (99, 98, 97). К сожалению не удается отложить это на потом т.к. "текущий" может измениться

Но все равно - впечатляет, круто

Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #102 : Апрель 28, 2014, 08:51 »

Не вижу как - ведь должно быть 3 контейнера индексов (позиция, текстура, нормаль).
Информация по каждому индексу хранится в структуре Index, а они уже лежат в контейнере.

1) строки могут быть склеены
Это не проблема. Улыбающийся

2) возможны такие индексы
В спецификации по формату я такого не увидел, хотя я смотрел его через строчку.
Покажите, где про это написано.

А так, это тоже не проблема. Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #103 : Апрель 28, 2014, 09:25 »

Информация по каждому индексу хранится в структуре Index, а они уже лежат в контейнере.
Ага, вижу. Но тут дека нехороша т.к. полигоны с большим числом вертексов редки. А для стандартных треугольников затрачивается 512 (gсс) байт для хранения 3 * 3 * sizeof(int). Вообще оbj файл задуман для хранения 3 независимых "пространств", поэтому лучше 3 контейнера.

Это не проблема. Улыбающийся
...
А так, это тоже не проблема. Улыбающийся
Верю, но как? Улыбающийся Было бы интересно посмотреть

Покажите, где про это написано.
Напр здесь http://www.martinreddy.net/gfx/3d/OBJ.spec
Цитировать
   v is a reference number for a vertex on the line. A minimum of two
    vertex numbers are required. There is no limit on the maximum.
    Positive values indicate absolute vertex numbers. Negative values
    indicate relative vertex numbers.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #104 : Апрель 28, 2014, 09:31 »

Но тут дека нехороша
Вы можете изменить тип контейнера на любой желаемый, больше ничего менять не придется.

Верю, но как? Улыбающийся Было бы интересно посмотреть
Когда доберусь до компьютера переделаю и покажу.
Склейку через '\' уже сделал, просто добавил в правила скипера выкусываение этого символа. Улыбающийся
Записан
Страниц: 1 ... 5 6 [7] 8   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.274 секунд. Запросов: 25.