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