Tuto01.とりあえずDirectX11 を動かす
【メインプログラムの修正】
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
}
}
// (3)終了処理
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
※ビルドして動作チェック
3D用プログラムのリンク
※今回はソースコードの形でリンク
プロジェクトにフィルタ、"Graphics"を作成して追加。
追加ファイル
※追加ファイルを全て追加すること
ここでは、ID3D11Context というインタフェースを用意して
(内部の実装クラスは、CD3D11Context)
そのインタフェースを経由してDirectX11 Graphics を操作しています。
解説はまだありません。スミマセン。
【DirectXの初期化と終了】
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
// インクルードファイルを追加
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include <D2D1.h>
#include <wincodec.h>
#include "D3DContext.h"
#include "D3D11Font.h"
#include "IMesh.h"
#include "MTAnimator.h"
#include "HighResTimer.h"
using namespace DirectX;
// ライブラリを追加
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dcompiler.lib")
// マクロ
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) { if (o){ delete (o); o = NULL; } }
#define SAFE_DELETE_ARRAY(o) { if (o){ delete [] (o); o = NULL; } }
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
ID3DContext *g_pD3DContext = NULL;
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// DirectX 11 関連
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
HRESULT hr;
CHighResTimer *pTimer = new CHighResTimer();
hr = CreateD3DContext(&g_pD3DContext,hWnd,true); // DirectX 11の初期化
if (FAILED(hr))
goto EXIT;
pTimer->Reset(); // タイマーをリセット
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
double elapsed = pTimer->GetElapsedTimeAndReset();
if (elapsed > 2.0)
elapsed = 2.0;
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pD3DContext->ClearRenderTargetView( ClearColor );
g_pD3DContext->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
//結果をウインドウに反映
g_pD3DContext->Present( 1, 0 );
}
}
EXIT:
// (3)終了処理
SAFE_DELETE(g_pD3DContext);
SAFE_DELETE(pTimer);
CoUninitialize();
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
グラフィックスデータの用意
グラフィックスデータ(シェーダ含む)
上のリンクよりファイルをダウンロード、ダウンロードしたファイルを解凍し、
ソリューション内のプロジェクトフォルダの中に、res フォルダを作成し、
そこへコピーする。
【メッシュの読み込みと表示】
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
// インクルードファイルを追加
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include <D2D1.h>
#include <wincodec.h>
#include "D3DContext.h"
#include "D3D11Font.h"
#include "IMesh.h"
#include "MTAnimator.h"
#include "HighResTimer.h"
using namespace DirectX;
// ライブラリを追加
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dcompiler.lib")
// マクロ
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) { if (o){ delete (o); o = NULL; } }
#define SAFE_DELETE_ARRAY(o) { if (o){ delete [] (o); o = NULL; } }
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
ID3DContext *g_pD3DContext = NULL;
ISimpleMesh *g_pMesh = NULL;
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// DirectX 11 関連
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
HRESULT hr;
ID3D11DeviceContext *pContext=NULL;
CHighResTimer *pTimer = new CHighResTimer();
hr = CreateD3DContext(&g_pD3DContext,hWnd,true); // DirectX 11の初期化
if (FAILED(hr))
goto EXIT;
pContext = g_pD3DContext->GetDeviceContext();
if (pContext != NULL){
g_pMesh = ISimpleMesh::CreateInstance(_T("res\\smile.x"));
if (g_pMesh != NULL){
if (FAILED(g_pMesh->RestoreDeviceObjects(pContext))){
goto EXIT;
}
}
}else
goto EXIT;
pTimer->Reset(); // タイマーをリセット
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
double elapsed = pTimer->GetElapsedTimeAndReset();
if (elapsed > 2.0)
elapsed = 2.0;
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pD3DContext->ClearRenderTargetView( ClearColor );
g_pD3DContext->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
g_pMesh->Render(pContext);
//結果をウインドウに反映
g_pD3DContext->Present( 1, 0 );
}
}
EXIT:
// (3)終了処理
SAFE_RELEASE(pContext);
SAFE_DELETE(g_pMesh);
SAFE_DELETE(g_pD3DContext);
SAFE_DELETE(pTimer);
CoUninitialize();
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
【単純な動き】
キャラクターを動かすには、WORLD 行列を使う。
行列のデータ型は以下の通り。
typedef struct DirectX::XMMATRIX
{
FLOAT _11, _12, _13, _14;
FLOAT _21, _22, _23, _24;
FLOAT _31, _32, _33, _34;
FLOAT _41, _42, _43, _44;
} D3DXMATRIX, *LPD3DXMATRIX;
※実際には、演算子オーバーロードなどが用意されており、もう少し高度なデータ型である。
また、どこかで見たような形(4行4列の行列)である。
【WORLD 行列を作る為の関数】
DirectX::XMMATRIX DirectX::XMMatrixIdentity(); // 移動しない行列(単位行列)を作成
DirectX::XMMATRIX DirectX::XMMatrixRotationY(FLOAT angle); // Y軸回転(Yaw)を算出
DirectX::XMMATRIX DirectX::XMMatrixRotationX(FLOAT angle); // X軸回転(Pitch)を算出
DirectX::XMMATRIX DirectX::XMMatrixRotationZ(FLOAT angle); // Z軸回転(Roll)を算出
DirectX::XMMATRIX DirectX::XMMatrixTranslation(FLOAT x, FLOAT y, FLOAT z); // 移動行列を算出
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
// インクルードファイルを追加
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include <D2D1.h>
#include <wincodec.h>
#include "D3DContext.h"
#include "D3D11Font.h"
#include "IMesh.h"
#include "MTAnimator.h"
#include "HighResTimer.h"
using namespace DirectX;
// ライブラリを追加
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dcompiler.lib")
// マクロ
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) { if (o){ delete (o); o = NULL; } }
#define SAFE_DELETE_ARRAY(o) { if (o){ delete [] (o); o = NULL; } }
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
ID3DContext *g_pD3DContext = NULL;
ISimpleMesh *g_pMesh = NULL;
// キャラクター関連のデータ
FLOAT g_fAngle = 0; // 角度
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// DirectX 11 関連
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
HRESULT hr;
ID3D11DeviceContext *pContext=NULL;
CHighResTimer *pTimer = new CHighResTimer();
hr = CreateD3DContext(&g_pD3DContext,hWnd,true); // DirectX 11の初期化
if (FAILED(hr))
goto EXIT;
pContext = g_pD3DContext->GetDeviceContext();
if (pContext != NULL){
g_pMesh = ISimpleMesh::CreateInstance(_T("res\\smile.x"));
if (g_pMesh != NULL){
if (FAILED(g_pMesh->RestoreDeviceObjects(pContext))){
goto EXIT;
}
}
}else
goto EXIT;
pTimer->Reset(); // タイマーをリセット
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
double elapsed = pTimer->GetElapsedTimeAndReset();
if (elapsed > 2.0)
elapsed = 2.0;
// 回転
g_fAngle += 0.05f * elapsed;
if (g_fAngle > XM_PI* 2.0f)
g_fAngle -= XM_PI * 2.0f;
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pD3DContext->ClearRenderTargetView( ClearColor );
g_pD3DContext->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
XMMATRIX matWorld;
matWorld = XMMatrixRotationY(g_fAngle);
g_pMesh->SetWorldMatrix(&matWorld);
g_pMesh->Render(pContext);
//結果をウインドウに反映
g_pD3DContext->Present( 1, 0 );
}
}
EXIT:
// (3)終了処理
SAFE_RELEASE(pContext);
SAFE_DELETE(g_pMesh);
SAFE_DELETE(g_pD3DContext);
SAFE_DELETE(pTimer);
CoUninitialize();
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
【やや複雑な動き】
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
// インクルードファイルを追加
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include <D2D1.h>
#include <wincodec.h>
#include "D3DContext.h"
#include "D3D11Font.h"
#include "IMesh.h"
#include "MTAnimator.h"
#include "HighResTimer.h"
using namespace DirectX;
// ライブラリを追加
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dcompiler.lib")
// マクロ
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) { if (o){ delete (o); o = NULL; } }
#define SAFE_DELETE_ARRAY(o) { if (o){ delete [] (o); o = NULL; } }
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
ID3DContext *g_pD3DContext = NULL;
ISimpleMesh *g_pMesh = NULL;
// キャラクター関連のデータ
FLOAT g_fAngle = 0; // 角度
FLOAT g_fX = 2.0f; // X座標
UINT g_uiPhase = 0;
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// DirectX 11 関連
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
HRESULT hr;
ID3D11DeviceContext *pContext=NULL;
CHighResTimer *pTimer = new CHighResTimer();
hr = CreateD3DContext(&g_pD3DContext,hWnd,true); // DirectX 11の初期化
if (FAILED(hr))
goto EXIT;
pContext = g_pD3DContext->GetDeviceContext();
if (pContext != NULL){
g_pMesh = ISimpleMesh::CreateInstance(_T("res\\smile.x"));
if (g_pMesh != NULL){
if (FAILED(g_pMesh->RestoreDeviceObjects(pContext))){
goto EXIT;
}
}
}else
goto EXIT;
pTimer->Reset(); // タイマーをリセット
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
double elapsed = pTimer->GetElapsedTimeAndReset();
if (elapsed > 2.0)
elapsed = 2.0;
// 回転
//g_fAngle += 0.05f * elapsed;
//if (g_fAngle > XM_PI* 2.0f)
// g_fAngle -= XM_PI * 2.0f;
switch(g_uiPhase){
case 0:
// 左を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI*0.5f)
break;
g_uiPhase++;
g_fAngle = XM_PI*0.5f;
break;
case 1:
// 左へ移動
g_fX -=0.1f * elapsed;
if (g_fX > -2.0f)
break;
g_fX = -2.0f;
g_uiPhase++;
break;
case 2:
// 右を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI*1.5f)
break;
g_uiPhase++;
g_fAngle = -XM_PI*0.5f;
break;
case 3:
// 右へ移動
g_fX += 0.1f * elapsed;
if (g_fX < 2.0f)
break;
g_fX = 2.0f;
g_uiPhase = 0;
break;
}
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pD3DContext->ClearRenderTargetView( ClearColor );
g_pD3DContext->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
XMMATRIX matWorld,matRotation,matTranslation;
matRotation = XMMatrixRotationY(g_fAngle);
matTranslation = XMMatrixTranslation(g_fX,0.f,0.f);
matWorld = matRotation * matTranslation;
g_pMesh->SetWorldMatrix(&matWorld);
g_pMesh->Render(pContext);
//結果をウインドウに反映
g_pD3DContext->Present( 1, 0 );
}
}
EXIT:
// (3)終了処理
SAFE_RELEASE(pContext);
SAFE_DELETE(g_pMesh);
SAFE_DELETE(g_pD3DContext);
SAFE_DELETE(pTimer);
CoUninitialize();
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
【カメラの設定】
カメラの設定にはビュー行列を用いる。
ビュー行列を算出する関数
DirectX::XMMatrixLookAtLH
また、レンズの設定にはプロジェクション行列を使用する。
プロジェクション行列を算出する関数
DirectX::XMMatrixPerspectiveFovLH
【カメラの設定・・・・俯瞰】
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
// インクルードファイルを追加
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include <D2D1.h>
#include <wincodec.h>
#include "D3DContext.h"
#include "D3D11Font.h"
#include "IMesh.h"
#include "MTAnimator.h"
#include "HighResTimer.h"
using namespace DirectX;
// ライブラリを追加
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dcompiler.lib")
// マクロ
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) { if (o){ delete (o); o = NULL; } }
#define SAFE_DELETE_ARRAY(o) { if (o){ delete [] (o); o = NULL; } }
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
ID3DContext *g_pD3DContext = NULL;
ISimpleMesh *g_pMesh = NULL;
// キャラクター関連のデータ
FLOAT g_fAngle = 0; // 角度
FLOAT g_fX = 2.0f; // X座標
UINT g_uiPhase = 0;
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// DirectX 11 関連
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
HRESULT hr;
ID3D11DeviceContext *pContext=NULL;
CHighResTimer *pTimer = new CHighResTimer();
hr = CreateD3DContext(&g_pD3DContext,hWnd,true); // DirectX 11の初期化
if (FAILED(hr))
goto EXIT;
pContext = g_pD3DContext->GetDeviceContext();
if (pContext != NULL){
g_pMesh = ISimpleMesh::CreateInstance(_T("res\\smile.x"));
if (g_pMesh != NULL){
if (FAILED(g_pMesh->RestoreDeviceObjects(pContext))){
goto EXIT;
}
}
}else
goto EXIT;
pTimer->Reset(); // タイマーをリセット
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
double elapsed = pTimer->GetElapsedTimeAndReset();
if (elapsed > 2.0)
elapsed = 2.0;
// 回転
//g_fAngle += 0.05f * elapsed;
//if (g_fAngle > XM_PI* 2.0f)
// g_fAngle -= XM_PI * 2.0f;
switch(g_uiPhase){
case 0:
// 左を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI*0.5f)
break;
g_uiPhase++;
g_fAngle = XM_PI*0.5f;
break;
case 1:
// 左へ移動
g_fX -=0.1f * elapsed;
if (g_fX > -2.0f)
break;
g_fX = -2.0f;
g_uiPhase++;
break;
case 2:
// 右を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI*1.5f)
break;
g_uiPhase++;
g_fAngle = -XM_PI*0.5f;
break;
case 3:
// 右へ移動
g_fX += 0.1f * elapsed;
if (g_fX < 2.0f)
break;
g_fX = 2.0f;
g_uiPhase = 0;
break;
}
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pD3DContext->ClearRenderTargetView( ClearColor );
g_pD3DContext->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
XMMATRIX matWorld,matRotation,matTranslation;
XMMATRIX matView; // ビュー行列
XMMATRIX matProj; // プロジェクション行列
matView = XMMatrixLookAtLH(
DirectX::XMLoadFloat3(&DirectX::XMFLOAT3(0,4.0f,-8.0f)),
DirectX::XMLoadFloat3(&DirectX::XMFLOAT3(0,0.0f,2.0f)),
DirectX::XMLoadFloat3(&DirectX::XMFLOAT3(0,1.f,0))
);
matProj = XMMatrixPerspectiveFovLH(XM_PI * 0.25f, 852.f/480.f,2.f,250.f);
matRotation = XMMatrixRotationY(g_fAngle);
matTranslation = XMMatrixTranslation(g_fX,0.f,0.f);
matWorld = matRotation * matTranslation;
g_pMesh->SetProjectionMatrix(&matProj);
g_pMesh->SetViewMatrix(&matView);
g_pMesh->SetWorldMatrix(&matWorld);
g_pMesh->Render(pContext);
//結果をウインドウに反映
g_pD3DContext->Present( 1, 0 );
}
}
EXIT:
// (3)終了処理
SAFE_RELEASE(pContext);
SAFE_DELETE(g_pMesh);
SAFE_DELETE(g_pD3DContext);
SAFE_DELETE(pTimer);
CoUninitialize();
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
【課題】
以下の4点を巡回する動作をプログラミングしなさい
( 2.0, 0.0,-2.0)
(-2.0, 0.0,-2.0)
(-2.0, 0.0, 2.0)
( 2.0, 0.0, 2.0)
【解答編】
#include "stdafx.h"
#include <crtdbg.h>
#include <tchar.h>
#include <stdio.h>
// インクルードファイルを追加
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include <D2D1.h>
#include <wincodec.h>
#include "D3DContext.h"
#include "D3D11Font.h"
#include "IMesh.h"
#include "MTAnimator.h"
#include "HighResTimer.h"
using namespace DirectX;
// ライブラリを追加
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"dxguid.lib")
#pragma comment(lib,"d3dcompiler.lib")
// マクロ
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) { if (o){ delete (o); o = NULL; } }
#define SAFE_DELETE_ARRAY(o) { if (o){ delete [] (o); o = NULL; } }
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
ID3DContext *g_pD3DContext = NULL;
ISimpleMesh *g_pMesh = NULL;
// キャラクター関連のデータ
FLOAT g_fAngle = 0; // 角度
FLOAT g_fX = 2.0f; // X座標
FLOAT g_fZ = 0.0f; // Z座標
UINT g_uiPhase = 0;
//
// 関数:WinMain
// 説明:アプリケーションのエントリーポイント
//
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
MSG msg;
// (1)初期化部分
msg.wParam = 0;
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("Game"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("Game"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,852,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
852 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
// 再表示の際、WndProc が呼び出される事にも注意!
// DirectX 11 関連
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
HRESULT hr;
ID3D11DeviceContext *pContext=NULL;
CHighResTimer *pTimer = new CHighResTimer();
hr = CreateD3DContext(&g_pD3DContext,hWnd,true); // DirectX 11の初期化
if (FAILED(hr))
goto EXIT;
pContext = g_pD3DContext->GetDeviceContext();
if (pContext != NULL){
g_pMesh = ISimpleMesh::CreateInstance(_T("res\\smile.x"));
if (g_pMesh != NULL){
if (FAILED(g_pMesh->RestoreDeviceObjects(pContext))){
goto EXIT;
}
}
}else
goto EXIT;
pTimer->Reset(); // タイマーをリセット
// (2)メッセージループ
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
double elapsed = pTimer->GetElapsedTimeAndReset();
if (elapsed > 2.0)
elapsed = 2.0;
// 回転
//g_fAngle += 0.05f * elapsed;
//if (g_fAngle > XM_PI* 2.0f)
// g_fAngle -= XM_PI * 2.0f;
switch(g_uiPhase){
case 0:
// 左を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI*0.5f)
break;
g_uiPhase++;
g_fAngle = XM_PI*0.5f;
break;
case 1:
// 左へ移動
g_fX -=0.1f * elapsed;
if (g_fX > -2.0f)
break;
g_fX = -2.0f;
g_uiPhase++;
break;
case 2:
// 奥を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI)
break;
g_uiPhase++;
g_fAngle = XM_PI;
break;
case 3:
// 奥へ移動
g_fZ +=0.1f * elapsed;
if (g_fZ < 4.0f)
break;
g_fZ = 4.0f;
g_uiPhase++;
break;
case 4:
// 右を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < XM_PI*1.5f)
break;
g_uiPhase++;
g_fAngle = -XM_PI*0.5f;
break;
case 5:
// 右へ移動
g_fX += 0.1f * elapsed;
if (g_fX < 2.0f)
break;
g_fX = 2.0f;
g_uiPhase++;
break;
case 6
:
// 右を向く
g_fAngle += 0.05f * elapsed;
if (g_fAngle < 0.f)
break;
g_uiPhase++;
g_fAngle = 0;
break;
case 7
:
// 右へ移動
g_fZ -= 0.1f * elapsed;
if (g_fZ > 0.0f)
break;
g_fZ = 0.0f;
g_uiPhase= 0;
break;
}
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
g_pD3DContext->ClearRenderTargetView( ClearColor );
g_pD3DContext->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
XMMATRIX matWorld,matRotation,matTranslation;
XMMATRIX matView; // ビュー行列
XMMATRIX matProj; // プロジェクション行列
matView = XMMatrixLookAtLH(
DirectX::XMLoadFloat3(&DirectX::XMFLOAT3(0,4.0f,-8.0f)),
DirectX::XMLoadFloat3(&DirectX::XMFLOAT3(0,0.0f,2.0f)),
DirectX::XMLoadFloat3(&DirectX::XMFLOAT3(0,1.f,0))
);
matProj = XMMatrixPerspectiveFovLH(XM_PI * 0.25f, 852.f/480.f,2.f,250.f);
matRotation = XMMatrixRotationY(g_fAngle);
matTranslation = XMMatrixTranslation(g_fX,0.f,g_fZ);
matWorld = matRotation * matTranslation;
g_pMesh->SetProjectionMatrix(&matProj);
g_pMesh->SetViewMatrix(&matView);
g_pMesh->SetWorldMatrix(&matWorld);
g_pMesh->Render(pContext);
//結果をウインドウに反映
g_pD3DContext->Present( 1, 0 );
}
}
EXIT:
// (3)終了処理
SAFE_RELEASE(pContext);
SAFE_DELETE(g_pMesh);
SAFE_DELETE(g_pD3DContext);
SAFE_DELETE(pTimer);
CoUninitialize();
return (int)msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}