山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他立方体の6面にテクスチャーを張り回転させる(DirectX9 32/64bit)
概要
ソースコードの説明
WinMain
最初に実行される関数です。
最初にウィンドウを作成し、Init3DDev関数でDirect Xの初期化を行います。
その後通常のWinMain関数と同じ様にメッセージループを構成しますが、メッセージの取り出しにGetMessage関数ではなく、PeekMessage関数を使用し、メッセージがないときもループが回るようにします。メッセージがないときにDraw関数を呼び出し描画を行います。
Init3DDev
Direct Xの初期化を行います。
D3DXCreateTextureFromFile
テクスチャに使うjpeg.ファイルを読み込みます。(1.jpg ~ 6.jpg)
実行時には、EXEファイルと同じフォルダーに1.jpg ~ 6.jpgを用意します。(ここでは256*256ピクセルとしております)
サンプルで使用しているす。画jpegファイルは下記のとおりです。ソースコードの圧縮ファイルに含まれます。同じ名前であれば他の画像と交換できま像の大きさは最大512*512ピクセル、縦横同じサイズ、1辺は2のn乗にする必要があります。
上面(ver3) 3.jpg | |||
前面(ver1) 1.jpg | 右側面(ver2) 2.jpg | 裏面(ver5) 5.jpg | 左側面(ver4) 4.jpg |
下面(ver6) 6.jpg | |||
SetupMatrices
draw関数から呼び出されます。
まずここで表示させたいポリゴンの頂点座標を定義します。
グローバルの構造体 D3DVERTEXCOR ver1からVer6が該当します。
ポリゴンは、3角形が基本ですので四角形なら6個の座標を定義しなければいけませんが、、DrawPrimitiveUP関数の第1引数の定義によっては、4個の頂点のみで描画できます。
ローカル座標を任意に回転させるD3DXMatrixRotationAxis
ポリゴンを ローカル座標の原点(0,0,0)と第2引数で指定される点と結ぶ軸を中心に 原点方向を向いた右回りに第3引数の角度回転させる行列を作成し第1引数に保存します。
行列を移動させる D3DXMatrixTranslation
ローカル座標をワールド座標へ移動させるのに使用しています。
x,y,zで移動させる距離を指定します。
デバイスにワールド座標への変換方法を設定する SetTransform
D3DXMatrixPerspectiveFovLH
ワールド座標をビュー座標に変換する。ワールド座標のどの方向からどの範囲を見るか(描画するか)を設定する。この関数は、左手座標(Xが右、Yが上、Zが奥行方向で奥 左手で手のひらを上側がにし人差し指をX方向に向けた時における親指のさしている方向がZ値が増える方向である。)においてワールド座標をビュー座標に変換する。
描画する遠近それぞれのZ値、画面の縦横比(アスペクト)、Y方向の視野角を指定する。
ビュー座標への変換行列を設定する SetTransform
レンタリングステートの設定 SetRenderState
カーニング方法 反時計周りの面を消去
ライディングをしない
Zバッファを使わない
draw
画面のクリア Clear
レンタリング開始 BeginScene
テクスチャを設定する SetTexture
レンタリングを行う DrawPrimitiveUP
レンタリング終了 EndScene
バッファの内容を表示 Present
Cleanup
Init3DDevで作成したデバイスとテクスチャを開放します。
WndProc
ウィンドウプロシージャーです。ウィンドウ関係のメッセージを処理します。通常WM_PAINTメッセージにより再描画を行いますが、スピードが要求される場合は、前期のとおり別の場所で処理しています。
コンパイル方法
Visual C++ 2008
Microsoft DirectX SDK June 2010をインストールをあらかじめ行っておく
プロジェクトに下記のパスを追加(64bit Windowsで64bitの実行ファイルを作成する場合)
includeパスにC:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include
LibパスにC:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64
を追加
ソースコード
// Direct X 9 Sample Program
// 立方体に6面にそれぞれ異なるテクスチャーを張り付けて回転させる
// 32bit/64bit マルチバイト/Unicode対応 Visual C++ 2008
#define szClassName TEXT("Texture 3DBox")
#include <windows.h>
#include <d3dx9.h>
#include <dxerr.h>
#include <tchar.h>
#pragma once
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
//頂点フォーマット
#define FVF_TLVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
typedef struct _D3DVERTEXCOR_ {
float x,y,z;
DWORD color;
} D3DVERTEXCOR;
// 頂点フォーマットの定義
struct TLVERTEX{
float x,y,z;
D3DCOLOR color;
float tu,tv;
};
#define TIME_SET 1000.0f
HWND hWnd;
LPDIRECT3D9 pD3D;
LPDIRECT3DDEVICE9 pDEV;
D3DPRESENT_PARAMETERS D3DPPWin;
LPDIRECT3DTEXTURE9 g_pTextures[6];
TLVERTEX ver1[]= //前面
{ { -50, -50, 50, 0xffffffff,1,1 },
{ 50, -50, 50, 0xffffffff,0,1 },
{ -50, 50, 50, 0xffffffff,1,0 },
{ 50, 50, 50, 0xffffffff,0,0 } };
TLVERTEX ver2[]= //右側面
{ { 50, -50, 50, 0xffffffff,1,1 },
{ 50, -50, -50, 0xffffffff,0,1 },
{ 50, 50, 50, 0xffffffff,1,0 },
{ 50, 50, -50, 0xffffffff,0,0 } };
TLVERTEX ver3[]= //上面
{ { -50, -50, -50, 0xffffffff,0,1 },
{ 50, -50, -50, 0xffffffff,1,1 },
{ -50, -50, 50, 0xffffffff,0,0 },
{ 50, -50, 50, 0xffffffff,1,0 } };
TLVERTEX ver4[]= //左側面
{ { -50, 50, 50, 0xffffffff,0,0 },
{ -50, 50, -50, 0xffffffff,1,0 },
{ -50, -50, 50, 0xffffffff,0,1 },
{ -50, -50, -50, 0xffffffff,1,1 } };
TLVERTEX ver5[]= //裏面
{ { -50, 50, -50, 0xffffffff,0,0 },
{ 50, 50, -50, 0xffffffff,1,0 },
{ -50, -50, -50, 0xffffffff,0,1 },
{ 50, -50, -50, 0xffffffff,1,1 } };
TLVERTEX ver6[]= //下面
{ { 50, 50, -50, 0xffffffff,1,1 },
{ -50, 50, -50, 0xffffffff,0,1 },
{ 50, 50, 50, 0xffffffff,1,0 },
{ -50, 50, 50, 0xffffffff,0,0 } };
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
void SetupMatrices_arg(float x,float y,float z=0);
void Draw(void);
HRESULT Init3DDev(HWND hwnd);
void Cleanup(void);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int){
MSG msg;
WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst,
NULL,NULL,NULL,NULL,szClassName,NULL };
if (RegisterClassEx(&wc)==0)
return FALSE;
HWND hWnd = CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,600,600,
NULL,NULL,hInst,NULL);
if (FAILED(Init3DDev(hWnd)))
return FALSE;
ShowWindow(hWnd,SW_SHOWDEFAULT);
UpdateWindow(hWnd);
ZeroMemory(&msg,sizeof(msg));
while(msg.message!=WM_QUIT){
if (PeekMessage(&msg,NULL,0U,0U,PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Draw();
}
Cleanup();
UnregisterClass(szClassName,wc.hInstance);
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam){
switch(msg){
case WM_DESTROY:
PostQuitMessage(0);
return 0L;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
TCHAR* tex_file[]={ TEXT("1.jpg"),TEXT("2.jpg"),TEXT("5.jpg"),TEXT("4.jpg"),TEXT("3.jpg"),TEXT("6.jpg"),0 };
//デバイス/モード等の初期化
HRESULT Init3DDev(HWND hwnd){
hWnd= hwnd;
pD3D= NULL;
pDEV= NULL;
HRESULT hr;
D3DDISPLAYMODE dmode;
// デバイス/モード等の初期化
if (pD3D==NULL)
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (pD3D==NULL)
return E_FAIL;
//現在のディスプレイモードを得る
if (FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&dmode)))
return E_FAIL;
// D3DDeviceオブジェクトの作成
ZeroMemory(&D3DPPWin, sizeof(D3DPPWin));
D3DPPWin.BackBufferFormat = dmode.Format;
D3DPPWin.BackBufferCount = 1;
D3DPPWin.SwapEffect = D3DSWAPEFFECT_DISCARD;
D3DPPWin.Windowed = TRUE;
D3DPPWin.EnableAutoDepthStencil = TRUE;
D3DPPWin.AutoDepthStencilFormat = D3DFMT_D16;
D3DPPWin.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &D3DPPWin, &pDEV);
if (FAILED(hr)){
hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPPWin, &pDEV);
if (FAILED(hr)){
hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &D3DPPWin, &pDEV);
if (FAILED(hr)){
MessageBox(NULL,TEXT("Create Device Error"),TEXT("Surface Error"),MB_OK); return E_FAIL; }
}
}
int n;
for(n=0;n<6;n++){
hr = D3DXCreateTextureFromFile(pDEV,tex_file[n],&g_pTextures[n]);
if (FAILED(hr)){
MessageBox(NULL,tex_file[n],TEXT("テクスチャがー読み込めませんでした。r"),MB_OK);
}
}
return S_OK;
}
//描画環境設定
void SetupMatrices_arg(float x,float y,float z){
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMATRIX w;
D3DXVECTOR3 v;
float q=timeGetTime()/TIME_SET;
v.x=0;
v.y=float(100.0f*cos(q/10.0f));
v.z=float(100.0f*sin(q/10.0f));
D3DXMatrixRotationAxis(&w,&v,q ); // 任意の軸を回転軸にして回転する行列を作成する。 システム時刻をミリ秒単位で取得
D3DXMatrixTranslation(&matView,x,y,z); // オフセットを指定して行列を作成する。
matView= w*matView;
pDEV->SetTransform(D3DTS_VIEW,&matView);
//透視変換の設定
D3DXMatrixPerspectiveFovLH(&matProj,D3DXToRadian(30.0f),1.0f,-300,300); // 視野に基づいて、左手座標系パースペクティブ射影行列を作成する
pDEV->SetTransform(D3DTS_PROJECTION,&matProj);
//描画設定
pDEV->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); //反時計回りの面を消去
pDEV->SetRenderState(D3DRS_LIGHTING,FALSE); //ライティングしない
pDEV->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE); //Zバッファ使わない
}
//描画処理
void Draw(void){
if (!pDEV)
return;
//黒で塗りつぶして消去
pDEV->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0,0);
//描画の開始
pDEV->BeginScene();
//描画環境の設定
pDEV->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
SetupMatrices_arg(0,0,400);
//ストリームを使わないで直接データを渡して描画する
pDEV->SetFVF(FVF_TLVERTEX);
pDEV->SetTexture(0,g_pTextures[0]);
pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,ver1,sizeof(TLVERTEX));
pDEV->SetTexture(0,g_pTextures[1]);
pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,ver2,sizeof(TLVERTEX));
pDEV->SetTexture(0,g_pTextures[2]);
pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,ver3,sizeof(TLVERTEX));
pDEV->SetTexture(0,g_pTextures[3]);
pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,ver4,sizeof(TLVERTEX));
pDEV->SetTexture(0,g_pTextures[4]);
pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,ver5,sizeof(TLVERTEX));
pDEV->SetTexture(0,g_pTextures[5]);
pDEV->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,ver6,sizeof(TLVERTEX));
pDEV->EndScene();
pDEV->Present(NULL,NULL,NULL,NULL);
}
void Cleanup(void){
int n;
for(n=0;n<6;n++){
if ( g_pTextures[n] != NULL )
g_pTextures[n]->Release();
}
pDEV->Release();
pD3D->Release();
}