0001: // ----------------------------------------------------------------------------
0002: //
0003: // main.cpp - ウィンドウズメイン部分
0004: // 
0005: // Copyright (c) 2002 imagire (imagire@gmail.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: 
0010: #define STRICT
0011: #include <stdio.h>
0012: #include <windows.h>
0013: #include <d3d8.h>
0014: #include <d3dx8.h>
0015: 
0016: #include "resource.h"
0017: #include "main.h"
0018: #include "draw.h"
0019: #include "font.h"
0020: 
0021: #include "CSkinModel.h"
0022: 
0023: // ----------------------------------------------------------------------------
0024: // オブジェクト
0025: // ----------------------------------------------------------------------------
0026: static LPDIRECT3DDEVICE8        s_lpD3DDEV = NULL;
0027: static bool                     s_end;      // 終了フラグ
0028: static HINSTANCE                shInstApp;
0029: static bool                     sZoom = false;
0030: 
0031: static CMyFont      sFont;
0032: extern CSkinModel   model;
0033: extern D3DXVECTOR4  rot;
0034: 
0035: // ----------------------------------------------------------------------------
0036: // プロトタイプ宣言
0037: // ----------------------------------------------------------------------------
0038: int PASCAL WinMain(HINSTANCE hInst,HINSTANCE hPrev,char *CmdLine,int CmdShow);
0039: LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
0040: LRESULT CALLBACK MyDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp);
0041: HRESULT InitD3D( HWND hWnd, LPDIRECT3D8 *ppD3D, D3DPRESENT_PARAMETERS &d3dpp );         // DirectX の初期化
0042: static void fps_disp();
0043: 
0044: // ----------------------------------------------------------------------------
0045: // Name: WinMain()
0046: // Desc: Windows アプリケーションはここから始まる
0047: //-----------------------------------------------------------------------------
0048: int PASCAL WinMain(HINSTANCE hInst,HINSTANCE hPrev,char *CmdLine,int CmdShow)
0049: {
0050:     LPDIRECT3D8             lpD3D = NULL;
0051:     D3DPRESENT_PARAMETERS   d3dpp;
0052: 
0053:     s_end = 0;
0054:     shInstApp = hInst;
0055:     // ウインドウの作成
0056:     RECT    rect;
0057:     SetRect(&rect, 0, 0, WIDTH, HEIGHT);
0058:     DWORD   style = (FULLSCREEN) ? WS_POPUP :(WS_CAPTION|WS_SYSMENU|WS_BORDER|WS_MINIMIZEBOX);
0059:     AdjustWindowRect(&rect, style, FALSE);  // ウィンドウスタイルを設定したときの、ウィンドウの大きさを調べる
0060:     int width  = rect.right - rect.left;
0061:     int height = rect.bottom - rect.top;    
0062:     
0063:     WNDCLASS wc;
0064:     ZeroMemory(&wc, sizeof(WNDCLASS));
0065:     wc.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
0066:     wc.hCursor          = LoadCursor(NULL, IDC_ARROW);
0067:     wc.hInstance        = hInst;
0068:     wc.lpfnWndProc      = MsgProc;
0069:     wc.lpszMenuName     = (char*)IDR_MENU;
0070:     wc.lpszClassName    = CAPTION;
0071:     if(RegisterClass(&wc) == 0) return 0; //ウィンドウ作成に使用できる新しいウィンドウクラスを作成する。
0072:     
0073:     HWND hWnd = CreateWindow(CAPTION        // 登録されているクラス名
0074:                             ,CAPTION        // ウィンドウ名
0075:                             ,style          // ウィンドウスタイル
0076:                             ,CW_USEDEFAULT  // ウィンドウの横方向の位置
0077:                             ,CW_USEDEFAULT  // ウィンドウの縦方向の位置
0078:                             ,width          // ウィンドウの幅
0079:                             ,height         // ウィンドウの高さ
0080:                             ,NULL           // 親ウィンドウまたはオーナーウィンドウのハンドル
0081:                             ,NULL           // メニューハンドルまたは子ウィンドウ ID
0082:                             ,hInst          // アプリケーションインスタンスのハンドル
0083:                             ,NULL           // ウィンドウ作成データ
0084:                             );
0085:     if(hWnd == NULL) return 0;
0086:     
0087:     // Direct3D の初期化
0088:     if(SUCCEEDED(InitD3D(hWnd, &lpD3D, d3dpp))){
0089:         
0090:         sFont.Init(s_lpD3DDEV, 12, 24);
0091: 
0092:         if(FAILED(InitRender(lpD3D, s_lpD3DDEV))) s_end = true;
0093:         
0094:         ShowWindow(hWnd, SW_SHOW);
0095:         UpdateWindow(hWnd);
0096:     
0097:         // メインループ
0098:         MSG msg;
0099:         while (!s_end)
0100:         {
0101:             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
0102:                 // メッセージの処理
0103:                 TranslateMessage(&msg);
0104:                 DispatchMessage(&msg);
0105:             }else{
0106:                 // Direct3D の描画
0107:                 // バックバッファと Z バッファをクリア
0108:                 s_lpD3DDEV->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0x50,0x6e,0xbf),1.0f,0);
0109:                 // シーン開始
0110:                 s_lpD3DDEV->BeginScene();
0111:                 
0112:                 Render(s_lpD3DDEV); // 描画などの処理
0113:                 fps_disp();         // fpsの描画
0114:                 
0115:                 // シーン終了
0116:                 s_lpD3DDEV->EndScene();
0117:                 if (FAILED(s_lpD3DDEV->Present(NULL,NULL,NULL,NULL)))
0118:                     s_lpD3DDEV->Reset(&d3dpp);// バックバッファをプライマリバッファにコピー
0119:             }
0120:         }
0121:     }
0122:     
0123:     // 終了
0124:     CleanRender(s_lpD3DDEV);
0125:     RELEASE(s_lpD3DDEV);
0126:     RELEASE(lpD3D);
0127:     
0128:     return 0;
0129: }
0130: //-----------------------------------------------------------------------------
0131: // Name: InitD3D()
0132: // Desc: Direct3D の初期化
0133: //-----------------------------------------------------------------------------
0134: HRESULT InitD3D( HWND hWnd, LPDIRECT3D8 *ppD3D, D3DPRESENT_PARAMETERS &d3dpp )
0135: {
0136:     // Direct3D オブジェクトを作成
0137:     if (NULL == (*ppD3D = Direct3DCreate8(D3D_SDK_VERSION))){
0138:         MessageBox(NULL,"Direct3D の作成に失敗しました。",CAPTION,MB_OK | MB_ICONSTOP);
0139:         return E_FAIL;
0140:     }
0141:     LPDIRECT3D8 pD3D = *ppD3D;
0142: 
0143:     // 現在の画面モードを取得
0144:     D3DDISPLAYMODE d3ddm;
0145:     if( FAILED( pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) return E_FAIL;
0146:     // ビデオカードの能力を調べる
0147:     D3DCAPS8 caps;
0148:     pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
0149: 
0150:     // Direct3D 初期化パラメータの設定
0151:     ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
0152:     d3dpp.BackBufferCount = 1;
0153:     if (FULLSCREEN){
0154:         d3dpp.Windowed = FALSE;
0155:         d3dpp.BackBufferWidth = WIDTH;
0156:         d3dpp.BackBufferHeight = HEIGHT;
0157:     }else{
0158:         d3dpp.Windowed = TRUE;
0159:         d3dpp.BackBufferWidth = 0;
0160:         d3dpp.BackBufferHeight = 0;
0161:     }
0162:     // ウインドウ : 現在の画面モードを使用
0163:     d3dpp.BackBufferFormat = d3ddm.Format;
0164:     d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
0165:     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
0166:     d3dpp.hDeviceWindow = hWnd;
0167:     // Z バッファの自動作成
0168:     d3dpp.EnableAutoDepthStencil = TRUE;
0169:     if( FAILED( pD3D->CheckDeviceFormat( caps.AdapterOrdinal, 
0170:                                            caps.DeviceType, d3ddm.Format, 
0171:                                            D3DUSAGE_DEPTHSTENCIL, 
0172:                                            D3DRTYPE_SURFACE,
0173:                                            D3DFMT_D24S8 ) ) ){
0174:         d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
0175:     }else{
0176:         d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
0177:     }
0178:     
0179:     DWORD  vs[] = {D3DCREATE_HARDWARE_VERTEXPROCESSING, D3DCREATE_MIXED_VERTEXPROCESSING, D3DCREATE_SOFTWARE_VERTEXPROCESSING,0 };
0180:     D3DDEVTYPE ps[] = {D3DDEVTYPE_HAL, D3DDEVTYPE_REF, (D3DDEVTYPE)0};
0181:     
0182:     DWORD v = (caps.VertexShaderVersion < D3DVS_VERSION(1,1)) ? 1 : 0;// 対応頂点シェーダー
0183:     DWORD p = (caps.PixelShaderVersion  < D3DPS_VERSION(0,0)) ? 1 : 0;// 対応ピクセルシェーダー
0184: 
0185:     for(;ps[p];p++){
0186:     for(;vs[v];v++){
0187:         if(SUCCEEDED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, ps[p],hWnd,vs[v],&d3dpp,&s_lpD3DDEV))) goto set_up;
0188:     }
0189:     }
0190: set_up:
0191:     return S_OK;
0192: }
0193: /*-------------------------------------------
0194:     ウィンドウ処理
0195: --------------------------------------------*/
0196: LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam)
0197: {
0198:     static long prevX = 0;
0199:     static long prevY = 0;
0200:     static int sizeMoving = FALSE;
0201:     long x,y,dx,dy;
0202:     D3DXMATRIX m;
0203:     D3DXVECTOR3 v;
0204: 
0205:     switch(msg){
0206:     case WM_LBUTTONDOWN:
0207:         prevX = (lParam << 16) >> 16;
0208:         prevY = lParam >> 16;
0209:         SetCapture(hWnd);
0210:         break;
0211:     case WM_LBUTTONUP:
0212:         ReleaseCapture();
0213:         break;
0214:     case WM_MOUSEMOVE:
0215:         x = (lParam << 16) >> 16;
0216:         y = lParam >> 16;
0217:         dx = x - prevX;
0218:         dy = y - prevY;
0219:         if(wParam & MK_LBUTTON){
0220:             if(dx != 0){
0221:                 rot.y += 0.01f*dx;
0222:             }
0223:             if(dy != 0){
0224:                 rot.x += 0.01f*dy;
0225:             }
0226:         }
0227:         prevX = x;
0228:         prevY = y;
0229:         break;
0230:     case WM_KEYUP:
0231:         switch(wParam){
0232:         case VK_SHIFT:
0233:             sZoom = false;
0234:             break;
0235:         }
0236:         break;
0237:     case WM_KEYDOWN:
0238:         switch(wParam){
0239:         case VK_ESCAPE:
0240:         case VK_F12:
0241:             // 終了要求
0242:             s_end = true;
0243:             return 1;
0244:         case VK_SHIFT:
0245:             sZoom = true;
0246:             break;
0247:         default:
0248:             break;
0249:         }
0250:         break;
0251:     case WM_COMMAND:
0252:         switch(LOWORD(wParam)){
0253:         case FILE_MENU_OPEN:
0254:             {
0255:             char filename[1024];
0256:             OPENFILENAME ofn;
0257:             filename[0] = '\0';
0258: 
0259:             ZeroMemory(&ofn,sizeof(ofn));
0260:             ofn.lStructSize = sizeof(ofn);
0261:             ofn.hwndOwner = hWnd;
0262:             ofn.hInstance = shInstApp;
0263:             ofn.lpstrFilter = ".X Files (.x)\0*.x\0";
0264:             ofn.lpstrTitle = "Load X-File";
0265:             ofn.lpstrFile = filename;
0266:             ofn.nMaxFile = 1024;
0267:             ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
0268:             if(GetOpenFileName(&ofn)){
0269:                 if(model.Load(filename)){
0270:                     InvalidateRect(hWnd,NULL,TRUE);
0271:                 }
0272:             }
0273:             }
0274:             break;
0275:         case FILE_MENU_EXIT:
0276:             s_end = true;
0277:             return 1;
0278:             break;
0279:         case FILE_MENU_ABOUT:// バージョン情報
0280:             DialogBox(shInstApp, MAKEINTRESOURCE(IDD_ABOUT_DIALOG), hWnd, (DLGPROC)MyDlgProc);
0281:             break;
0282:         default:
0283:             break;
0284:         }
0285:         break;
0286:     case WM_CLOSE:                  // ×ボタンを押した
0287:         s_end = true;
0288:         return 1;
0289:         break;
0290:     default:
0291:         return DefWindowProc(hWnd,msg,wParam,lParam);
0292:     }
0293:     return 0L;
0294: }
0295: // ----------------------------------------------------------------------------
0296: // Name: set_fps()
0297: // Desc: フレーム数の表示
0298: //-----------------------------------------------------------------------------
0299: static void fps_disp()
0300: {
0301:     static DWORD    last = timeGetTime();
0302:     static DWORD    frames = 0;
0303:     static char     buf[256] = "";
0304:     DWORD           current;
0305:     
0306:     current = timeGetTime();
0307:     frames++;
0308:     
0309:     if(500 <= current - last) {// 0.5秒後とに更新
0310:         float dt = (float)(current - last) / 1000.0f;
0311:         float fps = (float)frames / dt;
0312:         last = current;
0313:         frames = 0;
0314:         sprintf(buf, "%.02f fps", fps);
0315:     }
0316:     sFont.Print(buf, 0,0);
0317: }
0318: // ----------------------------------------------------------------------------
0319: // Name: MyDlgProc
0320: // Desc: バージョン情報のプロシージャ
0321: //-----------------------------------------------------------------------------
0322: LRESULT CALLBACK MyDlgProc(HWND hDlgWnd, UINT msg, WPARAM wp, LPARAM lp)
0323: {
0324:     switch (msg) {
0325:     case WM_INITDIALOG:
0326:         return FALSE;
0327:     case WM_COMMAND:
0328:         switch (LOWORD(wp)) {
0329:             case IDOK:
0330:                 EndDialog(hDlgWnd, IDOK);
0331:                 break;
0332:             default:
0333:                 return FALSE;
0334:         }
0335:     default:
0336:         return FALSE;
0337:     }
0338:     return TRUE;
0339: }
0340: