|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|DxMesh| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|Unicode| Microsoft DirectX SDK (February 2010) DxMesh.cpp #highlight(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; } }}