XNA Creators Club Online
Page 1 of 1 (6 items)
Sort Posts: Previous Next

terrain problem

Last post 5/1/2009 4:54 PM by LicenseToBill. 5 replies.
  • 5/1/2009 1:46 PM

    terrain problem

    I'm trying to add functionality to my program to create and draw terrain, Flat terrain would do for the time being. The error I get is in the draw function on the line that says "pass.begin" but I'm afraid it is quite non descript. My code is shown below

    public void CreateTerrain(int widthOfWorld, int heightOfWorld, int cellsWide, int cellsHigh, string texture)
            {
                int numOfVertices = (cellsHigh + 1) * (cellsWide + 1);
                int numOfTriangles = (cellsWide * 2) * cellsHigh;
                triangleIndices = new int[numOfTriangles * 3];
                terrainVertices = new VertexPositionNormalTexture[numOfVertices];
                int count = 0;
                int worldZPosition = -100;
                for (int y = 0; y < (cellsHigh + 1); y++)
                {
                    int worldXPosition = -100;
                    for (int x = 0; x < (cellsWide + 1); x++)
                    {
                        terrainVertices[count].Position = new Vector3(worldXPosition, 0, worldZPosition);
                        terrainVertices[count].Normal = Vector3.Up;
                        terrainVertices[count].TextureCoordinate.X = (float)x / (cellsWide);
                        terrainVertices[count].TextureCoordinate.Y = (float)y / (cellsHigh);

                        count++;

                        // Advance in x
                        worldXPosition += 1;
                    }
                    // Advance in z
                    worldZPosition += 1;
                }
                vertexBuffer = new VertexBuffer(graphics.GraphicsDevice,
                                   VertexPositionNormalTexture.SizeInBytes * terrainVertices.Length,
                                   BufferUsage.WriteOnly);
                vertexBuffer.SetData(terrainVertices);

                indexBuffer = new IndexBuffer(graphics.GraphicsDevice, typeof(int),
                              triangleIndices.Length, BufferUsage.WriteOnly);

                indexBuffer.SetData(triangleIndices);
            }
                int index = 0;
                int startVertex = 0;
                for (int cellY = 0; cellY < cellsHigh; cellY++)
                {
                    for (int cellX = 0; cellX < cellsWide; cellX++)
                    {
                        triangleIndices[index] = startVertex + 0;
                        triangleIndices[index + 1] = startVertex + 1;
                        triangleIndices[index + 2] = startVertex + cellsWide + 1;

                        index += 3;

                        triangleIndices[index] = startVertex + 1;
                        triangleIndices[index + 1] = startVertex + cellsWide + 2;
                        triangleIndices[index + 2] = startVertex + cellsWide + 1;

                        index += 3;

                        startVertex++;
                    }
                    startVertex++;
                }

    public void drawTerrain()
            {
                graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionNormalTexture.VertexElements);
                BasicEffect newEffect = new BasicEffect(graphics.GraphicsDevice, new EffectPool());
                newEffect.Texture = myGame.Load<Texture2D>("terrain");
                newEffect.Projection = CWorld.instance.projection;
                newEffect.World = Matrix.Identity;
                newEffect.View = CCamera.instance.view;

                foreach (EffectPass pass in newEffect.CurrentTechnique.Passes)
                {
                    pass.Begin(); //An unexpected error has occured. InvalidOperationException was unhandled

                    graphics.GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, terrainVertices,
                        0, terrainVertices.Length, triangleIndices, 0, triangleIndices.Length / 3);

                    pass.End();
                }
                newEffect.End();
            }
    Any idea where I'm going wrong? The integer triangleIndices and VertexPositionNormalTexture terrainVertices are being calculated correctly, so as far as I know the problem must be in the draw function, am I setting up newEffect properly?
  • 5/1/2009 2:27 PM In reply to

    Re: terrain problem

    add below before the foreach statement

    newEffect.Begin();

    also move this statement:

    BasicEffect newEffect = new BasicEffect(graphics.GraphicsDevice, new EffectPool());

    into your CreateTerrain method - instantiating a new Effect every frame is both unnecessary and inefficient.


    also if you want to use the vertexBuffer and indexBuffer you have created then add this:

    graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);
    graphics.GraphicsDevice.Indices = IndexBuffer;

    and call DrawIndexedPrimitive..

    Game hobbyist hell-bent on coding a diabolical Matrix
  • 5/1/2009 3:32 PM In reply to

    Re: terrain problem

    Hi Craig, thanks for replying.

    I decided not to do away with the vertexBuffer and indexBuffer and draw using DrawUserIndexedPrimitives, I made the changed you suggested and now I have a 2D plane being drawn (success!) but it is not applying the texture I want, it is plain white. I realised my CreateTerrain function actually did nothing with the string passed to it as a name for the texture to load, so I removed it and the name of the texture is hard coded into the draw function )not ideal I know but It'll do for now). I'll show exactly how my code looks now, can you advise why the texture is not being applied?

    public void CreateTerrain(int widthOfWorld, int heightOfWorld, int cellsWide, int cellsHigh)
            {
                newEffect = new BasicEffect(graphics.GraphicsDevice, new EffectPool());
                int numOfVertices = (cellsHigh + 1) * (cellsWide + 1);
                int numOfTriangles = (cellsWide * 2) * cellsHigh;
                triangleIndices = new int[numOfTriangles * 3];
                terrainVertices = new VertexPositionNormalTexture[numOfVertices];
                int count = 0;
                int worldZPosition = -100;
                for (int y = 0; y < (cellsHigh + 1); y++)
                {
                    int worldXPosition = -100;
                    for (int x = 0; x < (cellsWide + 1); x++)
                    {
                        terrainVertices[count].Position = new Vector3(worldXPosition, 0, worldZPosition);
                        terrainVertices[count].Normal = Vector3.Up;
                        terrainVertices[count].TextureCoordinate.X = (float)x / (cellsWide);
                        terrainVertices[count].TextureCoordinate.Y = (float)y / (cellsHigh);

                        count++;

                        // Advance in x
                        worldXPosition += 1;
                    }
                    // Advance in z
                    worldZPosition += 1;
                }
                int index = 0;
                int startVertex = 0;
                for (int cellY = 0; cellY < cellsHigh; cellY++)
                {
                    for (int cellX = 0; cellX < cellsWide; cellX++)
                    {
                        triangleIndices[index] = startVertex + 0;
                        triangleIndices[index + 1] = startVertex + 1;
                        triangleIndices[index + 2] = startVertex + cellsWide + 1;

                        index += 3;

                        triangleIndices[index] = startVertex + 1;
                        triangleIndices[index + 1] = startVertex + cellsWide + 2;
                        triangleIndices[index + 2] = startVertex + cellsWide + 1;

                        index += 3;

                        startVertex++;
                    }
                    startVertex++;
                }
            }

    public void drawTerrain()
            {
                graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionNormalTexture.VertexElements);
                newEffect.Texture = myGame.Load<Texture2D>("terrain");
                newEffect.Projection = CCamera.instance.projection;
                newEffect.World = Matrix.Identity;
                newEffect.View = CCamera.instance.view;
                newEffect.Begin();
                foreach (EffectPass pass in newEffect.CurrentTechnique.Passes)
                {
                    pass.Begin();
                    {
                        graphics.GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, terrainVertices,
                            0, terrainVertices.Length, triangleIndices, 0, triangleIndices.Length / 3);
                    }
                    pass.End();
                }
                newEffect.End();
            }
    Again many thanks, your help is greatly appreciated.

  • 5/1/2009 3:41 PM In reply to

    Re: terrain problem

    sorry I meant i HAVE done away with the index and vertex buffers
  • 5/1/2009 3:44 PM In reply to

    Re: terrain problem

    You've set the Texture property on the effect ok, you just need to also set the TextureEnabled property to true.

    newEffect.TextureEnabled = true;


    might as well do these too.

    newEffect.VertexColorEnabled = false;

    graphics.GraphicsDevice.RenderState.DepthBufferEnable = true;
    graphics.GraphicsDevice.RenderState.AlphaTestEnable = false;
    graphics.GraphicsDevice.RenderState.AlphaBlendEnable = false;

    also move the new VertexDeclaration into the CreateTerrain method exactly like you did for the BasicEffect



    Game hobbyist hell-bent on coding a diabolical Matrix
  • 5/1/2009 4:54 PM In reply to

    Re: terrain problem

    Brilliant, all sorted thanks bud.
Page 1 of 1 (6 items) Previous Next