3Dプログラミング基本 1-3

~移動、拡大縮小、回転~

1-3-1.各種の変数宣言

D3DXVECTOR3     g_pos = D3DXVECTOR3(0,0,0);     //  座標			
D3DXVECTOR3     g_rot = D3DXVECTOR3(0,0,0);     //  回転			
D3DXVECTOR3     g_scal = D3DXVECTOR3(1,1,1);    //  拡大縮小			
D3DXMATRIX      g_matrix;                       //  上記の3変数をまとめて管理する行列変数		
        

DirectXでは3つの値を持つ変数としてD3DXVECTOR3型が定義されています。

▲TOP

1-3-2.移動処理

//キーボード入力							
if(DXUTIsKeyDown(VK_UP))    //上キー入力		
{							
	g_pos.z += 0.2f;        //Z方向に0.2f分加算		
}							
if(DXUTIsKeyDown(VK_DOWN))  //下キー入力		
{							
	g_pos.z -= 0.2f;        //Z方向に0.2f分減算		
}							
if(DXUTIsKeyDown(VK_RIGHT)  //右キー入力		
{							
	g_pos.x += 0.2f;        //X方向に0.2f分加算		
}							
if(DXUTIsKeyDown(VK_LEFT))  //左キー入力		
{							
	g_pos.x -= 0.2f;        //X方向に0.2f分減算		
        
  

▲TOP

1-3-3.拡大縮小処理

//X軸拡縮							
if(DXUTIsKeyDown('Q'))  //Qキー入力		
{							
	g_scal.x += 0.2f;   //X方向に0.2f分拡大		
}							
if(DXUTIsKeyDown('W'))  //Wキー入力		
{							
	g_scal.x -= 0.2f;   //X方向に0.2f分縮小		
}							
//Y軸拡縮							
if(DXUTIsKeyDown('A'))  //Aキー入力		
{							
	g_scal.y += 0.2f;   //Y方向に0.2f分拡大		
}							
if(DXUTIsKeyDown('S'))  //Sキー入力		
{							
	g_scal.y -= 0.2f;   //Y方向に0.2f分縮小		
}							
//Z軸拡縮							
if(DXUTIsKeyDown('Z'))  //Zキー入力		
{							
	g_scal.z += 0.2f;   //Z方向に0.2f分拡大		
}							
if(DXUTIsKeyDown('X'))  //Xキー入力		
{							
	g_scal.z -= 0.2f;   //Z方向に0.2f分縮小		
}															
        
  

▲TOP

1-2-4.回転処理

if(DXUTIsKeyDown(VK_SHIFT)) //SHIFTキー入力		
{							
	//ピッチ(X軸回転)						
	if(DXUTIsKeyDown('Q'))  //Qキー入力		
	{						
		g_rot.x += 0.2f;    //X軸方向に0.2f分加算回転		
	}						
	if(DXUTIsKeyDown('W'))  //Wキー入力		
	{						
		g_rot.x -= 0.2f;    //X軸方向に0.2f分減算回転		
	}						
	//ヨー(Y軸回転)						
	if(DXUTIsKeyDown('A'))  //Aキー入力		
	{						
		g_rot.y += 0.2f;    //Y軸方向に0.2f分加算回転		
	}						
	if(DXUTIsKeyDown('S'))  //Sキー入力		
	{						
		g_rot.y -= 0.2f;    //Y軸方向に0.2f分減算回転		
	}						
	//ロール(Z軸回転)						
	if(DXUTIsKeyDown('Z'))  //Zキー入力		
	{						
		g_rot.z += 0.2f;    //Z軸方向に0.2f分加算回転		
	}						
	if(DXUTIsKeyDown('X'))  //Xキー入力		
	{						
		g_rot.z -= 0.2f;    //Z軸方向に0.2f分減算回転		
	}						
}																	
        

▲TOP

1-3-5.移動・拡大縮小・回転情報をまとめ、セットする

D3DXMATRIX t_matrix;    //作業用行列変数								
        
//  モデルを表示するためのマトリクス作成										
D3DXMatrixTranslation(&g_matrix , g_pos.x , g_pos.y ,g_pos.z);                 //  移動マトリクスの作成		
D3DXMatrixScaling(&t_matrix , g_scal.x , g_scal.y ,g_scal.z);                  //  拡大縮小マトリクスの作成		
//  ここで移動マトリクスと拡大縮小マトリクスを合成する										
g_matrix = t_matrix * g_matrix;                                                 //  掛け算をする順番が大事		
D3DXMatrixRotationYawPitchRoll(&t_matrix , g_rot.y , g_rot.x , g_rot.z);        //  回転マトリクスの作成		
//  ここで移動&拡大縮小マトリクスと回転マトリクスを合成する										
g_matrix = t_matrix * g_matrix;                                                 //  掛け算をする順番が大事							
        
DXUTGetD3DDevice()->SetTransform(D3DTS_WORLD, &g_matrix);   //  マトリクスのセット						
        

▲TOP

1-3-6.デバッグ用数値表示

#include 							
        
//  フォント変数	
LPD3DXFONT pFont;							
        
//	フォントの作成			
D3DXCreateFont( DXUTGetD3DDevice(),				
	16,			
	0,			
	FW_NORMAL,			
	1,			
	false,			
	DEFAULT_CHARSET,			
	OUT_DEFAULT_PRECIS,			
	DEFAULT_QUALITY,			
	DEFAULT_PITCH,			
	L"",			
	&pFont);							
        
//  文字列の準備と生成・表示							
TCHAR str[255];								
RECT rect;								
								
SetRect( &rect , 0,0,640,480);								
_stprintf( str ,L"座標:%.2f %.2f %.2f",g_pos.x , g_pos.y ,g_pos.z);								
pFont->DrawText( NULL,str,-1,&rect,NULL,D3DCOLOR_RGBA(255,255,255,255));								
SetRect( &rect , 0,20,640,480);								
_stprintf( str ,L"拡大縮小:%.2f %.2f %.2f",g_scal.x , g_scal.y ,g_scal.z);								
pFont->DrawText( NULL,str,-1,&rect,NULL,D3DCOLOR_RGBA(255,255,255,255));								
SetRect( &rect , 0,40,640,480);								
_stprintf( str ,L"回転:%.2f %.2f %.2f",g_rot.x , g_rot.y ,g_rot.z);								
pFont->DrawText( NULL,str,-1,&rect,NULL,D3DCOLOR_RGBA(255,255,255,255));						
        

ここで、_Tマクロについて説明する。(※補足のため、読み飛ばしてもよい。)


まずは、基礎知識のUnicodeとMBCSについてです。

近年、主流になりつつあるUnicode (ユニコード) は、世界中の文字を表すことのできる国際対応の文字セットです。

MBCS(Multibyte-Character Set:マルチバイト文字セット) は,日本で言えば Shift_JIS のような文字セットのことで、

1 文字を 1 バイトで表現できない言語で従来から使われてきた文字セットのことです。

Visual Studio 2005 以降では「Unicode 文字セットを使用する」がデフォルトの設定となっています。

そして、C言語 の文字型としてchar 型の他にワイド文字用のwchar_t 型というものがあります。

Unicode を使用する設定が有効になっているとき,文字は char 型でなく wchar_t 型扱いとなります。)

wchar_t 型の文字リテラルには,L'c' のようにプリフィックス L を付けなければなりません。


ここで、登場するのが_Tマクロです。

_Tマクロはtchar.h の中に定義されていて,_UNICODE が宣言されているときにだけ,プリフィックス L を付してくれます。

宣言されていないときには、Lをつけません。

例えば,_T("hoge") 書くと,_UNICODE が宣言されているときには L"hoge",宣言されていないときには "hoge" と変換されます。

このようにUnicodeとMBCSに対応したものだということが分かってもらえたと思います。

よって今後は、L""だったところは、_T("")と直してコードを書いて行きます。

▲TOP

1-3-7.プログラミング

DxStdAfx.h (EmptyProject.cppではないので注意)

※追加箇所はマーカーで表記

//--------------------------------------------------------------------------------------										
// File: DxStdAfx.h										
//										
// Desc: Standard includes and precompiled headers for DXUT										
//										
// Copyright (c) Microsoft Corporation. All rights reserved.										
//--------------------------------------------------------------------------------------										
#pragma once										
#ifndef DXSDK_STDAFX_H										
#define DXSDK_STDAFX_H										
										
#ifndef STRICT										
#define STRICT										
#endif										
										
// If app hasn't choosen, set to work with Windows 98, Windows Me, Windows 2000, Windows XP and beyond										
#ifndef WINVER										
#define WINVER         0x0410										
#endif										
#ifndef _WIN32_WINDOWS										
#define _WIN32_WINDOWS 0x0410 										
#endif										
#ifndef _WIN32_WINNT										
#define _WIN32_WINNT   0x0500 										
#endif										
										
#define DIRECTSOUND_VERSION 0x0800										
										
// #define DXUT_AUTOLIB to automatically include the libs needed for DXUT 										
#ifdef DXUT_AUTOLIB										
#pragma comment( lib, "dxerr.lib" )										
#pragma comment( lib, "dxguid.lib" )										
#if defined(DEBUG) || defined(_DEBUG)										
#pragma comment( lib, "d3dx9d.lib" )										
#else										
#pragma comment( lib, "d3dx9.lib" )										
#endif										
#pragma comment( lib, "d3d9.lib" )										
#pragma comment( lib, "winmm.lib" )										
#pragma comment( lib, "comctl32.lib" )										
#endif										
										
#pragma warning( disable : 4100 )       // disable unreference formal parameter warnings for /W4 builds										
#include 										
#include 										
#include 										
#include 										
#include 										
#include                    // for InitCommonControls() 										
#include                    // for ExtractIcon()										
#include                         // for placement new										
#include       										
#include       										
#include 										
#include                      // Header for XInput APIs											
        

↓EmptyProject.cpp

//--------------------------------------------------------------------------------------													
// File: EmptyProject.cpp													
//													
// Empty starting point for new Direct3D applications													
//													
// Copyright (c) Microsoft Corporation. All rights reserved.													
//--------------------------------------------------------------------------------------													
#include "dxstdafx.h"													
#include "resource.h"													
													
//	フォント変数												
LPD3DXFONT pFont;													
																									
//変数宣言													
CDXUTMesh		*g_mesh;				//	モデルを扱うポインタ変数						
D3DXVECTOR3		g_pos = D3DXVECTOR3(0,0,0);				//	座標						
D3DXVECTOR3		g_rot = D3DXVECTOR3(0,0,0);				//	回転						
D3DXVECTOR3		g_scal = D3DXVECTOR3(1,1,1);				//	拡大縮小						
D3DXMATRIX		g_matrix;				//	上記の3変数をまとめて管理する行列変数						
																							
//--------------------------------------------------------------------------------------													
// Rejects any devices that aren't acceptable by returning false													
//--------------------------------------------------------------------------------------													
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 													
                                  D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )													
{													
    // Typically want to skip backbuffer formats that don't support alpha blending													
    IDirect3D9* pD3D = DXUTGetD3DObject(); 													
    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,													
                    AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 													
                    D3DRTYPE_TEXTURE, BackBufferFormat ) ) )													
        return false;													
													
    return true;													
}													
													
//--------------------------------------------------------------------------------------													
// Before a device is created, modify the device settings as needed													
//--------------------------------------------------------------------------------------													
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext )													
{													
    return true;													
}													
													
//--------------------------------------------------------------------------------------													
// Create any D3DPOOL_MANAGED resources here 													
//--------------------------------------------------------------------------------------													
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )													
{													
    return S_OK;													
}													
													
//--------------------------------------------------------------------------------------													
// Create any D3DPOOL_DEFAULT resources here 													
//--------------------------------------------------------------------------------------													
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 													
                                const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )													
{													
    return S_OK;													
}													
													
//--------------------------------------------------------------------------------------													
// Handle updates to the scene													
//--------------------------------------------------------------------------------------													
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )													
{													
	D3DXMATRIX t_matrix;					//作業用行列変数							
													
	//キーボード入力												
	if(DXUTIsKeyDown(VK_UP))					//上キー入力							
	{												
		g_pos.z += 0.2f;				//Z方向に0.2f分加算							
	}												
	if(DXUTIsKeyDown(VK_DOWN))					//下キー入力							
	{												
		g_pos.z -= 0.2f;				//Z方向に0.2f分減算							
	}												
	if(DXUTIsKeyDown(VK_RIGHT))					//右キー入力							
	{												
		g_pos.x += 0.2f;				//X方向に0.2f分加算							
	}												
	if(DXUTIsKeyDown(VK_LEFT))					//左キー入力							
	{												
		g_pos.x -= 0.2f;				//X方向に0.2f分減算							
	}												
													
	if(DXUTIsKeyDown(VK_SHIFT))					//SHIFTキー入力							
	{												
		//ピッチ(X軸回転)											
		if(DXUTIsKeyDown('Q'))				//Qキー入力							
		{											
			g_rot.x += 0.2f;			//X軸方向に0.2f分加算回転							
		}											
		if(DXUTIsKeyDown('W'))				//Wキー入力							
		{											
			g_rot.x -= 0.2f;			//X軸方向に0.2f分減算回転							
		}											
		//ヨー(Y軸回転)											
		if(DXUTIsKeyDown('A'))				//Aキー入力							
		{											
			g_rot.y += 0.2f;			//Y軸方向に0.2f分加算回転							
		}											
		if(DXUTIsKeyDown('S'))				//Sキー入力							
		{											
			g_rot.y -= 0.2f;			//Y軸方向に0.2f分減算回転							
		}											
		//ロール(Z軸回転)											
		if(DXUTIsKeyDown('Z'))				//Zキー入力							
		{											
			g_rot.z += 0.2f;			//Z軸方向に0.2f分加算回転							
		}											
		if(DXUTIsKeyDown('X'))				//Xキー入力							
		{											
			g_rot.z -= 0.2f;			//Z軸方向に0.2f分減算回転							
		}											
	}												
	else												
	{												
		//X軸拡縮											
		if(DXUTIsKeyDown('Q'))				//Qキー入力							
		{											
			g_scal.x += 0.2f;			//X方向に0.2f分拡大							
		}											
		if(DXUTIsKeyDown('W'))				//Wキー入力							
		{											
			g_scal.x -= 0.2f;			//X方向に0.2f分縮小							
		}											
		//Y軸拡縮											
		if(DXUTIsKeyDown('A'))				//Aキー入力							
		{											
			g_scal.y += 0.2f;			//Y方向に0.2f分拡大							
		}											
		if(DXUTIsKeyDown('S'))				//Sキー入力							
		{											
			g_scal.y -= 0.2f;			//Y方向に0.2f分縮小							
		}											
		//Z軸拡縮											
		if(DXUTIsKeyDown('Z'))				//Zキー入力							
		{											
			g_scal.z += 0.2f;			//Z方向に0.2f分拡大							
		}											
		if(DXUTIsKeyDown('X'))				//Xキー入力							
		{											
			g_scal.z -= 0.2f;			//Z方向に0.2f分縮小							
		}											
	}												
													
	//	モデルを表示するためのマトリクス作成											
	D3DXMatrixTranslation(&g_matrix , g_pos.x , g_pos.y ,g_pos.z);								//	移動マトリクスの作成			
	D3DXMatrixScaling(&t_matrix , g_scal.x , g_scal.y ,g_scal.z);								//	拡大縮小マトリクスの作成			
	//	ここで移動マトリクスと拡大縮小マトリクスを合成する											
	g_matrix = t_matrix * g_matrix;												
	D3DXMatrixRotationYawPitchRoll(&t_matrix , g_rot.y , g_rot.x , g_rot.z);								//	回転マトリクスの作成			
	//	ここで移動&拡大縮小マトリクスと回転マトリクスを合成する											
	g_matrix = t_matrix * g_matrix;												
}		
        

↓Render the scene

											
//--------------------------------------------------------------------------------------													
// Render the scene 													
//--------------------------------------------------------------------------------------													
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )													
{													
    HRESULT hr;													
													
    // Clear the render target and the zbuffer 													
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );													
													
    // Render the scene													
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )													
    {													
	//	モデルの表示											
	DXUTGetD3DDevice()->SetTransform(D3DTS_WORLD, &g_matrix);								//	マトリクスのセット			
	g_mesh->Render( DXUTGetD3DDevice() );												
													
	//	文字列の準備と生成・表示											
	TCHAR str[255];												
	RECT rect;												
													
	SetRect( &rect , 0,0,640,480);												
	_stprintf( str ,_T("座標:%.2f %.2f %.2f"),g_pos.x , g_pos.y ,g_pos.z);												
	pFont->DrawText( NULL,str,-1,&rect,NULL,D3DCOLOR_RGBA(255,255,255,255));												
	SetRect( &rect , 0,20,640,480);												
	_stprintf( str ,_T("拡大縮小:%.2f %.2f %.2f"),g_scal.x , g_scal.y ,g_scal.z);												
	pFont->DrawText( NULL,str,-1,&rect,NULL,D3DCOLOR_RGBA(255,255,255,255));												
	SetRect( &rect , 0,40,640,480);												
	_stprintf( str ,_T("回転:%.2f %.2f %.2f"),g_rot.x , g_rot.y ,g_rot.z);												
	pFont->DrawText( NULL,str,-1,&rect,NULL,D3DCOLOR_RGBA(255,255,255,255));												
													
	V( pd3dDevice->EndScene() );												
    }													
}													
	

↓Handle messages to the application

※変更箇所は下部にて別途補足説明をする

													
//--------------------------------------------------------------------------------------													
// Handle messages to the application 													
//--------------------------------------------------------------------------------------													
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, 													
                          bool* pbNoFurtherProcessing, void* pUserContext )													
{													
    return 0;													
}													
													
//--------------------------------------------------------------------------------------													
// Release resources created in the OnResetDevice callback here 													
//--------------------------------------------------------------------------------------													
void CALLBACK OnLostDevice( void* pUserContext )													
{													
}													
													
//--------------------------------------------------------------------------------------													
// Release resources created in the OnCreateDevice callback here													
//--------------------------------------------------------------------------------------													
void CALLBACK OnDestroyDevice( void* pUserContext )													
{													
	//	3Dモデルの解放											
	SAFE_DELETE( g_mesh );												
													
	//フォント変数の解放												
	SAFE_RELEASE( pFont );												
}													
													
//	アプリケーション初期化関数												
void InitApp( void )													
{													
	//	モデルのロード											
	g_mesh = new CDXUTMesh();							//	モデルを実体化しポインタを取得				
	g_mesh->Create(DXUTGetD3DDevice(),_T("isu.x"));							//	モデルのロード(これは描画用でない)				
	g_mesh->RestoreDeviceObjects(DXUTGetD3DDevice());							//	描画用モデルの作成				
													
	/////////////////////////////////////////////////////////////////////////////////////////////												
	//	3D環境の設定											
	//	カメラセット											
	D3DXMATRIX matview;			//	カメラ情報を格納するための行列変数								
	//	注視マトリクスの生成				順番に、カメラ位置、注視点、上方向の定義							
	D3DXMatrixLookAtLH( &matview , &D3DXVECTOR3(0,10,-10),&D3DXVECTOR3(0,0,0),&D3DXVECTOR3(0,1,0));												
	DXUTGetD3DDevice()->SetTransform(D3DTS_VIEW,&matview);							//	マトリクスのセット				
													
	//	プロジェクション(パース)の生成											
	D3DXMATRIX matproj;					//	プロジェクション情報を格納するための行列変数						
	//注視マトリクスの生成			順番に、行列変数、視野角、アスペクト比、クリッピング領域(前方、後方)									
	D3DXMatrixPerspectiveFovLH ( &matproj , D3DXToRadian(45),640.0f/480.0f , 0.1f,2000.0f);												
	DXUTGetD3DDevice()->SetTransform(D3DTS_PROJECTION,&matproj);								//	マトリクスのセット			
													
	// ライトon  ライトを有効にすればデフォルト値で初期化される。												
	DXUTGetD3DDevice()->LightEnable(0,true);												
}													
		
	

※補足説明※

●35行めの[ g_mesh->Create(DXUTGetD3DDevice(),_T("isu.x")); ]の[ T("isu.x") ]は処理を変更した箇所。


↓Initialize everything and go into a render loop

												
//--------------------------------------------------------------------------------------													
// Initialize everything and go into a render loop													
//--------------------------------------------------------------------------------------													
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )													
{													
    // Enable run-time memory check for debug builds.													
#if defined(DEBUG) | defined(_DEBUG)													
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );													
#endif													
													
    // Set the callback functions													
    DXUTSetCallbackDeviceCreated( OnCreateDevice );													
    DXUTSetCallbackDeviceReset( OnResetDevice );													
    DXUTSetCallbackDeviceLost( OnLostDevice );													
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );													
    DXUTSetCallbackMsgProc( MsgProc );													
    DXUTSetCallbackFrameRender( OnFrameRender );													
    DXUTSetCallbackFrameMove( OnFrameMove );													
   													
    // TODO: Perform any application-level initialization here													
													
    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application													
    DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes													
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen													
    DXUTCreateWindow( _T("EmptyProject") );													
    DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );													
													
//	フォントの作成												
D3DXCreateFont( DXUTGetD3DDevice(),													
	16,												
	0,												
	FW_NORMAL,												
	1,												
	false,												
	DEFAULT_CHARSET,												
	OUT_DEFAULT_PRECIS,												
	DEFAULT_QUALITY,												
	DEFAULT_PITCH,												
	_T(""),												
	&pFont);												
																										
//アプリケーションの初期化													
InitApp();													
													
    // Start the render loop													
    DXUTMainLoop();													
													
    // TODO: Perform any application-level cleanup here													
													
    return DXUTGetExitCode();													
}							
        

※補足説明※

●26行めの[ DXUTCreateWindow( _T("EmptyProject") ); ]は処理を変更した箇所。


1-1-3.動作確認

上下左右キーで移動。QWASZXキーで拡大縮小。

SHIFT+QWASZXキーで回転が出来れば、完了です。


1-1-3 動作確認

↓参考動画


▲TOP

>「1-4 別モデルのロードと表示」へ続く