Exemple #1
0
 public Facet(StlVector3 normal, StlVector3 a, StlVector3 b, StlVector3 c)
 {
     this.normal = normal;
     this.a      = a;
     this.b      = b;
     this.c      = c;
 }
Exemple #2
0
        public static StlVector3 ToCoordinateSpace(StlVector3 point, CoordinateSpace space)
        {
            if (space == CoordinateSpace.Left)
            {
                return(new StlVector3(-point.y, point.z, point.x));
            }

            return(new StlVector3(point.z, -point.x, point.y));
        }
Exemple #3
0
        static StlVector3 StringToVec3(string str)
        {
            string[]   split = str.Trim().Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
            StlVector3 v     = new StlVector3();

            float.TryParse(split[0], out v.x);
            float.TryParse(split[1], out v.y);
            float.TryParse(split[2], out v.z);

            return(v);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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());
        }
Exemple #6
0
        static async Task <IEnumerable <Facet> > ImportAsciiAsync(string path)
        {
            List <Facet> facets = new List <Facet>();

            using (StreamReader sr = new StreamReader(path))
            {
                string     line;
                int        state = EMPTY, vertex = 0;
                StlVector3 normal = StlVector3.zero;
                StlVector3 a = StlVector3.zero, b = StlVector3.zero, c = StlVector3.zero;
                bool       exit = false;

                while (sr.Peek() > 0 && !exit)
                {
                    line = await sr.ReadLineAsync();

                    line  = line.Trim();
                    state = ReadState(line);

                    switch (state)
                    {
                    case SOLID:
                        continue;

                    case FACET:
                        normal = StringToVec3(line.Replace("facet normal ", ""));
                        break;

                    case OUTER:
                        vertex = 0;
                        break;

                    case VERTEX:
                        // maintain counter-clockwise orientation of vertices:
                        if (vertex == 0)
                        {
                            a = StringToVec3(line.Replace("vertex ", ""));
                        }
                        else if (vertex == 2)
                        {
                            c = StringToVec3(line.Replace("vertex ", ""));
                        }
                        else if (vertex == 1)
                        {
                            b = StringToVec3(line.Replace("vertex ", ""));
                        }
                        vertex++;
                        break;

                    case ENDLOOP:
                        break;

                    case ENDFACET:
                        facets.Add(new Facet(normal, a, b, c));
                        break;

                    case ENDSOLID:
                        exit = true;
                        break;

                    case EMPTY:
                    default:
                        break;
                    }
                }
            }

            return(facets);
        }