Heightmap to Mesh by MOGRE         A Mogre code snippet for generating a Mesh by a height map image

This is a code snippet for Mogre which you can use to generate a mesh by a grayscaled Height Map image.
It's useful to load a terrain as mesh and was done by user noferat.

This code is a modification of the snippet Generating A Mesh.


help For questions, feeback and bug reports use this forum topic.


Note:
If you have some artefacts, you should set the MaxMipLevel to 1.

Source code

void GenMesh()
{
    /// Create the mesh via the MeshManager
        MeshPtr msh = MeshManager.Singleton.CreateManual("Rive_", "General");
    float max = 0;
    /// Create one submesh
    SubMesh sub = msh.CreateSubMesh();
////////////Image in ArrayList, its grayscale heightmap
  Bitmap image = (Bitmap)arr[0]; 
            ////////////////////   
    int  nVertices = image.Width*image.Height;
    int vbufCount = 3*2*nVertices;
            //////generate triangles order
    ArrayList arra = new ArrayList();
    int jf = 0;
    int ibufCount = nVertices;             
                 for (int j = 0; j < image.Height-1; j++)
                     for (int i = 0; i < image.Width; i++)
                 {
                     if (i - 1 >= 0)
                     {
                         arra.Add(jf - 1);
                         arra.Add(jf);
                         arra.Add(image.Width + jf);
                       
                     }
                     if (i + 1 <= image.Width)
                     {
                         arra.Add(jf);
                         arra.Add(image.Width + 1 + jf);
                         arra.Add(image.Width + jf);                       
                     }
                     jf++;
                 }
            int iVerticles=arra.Count;
             uint[] face = new uint[arra.Count];
             for (int i = 0; i < iVerticles; i++) face[i] = (uint)(int)arra[i];
           
  ///////////
    float []vertices = new float[vbufCount];
    int temp=0;
            for(int i=0;i<image.Width;i++)
                for(int j=0;j<image.Height;j++)
                {
                    Vector3 vc=new Vector3(i,image.GetPixel(i,j).R,j);//R - height mesh, as grayscale, for example (255,255,255)- r,g,b - equal
                    Vector3 nc=vc.NormalisedCopy;
                    vertices[temp]=vc.x;
                    vertices[temp+1]=vc.y;
                    vertices[temp+2]=vc.z;
                    vertices[temp+3]=nc.x;
                    vertices[temp+4]=nc.y;
                    vertices[temp+5]=nc.z;
                    if (max < vc.y) max = vc.y;
                    temp+=6;
                }
            /////Vertex color
            uint[] color = new uint[nVertices];
            for (int i = 0; i < nVertices; i++) color[i] = 43534346;       

    /// Create vertex data structure for 8 vertices shared between submeshes
    msh.sharedVertexData = new VertexData();
    msh.sharedVertexData.vertexCount = (uint)nVertices;

    /// Create declaration (memory format) of vertex data
    VertexDeclaration decl = msh.sharedVertexData.vertexDeclaration;
    uint offset = 0;
    // 1st buffer
    decl.AddElement(0, offset, VertexElementType.VET_FLOAT3,VertexElementSemantic.VES_POSITION);
    offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3);
    decl.AddElement(0, offset,VertexElementType.VET_FLOAT3,VertexElementSemantic.VES_NORMAL);
    offset += VertexElement.GetTypeSize(VertexElementType.VET_FLOAT3);
    /// Allocate vertex buffer of the requested number of vertices (vertexCount)
    /// and bytes per vertex (offset)
    HardwareVertexBufferSharedPtr vbuf =
        HardwareBufferManager.Singleton.CreateVertexBuffer(
        offset, msh.sharedVertexData.vertexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY);
    /// Upload the vertex data to the card
            unsafe
            {                 
                fixed(void* vert=vertices) vbuf.WriteData(0, vbuf.SizeInBytes, vert, true); 
            }
   
    /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer
    VertexBufferBinding bind = msh.sharedVertexData.vertexBufferBinding;
    bind.SetBinding(0, vbuf);

    // 2nd buffer
    offset = 0;
    decl.AddElement(1, offset, VertexElementType.VET_COLOUR, VertexElementSemantic.VES_DIFFUSE);
    offset += VertexElement.GetTypeSize(VertexElementType.VET_COLOUR);
    ///// Allocate vertex buffer of the requested number of vertices (vertexCount)
    ///// and bytes per vertex (offset)
    vbuf = HardwareBufferManager.Singleton.CreateVertexBuffer(
        offset, msh.sharedVertexData.vertexCount, HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY);
    ///// Upload the vertex data to the card
    unsafe
    {
        fixed (void* vert = color) vbuf.WriteData(0, vbuf.SizeInBytes, vert, true);
    }

    ///// Set vertex buffer binding so buffer 1 is bound to our colour buffer
    bind.SetBinding(1, vbuf);

    /// Allocate index buffer of the requested number of vertices (ibufCount)
    HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager.Singleton.
        CreateIndexBuffer(
        HardwareIndexBuffer.IndexType.IT_32BIT,
        (uint)iVerticles,
        HardwareBuffer.Usage.HBU_STATIC_WRITE_ONLY);

    ///// Upload the index data to the card
    unsafe
    {
        fixed (void* vert = face) ibuf.WriteData(0, ibuf.SizeInBytes, vert, true);
    }   

    /// Set parameters of the submesh
    sub.useSharedVertices = true;
    sub.indexData.indexBuffer = ibuf;
    sub.indexData.indexCount = (uint)iVerticles;
    sub.indexData.indexStart = 0;

    /// Set bounding information (for culling)
   msh._setBounds(new AxisAlignedBox(0,0,0,image.Width,max,image.Height));   

    /// Notify -Mesh object that it has been loaded
    msh.Load();
}