#include "stdhdr.h"
#include "Debug.h"
#include "Graphics.h"
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3d8.lib")
#pragma comment(lib, "d3dx8.lib")
IDirect3D8 *g_pD3D;
IDirect3DDevice8 *g_pd3dDevice;
BOOL InitDirectXGraphics()
{
g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);
if (g_pD3D == NULL)
return FALSE;
return InitDevice(TRUE);
}
BOOL InitDevice(BOOL bFullScreen)
{
HRESULT h;
ShowWindow(hWndMain, SW_HIDE);
if (bFullScreen)
{
SetWindowLong(hWndMain, GWL_STYLE, WS_POPUP);
SetWindowPos(hWndMain, NULL, 0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN), SWP_NOZORDER);
}
else
{
SetWindowLong(hWndMain, GWL_STYLE, WS_POPUP|WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX);
}
ShowWindow(hWndMain, SW_SHOW);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
if (bFullScreen)
{
d3dpp.Windowed = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.BackBufferCount = 2;
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
d3dpp.hDeviceWindow = hWndMain;
d3dpp.BackBufferWidth = 640;
d3dpp.BackBufferHeight = 480;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
}
else
{
D3DDISPLAYMODE d3ddm;
if (FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
return FALSE;
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
}
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
h = g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWndMain,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice);
if (FAILED(h))
return FALSE;
if (!bFullScreen)
{
int cxScreen = GetSystemMetrics(SM_CXSCREEN);
int cyScreen = GetSystemMetrics(SM_CYSCREEN);
RECT r;
r.left = (cxScreen - 640) / 2;
r.top = (cyScreen - 480) / 2;
r.right = r.left + 640;
r.bottom = r.top + 480;
AdjustWindowRect(&r, WS_POPUP|WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_MINIMIZEBOX, FALSE);
SetWindowPos(hWndMain, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER);
}
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
return TRUE;
}
void BeginScene()
{
#ifdef _DEBUG
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0);
#endif
g_pd3dDevice->BeginScene();
}
void EndScene()
{
g_pd3dDevice->EndScene();
}
void Flip()
{
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}
void CloseDevice()
{
if (g_pd3dDevice != NULL)
{
g_pd3dDevice->Release();
g_pd3dDevice = NULL;
}
}
void ExitDirectXGraphics()
{
CloseDevice();
if (g_pD3D != NULL)
{
g_pD3D->Release();
g_pD3D = NULL;
}
}
struct CCustomVertex
{
float x, y, z, rhw; DWORD dwColor; float tu, tv; };
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
struct CRectangularObject
{
IDirect3DTexture8 *pTexture;
CCustomVertex vertices[4];
};
CRectangularObject *g_pObjects;
UINT g_nObjectBufferSize, g_nNewObjectPointer;
IDirect3DVertexBuffer8 *g_pVB;
BOOL SetObjectBufferSize(UINT nBufferSize)
{
if (g_pObjects != NULL)
return FALSE;
g_pObjects = new CRectangularObject[nBufferSize];
if (g_pObjects == NULL)
return FALSE;
g_nObjectBufferSize = nBufferSize;
g_nNewObjectPointer = 0;
return TRUE;
}
void ReleaseObjectBuffer()
{
if (g_pObjects != NULL)
{
delete [] g_pObjects;
g_pObjects = NULL;
}
}
int CreateRectangularObject(int x, int y, int cx, int cy,
IDirect3DTexture8 *pTexture, int xSrc, int ySrc)
{
if (g_pObjects == NULL)
return -1;
if (g_pVB != NULL)
return -1;
if (g_nNewObjectPointer == g_nObjectBufferSize)
return -1;
CRectangularObject *pObj = &g_pObjects[g_nNewObjectPointer];
D3DSURFACE_DESC desc;
pTexture->GetLevelDesc(0, &desc);
TRACE(_T("Creating object from texture %08X (%d,%d)\n"), pTexture, desc.Width, desc.Height);
pObj->vertices[0].x = pObj->vertices[2].x = (float)x - 0.5f;
pObj->vertices[1].x = pObj->vertices[3].x = (float)(x + cx) - 0.5f;
pObj->vertices[0].y = pObj->vertices[1].y = (float)y - 0.5f;
pObj->vertices[2].y = pObj->vertices[3].y = (float)(y + cy) - 0.5f;
pObj->vertices[0].z = pObj->vertices[1].z =
pObj->vertices[2].z = pObj->vertices[3].z = 0.5f;
pObj->vertices[0].rhw = pObj->vertices[1].rhw =
pObj->vertices[2].rhw = pObj->vertices[3].rhw = 1.0f;
pObj->vertices[0].dwColor = pObj->vertices[1].dwColor =
pObj->vertices[2].dwColor = pObj->vertices[3].dwColor = 0xFFFFFFFF;
pObj->vertices[0].tu = pObj->vertices[2].tu = (float)xSrc / (float)desc.Width;
pObj->vertices[1].tu = pObj->vertices[3].tu = (float)(xSrc + cx) / (float)desc.Width;
pObj->vertices[0].tv = pObj->vertices[1].tv = (float)ySrc / (float)desc.Height;
pObj->vertices[2].tv = pObj->vertices[3].tv = (float)(ySrc + cy) / (float)desc.Height;
pObj->pTexture = pTexture;
g_nNewObjectPointer++;
return g_nNewObjectPointer - 1;
}
BOOL MoveObject(int nIndex, int x, int y)
{
if (g_pObjects == NULL)
return FALSE;
if (nIndex == -1)
return FALSE;
if ((UINT)nIndex >= g_nNewObjectPointer)
return FALSE;
CRectangularObject *pObj = &g_pObjects[nIndex];
int cx = (int)(pObj->vertices[3].x - pObj->vertices[0].x);
int cy = (int)(pObj->vertices[3].y - pObj->vertices[0].y);
pObj->vertices[0].x = pObj->vertices[2].x = (float)x - 0.5f;
pObj->vertices[1].x = pObj->vertices[3].x = (float)(x + cx) - 0.5f;
pObj->vertices[0].y = pObj->vertices[1].y = (float)y - 0.5f;
pObj->vertices[2].y = pObj->vertices[3].y = (float)(y + cy) - 0.5f;
return TRUE;
}
BOOL SetObjectTexture(int nIndex, IDirect3DTexture8 *pTexture)
{
if (g_pObjects == NULL)
return FALSE;
if (nIndex == -1)
return FALSE;
if ((UINT)nIndex >= g_nNewObjectPointer)
return FALSE;
g_pObjects[nIndex].pTexture = pTexture;
return TRUE;
}
BOOL CreateVertexBuffer()
{
HRESULT h;
if (g_pVB != NULL)
return FALSE;
h = g_pd3dDevice->CreateVertexBuffer(g_nNewObjectPointer * 4 * sizeof(CCustomVertex),
D3DUSAGE_WRITEONLY,
D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB);
if (FAILED(h))
return FALSE;
CCustomVertex *pVertices;
h = g_pVB->Lock(0, 0, (BYTE **)&pVertices, D3DLOCK_DISCARD);
if (FAILED(h))
return FALSE;
for (UINT i = 0; i < g_nNewObjectPointer; i++)
{
memcpy(pVertices, g_pObjects[i].vertices, 4 * sizeof(CCustomVertex));
pVertices += 4;
}
g_pVB->Unlock();
return TRUE;
}
BOOL RefreshVertexBuffer()
{
HRESULT h;
if (g_pVB == NULL)
return FALSE;
CCustomVertex *pVertices;
h = g_pVB->Lock(0, 0, (BYTE **)&pVertices, D3DLOCK_DISCARD);
if (FAILED(h))
return FALSE;
for (UINT i = 0; i < g_nNewObjectPointer; i++)
{
memcpy(pVertices, g_pObjects[i].vertices, 4 * sizeof(CCustomVertex));
pVertices += 4;
}
g_pVB->Unlock();
return TRUE;
}
void ReleaseVertexBuffer()
{
if (g_pVB != NULL)
{
g_pVB->Release();
g_pVB = NULL;
}
}
void BeginDrawingObjects()
{
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetStreamSource(0, g_pVB, sizeof(CCustomVertex));
g_pd3dDevice->SetVertexShader(D3DFVF_CUSTOMVERTEX);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
}
void DrawObject(int nIndex)
{
g_pd3dDevice->SetTexture(0, g_pObjects[nIndex].pTexture);
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, nIndex * 4, 2);
}
IDirect3DTexture8 *LoadTexture(LPCTSTR lpFilename)
{
IDirect3DTexture8 *pTexture;
HRESULT h = D3DXCreateTextureFromFileEx(g_pd3dDevice, lpFilename,
D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_FILTER_NONE, D3DX_DEFAULT,
0, NULL, NULL, &pTexture);
if (FAILED(h))
return NULL;
return pTexture;
}