XSDでCOLLADA

COLLADAのとっかりはこちら。COLLADA DOMを使った3Dモデルデータの読み込み

XSDはこちら。CodeSynthesis XSD

おおまかな流れとしては,

  • XSDをVisual Studioに導入する
  • COLLADA 1.4.1 Schema (includes OpenGL ES Profile)をローカルに保存する。
  • 保存したSchemaをソリューションに追加して,XSDでC++パーサにコンパイルする。
  • コンパイルオプションはこちらにあるように–parts 3等で分割指定が必須。
  • コンパイルしたC++パーサをソリューションに追加する。
  • COLLADAの読み込み部分を作成する。1行で読み込めるが初めから高速化に対応した方がよい。
  • OpenGLの表示処理を作成する。パース結果の利用方法(triangleのみ描画)は下記。
using namespace COLLADASchema;
const COLLADA::library_geometries_sequence& g = bhc->m_dae_preview->library_geometries();
for (COLLADA::library_geometries_const_iterator i = g.begin(); i != g.end(); i++) {
  const library_geometries::geometry_sequence& h = (*i).geometry();
  for (library_geometries::geometry_const_iterator j = h.begin(); j != h.end(); j++) {
    const mesh::triangles_sequence& t = (*j).mesh()->triangles();
    for (mesh::triangles_const_iterator k = t.begin(); k != t.end(); k++) {
      unsigned int numberOfInputs = (*k).input().size();
      unsigned int numberOfTriangles = (*k).p()->size() / numberOfInputs;
      unsigned int offset = 0;
      int texoffset = -255;
      int noroffset = -255;
      for (triangles::input_const_iterator l = (*k).input().begin(); l != (*k).input().end(); l++) {
        if ((*l).semantic() == "VERTEX")
          offset = (*l).offset();
        if ((*l).semantic() == "TEXCOORD")
          texoffset = (*l).offset();
        if ((*l).semantic() == "NORMAL")
          noroffset = (*l).offset();
      }
      for (int ii = 0; ii < numberOfTriangles; ii++) {
        int index = (*k).p()->at(ii * numberOfInputs + offset);
        if (noroffset == -255) {
          glNormal3f(
            (*j).mesh()->source().at(1).float_array()->at(index * 3),
            (*j).mesh()->source().at(1).float_array()->at(index * 3 + 1),
            (*j).mesh()->source().at(1).float_array()->at(index * 3 + 2)
          );
        } else {
          int norindex = (*k).p()->at(ii * numberOfInputs + noroffset);
          glNormal3f(
            (*j).mesh()->source().at(1).float_array()->at(norindex * 3),
            (*j).mesh()->source().at(1).float_array()->at(norindex * 3 + 1),
            (*j).mesh()->source().at(1).float_array()->at(norindex * 3 + 2)
          );
        }
        if (texoffset != -255) {
          int texindex = (*k).p()->at(ii * numberOfInputs + texoffset);
          glTexCoord2f(
            (*j).mesh()->source().at(2).float_array()->at(texindex * 2),
            (*j).mesh()->source().at(2).float_array()->at(texindex * 2 + 1)
          );
        }
        glVertex3f(
          (*j).mesh()->source().at(0).float_array()->at(index * 3),
          (*j).mesh()->source().at(0).float_array()->at(index * 3 + 1),
          (*j).mesh()->source().at(0).float_array()->at(index * 3 + 2)
        );
      }
    }
  }
}

m_dae_previewは,

std::auto_ptr<COLLADASchema::COLLADA>   m_dae_preview;

というデータメンバで,COLLADAをロードした結果を保持している。

COLLADA DOMより少し速度が遅いし,分かりやすさもないので,COLLADAをパースしてみたい人は素直にCOLLADA DOMを使った方がよいかも。

コメント

コメントを残す

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