/// <summary>Create a point cloud plot</summary> private ChartGfxPiece CreatePointPlot(RangeI idx_range) { var n = idx_range.Sizei; // Resize the geometry buffers m_vbuf.Resize(n); m_ibuf.Resize(n); m_nbuf.Resize(1); // Create the vertex/index data var col = Options.Colour; var x_range = RangeF.Invalid; for (int i = 0, iend = n; i != iend; ++i) { var pt = m_data[i + idx_range.Begi]; m_vbuf[i] = new View3d.Vertex(new v4((float)pt.xf, (float)pt.yf, 0f, 1f), col); m_ibuf[i] = (ushort)i; x_range.Grow(pt.xf); } // Create a nugget for the points using the sprite shader { var mat = View3d.Material.New(); mat.m_diff_tex = View3d.Texture.FromStock((View3d.EStockTexture)Options.PointStyle)?.Handle ?? IntPtr.Zero; mat.Use(View3d.ERenderStep.ForwardRender, View3d.EShaderGS.PointSpritesGS, $"*PointSize {{{Options.PointSize} {Options.PointSize}}} *Depth {{{false}}}"); m_nbuf[0] = new View3d.Nugget(View3d.ETopo.PointList, View3d.EGeom.Vert | View3d.EGeom.Colr | View3d.EGeom.Tex0, mat: mat); } // Create the graphics var gfx = new View3d.Object($"{Name}-[{idx_range.Beg},{idx_range.End})", 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray(), Id); return(new ChartGfxPiece(gfx, x_range)); }
/// <summary>Create a step line plot</summary> private ChartGfxPiece CreateStepLinePlot(RangeI idx_range) { var n = idx_range.Sizei; // Resize the geometry buffers m_vbuf.Resize(2 * n); m_ibuf.Resize(2 * n + (Options.PointsOnLinePlot ? n : 0)); m_nbuf.Resize(1 + (Options.PointsOnLinePlot ? 1 : 0)); // Create the vertex/index data int vert = 0, indx = 0; var col = Options.Colour; var x_range = RangeF.Invalid; for (int i = 0, iend = Math.Min(n + 1, m_data.Count - idx_range.Begi); i != iend; ++i) { // Get the point and the next point var j = i + idx_range.Begi; var pt = m_data[j]; var pt_r = j + 1 != m_data.Count ? m_data[j + 1] : pt; var v = vert; m_vbuf[vert++] = new View3d.Vertex(new v4((float)pt.xf, (float)pt.yf, 0f, 1f), col); m_vbuf[vert++] = new View3d.Vertex(new v4((float)pt_r.xf, (float)pt.yf, 0f, 1f), col); m_ibuf[indx++] = (ushort)(v + 0); m_ibuf[indx++] = (ushort)(v + 1); x_range.Grow(pt.xf); } // Create a nugget for the list strip using the thick line shader { var mat = View3d.Material.New(); mat.Use(View3d.ERenderStep.ForwardRender, View3d.EShaderGS.ThickLineListGS, $"*LineWidth {{{Options.LineWidth}}}"); m_nbuf[0] = new View3d.Nugget(View3d.ETopo.LineStrip, View3d.EGeom.Vert | View3d.EGeom.Colr, 0, (uint)vert, 0, (uint)indx, View3d.ENuggetFlag.None, false, mat); } // Create a nugget for the points (if visible) if (Options.PointsOnLinePlot) { // Add indices for the points var i0 = indx; for (int i = 0, iend = n; i != iend; ++i) { m_ibuf[indx++] = (ushort)(i * 2); } var mat = View3d.Material.New(); mat.m_diff_tex = View3d.Texture.FromStock((View3d.EStockTexture)Options.PointStyle)?.Handle ?? IntPtr.Zero; mat.Use(View3d.ERenderStep.ForwardRender, View3d.EShaderGS.PointSpritesGS, $"*PointSize {{{Options.PointSize} {Options.PointSize}}} *Depth {{{false}}}"); m_nbuf[1] = new View3d.Nugget(View3d.ETopo.PointList, View3d.EGeom.Vert | View3d.EGeom.Colr | View3d.EGeom.Tex0, 0, (uint)vert, (uint)i0, (uint)indx, View3d.ENuggetFlag.None, false, mat); } // Create the graphics var gfx = new View3d.Object($"{Name}-[{idx_range.Beg},{idx_range.End})", 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray(), Id); return(new ChartGfxPiece(gfx, x_range)); }
/// <summary>Create a line plot</summary> private ChartGfxPiece CreateLinePlot(RangeI idx_range) { var n = idx_range.Sizei; if (n == 0) { throw new ArgumentException($"{nameof(ChartControl)}.{nameof(CreateLinePlot)} Index range must not be empty"); } // Resize the geometry buffers m_vbuf.Resize(n); m_ibuf.Resize(n); m_nbuf.Resize(1 + (Options.PointsOnLinePlot ? 1 : 0)); // Create the vertex/index data int vert = 0, indx = 0; var col = Options.Colour; var x_range = RangeF.Invalid; for (int i = 0, iend = Math.Min(n, m_data.Count - idx_range.Begi); i != iend; ++i) { var j = i + idx_range.Begi; var pt = m_data[j]; var v = vert; m_vbuf[vert++] = new View3d.Vertex(new v4((float)pt.xf, (float)pt.yf, 0f, 1f), col); m_ibuf[indx++] = (ushort)(v); x_range.Grow(pt.xf); } // Create a nugget for the list strip using the thick line shader { var mat = View3d.Material.New(); mat.Use(View3d.ERenderStep.ForwardRender, View3d.EShaderGS.ThickLineListGS, $"*LineWidth {{{Options.LineWidth}}}"); m_nbuf[0] = new View3d.Nugget(View3d.ETopo.LineStrip, View3d.EGeom.Vert | View3d.EGeom.Colr, mat: mat); } // Create a nugget for the points (if visible) if (Options.PointsOnLinePlot) { var mat = View3d.Material.New(); mat.m_diff_tex = View3d.Texture.FromStock((View3d.EStockTexture)Options.PointStyle)?.Handle ?? IntPtr.Zero; mat.Use(View3d.ERenderStep.ForwardRender, View3d.EShaderGS.PointSpritesGS, $"*PointSize {{{Options.PointSize} {Options.PointSize}}} *Depth {{{false}}}"); m_nbuf[1] = new View3d.Nugget(View3d.ETopo.PointList, View3d.EGeom.Vert | View3d.EGeom.Colr | View3d.EGeom.Tex0, range_overlaps: true, mat: mat); } // Create the graphics var gfx = new View3d.Object($"{Name}-[{idx_range.Beg},{idx_range.End})", 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray(), Id); return(new ChartGfxPiece(gfx, x_range)); }
/// <summary>Callback for creating the "net" object</summary> private void CreateOnlyCB(IntPtr ctx, int vcount, int icount, int ncount, View3d.Vertex[] verts, ushort[] indices, View3d.Nugget[] nuggets, out int new_vcount, out int new_icount, out int new_ncount) { new_vcount = 0; new_icount = 0; new_ncount = 0; for (int i = 0; i != 10; ++i) { verts[new_vcount++] = new View3d.Vertex(new v4(i, 0, 0, 1f)); verts[new_vcount++] = new View3d.Vertex(new v4(0, 0, 9 - i, 1f)); indices[new_icount++] = (ushort)(new_vcount - 2); indices[new_icount++] = (ushort)(new_vcount - 1); } nuggets[new_ncount++] = new View3d.Nugget(View3d.ETopo.LineList, View3d.EGeom.Vert); }
protected override void UpdateGfxCore() { var snr_colour = Settings.Colour.ToArgbU(); var width = Settings.GraphicsWidth * Chart.XAxis.Span; var attr = Settings.Attribute; var power = Settings.Power; var count = Levels.Count; if (count <= 1) { Gfx = null; return; } // Create graphics for the support and resistance data m_vbuf.Resize(count * 2); m_ibuf.Resize(count * 2); m_nbuf.Resize(1); var values = attr == EAttribute.MedianCount ? Levels.Select(x => x.Median).Normalise() : attr == EAttribute.TradeVolume ? Levels.Select(x => x.Volume).Normalise() : attr == EAttribute.TimeAtLevel ? Levels.Select(x => x.Time).Normalise() : null; int l = 0, v = 0, i = 0; foreach (var value in values) { var x = (float)(Math.Pow(value, power) * width); var y = (float)(Levels[l].Price); ++l; m_ibuf[i++] = (ushort)v; m_vbuf[v++] = new View3d.Vertex(new v4(-x, y, 0, 1)); m_ibuf[i++] = (ushort)v; m_vbuf[v++] = new View3d.Vertex(new v4(0, y, 0, 1)); } m_nbuf[0] = new View3d.Nugget(View3d.EPrim.TriStrip, View3d.EGeom.Vert, 0, (uint)v, 0, (uint)i, !Bit.AllSet(snr_colour, 0xFF000000)); // Create the graphics Gfx = new View3d.Object(Name, snr_colour, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray()); base.UpdateGfxCore(); }
protected override void UpdateGfxCore() { var line_colour = (Selected ? Settings.Colour.Lerp(Color.Gray, 0.2f) : Settings.Colour).ToArgbU(); var region_colour = (Selected ? Settings.RegionColour.Lerp(Color.Gray, 0.2f) : Settings.RegionColour).ToArgbU(); var width = (float)Chart.XAxis.Span; // Create graphics for the horizontal line m_vbuf.Resize(2 + (Level.WidthPips != 0 ? 4 : 0)); m_ibuf.Resize(2 + (Level.WidthPips != 0 ? 6 : 0)); m_nbuf.Resize(1 + (Level.WidthPips != 0 ? 1 : 0)); m_vbuf[0] = new View3d.Vertex(new v4(0, 0, 0, 1), line_colour); m_vbuf[1] = new View3d.Vertex(new v4(width, 0, 0, 1), line_colour); m_ibuf[0] = 0; m_ibuf[1] = 1; var mat = new View3d.Material(shader: View3d.EShader.ThickLineListGS, shader_data: new int[4] { Settings.LineWidth, 0, 0, 0 }); m_nbuf[0] = new View3d.Nugget(View3d.EPrim.LineList, View3d.EGeom.Vert | View3d.EGeom.Colr, 0, 2, 0, 2, !Bit.AllSet(line_colour, 0xFF000000), mat); if (Level.WidthPips != 0) { var hh = (float)(Instrument.PriceData.PipSize * Level.WidthPips / 2.0); m_vbuf[2] = new View3d.Vertex(new v4(0, -hh, 0, 1), region_colour); m_vbuf[3] = new View3d.Vertex(new v4(width, -hh, 0, 1), region_colour); m_vbuf[4] = new View3d.Vertex(new v4(0, +hh, 0, 1), region_colour); m_vbuf[5] = new View3d.Vertex(new v4(width, +hh, 0, 1), region_colour); m_ibuf[2] = 2; m_ibuf[3] = 3; m_ibuf[4] = 5; m_ibuf[5] = 5; m_ibuf[6] = 4; m_ibuf[7] = 2; m_nbuf[1] = new View3d.Nugget(View3d.EPrim.TriList, View3d.EGeom.Vert | View3d.EGeom.Colr, 2, 6, 2, 8, !Bit.AllSet(region_colour, 0xFF000000)); } // Create the graphics Gfx = new View3d.Object(Name, 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray()); base.UpdateGfxCore(); }
protected override void UpdateGfxCore() { var line_colour = (Selected ? Settings.Colour.Lerp(Color.Gray, 0.5f) : Settings.Colour).ToArgbU(); var region_colour = (Selected ? Settings.RegionColour.Lerp(Color.Gray, 0.5f) : Settings.RegionColour).ToArgbU(); var region_height = Settings.RegionHeight; var width = (float)Chart.XAxis.Span; // Create graphics for the horizontal line m_vbuf.Resize(2 + (region_height != 0 ? 4 : 0)); m_ibuf.Resize(2 + (region_height != 0 ? 6 : 0)); m_nbuf.Resize(1 + (region_height != 0 ? 1 : 0)); m_vbuf[0] = new View3d.Vertex(new v4(0, 0, 0, 1), line_colour); m_vbuf[1] = new View3d.Vertex(new v4(width, 0, 0, 1), line_colour); m_ibuf[0] = 0; m_ibuf[1] = 1; m_nbuf[0] = new View3d.Nugget(View3d.EPrim.LineList, View3d.EGeom.Vert | View3d.EGeom.Colr, 0, 2, 0, 2); if (region_height != 0) { var half_height = (float)(Instrument.PriceData.PipSize * region_height / 2.0); m_vbuf[2] = new View3d.Vertex(new v4(0, -half_height, 0, 1), region_colour); m_vbuf[3] = new View3d.Vertex(new v4(width, -half_height, 0, 1), region_colour); m_vbuf[4] = new View3d.Vertex(new v4(0, +half_height, 0, 1), region_colour); m_vbuf[5] = new View3d.Vertex(new v4(width, +half_height, 0, 1), region_colour); m_ibuf[2] = 2; m_ibuf[3] = 3; m_ibuf[4] = 5; m_ibuf[5] = 5; m_ibuf[6] = 4; m_ibuf[7] = 2; m_nbuf[1] = new View3d.Nugget(View3d.EPrim.TriList, View3d.EGeom.Vert | View3d.EGeom.Colr, 2, 6, 2, 8, !Bit.AllSet(region_colour, 0xFF000000)); } // Create the graphics Gfx = new View3d.Object(Name, 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray()); base.UpdateGfxCore(); }
public FormView3d() { InitializeComponent(); m_view3d = new View3dControl { Name = "m_view3d", BorderStyle = BorderStyle.FixedSingle, Dock = DockStyle.Fill, }; Controls.Add(m_view3d); m_demo_objs = m_view3d.Window.CreateDemoScene(); m_view3d.Camera.ResetView(); m_view3d.Camera.Lookat(new v4(10f, 10f, 5f, 1f), v4.Origin, v4.YAxis); // Simple create object m_obj0 = new View3d.Object("*Box test FFFFFFFF {1 2 3}", false, null); m_obj0.O2P = m4x4.Transform(0.5f, -0.3f, 0.2f, new v4(-0.3f, 1.2f, 0.5f, 1f)); m_view3d.Window.AddObject(m_obj0); m_obj0.ShowNormals = true; m_view3d.Window.Diag.NormalsLength = 0.5f; m_view3d.Window.Diag.NormalsColour = Colour32.Yellow; // Create a texture and assign it to an object m_tex0 = new View3d.Texture(100, 100, new View3d.TextureOptions { GdiCompatible = true }); using (var tex = new View3d.Texture.Lock(m_tex0, discard: true)) { tex.Gfx.Clear(Color.DarkBlue); tex.Gfx.FillEllipse(Brushes.RoyalBlue, 10, 10, 80, 80); tex.Gfx.DrawString("Paul Rulz", SystemFonts.DefaultFont, Brushes.Black, new PointF(30, 40)); } m_view3d.Window.RestoreRT(); m_obj0.SetTexture(m_tex0); // Create object via callback m_obj1 = new View3d.Object("net", 0xFF0000FF, 20, 20, 1, CreateOnlyCB, null); m_view3d.Window.AddObject(m_obj1); // Create an object with a texture from a rendered scene m_obj2 = new View3d.Object("*Box Rt FFFFFFFF {0.7 0.9 0.4}", false, null); m_obj2.O2P = m4x4.Transform(-0.5f, 0.4f, 0.6f, new v4(0.5f, -0.2f, -0.3f, 1f)); m_view3d.Window.AddObject(m_obj2); // Create a texture and use it as a render target m_tex2 = new View3d.Texture(200, 200, new View3d.TextureOptions { Format = View3d.EFormat.DXGI_FORMAT_R8G8B8A8_UNORM, Mips = 1U, Filter = View3d.EFilter.D3D11_FILTER_MIN_MAG_MIP_LINEAR, AddrU = View3d.EAddrMode.D3D11_TEXTURE_ADDRESS_CLAMP, AddrV = View3d.EAddrMode.D3D11_TEXTURE_ADDRESS_CLAMP, BindFlags = View3d.EBindFlags.D3D11_BIND_SHADER_RESOURCE | View3d.EBindFlags.D3D11_BIND_RENDER_TARGET, MiscFlags = View3d.EResMiscFlags.NONE, ColourKey = 0, HasAlpha = false, GdiCompatible = false, DbgName = "Test RT", }); m_view3d.Paint += (s, a) => { // Make sure 'm_obj' is not rendered (because it uses the texture we're rendering to) m_view3d.Window.RemoveObject(m_obj2); m_view3d.Window.SetRT(m_tex2, null, false); m_view3d.Window.AddObject(m_obj2); }; m_obj2.SetTexture(m_tex2); // Create a gizmo for moving objects in the scene // Position it at the origin of m_obj0 and scale by 2 m_giz = new View3d.Gizmo(View3d.Gizmo.EMode.Scale, m_obj0.O2P * m4x4.Scale(0.1f, v4.Origin)); m_giz.Attach(m_obj0); m_giz.Moved += (s, a) => { m_status.SetStatusMessage(msg: "Gizmo", display_time: TimeSpan.FromSeconds(2)); }; m_view3d.Window.AddGizmo(m_giz); m_btn_translate.Click += (s, a) => m_giz.Mode = View3d.Gizmo.EMode.Translate; m_btn_rotate.Click += (s, a) => m_giz.Mode = View3d.Gizmo.EMode.Rotate; m_btn_scale.Click += (s, a) => m_giz.Mode = View3d.Gizmo.EMode.Scale; // Create an object from buffers created in C# { var verts = new View3d.Vertex[] { new View3d.Vertex(new v4(1f, 1f, 0f, 1f), 0xFFFF0000), new View3d.Vertex(new v4(2f, 0f, 0f, 1f), 0xFF00FF00), new View3d.Vertex(new v4(3f, 1f, 0f, 1f), 0xFF0000FF), }; var indcs = new ushort[] { 0, 1, 2 }; var nuggets = new View3d.Nugget[] { new View3d.Nugget(View3d.ETopo.TriList, View3d.EGeom.Vert | View3d.EGeom.Colr) }; m_obj3 = new View3d.Object("Obj3", 0xFFFFFFFF, 3, 3, 1, verts, indcs, nuggets, null); m_view3d.Window.AddObject(m_obj3); } }
protected override void UpdateGfxCore() { // Generate the EMA line for the visible area of the chart var ema_colour = Settings.ColourEMA.ToArgbU(); var bol_colour = Settings.ColourBollingerBands.ToArgbU(); // Get the visible X axis range, and convert it to positive indices var first_idx = Instrument.FirstIdx; var rng = Instrument.IndexRange((int)(Chart.XAxis.Min - 1), (int)(Chart.XAxis.Max + 1)); rng.Beg = Maths.Clamp(rng.Beg - first_idx, 0, m_ema.Count); rng.End = Maths.Clamp(rng.End - first_idx, 0, m_ema.Count); if (rng.Counti == 0) { Gfx = null; return; } var count = rng.Counti; m_vbuf.Resize(count); m_ibuf.Resize((count - 1) * 2); m_nbuf.Resize(1); // EMA model var v = 0; var i = 0; foreach (var candle_index in rng) { var ema = m_ema[(int)candle_index]; m_vbuf[v++] = new View3d.Vertex(new v4(candle_index + first_idx, (float)ema.Mean, ChartUI.Z.Indicators, 1f), ema_colour); } for (var vi = 0; i != m_ibuf.Count; ++vi) { m_ibuf[i++] = (ushort)(vi); m_ibuf[i++] = (ushort)(vi + 1); } var mat = new View3d.Material(shader: View3d.EShader.ThickLineListGS, shader_data: new[] { Settings.Width, 0, 0, 0 }); m_nbuf[0] = new View3d.Nugget(View3d.EPrim.LineList, View3d.EGeom.Vert | View3d.EGeom.Colr, 0, (uint)v, 0, (uint)i, false, mat); // Add geometry for Bollinger bands if (Settings.BollingerBands != 0) { m_vbuf.Resize(m_vbuf.Count + 2 * count); m_ibuf.Resize(m_ibuf.Count + 2 * count); m_nbuf.Resize(m_nbuf.Count + 2); // Lower/Upper band foreach (var candle_index in rng) { var ema = m_ema[(int)candle_index]; m_vbuf[v++] = new View3d.Vertex(new v4(candle_index + first_idx, (float)(ema.Mean - Settings.BollingerBands * ema.PopStdDev), ChartUI.Z.Indicators, 1f), bol_colour); m_ibuf[i++] = (ushort)(v - 1); } m_nbuf[1] = new View3d.Nugget(View3d.EPrim.LineStrip, View3d.EGeom.Vert | View3d.EGeom.Colr, (uint)(v - count), (uint)v, (uint)(i - count), (uint)i); foreach (var candle_index in rng) { var ema = m_ema[(int)candle_index]; m_vbuf[v++] = new View3d.Vertex(new v4(candle_index + first_idx, (float)(ema.Mean + Settings.BollingerBands * ema.PopStdDev), ChartUI.Z.Indicators, 1f), bol_colour); m_ibuf[i++] = (ushort)(v - 1); } m_nbuf[2] = new View3d.Nugget(View3d.EPrim.LineStrip, View3d.EGeom.Vert | View3d.EGeom.Colr, (uint)(v - count), (uint)v, (uint)(i - count), (uint)i); } // Create the graphics Gfx = new View3d.Object(Name, 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray()); base.UpdateGfxCore(); }
/// <summary>Create a bar graph</summary> private ChartGfxPiece CreateBarPlot(RangeI idx_range) { var n = idx_range.Sizei; // Resize the geometry buffers m_vbuf.Resize(4 * n); m_ibuf.Resize(6 * n); m_nbuf.Resize(1); // Create the vertex/index data int vidx = 0, iidx = 0, nidx = 0; var col = Options.Colour; var lwidth = (0.0 - Options.BarHorizontalAlignment) * Options.BarWidth; var rwidth = (1.0 - Options.BarHorizontalAlignment) * Options.BarWidth; var x_range = RangeF.Invalid; for (int i = 0; i != n; ++i) { // Get the points on either side of 'i' var j = i + idx_range.Begi; var pt_l = j != 0 ? m_data[j - 1] : null; var pt = m_data[j]; var pt_r = j + 1 != m_data.Count ? m_data[j + 1] : null; // Get the distance to the left and right of 'pt.x' var l = pt_l != null ? lwidth * (pt_l.xf - pt.xf) : 0; var r = pt_r != null ? rwidth * (pt_r.xf - pt.xf) : 0; if (j == 0 && j + 1 != m_data.Count && pt_r != null) { l = -lwidth * (pt_r.xf - pt.xf); } if (j + 1 == m_data.Count && j != 0 && pt_l != null) { r = -rwidth * (pt_l.xf - pt.xf); } var v = vidx; m_vbuf[vidx++] = new View3d.Vertex(new v4((float)(pt.xf + r), (float)(pt.yf >= 0f ? pt.yf : 0f), 0f, 1f), col); m_vbuf[vidx++] = new View3d.Vertex(new v4((float)(pt.xf - l), (float)(pt.yf >= 0f ? pt.yf : 0f), 0f, 1f), col); m_vbuf[vidx++] = new View3d.Vertex(new v4((float)(pt.xf - l), (float)(pt.yf >= 0f ? 0f : pt.yf), 0f, 1f), col); m_vbuf[vidx++] = new View3d.Vertex(new v4((float)(pt.xf + r), (float)(pt.yf >= 0f ? 0f : pt.yf), 0f, 1f), col); m_ibuf[iidx++] = (ushort)(v + 0); m_ibuf[iidx++] = (ushort)(v + 1); m_ibuf[iidx++] = (ushort)(v + 2); m_ibuf[iidx++] = (ushort)(v + 2); m_ibuf[iidx++] = (ushort)(v + 3); m_ibuf[iidx++] = (ushort)(v + 0); x_range.Grow(pt.xf); } // Create a nugget for the tri list uint v0 = 0, v1 = (uint)vidx; uint i0 = 0, i1 = (uint)iidx; var flags = col.A != 0xff ? View3d.ENuggetFlag.GeometryHasAlpha : View3d.ENuggetFlag.None; m_nbuf[nidx++] = new View3d.Nugget(View3d.ETopo.TriList, View3d.EGeom.Vert | View3d.EGeom.Colr, v0, v1, i0, i1, flags); // Add the bar 'tops' if (Options.LinesOnBarPlot) { // Use line strips m_vbuf.Resize(m_vbuf.Count + n * 2); m_ibuf.Resize(m_ibuf.Count + n * 2); m_nbuf.Resize(m_nbuf.Count + 1); var line_colour = col.Darken(0.25f).Alpha(1f); for (int i = 0; i != n; ++i) { var vert0 = m_vbuf[i * 4 + 0]; var vert1 = m_vbuf[i * 4 + 1]; var v = vidx; m_vbuf[vidx++] = new View3d.Vertex(vert0.m_pos, line_colour); m_vbuf[vidx++] = new View3d.Vertex(vert1.m_pos, line_colour); m_ibuf[iidx++] = (ushort)(v + 0); m_ibuf[iidx++] = (ushort)(v + 1); } // Create a nugget for the bar tops v0 = v1; v1 += (uint)(n * 2); i0 = i1; i1 += (uint)(n * 2); m_nbuf[nidx++] = new View3d.Nugget(View3d.ETopo.LineList, View3d.EGeom.Vert | View3d.EGeom.Colr, v0, v1, i0, i1); } // Create the graphics var gfx = new View3d.Object($"{Name}-[{idx_range.Beg},{idx_range.End})", 0xFFFFFFFF, m_vbuf.Count, m_ibuf.Count, m_nbuf.Count, m_vbuf.ToArray(), m_ibuf.ToArray(), m_nbuf.ToArray(), Id); return(new ChartGfxPiece(gfx, x_range)); }