1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

fbxsdkで3Dモデルのロード パート1

Last updated at Posted at 2019-12-21

#自己紹介
某東京にある専門学校に在校している3年生です。
今、就活作品をOpenGLで制作しています。
最近はマイクラはまってます。

#はじめに
fbxsdkで3Dモデルをロードする記事を備忘録として書きます。
fbxsdkの導入などについては他の方の記事を見てください。
この記事ではfbxsdkの初期化と頂点座標の取得、頂点インデックスの取得を行います。
fbxsdkは.fbxの他に.obj, .dxf, .daeも読み込みと書き出しができるらしいです。
自分は.objと.fbxしか読み込んだことがないです。

#必要なクラスを作る

まず頂点のデータを格納するVertexとモデルの情報を保存するModelAssetを作ります。
それと、ロードする用のModelLoaderを作ります。

vertex.hpp
#pragma once

struct Vertex
{
	GLfloat position[3];
};
model_asset.hpp
#pragma once
#include "vertex.hpp"

struct ModelAsset
{
    Vertex* vertices;
    int vertices_count;
    GLuint* indices;
    GLsizei indices_count;
};
model_loader.hpp
#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の取得

model_loader.cpp
#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()で頂点座標を取得できるのでそれを配列に格納します。

model_loader.cpp
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;
	}
}

#頂点インデックスの読み込み

model_loader.cpp
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内で使用する

model_data.cpp
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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?