static StlMesh[] ImportSmoothNormals(IEnumerable <Facet> faces, CoordinateSpace modelCoordinateSpace, UpAxis modelUpAxis, IndexFormat indexFormat) { var facets = faces as Facet[] ?? faces.ToArray(); int maxVertexCount = indexFormat == IndexFormat.UInt32 ? MaxFacetsPerMesh32 * 3 : MaxFacetsPerMesh16 * 3; int triangleCount = facets.Length * 3; //Dictionary<StlVector3, StlVector3> smoothNormals = new Dictionary<StlVector3, StlVector3>(triangleCount / 2); //// In case meshes are split, we need to calculate smooth normals first //foreach(var face in faces) //{ // var x = (StlVector3) face.a; // var y = (StlVector3) face.b; // var z = (StlVector3) face.c; // var normal = face.normal; // if(smoothNormals.ContainsKey(x)) // smoothNormals[x] += normal; // else // smoothNormals.Add(x, normal); // if(smoothNormals.ContainsKey(y)) // smoothNormals[y] += normal; // else // smoothNormals.Add(y, normal); // if(smoothNormals.ContainsKey(z)) // smoothNormals[z] += normal; // else // smoothNormals.Add(z, normal); //} int numProcs = Environment.ProcessorCount; int concurrencyLevel = numProcs * 2; ConcurrentDictionary <StlVector3, StlVector3> smoothNormals = new ConcurrentDictionary <StlVector3, StlVector3>(concurrencyLevel, triangleCount / 2); // In case meshes are split, we need to calculate smooth normals first Parallel.ForEach(faces, (face) => { var x = face.a; var y = face.b; var z = face.c; var normal = face.normal; if (smoothNormals.ContainsKey(x)) { smoothNormals[x] += normal; } else { smoothNormals.TryAdd(x, normal); } if (smoothNormals.ContainsKey(y)) { smoothNormals[y] += normal; } else { smoothNormals.TryAdd(y, normal); } if (smoothNormals.ContainsKey(z)) { smoothNormals[z] += normal; } else { smoothNormals.TryAdd(z, normal); } }); List <StlMesh> meshes = new List <StlMesh>(); List <StlVector3> pos = new List <StlVector3>(Math.Min(maxVertexCount, triangleCount)); List <StlVector3> nrm = new List <StlVector3>(Math.Min(maxVertexCount, triangleCount)); List <int> tri = new List <int>(triangleCount); Dictionary <StlVector3, int> map = new Dictionary <StlVector3, int>(); int vertex = 0; StlVector3[] points = new StlVector3[3]; foreach (var face in facets) { if (vertex + 3 > maxVertexCount) { var mesh = new StlMesh { vertices = pos.ToArray(), normals = nrm.ToArray(), indexFormat = indexFormat }; if (modelCoordinateSpace == CoordinateSpace.Right) { tri.Reverse(); } mesh.triangles = tri.ToArray(); meshes.Add(mesh); vertex = 0; pos.Clear(); nrm.Clear(); tri.Clear(); map.Clear(); } points[0] = face.a; points[1] = face.b; points[2] = face.c; for (int i = 0; i < 3; i++) { int index = -1; var hash = points[i]; if (!map.TryGetValue(hash, out index)) { if (modelCoordinateSpace == CoordinateSpace.Right) { pos.Add(Stl.ToCoordinateSpace(points[i], CoordinateSpace.Left)); nrm.Add(Stl.ToCoordinateSpace(smoothNormals[hash].normalized, CoordinateSpace.Left)); } else { pos.Add(points[i]); nrm.Add(smoothNormals[hash].normalized); } tri.Add(vertex); map.Add(hash, vertex++); } else { tri.Add(index); } } } if (vertex > 0) { var mesh = new StlMesh { vertices = pos.ToArray(), normals = nrm.ToArray(), indexFormat = indexFormat }; if (modelCoordinateSpace == CoordinateSpace.Right) { tri.Reverse(); } mesh.triangles = tri.ToArray(); meshes.Add(mesh); vertex = 0; pos.Clear(); nrm.Clear(); tri.Clear(); map.Clear(); } return(meshes.ToArray()); }
static StlMesh[] ImportHardNormals(IEnumerable <Facet> faces, CoordinateSpace modelCoordinateSpace, UpAxis modelUpAxis, IndexFormat indexFormat) { var facets = faces as Facet[] ?? faces.ToArray(); int faceCount = facets.Length, f = 0; int maxFacetsPerMesh = indexFormat == IndexFormat.UInt32 ? MaxFacetsPerMesh32 : MaxFacetsPerMesh16; int maxVertexCount = maxFacetsPerMesh * 3; StlMesh[] meshes = new StlMesh[faceCount / maxFacetsPerMesh + 1]; for (int meshIndex = 0; meshIndex < meshes.Length; meshIndex++) { int len = System.Math.Min(maxVertexCount, (faceCount - f) * 3); StlVector3[] v = new StlVector3[len]; StlVector3[] n = new StlVector3[len]; int[] t = new int[len]; for (int it = 0; it < len; it += 3) { v[it] = facets[f].a; v[it + 1] = facets[f].b; v[it + 2] = facets[f].c; n[it] = facets[f].normal; n[it + 1] = facets[f].normal; n[it + 2] = facets[f].normal; t[it] = it + 0; t[it + 1] = it + 1; t[it + 2] = it + 2; f++; } if (modelCoordinateSpace == CoordinateSpace.Right) { for (int i = 0; i < len; i += 3) { v[i + 0] = Stl.ToCoordinateSpace(v[i + 0], CoordinateSpace.Left); v[i + 1] = Stl.ToCoordinateSpace(v[i + 1], CoordinateSpace.Left); v[i + 2] = Stl.ToCoordinateSpace(v[i + 2], CoordinateSpace.Left); n[i + 0] = Stl.ToCoordinateSpace(n[i + 0], CoordinateSpace.Left); n[i + 1] = Stl.ToCoordinateSpace(n[i + 1], CoordinateSpace.Left); n[i + 2] = Stl.ToCoordinateSpace(n[i + 2], CoordinateSpace.Left); var a = t[i + 2]; t[i + 2] = t[i]; t[i] = a; } } meshes[meshIndex] = new StlMesh { vertices = v, normals = n, triangles = t, indexFormat = indexFormat }; } return(meshes); }
public Spine(string key, List <Vertex> points, List <Geometry> geometries, int direction) { Key = key; Points = points; Geometries = geometries; if (Points.Count == 4) { //Считывание модели из файла Model = new StlMesh(StlFile.Load(new FileStream("FullModel.stl", FileMode.Open, FileAccess.Read)) .Triangles); int k = 0; Up = new List <Pointes>(); Down = new List <Pointes>(); UpC = new List <Pointes>(); DownC = new List <Pointes>(); using (StreamReader sr = new StreamReader("up.txt")) { while (sr.Peek() >= 0) { string str; string[] strArray; str = sr.ReadLine(); strArray = str.Split(' '); Pointes currentPoint = new Pointes(); currentPoint.X = float.Parse(strArray[0], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Y = float.Parse(strArray[1], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Z = float.Parse(strArray[2], NumberStyles.Float, CultureInfo.InvariantCulture); Up.Add(currentPoint); } } using (StreamReader sr = new StreamReader("down.txt")) { while (sr.Peek() >= 0) { string str; string[] strArray; str = sr.ReadLine(); strArray = str.Split(' '); Pointes currentPoint = new Pointes(); currentPoint.X = float.Parse(strArray[0], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Y = float.Parse(strArray[1], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Z = float.Parse(strArray[2], NumberStyles.Float, CultureInfo.InvariantCulture); Down.Add(currentPoint); } } using (StreamReader sr = new StreamReader("up_corner.txt")) { while (sr.Peek() >= 0) { string str; string[] strArray; str = sr.ReadLine(); strArray = str.Split(' '); Pointes currentPoint = new Pointes(); currentPoint.X = float.Parse(strArray[0], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Y = float.Parse(strArray[1], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Z = float.Parse(strArray[2], NumberStyles.Float, CultureInfo.InvariantCulture); UpC.Add(currentPoint); } } using (StreamReader sr = new StreamReader("down_corner.txt")) { while (sr.Peek() >= 0) { string str; string[] strArray; str = sr.ReadLine(); strArray = str.Split(' '); Pointes currentPoint = new Pointes(); currentPoint.X = float.Parse(strArray[0], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Y = float.Parse(strArray[1], NumberStyles.Float, CultureInfo.InvariantCulture); currentPoint.Z = float.Parse(strArray[2], NumberStyles.Float, CultureInfo.InvariantCulture); DownC.Add(currentPoint); } } U = new List <int>(); foreach (var a in Up) { foreach (var b in Model.Vertices) { if (a.X == b.X && a.Y == b.Y && a.Z == b.Z) { U.Add(b.IdInMesh); } } } D = new List <int>(); foreach (var a in Down) { foreach (var b in Model.Vertices) { if (a.X == b.X && a.Y == b.Y && a.Z == b.Z) { D.Add(b.IdInMesh); } } } UC = new List <int>(); foreach (var a in UpC) { foreach (var b in Model.Vertices) { if (a.X == b.X && a.Y == b.Y && a.Z == b.Z) { UC.Add(b.IdInMesh); } } } DC = new List <int>(); foreach (var a in DownC) { foreach (var b in Model.Vertices) { if (a.X == b.X && a.Y == b.Y && a.Z == b.Z) { DC.Add(b.IdInMesh); } } } //TODO Здесь добавить маркировку точек if (direction == 0) { //Отражение Model.Vertices = Transformation.ConvertPointsArrayToList( Transformation.ReflectionObject(Transformation.ConvertPointsListToArray(Model.Vertices), true, false, false)); } //Масштабирование var dy = Vertex.D(Points[2], Points[3]) / Vertex.D(Model.Vertices[_k2], Model.Vertices[_k3]); var dx = Vertex.D(Points[2], Points[1]) / Vertex.D(Model.Vertices[_k2], Model.Vertices[_k1]); Model.Vertices = Transformation.ConvertPointsArrayToList( Transformation.ScaleObject(Transformation.ConvertPointsListToArray(Model.Vertices), dx, dy, dx)); //Поворот double k2 = (Points[0].Y - Points[3].Y) / (Points[0].X - Points[3].X); double k1 = (Model.Vertices[_k0].Y - Model.Vertices[_k3].Y) / (Model.Vertices[_k0].X - Model.Vertices[_k3].X); double alfa = Math.Atan((k2 - k1) / (1 + k2 * k1)); Model.Vertices = Transformation.ConvertPointsArrayToList(Transformation.Rotate(alfa, Transformation.ConvertPointsListToArray(Model.Vertices), 3, 0, 0, 0)); //Перемещение Model.Vertices = Transformation.ConvertPointsArrayToList(Transformation.MoveObject( Transformation.ConvertPointsListToArray(Model.Vertices), Points[3].X - Model.Vertices[_k3].X, Points[3].Y - Model.Vertices[_k3].Y, 0)); } }