Nanashi-softプログラマ専用DirectX11開発


◇DirectX11プログラミング -単純なPMDファイルを見てみる-

DirectX11では .Xフォーマットがサポートされなくなり,自分でモデルデータの形式を決める必要があります
PMDフォーマットは色々な人に解析され,様々なツールが開発されています
なので,このデータフォーマットを読み込めるようにしたいと思います

pmdファイルに変換するには色々な方法があります
メタセコイアで色々実験したので,これでやってみます

まず,メタセコイアから .X形式で保存します
それを PMDエディタで,メニューのファイル→インポート→Xファイルで読み込み,.pmd形式で保存します
↓参考ホームページ
○PMDエディタの使い方
http://www6.atwiki.jp/vpvpwiki/pages/118.html

生成したデータを,作成した TSXBINの PMDマクロを通して確認する
face_vert_countのところに注目。頂点数が 36になっています
つまり,全部三角形のデータになりました

見た目,↓こんな感じのデータだけれど大丈夫かなぁ?
0xBF7FFFFF,0x3F7FFFFF,0xBF7FFFFF
法則的には合っている感じなので,やってみてから考えればいいよね
どうせ考えてもわからんし('-'*) ←

既にマクロで読み込めているので,それをそのまま C++で書き直します
まずは,頂点データとそのインデックスデータのみを読み込んでみます

・pmd.hヘッダーファイル
class pmd{
public:
#pragma pack(push,1) //アラインメント制御をオフる
//ヘッダー
struct t_header{
unsigned char magic[3];
float version;
unsigned char model_name[20];
unsigned char comment[256];
};
t_header header;
//頂点リスト
unsigned long vert_count;
struct t_vertex{
float pos[3];
float normal_vec[3];
float uv[2];
unsigned short bone_num[2];
unsigned char bone_weight;
unsigned char edge_flag;
};
t_vertex *vertex;
//面頂点リスト
unsigned long face_vert_count;
unsigned short *face_vert_index;
#pragma pack(pop) //アラインメント制御エンド

//コンストラクタ
pmd(char *);

//デストラクタ
~pmd();
};
ヘッダーファイル記述のポイントは,#pragma(プラグマ)を使ってアラインメント制御を行う点でしょうか
この #pragmaと言うのはコンパイラに指示を与える為の命令で,コンパイラ毎に記述方法が異なります
構造体アラインメントと言うのは,構造体を宣言した際に行われるメモリ効率化のことです

Windows2000以降で動作するようなソフトの場合,大抵4バイトアラインメントになっています
上の t_headerだと,
struct t_header{
unsigned char magic[3]; ←3バイト
<ここに自動的に1バイト分の空きができる>
float version;
unsigned char model_name[20];
unsigned char comment[256];
};
その方が速いから,コンパイラが予期に計らってくれたわけですが
今回のように,ファイルから直接この構造体にリードした場合,この自動的に空けてくれた1バイト分ずれてしまいます

そこで,コンパイラに,ここは1バイトアラインメントにしてね。と教えるのが
#pragma pack(push,1)
です
そうすると,間があく心配は無くなります

・pmd.cpp C++プログラムファイル
#include "pmd.h"
#include <windows.h>
#include <stdio.h>

//コンストラクタ
pmd::pmd(char *filename)
{
FILE *hFP;
hFP = fopen(filename, "rb");
if(hFP != 0){
//ヘッダー読み込み
fread(&header, sizeof(struct t_header), 1, hFP);

//頂点数読み込み
fread(&vert_count, sizeof(vert_count), 1, hFP);

//頂点データ読み込み
vertex = new t_vertex[vert_count];
fread(vertex, 38, vert_count, hFP);

//面頂点リスト読み込み
fread(&face_vert_count, sizeof(face_vert_count), 1, hFP);

//面頂点リストデータ読み込み
face_vert_index = new unsigned short[face_vert_count];
fread(face_vert_index, 2, face_vert_count, hFP);

fclose(hFP);
}else{
MessageBoxW(NULL, L"fopen", L"Err", MB_ICONSTOP);
}
}

//デストラクタ
pmd::~pmd(void)
{
}
これをメインプログラムに繋ぐ('-'*)
#include "pmd.h"	//PMDローダー
を追記

VC++2010の左にあるソリューションエクスプローラーの,ソースファイルに,
エクスプローラーから pmd.cppをドラッグドロップして追加する

これで pmdクラスが使用可能になったはずです

初期化の後に記述している頂点データの部分を書き換えます
const int TYOUTENと,Vertex3D hVectorData[TYOUTEN] = {のデータ定義部分を削除
unsigned short hIndexData[24] = {のインデックスデータ部分も削除
まぁ,エラーになった変数を削除すればいいです(ぉ

その代わりに,pmdクラスからデータを取ってくる処理を記述します
	//pmdクラスを生成する。その際にコンストラクタにファイル名を教える
pmd *modeldata;
modeldata = new pmd("rippoutai.pmd");

//頂点データを取得
int TYOUTEN = modeldata->vert_count;

for(int i=0; i < TYOUTEN; i++){
hVectorData[i].pos[0] = modeldata->vertex[i].pos[0];
hVectorData[i].pos[1] = modeldata->vertex[i].pos[1];
hVectorData[i].pos[2] = modeldata->vertex[i].pos[2];
hVectorData[i].col[0] = 0.0f;
hVectorData[i].col[1] = 0.0f;
hVectorData[i].col[2] = 0.5f;
hVectorData[i].col[3] = 1.0f;
hVectorData[i].tex[0] = 0.0f;
hVectorData[i].tex[1] = 1.0f;
}

//インデックスデータを取得
int INDEXSU = modeldata->face_vert_count;

unsigned short *hIndexData;
hIndexData = new unsigned short[INDEXSU];

for(int i=0; i < INDEXSU; i++){
hIndexData[i] = modeldata->face_vert_index[i];
}
一見複雑そうですが,そんな事はありません。メンドイだけです(^^;
VC++2010は優秀なので,とりあえず .で記述しておけば,->でなければならないとことはコンパイルエラーで教えてくれます(ぉ
もういっそのこと,全部ドット演算子で書けば,予期に計らってくれればいいのに ←

インデックスバッファ作成時の ByteWidthに,このインデックスのサイズが入るようにします
	hBufferDesc.ByteWidth = sizeof(unsigned short) * INDEXSU;
あとは,描画の際に DrawIndexedを使うのが注意点です
		hpDeviceContext->DrawIndexed(INDEXSU, 0, 0);
これを実行すると,立方体が表示されました


色点けの都合上,全部同じ色なのでわかり辛いですね
ラスタライザをワイヤーフレームに切り替えてみます
			D3D11_FILL_SOLID,

			D3D11_FILL_WIREFRAME,

三角形の単位でよく見てみると,きちんと立方体になっている事がわかります

同様に,球体を pmdファイルに変換して,表示してみます
単純に,ファイル名を変更するだけ(のはず)です

これ 336ポリゴンあるのですよw
さすがにこれは人力では厳しいでしょう。pmdデータを読めるからこその芸当です

モデルデータさえ作れば,何でも表示できるはずです
pmdファイルと言うことは,アレもできるんじゃないの? と思われるかも知れませんが
まだムリでしょう。でもやってみます

あ! 表示できてるw
グチャッとなったのを載せるつもりだったのにww ←

44991ポリゴンもあります('-'*)
256ポリゴンとかまでしか表示できないと思っていたのですが,ショボいプログラムにしては高機能ですね


TOPプログラマ専用DirectX11開発