ПрограммированиеФорумГрафика

Проблема с отображением куба в DirectX SDK

#0
13:19, 26 авг 2009

Проблема с отображением куба.
Должен по идее был отображаться куб с разноцветными гранями на зеленом фоне,а отображается только зеленый фон.
Вот функция рисования куба:

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);
}

#1
14:05, 26 авг 2009

Что ж, начнём. :) Для начала выговор. Так вопросы не задают, у тебя тут половина переменных не объявлена (или не показано объявление). И если читатели твоего вопроса не знают книгу М. Фленова с которой взят код, они вряд ли ответят. Чудо, что у тебя этот код вообще запускается. Теперь совет. Если скачал книгу, а не приобрёл в бумажном виде, то постарайся найти к ней ещё и диск. А уж что касается Фленова и в частности этой книги, из которой взят код, то без диска дальнейшие примеры тебе разбирать будет очень сложно, потому что в книге не всё указано. Теперь по делу, что касается кода. Ты бы начал с чего попроще, потому что ты должен понимать всё что ты пишешь и для чего ты это пишешь. И вот когда ты начнёшь это понимать, ты перестанешь писать такой ужас. :) А ужас потому, что больше половины тут нужно было раскидать по функциям, а не скидывать в одну кучу. Часть функций ты будешь вызывать один раз при инициализации программы, а часть (Ту, в которой рендер происходит) - каждый кадр. В общем я не знаю, почему он у тебя не пошёл, у меня он в таком виде даже не скомпилился, поэтому выдаю тебе рабочий код этого примера. Заодно комменты немного накидаю.

// сначала идут объявления глобальных переменных, они у тебя скорее всего есть. 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);
}

Вот. Если у тебя нет очистки буфера и переключения буферов, напиши, куда-нибудь приделаем. :) В общем, разбирайся, если что, спрашивай.

#2
15:40, 26 авг 2009

Спасибо огромное за помощь :)
Но что-то у меня все-таки не получается:
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;
}
 


  Функция инициализации DirectX отдельным .сpp файлом.

  Я не уверен,там ли я вывод осуществляю.

#3
17:17, 26 авг 2009

В общем, у тебя как у Фленова в примерах. Для начала пойдёт. По поводу 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, везде, у всех функций. Предупреждений нет, но писать это всё не очень прикольно. Поспрашиваю народ, может кто ещё что подскажет. Но в целом, особо не обращай внимания, так как юзается это редко.

#4
17:35, 26 авг 2009

Ну и еще не мешало бы язык выучить на котором программишь :)

#5
17:41, 26 авг 2009

Это конечно тоже очень важно. :) Ну в принципе, программирование 3D-графики довольно неплохой повод для изучения языка. На практике лучше учить, чем в теории. :)

#6
19:22, 26 авг 2009

Спасибо огромное за помощь :)
С кубом я разобрался=)

ПрограммированиеФорумГрафика

Тема в архиве.