[1] 質問文
[1.1] 自分が今行いたい事は何か
DirectX9 に おいて、複数の異なるメッシュを読み込む方法がわからないので質問させて頂きます。複数のメッシュを読み込みたいのです。具体的には、自キャラと地形のふたつを描画させたいのです。DirectXは初めてなので、手探りの状態で作っています。
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
検索をかけてみたところ、どうもLoadModel()関数というものが存在(自作?)するらしいのですが、どうもよくわからないというのが実情です。それと、D3DXLoadMeshFromX関数、D3DXCreateTextureFromFile関数を二つ書いたりもしたのですが、実行画面に何も映りません。ファイル名はきちんと書いているつもりです。
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
バージョンの違いでしょうか。pMesh が g_pMesh になっていたり、そういったサンプルソース(ネット上)のを読み込んでもエラーが出ます。
[1.4] 今何がわからないのか、知りたいのか
DirectX9 に おいて、複数の異なるメッシュを読み込む方法がわからないので質問させて頂きます。
InitGeometry()関数の後半の記述がなんなのかも、理解できません。
殆ど手探りで作っています。このソースも、チュートリアルのサンプルに少し手を加えたものです。
[2] 環境
[2.1] OS : Windows Vista,
[2.2] コンパイラ名 : VC++ 2008EE,
複数のメッシュの読み込みについて
Re: 複数のメッシュの読み込みについて
//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: Load the mesh and build the material and texture arrays
//-----------------------------------------------------------------------------
// 3Dモデル作成 xファイルの読み込み等
// マテリアルは、D3DXLoadMeshFromX関数で取得したマテリアルバッファから格納
// テクスチャは、D3DXCreateTextureFromFileで取得する。
HRESULT InitGeometry()
{
LPD3DXBUFFER pD3DXMtrlBuffer;
// D3DXLoadMeshFromX()によってxファイルを読み込む
if( FAILED( D3DXLoadMeshFromX( "meka.x", D3DXMESH_SYSTEMMEM,
g_pd3dDevice, NULL,
&pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
&g_pMesh ) ) )
{
// If model is not in current folder, try parent folder
// 同一フォルダにxファイルが無い場合に探す
if( FAILED( D3DXLoadMeshFromX( "..\\Tiger.x", D3DXMESH_SYSTEMMEM,
g_pd3dDevice, NULL,
&pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
&g_pMesh ) ) )
{
MessageBox(NULL, "Could not find tiger.x", "Meshes.exe", MB_OK);
return E_FAIL;
}
}
// We need to extract the material properties and texture names from the
// pD3DXMtrlBuffer
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
if( g_pMeshMaterials == NULL )
return E_OUTOFMEMORY;
g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
if( g_pMeshTextures == NULL )
return E_OUTOFMEMORY;
for( DWORD i=0; i<g_dwNumMaterials; i++ )
{
// Copy the material
g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
// Set the ambient color for the material (D3DX does not do this)
g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
g_pMeshTextures[i] = NULL;
if( d3dxMaterials[i].pTextureFilename != NULL &&
lstrlen(d3dxMaterials[i].pTextureFilename) > 0 )
{
// Create the texture
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
d3dxMaterials[i].pTextureFilename,
&g_pMeshTextures[i] ) ) )
{
// If texture is not in current folder, try parent folder
const TCHAR* strPrefix = TEXT("..\\");
TCHAR strTexture[MAX_PATH];
StringCchCopy( strTexture, MAX_PATH, strPrefix );
StringCchCat( strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename );
// If texture is not in current folder, try parent folder
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
strTexture,
&g_pMeshTextures[i] ) ) )
{
MessageBox(NULL, "Could not find texture map", "Meshes.exe", MB_OK);
}
}
}
}
// Done with the material buffer
pD3DXMtrlBuffer->Release();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
if( g_pMeshMaterials != NULL )
delete[] g_pMeshMaterials;
if( g_pMeshTextures )
{
for( DWORD i = 0; i < g_dwNumMaterials; i++ )
{
if( g_pMeshTextures[i] )
g_pMeshTextures[i]->Release();
}
delete[] g_pMeshTextures;
}
if( g_pMesh != NULL )
g_pMesh->Release();
if( g_pd3dDevice != NULL )
g_pd3dDevice->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
//-----------------------------------------------------------------------------
// ここではワールド変換、カメラと注視点(ビュー変換)、射影変換を行うための行列を作成し、
// Direct3Dデバイスに渡す。
VOID SetupMatrices()
{
// Set up world matrix
D3DXMATRIXA16 matWorld1, matWorld2;
// 平行移動行列を作り位置を変える. mx,my,mz は、位置(座標)を格納する変数 移動処理に用いる
D3DXMatrixTranslation( &matWorld1, mx, my, mz );
// 回転行列 引数にangle を渡し、回転処理に用いる
D3DXMatrixRotationY( &matWorld2, angle );//timeGetTime()/1000.0f );
matWorld2 *= matWorld1;
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld2 );
// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye five units back along the z-axis and up three units, look at the
// origin, and define "up" to be in the y-direction.
D3DXVECTOR3 vEyePt( 0.0f, 15.0f,-15.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 3.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 5.0f, 0.0f );
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
// Clear the backbuffer and the zbuffer
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
// Begin the scene
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
// Setup the world, view, and projection matrices
SetupMatrices();
// Meshes are divided into subsets, one for each material. Render them in
// a loop
for( DWORD i=0; i<g_dwNumMaterials; i++ )
{
// Set the material and texture for this subset
g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] );
g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );
// Draw the mesh subset
g_pMesh->DrawSubset( i );
}
// End the scene
g_pd3dDevice->EndScene();
}
// Present the backbuffer contents to the display
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
問題の部分のみ載せて頂きたいです。
申し訳ありません。
Re: 複数のメッシュの読み込みについて
Xファイルからメッシュを読み込むということでよいのですね?
それでしたら、少なくとも2つの方法があります。
1. 自分でXファイルを解析して読み込ませる。
2. DirectXのヘルパー関数を使う。
多分今回は、2のほうがよいと思いますので、こちらを使います。
DirectXにはXファイルからメッシュを作成してくれる、D3DXLoadMeshFromXという関数があります。
これを呼び出した後、マテリアルの設定、テクスチャの設定を行う形になります。
テクスチャの設定では、D3DXLoadMeshFromXを呼び出します。
基本的にこのような流れで自作関数を作って複数回呼び出せば、複数のメッシュを作成することが出来ます。
簡単なソースコードを載せておきますので参考にしてください。
エラーチェックなどを除いているため、そのあたりは自分で処理することになりますが、流れとしてはこんな感じです。
それでしたら、少なくとも2つの方法があります。
1. 自分でXファイルを解析して読み込ませる。
2. DirectXのヘルパー関数を使う。
多分今回は、2のほうがよいと思いますので、こちらを使います。
DirectXにはXファイルからメッシュを作成してくれる、D3DXLoadMeshFromXという関数があります。
これを呼び出した後、マテリアルの設定、テクスチャの設定を行う形になります。
テクスチャの設定では、D3DXLoadMeshFromXを呼び出します。
基本的にこのような流れで自作関数を作って複数回呼び出せば、複数のメッシュを作成することが出来ます。
簡単なソースコードを載せておきますので参考にしてください。
LPDIRECT3DDEVICE9 g_pD3DDev;
LPD3DXMESH g_pMesh;
D3DMATERIAL9* g_pMtrl;
LPDIRECT3DTEXTURE* g_pTex;
DWORD g_NumMtrl;
bool CreateMesh( const char* pFileName )
{
// Xファイルの読み込み
LPD3DXBUFFER pD3DXMtrlBuf;
D3DXLoadMeshFromX( pFileName, D3DXMESH_SYSTEMEM, g_pD3DDev, NULL, &g_pMtrl, NULL, &g_NumMtrl, &g_pMesh );
// マテリアル情報の読み込み
g_pMtrl = new D3DMATERIAL9[ g_NumMtrl ];
g_pTex = new LPDIRECT3DTEXTURE9[ g_NumMtrl ];
D3DXMATERIAL* pD3DXMtrl = static_cast < D3DXMATERIAL* > ( pD3DXMtrlBuf->GetBufferPointer() );
for( DWORD i = 0; i < g_NumMtrl; i++ ){
// Xファイルには環境光成分がないため、Diffuse色で置き換える。
g_pMtrl[ i ].Ambient = g_pMtrl[ i ].Diffuse;
// テクスチャの読み込み
if( !g_pMtrl[ i ].pTextureFileName ){
g_pTex[ i ] = NULL;
}
else{
if( FAILED( D3DXCreateTextureFromFile( g_pD3DDev, g_pMtrl[ i ].pTextureFileName, &g_pTex[ i ] ) ) ){
g_pTex[ i ] = NULL;
}
pD3DMtrlBuf->Release();
}
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR pStr, int cmd )
{
// 初期化などのいろいろな処理
CreateMesh( "mesh1.x" ); // 1つ目のメッシュ作成
CreateMesh( "mesh2.x" ); // 2つ目のメッシュ作成
// 終了処理など。
return 0;
}
Re: 複数のメッシュの読み込みについて
って、丁度書き込みしている時に投稿されたので気がつきませんでした^^;
長くなってしまったので別のレスで書きます。
>pMesh が g_pMesh になっていたり
これは、ただ単に変数の命名の仕方を変えているだけです。
この場合ですと、例えばg_pMeshならこのg_はグローバル変数であることを示します。
まあつまり、グローバル変数だよっていうことがすぐにわかるようにするためにしているわけです。
>nitGeometry()関数の後半の記述がなんなのかも、理解できません
これは、マテリアル情報の処理を行っています。
簡略化したものを私のほうで用意しているので、それを見てください。流れをつかみやすいように、エラーチェックなど省略しまくっていますが。。。
(ただ、これですときちんと処理を行っていない部分もあるかもしれませんが^^;)
長くなってしまったので別のレスで書きます。
>pMesh が g_pMesh になっていたり
これは、ただ単に変数の命名の仕方を変えているだけです。
この場合ですと、例えばg_pMeshならこのg_はグローバル変数であることを示します。
まあつまり、グローバル変数だよっていうことがすぐにわかるようにするためにしているわけです。
>nitGeometry()関数の後半の記述がなんなのかも、理解できません
これは、マテリアル情報の処理を行っています。
簡略化したものを私のほうで用意しているので、それを見てください。流れをつかみやすいように、エラーチェックなど省略しまくっていますが。。。
(ただ、これですときちんと処理を行っていない部分もあるかもしれませんが^^;)
Re: 複数のメッシュの読み込みについて
何度もすいません;;
掲載したソースコードが間違っていました。
LPDIRECT3DDEVICE9 g_pD3DDev;
LPD3DXMESH g_pMesh;
D3DMATERIAL9* g_pMtrl;
LPDIRECT3DTEXTURE* g_pTex;
DWORD g_NumMtrl;
ですが、このままではまずいですね。。。
C++のクラスをご存知なのなら、これをメンバ変数にしてしまうという方法がありますが、今回の場合はCで考えてみることにします。
本当は、可変長配列を使うとよいのですが、ここではただ単に配列としてみました。
当然このままではメッシュが作れる限界数が存在することになるので、最終的には可変長配列やクラス化を検討することとなります。
修正したコードを乗せておきますね。
あと、ソースコード見ましたが、2つあるD3DXLoadMeshFromXに異なるメッシュを指定しているのはなぜです?
これは、コメントから察するに多分パスに関する対策を行っていると思うので、別のメッシュを指定してはまずいのではないですか?
掲載したソースコードが間違っていました。
LPDIRECT3DDEVICE9 g_pD3DDev;
LPD3DXMESH g_pMesh;
D3DMATERIAL9* g_pMtrl;
LPDIRECT3DTEXTURE* g_pTex;
DWORD g_NumMtrl;
ですが、このままではまずいですね。。。
C++のクラスをご存知なのなら、これをメンバ変数にしてしまうという方法がありますが、今回の場合はCで考えてみることにします。
本当は、可変長配列を使うとよいのですが、ここではただ単に配列としてみました。
当然このままではメッシュが作れる限界数が存在することになるので、最終的には可変長配列やクラス化を検討することとなります。
修正したコードを乗せておきますね。
// 今回は2つのメッシュを読み込むとする。同時に読み込めるメッシュはこの場合2つ。
LPDIRECT3DDEVICE9 g_pD3DDev;
LPD3DXMESH g_pMesh[ 2 ];
D3DMATERIAL9* g_pMtrl[ 2 ];
LPDIRECT3DTEXTURE* g_pTex[ 2 ];
DWORD g_NumMtrl[ 2 ];
bool CreateMesh( const char* pFileName, int index )
{
// Xファイルの読み込み
LPD3DXBUFFER pD3DXMtrlBuf;
D3DXLoadMeshFromX( pFileName, D3DXMESH_SYSTEMEM, g_pD3DDev, NULL, &g_pMtrl[ index ], NULL, &g_NumMtrl[ index ], &g_pMesh[ index ] );
// マテリアル情報の読み込み
g_pMtrl[ index ] = new D3DMATERIAL9[ g_NumMtrl ];
g_pTex[ index ] = new LPDIRECT3DTEXTURE9[ g_NumMtrl ];
D3DXMATERIAL* pD3DXMtrl = static_cast < D3DXMATERIAL* > ( pD3DXMtrlBuf->GetBufferPointer() );
for( DWORD i = 0; i < g_NumMtrl[ index ]; i++ ){
// Xファイルには環境光成分がないため、Diffuse色で置き換える。
g_pMtrl[ index ][ i ].Ambient = g_pMtrl[ index ][ i ].Diffuse;
// テクスチャの読み込み
if( !g_pMtrl[ index ][ i ].pTextureFileName ){
g_pTex[ index ][ i ] = NULL;
}
else{
if( FAILED( D3DXCreateTextureFromFile( g_pD3DDev, g_pMtrl[ index ][ i ].pTextureFileName, &g_pTex[ index ][ i ] ) ) ){
g_pTex[ index ][ i ] = NULL;
}
pD3DMtrlBuf->Release();
}
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR pStr, int cmd )
{
// 初期化などのいろいろな処理
CreateMesh( "mesh1.x", 0 ); // 1つ目のメッシュ作成
CreateMesh( "mesh2.x", 1 ); // 2つ目のメッシュ作成
// 終了処理など。
return 0;
}
これは、コメントから察するに多分パスに関する対策を行っていると思うので、別のメッシュを指定してはまずいのではないですか?
Re: 複数のメッシュの読み込みについて
あ、いえ、大丈夫です。ぬっち さんが書きました:何度もすいません;;
掲載したソースコードが間違っていました。
LPDIRECT3DDEVICE9 g_pD3DDev;
LPD3DXMESH g_pMesh;
D3DMATERIAL9* g_pMtrl;
LPDIRECT3DTEXTURE* g_pTex;
DWORD g_NumMtrl;
ですが、このままではまずいですね。。。
C++のクラスをご存知なのなら、これをメンバ変数にしてしまうという方法がありますが、今回の場合はCで考えてみることにします。
本当は、可変長配列を使うとよいのですが、ここではただ単に配列としてみました。
当然このままではメッシュが作れる限界数が存在することになるので、最終的には可変長配列やクラス化を検討することとなります。
修正したコードを乗せておきますね。
あと、ソースコード見ましたが、2つあるD3DXLoadMeshFromXに異なるメッシュを指定しているのはなぜです?
これは、コメントから察するに多分パスに関する対策を行っていると思うので、別のメッシュを指定してはまずいのではないですか?
今、ソースを修正していました。
すみません。C++は詳しくないのです。
異なるメッシュを指定している筈は・・・・って本当ですね。
早速、修正しました。申し訳ありません・・・。
今、ぬっちさんのソースを参考に、自分なりに書き直しています。
ありがとうございます。本当、すみません・・・。
Re: 複数のメッシュの読み込みについて
すみません。
手直ししたのですが、下記のようなエラーが生じてしまいます。
手直ししたのですが、下記のようなエラーが生じてしまいます。
1>------ ビルド開始: プロジェクト: game_DirectX, 構成: Debug Win32 ------
1>コンパイルしています...
1>Meshes.cpp
1>c:\program files\microsoft directx sdk (february 2007)\include\d3d9types.h(1385) : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(45) : error C2664: 'D3DXLoadMeshFromXA' : 5 番目の引数を 'D3DMATERIAL9 **' から 'LPD3DXBUFFER *' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(48) : error C2440: '初期化中' : 'DWORD [2]' から 'unsigned int' に変換できません。
1> この変換が可能なコンテキストはありません。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(49) : error C2440: '初期化中' : 'DWORD [2]' から 'unsigned int' に変換できません。
1> この変換が可能なコンテキストはありません。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(51) : error C2446: '<' : 'DWORD *' 型から 'DWORD' 型への変換ができません。
1> この変換が可能なコンテキストはありません。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(51) : error C2040: '<' : 'DWORD' は 'DWORD [2]' と間接操作のレベルが異なります。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(55) : error C2039: 'pTextureFileName' : '_D3DMATERIAL9' のメンバではありません。
1> c:\program files\microsoft directx sdk (february 2007)\include\d3d9types.h(155) : '_D3DMATERIAL9' の宣言を確認してください。
1>c:\users\yoshikazu\documents\visual studio 2008\projects\game_directx\game_directx\meshes.cpp(59) : error C2039: 'pTextureFileName' : '_D3DMATERIAL9' のメンバではありません。
1> c:\program files\microsoft directx sdk (february 2007)\include\d3d9types.h(155) : '_D3DMATERIAL9' の宣言を確認してください。
1>game_DirectX - エラー 7、警告 1
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
Re: 複数のメッシュの読み込みについて
うーん、いくつか間違ってる部分がありました;;
申し訳ない。。。
面倒ですので、前にあげてもらったソースコードをこちらで編集します。
しばらくお待ちください。
申し訳ない。。。
面倒ですので、前にあげてもらったソースコードをこちらで編集します。
しばらくお待ちください。
Re: 複数のメッシュの読み込みについて
とりあえず、DirectX SDKのtutorialの6番目のMesh読み込みのプログラムで、複数のメッシュが読み込めるように変更しました。
ソース内でサンプルを改良したのは//****で挟むようになっています。
ここで表示したのは同じモデルですが、別のファイルからも取得しているので、複数のメッシュからの読み込みに成功していると考えられます。("tiger.x"と"tiger2.x")
もちろん、CreateMeshの片方を削除すると、1つのモデルしか表示されません。
確認してみてください。
ソース内でサンプルを改良したのは//****で挟むようになっています。
ここで表示したのは同じモデルですが、別のファイルからも取得しているので、複数のメッシュからの読み込みに成功していると考えられます。("tiger.x"と"tiger2.x")
もちろん、CreateMeshの片方を削除すると、1つのモデルしか表示されません。
確認してみてください。
- 添付ファイル
-
- main.cpp
- (13.72 KiB) ダウンロード数: 231 回
Re: 複数のメッシュの読み込みについて
ありがとうございます。
確認致しました。
DirectXはまだ始めたばかりだったので、
手探りだったのです・・・。
本当にご迷惑をおかけしたと思います。
申し訳ありませんでした。
ソースを見て、勉強させて頂きます。
ありがとうございます。
確認致しました。
DirectXはまだ始めたばかりだったので、
手探りだったのです・・・。
本当にご迷惑をおかけしたと思います。
申し訳ありませんでした。
ソースを見て、勉強させて頂きます。
ありがとうございます。