12 марта 2010 в 15:50
Direct3D Урок 02: Отображение объектов
В этой статье мы научимся отображать простейший трехмерный объект - кубик. За основу мы возьмём проект из "первой статьи". Далее я приведу текст который нужно будет вставить в него, а незатронутые здесь функции будут опущены.
Для начала определим несколько новых переменных в начале переменных: первым делов объявляем два буфера: один буфер вершинный, другой - индексный.
Можно воспользоваться и одним, но так уйдет меньше памяти.
LPDIRECT3DVERTEXBUFFER9 MyVertexBuffer; // Вертекс буфер для отрисовки кубика LPDIRECT3DINDEXBUFFER9 MyIndexBuffer; // Индекс буфер для отрисовки кубика
Далее определяем структуру наших вершин. У нас они содержат свою позицию и цвет:
struct MyVertex
{
D3DXVECTOR3 position;
D3DCOLOR color;
};
Потом оговариваем формат вершин.
const DWORD MyVertex_FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
Теперь переходим к функции инициализации AllInit. Вот как она должна выглядеть:
bool AllInit()
{
if(!InitD3D())
return false;
После этого создадим буфер вершин:
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 8*sizeof(MyVertex), // Размер буфера (в нашем случае 8 вершин // каждая размером в структуру MyVertex) D3DUSAGE_WRITEONLY, // Используем буфер только для чтения MyVertex_FVF, // Формат наших вершин D3DPOOL_MANAGED, // DirectX сам управляет пересозданием буфера &MyVertexBuffer, // Наш указатель на буфер NULL // Оставим NULL ) ) ) return false; // Если произошла ошибка сообщить об этом
И буфер индексов:
if( FAILED( g_pd3dDevice->CreateIndexBuffer( 36*sizeof(short), // Размер буфера индексов (в нашем случае // 36 индексов каждый размером в short) D3DUSAGE_WRITEONLY, // Используем буфер только для чтения D3DFMT_INDEX16, // Формат индексов (для short - D3DFMT_INDEX16 // для DWORD - D3DFMT_INDEX32) D3DPOOL_MANAGED, // DirectX сам управляет пересозданием буфера &MyIndexBuffer, // Наш указатель на буфер NULL // Оставим NULL ) ) ); return false;
А теперь надо их заполнить :)) Сначала вершины:
// Вершины для кубика
MyVertex v[] =
{
{ -1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 255, 0, 0), },
{ -1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB( 0, 255, 0), },
{ 1.0f, -1.0f, -1.0f, D3DCOLOR_XRGB( 0, 0, 255), },
{ 1.0f, 1.0f, -1.0f, D3DCOLOR_XRGB( 255, 255, 0), },
{ 1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB( 255, 0, 255), },
{ 1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB( 0, 255, 255), },
{ -1.0f, -1.0f, 1.0f, D3DCOLOR_XRGB( 0, 0, 0), },
{ -1.0f, 1.0f, 1.0f, D3DCOLOR_XRGB( 255, 255, 255), }
};
void * pBuf;
// заполненяем вершинный буфер
MyVertexBuffer->Lock( 0, 8 * sizeof(MyVertex), &pBuf, 0 );
memcpy( pBuf, v, 8 * sizeof(MyVertex));
MyVertexBuffer->Unlock();
Теперь индексы:
// Индексы для кубика
short inds[36] =
{
0, 1, 2,
2, 1, 3,
2, 3, 4,
4, 3, 5,
4, 5, 6,
6, 5, 7,
6, 7, 0,
0, 7, 1,
1, 7, 3,
3, 7, 5,
0, 2, 6,
2, 4, 6};
// заполненяем индексный буфер
MyIndexBuffer->Lock( 0, 36 * sizeof(short), &pBuf, 0 );
memcpy( pBuf, inds, 36 * sizeof(short));
MyIndexBuffer->Unlock();
По умолчанию Direct3D не рисует задние стороны полигонов, поэтому на всякий пожарный мы отключим эту функцию (cull). У нас не ни одной лампочки на сцене (пока...), и поэтому отключим освещение, иначе все будет темно (???). И напоследок включаем буфер глубины (Z-буфер), чтобы наш кубик правильно отображался. Потом просчитываем проекционную матрицу. Все это происходит в функции ReInit. Добавляем ее сюда:
ReInit(); return true; }
Переходим к процедуре рисования. Чтобы отрисовать наш кубик мы должны:
1. Устанавливить вершинный буфер. Делается это функцией SetStreamSource( 0, MyVertexBuffer, 0, sizeof(MyVertex) );
2. Устанавливить индексный буфер: SetIndices(MyIndexBuffer);
3. Установить формат вершин: SetFVF( MyVertex_FVF );
4. Произвести отрисовку примитива: DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
Теперь функция отрисовки у нас будет выглядеть так:
VOID Render()
{
HRESULT hr;
// Проверяем Direct3dDevice на потерянность
hr = g_pd3dDevice->TestCooperativeLevel();
// если окно не в фокусе выходим из цикла рендеринга
if(hr==D3DERR_DEVICELOST)
return;
// если окно опять в фокусе пытаемся восстановить устройство рендеринга
if(hr==D3DERR_DEVICENOTRESET)
{
Cleanup();
g_pd3dDevice->Reset(&d3dpp); // если окно опять в фокусе пытаемся
// восстановить наш g_pd3dDevice
if( g_pd3dDevice )
ReInit();
}
if( NULL == g_pd3dDevice )
return;
// Начинаем отрисовку нашей сцены
if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
{
// Очищаем задний буфер и буфер глубины
g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(rand()%255, rand()%255, rand()%255), 1.0f, 0L);
//--------------------------//
// Здесь мы будем рисовать! //
//--------------------------//
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
//D3DXMatrixRotationZ(&matWorld, GetTickCount()/1024.0f);
D3DXMatrixRotationYawPitchRoll( &matWorld,
GetTickCount()/1024.0f,
GetTickCount()/2048.0f,
GetTickCount()/2048.0f );
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3(4.0f, 4.0f, 4.0f), // Точка из которой мы смотрим
// Место положения камеры
&D3DXVECTOR3(0.0f, 0.0f, 0.0f), // Точка в которую смотрим
&D3DXVECTOR3(0.0f, 1.0f, 0.0f)); // Где верх?
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
// Устанавливаем вершинный и индексный буфера
g_pd3dDevice->SetStreamSource( 0, MyVertexBuffer, 0, sizeof(MyVertex) );
g_pd3dDevice->SetIndices(MyIndexBuffer);
// устанавливаем формат вершин
g_pd3dDevice->SetFVF( MyVertex_FVF );
// Производим отрисовку
g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
g_pd3dDevice->EndScene(); // Закончили рисовать
g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); // Отображаем задний буфер
}
}
Перед завершением программы нам остается только освободить память из под буферов: переходим в функцию
AllShutdown() и добавляем: SAFE_RELEASE(MyVertexBuffer); SAFE_RELEASE(MyIndexBuffer);
Теперь она выглядит у нас так:
void AllShutdown()
{
Cleanup();
SAFE_RELEASE(MyVertexBuffer);
SAFE_RELEASE(MyIndexBuffer);
SAFE_RELEASE(g_pd3dDevice);
SAFE_RELEASE(g_pD3D);
}
На этом статья заканчивается, и теперь у вас есть возможность пофантазировать...
комментарии отсутствуют
авторизуйтесь