PlotlyScene.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Numerics;
  5. using System.Text;
  6. using Plotly;
  7. using Plotly.Types;
  8. using TRACES = Plotly.Box<Plotly.Types.ITracesProperty>;
  9. using VERTEX = SharpGLTF.Geometry.IVertexBuilder;
  10. namespace SharpGLTF
  11. {
  12. public class PlotlyScene
  13. {
  14. #region data
  15. private readonly List<TRACES> _Traces = new List<TRACES>();
  16. private readonly Dictionary<Object, int> mats = new Dictionary<Object, int>(); // materials to color mapping
  17. #endregion
  18. #region API
  19. public void AppendTriangles<TMaterial>(IEnumerable<(VERTEX A, VERTEX B, VERTEX C, TMaterial Material)> tris, Matrix4x4 xform, Func<TMaterial, int> materialColorFunc)
  20. {
  21. var trace = _CreateTrace(tris, xform, materialColorFunc);
  22. _Traces.Add(trace);
  23. }
  24. public Box<IPlotProperty> ToPlotProperties() { return Plot.traces(_Traces.ToArray()); }
  25. public Plot ToPlot()
  26. {
  27. var plot = ToPlotProperties();
  28. var layout = _CreateLayoutProperties();
  29. var document = new Plot(plot, layout);
  30. return document;
  31. }
  32. public string ToHtml()
  33. {
  34. Plot document = ToPlot();
  35. return document.Render().ToString();
  36. }
  37. #endregion
  38. #region core
  39. private static Box<IPlotProperty> _CreateLayoutProperties()
  40. {
  41. var xaxis = Scene.xaxis(Xaxis.color("red"));
  42. var yaxis = Scene.yaxis(Yaxis.color("green"));
  43. var zaxis = Scene.zaxis(Zaxis.color("blue"));
  44. var camera = Camera.up(Up.x(0), Up.y(1), Up.z(0));
  45. var scene = Layout.scene(Scene.Aspectmode.data(), Scene.camera(camera), xaxis, yaxis, zaxis);
  46. return Plot.layout
  47. (Layout.autosize(true)
  48. // , Layout.width(0)
  49. , Layout.height(920)
  50. // , Layout.margin(Margin.autoexpand(true))
  51. // , Layout.margin(Margin.pad(5))
  52. // , Layout.margin(Margin.t(5), Margin.b(5))
  53. , scene
  54. );
  55. }
  56. private TRACES _CreateTrace<TMaterial>(IEnumerable<(VERTEX A, VERTEX B, VERTEX C, TMaterial Material)> tris, Matrix4x4 xform, Func<TMaterial, int> materialColorFunc)
  57. {
  58. var vrts = new List<(Vector3 p, Vector3 n)>(); // vertex list
  59. var vrtm = new Dictionary<(Vector3 p, Vector3 n), int>(); // vertex sharing map
  60. var idxs = new List<(int, int, int)>(); // triangle indices
  61. var tric = new List<int>(); // face colors
  62. int _useSharedVertex(VERTEX v)
  63. {
  64. var g = v.GetGeometry();
  65. g.TryGetNormal(out Vector3 n);
  66. var item = (g.GetPosition(), n);
  67. if (vrtm.TryGetValue(item, out int idx)) return idx;
  68. idx = vrts.Count;
  69. vrts.Add(item);
  70. vrtm.Add(item, idx);
  71. return idx;
  72. }
  73. foreach (var (A, B, C, Material) in tris)
  74. {
  75. if (!mats.TryGetValue(Material, out int color))
  76. {
  77. mats[Material] = color = materialColorFunc(Material);
  78. }
  79. var ap = _useSharedVertex(A);
  80. var bp = _useSharedVertex(B);
  81. var cp = _useSharedVertex(C);
  82. idxs.Add((ap, bp, cp));
  83. tric.Add(color);
  84. }
  85. // create a Plotly Mesh3D from the previously filled lists.
  86. var mx = Mesh3d.x(vrts.Select(item => item.p.X));
  87. var my = Mesh3d.y(vrts.Select(item => item.p.Y));
  88. var mz = Mesh3d.z(vrts.Select(item => item.p.Z));
  89. var mi = Mesh3d.i(idxs.Select(item => item.Item1).ToArray());
  90. var mj = Mesh3d.j(idxs.Select(item => item.Item2).ToArray());
  91. var mk = Mesh3d.k(idxs.Select(item => item.Item3).ToArray());
  92. var mo = Mesh3d.opacity(1);
  93. var mc = Mesh3d.facecolor(tric.ToArray());
  94. return Traces.mesh3d(mx, my, mz, mi, mj, mk, mo, mc);
  95. }
  96. #endregion
  97. }
  98. }