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); }
На этом статья заканчивается, и теперь у вас есть возможность пофантазировать...
комментарии отсутствуют
авторизуйтесь