春到来! それは新しい C++ 出会いの季節ですね!
GW も間近に迫ってひと段落してきたこの季節, wavefront .obj モデルをロードして新しい自分にチャレンジしたくなりますね!
たとえばマインクラフトデータを Mineways を使って .obj にエクスポートしたのを自分のツールで読んでみたいですね!
でも .obj のロードはクセがあってパーサ書くのめんどい... と思っていたズボラなアナタに朗報!
世界中のみんなに愛され使われていると言っても過言ではない, シングルヘッダオンリーな .obj ローダである TinyObjLoader で始めて周りのみんなの視線を独り占めしましょう!
2016 年版では C++ コードのデトックス も適用してキレイさとダイエットにも励みました!
https://github.com/syoyo/tinyobjloader/tree/develop
(2016 年版はもうちょっとテストとダイエットに励みたいので, まだ develop
branch にあります.
)
取得する
$ git clone https://github.com/syoyo/tinyobjloader.git
$ cd tinyobjloader
$ git fetch
$ git checkout -b develop origin/develop
あとは tiny_obj_loader.h
を自分のプロジェクトにコピーして完了です.
データ構造
2016 年版からちょっと変わったよ!
attrib_t
typedef struct {
std::vector<float> vertices; // 'v'
std::vector<float> normals; // 'vn'
std::vector<float> texcoords; // 'vt'
} attrib_t;
attrib_t
には頂点アトリビュートである vertices
, normals
and texcoords
の一次元配列が格納されています. これはどのシェイプ(shape_t
)にも共通です.
shape_t
typedef struct {
std::vector<index_t> indices;
std::vector<unsigned char>
num_vertices; // The number of vertices per face. Up to 255.
std::vector<int> material_ids; // per-face material ID
std::vector<tag_t> tags; // SubD tag
} mesh_t;
typedef struct {
std::string name;
mesh_t mesh;
} shape_t;
shape_t
は個々のシェイプ(形状)データが格納されます. シェイプは o
もしくは g
ごとに作成されます.
シェイプでは頂点インデックス(.obj で f
行で定義されるインデックス. vertex, normal, texcoord それぞれ. 定義されていないインデックスには 0x80000000(-2147483648) が設定されます)と, face の面数(三角形の場合は 3, 四角形の場合は 4), per-face でのマテリアル ID を持ちます.
tags
は optional で, OpenSubdiv 用の拡張です. 上級者向け.
サンプル
OpenGL で描画するサンプルが https://github.com/tinyobjloader/tinyobjloader/tree/master/examples/viewer にあります.