3Dモデルの回転 -DirectX-

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Repsol

3Dモデルの回転 -DirectX-

#1

投稿記事 by Repsol » 14年前

質問させて下さい。
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));

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 3Dモデルの回転 -DirectX-

#2

投稿記事 by softya(ソフト屋) » 14年前

肝心のmatWorldとmatRotationの行列処理の部分が無いので、 どうなっているか分かりませんがmatWorld*matRotationとmatRotation*matWorldでは全く動作が異なります。
逆にしてみてください。
[追記]
あとmatRotationは3Dモデル・キャラクタだけに使ってくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Repsol

Re: 3Dモデルの回転 -DirectX-

#3

投稿記事 by Repsol » 14年前

御返事、ありがとうございます。
前述したソースに、
下記のようにコードを追記したら、
キャラクタのみ、回転することに成功しました。

コード:

case WM_KEYDOWN: // キーが押されたら
switch( wParam )
{
case VK_SPACE: // 自キャラ(モデル)の回転
Thing[0].vecPosition.y += 0.1f;
break;
}
ですが、回転に成功したのは良いものの、
今度はキャラクタが、回転しながらY軸方向上へと上っていってしまうんです。
この原因がよく分かりません。
本当は原点座標で回転させたいのですが・・・。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 3Dモデルの回転 -DirectX-

#4

投稿記事 by softya(ソフト屋) » 14年前

申し訳ないですが、InitThing()とかの関数が出てくるDirectX系のライブラリを存じません。
なので、Thing[0].vecPosition.yの値が何を意味するかも分かりません。
正確に回答したいと思いますので、参考にしている書籍あるいはサイトの情報とInitThing()などの関数の中身やThingの構造体あるいはクラスの定義を見せてください。Thingがクラスであれば、その関数処理も見たいです。

あと、vecPositionと言う名前からして回転系のパラメータには見えません。たぶん移動系のパラメータです。なにか勘違いされていないでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Repsol

Re: 3Dモデルの回転 -DirectX-

#5

投稿記事 by Repsol » 14年前

御返事、ありがとうございます。
参考にしている書籍は、工学社の「はじめての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 );
     }	 	
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 3Dモデルの回転 -DirectX-

#6

投稿記事 by softya(ソフト屋) » 14年前

同じパラメータが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;
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Repsol

Re: 3Dモデルの回転 -DirectX-

#7

投稿記事 by Repsol » 14年前

ありがとうございます。
ご回答の通り、コードを構造体に追記したところ、
無事にキャラクタモデルが回転致しました。
助かりました。
本当にありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る