Indexed Primitive Rendering problem

Started by
4 comments, last by BlackGhost 20 years, 6 months ago
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]
Advertisement
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]
TechleadEnilno, the Ultima 2 projectwww.dr-code.org/enilno
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]
When setting up indices, I believe:

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

.. should be:

for (int y = 0; y < mapHeight - 2; y++)
Btw, i'm doing something similar; this is my code for generating a single trianglestrip for the entire patch:

gridsize = 33;  // or whatevernumSquares = gridsize - 1;primitiveType = PrimitiveType.TriangleStrip;numIndices = (gridsize * 2 * numSquares);numIndices += (numSquares-1);numFaces = numSquares * numSquares * 2;	// "regular" terrain trisnumFaces += ((numSquares-1) * 3);			// connecting turnindexBuffer = 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]
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.

This topic is closed to new replies.

Advertisement