/// <summary> Construct, on an item list, a buffer with this size </summary>
 public GLMatrixBufferWithGenerations(GLItemsList items, int maximumsize)
 {
     MatrixBuffer = new GLBuffer();
     items.Add(MatrixBuffer);
     Max = maximumsize;
     MatrixBuffer.AllocateBytes(Max * GLLayoutStandards.Mat4size);
     MatrixBuffer.AddPosition(0);        // CreateMatrix4 needs to have a position
 }
Exemplo n.º 2
0
        private void CreateBodies(StarScan.ScanNode node, int subnode)
        {
            rBodyObjects.Clear();

            bodyinfo = new List <BodyInfo>();

            bool sysenabled = false;

            if (subnode > 0 && node.NodeType == StarScan.ScanNodeType.barycentre && node.Children != null)
            {
                node       = node.Children.Values[subnode - 1];
                sysenabled = true;
            }

            displaycontrol.ApplyToControlOfName("sys*", (c) => { c.Visible = sysenabled; });

            BodyInfo.CreateInfoTree(node, null, -1, 0, bodyinfo);

            foreach (var o in bodyinfo)
            {
                System.Diagnostics.Debug.Write($"Body {o.scannode.OwnName} {o.scannode.scandata?.StarType} {o.scannode.scandata?.PlanetClass} Lvl {o.scannode.Level} ");

                if (o.kepler != null)
                {
                    System.Diagnostics.Debug.Write($"SMA {o.kepler.SemiMajorAxis / oneAU_m} AU {o.kepler.SemiMajorAxis / 1000} km " +
                                                   $" Ecc {o.kepler.Eccentricity} Orbital Period {o.kepler.OrbitalPeriodS / 24 / 60 / 60 / 365} Y Radius {o.scannode.scandata.nRadius} m CM {o.kepler.CentralMass} axt {o.scannode.scandata.nAxialTilt}");
                }

                System.Diagnostics.Debug.WriteLine("");

                if (o.kepler != null)
                {
                    Vector4[]     orbit = o.kepler.Orbit(currentjd, 0.1, mscaling);
                    GLRenderState lines = GLRenderState.Lines(1);
                    lines.DepthTest = false;

                    o.orbitpos.ColorIndex = node.scandata?.nRadius != null ? 0 : 1;

                    var riol = GLRenderableItem.CreateVector4(items, PrimitiveType.LineStrip, lines, orbit, o.orbitpos);
                    rBodyObjects.Add(orbitlineshader, riol);

                    GLRenderState quad = GLRenderState.Quads(cullface: false);
                    quad.DepthTest = false;
                    var s       = 100000e3f * mscaling;
                    var quadpos = new Vector4[] { new Vector4(-s, 0, -s, 1), new Vector4(-s, 0, +s, 1), new Vector4(+s, 0, +s, 1), new Vector4(+s, 0, -s, 1) };
                    var plane   = GLRenderableItem.CreateVector4(items, PrimitiveType.Quads, quad, quadpos, o.bodypos);
                    rBodyObjects.Add(bodyplaneshader, plane);
                }
            }

            int bodies = bodyinfo.Count;

            // hold planet and barycentre positions/sizes/imageno
            bodymatrixbuffer.AllocateBytes(GLBuffer.Mat4size * bodies);

            GLRenderState rt = GLRenderState.Tri();

            rt.DepthTest = false;
            var ribody = GLRenderableItem.CreateVector4Vector2Matrix4(items, PrimitiveType.Triangles, rt, spherebuffer, spheretexcobuffer, bodymatrixbuffer,
                                                                      spherebuffer.Length / sizeof(float) / 4,
                                                                      ic: bodies, matrixdivisor: 1);

            rBodyObjects.Add(bodyshader, ribody);

            rifind = GLRenderableItem.CreateVector4Vector2Matrix4(items, PrimitiveType.Triangles, GLRenderState.Tri(), spherebuffer, spheretexcobuffer, bodymatrixbuffer,
                                                                  spherebuffer.Length / sizeof(float) / 4,
                                                                  ic: bodies, matrixdivisor: 1);
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Closed += ShaderTest_Closed;

            gl3dcontroller = new Controller3D();
            gl3dcontroller.PaintObjects = ControllerDraw;
            gl3dcontroller.MatrixCalc.PerspectiveNearZDistance = 0.1f;
            gl3dcontroller.ZoomDistance = 20F;
            gl3dcontroller.Start(glwfc, new Vector3(0, 0, 0), new Vector3(135, 0, 0), 1F);

            gl3dcontroller.KeyboardTravelSpeed = (ms, eyedist) =>
            {
                return((float)ms / 100.0f);
            };

            items.Add(new GLColorShaderWorld(), "COSW");
            GLRenderState rl1 = GLRenderState.Lines(1);

            {
                rObjects.Add(items.Shader("COSW"), "L1",   // horizontal
                             GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl1,
                                                                  GLShapeObjectFactory.CreateLines(new Vector3(-100, 0, -100), new Vector3(-100, 0, 100), new Vector3(10, 0, 0), 21),
                                                                  new Color4[] { Color.Gray })
                             );


                rObjects.Add(items.Shader("COSW"),    // vertical
                             GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl1,
                                                                  GLShapeObjectFactory.CreateLines(new Vector3(-100, 0, -100), new Vector3(100, 0, -100), new Vector3(0, 0, 10), 21),
                                                                  new Color4[] { Color.Gray })
                             );
            }

            int hsize = 10, vsize = 5, zsize = 10;

            boundingbox = new Vector4[]
            {
                new Vector4(-hsize, -vsize, zsize, 1),
                new Vector4(-hsize, vsize, zsize, 1),
                new Vector4(hsize, vsize, zsize, 1),
                new Vector4(hsize, -vsize, zsize, 1),

                new Vector4(-hsize, -vsize, -zsize, 1),
                new Vector4(-hsize, vsize, -zsize, 1),
                new Vector4(hsize, vsize, -zsize, 1),
                new Vector4(hsize, -vsize, -zsize, 1),
            };


            {
                GLRenderState rll = GLRenderState.Lines(4);

                rObjects.Add(items.Shader("COSW"),
                             GLRenderableItem.CreateVector4(items, PrimitiveType.Lines, rll, boundingbox));

                Vector4[] extralines = new Vector4[]
                {
                    new Vector4(-hsize, -vsize, zsize, 1),
                    new Vector4(-hsize, -vsize, -zsize, 1),

                    new Vector4(-hsize, vsize, zsize, 1),
                    new Vector4(-hsize, vsize, -zsize, 1),

                    new Vector4(hsize, vsize, zsize, 1),
                    new Vector4(hsize, vsize, -zsize, 1),

                    new Vector4(hsize, -vsize, zsize, 1),
                    new Vector4(hsize, -vsize, -zsize, 1),

                    new Vector4(-hsize, -vsize, zsize, 1),
                    new Vector4(hsize, -vsize, zsize, 1),

                    new Vector4(-hsize, -vsize, -zsize, 1),
                    new Vector4(hsize, -vsize, -zsize, 1),
                };

                GLRenderState rl = GLRenderState.Lines(4);
                rObjects.Add(items.Shader("COSW"),
                             GLRenderableItem.CreateVector4(items, PrimitiveType.Lines, rl, extralines));
            }

            items.Add(new GLFixedShader(System.Drawing.Color.Purple), "LINEPURPLE");

            indicatorlinebuffer = new GLBuffer();                                                                          // new buffer
            indicatorlinebuffer.AllocateBytes(sizeof(float) * 4 * 2, OpenTK.Graphics.OpenGL4.BufferUsageHint.DynamicCopy); // set size of vec buffer
            rObjects.Add(items.Shader("LINEPURPLE"), GLRenderableItem.CreateVector4(items, PrimitiveType.Lines, rl1, indicatorlinebuffer, 2));

            items.Add(new GLFixedProjectionShader(System.Drawing.Color.Yellow), "DOTYELLOW");
            interceptpointbuffer = new GLBuffer();                                                                           // new buffer
            interceptpointbuffer.AllocateBytes(sizeof(float) * 4 * 12, OpenTK.Graphics.OpenGL4.BufferUsageHint.DynamicCopy); // set size of vec buffer
            GLRenderState rp1 = GLRenderState.Points(10);

            interceptri = GLRenderableItem.CreateVector4(items, PrimitiveType.Points, rp1, interceptpointbuffer, 0);
            rObjects.Add(items.Shader("DOTYELLOW"), interceptri);

            items.Add(new GLFixedProjectionShader(System.Drawing.Color.FromArgb(60, Color.Blue)), "SURFACEBLUE");
            surfacebuffer = new GLBuffer();                                                                                // new buffer
            surfacebuffer.AllocateBytes(sizeof(float) * 4 * (6 + 2), OpenTK.Graphics.OpenGL4.BufferUsageHint.DynamicCopy); // set size of vec buffer
            GLRenderState rtf = GLRenderState.Tri();

            surfaceri = GLRenderableItem.CreateVector4(items, PrimitiveType.TriangleFan, rtf, surfacebuffer, 0);
            rObjects.Add(items.Shader("SURFACEBLUE"), surfaceri);

            items.Add(new GLMatrixCalcUniformBlock(), "MCUB");      // create a matrix uniform block
        }
Exemplo n.º 4
0
        public void Start(GLOFC.WinForm.GLWinFormControl glwfc, GalacticMapping edsmmapping, GalacticMapping eliteregions)
        {
            this.glwfc        = glwfc;
            this.edsmmapping  = edsmmapping;
            this.elitemapping = eliteregions;

            hptimer.Start();

            items.Add(new GLMatrixCalcUniformBlock(), "MCUB");     // create a matrix uniform block

            int lyscale = 1;
            int front = -20000 / lyscale, back = front + 90000 / lyscale, left = -45000 / lyscale, right = left + 90000 / lyscale, vsize = 2000 / lyscale;

            if (false)     // debug bounding box
            {
                Vector4[] displaylines = new Vector4[]
                {
                    new Vector4(left, -vsize, front, 1), new Vector4(left, +vsize, front, 1),
                    new Vector4(left, +vsize, front, 1), new Vector4(right, +vsize, front, 1),
                    new Vector4(right, +vsize, front, 1), new Vector4(right, -vsize, front, 1),
                    new Vector4(right, -vsize, front, 1), new Vector4(left, -vsize, front, 1),

                    new Vector4(left, -vsize, back, 1), new Vector4(left, +vsize, back, 1),
                    new Vector4(left, +vsize, back, 1), new Vector4(right, +vsize, back, 1),
                    new Vector4(right, +vsize, back, 1), new Vector4(right, -vsize, back, 1),
                    new Vector4(right, -vsize, back, 1), new Vector4(left, -vsize, back, 1),

                    new Vector4(left, -vsize, front, 1), new Vector4(left, -vsize, back, 1),
                    new Vector4(left, +vsize, front, 1), new Vector4(left, +vsize, back, 1),
                    new Vector4(right, -vsize, front, 1), new Vector4(right, -vsize, back, 1),
                    new Vector4(right, +vsize, front, 1), new Vector4(right, +vsize, back, 1),
                };

                GLRenderState rl = GLRenderState.Lines(1);

                items.Add(new GLShaderPipeline(new GLPLVertexShaderWorldCoord(), new GLPLFragmentShaderFixedColor(Color.Yellow)), "LINEYELLOW");
                rObjects.Add(items.Shader("LINEYELLOW"),
                             GLRenderableItem.CreateVector4(items, PrimitiveType.Lines, rl, displaylines));

                items.Add(new GLColorShaderWorld(), "COS-1L");

                float h = 0;

                int   dist = 1000 / lyscale;
                Color cr   = Color.FromArgb(100, Color.White);
                rObjects.Add(items.Shader("COS-1L"),    // horizontal
                             GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl,
                                                                  GLShapeObjectFactory.CreateLines(new Vector3(left, h, front), new Vector3(left, h, back), new Vector3(dist, 0, 0), (back - front) / dist + 1),
                                                                  new OpenTK.Graphics.Color4[] { cr })
                             );

                rObjects.Add(items.Shader("COS-1L"),
                             GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, rl,
                                                                  GLShapeObjectFactory.CreateLines(new Vector3(left, h, front), new Vector3(right, h, front), new Vector3(0, 0, dist), (right - left) / dist + 1),
                                                                  new OpenTK.Graphics.Color4[] { cr })
                             );

                rObjects.Add(new GLOperationClearDepthBuffer());
            }

            int ctrlo = 2048 | 32 | 64;

            ctrlo = -1;

            if ((ctrlo & 1) != 0) // galaxy
            {
                volumetricboundingbox = new Vector4[]
                {
                    new Vector4(left, -vsize, front, 1),
                    new Vector4(left, vsize, front, 1),
                    new Vector4(right, vsize, front, 1),
                    new Vector4(right, -vsize, front, 1),

                    new Vector4(left, -vsize, back, 1),
                    new Vector4(left, vsize, back, 1),
                    new Vector4(right, vsize, back, 1),
                    new Vector4(right, -vsize, back, 1),
                };


                const int gnoisetexbinding = 3;     //tex bindings are attached per shaders so are not global
                const int gdisttexbinding  = 4;
                const int galtexbinding    = 1;

                volumetricblock = new GLVolumetricUniformBlock(volumenticuniformblock);
                items.Add(volumetricblock, "VB");

                int         sc      = 1;
                GLTexture3D noise3d = new GLTexture3D(1024 * sc, 64 * sc, 1024 * sc, OpenTK.Graphics.OpenGL4.SizedInternalFormat.R32f);                           // red channel only
                items.Add(noise3d, "Noise");
                ComputeShaderNoise3D csn = new ComputeShaderNoise3D(noise3d.Width, noise3d.Height, noise3d.Depth, 128 * sc, 16 * sc, 128 * sc, gnoisetexbinding); // must be a multiple of localgroupsize in csn
                csn.StartAction += (A, m) => { noise3d.BindImage(gnoisetexbinding); };
                csn.Run();                                                                                                                                        // compute noise
                csn.Dispose();

                GLTexture1D gaussiantex = new GLTexture1D(1024, OpenTK.Graphics.OpenGL4.SizedInternalFormat.R32f); // red channel only
                items.Add(gaussiantex, "Gaussian");

                // set centre=width, higher widths means more curve, higher std dev compensate.
                // fill the gaussiantex with data
                ComputeShaderGaussian gsn = new ComputeShaderGaussian(gaussiantex.Width, 2.0f, 2.0f, 1.4f, gdisttexbinding);
                gsn.StartAction += (A, m) => { gaussiantex.BindImage(gdisttexbinding); };
                gsn.Run();      // compute noise
                gsn.Dispose();

                GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits);

                // load one upside down and horz flipped, because the volumetric co-ords are 0,0,0 bottom left, 1,1,1 top right
                GLTexture2D galtex = new GLTexture2D(Properties.Resources.Galaxy_L180, SizedInternalFormat.Rgba8);
                items.Add(galtex, "galtex");
                galaxyshader = new GalaxyShader(volumenticuniformblock, galtexbinding, gnoisetexbinding, gdisttexbinding);
                items.Add(galaxyshader, "Galaxy-sh");
                // bind the galaxy texture, the 3dnoise, and the gaussian 1-d texture for the shader
                galaxyshader.StartAction += (a, m) => { galtex.Bind(galtexbinding); noise3d.Bind(gnoisetexbinding); gaussiantex.Bind(gdisttexbinding); };      // shader requires these, so bind using shader

                GLRenderState rt = GLRenderState.Tri();
                galaxyrenderable = GLRenderableItem.CreateNullVertex(OpenTK.Graphics.OpenGL4.PrimitiveType.Points, rt);   // no vertexes, all data from bound volumetric uniform, no instances as yet
                rObjects.Add(galaxyshader, "galshader", galaxyrenderable);
            }

            if ((ctrlo & 2) != 0)
            {
                var corr = new GalMapRegions.ManualCorrections[] {          // nerf the centeroid position slightly
                    new GalMapRegions.ManualCorrections("The Galactic Aphelion", y: -2000),
                    new GalMapRegions.ManualCorrections("The Abyss", y: +3000),
                    new GalMapRegions.ManualCorrections("Eurus", y: -3000),
                    new GalMapRegions.ManualCorrections("The Perseus Transit", x: -3000, y: -3000),
                    new GalMapRegions.ManualCorrections("Zephyrus", x: 0, y: 2000),
                };

                edsmgalmapregions = new GalMapRegions();
                edsmgalmapregions.CreateObjects("edsmregions", items, rObjects, edsmmapping, 8000, corr: corr);
            }

            if ((ctrlo & 4) != 0)
            {
                elitemapregions = new GalMapRegions();
                elitemapregions.CreateObjects("eliteregions", items, rObjects, eliteregions, 8000);
                EliteRegionsEnable = false;
            }

            if ((ctrlo & 8) != 0)
            {
                int    gran = 8;
                Bitmap img  = Properties.Resources.Galaxy_L180;
                Bitmap heat = img.Function(img.Width / gran, img.Height / gran, mode: GLOFC.Utils.BitMapHelpers.BitmapFunction.HeatMap);
                heat.Save(@"c:\code\heatmap.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

                Random rnd = new Random(23);

                GLBuffer buf = items.NewBuffer(16 * 350000, false); // since RND is fixed, should get the same number every time.
                buf.StartWrite(0);                                  // get a ptr to the whole schebang

                int xcw = (right - left) / heat.Width;
                int zch = (back - front) / heat.Height;

                int points = 0;

                for (int x = 0; x < heat.Width; x++)
                {
                    for (int z = 0; z < heat.Height; z++)
                    {
                        int i = heat.GetPixel(x, z).R;
                        if (i > 32)
                        {
                            int gx = left + x * xcw;
                            int gz = front + z * zch;

                            float  dx = (float)Math.Abs(gx) / 45000;
                            float  dz = (float)Math.Abs(25889 - gz) / 45000;
                            double d  = Math.Sqrt(dx * dx + dz * dz); // 0 - 0.1412
                            d = 1 - d;                                // 1 = centre, 0 = unit circle
                            d = d * 2 - 1;                            // -1 to +1
                            double dist = ObjectExtensionsNumbersBool.GaussianDist(d, 1, 1.4);

                            int c = Math.Min(Math.Max(i * i * i / 120000, 1), 40);
                            //int c = Math.Min(Math.Max(i * i * i / 24000000, 1), 40);

                            dist *= 2000 / lyscale;
                            //System.Diagnostics.Debug.WriteLine("{0} {1} : dist {2} c {3}", x, z, dist, c);
                            //System.Diagnostics.Debug.Write(c);
                            GLPointsFactory.RandomStars4(buf, c, gx, gx + xcw, gz, gz + zch, (int)dist, (int)-dist, rnd, w: 0.8f);
                            points += c;
                            System.Diagnostics.Debug.Assert(points < buf.Length / 16);
                        }
                    }
                    //System.Diagnostics.Debug.WriteLine(".");
                }

                buf.StopReadWrite();

                stardots = new GalaxyStarDots();
                items.Add(stardots);
                GLRenderState rc = GLRenderState.Points(1);
                rc.DepthTest = false; // note, if this is true, there is a wierd different between left and right in view.. not sure why
                rObjects.Add(stardots, "stardots", GLRenderableItem.CreateVector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Points, rc, buf, points));
                System.Diagnostics.Debug.WriteLine("Stars " + points);
            }

            rObjects.Add(new GLOperationClearDepthBuffer()); // clear depth buffer and now use full depth testing on the rest

            if ((ctrlo & 16) != 0)
            {
                items.Add(new GLTexture2D(Properties.Resources.StarFlare2, SizedInternalFormat.Rgba8), "lensflare");
                items.Add(new GLPointSpriteShader(items.Tex("lensflare"), 64, 40), "PS");
                var p = GLPointsFactory.RandomStars4(1000, 0, 25899 / lyscale, 10000 / lyscale, 1000 / lyscale, -1000 / lyscale);

                GLRenderState rps = GLRenderState.PointSprites();

                rObjects.Add(items.Shader("PS"), "starsprites", GLRenderableItem.CreateVector4Color4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Points, rps, p, new Color4[] { Color.White }));
            }

            if ((ctrlo & 32) != 0)
            {
                gridvertshader = new DynamicGridVertexShader(Color.Cyan);
                //items.Add(gridvertshader, "PLGRIDVertShader");
                var frag = new GLPLFragmentShaderVSColor();
                //items.Add(frag, "PLGRIDFragShader");

                GLRenderState rl = GLRenderState.Lines(1);

                items.Add(new GLShaderPipeline(gridvertshader, frag), "DYNGRID");

                gridrenderable = GLRenderableItem.CreateNullVertex(OpenTK.Graphics.OpenGL4.PrimitiveType.Lines, rl, drawcount: 2);

                rObjects.Add(items.Shader("DYNGRID"), "DYNGRIDRENDER", gridrenderable);
            }

            if ((ctrlo & 64) != 0)
            {
                gridbitmapvertshader = new DynamicGridCoordVertexShader();
                var frag = new GLPLFragmentShaderTexture2DIndexed(0);

                GLRenderState rl = GLRenderState.Tri(cullface: false);

                GLTexture2DArray gridtexcoords = new GLTexture2DArray();
                items.Add(gridtexcoords, "PLGridBitmapTextures");

                GLShaderPipeline sp = new GLShaderPipeline(gridbitmapvertshader, frag);
                items.Add(sp, "DYNGRIDBitmap");

                rObjects.Add(items.Shader("DYNGRIDBitmap"), "DYNGRIDBitmapRENDER", GLRenderableItem.CreateNullVertex(OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rl, drawcount: 4, instancecount: 9));
            }

            GLStorageBlock findresults = items.NewStorageBlock(findblock);

            float sunsize = .5f;

            if ((ctrlo & 128) != 0)
            {
                Random rnd = new Random(52);
                List <HistoryEntry> pos    = new List <HistoryEntry>();
                DateTime            start  = new DateTime(2020, 1, 1);
                Color[]             colors = new Color[] { Color.Red, Color.Green, Color.Blue, Color.White, Color.Black, Color.Purple, Color.Yellow };
                for (int j = 0; j <= 200; j++)
                {
                    Color  jc   = colors[j % colors.Length];
                    int    i    = j * 10;
                    string name = "Kyli Flyuae AA-B h" + j.ToString();
                    if (i < 30000)
                    {
                        pos.Add(new HistoryEntry(start, name, i + rnd.Next(50), rnd.Next(50), i, jc));
                    }
                    else if (i < 60000)
                    {
                        pos.Add(new HistoryEntry(start, name, 60000 - i + rnd.Next(50), rnd.Next(50), i, jc));
                    }
                    else if (i < 90000)
                    {
                        pos.Add(new HistoryEntry(start, name, -(i - 60000) + rnd.Next(50), rnd.Next(50), 120000 - i, jc));
                    }
                    else
                    {
                        pos.Add(new HistoryEntry(start, name, -30000 + (i - 90000) + rnd.Next(50), rnd.Next(50), -i + 120000, jc));
                    }

                    start = start.AddDays(1);
                }

                // tested to 50k stars

                travelpath = new TravelPath(1000);
                travelpath.Create(items, rObjects, pos, sunsize, sunsize, findresults, true);
                travelpath.SetSystem(0);
            }

            if ((ctrlo & 256) != 0)
            {
                galmapobjects = new GalMapObjects();
                galmapobjects.CreateObjects(items, rObjects, edsmmapping, findresults, true);
            }

            if ((ctrlo & 512) != 0)
            {
                //  galaxystars = new GalaxyStars(items, rObjects, sunsize, findresults);
            }

            if ((ctrlo & 1024) != 0)
            {
                rightclickmenu = new GLContextMenu("RightClickMenu",
                                                   new GLMenuItem("RCMInfo", "Information")
                {
                    MouseClick = (s, e) => {
                        var nl = NameLocationDescription(rightclickmenu.Tag);
                        System.Diagnostics.Debug.WriteLine($"Info {nl.Item1} {nl.Item2}");
                        // logical name is important as menu uses it to close down
                        GLMessageBox msg = new GLMessageBox("InfoBoxForm-1", displaycontrol, e.WindowLocation,
                                                            nl.Item3, $"{nl.Item1} @ {nl.Item2.X:#.#},{nl.Item2.Y:#.#},{nl.Item2.Z:#.#}", GLMessageBox.MessageBoxButtons.OK, null,
                                                            Color.FromArgb(220, 60, 60, 70), Color.DarkOrange);
                    }
                },
                                                   new GLMenuItem("RCMZoomIn", "Goto Zoom In")
                {
                    MouseClick = (s1, e1) => {
                        var nl = NameLocationDescription(rightclickmenu.Tag);
                        gl3dcontroller.SlewToPositionZoom(nl.Item2, 100, -1);
                    }
                },
                                                   new GLMenuItem("RCMGoto", "Goto Position")
                {
                    MouseClick = (s1, e1) => {
                        var nl = NameLocationDescription(rightclickmenu.Tag);
                        System.Diagnostics.Debug.WriteLine($"Goto {nl.Item1} {nl.Item2}");
                        gl3dcontroller.SlewToPosition(nl.Item2, -1);
                    }
                },
                                                   new GLMenuItem("RCMLookAt", "Look At")
                {
                    MouseClick = (s1, e1) => {
                        var nl = NameLocationDescription(rightclickmenu.Tag);
                        gl3dcontroller.PanTo(nl.Item2, -1);
                    }
                }
                                                   );
            }

            if ((ctrlo & 2048) != 0)
            {
                bookmarks = new Bookmarks();
                var syslist = new List <SystemClass> {
                    new SystemClass("bk1", 1000, 0, 0), new SystemClass("bk1", 1000, 0, 2000),
                };
                bookmarks.Create(items, rObjects, syslist, 10, findresults, false);
            }
            // Matrix calc holding transform info

            matrixcalc = new GLMatrixCalc();
            matrixcalc.PerspectiveNearZDistance = 1f;
            matrixcalc.PerspectiveFarZDistance  = 120000f / lyscale;
            matrixcalc.InPerspectiveMode        = true;
            matrixcalc.ResizeViewPort(this, glwfc.Size);          // must establish size before starting

            // menu system

            displaycontrol           = new GLControlDisplay(items, glwfc, matrixcalc, true, 0.00001f, 0.00001f); // hook form to the window - its the master
            displaycontrol.Font      = new Font("Arial", 10f);
            displaycontrol.Focusable = true;                                                                     // we want to be able to focus and receive key presses.
            displaycontrol.SetFocus();

            // 3d controller

            gl3dcontroller = new Controller3D();
            gl3dcontroller.PosCamera.ZoomMax     = 600; // gives 5ly
            gl3dcontroller.ZoomDistance          = 3000F / lyscale;
            gl3dcontroller.PosCamera.ZoomMin     = 0.1f;
            gl3dcontroller.PosCamera.ZoomScaling = 1.1f;
            gl3dcontroller.YHoldMovement         = true;
            gl3dcontroller.PaintObjects          = Controller3DDraw;
            gl3dcontroller.KeyboardTravelSpeed   = (ms, eyedist) =>
            {
                double eyedistr = Math.Pow(eyedist, 1.0);
                float  v        = (float)Math.Max(eyedistr / 1200, 0);
                //System.Diagnostics.Debug.WriteLine("Speed " + eyedistr + " "+ v);
                return((float)ms * v);
            };

            // hook gl3dcontroller to display control - its the slave. Do not register mouse UI, we will deal with that.
            gl3dcontroller.Start(matrixcalc, displaycontrol, new Vector3(0, 0, 0), new Vector3(140.75f, 0, 0), 0.5F, false, true);
            //gl3dcontroller.Start(matrixcalc, displaycontrol, new Vector3(0, 0, 0), new Vector3(90F, 0, 0), 0.5F, false, true);

            if (displaycontrol != null)
            {
                displaycontrol.Paint += (o, ts) =>        // subscribing after start means we paint over the scene, letting transparency work
                {
                    // MCUB set up by Controller3DDraw which did the work first
                    galaxymenu.UpdateCoords(gl3dcontroller.MatrixCalc, gl3dcontroller.PosCamera.ZoomFactor);
                    // debug this galaxymenu.DebugStatusText(gl3dcontroller.PosCamera.StringPositionCamera);  gl3dcontroller.PosCamera.SetPositionCamera(gl3dcontroller.PosCamera.StringPositionCamera);
                    displaycontrol.Animate(glwfc.ElapsedTimems);
                    displaycontrol.Render(glwfc.RenderState, ts);
                };
            }

            displaycontrol.MouseClick += MouseClickOnMap;
            displaycontrol.MouseUp    += MouseUpOnMap;
            displaycontrol.MouseDown  += MouseDownOnMap;
            displaycontrol.MouseMove  += MouseMoveOnMap;
            displaycontrol.MouseWheel += MouseWheelOnMap;

            galaxymenu = new MapMenu(this);

            // Autocomplete text box at top for searching

            GLTextBoxAutoComplete tbac = ((GLTextBoxAutoComplete)displaycontrol[MapMenu.EntryTextName]);

            tbac.PerformAutoCompleteInUIThread = (s, a, set) =>
            {
                System.Diagnostics.Debug.Assert(Application.MessageLoop);       // must be in UI thread
                var           glist = edsmmapping.galacticMapObjects.Where(x => s.Length < 3 ? x.name.StartsWith(s, StringComparison.InvariantCultureIgnoreCase) : x.name.Contains(s, StringComparison.InvariantCultureIgnoreCase)).Select(x => x).ToList();
                List <string> list  = glist.Select(x => x.name).ToList();
                list.AddRange(travelpath.CurrentList.Where(x => s.Length < 3 ? x.System.Name.StartsWith(s, StringComparison.InvariantCultureIgnoreCase) : x.System.Name.Contains(s, StringComparison.InvariantCultureIgnoreCase)).Select(x => x.System.Name));
                foreach (var x in list)
                {
                    set.Add(x);
                }
            };

            tbac.SelectedEntry = (a) =>                                   // in UI thread
            {
                System.Diagnostics.Debug.Assert(Application.MessageLoop); // must be in UI thread
                System.Diagnostics.Debug.WriteLine("Selected " + tbac.Text);
                var gmo = edsmmapping.galacticMapObjects.Find(x => x.name.Equals(tbac.Text, StringComparison.InvariantCultureIgnoreCase));
                if (gmo != null)
                {
                    System.Diagnostics.Debug.WriteLine("Move to gmo " + gmo.points[0]);
                    gl3dcontroller.SlewToPosition(new Vector3((float)gmo.points[0].X, (float)gmo.points[0].Y, (float)gmo.points[0].Z), -1);
                }
                else
                {
                    var he = travelpath.CurrentList.Find(x => x.System.Name.Equals(tbac.Text, StringComparison.InvariantCultureIgnoreCase));
                    if (he != null)
                    {
                        System.Diagnostics.Debug.WriteLine("Move to sys " + he.System.Name);
                        gl3dcontroller.SlewToPosition(new Vector3((float)he.System.X, (float)he.System.Y, (float)he.System.Z), -1);
                    }
                    else
                    {
                        tbac.InErrorCondition = true;
                    }
                }
            };

            if (galaxystars != null)
            {
                galaxystars.Start();
            }

            if (false)         // enable for debug buffer
            {
                debugbuffer = new GLStorageBlock(31, true);
                debugbuffer.AllocateBytes(32000, OpenTK.Graphics.OpenGL4.BufferUsageHint.DynamicCopy);       // set size of vec buffer
            }

            if (false)          // enable for debug
            {
                items.Add(new GLColorShaderObjectTranslation(), "COSOT");
                GLRenderState rc = GLRenderState.Tri(cullface: false);
                rc.DepthTest = false;

                Vector3[] markers = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, -5, 0), new Vector3(0, -5 - 3.125f / 2f, 0) };

                for (int i = 0; i < markers.Length; i++)
                {
                    rObjects.Add(items.Shader("COSOT"), "marker" + i,
                                 GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Triangles, rc,
                                                                      GLCubeObjectFactory.CreateSolidCubeFromTriangles(0.5f),
                                                                      new Color4[] { Color4.Red, Color4.Green, Color4.Blue, Color4.White, Color4.Cyan, Color4.Orange },
                                                                      new GLRenderDataTranslationRotation(markers[i])
                                                                      ));
                }
            }
        }