#define STRICT #define WIN32_LEAN_AND_MEAN #define SAFE_RELEASE(x) { if(x){ (x)->Release(); (x)=NULL; } } #define D3D_DEBUG_INFO #include #include #include #include #include"SelectDevice.h" #include"RubikCube.h" // アプリケーション関連 HINSTANCE g_hInst=NULL; HWND g_hWnd=NULL; RECT g_rcWnd; SIZE g_sizeFullMode; bool g_bWndMode=true; bool g_bActive=false; // DirectX関連 IDirect3D9 *g_pD3D=NULL; IDirect3DDevice9 *g_pD3DDevice=NULL; D3DPRESENT_PARAMETERS g_D3DPP,g_D3DPPWnd,g_D3DPPFull; bool g_bDeviceLost=false; // 頂点関連 struct XYZBuffer { FLOAT x,y,z; }; struct ColorBuffer { D3DCOLOR color; }; D3DVERTEXELEMENT9 g_decl[]= { {0,0,D3DDECLTYPE_FLOAT3 ,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0}, {1,0,D3DDECLTYPE_D3DCOLOR,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_COLOR ,0}, D3DDECL_END() }; IDirect3DVertexDeclaration9 *g_pVertexDeclaration=NULL; IDirect3DVertexBuffer9 *g_pD3DVBXYZ=NULL,*g_pD3DVBColor=NULL; IDirect3DIndexBuffer9 *g_pD3DIBuffer=NULL; // 座標変換行列 D3DXMATRIX g_matWorld,g_matView,g_matProj; // シェーダ ID3DXEffect *g_pD3DXEffect=NULL; // 関数原型宣言 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam); HRESULT InitApp(HINSTANCE hInst) { g_hInst=hInst; WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = MainWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = _T(__FILE__); if(!RegisterClass(&wc)) return DXTRACE_ERR_MSGBOX(_T("InitApp RegisterClass"),GetLastError()); RECT rc; GetWindowRect(GetDesktopWindow(),&rc); g_sizeFullMode.cx=rc.right-rc.left; g_sizeFullMode.cy=rc.bottom-rc.top; if(g_bWndMode) { rc.left=0; rc.top=0; rc.right=640; rc.bottom=480; AdjustWindowRect(&rc,WS_OVERLAPPEDWINDOW,FALSE); rc.right-=rc.left; rc.bottom-=rc.top; rc.left=CW_USEDEFAULT; rc.top=CW_USEDEFAULT; } else { rc.left=0; rc.top=0; rc.right=g_sizeFullMode.cx; rc.bottom=g_sizeFullMode.cy; } g_hWnd=CreateWindow( _T(__FILE__),_T("ルービックキューブ"), (g_bWndMode?WS_OVERLAPPEDWINDOW:WS_POPUP) | WS_VISIBLE, rc.left,rc.top,rc.right,rc.bottom, NULL,NULL,hInst,NULL); if(g_hWnd==NULL) return DXTRACE_ERR_MSGBOX(_T("InitApp CreateWindow"),GetLastError()); return S_OK; } HRESULT InitVertex(void) { HRESULT hr=g_pD3DDevice->CreateVertexDeclaration(g_decl,&g_pVertexDeclaration); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics CreateVertexDeclaration"),hr); hr=g_pD3DDevice->CreateVertexBuffer(sizeof(XYZBuffer)*8*CUBES,0,0,D3DPOOL_MANAGED,&g_pD3DVBXYZ,NULL); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics CreateVertexBuffer XYZBuffer"),hr); hr=g_pD3DDevice->CreateVertexBuffer(sizeof(ColorBuffer)*8*CUBES,0,0,D3DPOOL_MANAGED,&g_pD3DVBColor,NULL); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics CreateVertexBuffer ColorBuffer"),hr); hr=g_pD3DDevice->CreateIndexBuffer(36*2*CUBES,0,D3DFMT_INDEX16,D3DPOOL_MANAGED,&g_pD3DIBuffer,NULL); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics CreateIndexBuffer"),hr); for(int i=0;iLock(sizeof(XYZBuffer)*8*i,sizeof(XYZBuffer)*8,(void**)&pXYZBuffer,0); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics Lock XYZBuffer"),hr); float x=(i%3)*2.1f-2.1f; float y=-((i/3)%3)*2.1f+2.1f; float z=(i/9)*2.1f-2.1f; pXYZBuffer[0].x=-1.0f+x; pXYZBuffer[0].y= 1.0f+y; pXYZBuffer[0].z=-1.0f+z; pXYZBuffer[1].x= 1.0f+x; pXYZBuffer[1].y= 1.0f+y; pXYZBuffer[1].z=-1.0f+z; pXYZBuffer[2].x=-1.0f+x; pXYZBuffer[2].y=-1.0f+y; pXYZBuffer[2].z=-1.0f+z; pXYZBuffer[3].x= 1.0f+x; pXYZBuffer[3].y=-1.0f+y; pXYZBuffer[3].z=-1.0f+z; pXYZBuffer[4].x=-1.0f+x; pXYZBuffer[4].y= 1.0f+y; pXYZBuffer[4].z= 1.0f+z; pXYZBuffer[5].x= 1.0f+x; pXYZBuffer[5].y= 1.0f+y; pXYZBuffer[5].z= 1.0f+z; pXYZBuffer[6].x=-1.0f+x; pXYZBuffer[6].y=-1.0f+y; pXYZBuffer[6].z= 1.0f+z; pXYZBuffer[7].x= 1.0f+x; pXYZBuffer[7].y=-1.0f+y; pXYZBuffer[7].z= 1.0f+z; hr=g_pD3DVBXYZ->Unlock(); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics UnLock XYZBuffer"),hr); ColorBuffer *pColorBuffer; hr=g_pD3DVBColor->Lock(sizeof(ColorBuffer)*8*i,sizeof(ColorBuffer)*8,(void**)&pColorBuffer,0); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics Lock ColorBuffer"),hr); pColorBuffer[0].color=D3DCOLOR_ARGB(0xff,0xff,0x00,0x00); pColorBuffer[1].color=D3DCOLOR_ARGB(0xff,0x00,0xff,0x00); pColorBuffer[2].color=D3DCOLOR_ARGB(0xff,0x00,0x00,0xff); pColorBuffer[3].color=D3DCOLOR_ARGB(0xff,0x00,0x00,0x00); pColorBuffer[4].color=D3DCOLOR_ARGB(0xff,0xff,0xff,0x00); pColorBuffer[5].color=D3DCOLOR_ARGB(0xff,0xff,0x00,0xff); pColorBuffer[6].color=D3DCOLOR_ARGB(0xff,0x00,0xff,0xff); pColorBuffer[7].color=D3DCOLOR_ARGB(0xff,0x00,0x00,0x00); hr=g_pD3DVBColor->Unlock(); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics UnLock ColorBuffer"),hr); WORD *pIndex; hr=g_pD3DIBuffer->Lock(36*2*i,36*2,(void**)&pIndex,0); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics Lock Index"),hr); pIndex[ 0]=0; pIndex[ 1]=3; pIndex[ 2]=2; pIndex[ 3]=0; pIndex[ 4]=1; pIndex[ 5]=3; pIndex[ 6]=5; pIndex[ 7]=6; pIndex[ 8]=7; pIndex[ 9]=5; pIndex[10]=4; pIndex[11]=6; pIndex[12]=1; pIndex[13]=7; pIndex[14]=3; pIndex[15]=1; pIndex[16]=5; pIndex[17]=7; pIndex[18]=2; pIndex[19]=4; pIndex[20]=0; pIndex[21]=2; pIndex[22]=6; pIndex[23]=4; pIndex[24]=4; pIndex[25]=1; pIndex[26]=0; pIndex[27]=4; pIndex[28]=5; pIndex[29]=1; pIndex[30]=6; pIndex[31]=2; pIndex[32]=3; pIndex[33]=6; pIndex[34]=3; pIndex[35]=7; hr=g_pD3DIBuffer->Unlock(); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics UnLock Index"),hr); } InitCubeMatrix(); D3DXMatrixIdentity(&g_matWorld); D3DXVECTOR3 vEye(0.0f,10.0f,-10.0f); D3DXVECTOR3 vAt(0.0f,0.0f,0.0f); D3DXVECTOR3 vUp(0.0f,1.0f,0.0f); D3DXMatrixLookAtLH(&g_matView,&vEye,&vAt,&vUp); D3DXMatrixPerspectiveFovLH(&g_matProj,D3DX_PI/3.0f, (float)g_D3DPP.BackBufferWidth/g_D3DPP.BackBufferHeight,5.0f,20.0f); return S_OK; } HRESULT InitDXGraphics(void) { g_pD3D=Direct3DCreate9(D3D_SDK_VERSION); if(g_pD3D==NULL) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics Direct3DCreate9"),E_FAIL); UINT adapter; D3DDEVTYPE device; HRESULT hr=SelectD3DDevice(&adapter,&device); if(FAILED(hr)) DXTRACE_ERR_MSGBOX(_T("InitDxGraphics SelectD3DDevice"),hr); if(g_bWndMode) CopyMemory(&g_D3DPP,&g_D3DPPWnd,sizeof(D3DPRESENT_PARAMETERS)); else CopyMemory(&g_D3DPP,&g_D3DPPFull,sizeof(D3DPRESENT_PARAMETERS)); hr=g_pD3D->CreateDevice(adapter,device,g_hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,&g_D3DPP,&g_pD3DDevice); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("InitDXGraphics CreateDevice D3DCREATE_HARDWARE_VERTEXPROCESSING"),hr); hr=g_pD3D->CreateDevice(adapter,device,g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,&g_D3DPP,&g_pD3DDevice); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("InitDXGraphics CreateDevice D3DCREATE_SOFTWARE_VERTEXPROCESSING"),hr); } } D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; vp.Width = g_D3DPP.BackBufferWidth; vp.Height = g_D3DPP.BackBufferHeight; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; hr=g_pD3DDevice->SetViewport(&vp); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics SetViewport"),hr); hr=D3DXCreateEffectFromFile(g_pD3DDevice,_T("shader.fx"),NULL,NULL,0,NULL,&g_pD3DXEffect,NULL); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics D3DXCreateEffectFromFile"),hr); D3DXHANDLE hTech=NULL,hTechNext; while(true) { hr=g_pD3DXEffect->FindNextValidTechnique(hTech,&hTechNext); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics FindNextValidTechnique"),hr); if(hTechNext==NULL) break; hTech=hTechNext; hr=g_pD3DXEffect->ValidateTechnique(hTech); if(FAILED(hr)) return DXTRACE_ERR_MSGBOX(_T("InitDXGraphics ValidateTechnique"),hr); } return InitVertex(); } HRESULT InitD3DObject(void) { g_pD3DDevice->SetRenderState(D3DRS_ZENABLE, g_D3DPP.EnableAutoDepthStencil ? D3DZB_TRUE : D3DZB_FALSE); g_pD3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, g_D3DPP.MultiSampleType!=D3DMULTISAMPLE_NONE ? TRUE : FALSE); g_pD3DDevice->SetVertexDeclaration(g_pVertexDeclaration); g_pD3DDevice->SetStreamSource(0,g_pD3DVBXYZ,0,sizeof(XYZBuffer)); g_pD3DDevice->SetStreamSource(1,g_pD3DVBColor,0,sizeof(ColorBuffer)); g_pD3DDevice->SetIndices(g_pD3DIBuffer); if(g_pD3DXEffect) g_pD3DXEffect->OnResetDevice(); g_pD3DXEffect->SetTechnique("TVPShader"); return S_OK; } HRESULT Render(void) { DWORD Flags=(g_D3DPP.EnableAutoDepthStencil==TRUE)? D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL : D3DCLEAR_TARGET; g_pD3DDevice->Clear(0,NULL,Flags,D3DCOLOR_ARGB(255,0,0,0),1.0f,0); if(SUCCEEDED(g_pD3DDevice->BeginScene())) { UINT numPass; g_pD3DXEffect->Begin(&numPass,0); for(UINT iPass=0;iPassBeginPass(iPass); for(int i=0;iSetMatrix("WorldViewProj",&mat); g_pD3DXEffect->CommitChanges(); g_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,8*i,0,8,0,12); } g_pD3DXEffect->EndPass(); } g_pD3DXEffect->End(); g_pD3DDevice->EndScene(); } return g_pD3DDevice->Present(NULL,NULL,NULL,NULL); } HRESULT CleanupD3DObject(void) { if(g_pD3DXEffect) g_pD3DXEffect->OnLostDevice(); return S_OK; } bool CleanupDXGraphics(void) { SAFE_RELEASE(g_pD3DXEffect); SAFE_RELEASE(g_pD3DIBuffer); SAFE_RELEASE(g_pD3DVBColor); SAFE_RELEASE(g_pD3DVBXYZ); SAFE_RELEASE(g_pVertexDeclaration); SAFE_RELEASE(g_pD3DDevice); SAFE_RELEASE(g_pD3D); return true; } HRESULT ChangeWindowSize(void) { CleanupD3DObject(); HRESULT hr=g_pD3DDevice->Reset(&g_D3DPP); if(FAILED(hr)) { if(hr==D3DERR_DEVICELOST) g_bDeviceLost=true; else DestroyWindow(g_hWnd); return DXTRACE_ERR_MSGBOX(_T("ChangeWindowSize Reset"),hr); } hr=InitD3DObject(); if(FAILED(hr)) { DestroyWindow(g_hWnd); return DXTRACE_ERR_MSGBOX(_T("ChangeWindowSize InitD3DObject"),hr); } D3DVIEWPORT9 vp; vp.X = 0; vp.Y = 0; vp.Width = g_D3DPP.BackBufferWidth; vp.Height = g_D3DPP.BackBufferHeight; vp.MinZ = 0.0f; vp.MaxZ = 1.0f; hr=g_pD3DDevice->SetViewport(&vp); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("ChangeWindowSize SetViewport"),hr); DestroyWindow(g_hWnd); } return hr; } void ChangeDisplayMode(void) { g_bWndMode = !g_bWndMode; CleanupD3DObject(); if(g_bWndMode) CopyMemory(&g_D3DPP,&g_D3DPPWnd,sizeof(D3DPRESENT_PARAMETERS)); else { CopyMemory(&g_D3DPP,&g_D3DPPFull,sizeof(D3DPRESENT_PARAMETERS)); GetWindowRect(g_hWnd,&g_rcWnd); } HRESULT hr=g_pD3DDevice->Reset(&g_D3DPP); if(FAILED(hr)) { if(hr==D3DERR_DEVICELOST) g_bDeviceLost=true; else DestroyWindow(g_hWnd); DXTRACE_ERR_MSGBOX(_T("ChangeDisplayMode Reset"),hr); return; } hr=InitD3DObject(); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("ChangeDisplayMode InitD3DObject"),hr); DestroyWindow(g_hWnd); return; } if(g_bWndMode) { SetWindowLong(g_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW | WS_VISIBLE); SetWindowPos(g_hWnd,HWND_NOTOPMOST, g_rcWnd.left,g_rcWnd.top, g_rcWnd.right-g_rcWnd.left,g_rcWnd.bottom-g_rcWnd.top, SWP_SHOWWINDOW); } else { SetWindowLong(g_hWnd,GWL_STYLE,WS_POPUP | WS_VISIBLE); } } LRESULT CALLBACK MainWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { static float c_rp=D3DX_PI/180.0f,c_rm=-D3DX_PI/180.0f; D3DXMATRIX mat; switch(msg) { case WM_ACTIVATE: g_bActive=(LOWORD(wParam)!=WA_INACTIVE); return 0; case WM_SIZE: if(!g_pD3DDevice || g_bDeviceLost) return 0; if(wParam==SIZE_MINIMIZED || (wParam!=SIZE_MAXIMIZED && wParam!=SIZE_RESTORED)) return 0; g_D3DPP.BackBufferWidth = LOWORD(lParam); g_D3DPP.BackBufferHeight = HIWORD(lParam); ChangeWindowSize(); return 0; case WM_KEYDOWN: switch(wParam) { case VK_F1: ChangeDisplayMode(); return 0; case VK_ESCAPE: SendMessage(hWnd,WM_CLOSE,0,0); return 0; case VK_UP: D3DXMatrixRotationX(&mat,c_rp); g_matWorld*=mat; return 0; case VK_DOWN: D3DXMatrixRotationX(&mat,c_rm); g_matWorld*=mat; return 0; case VK_LEFT: D3DXMatrixRotationY(&mat,c_rp); g_matWorld*=mat; return 0; case VK_RIGHT: D3DXMatrixRotationY(&mat,c_rm); g_matWorld*=mat; return 0; case VK_NUMPAD0: Indicate(0); return 0; case VK_NUMPAD1: Indicate(1); return 0; case VK_NUMPAD2: Indicate(2); return 0; case VK_NUMPAD3: Indicate(3); return 0; case VK_NUMPAD4: Indicate(4); return 0; case VK_NUMPAD5: Indicate(5); return 0; case VK_NUMPAD6: Indicate(6); return 0; case VK_NUMPAD7: Indicate(7); return 0; case VK_NUMPAD8: Indicate(8); return 0; case VK_NUMPAD9: Indicate(9); return 0; case VK_ADD: Rotation(true); ChangeIndex(true); return 0; case VK_SUBTRACT: Rotation(false); ChangeIndex(false); return 0; case VK_SPACE: Shuffle(10); return 0; } return 0; case WM_SETCURSOR: if(!g_bWndMode){ SetCursor(NULL); return TRUE; } break; case WM_DESTROY: CleanupD3DObject(); CleanupDXGraphics(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd,msg,wParam,lParam); } bool AppIdle(void) { if(!g_pD3D || !g_pD3DDevice) return false; if(!g_bActive) return true; HRESULT hr; if(g_bDeviceLost) { Sleep(100); hr=g_pD3DDevice->TestCooperativeLevel(); if(FAILED(hr)) { if(hr==D3DERR_DEVICELOST) { g_bDeviceLost=true; return true; } if(hr!=D3DERR_DEVICENOTRESET) return false; CleanupD3DObject(); hr=g_pD3DDevice->Reset(&g_D3DPP); if(FAILED(hr)) { if(hr==D3DERR_DEVICELOST) { g_bDeviceLost=true; return true; } DXTRACE_ERR_MSGBOX(_T("AppIdle Reset"),hr); return false; } hr=InitD3DObject(); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("AppIdle InitD3DObject"),hr); return false; } } g_bDeviceLost=false; } hr=Render(); if(hr==D3DERR_DEVICELOST) g_bDeviceLost=true; else if(FAILED(hr)) return false; return true; } int WINAPI _tWinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nCmdShow) { HRESULT hr=InitApp(hInst); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("_tWinMain InitApp"),hr); return 0; } hr=InitDXGraphics(); if(FAILED(hr)) DXTRACE_ERR_MSGBOX(_T("_tWinMain InitDXGraphics"),hr); else { hr=InitD3DObject(); if(FAILED(hr)) { DXTRACE_ERR_MSGBOX(_T("_tWinMain InitD3DObject"),hr); DestroyWindow(g_hWnd); } } MSG msg; do { if(PeekMessage(&msg,0,0,0,PM_REMOVE)) { DispatchMessage(&msg); } else { if(!AppIdle()) DestroyWindow(g_hWnd); Sleep(1); } }while(msg.message!=WM_QUIT); return (int)msg.wParam; }