Проблема с отображением куба.
Должен по идее был отображаться куб с разноцветными гранями на зеленом фоне,а отображается только зеленый фон.
Вот функция рисования куба:
void DrawScene()
{
//Массив куба
const sVertex svVortexList[]={
//Грань 1
-0.5f, -0.5f, -0.5f, 0x00ff0000,
-0.5f, 0.5f, -0.5f, 0x00ff0000,
0.5f, -0.5f, -0.5f, 0x00ff0000,
0.5f, 0.5f, -0.5f, 0x00ff0000,
//Грань 2
0.5f, -0.5f, -0.5f, 0x0000ff00,
0.5f, 0.5f, -0.5f, 0x0000ff00,
0.5f, -0.5f, 0.5f, 0x0000ff00,
0.5f, 0.5f, 0.5f, 0x0000ff00,
//Грань 3
0.5f, -0.5f, 0.5f, 0x000000ff,
0.5f, 0.5f, 0.5f, 0x000000ff,
-0.5f, -0.5f, 0.5f, 0x000000ff,
-0.5f, 0.5f, 0.5f, 0x000000ff,
//Грань 4
-0.5f, -0.5f, 0.5f, 0x00ffff00,
-0.5f, 0.5f, 0.5f, 0x00ffff00,
-0.5f, -0.5f, -0.5f, 0x00ffff00,
-0.5f, 0.5f, -0.5f, 0x00ffff00,
//Грань 5
-0.5f, 0.5f, -0.5f, 0x0000ffff,
-0.5f, 0.5f, 0.5f, 0x0000ffff,
0.5f, 0.5f, -0.5f, 0x0000ffff,
0.5f, 0.5f, 0.5f, 0x0000ffff,
//Грань 6
0.5f, -0.5f, -0.5f, 0x00ff00ff,
0.5f, -0.5f, 0.5f, 0x00ff00ff,
-0.5f, -0.5f, -0.5f, 0x00ff00ff,
-0.5f, -0.5f, 0.5f, 0x00ff00ff,
};
//Создание буфера веришин
HRESULT hRes = pD3DDevice->CreateVertexBuffer(sizeof(sVertex)*
iVertsNum, 0 , D3DFVF_XYZ | D3DFVF_DIFFUSE,
D3DPOOL_DEFAULT, &vBuffer, 0);
if (FAILED(hRes))
return;
//Блокировка буфера вершин и заполнение
hRes = vBuffer->Lock(0,sizeof(sVertex)*iVertsNum,&pBuf,0);
if (FAILED(hRes))
return;
memcpy(pBuf,svVortexList,sizeof(sVertex)*iVertsNum);
vBuffer->Unlock();
//Массив индексов построения треугольника
const unsigned short Idxes[]={
0,1,2,2,1,3,
4,5,6,6,5,7,
8,9,10,10,9,11,
12,13,14,14,13,15,
16,17,18,18,17,19,
20,21,22,22,21,23,
};
//Создание буфера индексов
hRes = pD3DDevice->CreateIndexBuffer(sizeof(short)*iIdxNum,
D3DUSAGE_WRITEONLY, D3DFMT_INDEX16,D3DPOOL_DEFAULT,
&iBuffer,0);
if (FAILED(hRes))
return;
//Блокировка буфера индексов и заполнение
hRes = iBuffer->Lock(0,sizeof(short)*iIdxNum,&pBuf,0);
if (FAILED(hRes))
return;
memcpy(pBuf,Idxes,sizeof(short)*iIdxNum);
iBuffer->Unlock();
//Закрашивание экрана зеленым цветом
pD3DDevice->Clear(0,NULL,D3DCLEAR_TARGET,
D3DCOLOR_XRGB(0,255,0),1.0f,0);
pD3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
//Установка матрицы вида
D3DMATRIX View={
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,5,1,
};
pD3DDevice->SetTransform(D3DTS_VIEW,&View);
//Подготовка сцены в заднем буффере
pD3DDevice->BeginScene();
//Определение вершинного формата
pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
//Установка вершинного буфера
pD3DDevice->SetStreamSource(0,vBuffer,0,sizeof(sVertex));
//Установка индексеого буффера
pD3DDevice->SetIndices(iBuffer);
//Вывод объекта
pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
0,0,36,0,iPointsNum);
pD3DDevice->EndScene();
pD3DDevice->Present(NULL,NULL,0,NULL);
}
Что ж, начнём. :) Для начала выговор. Так вопросы не задают, у тебя тут половина переменных не объявлена (или не показано объявление). И если читатели твоего вопроса не знают книгу М. Фленова с которой взят код, они вряд ли ответят. Чудо, что у тебя этот код вообще запускается. Теперь совет. Если скачал книгу, а не приобрёл в бумажном виде, то постарайся найти к ней ещё и диск. А уж что касается Фленова и в частности этой книги, из которой взят код, то без диска дальнейшие примеры тебе разбирать будет очень сложно, потому что в книге не всё указано. Теперь по делу, что касается кода. Ты бы начал с чего попроще, потому что ты должен понимать всё что ты пишешь и для чего ты это пишешь. И вот когда ты начнёшь это понимать, ты перестанешь писать такой ужас. :) А ужас потому, что больше половины тут нужно было раскидать по функциям, а не скидывать в одну кучу. Часть функций ты будешь вызывать один раз при инициализации программы, а часть (Ту, в которой рендер происходит) - каждый кадр. В общем я не знаю, почему он у тебя не пошёл, у меня он в таком виде даже не скомпилился, поэтому выдаю тебе рабочий код этого примера. Заодно комменты немного накидаю.
// сначала идут объявления глобальных переменных, они у тебя скорее всего есть. IDirect3D9* и IDirect3D9Device*.
// вершинный буфер
IDirect3DVertexBuffer9 * vBuffer;
// индексный буфер
IDirect3DIndexBuffer9 * iBuffer;
// константы для куба
const int iVertsNum = 24;
const int iIdxNum = 36;
const int iPointsNum = 12;
// структура каждой вершины куба, в данном случае 3 координаты и цвет.
struct sVertex
{
float x, y, z;
DWORD color;
};
// Вот эту функцию вызывай один раз при инициализации программы, после D3DInit, которая после создания окна находится, найдёшь.
void CreateQuad()
{
const sVertex svVortexList[] = {
-0.5f, -0.5f, -0.5f, 0x00ff0000,
-0.5f, 0.5f, -0.5f, 0x00ff0000,
0.5f, -0.5f, -0.5f, 0x00ff0000,
0.5f, 0.5f, -0.5f, 0x00ff0000,
0.5f, -0.5f, -0.5f, 0x0000ff00,
0.5f, 0.5f, -0.5f, 0x0000ff00,
0.5f, -0.5f, 0.5f, 0x0000ff00,
0.5f, 0.5f, 0.5f, 0x0000ff00,
0.5f, -0.5f, 0.5f, 0x000000ff,
0.5f, 0.5f, 0.5f, 0x000000ff,
-0.5f, -0.5f, 0.5f, 0x000000ff,
-0.5f, 0.5f, 0.5f, 0x000000ff,
-0.5f, -0.5f, 0.5f, 0x00ffff00,
-0.5f, 0.5f, 0.5f, 0x00ffff00,
-0.5f, -0.5f, -0.5f, 0x00ffff00,
-0.5f, 0.5f, -0.5f, 0x00ffff00,
-0.5f, 0.5f, -0.5f, 0x0000ffff,
-0.5f, 0.5f, 0.5f, 0x0000ffff,
0.5f, 0.5f, -0.5f, 0x0000ffff,
0.5f, 0.5f, 0.5f, 0x0000ffff,
0.5f, -0.5f, -0.5f, 0x00ff00ff,
0.5f, -0.5f, 0.5f, 0x00ff00ff,
-0.5f, -0.5f, -0.5f, 0x00ff00ff,
-0.5f, -0.5f, 0.5f, 0x00ff00ff,
};
void * pBuf;
HRESULT hRes = pD3DDevice->CreateVertexBuffer(sizeof(sVertex) * iVertsNum,
D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DPOOL_DEFAULT, &vBuffer, 0);
if (FAILED(hRes))
return;
// заполнение вершинного буфера
hRes = vBuffer->Lock(0, sizeof(sVertex) * iVertsNum, &pBuf, 0);
if (FAILED(hRes))
return;
memcpy(pBuf, svVortexList, sizeof(sVertex) * iVertsNum);
vBuffer->Unlock();
const unsigned short Idxes[]={
0,1,2,2,1,3,
4,5,6,6,5,7,
8,9,10,10,9,11,
12,13,14,14,13,15,
16,17,18,18,17,19,
20,21,22,22,21,23,
};
// создание индексного буфера
hRes = pD3DDevice->CreateIndexBuffer( sizeof(short) * iIdxNum,
0, D3DFMT_INDEX16, D3DPOOL_DEFAULT,&iBuffer, 0);
if (FAILED(hRes))
return;
// заполнение индексного буфера
hRes = iBuffer->Lock(0, sizeof(short) * iIdxNum, &pBuf, 0);
if (FAILED(hRes))
return;
memcpy(pBuf, Idxes, sizeof(short) * iIdxNum);
iBuffer->Unlock();
}
// А вот эту функцию вызываешь между очисткой буфера и переключением буферов, например вот так
/*pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30,160,160), 1.0f, 0);
pD3DDevice->BeginScene();
DrawScene();
pD3DDevice->EndScene();
pD3DDevice->Present(NULL, NULL, 0, NULL);*/
void DrawScene()
{
ViewAngle+=0.01;
float b = ViewAngle;
D3DMATRIX World = {
cos(b)*cos(b), cos(b)*sin(b), sin(b), 0,
-sin(b), cos(b), 0, 0,
-sin(b)*cos(b), -sin(b)*sin(b), cos(b), 0,
0, 0, 0, 1,
};
pD3DDevice->SetTransform(D3DTS_WORLD, &World);
D3DMATRIX View = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 1, 5, 1,
};
pD3DDevice->SetTransform(D3DTS_VIEW, &View);
// вершинный формат
pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE);
// вершинный буфер
pD3DDevice->SetStreamSource(0, vBuffer, 0, sizeof(sVertex));
// индексный буфер
pD3DDevice->SetIndices(iBuffer);
// убери отсюда комментарий, чтобы куб был в виде треугольников
// pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
// вывод объекта
pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, iVertsNum, 0, iPointsNum);
}
Вот. Если у тебя нет очистки буфера и переключения буферов, напиши, куда-нибудь приделаем. :) В общем, разбирайся, если что, спрашивай.
Спасибо огромное за помощь :)
Но что-то у меня все-таки не получается:
1.Как описывать переменную ViewAngle....когда я описываю как float мне выводит предупреждение: '+=' : truncation from 'double' to 'float' ,а когда описываю как double выводит
'initializing' : conversion from 'double' to 'float', possible loss of data для каждого синуса и косинуса в матрице.
2.Очистки и переключения буферов вроде бы нету...
У меня подключение DirectX в функции BOOL InitInstance перед вызовом функции CreateQuard рисованием окна:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
if (DX3DInit( &pD3D, &pD3DDevice, hWnd, 800, 600, FALSE)!=S_OK)
{
MessageBox(hWnd, _T("Error when initing DirectX"),_T("Error"), MB_OK);
return FALSE;
}
CreateQuard();
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
А код
pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30,160,160), 1.0f, 0);
pD3DDevice->BeginScene();
DrawScene();
pD3DDevice->EndScene();
pD3DDevice->Present(NULL, NULL, 0, NULL);
я вставил в функцию LRESULT CALLBACK WndProc :
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30,160,160), 1.0f, 0);
pD3DDevice->BeginScene();
DrawScene();
pD3DDevice->EndScene();
pD3DDevice->Present(NULL, NULL, 0, NULL);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Я не уверен,там ли я вывод осуществляю.
В общем, у тебя как у Фленова в примерах. Для начала пойдёт. По поводу double и float особо не парься, так как эти матрицы вручную обычно не составляются, потому что в D3DX9 есть функции, которые сами составят готовые матрицы. Например чтобы составить матрицу вращения вокруг оси X, можно сделать так:
float f;
D3DMATRIX World = {
1, 0, 0, 0,
cos(f), -sin(f), 0, 0,
sin(f), cos(f),0, 0,
0, 0, 0, 1,
};
pD3DDevice->SetTransform(D3DTS_WORLD, &World);
А можно не париться с математикой и сделать так:
float f;
D3DXMATRIX World;
D3DXMatrixRotationX(&World, f);
pD3DDevice->SetTransform(D3DTS_WORLD, &World);
Функция сама заполнит матрицу, но для этого нужно подключить файл d3dx9.h и библиотеку d3dx9.lib.
Ну ладно, это отдельная тема.
По поводу остального. Функция называется CreateQuad, а не CreateQuard, хоть это роли и не играет для компилятора, но всё равно, лучше исправь опечатку. :)
Что же касается угла, то тут ситуация сложная. Раз уж ты пока составляешь матрицы вручную, пробуем прикинуть что мы тут имеем.
А имеем мы не очень прикольную картину. Функции sin и cos принимают и возвращают double, а вот D3DMATRIX принимает float., следовательно, как бы мы эти переменные не объявляли, один из них всегда будет недоволен типом данных. :) Единственный вариант, который я смог сделать, чтобы не было предупреждений такой:
double ViewAngle=0;
// выставляем матрицу для объекта в мировых координатах
ViewAngle+=0.01f;
double b = ViewAngle;
D3DMATRIX World = {
(float)cos(b)*(float)cos(b), (float)cos(b)*(float)sin(b), (float)sin(b), 0,
(float)-sin(b), (float)cos(b), 0, 0,
(float)-sin(b)*(float)cos(b), (float)-sin(b)*(float)sin(b), (float)cos(b), 0,
0, 0, 0, 1,
};
pD3DDevice->SetTransform(D3DTS_WORLD, &World);
То есть, передаём в функции double, а возвращаемый ей double явно приводим к float, везде, у всех функций. Предупреждений нет, но писать это всё не очень прикольно. Поспрашиваю народ, может кто ещё что подскажет. Но в целом, особо не обращай внимания, так как юзается это редко.
Ну и еще не мешало бы язык выучить на котором программишь :)
Это конечно тоже очень важно. :) Ну в принципе, программирование 3D-графики довольно неплохой повод для изучения языка. На практике лучше учить, чем в теории. :)
Спасибо огромное за помощь :)
С кубом я разобрался=)
Тема в архиве.