boost spirit qiでmqo(メタセコイア)ファイル解析&とりあえず描画

ポリゴンが描画できるようになったので、今度はモデルデータファイルを読み込んで表示してみる。モデルデータは、データ作成と解析が簡単にできるmqoファイル(メタセコイアの出力ファイル、テキスト形式)を使用する。

とりあえずmqoファイル表示
とりあえずmqoファイル表示

ファイル解析
Boost Spirit ライブラリのQiを使って解析。かなり特殊な使い方をするライブラリですが興味があったので使ってみます。主に使う関数は
bool boost::spirit::qi::parse(開始, 終了, 文法, 属性,,,属性);
開始終了: イテレータで解析範囲指定
文法: 解析方法、一致していればtrueを返す
属性: 解析結果を受け取る。詳しくはソースコードで

spiritの準備

#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
using qi::char_;
using qi::int_;
using qi::float_;
using qi::space;
using qi::blank;
using qi::unused;

includeとコードを短縮するための定義。

mqoヘッダの解析 単純なparse使用例 

//ヘッダチェック
if( !qi::parse(first, last,
			"Metasequoia Document\r\nFormat Text Ver 1.0\r\n")
){
	return false;
}

指定した文字列と一致しているかどうか調べてmqoファイル判定。

空白スキップ 簡単な文法と属性の使用例 

//空白スキップ
std::string attr_str;//属性実験用
if( !qi::parse(first, last, *space, attr_str) ){
	return false;//エラー
}

space : ライブラリに用意されている文法、空白文字(タブ、改行も含む)を表す
* : 演算子 *spaceは0回以上空白文字が続く
attr_str : 属性 *spaceの結果(文法に一致した空白文字列)

mqoチャンクの解析 >>演算子と属性での数値取得 

int mat_num = 0;
if( !qi::parse(first, last,
		"Material" >> +blank >>int_ >> *blank >> "{" >> eline,	//rule
					// "Material"のような値(リテラル)には属性がないので属性を書かない
		unused,		// +blankの属性
		mat_num,	// qi::int_の属性
		unused)		// *blankの属性 なくてもいい
){
	return false;
}

Materialチャンクの解析。>>は複数の文法を連結する演算子。
Material文字列の後に空白(blank、改行含まず)1回以上、その後に整数値(int_)、その後・・・。
>>で連結した場合、それぞれの項に対応する属性を複数引数で指定し、結果を受け取る。unusedは結果を受け取らない属性。int_に対応する属性でマテリアルの個数を取得。
elineはライブラリではなく独自に定義した文法、改行コード(\r\n)を表す。

“文字列”の解析 独自の文法定義 

//-----------------------------------------------------
//"文字列" 属性は""で囲まれた部分
template<typename Iterator, typename A1=qi::unused_type>
struct dqstring : qi::grammar<Iterator, A1()>
{
    dqstring() : dqstring::base_type(r)
    {
        r = '\"' >> *(char_ - char_('\"')) >> '\"';
    }
	//'\"'の項は、属性がないため属性A1には含まれない(たぶん)
	qi::rule<Iterator, A1()> r;
};

すでにある文法を組み合わせて新しい文法を定義できる。
dqstringはC言語などで使う”文字列”表記を表現する文法定義。

独自文法を使った解析

endline<Iterator> eline;
dqstring<Iterator, std::string> dqstr;

// Object ”objname" {\r\n
std::string obj_name;
if( !qi::parse(first, last,
			"Object" >> +blank >> dqstr >> *blank >> "{" >> eline,	//rule
			unused,		// +blankの属性
			obj_name)	// dqstrの属性
){
	return false;
}

定義した文法を使うには、インスタンス化してparse関数で使用。spaceやint_などはboostライブラリ側でインスタンス化した文法。

mqoファイルの解析
今回はspiritライブラリの基本的な部分のみ使用してmqoファイルを解析しました。他にもいろいろな機能がありますが、特に必要ではなく、無理に使っても意味不明なソースコードになりそうなので使いませんでした。
とりあえず使ってみましたが

  • コンパイルが遅すぎる!
  • 実行速度も遅い!

たぶん今後使うことはなさそうです。
(コンパイル40秒、数Mのファイル解析に約1分)

解析結果の表示
とりあえず表示してみる。最初のObjectのみ表示、テクスチャは固定。
mqoファイルをいくつか解析して表示すると、文法間違いを多数発見。その都度修正。
それなりに頂点数の多い複雑なモデルも何とか表示できているみたい。
次は、複数オブジェクトの表示と姿勢計算、テクスチャ対応の予定。

サンプルダウンロード とりあえずmqoファイル表示

Boost C++ Library
Metasequoia 3Dポリゴンモデラー

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

認証:数字を入力してください(必須) * Time limit is exhausted. Please reload CAPTCHA.