private static void calculateAndSetNormalForTri(ref TriangleFace triangleFace, Mesh mesh) { //if the normal list is empty for this mesh or null - set it to be the same size //as the list of verts. we'll generate on normal per vert. if (mesh.VertexNormalData == null || mesh.VertexNormalData.Count < 1) { mesh.VertexNormalData = Enumerable.Repeat(Vector3.Zero, mesh.VertexData.Count()).ToList(); } var triVerts = triangleFace.vertIndexList.Select(ind => mesh.VertexData[ind - 1].ToVector3()).ToArray(); var a = triVerts[0]; var b = triVerts[1]; var c = triVerts[2]; var calculatedNormal = Vector3.Normalize(Vector3.Cross((b - a), (c - a))); //temporarily we will add these normals to the normals array - we'll average them later. var inds = new List <int>(); foreach (var vertIndex in triangleFace.vertIndexList) { mesh.VertexNormalData[vertIndex - 1] = calculatedNormal; } //copy the array. //TODO because this is a struct, it does not end up modifying the tris we set in mesh... //bad design. triangleFace.NormalIndexList = triangleFace.vertIndexList.ToArray(); }
public static (List <TriangleFace>, Dictionary <Vector3, List <TriangleFace> >) createTriangles(int[] triangles, Vector3[] vertices) { var mappedTriangles = new List <TriangleFace>(); var vertexToTriangles = new Dictionary <Vector3, List <TriangleFace> >(); for (int i = 0; i < triangles.Length; i += 3) { var v1 = vertices[triangles[i]]; var v2 = vertices[triangles[i + 1]]; var v3 = vertices[triangles[i + 2]]; var triangle = new TriangleFace(v1, v2, v3); mappedTriangles.Add(triangle); foreach (Vector3 v in new ArrayList() { v1, v2, v3 }) { List <TriangleFace> trianglesOfVertex; if (!vertexToTriangles.ContainsKey(v)) { trianglesOfVertex = new List <TriangleFace>(); vertexToTriangles.Add(v, trianglesOfVertex); } else { trianglesOfVertex = vertexToTriangles[v]; } trianglesOfVertex.Add(triangle); } } return(mappedTriangles, vertexToTriangles); }
public void addAdjacent(TriangleFace adj) { if (this.isAdjacent(adj)) { this.adjacent.Add(adj); adj.adjacent.Add(this); } }
public static Vector3 BaryCoordinates2(int x, int y, TriangleFace triangle, Vector2[] vectors) { var pt1 = vectors[triangle.vertIndexList[0] - 1]; var pt2 = vectors[triangle.vertIndexList[1] - 1]; var pt3 = vectors[triangle.vertIndexList[2] - 1]; return(BaryCoordinates2(x, y, pt1, pt2, pt3)); }
public OBJFile(FileStream stream) { this.vertices = new List <VertexPosition>(); this.triangleFaces = new List <TriangleFace>(); this.quadFaces = new List <QuadFace>(); StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); text = text.Replace("\r", ""); text = text.Replace('.', ','); string[] lines = text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines) { string[] words = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); //if (words[0] == "v") //{ // float x = float.Parse(words[1]); // float y = float.Parse(words[2]); // float z = float.Parse(words[3]); // VertexPosition coord = new VertexPosition(x, y, z); // this.vertices.Add(coord); //} switch (words[0]) { case "v": float x = float.Parse(words[1]); float y = float.Parse(words[2]); float z = float.Parse(words[3]); VertexPosition coord = new VertexPosition(x, y, z); this.vertices.Add(coord); break; case "f": if (words.Length == 5) { int a4 = int.Parse(words[1].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int b4 = int.Parse(words[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int c4 = int.Parse(words[3].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int d4 = int.Parse(words[4].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); QuadFace face4 = new QuadFace(a4, b4, c4, d4); this.quadFaces.Add(face4); break; } int a = int.Parse(words[1].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int b = int.Parse(words[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int c = int.Parse(words[3].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); TriangleFace face = new TriangleFace(a, b, c); this.triangleFaces.Add(face); break; } } this.mesh = new MeshBase(); this.mesh.QuadFaces = this.quadFaces; this.mesh.TriangleFaces = this.triangleFaces; this.mesh.Vertices = this.vertices; string[] path = stream.Name.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); this.mesh.Name = HeadFile.ReplaceExtention(path[path.Length - 1], ""); }
public OBJFile(FileStream stream) { this.vertices = new List<VertexPosition>(); this.triangleFaces = new List<TriangleFace>(); this.quadFaces = new List<QuadFace>(); StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); text = text.Replace("\r", ""); text = text.Replace('.', ','); string[] lines = text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines) { string[] words = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); //if (words[0] == "v") //{ // float x = float.Parse(words[1]); // float y = float.Parse(words[2]); // float z = float.Parse(words[3]); // VertexPosition coord = new VertexPosition(x, y, z); // this.vertices.Add(coord); //} switch (words[0]) { case "v": float x = float.Parse(words[1]); float y = float.Parse(words[2]); float z = float.Parse(words[3]); VertexPosition coord = new VertexPosition(x, y, z); this.vertices.Add(coord); break; case "f": if (words.Length == 5) { int a4 = int.Parse(words[1].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int b4 = int.Parse(words[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int c4 = int.Parse(words[3].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int d4 = int.Parse(words[4].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); QuadFace face4 = new QuadFace(a4, b4, c4, d4); this.quadFaces.Add(face4); break; } int a = int.Parse(words[1].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int b = int.Parse(words[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int c = int.Parse(words[3].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); TriangleFace face = new TriangleFace(a, b, c); this.triangleFaces.Add(face); break; } } this.mesh = new MeshBase(); this.mesh.QuadFaces = this.quadFaces; this.mesh.TriangleFaces = this.triangleFaces; this.mesh.Vertices = this.vertices; string[] path = stream.Name.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); this.mesh.Name = HeadFile.ReplaceExtention(path[path.Length - 1],""); }
private static (Vector3, Vector3) calculateTangetSpaceForTri(TriangleFace triangleFace, Mesh mesh) { var triVerts = triangleFace.vertIndexList.Select(ind => mesh.VertexData[ind - 1].ToVector3()).ToArray(); var uvs = triangleFace.UVIndexList.Select(ind => mesh.VertexUVData[ind - 1]).ToArray(); var normals = triangleFace.NormalIndexList.Select(ind => mesh.VertexNormalData[ind - 1]).ToArray(); var p0 = triVerts[0]; var p1 = triVerts[1]; var p2 = triVerts[2]; var tex0 = uvs[0]; var tex1 = uvs[1]; var tex2 = uvs[2]; var norm0 = normals[0]; var norm1 = normals[1]; var norm2 = normals[2]; var q1 = Vector3.Subtract(p1, p0); var q2 = Vector3.Subtract(p2, p0); var temp1 = Vector2.Subtract(tex1, tex0); var temp2 = Vector2.Subtract(tex2, tex0); var s = new Vector2(temp1.X, temp2.X); var t = new Vector2(temp1.Y, temp2.Y); //TODO are uv coords incorrect? var recip = 1.0 / ((temp1.X * temp2.Y) - (temp1.Y * temp2.X)); if (double.IsInfinity(recip)) { recip = 1.0; } //these seem exactly the same... var udir = Vector3.Multiply((float)recip, Vector3.Subtract(Vector3.Multiply(temp2.Y, q1), (Vector3.Multiply(temp1.Y, q2)))); var vdir = Vector3.Multiply((float)recip, Vector3.Subtract(Vector3.Multiply(temp1.X, q2), (Vector3.Multiply(temp2.X, q1)))); //var udir = new Vector3((t.Y * q1.X - t.X * q2.X) * recip, (t.Y * q1.Y - t.X * q2.Y) * recip, (t.Y * q1.Z - t.X * q2.Z) * recip); //var vdir = new Vector3((s.X * q2.X - s.Y * q1.X) * recip, (s.X * q2.Y - s.Y * q1.Y) * recip, (s.X * q2.Z - s.Y * q1.Z) * recip); if (float.IsInfinity(udir.X) || float.IsInfinity(udir.Y) || float.IsInfinity(udir.Z) || float.IsInfinity(vdir.X) || float.IsInfinity(vdir.Y) || float.IsInfinity(vdir.Z)) { throw new ArgumentException(); } return(udir, vdir); }
public static bool pixelIsInsideTriangle(int x, int y, TriangleFace triangle, Vector3[] vectors) { var pt1 = vectors[triangle.vertIndexList[0] - 1]; var pt2 = vectors[triangle.vertIndexList[1] - 1]; var pt3 = vectors[triangle.vertIndexList[2] - 1]; var barycenter = TriangleExtensions.BaryCoordinates2(x, y, pt1.ToVector2(), pt2.ToVector2(), pt3.ToVector2()); //only in the triangle if coefs are all positive. if (barycenter.X < 0 || barycenter.X >= 1f || barycenter.Y < 0 || barycenter.Y >= 1f || barycenter.Z < 0 || barycenter.Z >= 1f) { return(false); } return(true); }
public static List <TriangleFace> extractFaces(List <TriangleFace> faces, int numToExtract) { if (faces == null || numToExtract > faces.Count || numToExtract <= 0) { throw new Exception("The list of faces doesn't have enough faces to extract"); } List <TriangleFace> adjPoll = new List <TriangleFace>(); HashSet <TriangleFace> extractedFaces = new HashSet <TriangleFace>(); TriangleFace face = faces[UnityEngine.Random.Range(0, faces.Count)]; extractOneFace(faces, extractedFaces, adjPoll, face); for (int i = 1; i < numToExtract; i++) { bool foundOne = false; foreach (TriangleFace adj in adjPoll) { if (!extractedFaces.Contains(adj) && faces.Contains(adj)) { foundOne = true; extractOneFace(faces, extractedFaces, adjPoll, adj); Shuffle(adjPoll); break; } } if (!foundOne) { throw new Exception("Wasn't able to find a connected"); } } return(new List <TriangleFace>(extractedFaces)); }
static void extractOneFace(List <TriangleFace> allFaces, HashSet <TriangleFace> extractedFaces, List <TriangleFace> adjPoll, TriangleFace face) { extractedFaces.Add(face); allFaces.Remove(face); adjPoll.Remove(face); adjPoll.AddRange(face.adjacent); }
public bool isAdjacent(TriangleFace adj) { return(adj != null && this.hasEqualVertices(adj.vertices, 2)); }
// // Steps Extrude // public static Surface Extrude(this Polyline curve, int steps, double height, double taper) { Vector3F normal = Vector3F.Undefined; taper = (taper < 0 ? -1f : 1f) - taper; if (curve.Points.Count < 2) { return(null); } if (steps < 2) { return(null); } steps = ((steps / 4) + ((steps % 4) != 0 ? 4 : 0)) * 4; if (curve.Points.Count > 2) { normal = Vector3F.CrossProduct(new Vector3F(curve.Points[0].Point, curve.Points[1].Point), new Vector3F(curve.Points[0].Point, curve.Points[2].Point)); } if (normal.IsUndefined) { normal = new Vector3F(0, 0, -1); } normal = normal.Unit(); Surface surface = new Surface(); for (double i = 0; i <= 1; i = i + 1 / (double)steps) { surface.Points.Add(curve.GetParametricPoint(i)); } int num = 0; Point3F sumBase = new Point3F(0, 0, 0); Point3F sumHeight = new Point3F(0, 0, 0); for (double j = 0; j <= 1; j = j + 1 / (double)steps) { Point3F item = surface.Points[num]; sumBase = sumBase.Add(item); item.X = (item.X * taper) + (normal.X * height); item.Y = (item.Y * taper) + (normal.Y * height); item.Z = item.Z + (normal.Z * height); sumHeight = sumHeight.Add(item); surface.Points.Add(item); num++; } sumBase.DivideBy(num); sumHeight.DivideBy(num); TriangleFace[] faces = new TriangleFace[(num + (curve.Closed ? 1 : 0)) * 2]; int k; for (k = 0; k < num - 1; k++) { faces [k * 2] = new TriangleFace(k, k + 1, k + num + 1); faces [k * 2 + 1] = new TriangleFace(k, k + num + 1, k + num); } if (curve.Closed) { faces [k * 2] = new TriangleFace(num - 1, 0, num); faces [k * 2 + 1] = new TriangleFace(num - 1, num, 2 * num - 1); } surface.Faces = faces; return(surface); }
public void VerticesAreNotSimilar() { Assert.False(TriangleFace.areVerticesEqual(new Vector3(2, 1, 1), new Vector3(1, 1, 1))); }
public void VerticesAreSimilar() { Assert.True(TriangleFace.areVerticesEqual(new Vector3(1, 1, 1), new Vector3(1, 1, 1))); }
public void Setup() { t1 = new TriangleFace(new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 1, 0)); t2 = new TriangleFace(new Vector3(0, 0, 0), new Vector3(1, 1, 0), new Vector3(0, 1, 0)); t3 = new TriangleFace(new Vector3(0, 1, 0), new Vector3(1, 1, 0), new Vector3(1, 2, 0)); }