private void IntCreatePath(GLItemsList items, GLRenderProgramSortedList rObjects, GLStorageBlock bufferfindresults) { HistoryEntry lastone = lastpos != -1 && lastpos < currentfilteredlist.Count ? currentfilteredlist[lastpos] : null; // see if lastpos is there, and store it if (TravelPathEndDateEnable || TravelPathStartDateEnable) { currentfilteredlist = unfilteredlist.Where(x => (!TravelPathStartDateEnable || x.EventTimeUTC >= TravelPathStartDate) && (!TravelPathEndDateEnable || x.EventTimeUTC <= TravelPathEndDate)).ToList(); if (currentfilteredlist.Count > MaxStars) { currentfilteredlist = currentfilteredlist.Skip(currentfilteredlist.Count - MaxStars).ToList(); } } else { if (unfilteredlist.Count > MaxStars) { currentfilteredlist = unfilteredlist.Skip(currentfilteredlist.Count - MaxStars).ToList(); } else { currentfilteredlist = unfilteredlist; } } // do date filter on currentfilteredlist lastpos = lastone == null ? -1 : currentfilteredlist.IndexOf(lastone); // may be -1, may have been removed var positionsv4 = currentfilteredlist.Select(x => new Vector4((float)x.System.X, (float)x.System.Y, (float)x.System.Z, 0)).ToArray(); var colours = currentfilteredlist.Select(x => x.JumpColor).ToArray(); float seglen = tapesize * 10; // a tape is a set of points (item1) and indexes to select them (item2), so we need an element index in the renderer to use. var tape = GLTapeObjectFactory.CreateTape(positionsv4, colours, tapesize, seglen, 0F.Radians(), margin: sunsize * 1.2f); if (ritape == null) // first time.. { // first the tape var tapetex = new GLTexture2D(Properties.Resources.chevron, internalformat: OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); // tape image items.Add(tapetex); tapetex.SetSamplerMode(OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat, OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat); tapefrag = new GLPLFragmentShaderTextureTriStripColorReplace(1, Color.FromArgb(255, 206, 0, 0)); var vert = new GLPLVertexShaderWorldTextureTriStrip(); tapeshader = new GLShaderPipeline(vert, tapefrag); items.Add(tapeshader); GLRenderState rts = GLRenderState.Tri(tape.Item3, cullface: false); // set up a Tri strip, primitive restart value set from tape, no culling rts.DepthTest = depthtest; // no depth test so always appears // now the renderer, set up with the render control, tape as the points, and bind a RenderDataTexture so the texture gets binded each time ritape = GLRenderableItem.CreateVector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rts, tape.Item1.ToArray(), new GLRenderDataTexture(tapetex)); tapepointbuf = items.LastBuffer(); // keep buffer for refill ritape.Visible = tape.Item1.Count > 0; // no items, set not visible, so it won't except over the BIND with nothing in the element buffer ritape.CreateElementIndex(items.NewBuffer(), tape.Item2.ToArray(), tape.Item3); // finally, we are using index to select vertexes, so create an index rObjects.Add(tapeshader, "travelpath-tape", ritape); // add render to object list // now the stars starposbuf = items.NewBuffer(); // where we hold the vertexes for the suns, used by renderer and by finder starposbuf.AllocateFill(positionsv4); //Vector4[] vectors = starposbuf.ReadVector4s(0, starposbuf.Length / 16); sunvertex = new GLPLVertexShaderModelCoordWorldAutoscale(new Color[] { Color.Yellow, Color.FromArgb(255, 230, 230, 1) }, autoscale: 30, autoscalemin: 1f, autoscalemax: 2f, useeyedistance: false); // below scale, 1f, above scale, scale up to x times (eyedist/scale) sunshader = new GLShaderPipeline(sunvertex, new GLPLStarSurfaceFragmentShader()); items.Add(sunshader); var shape = GLSphereObjectFactory.CreateSphereFromTriangles(2, sunsize); GLRenderState rt = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear rt.DepthTest = depthtest; rt.DepthClamp = true; renderersun = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, rt, shape, starposbuf, 0, null, currentfilteredlist.Count, 1); rObjects.Add(sunshader, "travelpath-suns", renderersun); // find compute var geofind = new GLPLGeoShaderFindTriangles(bufferfindresults, 16); findshader = items.NewShaderPipeline(null, sunvertex, null, null, geofind, null, null, null); rifind = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, GLRenderState.Tri(), shape, starposbuf, ic: currentfilteredlist.Count, seconddivisor: 1); // Sun names, handled by textrenderer textrenderer = new GLBitmaps("bm-travelmap", rObjects, new Size(128, 40), depthtest: depthtest, cullface: false); items.Add(textrenderer); } else { tapepointbuf.AllocateFill(tape.Item1.ToArray()); // replace the points with a new one ritape.RenderState.PrimitiveRestart = GL4Statics.DrawElementsRestartValue(tape.Item3); // IMPORTANT missing bit Robert, must set the primitive restart value to the new tape size ritape.CreateElementIndex(ritape.ElementBuffer, tape.Item2.ToArray(), tape.Item3); // update the element buffer ritape.Visible = tape.Item1.Count > 0; starposbuf.AllocateFill(positionsv4); // and update the star position buffers so find and sun renderer works renderersun.InstanceCount = positionsv4.Length; // update the number of suns to draw. rifind.InstanceCount = positionsv4.Length; // update the find list } // name bitmaps HashSet <object> hashset = new HashSet <object>(currentfilteredlist); // so it can find it quickly textrenderer.CurrentGeneration++; // setup for next generation textrenderer.RemoveGeneration(textrenderer.CurrentGeneration - 1, hashset); // and remove all of the previous one which are not in hashset. Font fnt = new Font("Arial", 8.5F); using (StringFormat fmt = new StringFormat()) { fmt.Alignment = StringAlignment.Center; foreach (var isys in currentfilteredlist) { if (textrenderer.Exist(isys) == false) // if does not exist already, need a new label { textrenderer.Add(isys, isys.System.Name, fnt, Color.White, Color.Transparent, new Vector3((float)isys.System.X, (float)isys.System.Y - 5, (float)isys.System.Z), new Vector3(20, 0, 0), new Vector3(0, 0, 0), textformat: fmt, rotatetoviewer: true, rotateelevation: false, alphafadescalar: -200, alphafadepos: 300); } } } fnt.Dispose(); }
public void Start(string name, int maxstars, float sunsize, float tapesize, GLStorageBlock bufferfindresults, bool depthtest, GLItemsList items, GLRenderProgramSortedList rObjects) { this.MaxStars = maxstars; this.tapesize = tapesize; this.sunsize = sunsize; // first the tape var tapetex = new GLTexture2D(BaseUtils.Icons.IconSet.GetBitmap("GalMap.chevron"), internalformat: OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); // tape image items.Add(tapetex); tapetex.SetSamplerMode(OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat, OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat); // configure the fragger, set the replacement color, and set the distance where the replacement color is used for all pixels tapefrag = new GLPLFragmentShaderTextureTriStripColorReplace(1, Color.FromArgb(255, 206, 0, 0), 1000); // create the vertex shader with the autoscale required var vert = new GLPLVertexShaderWorldTextureTriStripNorm(100, 1, 10000); vert.SetWidth(tapesize); // set the nominal tape width tapeshader = new GLShaderPipeline(vert, tapefrag); items.Add(tapeshader); GLRenderState rts = GLRenderState.Tri(OpenTK.Graphics.OpenGL4.DrawElementsType.UnsignedByte, cullface: false); // set up a Tri strip, Default primitive restart rts.DepthTest = depthtest; // no depth test so always appears // now the renderer, set up with the render control, tape as the points, and bind a RenderDataTexture so the texture gets binded each time var zerotape = new Vector4[] { Vector4.Zero }; // just use an dummy array to get this going ritape = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rts, zerotape, zerotape, new GLRenderDataTexture(tapetex)); tapepointbuf = items.LastBuffer(); // keep buffer for refill ritape.ElementBuffer = items.NewBuffer(); // empty buffer for element index for now ritape.Visible = false; // until its filled, not visible (important, we don't want render to execute unless its been fully set up below) rObjects.Add(tapeshader, name + "-tape", ritape); // add render to object list // now the stars starposbuf = items.NewBuffer(); // where we hold the vertexes for the suns, used by renderer and by finder // the colour index of the stars is selected by the w parameter of the world position vertexes. // we autoscale to make them bigger at greater distances from eye sunvertex = new GLPLVertexShaderModelCoordWorldAutoscale(new Color[] { Color.Yellow, Color.FromArgb(255, 230, 230, 1) }, autoscale: 30, autoscalemin: 1, autoscalemax: 2, useeyedistance: false); sunshader = new GLShaderPipeline(sunvertex, new GLPLStarSurfaceFragmentShader()); items.Add(sunshader); var shape = GLSphereObjectFactory.CreateSphereFromTriangles(2, sunsize); GLRenderState rt = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear rt.DepthTest = depthtest; rt.DepthClamp = true; renderersun = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, rt, shape, starposbuf, 0, null, 0, 1); renderersun.Visible = false; // until its filled, not visible rObjects.Add(sunshader, name + "-suns", renderersun); // find compute var geofind = new GLPLGeoShaderFindTriangles(bufferfindresults, 16); findshader = items.NewShaderPipeline(null, sunvertex, null, null, geofind, null, null, null); rifind = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, GLRenderState.Tri(), shape, starposbuf, ic: 0, seconddivisor: 1); // Sun names, handled by textrenderer textrenderer = new GLBitmaps(name + "-text", rObjects, BitMapSize, depthtest: depthtest, cullface: false); items.Add(textrenderer); }