#自己紹介
某東京にある専門学校に在校している3年生です。
今、就活作品をOpenGLで制作しています。
最近はマイクラはまってます。
#はじめに
fbxsdkで3Dモデルをロードする記事を備忘録として書きます。
fbxsdkの導入などについては他の方の記事を見てください。
この記事ではfbxsdkの初期化と頂点座標の取得、頂点インデックスの取得を行います。
fbxsdkは.fbxの他に.obj, .dxf, .daeも読み込みと書き出しができるらしいです。
自分は.objと.fbxしか読み込んだことがないです。
#必要なクラスを作る
まず頂点のデータを格納するVertexとモデルの情報を保存するModelAssetを作ります。
それと、ロードする用のModelLoaderを作ります。
#pragma once
struct Vertex
{
GLfloat position[3];
};
#pragma once
#include "vertex.hpp"
struct ModelAsset
{
Vertex* vertices;
int vertices_count;
GLuint* indices;
GLsizei indices_count;
};
#pragma once
#include <fbxsdk.h>
#include <iostream>
#include "model_asset.h"
class ModelLoader
{
public:
static void Load(ModelAsset& model_asset, const char* path);
private:
static void LoadVertex(ModelAsset& model_asset, FbxMesh& mesh);
static void LoadIndices(ModelAsset& model_asset, FbxMesh& mesh);
};
これらが今回使うクラスと構造体です。
#fbxsdkの初期化とMeshの取得
#include "model_loader.h"
void ModelLoader::Load(ModelAsset& model_asset, const char* path)
{
// fbxsdk 初期化処理
FbxManager* manager = FbxManager::Create();
if (!manager) {
std::cerr << "failed to create FbxManager." << std::endl;
manager->Destroy();
return;
}
FbxScene* scene = FbxScene::Create(manager, "");
if (!scene) {
std::cerr << "failed to create FbxScene." << std::endl;
manager->Destroy();
return;
}
FbxImporter* importer = FbxImporter::Create(manager, "");
if (!importer) {
std::cerr << "failed to create FbxImporter." << std::endl;
manager->Destroy();
scene->Destroy();
return;
}
if (!importer->Initialize(path, -1, manager->GetIOSettings())) {
std::cerr << "failed to initialize FbxImporter." << std::endl;
importer->Destroy();
manager->Destroy();
scene->Destroy();
return;
}
if (!importer->Import(scene))
{
std::cerr << "failed to import: " << path << std::endl;
importer->Destroy();
manager->Destroy();
scene->Destroy();
return;
}
importer->Destroy();
// ポリゴンを三角形に変換
FbxGeometryConverter geometry_converter(manager);
geometry_converter.Triangulate(scene, true);
FbxMesh* mesh = scene->GetSrcObject<FbxMesh>();
if (!mesh) {
std::cerr << "failed to load mesh." << " (" << path << ")" << std::endl;
scene->Destroy();
manager->Destroy();
return;
}
}
#頂点の読み込み
mesh.GetControlPointsCount()で頂点の数を取得します。
mesh.getControlPointAt()で頂点座標を取得できるのでそれを配列に格納します。
void ModelLoader::LoadVertex(ModelAsset& model_asset, FbxMesh& mesh)
{
int control_points_count = mesh.GetControlPointsCount();
model_asset.vertices_count = control_points_count;
model_asset.vertices = new Vertex[control_points_count];
for (int i = 0; i < control_points_count; i++) {
FbxVector4 point = mesh.GetControlPointAt(i);
Vertex vertex;
vertex.position[0] = point[0];
vertex.position[1] = point[1];
vertex.position[2] = point[2];
model_asset.vertices[i] = vertex;
}
}
#頂点インデックスの読み込み
void ModelLoader::LoadIndices(ModelAsset& model_asset, FbxMesh& mesh)
{
int polygon_vertex_count = mesh.GetPolygonVertexCount();
model_asset.indices_count = polygon_vertex_count;
model_asset.indices = new GLuint[polygon_vertex_count];
for (int i = 0; i < polygon_vertex_count; i++) {
model_asset.indices[i] = mesh.GetPolygonVertices()[i];
}
}
#LoadVertexとLoadIndicesをLoad内で使用する
void ModelLoader::Load(ModelAsset& model_asset, const char* path)
{
// fbxsdk 初期化処理
FbxManager* manager = FbxManager::Create();
if (!manager) {
std::cerr << "failed to create FbxManager." << std::endl;
manager->Destroy();
return;
}
FbxScene* scene = FbxScene::Create(manager, "");
if (!scene) {
std::cerr << "failed to create FbxScene." << std::endl;
manager->Destroy();
return;
}
FbxImporter* importer = FbxImporter::Create(manager, "");
if (!importer) {
std::cerr << "failed to create FbxImporter." << std::endl;
manager->Destroy();
scene->Destroy();
return;
}
if (!importer->Initialize(path, -1, manager->GetIOSettings())) {
std::cerr << "failed to initialize FbxImporter." << std::endl;
importer->Destroy();
manager->Destroy();
scene->Destroy();
return;
}
if (!importer->Import(scene))
{
std::cerr << "failed to import: " << path << std::endl;
importer->Destroy();
manager->Destroy();
scene->Destroy();
return;
}
importer->Destroy();
// ポリゴンを三角形に変換
FbxGeometryConverter geometry_converter(manager);
geometry_converter.Triangulate(scene, true);
FbxMesh* mesh = scene->GetSrcObject<FbxMesh>();
if (!mesh) {
std::cerr << "failed to load mesh." << " (" << path << ")" << std::endl;
scene->Destroy();
manager->Destroy();
return;
}
LoadVertex(model_asset, *mesh);
LoadIndices(model_asset, *mesh);
scene->Destroy();
manager->Destroy();
}
次は法線座標とuvなどをやろうと思います。
間違っている箇所があればコメントしてほしいです。
参考URL
fbxsdk: http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/
ゲームが作りたいんだ!: https://shikemokuthinking.blogspot.com/2013/06/fbxfbxsdkvc2010.html?view=magazine