【DirectX】行列を使用した2Dポリゴンの拡大縮小・回転について

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

【DirectX】行列を使用した2Dポリゴンの拡大縮小・回転について

#1

投稿記事 by うまお » 5年前

[1] 質問文
 [1.1] 自分が今行いたい事は何か
2Dゲームを作りたいがために板ポリゴンを用意して移動処理等を書いてみたが、拡大縮小・回転の処理が想定していた処理と違う(拡大縮小についてはポリゴンが移動しながら行われてしまい、回転に関してもポリゴンの位置も移動している)。その為拡大縮小と回転を板ポリゴンの中心を軸に行いたいがやり方がわからない。
 [1.2] どのように取り組んだか(プログラムコードがある場合記載)
Main.cpp

コード:

//=============================================================================
//【Main.cpp】
//メインとなるクラス
//=============================================================================

//*****************************************************************************
//インクルード・ヘッダーファイル
//*****************************************************************************
#include "Main.h"																//メインとなるヘッダー
#include "Player.h"																//Playerポリゴンのヘッダー

//*****************************************************************************
//ライブラリのリンク
//*****************************************************************************

//*****************************************************************************
//マクロ定義
//*****************************************************************************
#define CLASS_NAME		"ウィンドウのクラス名"									//ウィンドウのクラス名
#define WINDOW_NAME		"Windowsテンプレート"									//ウィンドウのキャプション名

//*****************************************************************************
//イーナム定義
//*****************************************************************************

//*****************************************************************************
//構造体定義
//*****************************************************************************

//*****************************************************************************
//プロトタイプ宣言
//*****************************************************************************
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);							//ウィンドウプロシジャ関数
HRESULT Init3D3(HWND, BOOL);													//Direct3D初期化関数
void	Uninit3D3(void);														//Direct3D終了処理関数
void	Update(void);															//更新処理関数
void	Draw(void);																//画面描写処理関数

//*****************************************************************************
//グローバル変数:
//*****************************************************************************
LPDIRECT3D9			g_pD3D = NULL;												//Direct3Dへアクセスするためのポインタ
LPDIRECT3DDEVICE9	g_pD3DDevice = NULL;										//ビデオカードへアクセスするためのポインタ


//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【メイン関数】
//WinMain()からプログラムが開始される
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int APIENTRY WinMain(
	HINSTANCE hInstance,														//インスタンスハンドル
	HINSTANCE hPrevInstance,													//未使用(常にNULL)
	LPSTR	  lpCmdLine,														//コマンドライン引数
	int		  nCmdShow)															//ウィンドウの表示方法
{
	//ウィンドウクラスを登録
	WNDCLASSEX wcex;															//WNDCLASSEX構造体の変数
	wcex.cbSize			= sizeof(WNDCLASSEX);									//WNDCLASSEX構造体のサイズ
	wcex.style			= CS_CLASSDC;											//ウインドウスタイル
	wcex.lpfnWndProc	= WndProc;												//ウィンドウプロシージャのアドレス
	wcex.cbClsExtra		= 0;													//補助メモリを追加するためのサイズ
	wcex.cbWndExtra		= 0;													//ウインドウを表す内部データ構造体に追加するメモリ
	wcex.hInstance		= hInstance;											//WinMain()のインスタンスハンドル
	wcex.hIcon			= LoadIcon(NULL, IDI_APPLICATION);						//タスクバーやタイトルバーに表示されるアイコン
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);							//hCursor:ウィンドウのクライアントエリア上のマウスカーソル
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW + 1);							//ウインドウのクライアント領域の背景色
	wcex.lpszMenuName	= NULL;													//メニュー
	wcex.lpszClassName	= TEXT(CLASS_NAME);										//Windowクラスの名前
	wcex.hIconSm		= LoadIcon(NULL, IDI_APPLICATION);						//使用する小さいアイコン
	if (RegisterClassEx(&wcex) == 0) return 0;									//RegisterClass関数を使用してNDCLASSEX構造体の登録を行い失敗したら終了する

	//ウィンドウ生成を行う
	HWND hWnd;																	//ウィンドウハンドルの変数
	hWnd = CreateWindowEx(														//CreateWindowEx関数を使用してウインドウを生成する。
		0,																		//拡張ウィンドウスタイル
		TEXT(CLASS_NAME),														//登録されているクラス名
		TEXT(WINDOW_NAME),														//タイトルバーに表示する文字列
		WS_OVERLAPPEDWINDOW,													//ウィンドウスタイル
		CW_USEDEFAULT,															//ウインドウ左上のX座標
		CW_USEDEFAULT,															//ウインドウ左上のY座標
		(SCREEN_WIDTH + GetSystemMetrics(SM_CXDLGFRAME) * 2),					//ウィンドウの幅
		(SCREEN_HEIGHT + GetSystemMetrics(SM_CYDLGFRAME) * 2)					//ウィンドウの高さ
		+ GetSystemMetrics(SM_CYCAPTION),
		NULL,																	//オーナー(親)ウィンドウのハンドル
		NULL,																	//メニューハンドルまたは子のID(識別子)
		hInstance,																//アプリケーションインスタンスのハンドル
		NULL);																	//ウィンドウ作成データ
	if (!hWnd) return 0;														//失敗した場合終了する

	//Direct3Dの初期化を行う
	if (FAILED(Init3D3(hWnd, WINMODE))) return 0;								//失敗した場合終了する

	ShowWindow(hWnd, nCmdShow);													//ShowWindow関数を使用してウィンドウを表示する
	UpdateWindow(hWnd);															//UpdateWindow関数を使用してウィンドウを更新する

	//FPS制御の準備を行う
	DWORD dwBeforeTime;															//時間更新前格納用変数
	DWORD dwAfterTime;															//時間更新後格納用変数
	timeBeginPeriod(1);															//ミリ単位で最小タイマ分解能を指定
	dwBeforeTime = timeGetTime();												//timeGetTime関数でソフト起動時のシステム時間をミリ単位で取得し格納する

	//メインメッセージループを行う
	MSG msg = { 0 };															//MSG構造体の変数
	while (WM_QUIT != msg.message)
	{
		//メッセージ処理
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {					//PeekMessage関数を使用してキューにメッセージがポストされてるかを確認する
			TranslateMessage(&msg);												//TranslateMessage関数を使用して押されているキーボードの情報をアプリケーションが取得できる形に変換してくれている
			DispatchMessage(&msg);												//DispatchMessage関数を使用して取得したメッセージをウインドウプロシージャに送る処理をする
		}
		//DirectX処理
		else {
			dwAfterTime = timeGetTime();										//timeGetTime関数で現在のシステム時間をミリ単位で取得し格納する
			if (FRAME_DIRAY <= dwAfterTime - dwBeforeTime) {					//フレーム周期 <= 現在のシステム時間-更新前のシステム時間の場合処理を行う
				dwBeforeTime = dwAfterTime;										//更新を行ったため現在のシステム時間を時間更新前格納用変数に格納
				Update();														//更新処理を行う
				Draw();															//描写処理を行う
			}
		}
	}

	//ウィンドウクラスを削除しメモリを解放する
	UnregisterClass(TEXT(CLASS_NAME), wcex.hInstance);

	//Direct3Dの終了処理を行う
	Uninit3D3();

	//WM_QUITメッセージを受け取って正常に終了する場合はmsg.wParamを返さないといけない
	//メッセージループに入る前の場合は0を返す
	return (int)msg.wParam;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【ウィンドウプロシージャ関数】
//メッセージループで取得したメッセージを処理する関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LRESULT CALLBACK WndProc(
	HWND   hWnd,																//メッセージが発生したウィンドウのハンドル
	UINT   message,																//メッセージコード
	WPARAM wParam,																//メッセージの付加情報(メッセージコードにより異なる)
	LPARAM lParam)																//メッセージの付加情報(メッセージコードにより異なる)
{
	//messageによってメッセージを判断する。
	switch (message)
	{
	case WM_DESTROY:															//ウィンドウ右上の閉じるボタンを押した際
		PostQuitMessage(0);														//PostQuitMessage関数を使用してWM_QUITメッセージを発生させる
		DestroyWindow(hWnd);
		break;

	default:																	//ウィンドウプロシージャが処理しない部分
		return DefWindowProc(hWnd, message, wParam, lParam);					//DefWindowProc関数を使用してWindows側で勝手に処理をさせる
																				//この関数を実行しないと基本的なウィンドウの動作ができなくなる
	}
	return 0;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Direct3D初期化関数】
//Direct3Dの初期化処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT Init3D3(
	HWND hWnd,																	//ウィンドウハンドル
	BOOL bWindow)																//ウィンドウモード
{
	D3DPRESENT_PARAMETERS d3dpp;												//D3DPRESENT_PARAMETERS構造体の変数
	D3DDISPLAYMODE		  d3ddm;												//D3DDISPLAYMODE構造体の変数

	//IDIRECT3D9コンポーネントの取得を行い、失敗したらE_FAILを返す
	if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) return E_FAIL;

	//GetAdapterDisplayMode関数を使用して現在のディスプレイモードの取得を行い、失敗したらE_FAILを返す
	if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) return E_FAIL;

	ZeroMemory(&d3dpp, sizeof(d3dpp));											//ZeroMemoryを使用してd3dppを初期化している?
	d3dpp.BackBufferWidth					= SCREEN_WIDTH;						//画面の幅
	d3dpp.BackBufferHeight					= SCREEN_HEIGHT;					//画面の高さ
	d3dpp.BackBufferFormat					= d3ddm.Format;						//バックバッファのフォーマット
	d3dpp.BackBufferCount					= 1;								//バックバッファの数
	d3dpp.MultiSampleType;														//マルチサンプルの数
	d3dpp.MultiSampleQuality;													//マルチサンプルの品質レベル
	d3dpp.SwapEffect						= D3DSWAPEFFECT_DISCARD;			//フロントバッファとバックバッファの切り替え方法
	d3dpp.hDeviceWindow;														//画面を描画するウィンドウハンドル
	d3dpp.Windowed							= bWindow;							//スクリーンモード
	d3dpp.EnableAutoDepthStencil			= TRUE;								//深度ステンシルバッファの有無
	d3dpp.AutoDepthStencilFormat			= D3DFMT_D24X8;						//ステンシルバッファのフォーマット
	d3dpp.Flags;																//バックバッファからフロントバッファへ転送する時の機能のオプション
	//ウィンドウモードごとの設定部分
	if (bWindow) {																//ウィンドウモード
		d3dpp.FullScreen_RefreshRateInHz	= 0;								//フルスクリーンでのリフレッシュレート
		d3dpp.PresentationInterval			= D3DPRESENT_INTERVAL_IMMEDIATE;	//スワップの書き換えタイミング
	}
	else {																		//フルスクリーンモード
		d3dpp.FullScreen_RefreshRateInHz	= D3DPRESENT_RATE_DEFAULT;
		d3dpp.PresentationInterval			= D3DPRESENT_INTERVAL_DEFAULT;
	}
																				//IDirect3DDevice9コンポーネントの取得を行い、失敗したらE_FAILを返す
	if (FAILED(g_pD3D->CreateDevice(											//最初に描画と頂点処理をハードウェアで行うようにする
		D3DADAPTER_DEFAULT,														//ディスプレイアダプタの番号
		D3DDEVTYPE_HAL,															//D3DDEVTYPE列挙型のメンバ
																				//D3DDEVTYPE_HALでハードウェアで描画実行をするように指定
		hWnd,																	//描画を行うウィンドウハンドル
		D3DCREATE_HARDWARE_VERTEXPROCESSING,									//デバイスの作成を制御するオプションフラグ
																				//D3DCREATE_HARDWARE_VERTEXPROCESSINGでハードウェアを使用して頂点処理を行うようにする
		&d3dpp,																	//D3DPRESENT_PARAMETERS構造体へのポインタ
		&g_pD3DDevice)))														//IDirect3DDevice9コンポーネントへのポインタ
		if (FAILED(g_pD3D->CreateDevice(										//上記で失敗したため描画をハードウェアで行い頂点処理をCPUで行うようにする
			D3DADAPTER_DEFAULT,
			D3DDEVTYPE_HAL,
			hWnd,
			D3DCREATE_SOFTWARE_VERTEXPROCESSING,								//D3DCREATE_SOFTWARE_VERTEXPROCESSINGでCPUを使用して頂点処理を行うようにする
			&d3dpp,
			&g_pD3DDevice)))
			if (FAILED(g_pD3D->CreateDevice(									//上記で失敗したため描画をCPUで行い頂点処理をハードウェアで行うようにする
				D3DADAPTER_DEFAULT,
				D3DDEVTYPE_REF,													//D3DDEVTYPE_REFでCPUで描画実行をするように指定
				hWnd,
				D3DCREATE_HARDWARE_VERTEXPROCESSING,
				&d3dpp,
				&g_pD3DDevice)))
				if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,				//上記で失敗したため描画と頂点処理をCPUで行うようにする
					D3DDEVTYPE_REF,
					hWnd,
					D3DCREATE_SOFTWARE_VERTEXPROCESSING,
					&d3dpp,
					&g_pD3DDevice)))
				{
					g_pD3D->Release();											//Release関数でメモリを開放する
					return E_FAIL;
				}

	//ポリゴンとテクスチャの色の乗算処理
	g_pD3DDevice->SetTextureStageState(											//ここでテクスチャの色を1番目の対象にする
		0,																		//対象となるテクスチャステージ
		D3DTSS_COLORARG1,														//D3DTEXTURESTAGESTATETYPE列挙型で合成対象や合成演算を決める
																				//D3DTSS_COLORARG1			:1番目に対象となる色の引数
		D3DTA_TEXTURE);															//上記の処理によって入るものが異なる
																				//D3DTA_TEXTURE				:テクスチャを対象

	g_pD3DDevice->SetTextureStageState(											//ここで色に対する処理を指定
		0,
		D3DTSS_COLOROP,															//D3DTSS_COLOROP			:色の演算子
		D3DTOP_MODULATE);														//D3DTOP_MODULATE			:乗算

	g_pD3DDevice->SetTextureStageState(											//ここでポリゴンの色を2番目の対象にする
		0,
		D3DTSS_COLORARG2,														//D3DTSS_COLORARG2			:2番目に対象となる色の引数
		D3DTA_DIFFUSE);															//D3DTA_DIFFUSE				:ポリゴンを対象

																				//αブレンディング処理を行う
	g_pD3DDevice->SetTextureStageState(											//テクスチャの色を1番目の対象にする
		0,
		D3DTSS_COLORARG1,
		D3DTA_TEXTURE);

	g_pD3DDevice->SetTextureStageState(											//色に対する処理を指定
		0,
		D3DTSS_COLOROP,
		D3DTOP_BLENDTEXTUREALPHA);												//D3DTOP_BLENDTEXTUREALPHA	:あらかじめ乗算されたアルファを使用するテクスチャステージの線形ブレンディングを実行する

	g_pD3DDevice->SetTextureStageState(											//ポリゴンの色を2番目の対象にする
		0,
		D3DTSS_COLORARG2,
		D3DTA_DIFFUSE);

	g_pD3DDevice->SetTextureStageState(											//ここでα値に対する処理を指定
		0,
		D3DTSS_ALPHAOP,
		D3DTOP_SELECTARG2);														//2番目の色はアルファ引数を変更せずに使用する

	g_pD3DDevice->SetTextureStageState(											//ポリゴンのα値を対象にする
		0,
		D3DTSS_ALPHAARG2,														//2番目のα値を対象
		D3DTA_DIFFUSE);

	//ポリゴンとテクスチャの透明度の乗算処理
	g_pD3DDevice->SetTextureStageState(											//ここでテクスチャのα値を対象にする
		0,
		D3DTSS_ALPHAARG1,														//D3DTSS_ALPHAARG1			:1番目に対象となるα値
		D3DTA_TEXTURE);

	g_pD3DDevice->SetTextureStageState(											//ここでα値に対する処理を指定
		0,
		D3DTSS_ALPHAOP,															//アルファブレンディング処理
		D3DTOP_MODULATE);

	g_pD3DDevice->SetTextureStageState(											//ここでポリゴンのα値を対象にする
		0,
		D3DTSS_ALPHAARG1,														//D3DTSS_ALPHAARG2			:2番目に対象となるα値
		D3DTA_TEXTURE);

	if (FAILED(InitPlayer(g_pD3D, g_pD3DDevice))) return E_FAIL;				//Playerポリゴン初期化処理

	return S_OK;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Direct3D終了処理関数】
//Direct3Dの終了処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Uninit3D3(void)
{
	if (g_pD3DDevice != NULL) {
		g_pD3DDevice->Release();
		g_pD3DDevice = NULL;
	}
	if (g_pD3D != NULL) {
		g_pD3D->Release();
		g_pD3D = NULL;
	}

	UninitPlayer();																//Playerポリゴン終了処理

}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【更新処理関数】
//更新に関する処理を扱う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Update(void)
{
	UpdataPlayer(g_pD3DDevice);																//Playerポリゴン更新処理
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【画面描写処理関数】
//ウィンドウの描写処理を扱う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Draw(void)
{
	//Clear関数で指定した色でクリアし、深度バッファをクリアする。更にステンシルバッファを削除する
	g_pD3DDevice->Clear(
		0,																		//クリアする矩形領域の数
		NULL,																	//矩形領域
		(D3DCLEAR_TARGET														//レンタリングターゲットをクリアしてClearパラメータの色にする
		| D3DCLEAR_ZBUFFER),													//深海バッファをクリアしてZパラメータの値にする
		D3DCOLOR_RGBA(0, 0, 0, 0),												//透明度100%で指定した色にクリア
		1.0f,																	//Zバッファのクリア値
		0);																		//ステンシルバッファのクリア値

	if (SUCCEEDED(g_pD3DDevice->BeginScene()))									//バックバッファに描画開始
	{

		DrawPlayer(g_pD3DDevice);												//Playerポリゴン描画処理

		g_pD3DDevice->EndScene();												//バックバッファの描画終了
	}

	g_pD3DDevice->Present(NULL, NULL, NULL, NULL);								//Present関数で画面に表示
}
Main.h

コード:

//=============================================================================
//【Main.h】
//メインとなるヘッダー
//=============================================================================
#ifndef _MAIN_H_														//二重定義防止の為に行う
#define _MAIN_H_

//*****************************************************************************
//インクルード・ヘッダーファイル
//*****************************************************************************
#include <windows.h>													//Windows標準関数実装
#include <d3d9.h>														//Direct3D関連実装
#include <d3dx9.h>														//Direct3D関連関数実装

//*****************************************************************************
//ライブラリのリンク
//*****************************************************************************
#pragma comment	(lib, "dxguid.lib")										//グローバルユニークIDに関わるライブラリ
#pragma comment	(lib, "d3d9.lib")										//Direct3Dコアライブラリ
#pragma comment	(lib, "d3dx9.lib")										//Direct3D拡張ライブラリ
#pragma comment	(lib,"winmm.lib")										//Windowsライブラリ

//*****************************************************************************
//マクロ定義
//*****************************************************************************
#define WINMODE			TRUE											//ウィンドウモードの指定
#define SCREEN_WIDTH	(800)											//ウィンドウの幅
#define SCREEN_HEIGHT	(600)											//ウインドウの高さ
#define SCREEN_CENTER_X (SCREEN_WIDTH/2)								//ウィンドウの中心座標X
#define SCREEN_CENTER_Y (SCREEN_HEIGHT/2)								//ウィンドウの中心座標Y
#define FPS				(60)											//1秒間に画面を更新する回数(フレーム/秒)
#define FRAME_DIRAY		((DWORD)(1000 / FPS))							//フレーム周期(1フレームあたりの最大処理時間)
#define NUM_VERTEX		(4)												//頂点の数
#define NUM_POLYGON		(2)												//ポリゴンの数

#define FVF_CUSTOM		(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)	//頂点情報フラグ
//D3DFVF_XYZRHW	:トランスフォームされた頂点の位置座標を含む頂点フォーマット
//D3DFVF_DIFFUSE:ディフューズ色成分を含む頂点フォーマット
//D3DFVF_TEX1	:テクスチャ座標の頂点フォーマット

//*****************************************************************************
//イーナム定義
//*****************************************************************************

//*****************************************************************************
//構造体定義
//*****************************************************************************
typedef struct	CUSTOMVERTEX											//2Dに必須なフォーマットをまとめた構造体の定義
{
	D3DXVECTOR3 pos;													//頂点座標
	float		rhw;													//除算数
	D3DCOLOR    col;													//頂点カラー
	D3DXVECTOR2 tex;													//テクスチャ座標
};

//*****************************************************************************
//プロトタイプ宣言
//*****************************************************************************

#endif
Player.cpp(今回の質問の箇所)

コード:

//=============================================================================
//【Player.cpp】
//Playerポリゴンを管理する関数を扱うクラス
//=============================================================================

//*****************************************************************************
//インクルード・ヘッダーファイル
//*****************************************************************************
#include "Player.h"

//*****************************************************************************
//ライブラリのリンク
//*****************************************************************************

//*****************************************************************************
//マクロ定義
//*****************************************************************************
//#define PLAYER_TEXTURENAME		 "DATA/TEXTURE/Player.png"											//テクスチャファイル名
#define PLAYER_INITPOS_X		 (SCREEN_CENTER_X)														//初期位置X
#define PLAYER_INITPOS_Y		 (SCREEN_CENTER_Y)														//初期位置Y
#define PLAYER_SIZE_X			 (50)																	//横幅
#define PLAYER_SIZE_Y			 (50)																	//横幅

//*****************************************************************************
//イーナム定義
//*****************************************************************************

//*****************************************************************************
//構造体定義
//*****************************************************************************

//*****************************************************************************
//プロトタイプ宣言
//*****************************************************************************
void MakeFormatPlayer(LPDIRECT3DDEVICE9 pDevice);														//Playerポリゴンフォーマット情報作成関数
void MovePlayer(float, float, float);																	//Playerポリゴン移動関数
void ZoomPlayer(float, float, float);																	//Playerポリゴン拡大縮小関数
void RotationPlayer(float);																				//Playerポリゴン回転関数

//*****************************************************************************
//グローバル変数:
//*****************************************************************************
CUSTOMVERTEX			g_pFormatPlayer[NUM_VERTEX];													//フォーマット情報格納用変数
LPDIRECT3DVERTEXBUFFER9 g_pVertexPlayer = NULL;															//頂点バッファコンポーネントへのポインタ

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン初期化関数】
//Playerポリゴンの初期化処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT InitPlayer(
	LPDIRECT3D9		  pD3D,																				//Direct3Dへアクセスするためのポインタ
	LPDIRECT3DDEVICE9 pDevice)																			//ビデオカードへアクセスするためのポインタ
{
	//フォーマット情報を作成する
	MakeFormatPlayer(pDevice);

	//頂点バッファの作成をする
	if (FAILED(pDevice->CreateVertexBuffer(
		sizeof(CUSTOMVERTEX) * 4,																		//確保する頂点バッファのサイズ
		D3DUSAGE_WRITEONLY,																				//リソースの使用法を定義するフラグ
		FVF_CUSTOM,																						//頂点フォーマットの型の指定
		D3DPOOL_MANAGED,																				//どの種類のメモリに頂点バッファを置くかの指定
		&g_pVertexPlayer,																				//頂点バッファコンポーネントへのポインタのアドレス
		NULL)))																							//特に使用されていない為NULL
	{
		pDevice->Release();
		pD3D->Release();
		return E_FAIL;
	}

	return S_OK;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン終了処理関数】
//Playerポリゴンの終了処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void UninitPlayer(void)
{
	if (g_pVertexPlayer != NULL) {
		g_pVertexPlayer->Release();
		g_pVertexPlayer = NULL;
	}
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン更新処理関数】
//Playeポリゴンrの更新処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void UpdataPlayer(LPDIRECT3DDEVICE9 pDevice)
{
	
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン描画処理関数】
//Playerポリゴンの描画処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void DrawPlayer(LPDIRECT3DDEVICE9 pDevice)																//ビデオカードへアクセスするためのポインタ
{
	//頂点バッファを書き込むためにメモリをロックする
	void *pData;
	if (SUCCEEDED(g_pVertexPlayer->Lock(
		0,																								//全体にロックをするため0
		sizeof(CUSTOMVERTEX) * 4,																		//ロックしたいメモリサイズ
		(void**)&pData,																					//ロックされたメモリ範囲の先頭アドレスへのポインタ
		0)))																							//ロック時の動作を定義するフラグ
	{
		memcpy(pData, g_pFormatPlayer, sizeof(CUSTOMVERTEX) * 4);
		g_pVertexPlayer->Unlock();
	}
	//ストリームソースという頂点処理の流れに頂点バッファを実際にセットする
	pDevice->SetStreamSource(
		0,																								//ストリームの番号
		g_pVertexPlayer,																				//頂点バッファコンポーネントへのポインタ
		0,																								//頂点データの書き始めを示すオフセット
		sizeof(CUSTOMVERTEX));																			//1頂点のサイズ
	//ストリームに頂点バッファの型を教える
	pDevice->SetFVF(FVF_CUSTOM);
	//頂点の結び方とポリゴンの描画枚数を指定
	pDevice->DrawPrimitive(
		D3DPT_TRIANGLESTRIP,																			//頂点をどう結びポリゴンにするかのフラグ
		0,																								//描画を開始する最初の頂点番号
		2);																								//描画するポリゴンの数
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴンフォーマット情報作成関数】
//Playerポリゴンのフォーマット情報作成処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void MakeFormatPlayer(LPDIRECT3DDEVICE9 pDevice)														//ビデオカードへアクセスするためのポインタ
{
	//頂点座標設定
	g_pFormatPlayer[0].pos =																			//左上
		D3DXVECTOR3(PLAYER_INITPOS_X - PLAYER_SIZE_X / 2, PLAYER_INITPOS_Y - PLAYER_SIZE_Y / 2, 0.0f);
	g_pFormatPlayer[1].pos =																			//右上
		D3DXVECTOR3(PLAYER_INITPOS_X + PLAYER_SIZE_X / 2, PLAYER_INITPOS_Y - PLAYER_SIZE_Y / 2, 0.0f);
	g_pFormatPlayer[2].pos =																			//左下
		D3DXVECTOR3(PLAYER_INITPOS_X - PLAYER_SIZE_X / 2, PLAYER_INITPOS_Y + PLAYER_SIZE_Y / 2, 0.0f);
	g_pFormatPlayer[3].pos =																			//右下
		D3DXVECTOR3(PLAYER_INITPOS_X + PLAYER_SIZE_X / 2, PLAYER_INITPOS_Y + PLAYER_SIZE_Y / 2, 0.0f);
	//除算数設定
	g_pFormatPlayer[0].rhw = 1.0f;
	g_pFormatPlayer[1].rhw = 1.0f;
	g_pFormatPlayer[2].rhw = 1.0f;
	g_pFormatPlayer[3].rhw = 1.0f;
	//頂点カラー設定
	g_pFormatPlayer[0].col =
		D3DCOLOR_RGBA(255, 255, 255, 255);
	g_pFormatPlayer[1].col =
		D3DCOLOR_RGBA(255, 255, 255, 255);
	g_pFormatPlayer[2].col =
		D3DCOLOR_RGBA(255, 255, 255, 255);
	g_pFormatPlayer[3].col =
		D3DCOLOR_RGBA(255, 255, 255, 255);
	//テクスチャ座標設定
	g_pFormatPlayer[0].tex =
		D3DXVECTOR2(0.0f, 0.0f);																		//左上
	g_pFormatPlayer[1].tex =
		D3DXVECTOR2(1.0f, 0.0f);																		//右上
	g_pFormatPlayer[2].tex =
		D3DXVECTOR2(0.0f, 1.0f);																		//左下
	g_pFormatPlayer[3].tex =
		D3DXVECTOR2(1.0f, 1.0f);																		//右下
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン移動関数】
//Playerポリゴンの移動処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void MovePlayer(
	float x,																							//移動距離X
	float y,																							//移動距離Y
	float z)																							//移動距離Z
{
	D3DXMATRIX PosMatrix;																				//Playerポリゴンの現在位置格納用単位行列
	D3DXMATRIX MoveMatrix;																				//Playerポリゴンの移動量格納用単位行列
	//行列初期化
	D3DXMatrixIdentity(&PosMatrix);
	D3DXMatrixIdentity(&MoveMatrix);
	//移動処理
	D3DXMatrixTranslation(																				//D3DXMatrixTranslation関数を使用してMoveMatrixに移動量を格納する
		&MoveMatrix,
		x,
		y,
		z);
	for (int i = 0; i < NUM_VERTEX; i++) {
		D3DXMatrixTranslation(																			//D3DXMatrixTranslation関数を使用してPosMatrixに現在地を格納する
			&PosMatrix,
			g_pFormatPlayer[i].pos.x,
			g_pFormatPlayer[i].pos.y,
			g_pFormatPlayer[i].pos.z);
		PosMatrix *= MoveMatrix;																		//現在地の行列に移動量行列を加算する
		g_pFormatPlayer[i].pos.x = PosMatrix._41;														//演算結果をポリゴンのX座標に格納する
		g_pFormatPlayer[i].pos.y = PosMatrix._42;														//演算結果をポリゴンのY座標に格納する
		g_pFormatPlayer[i].pos.z = PosMatrix._43;														//演算結果をポリゴンのZ座標に格納する
	}
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン拡大縮小関数】
//Playerポリゴンの拡大処理と縮小処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void ZoomPlayer(float x, float y, float z)
{

	D3DXMATRIX	PosMatrix;																				//Playerポリゴンの現在位置格納用単位行列
	D3DXMATRIX	ZoomMatrix;																				//Playerポリゴンの拡張量格納用単位行列

	//行列初期化
	D3DXMatrixIdentity(&PosMatrix);
	D3DXMatrixIdentity(&ZoomMatrix);

	//拡大縮小処理
	D3DXMatrixScaling(																					//D3DXMatrixScaling関数を使用してZoomMatrixに拡張量を格納する
		&ZoomMatrix,
		x,
		y,
		z);
	for (int i = 0; i < NUM_VERTEX; i++) {
		D3DXMatrixTranslation(																			//D3DXMatrixTranslation関数を使用してPosMatrixに現在地を格納する
			&PosMatrix,
			g_pFormatPlayer[i].pos.x,
			g_pFormatPlayer[i].pos.y,
			g_pFormatPlayer[i].pos.z);
		PosMatrix *= ZoomMatrix;																		//現在地の行列に拡張量行列を加算する
		g_pFormatPlayer[i].pos.x = PosMatrix._41;														//演算結果をポリゴンのX座標に格納する
		g_pFormatPlayer[i].pos.y = PosMatrix._42;														//演算結果をポリゴンのY座標に格納する
		g_pFormatPlayer[i].pos.z = PosMatrix._43;														//演算結果をポリゴンのZ座標に格納する
	}
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン回転関数】
//Playerポリゴンの回転処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void RotationPlayer(float angle)
{
	D3DXMATRIX	PosMatrix;																				//Playerポリゴンの現在位置格納用単位行列
	D3DXMATRIX	RotationMatrix;																			//Playerポリゴンの回転量格納用単位行列

	//行列初期化
	D3DXMatrixIdentity(&PosMatrix);
	D3DXMatrixIdentity(&RotationMatrix);

	//拡大縮小処理
	D3DXMatrixRotationZ(																				//D3DXMatrixRotationZ関数を使用してRotationMatrixに回転量を格納する
		&RotationMatrix,
		D3DXToRadian(angle));
	for (int i = 0; i < NUM_VERTEX; i++) {
		D3DXMatrixTranslation(																			//D3DXMatrixTranslation関数を使用してPosMatrixに現在地を格納する
			&PosMatrix,
			g_pFormatPlayer[i].pos.x,
			g_pFormatPlayer[i].pos.y,
			g_pFormatPlayer[i].pos.z);
		PosMatrix *= RotationMatrix;																	//現在地の行列に回転量行列を加算する
		g_pFormatPlayer[i].pos.x = PosMatrix._41;														//演算結果をポリゴンのX座標に格納する
		g_pFormatPlayer[i].pos.y = PosMatrix._42;														//演算結果をポリゴンのY座標に格納する
		g_pFormatPlayer[i].pos.z = PosMatrix._43;														//演算結果をポリゴンのZ座標に格納する
	}
}
Player.h

コード:

//=============================================================================
//【Player.h】
//Playerポリゴン用ヘッダー
//=============================================================================
#ifndef _Player_H_									//二重定義防止の為に行う
#define _Player_H_

//*****************************************************************************
//インクルード・ヘッダーファイル
//*****************************************************************************
#include "Main.h"

//*****************************************************************************
//ライブラリのリンク
//*****************************************************************************

//*****************************************************************************
//マクロ定義
//*****************************************************************************

//*****************************************************************************
//イーナム定義
//*****************************************************************************

//*****************************************************************************
//構造体定義
//*****************************************************************************

//*****************************************************************************
//プロトタイプ宣言
//*****************************************************************************
HRESULT InitPlayer(LPDIRECT3D9, LPDIRECT3DDEVICE9);	//Playerポリゴン初期化処理関数
void	UninitPlayer(void);							//Playerポリゴン終了処理関数
void	UpdataPlayer(LPDIRECT3DDEVICE9 pDevic);		//Playerポリゴン更新処理関数
void	DrawPlayer(LPDIRECT3DDEVICE9 pDevice);		//Player描画処理関数

#endif
 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
実行できている為割愛。
 [1.4] 今何がわからないのか、知りたいのか
板ポリゴンの中心を軸に位置が変わらなず回転・拡大縮小を行いたい。
[2] 環境  
 [2.1] OS:Windows10
 [2.2] コンパイラ名: Visual C++ 2017

[3] その他
・C、DirectX共に半年触ったか触っていないか程度。現在きちんと講習を受けている最中。
 正し軽い基礎はjavaを1年独学でやっていた。

参照魚
記事: 109
登録日時: 6年前

Re: 【DirectX】行列を使用した2Dポリゴンの拡大縮小・回転について

#2

投稿記事 by 参照魚 » 5年前

頂点座標にプレイヤーの位置(PLAYER_INIT_POS)を入れているため原点(画面左上)を中心に拡縮・回転がされてしまっていると思われます。

うまお

Re: 【DirectX】行列を使用した2Dポリゴンの拡大縮小・回転について

#3

投稿記事 by うまお » 5年前

参照魚 さんが書きました:
5年前
頂点座標にプレイヤーの位置(PLAYER_INIT_POS)を入れているため原点(画面左上)を中心に拡縮・回転がされてしまっていると思われます。
プレイヤーの初期位置を中心にポリゴンを形成するのでそこが変わるならどのように書けばいいのでしょうか…?

参照魚
記事: 109
登録日時: 6年前

Re: 【DirectX】行列を使用した2Dポリゴンの拡大縮小・回転について

#4

投稿記事 by 参照魚 » 5年前

プレイヤーの位置は移動行列により実現されます。

コード:

D3DXMatrixScaling( &ZoomMatrix, x, y, 1.0f); // 2DならZ軸方向の拡縮は影響しないので1
D3DXMatrixRotationZ( &RotationMatrix, D3DXToRadian(angle) );
D3DXMatrixTranslation( &MoveMatrix, PLAYER_INIT_POS_X, PLAYER_INIT_POS_Y, 0.0f ); // 2DならZ軸方向の拡縮は影響しないので0

// 拡縮×回転×移動の掛け算で変換行列が生成されます
const D3DXMATRIX TransformMatrix = ZoomMatrix * RotationMatrix * MoveMatrix;

//ポリゴンの頂点座標(ポリゴンの中心を原点とした場合の各頂点の位置)
const D3DXVECTOR2 inVector[NUM_VERTEX] = {
 D3DXVECTOR2(-PLAYER_SIZE_X/2, -PLAYER_SIZE_Y/2),
 D3DXVECTOR2(+PLAYER_SIZE_X/2, -PLAYER_SIZE_Y/2),
 D3DXVECTOR2(-PLAYER_SIZE_X/2, +PLAYER_SIZE_Y/2),
 D3DXVECTOR2(+PLAYER_SIZE_X/2, +PLAYER_SIZE_Y/2),
};

// 変換後頂点を格納する変数
D3DXVECTOR4 outVector;

for (int i = 0; i < NUM_VERTEX; i++) {
 D3DXVec2Transform( &outVector,&inVector, &TransformMatrix ); //各頂点座標を変換する
 
 // 変換結果を頂点座標に格納
 g_pFormatPlayer[i].pos.x = outVector.x;
 g_pFormatPlayer[i].pos.y = outVector.y;
 g_pFormatPlayer[i].pos.z = 0.0f;
}

うまお

Re: 【DirectX】行列を使用した2Dポリゴンの拡大縮小・回転について

#5

投稿記事 by うまお » 5年前

参照魚 さんが書きました:
5年前
プレイヤーの位置は移動行列により実現されます。

コード:

D3DXMatrixScaling( &ZoomMatrix, x, y, 1.0f); // 2DならZ軸方向の拡縮は影響しないので1
D3DXMatrixRotationZ( &RotationMatrix, D3DXToRadian(angle) );
D3DXMatrixTranslation( &MoveMatrix, PLAYER_INIT_POS_X, PLAYER_INIT_POS_Y, 0.0f ); // 2DならZ軸方向の拡縮は影響しないので0

// 拡縮×回転×移動の掛け算で変換行列が生成されます
const D3DXMATRIX TransformMatrix = ZoomMatrix * RotationMatrix * MoveMatrix;

//ポリゴンの頂点座標(ポリゴンの中心を原点とした場合の各頂点の位置)
const D3DXVECTOR2 inVector[NUM_VERTEX] = {
 D3DXVECTOR2(-PLAYER_SIZE_X/2, -PLAYER_SIZE_Y/2),
 D3DXVECTOR2(+PLAYER_SIZE_X/2, -PLAYER_SIZE_Y/2),
 D3DXVECTOR2(-PLAYER_SIZE_X/2, +PLAYER_SIZE_Y/2),
 D3DXVECTOR2(+PLAYER_SIZE_X/2, +PLAYER_SIZE_Y/2),
};

// 変換後頂点を格納する変数
D3DXVECTOR4 outVector;

for (int i = 0; i < NUM_VERTEX; i++) {
 D3DXVec2Transform( &outVector,&inVector, &TransformMatrix ); //各頂点座標を変換する
 
 // 変換結果を頂点座標に格納
 g_pFormatPlayer[i].pos.x = outVector.x;
 g_pFormatPlayer[i].pos.y = outVector.y;
 g_pFormatPlayer[i].pos.z = 0.0f;
}
何とかうまく行きました。
とりあえずPLAYER_INITPOSがWorld座標に当てはまることが分かったためInitPlayer関数で生成後に初期位置に移動するという仕組みに変更しました。

また、行列での移動、回転、拡大縮小処理をすべてまとめて以下の関数化ができたのでこちらを使用して移動等を行うようにしました。

コード:

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//【Playerポリゴン座標変更関数】
//Playerポリゴンの座標の変更処理を行う関数
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PosChangePlayer(
	float moveX,																										//X移動量
	float moveY,																										//Y移動量
	float moveZ,																										//Z移動量
	float zoomX,																										//X拡張量
	float zoomY,																										//Y拡張量
	float zoomZ,																										//Z拡張量
	float angle)																										//回転量
{
	D3DXMATRIX	PosMatrix;																								//Playerポリゴンの現在位置格納用単位行列
	D3DXMATRIX	MoveMatrix;																								//Playerポリゴンの移動量格納用単位行列
	D3DXMATRIX	ZoomMatrix;																								//Playerポリゴンの拡張量格納用単位行列
	D3DXMATRIX	RotationMatrix;																							//Playerポリゴンの回転量格納用単位行列

	//行列初期化
	D3DXMatrixIdentity(&MoveMatrix);
	D3DXMatrixIdentity(&PosMatrix);
	D3DXMatrixIdentity(&ZoomMatrix);
	D3DXMatrixIdentity(&RotationMatrix);

	//D3DXMatrixTranslation関数を使用してMoveMatrixに移動量を格納する
	D3DXMatrixTranslation(
		&MoveMatrix,
		moveX,
		moveY,
		moveZ);
	//D3DXMatrixScaling関数を使用してZoomMatrixに拡張量を格納する
	D3DXMatrixScaling(
		&ZoomMatrix,
		zoomX,
		zoomY,
		zoomZ);
	//D3DXMatrixRotationZ関数を使用してRotationMatrixに回転量を格納する
	D3DXMatrixRotationZ(
		&RotationMatrix,
		D3DXToRadian(angle));

	for (int i = 0; i < NUM_VERTEX; i++) {
		PosMatrix = g_pBasePosMATRIXPlayer[i] * ZoomMatrix * RotationMatrix * MoveMatrix;								//現在地の行列に計算した今までの行列を加算して格納する
		g_pFormatPlayer[i].pos.x = PosMatrix._41;																		//演算結果をポリゴンのX座標に格納する
		g_pFormatPlayer[i].pos.y = PosMatrix._42;																		//演算結果をポリゴンのY座標に格納する
		g_pFormatPlayer[i].pos.z = PosMatrix._43;																		//演算結果をポリゴンのZ座標に格納する
	}
}
新しく増えたg_pBasePosMATRIXPlayerについては頂点座標を決める際に以下の処理を加えてベースとなるMatrixを作成してます。

コード:

	//頂点座標設定
	g_pFormatPlayer[0].pos =																							//左上
		D3DXVECTOR3(-PLAYER_SIZE_X / 2,  -PLAYER_SIZE_Y / 2, 0.0f);
	g_pFormatPlayer[1].pos =																							//右上
		D3DXVECTOR3(+ PLAYER_SIZE_X / 2,  - PLAYER_SIZE_Y / 2, 0.0f);
	g_pFormatPlayer[2].pos =																							//左下
		D3DXVECTOR3( - PLAYER_SIZE_X / 2,  + PLAYER_SIZE_Y / 2, 0.0f);
	g_pFormatPlayer[3].pos =																							//右下
		D3DXVECTOR3( + PLAYER_SIZE_X / 2,  + PLAYER_SIZE_Y / 2, 0.0f);
	D3DXMatrixTranslation(&g_pBasePosMATRIXPlayer[0], g_pFormatPlayer[0].pos.x, g_pFormatPlayer[0].pos.y, g_pFormatPlayer[0].pos.z);
	D3DXMatrixTranslation(&g_pBasePosMATRIXPlayer[1], g_pFormatPlayer[1].pos.x, g_pFormatPlayer[1].pos.y, g_pFormatPlayer[0].pos.z);
	D3DXMatrixTranslation(&g_pBasePosMATRIXPlayer[2], g_pFormatPlayer[2].pos.x, g_pFormatPlayer[2].pos.y, g_pFormatPlayer[0].pos.z);
	D3DXMatrixTranslation(&g_pBasePosMATRIXPlayer[3], g_pFormatPlayer[3].pos.x, g_pFormatPlayer[3].pos.y, g_pFormatPlayer[0].pos.z);

返信

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