// в этом файле лежат все функции WinAPI
#include <windows.h>
// подключаем заголовочный файл DirectX 9 SDK
#include <d3d9.h>
#include <d3dx9.h>
// Для работы с mesh
#include <d3dx9mesh.h>
#include <math.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
LPDIRECT3D9 pDirect3D = NULL;
LPDIRECT3DDEVICE9 pDirect3DDevice = NULL;
// Указатель на Mesh
LPD3DXMESH pMesh = NULL;
// Указател на буфер mesh-а
LPD3DXBUFFER pMeshBuffer = NULL;
// Указатель на буфер материалов
D3DMATERIAL9 *pMeshMaterial = NULL;
// Указатель на буфер текстур
LPDIRECT3DTEXTURE9 *pMeshTexture = NULL;
// Количество материала и текстур
DWORD dwNumber = 0;
DWORD OneTick = 0;
HINSTANCE hInstance;
// Функция обработки сообщений - прототип
LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
// Функция инициализации Direct3D - прототип
HRESULT InitDirect3D(HWND hwnd);
// Функция рендеринга Direct3D - прототип
void RenderingDirect3D(void);
// Функция освобождения захваченных ресурсов - прототип
void DeleteDirect3D(void);
// Функция инициализации объекта (буфера и индексов вершин) - прототип
HRESULT InitMesh(void);
// Установка матриц преобоазования - прототип
void Matrix(void);
// Рисует созданную mesh - прототип
void DrawMyMesh(void);
// Функция которая является входной точкой приложения
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow)
{
WNDCLASSEX windowsclass;
HWND hwnd;
MSG msg;
hInstance = hInst;
windowsclass.cbSize = sizeof(WNDCLASSEX);
windowsclass.style = CS_DBLCLKS|CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
windowsclass.lpfnWndProc = MainWinProc;
windowsclass.cbClsExtra = 0;
windowsclass.cbWndExtra = 0;
windowsclass.hInstance = hInst;
windowsclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowsclass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowsclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
windowsclass.lpszMenuName = NULL;
windowsclass.lpszClassName = "WINDOWSCLASS";
windowsclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&windowsclass))
return 0;
hwnd = CreateWindowEx(NULL, "WINDOWSCLASS", "Загрузка Х-файла с вращением", WS_OVERLAPPEDWINDOW|
WS_VISIBLE, 0, 0, 770, 500, NULL, NULL, hInst, NULL);
if (!hwnd)
return 0;
if (SUCCEEDED(InitDirect3D(hwnd)))
{
if (SUCCEEDED(InitMesh()))
{
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
RenderingDirect3D();
}
}
}
return (int)msg.wParam;
}
// Функция обработки сообщений
LRESULT CALLBACK MainWinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
// События Создания объектов
case WM_CREATE:
break;
//Обработка сообщений от элементов управления
case WM_COMMAND:
break;
//WM_PAINT - для рисования
case WM_PAINT:
break;
// WM_DESTROY - для закрытия окна
case WM_DESTROY:
DeleteDirect3D();
PostQuitMessage(0);
break;
}
return (DefWindowProc(hwnd, msg, wparam, lparam));
}
// Функция инициализации Direct3D
HRESULT InitDirect3D(HWND hwnd)
{
if (NULL == (pDirect3D = Direct3DCreate9(D3D_SDK_VERSION)))
return E_FAIL;
D3DDISPLAYMODE Display;
if (FAILED(pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &Display)))
return E_FAIL;
D3DPRESENT_PARAMETERS Direct3DParameter;
ZeroMemory(&Direct3DParameter, sizeof(Direct3DParameter));
Direct3DParameter.Windowed = true;
Direct3DParameter.SwapEffect = D3DSWAPEFFECT_DISCARD;
Direct3DParameter.BackBufferFormat = Display.Format;
// Включаем z-буфер
Direct3DParameter.EnableAutoDepthStencil = TRUE;
// Формат поверхности z-буфера
Direct3DParameter.AutoDepthStencilFormat = D3DFMT_D16;
if (FAILED(pDirect3D -> CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &Direct3DParameter, &pDirect3DDevice)))
return E_FAIL;
pDirect3DDevice->SetRenderState(D3DRS_LIGHTING, false);
// Включаем z-буфер
pDirect3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
return S_OK;
}
// Функция рендеринга Direct3D
void RenderingDirect3D(void)
{
if (pDirect3DDevice == NULL)
return;
// Очистка z-буфера
pDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(172, 221, 101), 1.0f, 0);
pDirect3DDevice->BeginScene();
Matrix();
DrawMyMesh();
pDirect3DDevice->EndScene();
pDirect3DDevice->Present(NULL, NULL, NULL, NULL);
}
// Функция освобождения захваченных ресурсов
void DeleteDirect3D(void)
{
if (pDirect3DDevice != NULL)
pDirect3DDevice->Release();
if (pDirect3D != NULL)
pDirect3D->Release();
if (pMeshMaterial != NULL)
delete [] pMeshMaterial;
if (pMeshTexture)
{
for(DWORD i = 0; i < dwNumber; i++)
{
if (pMeshTexture[i])
pMeshTexture[i]->Release();
}
delete [] pMeshTexture;
}
if (pMesh != NULL)
pMesh->Release();
}
// Функция инициализации объекта (буфера и индексов вершин)
HRESULT InitMesh(void)
{
if (FAILED(D3DXLoadMeshFromX("Tiger.x", D3DXMESH_SYSTEMMEM, pDirect3DDevice, NULL, &pMeshBuffer, NULL, &dwNumber, &pMesh)))
return E_FAIL;
// Извлекаем свойства материала и названия{имена} структуры
D3DXMATERIAL *D3DXMeshMaterial = (D3DXMATERIAL *)pMeshBuffer->GetBufferPointer();
pMeshMaterial = new D3DMATERIAL9[dwNumber];
pMeshTexture = new LPDIRECT3DTEXTURE9[dwNumber];
for (DWORD i = 0; i < dwNumber; i++)
{
// Копируем материал
pMeshMaterial[i] = D3DXMeshMaterial[i].MatD3D;
// Установить окружающего свет
pMeshMaterial[i].Ambient = pMeshMaterial[i].Diffuse;
// Загружаем текстуру
if ( FAILED(D3DXCreateTextureFromFile(pDirect3DDevice, D3DXMeshMaterial[i].pTextureFilename, &pMeshTexture[i])))
pMeshTexture[i] = NULL;
}
// Уничтожаем буфер материала
pMeshBuffer->Release();
return S_OK;
}
// Рисует созданную mesh
void DrawMyMesh(void)
{
for (DWORD i = 0; i < dwNumber; i++)
{
// Устанавливаем материал и текстуру
pDirect3DDevice->SetMaterial(&pMeshMaterial[i]);
pDirect3DDevice->SetTexture(0, pMeshTexture[i]);
// Рисуем Меш
pMesh->DrawSubset(i);
}
}
// Установка матриц преобоазования
void Matrix(void)
{
// Матрица вида
D3DXMATRIX MatrixView;
//матрица проекции
D3DXMATRIX MatrixProjection;
D3DXMATRIX MatrixWorld;
D3DXMATRIX MatrixTranslation;
D3DXMATRIX MatrixRotation;
float BeginAngle;
float rps;
UINT iTime;
float fAngle;
BeginAngle = D3DX_PI/4.0f;
rps = 0.5f;
iTime = GetTickCount();
if(!OneTick)
OneTick = iTime;
fAngle = BeginAngle + (iTime - OneTick) * (D3DX_PI * 2.0f * rps / 1000.0f);
D3DXMatrixRotationY(&MatrixRotation, fAngle); // поворот тигра
D3DXMatrixTranslation(&MatrixTranslation, 0.0f, 0.0f, 0.0f); // положение тигра
D3DXMatrixMultiply(&MatrixWorld, &MatrixRotation, &MatrixTranslation);
pDirect3DDevice->SetTransform(D3DTS_WORLD, &MatrixWorld);
// Изменяем видовую матрицу
D3DXMatrixLookAtLH(&MatrixView, // полученная в итоге видовая матрица
&D3DXVECTOR3(0.0f, 0.0f, 10.0f), // точка, из которой смотрим
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), // куда смотрим
&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // направление верха
// Устанавливаем видовую матрицу
pDirect3DDevice->SetTransform(D3DTS_VIEW, &MatrixView);
// Изменяем матрицу проекции
D3DXMatrixPerspectiveFovLH(&MatrixProjection, // полученная итоговая матрица проекции
D3DX_PI/4, // поле зрения в направлении оси Y в радианах
1.54f, // соотношения сторон экрана 770/500=1.54
10.0f, // передний план отсечения сцены
200.0f); // задний план отсечения сцены
// Устанавливаем матрицу проекции
pDirect3DDevice->SetTransform(D3DTS_PROJECTION, &MatrixProjection);
}