internal int[][] GenerateFacesInternal(MeshGenerator g) { if (IsEdge) { return(new int[0][]); } // Normal case { var below = g.Allocated[RelativeId(0, 1)]; var right = g.Allocated[RelativeId(1, 0)]; var diagonal = g.Allocated[RelativeId(1, 1)]; var edges = new List <int[]>(); // Simple case for (var row = 0; row < Size; row += Zoom) { for (var col = 0; col < Size; col += Zoom) { var v1 = VertexIndex(col, row); if (col + Zoom == Size) { // to right if (row + Zoom == Size) { // diagonal if (DrawDiagonal) { if (false) // (Zoom == right.Zoom && Zoom == below.Zoom) { var right_row = right.Zoom * (row / right.Zoom); var v2 = right.VertexIndex(0, right_row); var below_col = below.Zoom * (col / below.Zoom); var v3 = below.VertexIndex(below_col, 0); var v4 = diagonal.VertexIndex(0, 0); edges.Add(new[] { v1, v3, v2 }); edges.Add(new[] { v2, v3, v4 }); } else { // Compare right if (Zoom == right.Zoom) { edges.Add(new[] { v1, diagonal.VertexIndex(0, 0), right.VertexIndex(0, Size - right.Zoom) }); } else if (Zoom < right.Zoom && below.IsVertexIndex(col, 0)) { var v2 = below.VertexIndex(col, 0); var v3 = diagonal.VertexIndex(0, 0); edges.Add(new[] { v1, v2, v3 }); } else if (Zoom > right.Zoom) { for (var right_row = row; right_row < Size - right.Zoom; right_row += right.Zoom) { edges.Add(new[] { v1, right.VertexIndex(0, right_row + right.Zoom), right.VertexIndex(0, right_row) }); } edges.Add(new[] { v1, diagonal.VertexIndex(0, 0), right.VertexIndex(0, Size - right.Zoom) }); } // Compare below if (Zoom == below.Zoom) { edges.Add(new[] { v1, below.VertexIndex(Size - below.Zoom, 0), diagonal.VertexIndex(0, 0) }); } else if (Zoom < below.Zoom && right.IsVertexIndex(0, row)) { var v2 = right.VertexIndex(0, row); var v3 = diagonal.VertexIndex(0, 0); edges.Add(new[] { v1, v3, v2 }); } else if (Zoom > below.Zoom) { for (var below_col = col; below_col < Size - below.Zoom; below_col += below.Zoom) { edges.Add(new[] { v1, below.VertexIndex(below_col, 0), below.VertexIndex(below_col + below.Zoom, 0) }); } edges.Add(new[] { v1, below.VertexIndex(Size - below.Zoom, 0), diagonal.VertexIndex(0, 0) }); } } } } else { // to right only, same zoom if (Zoom == right.Zoom) { if (DrawRight1) { var v2 = right.VertexIndex(0, row); var v3 = VertexIndex(col, row + Zoom); var v4 = right.VertexIndex(0, row + Zoom); edges.Add(new[] { v1, v3, v2 }); edges.Add(new[] { v2, v3, v4 }); } } else if (Zoom > right.Zoom) { // right only, spacing getting tighter if (DrawRight2) { var v2 = VertexIndex(col, row + Zoom); var other_vertices = new List <int>(Zoom / right.Zoom + 1); for (var i = row; i < row + Zoom; i += right.Zoom) { other_vertices.Add(right.VertexIndex(0, i)); } other_vertices.Add(row + Zoom == Size ? diagonal.VertexIndex(0, 0) : right.VertexIndex(0, row + Zoom)); for (var i = 0; i < other_vertices.Count - 1; i++) { edges.Add(new[] { v1, other_vertices[i + 1], other_vertices[i] }); } edges.Add(new[] { v1, v2, other_vertices[other_vertices.Count - 1] }); } } else if (Zoom < right.Zoom) { // right only, spacing getting looser if (DrawRight3) { var v2 = VertexIndex(col, row + Zoom); var other_row = right.Zoom * (row / right.Zoom); if (row == other_row) { var v3 = right.VertexIndex(0, row); var v4 = other_row + right.Zoom == Size?diagonal.VertexIndex(0, 0) : right.VertexIndex(0, other_row + right.Zoom); edges.Add(new[] { v1, v4, v3 }); edges.Add(new[] { v1, v2, v4 }); } else { var v3 = other_row + right.Zoom == Size?diagonal.VertexIndex(0, 0) : right.VertexIndex(0, other_row + right.Zoom); edges.Add(new[] { v1, v2, v3 }); } } } else { System.Diagnostics.Debug.Assert(false, $"invalid pair of zooms: {Zoom} vs {right.Zoom}"); } } } else { // Below if (row + Zoom == Size) { // below only, same zoom if (Zoom == below.Zoom) { if (DrawDown1) { var v2 = VertexIndex(col + Zoom, row); var v3 = below.VertexIndex(col, 0); var v4 = below.VertexIndex(col + Zoom, 0); edges.Add(new[] { v1, v3, v2 }); edges.Add(new[] { v2, v3, v4 }); } } else if (Zoom > below.Zoom) { // below only, spacing getting tighter if (DrawDown2) { var v2 = VertexIndex(col + Zoom, row); var other_vertices = new List <int>(Zoom / below.Zoom + 1); for (var i = col; i < col + Zoom; i += below.Zoom) { other_vertices.Add(below.VertexIndex(i, 0)); } other_vertices.Add(col + Zoom == Size ? diagonal.VertexIndex(0, 0) : below.VertexIndex(col + Zoom, 0)); for (var i = 0; i < other_vertices.Count - 1; i++) { edges.Add(new[] { v1, other_vertices[i], other_vertices[i + 1] }); } edges.Add(new[] { v1, other_vertices[other_vertices.Count - 1], v2 }); } } else if (Zoom < below.Zoom) { // below only, spacing getting looser if (DrawDown3) { var v2 = VertexIndex(col + Zoom, row); var other_col = below.Zoom * (col / below.Zoom); if (col == other_col) { var v3 = below.VertexIndex(col, 0); var v4 = other_col + below.Zoom == Size?diagonal.VertexIndex(0, 0) : below.VertexIndex(other_col + below.Zoom, 0); edges.Add(new[] { v1, v3, v4 }); edges.Add(new[] { v1, v4, v2 }); } else { var v3 = other_col + below.Zoom == Size?diagonal.VertexIndex(0, 0) : below.VertexIndex(other_col + below.Zoom, 0); edges.Add(new[] { v1, v3, v2 }); } } } else { System.Diagnostics.Debug.Assert(false, $"invalid pair of zooms: {Zoom} vs {below.Zoom}"); } } else { // inside center patch if (DrawCenter) { var v2 = VertexIndex(col + Zoom, row); var v3 = VertexIndex(col, row + Zoom); var v4 = VertexIndex(col + Zoom, row + Zoom); edges.Add(new[] { v1, v3, v2 }); edges.Add(new[] { v2, v3, v4 }); } } } } } return(edges.ToArray()); } }
public void WritePlyFile(InMemoryTerrainManager manager, string path, bool?writeASCII = null, bool?writeColorVertices = null) { if (Allocated == null) { return; } var ascii = writeASCII.HasValue ? writeASCII.Value : WriteASCII; var color = writeColorVertices.HasValue ? writeColorVertices.Value : WriteColorVertices; var vertex_count = EnumerateVertices().Count(); var face_count = EnumerateFaces().Count(); var file = File.Open(path, FileMode.Create); var sw = new StreamWriter(file); using (var bw = new BinaryWriter(file)) { using (var ms = new MemoryStream(500)) using (var msw = new StreamWriter(ms)) { msw.WriteLine("ply"); msw.WriteLine(ascii ? "format ascii 1.0" : "format binary_little_endian 1.0"); msw.WriteLine($"element vertex {vertex_count}"); msw.WriteLine("property double x"); msw.WriteLine("property double y"); msw.WriteLine("property double z"); if (color) { msw.WriteLine("property uchar red"); msw.WriteLine("property uchar green"); msw.WriteLine("property uchar blue"); } msw.WriteLine($"element face {face_count}"); msw.WriteLine("property list uchar int vertex_index"); msw.WriteLine("end_header"); msw.Flush(); var bytes = ms.GetBuffer(); if (ascii) { for (var i = 0; i < ms.Length; i++) { sw.Write((char)bytes[i]); } } else { bw.Write(bytes, 0, (int)ms.Length); } } sw.Flush(); bw.Flush(); var count_vertices = 0; // testing math.Vector3d offset; { var vo = Allocated.Values.First(); var off = vo.VertexOffsets[0]; offset = MeshGenerator.LineSampleToMoonME(manager, vo.Line + off.Y, vo.Sample + off.X); } // Write the vertices foreach (var m in Allocated.Values) { var colorFromTile = m.Color; foreach (var vertex_offset in m.VertexOffsets) { var sample = m.Sample + vertex_offset.X; var line = m.Line + vertex_offset.Y; var pos = MeshGenerator.LineSampleToMoonME(manager, line, sample); // Testing pos = pos - offset; count_vertices++; if (ascii) { sw.Write($"{pos.X} {pos.Y} {pos.Z}"); if (color) { sw.WriteLine($" {colorFromTile.R} {colorFromTile.G} {colorFromTile.B}"); } } else { bw.Write(pos.X); bw.Write(pos.Y); bw.Write(pos.Z); if (color) { bw.Write(colorFromTile.R); bw.Write(colorFromTile.G); bw.Write(colorFromTile.B); } } } } System.Diagnostics.Debug.Assert(count_vertices == vertex_count); // write the faces if (ascii) { foreach (var face in EnumerateFaces()) { sw.Write(face.Length); for (var i = 0; i < face.Length; i++) { var idx = face[i]; System.Diagnostics.Debug.Assert(idx >= 0 && idx < vertex_count); sw.Write(' '); sw.Write(idx); } sw.WriteLine(); } } else { foreach (var face in EnumerateFaces()) { bw.Write((byte)face.Length); for (var i = 0; i < face.Length; i++) { var idx = face[i]; System.Diagnostics.Debug.Assert(idx >= 0 && idx < vertex_count); bw.Write(idx); } } } bw.Flush(); sw.Flush(); } }