Archived

This topic is now archived and is closed to further replies.

BlackGhost

Indexed Primitive Rendering problem

Recommended Posts

I generally feel bad posting source code and inviting other people to check it (I admit I don't check other's code in forums), but this problem has me completely stuck. So, if you've got nothing better to do, if you could find what's wrong with this code would be appreciated . It's from a program that tries to setup a basic ground mesh, so I use a 2 dimensional array of floats as a height map and setup the index and vertex buffer, so that I can render it as a list of triangles. The problem is that DirectX shows an error (InvalidCallException) when the DrawIndexedPrimitives() function is called. As far as I can say after some debugging, both the index and vertex buffer contain the expected values before the DrawIndexedPrimitives() call. If you could see what's going wrong (maybe I don't calculate the number of triangles correctly?), please open my eyes before they get burned from debugging sessions I include the functions that setup the vertex and index buffers, as well as the rendering part. The code is in C# but I doubt anyone who knows DirectX from C++ will have any trouble understanding what it's doing. Thanks for any help.
public void InitializeTerrain(int mapWidth, int mapHeight)
		{

			numTerrainPoints = mapWidth * mapHeight;
			numTerrainTriangles = (mapWidth - 1) * (mapHeight - 1) * 2;

			Random rand = new Random(Environment.TickCount);
			heightMap = new float[mapWidth, mapHeight];

			terrainBuffer = new VertexBuffer(typeof(CustomVertex.PositionColored),
				numTerrainPoints, dev, 0, CustomVertex.PositionColored.Format, Pool.Default);
			
			CustomVertex.PositionColored[] groundPoints = (CustomVertex.PositionColored[])terrainBuffer.Lock(0, 0);
			
			for (int y = 0; y < mapHeight; y++)
			{
				for (int x = 0; x < mapWidth; x++)
				{
					float height = (float)(rand.NextDouble() * 0.1);
					heightMap[x, y] = height;

					int currentVertexIndex = x + y*mapWidth;
					groundPoints[currentVertexIndex].X = 0.1f * x;
					groundPoints[currentVertexIndex].Z = 0.1f * y;
					groundPoints[currentVertexIndex].Y = height;

					int c = (int)(height * 2550);
					groundPoints[x + y*mapWidth].Color = Color.FromArgb(c, c, c).ToArgb();
				}
			}
			terrainBuffer.Unlock();

			terrainIndexes = new IndexBuffer(typeof(int), numTerrainTriangles * 3, dev,
						0, Pool.Default);

			int[] groundIndices = (int[])terrainIndexes.Lock(0, 0);

			int n = 0;
			for (int y = 0; y < mapHeight - 1; y++)
			{
				for (int x = 0; x < mapWidth - 1; x++)
				{					
					groundIndices[n] = x + (y*mapWidth);
					groundIndices[n + 1] = x + (y+1)*mapWidth;
					groundIndices[n + 2] = (x + 1) + (y*mapWidth);
					groundIndices[n + 3] = (x + 1) + (y*mapWidth);
					groundIndices[n + 4] = x + (y+1)*mapWidth;
					groundIndices[n + 5] = (x + 1) + (y + 1)*mapWidth;
					for (int k = 0; k < 5; k ++)
						Assert(groundIndices[k + n] <= mapWidth * mapHeight);

					n += 6;
				}
			}

			terrainIndexes.Unlock();
		}






public void Render()
		{
			if (dev == null) return;

			dev.Clear(ClearFlags.Target, Color.Black, 1.0f, 1);

			dev.RenderState.CullMode = Cull.None;
			dev.RenderState.ShadeMode = ShadeMode.Gouraud;
			//dev.RenderState.FillMode = FillMode.WireFrame;

			SetupMatrices();
			dev.Lights[0].Enabled = true;
			dev.Lights[0].Ambient = Color.FromArgb(100, 100, 100);
			dev.Lights[0].Commit();

			dev.Lights[1].Enabled = true;
			dev.Lights[1].Diffuse = Color.Red;
			dev.Lights[1].Direction = new Vector3(0.0f, 1.0f, 1.0f);
			dev.Lights[1].Commit();
			

			dev.BeginScene();

			// Render terrain

			if (terrainBuffer != null)
			{
				dev.SetStreamSource(0, terrainBuffer, 0, 
					DXHelp.GetTypeSize(typeof(CustomVertex.PositionColored)));

				dev.Indices = terrainIndexes;

				//int[] groundIndices = (int[])terrainIndexes.Lock(0, 0);


				dev.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
					numTerrainPoints, 0, numTerrainTriangles);
			}

			dev.EndScene();
			dev.Present();
		}

  
[edited by - blackghost on October 9, 2003 11:59:27 AM]

Share this post


Link to post
Share on other sites
Judging from the way you setup your verts, this should work for your index buffer.




int startvert = ((y*mapWidth) + x);

// triangle 1
groundIndices[n++] = startvert;

groundIndices[n++] = startvert+1;

groundIndices[n++] = startvert+mapWidth;

// triangle 2
groundIndices[n++] = startvert+1;

groundIndices[n++] = startvert+mapWidth+1;

groundIndices[n++] = startvert+mapWidth;




EDIT: groundIndices should be WORD not DWORD.

[edited by - RhoneRanger on October 9, 2003 1:05:42 PM]

Share this post


Link to post
Share on other sites
any updates on this, BlackGhost?

don't you have to set the vertexformat on the device?
dev.VertexFormat = CustomVertex.PositionColored.Format;

what about the lights? they seem not to be fully initialised, e.g. type, position etc.

I don't know what the DXHelp is, but maybe it gives the incorrect size of the CustomVertex.

it seems like it should work, the indices seems correctly calculated but maybe the terrain algorithm isn't the best HE HE

hope you fix it please say how if you did!



[edited by - apanjocko on October 15, 2003 7:14:13 AM]

Share this post


Link to post
Share on other sites
When setting up indices, I believe:

for (int y = 0; y < mapHeight - 1; y++)

.. should be:

for (int y = 0; y < mapHeight - 2; y++)

Share this post


Link to post
Share on other sites
Btw, i'm doing something similar; this is my code for generating a single trianglestrip for the entire patch:


gridsize = 33; // or whatever

numSquares = gridsize - 1;

primitiveType = PrimitiveType.TriangleStrip;

numIndices = (gridsize * 2 * numSquares);
numIndices += (numSquares-1);

numFaces = numSquares * numSquares * 2; // "regular" terrain tris

numFaces += ((numSquares-1) * 3); // connecting turn


indexBuffer = new IndexBuffer(typeof(ushort), numIndices, device, Usage.WriteOnly, Pool.Default);
ushort[] bufptr = (ushort[])indexBuffer.Lock(0, LockFlags.None);

int idxptr = 0;

for(int y=0;y<numSquares;) {
if (y != 0)
bufptr[idxptr++] = (ushort)(y * gridsize + 0);
y++;

// left to right strip

for(int x=0;x<gridsize;x++) {
bufptr[idxptr++] = (ushort)((y-1) * gridsize + x); // GetIndex(x, y-1);

bufptr[idxptr++] = (ushort)(y * gridsize + x); // GetIndex(x, y);

}

// connecting turn

bufptr[idxptr++] = (ushort)(y * gridsize + numSquares);
y++;

// right to left strip

for(int x=gridsize-1;x>=0;x--) {
bufptr[idxptr++] = (ushort)((y-1) * gridsize + x); // GetIndex(x, y-1);

bufptr[idxptr++] = (ushort)(y * gridsize + x); // GetIndex(x, y);

}
}



[edited by - fenghus on October 15, 2003 9:36:27 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by fenghus
When setting up indices, I believe:

for (int y = 0; y < mapHeight - 1; y++)

.. should be:

for (int y = 0; y < mapHeight - 2; y++)



i doubt it, as -1 already specifies to not iterate the last row.

Share this post


Link to post
Share on other sites