HobbyistBox

趣味事をつらつらと

【FBX to OBJ】02 FBXファイルを開こう

はじめに

今回から FBXSDK を使い実際にプログラミングをしていきたいと思います。

目標

今回は必要な情報(頂点座標や法線など)を取得する前段階、ファイルを開き情報にアクセスできるようにするまでを目標にしたいと思います。

環境

作業環境は

  • Windows10
  • VisualStudio 2015 Community
    • C++ コンソールアプリ
  • FBXSDK ver.20161_2
  • Blender 2.76

で進めます。

読み込む FBX ファイル

何はなくともまずは読み込む FBX ファイルが必要です。
ご自身が作成された 3D作品を使用してもいいのですが、何千、何万ポリゴンもあるファイルでは結果を追っていくのが大変なので前回作成した .objファイル同様 Cube が一つだけあるファイルを作成します。

Blender を起動し Cube が一つだけの状態で File >> Export >> FBX(.fbx) を選択、名前を付けてエクスポート。
プログラムからファイルを開くことになるので Cドライブ直下や、プロジェクトディレクトリにエクスポートするとファイルパスが短くてすみます。
また、ファイル名は半角英数で指定してください。

ではプログラミングをしていきましょう。

FBX Manager

SDKのメモリマネージメントをするシングルトンクラス FbxManager を作成します。
FBXSDK の API、クラスは fbxsdk ネームスペース内にあります。

#include<iostream>
#include<fbxsdk.h>

using namespace fbxsdk;

int main(int argc, char* argv[]) {
  FbxManager* manager = FbxManager::Create();

  if(manager == NULL) {
    std::cout << "Manager Create fail" << std::endl;
    return 0;
  }

  // ここに処理を追加していきます。

  manager->Destroy();
  return 1;
}

FbxManager::Create() は成功すればインスタンスを、失敗すれば NULL を返します。

処理が終わり不要になったら Destroy() 関数を呼びます。
すると、マネージャーに関連付けられたクラスやメモリも開放されます。

FBX Importer

FBX ファイルを読み込むための Importer クラスを作成、読み込みを行います。

FbxImporter* importer = FbxImporter::Create(manager, "");

const char* filePath = "C:\\Cube.fbx";

if(!importer->Initialize(filePath)) {
  std::cout << "Importer Initialize fail" << std::endl;
  manager->Destroy();

  return 0;
}

// ここに処理を追加していきます。

FbxImporter::Create() 関数は引数に FbxManager* と char* の名前を指定します。今回、名前は空文字列を指定しています。
成功すればインスタンスが返ります。失敗した場合なのですが、何が返るか調べきれませんでした。おそらく FbxManager と同じく NULL だとは思うのですが・・・。

Importer の作成ができたら、次に ファイルパスを引数にimporter->Initialize() 関数を呼びます。
この関数が実質のファイル読み込み処理となります。
成功すれば true を、失敗すると false が返ります。

今回はCドライブ直下に FBX ファイルを保存したのでファイルパスは C:\\Cube.fbx です。

FBX Scene

読み込んだファイルからシーン情報をインポートするため、FbxSceneクラスを作成し、インポート処理をします。

シーンとは3D空間を構成するオブジェクト(メッシュ、ライト、カメラなど)を格納するコンテナです。
つまり、FBX ファイルを読み込むという工程でいえば最後になります。

FbxScene* scene = FbxScene::Create(manager, "");

if(!importer->Import(scene)) {
  std::cout << "Import Scene fail" << std::endl;
  manager->Destroy();

  return 0;
}

importer->Destroy();

// ここに処理を追加していきます。

FbxScene::Create() 関数も FbxImporter 同様 FbxManager* と char* の名前を指定します。
成功すればインスタンスが返ります。こちらも失敗した場合の戻り値が不明のため NULL と仮定します。

作成した Scene クラスポインタを引数に importer->Import() 関数を呼びシーンをインポートします。
成功すれば true 失敗すれば false が返ります。

シーンのインポートが成功すれば FbxImporter は不要になりますので、明示的に破棄しておきます。

最後に

これで、FBX ファイル内の様々な情報にアクセスできるようになりました。
次回から FbxScene クラスを介して情報の取得方法を説明していきます。

では今回説明した一連のソースコードです。

#include<iostream>
#include<fbxsdk.h>

using namespace fbxsdk;

int main(int argc, char* argv[]) {
  // マネージャーの作成
  FbxManager* manager = FbxManager::Create();
  std::cout << "Create FbxManager ... ";
  if (manager == NULL) {
    std::cout << "fail!" << std::endl;

    return 0;
  }
  std::cout << "success!" << std::endl;

  // インポーターの作成
  FbxImporter* importer = FbxImporter::Create(manager, "");
  std::cout << "Create FbxImporter ... ";
  if (importer == NULL) {
    std::cout << "fail!" << std::endl;
    manager->Destroy();

    return 0;
   }
  std::cout << "success!" << std::endl;

  // ファイルを開く
  const char* filePath = "C:\\Cube.fbx";
  
  std::cout << "Open File [" << filePath << "] ... ";
  if (!importer->Initialize(filePath)) {
    std::cout << "fail!" << std::endl;
    manager->Destroy();

    return 0;
  }
  std::cout << "success!" << std::endl;

  // シーンの作成
  FbxScene* scene = FbxScene::Create(manager, "");
  std::cout << "Create FbxScene ... ";
  if (scene == NULL) {
    std::cout << "fail!" << std::endl;
    manager->Destroy();

    return 0;
  }
  std::cout << "success!" << std::endl;

  // ファイルからシーンを読み込む
  std::cout << "Import Scene ... ";
  if (!importer->Import(scene)) {
    std::cout << "fail!" << std::endl;
    manager->Destroy();

    return 0;
  }
  std::cout << "success!" << std::endl;

  // インポーターの明示的な破棄
  importer->Destroy();

  /*** ここに処理を書いていきます ***/

  // 後処理
  manager->Destroy();

  return 1;
}

ここで紹介しているプログラムを使用する場合は自己責任でお願いします。