protected static void ParseVertex(string line, ref MeshG m) { string[] components = line.Split(new char[] { ' ' }); //all components are needed position normal color if (components.Length != 9) { return; } float x = float.Parse(components[0]); float y = float.Parse(components[1]); float z = float.Parse(components[2]); float nx = float.Parse(components[3]); float ny = float.Parse(components[4]); float nz = float.Parse(components[5]); float r = float.Parse(components[6]); float g = float.Parse(components[7]); float b = float.Parse(components[8]); m.Vertices.Add(x); m.Vertices.Add(y); m.Vertices.Add(z); m.Normals.Add(nx); m.Normals.Add(ny); m.Normals.Add(nz); m.Colors.Add(r); m.Colors.Add(g); m.Colors.Add(b); }
public async Task <MeshG> Generate() { return(await Task.Run <MeshG>(() => { MeshG m = new MeshG(); CreateMesh(ref m); return m; })); }
public static void WriteMeshToFile(MeshG m, string path) { if (m == null) { return; } StringBuilder builder = new StringBuilder(); builder.AppendLine("vertices"); for (int i = 0; i < m.Vertices.Count - 2; i += 3) { string line = ""; float x = m.Vertices[i]; float r = m.Colors[i]; float nx = m.Normals[i]; float y = m.Vertices[i + 1]; float g = m.Colors[i + 1]; float ny = m.Normals[i + 1]; float z = m.Vertices[i + 2]; float b = m.Colors[i + 2]; float nz = m.Normals[i + 2]; //each vertice line contains the following x y z nx ny nz r g b //or basically the position normal color //they are all floats line = x + " " + y + " " + z + " " + nx + " " + ny + " " + nz + " " + r + " " + g + " " + b; builder.AppendLine(line); } builder.AppendLine("triangles"); //each line corresponds to a triangle //with each: index(v1) index2(v2) index3(v3) //triangles are CW orientation //all values are uints for (int i = 0; i < m.Triangles.Count - 2; i += 3) { string line = ""; uint idx1 = m.Triangles[i]; uint idx2 = m.Triangles[i + 1]; uint idx3 = m.Triangles[i + 2]; line = idx1 + " " + idx2 + " " + idx3; builder.AppendLine(line); } File.WriteAllText(path, builder.ToString()); }
//Generates the Triangles / Indices protected void CreateTriangles(ref MeshG m, ref List <Vector3f> points) { TriangleCount = 0; Triangulator trify = new Triangulator(); List <Vertex> vertices = new List <Vertex>(); foreach (Vector3f p in points) { vertices.Add(new Vertex(p.x, p.y)); } List <Triad> triads = trify.Triangulation(vertices); TriangleCount = triads.Count; foreach (Triad t in triads) { Vector3f a = points[t.a]; Vector3f b = points[t.b]; Vector3f c = points[t.c]; //due to how the triangle flipping is done in the triangulation part //it does not guarantee //triangles in the proper facing directions //therefore we make sure the ordering of the indices //is proper so all triangles face the same direction float ab = a.Cross2D(b); float bc = b.Cross2D(c); float ac = c.Cross2D(a); float sum = (ab + bc + ac) * 0.5f; if (sum <= 0) { m.Triangles.Add((uint)t.a); m.Triangles.Add((uint)t.b); m.Triangles.Add((uint)t.c); } else { m.Triangles.Add((uint)t.c); m.Triangles.Add((uint)t.b); m.Triangles.Add((uint)t.a); } } }
protected static void ParseTriangle(string line, ref MeshG m) { string[] components = line.Split(new char[] { ' ' }); if (components.Length != 3) { return; } uint idx = uint.Parse(components[0]); uint idx2 = uint.Parse(components[1]); uint idx3 = uint.Parse(components[2]); m.Triangles.Add(idx); m.Triangles.Add(idx2); m.Triangles.Add(idx3); }
public static MeshG ParseMeshString(string data) { MeshG m = new MeshG(); string[] lines = data.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); bool inVerts = false; bool inTriangles = false; for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (line.ToLower().Equals("vertices")) { inVerts = true; inTriangles = false; continue; } else if (line.ToLower().Equals("triangles")) { inVerts = false; inTriangles = true; continue; } if (inVerts) { ParseVertex(line, ref m); } else if (inTriangles) { ParseTriangle(line, ref m); } } return(m); }
//This is what actually creates the mesh protected void CreateMesh(ref MeshG m) { float d2 = 2.0f / (img.Width - 1); float d3 = 2.0f / (img.Height - 1); float cx = (img.Width - 1) * 0.5f; float cy = (img.Height - 1) * 0.5f; List <Vector3f> points = new List <Vector3f>(); float?lastPixel = null; for (int u = 0; u < img.Height; u++) { lastPixel = null; for (int v = 0; v < img.Width; v++) { Color c = Sampler.Sample(img, new Point(v, u)); float g = (float)(c.R + c.G + c.B) / 3.0f; Vector3f p = new Vector3f(0, 0, 0); //store the index for faster processing of triangle generation p.index = points.Count; p.color = c; p.x = v; p.y = u; if (lastPixel == null) { lastPixel = g; points.Add(p); } else { float len = Math.Abs(g - lastPixel.Value); bool lengthFit = (u == 0 || u == img.Height - 1); bool heightFit = (v == 0 || v == img.Width - 1); if (len > Tolerance || lengthFit || heightFit) { lastPixel = g; points.Add(p); } } } } //create triangles while flat still //it just makes it easier CreateTriangles(ref m, ref points); //Displace the points if necessary if (UseDisplacement) { Displace(points); } //small optimization float rgbM = 1.0f / 255.0f; //Colors, points, and normals share the same amount of data for (int i = 0; i < points.Count; i++) { Vector3f p = points[i]; Color c = p.color; m.Colors.Add((float)c.R * rgbM); m.Colors.Add((float)c.G * rgbM); m.Colors.Add((float)c.B * rgbM); //Convert to sphere coordinates if needed if (Sphererize) { //move to center p.x -= cx; p.y -= cy; VectorUtils.SpherePoint(p, 1.0f, d2, d3); } m.Vertices.Add(p.x); m.Vertices.Add(p.y); m.Vertices.Add(p.z); Vector3f normal = p.Normalize(); m.Normals.Add(normal.x); m.Normals.Add(normal.y); m.Normals.Add(normal.z); } }