Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am working on a smooth terrain generation algorithm in C# and using XNA to display the data.

I am making it so it creates a new point halfway between each point per iteration, at a random height between the two. This works OK, and I am getting the current result, randomly placed points.

enter image description here

Now what I want to do is turn these points into a primitive (I think that is what it is) and display it like a mountain, obviously using a mountain texture. Example below (using different point data, made up in paint)

enter image description here

Any help or tips are greatly appreciated, and look forward to your responses.

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

In addition to Blau's answer you could also generate a VertexBuffer. What you would do is something like:

// Create the arrays to hold the data.
var vertices = new VertexPositionColorTexture[_points.Length * 2];
var indicies = new short[6 * (_points.Length - 1)];

for (var i = 0; i < _points.Length; i++)
{
    var pt = _points[i];

    // Calculate the texture coordinate along the horizontal plane.
    var u = (float)_points.Length / i;

    var vertexIndex = i * 2;
    // Create the vertex at the top of the landscape
    // that is at the current X co-ordinate.
    vertices[vertexIndex + 0] = new VertexPositionColorTexture(
            new Vector3(pt.X, pt.Y, 0),
            Color.White,
            new Vector2(u, 0)
        );
    // And the bottom.
    vertices[vertexIndex + 1] = new VertexPositionColorTexture(
            new Vector3(pt.X, _height, 0),
            Color.White,
            new Vector2(u, 1)
        );

    // Create indicies that will make two triangles that
    // fill the *right* of the current vertex.
    if (i < _points.Length - 1)
    {
        var indexIndex = i * 6;
        indicies[indexIndex + 0] = (short)(vertexIndex + 0); // Top left
        indicies[indexIndex + 1] = (short)(vertexIndex + 1); // Bottom left
        indicies[indexIndex + 2] = (short)(vertexIndex + 3); // Bottom right

        indicies[indexIndex + 3] = (short)(vertexIndex + 0); // Top left
        indicies[indexIndex + 4] = (short)(vertexIndex + 3); // Bottom right
        indicies[indexIndex + 5] = (short)(vertexIndex + 2); // Top right
    }
}

_vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColorTexture), vertices.Length, BufferUsage.WriteOnly);
_indexBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, indicies.Length, BufferUsage.WriteOnly);

_vertexBuffer.SetData(vertices, 0, vertices.Length);
_indexBuffer.SetData(indicies, 0, indicies.Length);

// To draw:
GraphicsDevice.Indices = _indexBuffer;
GraphicsDevice.SetVertexBuffer(_vertexBuffer);
_basicEffect.Texture = _myTexture; // Your texture
_basicEffect.World = _worldMatrix;
foreach (var item in _basicEffect.CurrentTechnique.Passes)
{
    item.Apply();
    GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _vertexBuffer.VertexCount, 0, _indexBuffer.IndexCount);
}

This should create a vertex buffer that looks like this:

Vertex Buffer Outcome

You should read up on BasicEffect if you want to learn how to set up textures during your rendering.

share|improve this answer
    
This is the way I am going to do this, it allows me to set textures of each point. Thanks. –  Twitchy Oct 31 '11 at 23:28
    
This works. Though I had to make a minor change. var indexIndex = i * 6; indicies[i + 0] = (short)(vertexIndex + 0); needs to be var indexIndex = i * 6; indicies[indexIndex + 0] = (short)(vertexIndex + 0); –  Twitchy Nov 1 '11 at 4:37
    
Thanks for the feedback @Twitchy - I updated the answer. –  Jonathan Dickinson Nov 1 '11 at 8:08
    
No worries @Jonathan Dickinson . Currently, I am only using VertexPositionColor as I do not know how to use a texture with it. Could you elaborate on this some more? –  Twitchy Nov 1 '11 at 8:20
    
@Twitchy added a link and updated the sample. I assume you already have it rendering - so all it comes down to is assigning the Texture property on your BasicEffect and making sure the texture coords are accurate (which mine should be). If you upload the barebones code somewhere I can look at it for you. –  Jonathan Dickinson Nov 1 '11 at 9:39
add comment

You can create a Texture2D this way.

        Texture2D Mountain = new Texture2D( GraphicsDevice, Width, Height);
        Color[] PixelData = new Color[Width * Height];

        Color colA,colB;
        float r;
        for ( int x=0; x < Width && x < YourHeights.Length; x++ )
        {
            for ( int y=YourHeights[x]; y < Height; y++ )
            {
                // This is for colorize relative to height 
                // You can change or apply other texture
                if (y<Height/3) {
                    colB = Color.IndianRed;
                    colA = Color.White;
                    r = 1.0f - y / (Height/3.0f);
                }
                else if (y<2*Height/3) {
                    colB = Color.Indigo;
                    colA = Color.IndianRed;
                    r = 1.0f - (y-Height/3.0f) / (Height/3.0f);
                } else {
                    colB = Color.RosyBrown;
                    colA = Color.Indigo;
                    r = 1.0f - (y-2*Height/3.0f) / (Height/3.0f);
                }

                PixelData[x + y * Width] = Color.Lerp( colB, colA, r );
            }
        }
        Mountain.SetData<Color>( PixelData );

Maybe you need to build more textures if your level is too long... or you can modify the texture scrolling it and adding new columns of pixels in the scroll side.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.