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; }