Skip to main content
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

Copy to clipboard
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(); }