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