Index buffers, drawindexedprimitive, etc . . .

Started by
12 comments, last by d000hg 18 years, 10 months ago
Hi, I am using C++ and Direct3D9. I have been trying to go from drawprimitive (with a vertex buffer) to draw indexed primitive (with a vertex and index buffer). My code worked with drawprimitive, but it seems that I can't get drawindexedprimitive to work. I have looked at code everywhere on how to implement an index buffer and drawindexedprimitive. My code is exactly like has been suggested, though it still does not work. 1)How do I test to see whether my graphics card supports draw indexed primitive and index buffers? Which members of the D3DCAPS9 caps structure to I test for? 2)Here is my code, in great detail. I hope someone can help me fix this. It crashes on the line drawindexedprimitive. ////VERTEX.cpp //Create the vertex buffer and index buffer

void CVertexManager::SetupVertices(void)
{		
	//create d3d9 vertex buffer
	HRESULT hr=g_pD3DDevice9->CreateVertexBuffer(sizeof(VERTEX)*10920,D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,g_dwFVF,D3DPOOL_SYSTEMMEM,&g_pVertexBuffer,NULL);
	g_Log<<"SetupVertices() Create Vertex Buffer: "<<DXGetErrorString9(hr)<<endl;

	//create d3d9 index buffer (size=2 triangles * 3 indicies * sizeof(word))
	hr=g_pD3DDevice9->CreateIndexBuffer(6*sizeof(WORD),D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&g_pIndexBuffer,NULL);
	g_Log<<"SetupVertices() Create Index Buffer: "<<DXGetErrorString9(hr)<<endl;

	//fill index buffer
	WORD *usIndices=NULL;
	g_pIndexBuffer->Lock(0,0,(void**)&usIndices,0);//lock index buffer
	usIndices[0]=0;//index buffer data
	usIndices[1]=1;
	usIndices[2]=3;
	usIndices[3]=3;
	usIndices[4]=1;
	usIndices[5]=2;

	g_pIndexBuffer->Unlock();//unlock index buffer

	//set index buffer
	g_pD3DDevice9->SetIndices(g_pIndexBuffer);
}

//Add four vertices to make up a textured rectangle with 2 primitives

void CVertexManager::AddSquare(RECT &recPos,const float &fZOrder,TILE &TilePos)
{	
	if(m_lstVertexList.empty()==true)
	{
		m_nPrimitiveCount=0;
		m_nVertexCount=0;
	}

	//vertices must be sort in order of Z value (0.0 close, 10.0 far). Z values closer to 10 are rendered first.
	//Use RECT coordinates to create vertices
	VERTEX vrtBottomLeft,vrtTopLeft,vrtTopRight,vrtBottomRight;
	vrtTopLeft.x=recPos.left;      vrtTopLeft.y=recPos.top;        vrtTopLeft.z=fZOrder;     vrtTopLeft.tu=TilePos.m_tuLeft;      vrtTopLeft.tv=TilePos.m_tvTop;
	vrtTopRight.x=recPos.right;    vrtTopRight.y=recPos.top;       vrtTopRight.z=fZOrder;    vrtTopRight.tu=TilePos.m_tuRight;    vrtTopRight.tv=TilePos.m_tvTop;
	vrtBottomLeft.x=recPos.left;   vrtBottomLeft.y=recPos.bottom;  vrtBottomLeft.z=fZOrder;  vrtBottomLeft.tu=TilePos.m_tuLeft;   vrtBottomLeft.tv=TilePos.m_TvBottom;
	vrtBottomRight.x=recPos.right; vrtBottomRight.y=recPos.bottom; vrtBottomRight.z=fZOrder; vrtBottomRight.tu=TilePos.m_tuRight; vrtBottomRight.tv=TilePos.m_TvBottom;

	//add six vertices to the list of vertices
	// v1-----v2   //0.0-----0.0 //tu=horizontal
	// |----/-|    //|     /  |  //tv=vertical
	// |---/--|    //|   /    |
	// |--/---|    //| /      |
	// v0-----v3   //0.0-----1.0
	m_lstVertexList.push_back(vrtBottomLeft);
	m_lstVertexList.push_back(vrtTopLeft);
	m_lstVertexList.push_back(vrtTopRight);
	m_lstVertexList.push_back(vrtBottomRight);

	//update how many primitives and vertices there are to render
	++m_nPrimitiveCount;++m_nPrimitiveCount;
	m_nVertexCount+=4;
}

//Fill the vertex buffer with all the vertices in the list

void CVertexManager::FillVertexBuffer(void)
{
	//sort vertices in order of z value
	sort(m_lstVertexList.begin(),m_lstVertexList.end());
	
	//fill vertex buffer
    void *vb_vertices;
    g_pVertexBuffer->Lock(0,0,&vb_vertices,0);
    memcpy(vb_vertices,&(m_lstVertexList[0]),m_lstVertexList.size()*sizeof(VERTEX));
    g_pVertexBuffer->Unlock();
	
	//clear list of vertices
	m_lstVertexList.clear();
}

////MAIN.cpp //app_load

//create vertex buffer and index buffer
VertexManager.SetupVertices();

//set the flexible vertex format and stream source
g_pD3DDevice9->SetFVF(g_dwFVF);
g_pD3DDevice9->SetStreamSource(0,g_pVertexBuffer,0,sizeof(VERTEX));

//note: code that loads textures and other things is not included here

//app_loop

g_pD3DDevice9->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,255,0),1.0f,0);

g_pD3DDevice9->BeginScene();

//code showing recSquare and tile related things are not inculded here
VertexManager.AddSquare(recSquare,1.0f,TextureManager.GetTile("Texture1","Tile1"));

VertexManager.FillVertexBuffer();

//crashes on this line
g_pD3DDevice9->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,VertexManager.GetVertexCount(),0,VertexManager.GetPrimitiveCount());

g_pD3DDevice9->EndScene();

g_pD3DDevice9->Present(NULL,NULL,NULL,NULL);

Anyone able to help???

HTML5, iOS and Android Game Development using Corona SDK and moai SDK

Advertisement
Quote:1)How do I test to see whether my graphics card supports draw indexed primitive and index buffers? Which members of the D3DCAPS9 caps structure to I test for?

All hardware and drivers will support index buffers. The only thing you need to check is the maximum number of primitives, and maybe (if you really need it) support for D3DFMT_INDEX32/32bit indexes. This can be done in the usual enumeration way.

Quote:2)Here is my code, in great detail. I hope someone can help me fix this. It crashes on the line drawindexedprimitive.

I have to admit, I didn't read any of your code. You almost certainly need to stick the debug runtime on and watch the output. This will tell you why it failed - both the erronous return code and a message explaining it.

I spent quite a lot of time this afternoon writing up a wiki entry for NeXe titled Debugging. Follow it through if it's new to you, it will give you answers[attention]

If you don't understand the debug output, quote that back in this thread and we can help you further [smile]

Sorry to be a pain about the second question - but you'll learn to love the debug runtimes [grin]

Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Just had a peek at the MSDN for you...

D3DCAPS9 has a couple of properties you want to check: D3DCAPS9::MaxPrimitiveCount and D3DCAPS9::MaxVertexIndex.

For enumeration of 16/32 index buffers look into IDirect3D9::CheckDeviceFormat( ).

if( FAILED( CheckDeviceFormat(                 D3DADAPTER_DEFAULT,                 D3DDEVTYPE_HAL,                 ??,                 D3DUSAGE_DYNAMIC,                 D3DRTYPE_INDEXBUFFER,                 D3DFMT_INDEX32 ) ) )    {        //No support for 32bit index buffers, test for 16bit ones instead..?    }


hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

When I run my app, it crashes at the drawindexedprimitive line. DebugView spits out this:
[1056] Direct3D9: (ERROR) :No valid index stream currently set. DrawIndexedPrimitive failed.

Although I am sure my stream source is being set, etc. I just think my graphics card can't do drawindexedprimitive.


I tried checking to see if my GeForce2 MX400 32MB graphics card could do index buffers, drawindexedprimitive, etc.

HRESULT hrhr=g_pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_A8R8G8B8,D3DUSAGE_DYNAMIC,D3DRTYPE_INDEXBUFFER,D3DFMT_INDEX16);	g_Log<<"Error for Checking whether index buffer works: "<<DXGetErrorString9(hrhr)<<endl;

I get D3DERR_NOTAVAILABLE, so I think my graphics card can't do drawindexedprimitive, which is probably why I am having trouble.

HTML5, iOS and Android Game Development using Corona SDK and moai SDK

If it turns out that it is indeed the case that your current development system does not support something as integral as IBs - I would strongly suggest that you upgrade - if you possibly can. Assuming your reason for coding graphics is a learning experience, you are severely stunting your possible experience in this way...
-Scoot
When you call CheckDeviceFormat() you use D3DUSAGE_DYNAMIC as a usage flag - you don't actually create your index buffer with that dynamic flag so that shouldn't be a problem for you.

If your code actually failed to create the index buffer - which it would do if your graphics card didn't support them (which I find unlikely on the GF2, even an MX), then you'd know because of this line:

g_Log<<"SetupVertices() Create Index Buffer: "<<DXGetErrorString9(hr)<<endl;

Check your log to see if those calls actually succeed etc.

You might want to try and make another call to SetIndices() in your main loop. Maybe something is nullifying it without you noticing?

-Mezz
Ok, my index buffer was created succesfully, and the indicies have been set successfully. This has how it has always been.

I added another:
g_pD3DDevice9->SetIndices(g_pIndexBuffer);

before the drawindexedprimitive line in the main loop. Now it works. It draws a texture to the screen. However if I try to draw another square from the same texture, the second square is not drawn.

To sort this out I'll need a few questions answered:
1)After calling drawindexedprimitive does the index buffer empty? How can I make it empty?

2)What advantage is there to having a dynamic index buffer?

3)Should I make my index buffer so that it can hold enough indexes for every vertex that is going to be in the vertex buffer?

4)If I have a vector list of vertices and a vector list of indicies and I sort the verticies, will the indicies be in the wrong order and point to the wrong vertices?

[Edited by - utilae on May 25, 2005 10:11:46 PM]

HTML5, iOS and Android Game Development using Corona SDK and moai SDK

Quote:Original post by utilae
1)After calling drawindexedprimitive does the index buffer empty? How can I make it empty?

No, they're not emptied. An index buffer can't be emptied - it has a certain size. It always contains a number of indices. If you want to modify the indices, lock it and do so.

Quote:2)What advantage is there to having a dynamic index buffer?

As with dynamic vertex buffers, they should be faster to use with frequent updates.

Quote:3)Should I make my index buffer so that it can hold enough indexes for every vertex that is going to be in the vertex buffer?

Its range should cover the number of vertices. With 16 bit index buffers, you have 65536 vertices, [0, 65535] per DIP call. You can get around this using BaseVertexIndex. With BaseVertexIndex set to 4000, for example, you can now access [4000, 65935] in a single call.

Quote:4)If I have a vector list of vertices and a vector list of indicies and I sort the verticies, will the indicies be in the wrong order and point to the wrong vertices?

Yes.

Quote:Original post by Coder
No, they're not emptied. An index buffer can't be emptied - it has a certain size. It always contains a number of indices. If you want to modify the indices, lock it and do so.

Hmmmm, I guess I'll have to empty it somehow, by overwriting it with new index data. How would I use memset to clear the index buffer, do I fill it with zeroes or some other character?

Quote:Original post by Coder
Quote:Original post by utilae
4)If I have a vector list of vertices and a vector list of indicies and I sort the verticies, will the indicies be in the wrong order and point to the wrong vertices?

Yes.

This is a big problem then. I wonder how I can make the indicies get sorted the same as the vertices. See if I sort the vertices by z value, indicies don't have a z value to sort by. I guess I can make a struct that contains the index and a z value, then sort the list of structs and then fill another list (of shorts) with the indicies (now sorted) and then memcpy the sorted indicies over the existing data in the index buffer.

HTML5, iOS and Android Game Development using Corona SDK and moai SDK

Quote:Original post by utilae
Hmmmm, I guess I'll have to empty it somehow, by overwriting it with new index data. How would I use memset to clear the index buffer, do I fill it with zeroes or some other character?

You don't need memset. Lock the index buffer, overwrite the old data with the new index data, and unlock it.

This topic is closed to new replies.

Advertisement