開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 DxMesh
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト
文字セット Unicode

Microsoft DirectX SDK (February 2010)

DxMesh.cpp
/*
#2 視点操作
 
プロジェクトのプロパティ
[構成プロパティ]-[VC++ ディレクトリ]
[インクルード ディレクトリ]
C:\Program Files\Microsoft DirectX SDK (February 2010)\Include
[ライブラリ ディレクトリ]
C:\Program Files\Microsoft DirectX SDK (February 2010)\Lib\x86
 
Unicode
*/
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
 
#include <d3d9.h>
#include <d3dx9.h>
#include <stdio.h>
#include <time.h>
 
#define WIDTH(rect) ((rect).right - (rect).left)
#define HEIGHT(rect) ((rect).bottom - (rect).top)
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
 
#define APP_NAME L"DxMesh"
#define CLIENT_W 640
#define CLIENT_H 480
 
struct Mesh {
	ID3DXBuffer *pMat;
	DWORD dwNumMat;
	ID3DXMesh *pMesh;
};
 
// 関数プロトタイプ宣言
HRESULT InitD3D(HWND hWnd);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void Render(HWND hWnd);
BOOL OnKeyDown(HWND hWnd, WPARAM wParam);
HRESULT OnSave(void);
 
// 外部変数構造体
static struct {
	LPDIRECT3D9 pD3D;	// Direct3D9
	LPDIRECT3DDEVICE9 pDev;	// レンダリングデバイス
	LPD3DXFONT pFont;	// フォント
	Mesh cube;
	Mesh axis;
	float fDist;		// 原点との距離
	int nLat;		// 緯度
	int nLong;		// 経度
} g;
 
//==============================================================================
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow)
{
	g.fDist = 75.0f;
	g.nLat = 30;
	g.nLong = 210;
 
	// ウィンドウクラスの登録
	WNDCLASSEX wcx;
	ZeroMemory(&wcx, sizeof wcx);
	wcx.cbSize		= sizeof wcx;
	wcx.lpfnWndProc		= WndProc;
	wcx.hInstance		= hInstance;
	wcx.hCursor		= LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	wcx.lpszClassName	= APP_NAME;
	if (RegisterClassEx(&wcx) == 0) {
		return 0;
	}
 
	// ウィンドウサイズの計算
	RECT rect;
	SetRect(&rect, 0, 0, CLIENT_W, CLIENT_H);
	AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
 
	// ウィンドウの作成
	HWND hWnd = CreateWindow(
		APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 0, WIDTH(rect), HEIGHT(rect),
		NULL, NULL, hInstance, NULL);
	if (hWnd == NULL) {
		return 0;
	}
 
	// Direct3Dの初期化
	if (FAILED(InitD3D(hWnd))) {
		return 0;
	}
 
	// ウィンドウ表示
	ShowWindow(hWnd, nCmdShow);
 
	// メッセージループ
	MSG msg;
	do {
		Sleep(1);
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		} else {
			Render(hWnd);
		}
	} while (msg.message != WM_QUIT);
 
	SAFE_RELEASE(g.cube.pMesh);
	SAFE_RELEASE(g.axis.pMesh);
	SAFE_RELEASE(g.pFont);
	SAFE_RELEASE(g.pDev);
	SAFE_RELEASE(g.pD3D);
	return msg.wParam;
}
 
//------------------------------------------------------------------------------
HRESULT InitD3D(HWND hWnd)
{
	// Direct3D
	g.pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (g.pD3D == NULL) {
		return E_FAIL;
	}
 
	// デバイス作成用のパラメタ
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof d3dpp);
	d3dpp.BackBufferFormat		= D3DFMT_UNKNOWN;		// モニタの設定と同じ
	d3dpp.BackBufferCount		= 0;				// バックバッファの数 0->1
	d3dpp.MultiSampleType		= D3DMULTISAMPLE_NONE;		// マルチサンプリングしない
	d3dpp.SwapEffect		= D3DSWAPEFFECT_DISCARD;	// Direct3Dに任せる
	d3dpp.hDeviceWindow		= NULL;				// カバーウィンドウ
	d3dpp.Windowed			= TRUE;				// ウィンドウモード
	d3dpp.EnableAutoDepthStencil	= TRUE;				// 深度バッファ自動管理
	d3dpp.AutoDepthStencilFormat	= D3DFMT_D16;			// 深度バッファフォーマット
	d3dpp.PresentationInterval	= D3DPRESENT_INTERVAL_DEFAULT;	// モニタの垂直回帰を待つ
 
	// Direct3Dデバイスの作成
	HRESULT hr = g.pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
		hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g.pDev);
 
	// フォント
	if (SUCCEEDED(hr)) {
		hr = D3DXCreateFont(g.pDev, 40, 0, FW_HEAVY, 1, FALSE,
			SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS, ANTIALIASED_QUALITY,
			FF_DONTCARE, L"MS Pゴシック", &g.pFont);
	}
 
	// 立方体メッシュ作成
	if (SUCCEEDED(hr)) {
		hr = D3DXLoadMeshFromX(L"C:\\tmp\\Cube2.x", D3DXMESH_MANAGED, g.pDev,
			NULL, &g.cube.pMat, NULL, &g.cube.dwNumMat, &g.cube.pMesh);
	}
 
	// 軸メッシュ作成
	if (SUCCEEDED(hr)) {
		hr = D3DXLoadMeshFromX(L"C:\\tmp\\Axis.x", D3DXMESH_MANAGED, g.pDev,
			NULL, &g.axis.pMat, NULL, &g.axis.dwNumMat, &g.axis.pMesh);
	}
	return hr;
}
 
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg) {
	case WM_KEYDOWN:
		if (OnKeyDown(hWnd, wParam)) {
			return 0;
		}
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
 
//------------------------------------------------------------------------------
void Render(HWND hWnd)
{
	static int fps = 0;
	static int frame = 0;
	static time_t tmPrev = time(NULL);
 
	if (IsIconic(hWnd)) return;
	g.pDev->SetRenderState(D3DRS_ZENABLE, TRUE);
	g.pDev->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
 
	// 視点の設定
	D3DXMATRIX mtxView;
	float fRad = D3DXToRadian(g.nLat);	// 緯度
	float fPosY = sin(fRad) * g.fDist;
	float fDist = cos(fRad) * g.fDist;
	fRad = D3DXToRadian(g.nLong);		// 経度
	float fPoxX = sin(fRad) * fDist;
	float fPoxZ = cos(fRad) * fDist;
	D3DXMatrixLookAtLH(
		&mtxView,
		&D3DXVECTOR3(fPoxX, fPosY, fPoxZ),
		&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
		&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
	g.pDev->SetTransform(D3DTS_VIEW, &mtxView);
 
	D3DXMATRIX mtxProj;
	D3DXMatrixPerspectiveFovLH(&mtxProj, D3DXToRadian(45),
		(float)CLIENT_W / CLIENT_H, 0.1f, 100.0f);
	g.pDev->SetTransform(D3DTS_PROJECTION, &mtxProj);
 
	// ライトの設定
	g.pDev->SetRenderState(D3DRS_LIGHTING, TRUE);
	g.pDev->SetRenderState(D3DRS_AMBIENT, 0x007f7f7f);
	D3DLIGHT9 light;
	ZeroMemory(&light, sizeof light);
	light.Type	= D3DLIGHT_DIRECTIONAL;
	light.Diffuse	= D3DXCOLOR(1.0f, 1.0f, 1.0f, 0.0f);
	light.Ambient	= D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.0f);
	light.Direction	= D3DXVECTOR3(1.0f, -2.0f, 3.0f);
//	light.Range	= 1000.0f;
	g.pDev->SetLight(0, &light);
	g.pDev->LightEnable(0, TRUE);
 
	// バックバッファのクリア
	g.pDev->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
		D3DCOLOR_XRGB(0x7f,0x7f,0xff), 1.0f, 0);
	g.pDev->BeginScene();
 
	D3DCOLORVALUE matAmb = {0.3f, 0.3f, 0.3f, 1.0f};
//	D3DCOLORVALUE matDif = {1.0f, 0.0f, 0.0f, 1.0f};	// 元の色情報を上書き
	D3DXMATRIX mtxWorld;
	D3DXMatrixIdentity(&mtxWorld);
	g.pDev->SetTransform(D3DTS_WORLD, &mtxWorld);
 
	// 立方体描画
	for (DWORD dw = 0; dw < g.cube.dwNumMat; dw++) {
		D3DXMATERIAL *pMat = (D3DXMATERIAL *)g.cube.pMat->GetBufferPointer() + dw;
		pMat->MatD3D.Ambient = matAmb;
//		pMat->MatD3D.Diffuse = matDif;
		g.pDev->SetMaterial(&pMat->MatD3D);
		g.cube.pMesh->DrawSubset(dw);
	}
 
	// 軸描画
	for (DWORD dw = 0; dw < g.axis.dwNumMat; dw++) {
		D3DXMATERIAL *pMat = (D3DXMATERIAL *)g.axis.pMat->GetBufferPointer() + dw;
		pMat->MatD3D.Ambient = matAmb;
//		pMat->MatD3D.Diffuse = matDif;
		g.pDev->SetMaterial(&pMat->MatD3D);
		g.axis.pMesh->DrawSubset(dw);
	}
 
	// fps
	TCHAR szBuf[32];
	RECT rect;
	time_t tmCurr = time(NULL);
	if (tmCurr != tmPrev) {
		fps = frame;
		frame = 0;
		tmPrev = tmCurr;
	}
	frame++;
	SetRect(&rect, 0, 0, 50, 20);
	swprintf_s(szBuf, L"time=%lld fps=%d", tmCurr, fps);
	g.pFont->DrawText(NULL, szBuf, -1, &rect, DT_LEFT | DT_NOCLIP,
		D3DCOLOR_ARGB(0xff,0xff,0xff,0xff));
 
	// バックバッファを表画面に反映
	g.pDev->EndScene();
	g.pDev->Present(NULL, NULL, NULL, NULL);
}
 
//------------------------------------------------------------------------------
BOOL OnKeyDown(HWND hWnd, WPARAM wParam)
{
	switch (wParam) {
	case VK_LEFT:
		g.nLong++;
		break;
	case VK_RIGHT:
		g.nLong--;
		break;
	case VK_UP:
		g.nLat++;
		break;
	case VK_DOWN:
		g.nLat--;
		break;
	case VK_PRIOR:	// Page Up
		g.fDist -= 1.0f;
		break;
	case VK_NEXT:	// Page Down
		g.fDist += 1.0f;
		break;
	case 'S':
		if (GetKeyState(VK_CONTROL) < 0) {
			HRESULT hr = OnSave();
			if (FAILED(hr)) {
				MessageBox(hWnd, L"保存に失敗しました。", NULL, MB_OK);
			} else {
				MessageBox(hWnd, L"保存しました。", APP_NAME, MB_OK);
			}
		}
		break;
	case VK_ESCAPE:
		DestroyWindow(hWnd);
		break;
	default:
		return FALSE;
	}
	return TRUE;
}
 
//------------------------------------------------------------------------------
HRESULT OnSave(void)
{
	HRESULT hr = D3DXSaveMeshToX(
		L"C:\\tmp\\Cube2_2.x", g.cube.pMesh,
		NULL, (D3DXMATERIAL *)&g.cube.pMat, NULL,
		g.cube.dwNumMat, D3DXF_FILEFORMAT_TEXT);
	return hr;
}
 
最終更新:2012年11月26日 19:41