ardupilot/Tools/ArdupilotMegaPlanner/OpenGLtest.cs
Michael Oborne 09d8a8a2d1 Mission Planner 1.2.13
remove some mavlink 0.9 code
add arm/disarm button. Not yet implemented AC and AP Side.
modify heli setup screen
modify failsafe screen
fix old firmware under mono
workaround mono crash.
modify planner wp storage
tweak log dl screen
add change alt button
modify tlog wp extractor, multiple extractions
speed up srtm reading
fix lang edit.
2012-10-01 07:53:54 +08:00

380 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System.Drawing.Imaging;
using System.Drawing;
using GMap.NET;
using GMap.NET.WindowsForms;
namespace ArdupilotMega.Controls
{
public class OpenGLtest : GLControl
{
public static OpenGLtest instance;
// terrain image
Bitmap _terrain = new Bitmap(640,480);
int texture = 0;
float _angle = 0;
double cameraX, cameraY, cameraZ; // camera coordinates
double lookX, lookY, lookZ; // camera look-at coordinates
double step = 1 / 1200.0;
// image zoom level
int zoom = 11;
RectLatLng area = new RectLatLng(-35.04286,117.84262,0.1,0.1);
double _alt = 0;
public PointLatLngAlt LocationCenter {
get {
return new PointLatLngAlt(area.LocationMiddle.Lat, area.LocationMiddle.Lng,_alt,"");
}
set {
if (area.LocationMiddle.Lat == value.Lat && area.LocationMiddle.Lng == value.Lng)
return;
if (value.Lat == 0 && value.Lng == 0)
return;
_alt = value.Alt;
area = new RectLatLng(value.Lat + 0.15, value.Lng - 0.15, 0.3, 0.3);
// Console.WriteLine(area.LocationMiddle + " " + value.ToString());
this.Invalidate();
}
}
public Vector3 rpy = new Vector3();
public OpenGLtest()
{
instance = this;
InitializeComponent();
GL.GenTextures(1, out texture);
}
void getImage()
{
MapType type = MapType.GoogleSatellite;
PureProjection prj = null;
int maxZoom;
GMaps.Instance.AdjustProjection(type, ref prj, out maxZoom);
//int zoom = 14; // 12
if (!area.IsEmpty)
{
try
{
List<GPoint> tileArea = prj.GetAreaTileList(area, zoom, 0);
//string bigImage = zoom + "-" + type + "-vilnius.png";
//Console.WriteLine("Preparing: " + bigImage);
//Console.WriteLine("Zoom: " + zoom);
//Console.WriteLine("Type: " + type.ToString());
//Console.WriteLine("Area: " + area);
var types = GMaps.Instance.GetAllLayersOfType(type);
// current area
GPoint topLeftPx = prj.FromLatLngToPixel(area.LocationTopLeft, zoom);
GPoint rightButtomPx = prj.FromLatLngToPixel(area.Bottom, area.Right, zoom);
GPoint pxDelta = new GPoint(rightButtomPx.X - topLeftPx.X, rightButtomPx.Y - topLeftPx.Y);
DateTime startimage = DateTime.Now;
int padding = 0;
{
using (Bitmap bmpDestination = new Bitmap(pxDelta.X + padding * 2, pxDelta.Y + padding * 2))
{
using (Graphics gfx = Graphics.FromImage(bmpDestination))
{
gfx.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
// get tiles & combine into one
foreach (var p in tileArea)
{
Console.WriteLine("Downloading[" + p + "]: " + tileArea.IndexOf(p) + " of " + tileArea.Count);
foreach (MapType tp in types)
{
Exception ex;
WindowsFormsImage tile = GMaps.Instance.GetImageFrom(tp, p, zoom, out ex) as WindowsFormsImage;
if (tile != null)
{
using (tile)
{
int x = p.X * prj.TileSize.Width - topLeftPx.X + padding;
int y = p.Y * prj.TileSize.Width - topLeftPx.Y + padding;
{
gfx.DrawImage(tile.Img, x, y, prj.TileSize.Width, prj.TileSize.Height);
}
}
}
}
if ((DateTime.Now - startimage).TotalMilliseconds > 200)
break;
}
}
_terrain = new Bitmap(bmpDestination, 512, 512);
GL.BindTexture(TextureTarget.Texture2D, texture);
BitmapData data = _terrain.LockBits(new System.Drawing.Rectangle(0, 0, _terrain.Width, _terrain.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
//Console.WriteLine("w {0} h {1}",data.Width, data.Height);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
_terrain.UnlockBits(data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
}
}
if ((DateTime.Now - startimage).TotalMilliseconds > 200)
{
zoom--;
}
else
{
//zoom++;
}
}
catch { }
}
}
const float rad2deg = (float)(180 / Math.PI);
const float deg2rad = (float)(1.0 / rad2deg);
public Vector3 Normal(Vector3 a, Vector3 b, Vector3 c)
{
var dir = Vector3.Cross(b - a, c - a);
var norm = Vector3.Normalize(dir);
return norm;
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
if (this.DesignMode)
return;
if (area.LocationMiddle.Lat == 0 && area.LocationMiddle.Lng == 0)
return;
_angle+=1f;
// area.LocationTopLeft = new PointLatLng(area.LocationTopLeft.Lat + 0.0001,area.LocationTopLeft.Lng);
//area.Size = new SizeLatLng(0.1, 0.1);
try
{
base.OnPaint(e);
}
catch { return; }
double heightscale = (step / 90.0) * 4;
float scale = 1.0f;
float radians = (float)(Math.PI * (rpy.Z * -1) / 180.0f);
//radians = 0;
float mouseY = (float)(0.1 * scale);
cameraX = area.LocationMiddle.Lng; // multiplying by mouseY makes the
cameraZ = area.LocationMiddle.Lat; // camera get closer/farther away with mouseY
cameraY = (LocationCenter.Alt < srtm.getAltitude(cameraZ, cameraX, 20)) ? (srtm.getAltitude(cameraZ, cameraX, 20)+ 0.2) * heightscale : LocationCenter.Alt * heightscale;// (srtm.getAltitude(lookZ, lookX, 20) + 100) * heighscale;
lookX = area.LocationMiddle.Lng + Math.Sin(radians) * mouseY; ;
lookY = cameraY;
lookZ = area.LocationMiddle.Lat + Math.Cos(radians) * mouseY; ;
MakeCurrent();
GL.MatrixMode(MatrixMode.Projection);
OpenTK.Matrix4 projection = OpenTK.Matrix4.CreatePerspectiveFieldOfView(60 * deg2rad, 1f, 0.00001f, 5000.0f);
GL.LoadMatrix(ref projection);
Matrix4 modelview = Matrix4.LookAt((float)cameraX, (float)cameraY, (float)cameraZ, (float)lookX, (float)lookY, (float)lookZ, 0,1,0);
GL.MatrixMode(MatrixMode.Modelview);
// roll
modelview = Matrix4.Mult(modelview,Matrix4.CreateRotationZ (rpy.X * deg2rad));
// pitch
modelview = Matrix4.Mult(modelview, Matrix4.CreateRotationX(rpy.Y * -deg2rad));
GL.LoadMatrix(ref modelview);
GL.ClearColor(Color.Blue);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.LightModel(LightModelParameter.LightModelAmbient,new float[] {1f,1f,1f,1f});
GL.Enable(EnableCap.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, texture);
/*
GL.Begin(BeginMode.LineStrip);
GL.Color3(Color.White);
GL.Vertex3(0, 0, 0);
GL.Vertex3(area.Bottom, 0, area.Left);
GL.Vertex3(lookX, lookY, lookZ);
//GL.Vertex3(cameraX, cameraY, cameraZ);
GL.End();
*/
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
zoom = 11;
getImage();
sw.Stop();
Console.WriteLine("img " +sw.ElapsedMilliseconds);
sw.Start();
double increment = step * 5;
double cleanup = area.Bottom % increment;
double cleanup2 = area.Left % increment;
for (double z = (area.Bottom - cleanup); z < area.Top - step; z += increment)
{
//Makes OpenGL draw a triangle at every three consecutive vertices
GL.Begin(BeginMode.TriangleStrip);
for (double x = (area.Left - cleanup2); x < area.Right - step; x += increment)
{
int heightl = srtm.getAltitude(z, area.Right + area.Left - x, 20);
// Console.WriteLine(x + " " + z);
GL.Color3(Color.White);
// int heightl = 0;
double scale2 = (Math.Abs(x - area.Left) / area.WidthLng);// / (float)_terrain.Width;
double scale3 = (Math.Abs(z - area.Bottom) / area.HeightLat);// / (float)_terrain.Height;
double imgx = 1 - scale2;
double imgy = 1 - scale3;
// GL.Color3(Color.Red);
//GL.Color3(_terrain.GetPixel(imgx, imgy));
GL.TexCoord2(imgx,imgy);
GL.Vertex3(x, heightl * heightscale, z); // _terrain.GetPixel(x, z).R
try
{
heightl = srtm.getAltitude(z + increment, area.Right + area.Left - x, 20);
//scale2 = (Math.Abs(x - area.Left) / area.WidthLng) * (float)_terrain.Width;
scale3 = (Math.Abs(((z + increment) - area.Bottom)) / area.HeightLat);// / (float)_terrain.Height;
imgx = 1- scale2;
imgy = 1 - scale3;
// GL.Color3(Color.Green);
//GL.Color3(_terrain.GetPixel(imgx, imgy));
GL.TexCoord2(imgx,imgy);
GL.Vertex3(x, heightl * heightscale, z + increment);
// Console.WriteLine(x + " " + (z + step));
}
catch { break; }
}
GL.End();
}
GL.Enable(EnableCap.Blend);
GL.DepthMask(false);
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One);
GL.DepthMask(true);
GL.Disable(EnableCap.Blend);
GL.Flush();
sw.Stop();
Console.WriteLine("GL "+sw.ElapsedMilliseconds);
this.SwapBuffers();
//this.Invalidate();
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// OpenGLtest
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.Name = "OpenGLtest";
this.Load += new System.EventHandler(this.test_Load);
this.Resize += new System.EventHandler(this.test_Resize);
this.ResumeLayout(false);
}
private void test_Load(object sender, EventArgs e)
{
GL.Enable(EnableCap.DepthTest);
// GL.Enable(EnableCap.Light0);
GL.Enable(EnableCap.Lighting);
GL.Enable(EnableCap.ColorMaterial);
GL.Enable(EnableCap.Normalize);
//GL.Enable(EnableCap.LineSmooth);
//GL.Enable(EnableCap.PointSmooth);
//GL.Enable(EnableCap.PolygonSmooth);
GL.ShadeModel(ShadingModel.Smooth);
GL.Enable(EnableCap.CullFace);
GL.Enable(EnableCap.Texture2D);
}
private void test_Resize(object sender, EventArgs e)
{
MakeCurrent();
GL.Viewport(0, 0, this.Width, this.Height);
this.Invalidate();
}
}
}