ページ 1 / 1
3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 15:42
by Repsol
質問させて下さい。
DirectX9で3Dの勉強をしています。
回転行列を用いて、3Dモデルを回転させる事を先程学びました。
そこでメッシュデータを二つ(キャラクタと地形を)読み込み、
片方のメッシュ(3Dモデル・キャラクタ)を回転させようとしたところ、
地形まで回転してしまいます。
地形は不動のままで、キャラクタの3Dモデルのみを回転させるには、
どうしたらよろしいでしょうか?
コード:
D3DXMATRIXA16 matWorld,matRotation;
D3DXMatrixIdentity(&matWorld);
D3DXMatrixIdentity(&matRotation);
D3DXMatrixRotationY(&matRotation,fHeading);
case WM_KEYDOWN: // キーが押されたら
switch( wParam )
{
case VK_SPACE: // 自キャラ(モデル)の回転
fHeading += 0.1f;
break;
}
コード:
// 構造体を用いて、Xファイル毎にメッシュを作成する
InitThing(&Thing[0],"char.x",&D3DXVECTOR3(0,0,0));
InitThing(&Thing[1],"chikei.x",&D3DXVECTOR3(0,0,0));
Re: 3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 17:53
by softya(ソフト屋)
肝心のmatWorldとmatRotationの行列処理の部分が無いので、 どうなっているか分かりませんがmatWorld*matRotationとmatRotation*matWorldでは全く動作が異なります。
逆にしてみてください。
[追記]
あとmatRotationは3Dモデル・キャラクタだけに使ってくださいね。
Re: 3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 19:22
by Repsol
御返事、ありがとうございます。
前述したソースに、
下記のようにコードを追記したら、
キャラクタのみ、回転することに成功しました。
コード:
case WM_KEYDOWN: // キーが押されたら
switch( wParam )
{
case VK_SPACE: // 自キャラ(モデル)の回転
Thing[0].vecPosition.y += 0.1f;
break;
}
ですが、回転に成功したのは良いものの、
今度はキャラクタが、回転しながらY軸方向上へと上っていってしまうんです。
この原因がよく分かりません。
本当は原点座標で回転させたいのですが・・・。
Re: 3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 19:33
by softya(ソフト屋)
申し訳ないですが、InitThing()とかの関数が出てくるDirectX系のライブラリを存じません。
なので、Thing[0].vecPosition.yの値が何を意味するかも分かりません。
正確に回答したいと思いますので、参考にしている書籍あるいはサイトの情報とInitThing()などの関数の中身やThingの構造体あるいはクラスの定義を見せてください。Thingがクラスであれば、その関数処理も見たいです。
あと、vecPositionと言う名前からして回転系のパラメータには見えません。たぶん移動系のパラメータです。なにか勘違いされていないでしょうか?
Re: 3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 19:59
by Repsol
御返事、ありがとうございます。
参考にしている書籍は、工学社の「はじめての3Dゲーム開発」です。
http://www.kohgakusha.co.jp/books/detai ... 775-1043-6
THING構造体の中身を下記に記します。
コード:
struct THING
{
LPD3DXMESH pMesh;
D3DMATERIAL9* pMeshMaterials;
LPDIRECT3DTEXTURE9* pMeshTextures;
DWORD dwNumMaterials;
D3DXVECTOR3 vecPosition;
THING()
{
ZeroMemory(this,sizeof(THING));
}
};
THING Thing[THING_AMOUNT]; // 構造体配列の宣言
HRESULT InitThing(THING *,LPSTR,D3DXVECTOR3*);
InitThing()の中身です。
コード:
HRESULT InitThing(THING *pThing,LPSTR szXFileName,D3DXVECTOR3* pvecPosition)
{
// メッシュの初期位置
memcpy(&pThing->vecPosition,pvecPosition,sizeof(D3DXVECTOR3));
// Xファイルからメッシュをロードする
LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
if( FAILED( D3DXLoadMeshFromX( szXFileName, D3DXMESH_SYSTEMMEM,
pDevice, NULL, &pD3DXMtrlBuffer, NULL,
&pThing->dwNumMaterials, &pThing->pMesh ) ) )
{
MessageBox(NULL, "Xファイルの読み込みに失敗しました",szXFileName, MB_OK);
return E_FAIL;
}
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
pThing->pMeshMaterials = new D3DMATERIAL9[pThing->dwNumMaterials];
pThing->pMeshTextures = new LPDIRECT3DTEXTURE9[pThing->dwNumMaterials];
for( DWORD i=0; i<pThing->dwNumMaterials; i++ )
{
pThing->pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
pThing->pMeshMaterials[i].Ambient = pThing->pMeshMaterials[i].Diffuse;
pThing->pMeshTextures[i] = NULL;
if( d3dxMaterials[i].pTextureFilename != NULL &&
lstrlen(d3dxMaterials[i].pTextureFilename) > 0 )
{
if( FAILED( D3DXCreateTextureFromFile( pDevice,
d3dxMaterials[i].pTextureFilename,
&pThing->pMeshTextures[i] ) ) )
{
MessageBox(NULL, "テクスチャの読み込みに失敗しました", NULL, MB_OK);
}
}
}
pD3DXMtrlBuffer->Release();
return S_OK;
}
コード:
VOID RenderThing(THING* pThing)
{
//ワールドトランスフォーム(絶対座標変換)
D3DXMATRIXA16 matWorld,matRotation,matPosition;
//行列の初期化
D3DXMatrixIdentity(&matRotation);
D3DXMatrixIdentity(&matWorld);
//Y軸を中心に回転する変換行列の作成
D3DXMatrixRotationY(&matRotation,pThing->vecPosition.y);
D3DXMatrixMultiply(&matWorld,&matWorld,&matRotation);
//平行移動行列の作成
D3DXMatrixTranslation(&matPosition,pThing->vecPosition.x,pThing->vecPosition.y,
pThing->vecPosition.z);
D3DXMatrixMultiply(&matWorld,&matWorld,&matPosition);
pDevice->SetTransform( D3DTS_WORLD, &matWorld );
// ビュートランスフォーム(視点座標変換)
D3DXVECTOR3 vecEyePt( 0.0f, 15.0f,-15.0f ); //カメラ(視点)位置
D3DXVECTOR3 vecLookatPt( 0.0f, 3.0f, 0.0f );//注視位置
D3DXVECTOR3 vecUpVec( 0.0f, 5.0f, 0.0f );//上方位置
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vecEyePt, &vecLookatPt, &vecUpVec );
pDevice->SetTransform( D3DTS_VIEW, &matView );
// プロジェクショントランスフォーム(射影変換)
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
pDevice->SetTransform( D3DTS_PROJECTION, &matProj );
// ライトをあてる 白色で鏡面反射ありに設定
D3DXVECTOR3 vecDirection(1,1,1);
D3DLIGHT9 light;
ZeroMemory( &light, sizeof(D3DLIGHT9) );
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
light.Specular.r=1.0f;
light.Specular.g=1.0f;
light.Specular.b=1.0f;
D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDirection );
light.Range = 200.0f;
pDevice->SetLight( 0, &light );
pDevice->LightEnable( 0, TRUE );
// レンダリング
for( DWORD i=0; i<pThing->dwNumMaterials; i++ )
{
pDevice->SetMaterial( &pThing->pMeshMaterials[i] );
pDevice->SetTexture( 0,pThing->pMeshTextures[i] );
pThing->pMesh->DrawSubset( i );
}
}
Re: 3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 22:19
by softya(ソフト屋)
同じパラメータがRenderThing()関数内で回転と移動で兼用されています。
D3DXMatrixRotationY(&matRotation,pThing->vecPosition.y);
D3DXMatrixTranslation(&matPosition,pThing->vecPosition.x,pThing->vecPosition.y,
pThing->vecPosition.z);
これだと回転と移動が同じパラメータで発生します。
構造体に
D3DXVECTOR3 Rotation;
と追加してこれで回転をコントロールしてください。
つまり
D3DXMatrixRotationY(&matRotation,pThing->Rotation.y);
となります。
使うときはこうなります。
case VK_SPACE: // 自キャラ(モデル)の回転
Thing[0].Rotation.y += 0.1f;
break;
Re: 3Dモデルの回転 -DirectX-
Posted: 2011年4月05日(火) 22:28
by Repsol
ありがとうございます。
ご回答の通り、コードを構造体に追記したところ、
無事にキャラクタモデルが回転致しました。
助かりました。
本当にありがとうございます。