Program.cs
using System; using System.IO; using System.Collections.Generic; using System.Text; namespace DibujoOpenGL { class Program { static void Main(string[] args) { BinaryReader DatosSRTM = new BinaryReader(File.Open(@"c:\temp\N45E000.hgt", FileMode.Open)); VentanaDibujo demo = new VentanaDibujo(DatosSRTM); demo.Run(); } } }
Archivo N45E000.hgt obtenido de: http://dds.cr.usgs.gov/srtm/
A continuación una clase estática para leer el formato SRTM que tiene los datos de altura como Enteros con signo de 2 bytes en formato BigEndian (Byte más significativo primero).
Lector.cs
using System; using System.IO; namespace DibujoOpenGL { public enum ByteOrder : int { LittleEndian, BigEndian } static class Lector { public static byte[] ReadBytes(BinaryReader reader, int fieldSize, ByteOrder byteOrder) { byte[] bytes = new byte[fieldSize]; if (byteOrder == ByteOrder.LittleEndian) return reader.ReadBytes(fieldSize); else { for (int i = fieldSize - 1; i > -1; i--) bytes[i] = reader.ReadByte(); return bytes; } } public static Int16 ReadInt16(BinaryReader reader, ByteOrder byteOrder) { if (byteOrder == ByteOrder.LittleEndian) { return (Int16)reader.ReadInt16(); } else // Big-Endian { return BitConverter.ToInt16(ReadBytes(reader, 2, ByteOrder.BigEndian),0); } } } }
VentanaDibujo.cs
using System; using System.IO; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; using OpenTK.Input; using System.Drawing; namespace DibujoOpenGL { public class VentanaDibujo : GameWindow { private float cameraSpeed = 5f; private Matrix4 cameraMatrix; private float[] mouseSpeed = new float[2]; private BinaryReader datosSRTM; private Int16[,] filas = new Int16[1201,1201]; public VentanaDibujo(BinaryReader reader) : base(900, 600, GraphicsMode.Default, "Terreno") { GL.Enable(EnableCap.DepthTest); datosSRTM = reader; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); GL.ClearColor(Color.Black); GL.ShadeModel(ShadingModel.Smooth); // Tipo de pintado de vertices int w = this.Width; int h = this.Height; cameraMatrix = Matrix4.CreateTranslation(-300f, -100f, -300f); for (int i = 0; i <= 1200; i++) for (int j = 0; j <= 1200; j++) { filas[i,j] = Lector.ReadInt16(datosSRTM, ByteOrder.BigEndian); } datosSRTM.Close(); } protected override void OnRenderFrame(FrameEventArgs e) { GL.MatrixMode(MatrixMode.Modelview); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.LoadMatrix(ref cameraMatrix); GL.Color3(Color.Gray); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); // Render Modo Fill o Wire Vector3 MyColor = new Vector3(0.0f, 0.0f, 0.0f); GL.Color3(MyColor); for (int i = 0; i < 600; i++) { GL.Begin(BeginMode.TriangleStrip); GL.PushMatrix(); for (int j = 0; j <= 600; j++) { MyColor.X= 1.0f*0.01f*filas[i, j]; MyColor.Y = 0.52f * 0.01f * filas[i, j]; MyColor.Z = 0.0f * 0.01f * filas[i, j]; GL.Color3(MyColor); GL.Vertex3(j, 0.025f * filas[i, j], -i); MyColor.X = 1.0f * 0.01f * filas[i+1, j]; MyColor.Y = 0.52f * 0.01f * filas[i+1, j]; MyColor.Z = 0.0f * 0.01f * filas[i+1, j]; GL.Color3(MyColor); GL.Vertex3(j, 0.025f*filas[i + 1, j], -(i + 1)); } GL.End(); GL.PopMatrix(); } SwapBuffers(); } protected override void OnUpdateFrame(FrameEventArgs e) { float move = 50f; float look = 0.01f; //Rotation if (Keyboard[Key.Left]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.CreateRotationZ(-look)); } if (Keyboard[Key.Right]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.CreateRotationZ(look)); } if (Keyboard[Key.Up]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.Translation(0f, -move * (float)e.Time, 0.0f)); //cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.CreateRotationX(-look)); } if (Keyboard[Key.Down]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.Translation(0f, move * (float)e.Time, 0.0f)); //cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.CreateRotationX(look)); } if (Keyboard[Key.W]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.Translation(0f, 0.0f, move * (float)e.Time)); } if (Keyboard[Key.S]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.Translation(0f, 0.0f, -move * (float)e.Time)); } if (Keyboard[Key.A]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.Translation(move * (float)e.Time, 0f, 0f)); } if (Keyboard[Key.D]) { cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.Translation(-move * (float)e.Time, 0f, 0f)); } /* mouseSpeed[0] *= 0.9f; mouseSpeed[1] *= 0.9f; mouseSpeed[0] += Mouse.XDelta / 100f; mouseSpeed[1] += Mouse.YDelta / 100f; cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.RotateY(mouseSpeed[0] * (float)e.Time)); cameraMatrix = Matrix4.Mult(cameraMatrix, Matrix4.RotateX(mouseSpeed[1] * (float)e.Time));*/ if (Keyboard[Key.Escape]) Exit(); } protected override void OnResize(EventArgs e) { base.OnResize(e); GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height); Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 6, Width / (float)Height, 1.0f, 2500.0f); GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref projection); } } }
Os dejo un par de imágenes: