スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

自力で"Xファイル"を読み込む方法

今日は、前回作ったXファイルの読み込む方法を紹介したいと思います。
※個人的に、勝手に作ったので、効率が良いのか?とかは不明です。
(参考程度にどうぞ)

まず、3Dの物体をプログラム内で定義し、描画する方法を確認してみます。
---------------------------------------------------------------

#define FVF_VERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
typedef struct
{ float x,y,z; // 頂点座標
D3DCOLOR diffuse; // 色
} D3DVERTEX;

D3DVERTEX v[3]=
{ { 300.0f, 100.0f, 0.0f, 1.0f, 0xffff0000 }, //頂点=赤
{ 450.0f, 250.0f, 0.0f, 1.0f, 0xff00ff00 }, //右辺=緑
{ 150.0f, 250.0f, 0.0f, 1.0f, 0xff0000ff }, //左辺=青
};

**********色々と省略******************

//Device->SetMaterial( "D3DMATERIAL9"型の変数 );
//Device->SetTexture( 0, "LPDIRECT3DTEXTURE9"型の変数 );

Device->SetFVF(FVF_VERTEX);
Device->DrawPrimitiveUP(D3DPT_TRIANGLELIST,1,v,sizeof(D3DVERTEX));


---------------------------------------------------------------------------
大体こんな感じになります。

↓大まかな流れ。
---------------------------------------------------------------------------
①3Dモデルの情報を持つ構造体を定義。(上記の場合、頂点座標と色
②適宜、構造体の内部のデータを入れる。(座標とか)
③テクスチャやマテリアルを使いたい場合はSetTexture、SetMaterial関数を使う。
④SetFVF関数で、頂点フォーマットを設定。
(フォーマットを教える。「頂点座標と色のフォーマットを使いますよ」、みたいな。
これを忘れると変な事になります。
⑤DrawPrimitiveUP関数で面などを描画する。

---------------------------------------------------------------------------

これを見ても分かるように、
どんな複雑なオブジェクトであっても、
面の描画の繰り返しで完成する事が分かります。

【参考画像】
3Dモデルの流れ図

※マテリアルとテクスチャのセットする部分で、色や画像が変わっていないところは、
何もしないマテリアルとテクスチャをセットしている、と考えてください。


コレを踏まえると、描画をする部分はこんな感じになります。
---------------------------------------------------------------------------

VOID Render()
{
Device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0,0,60), 1.0f, 0 );
if( SUCCEEDED(Device->BeginScene()){

for(DWORD i = 0; i < マテリアルの数; i++){
Device->SetMaterial( &Material[i] );
Device->SetTexture( 0, Texture[i] );

Device->SetFVF(フォーマット指定);
for(DWORD j = 0; j < 面の数;i++){
Device->DrawPrimitiveUP(D3DPT_TRIANGLELIST,2か1,Test[j].v,sizeof(構造体));
}

}
Device->EndScene();
}
Device->Present( NULL, NULL, NULL, NULL );
}


---------------------------------------------------------------------------
で、メッシュを描画をしたことのある方は分かると思いますが、
通常は赤字の部分はg_Mesh->DrawSubset( i );という風になります。

要するに、DrawSubset関数で、全ての面を描画する部分
自分でfor文を使って実装したという事です。

内部データの方は、
fopen関数などを使って外部から読み込み、変数に代入すればOKです。

具体的なプログラムは,
もしかすると壊れる可能性もあるので公開はしません。

まぁ、普通はD3DXLoadMeshFromX関数などを使って終わりだと思います。
(需要は無いと思われる)

しかし、一から自分で実装してみるのも良いものですよ!(`・ω・´)+
動いた時に感動します。


【追記】(補足)
以前、データを読み込む部分は下記の様にしていたのですが、
-----------------------------------------------

void LoadData(void)
{
LoadVertex(); //頂点データを読み込む
LoadIndex(); //頂点インデックスを読み込む
LoadMaterial(); //マテリアルを読み込む
LoadNormals(); //法線を読み込む
LoadTextureCoords(); //UV座標を読み込む
LoadVertexColors(); //頂点色を読み込む
}


-----------------------------------------------
コレだと、UV座標や、頂点色を持たないXファイルや、
法線→マテリアル→UV座標→頂点データみたいに、
順番が入れ替わったXファイルの場合、
全然 対応できない状況でした。
ファイルポインタは全ての関数で共有しているため、順番が崩れると
「頂点座標」を格納する変数に、「法線ベクトル」を入れようとしたりなど
無茶苦茶になってしまう。)

で、改良版は
特定の文と一致した時、適切な関数を呼び出す
と言う風にしました。

Xファイルのデータが記述されている前には、必ずキーワードがあります。
-------------------------------
MeshNormals {
6;
0.000000;0.000000;-1.000000;,
1.000000;0.000000;0.000000;,
//以下略


MeshTextureCoords {
20;
0.000000;0.000000;,
1.000000;0.000000;,
//以下略

-------------------------------

なので、下記の様にswitch文を用いました。
日本語も混ざってて、微妙に実際のコードとは異なりますが、
おおまかな構造の例なので気にしないで下さい。
------------------------------------------------------

void LoadData(void){
while(ファイル終端に行くまで繰り返し読み込む){
switch(フラグ)
{
文字列"Mesh"を読み込んだ場合は: LoadVertex();LoadIndex(); break;
文字列"MeshNormals"を読み込んだ場合は: LoadNormals();break;
文字列"MeshMaterialList"を読み込んだ場合は: LoadMaterial()break;
//以下同じ様に処理を分岐。
}
}
}

-----------------------------------------------------
で、次回は、親子関係などを定義したXファイルを読み込もうと思ってます。
これにはFrameと呼ばれる構造が用いられているので、
読み込み部分はまたいろいろと変更しないといけないっぽいです。
(だが諦めない)
スポンサーサイト

テーマ : ゲーム製作 関連 - ジャンル : ゲーム

コメント
コメントの投稿
管理者にだけ表示を許可する



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。