Sign in to follow this  
lighting

Direct3D bug

Recommended Posts

Hi Anyone know why the following code works when I set d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 16, 0, 8); i.e. draw top, front, bottom and back of cube. But not when I run it as follows (to draw all of the cube) d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12); Note: this is taken from http://www.directxtutorial.com/Tutorial9/B-Direct3DBasics/dx9B9.aspx#still and is not my code. So I'm wondering, why doesn't it work? // include the basic windows header files and the Direct3D header file #include <windows.h> #include <windowsx.h> #include <d3d9.h> #include <d3dx9.h> // define the screen resolution and keyboard macros #define SCREEN_WIDTH 800 #define SCREEN_HEIGHT 600 #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) // include the Direct3D Library files #pragma comment (lib, "d3d9.lib") #pragma comment (lib, "d3dx9.lib") // global declarations LPDIRECT3D9 d3d; LPDIRECT3DDEVICE9 d3ddev; LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL; LPDIRECT3DINDEXBUFFER9 i_buffer = NULL; // function prototypes void initD3D(HWND hWnd); void render_frame(void); void cleanD3D(void); void init_graphics(void); void init_light(void); // sets up the light and the material struct CUSTOMVERTEX {FLOAT X, Y, Z; D3DVECTOR NORMAL;}; #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL) // the WindowProc function prototype LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // the entry point for any Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = L"WindowClass"; RegisterClassEx(&wc); hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our Direct3D Program", WS_OVERLAPPEDWINDOW, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); // set up and initialize Direct3D initD3D(hWnd); // enter the main loop: MSG msg; while(TRUE) { while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if(msg.message == WM_QUIT) break; render_frame(); if(KEY_DOWN(VK_ESCAPE)) PostMessage(hWnd, WM_DESTROY, 0, 0); } // clean up DirectX and COM cleanD3D(); return msg.wParam; } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: { PostQuitMessage(0); return 0; } break; } return DefWindowProc (hWnd, message, wParam, lParam); } // this function initializes and prepares Direct3D for use void initD3D(HWND hWnd) { d3d = Direct3DCreate9(D3D_SDK_VERSION); D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hWnd; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dpp.BackBufferWidth = SCREEN_WIDTH; d3dpp.BackBufferHeight = SCREEN_HEIGHT; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // create a device class using this information and the info from the d3dpp stuct d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); init_graphics(); // call the function to initialize the cube init_light(); // call the function to initialize the light and material d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE); // turn on the 3D lighting d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer d3ddev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); // ambient light } // this is the function used to render a single frame void render_frame(void) { d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3ddev->BeginScene(); // select which vertex format we are using d3ddev->SetFVF(CUSTOMFVF); // set the view transform D3DXMATRIX matView; D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3 (0.0f, 8.0f, 25.0f), // the camera position &D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // the look-at position &D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the projection transform D3DXMATRIX matProjection; D3DXMatrixPerspectiveFovLH(&matProjection, D3DXToRadian(45), (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, 1.0f, // the near view-plane 100.0f); // the far view-plane d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the world transform static float index = 0.0f; index+=0.03f; D3DXMATRIX matRotateY; D3DXMatrixRotationY(&matRotateY, index); d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY)); // select the vertex and index buffers to use d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX)); d3ddev->SetIndices(i_buffer); // draw the cube d3ddev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12); d3ddev->EndScene(); d3ddev->Present(NULL, NULL, NULL, NULL); } // this is the function that cleans up Direct3D and COM void cleanD3D(void) { v_buffer->Release(); i_buffer->Release(); d3ddev->Release(); d3d->Release(); } // this is the function that puts the 3D models into video RAM void init_graphics(void) { // create the vertices using the CUSTOMVERTEX struct CUSTOMVERTEX vertices[] = { { -3.0f, -3.0f, 3.0f, 0.0f, 0.0f, 1.0f, }, // side 1 { 3.0f, -3.0f, 3.0f, 0.0f, 0.0f, 1.0f, }, { -3.0f, 3.0f, 3.0f, 0.0f, 0.0f, 1.0f, }, { 3.0f, 3.0f, 3.0f, 0.0f, 0.0f, 1.0f, }, { -3.0f, -3.0f, -3.0f, 0.0f, 0.0f, -1.0f, }, // side 2 { -3.0f, 3.0f, -3.0f, 0.0f, 0.0f, -1.0f, }, { 3.0f, -3.0f, -3.0f, 0.0f, 0.0f, -1.0f, }, { 3.0f, 3.0f, -3.0f, 0.0f, 0.0f, -1.0f, }, { -3.0f, 3.0f, -3.0f, 0.0f, 1.0f, 0.0f, }, // side 3 { -3.0f, 3.0f, 3.0f, 0.0f, 1.0f, 0.0f, }, { 3.0f, 3.0f, -3.0f, 0.0f, 1.0f, 0.0f, }, { 3.0f, 3.0f, 3.0f, 0.0f, 1.0f, 0.0f, }, { -3.0f, -3.0f, -3.0f, 0.0f, -1.0f, 0.0f, }, // side 4 { 3.0f, -3.0f, -3.0f, 0.0f, -1.0f, 0.0f, }, { -3.0f, -3.0f, 3.0f, 0.0f, -1.0f, 0.0f, }, { 3.0f, -3.0f, 3.0f, 0.0f, -1.0f, 0.0f, }, { 3.0f, -3.0f, -3.0f, 1.0f, 0.0f, 0.0f, }, // side 5 { 3.0f, 3.0f, -3.0f, 1.0f, 0.0f, 0.0f, }, { 3.0f, -3.0f, 3.0f, 1.0f, 0.0f, 0.0f, }, { 3.0f, 3.0f, 3.0f, 1.0f, 0.0f, 0.0f, }, { -3.0f, -3.0f, -3.0f, -1.0f, 0.0f, 0.0f, }, // side 6 { -3.0f, -3.0f, 3.0f, -1.0f, 0.0f, 0.0f, }, { -3.0f, 3.0f, -3.0f, -1.0f, 0.0f, 0.0f, }, { -3.0f, 3.0f, 3.0f, -1.0f, 0.0f, 0.0f, }, }; // create a vertex buffer interface called v_buffer d3ddev->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX), 0, CUSTOMFVF, D3DPOOL_MANAGED, &v_buffer, NULL); VOID* pVoid; // a void pointer // lock v_buffer and load the vertices into it v_buffer->Lock(0, 0, (void**)&pVoid, 0); memcpy(pVoid, vertices, sizeof(vertices)); v_buffer->Unlock(); // create the indices using an int array int indices[] = { 0, 1, 2, // side 1 2, 1, 3, 4, 5, 6, // side 2 6, 5, 7, 8, 9, 10, // side 3 10, 9, 11, 12, 13, 14, // side 4 14, 13, 15, 16, 17, 18, // side 5 18, 17, 19, 20, 21, 22, // side 6 22, 21, 23, }; // create an index buffer interface called i_buffer d3ddev->CreateIndexBuffer(36*sizeof(int), 0, D3DFMT_INDEX32, D3DPOOL_MANAGED, &i_buffer, NULL); // lock i_buffer and load the indices into it i_buffer->Lock(0, 0, (void**)&pVoid, 0); memcpy(pVoid, indices, sizeof(indices)); i_buffer->Unlock(); } // this is the function that sets up the lights and materials void init_light(void) { D3DLIGHT9 light; // create the light struct D3DMATERIAL9 material; // create the material struct ZeroMemory(&light, sizeof(light)); // clear out the light struct for use light.Type = D3DLIGHT_DIRECTIONAL; // make the light type 'directional light' light.Diffuse = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f); // set the light's color light.Direction = D3DXVECTOR3(-1.0f, -0.3f, -1.0f); d3ddev->SetLight(0, &light); // send the light struct properties to light #0 d3ddev->LightEnable(0, TRUE); // turn on light #0 ZeroMemory(&material, sizeof(D3DMATERIAL9)); // clear out the struct for use material.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // set diffuse color to white material.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); // set ambient color to white d3ddev->SetMaterial(&material); // set the globably-used material to &material }

Share this post


Link to post
Share on other sites
There's a fairly large number of problems with that code, ranging from things that work but aren't guaranteed too (Relying on undefined behaviour), to things that will just crash outright if run on some hardware. That particular site is a terrible site to learn from; the articles might be easy to understand, but the code is just plain wrong. I've posted several times on these forums pointing out bugs in the directxtutorial source code, no doubt google will bring a few of them up.

For the actual bug, what do you mean it "doesn't work"? Does it not draw anything? Does it crash? Anything from the Debug Runtimes?

Share this post


Link to post
Share on other sites
So when it works it draws a partial cube with missing sides, rotating and lit up.
When I change it (as previously defined) to draw the whole cube, it crashes on startup.

Stepping through code it appears to crash on the first call of
d3ddev->Present(NULL, NULL, NULL, NULL);
So I'm guessing nothing is drawn.

Yeah - I'm really not getting a good vibe from that site.
It looks like a nice bare bones tutorial, but I really don't feel in control of my code. Not great.
Any advice would be very much appreciated.

So-I'm a good programmer, and am learning 3d as a hobby. Not massively into it, just wanted to give it a try.

Share this post


Link to post
Share on other sites
Quote:
Original post by lighting
I'm a good programmer


I know that I know nothing. Personally, I can't decide if I am a good programmer or not, because I don't know what I don't know yet.

Share this post


Link to post
Share on other sites
Quote:
Original post by lighting
When I change it (as previously defined) to draw the whole cube, it crashes on startup.

Stepping through code it appears to crash on the first call of
d3ddev->Present(NULL, NULL, NULL, NULL);
So I'm guessing nothing is drawn.
I'm going to guess that your device pointer is NULL. One of my main gripes with that site is that it doesn't teach you to check any of your return values. If CreateDevice() fails, then your device pointer will be NULL and you'll get a crash on that line (Or any other line that accesses your device pointer).

The debug runtimes (See the link in my previous post) will give you an error message if CreateDevice or any other function fails, which will help you track down the cause.

I've written a few articles of my own, which may be of interest to you.
Tutorial 1
Tutorial 2
Tutorial 3
Tutorial 4
Tutorial 5

Cheers,
Steve

Share this post


Link to post
Share on other sites
Quote:
Original post by marius1930
How do you suppose you'll create a cube out of 24 indices?

6 sides, 2 triangles per side, 3 vertices per triangle.
6 sides * 2 triangles = 12 indices
12 indices * 3 per triangle = 36
The 24 refers to the number of vertices used - which is 4 per face, 6 faces = 24. The number of indices is implicit given the primitive type and count.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this