Beispiel #1
0
    public Mesh ToMesh(Facing facing = Facing.Normal, GlobalSurfaceType surfaceType = GlobalSurfaceType.Normal)
    {
        Mesh mesh = new Mesh();

        ToMesh(mesh, facing, surfaceType);
        return(mesh);
    }
Beispiel #2
0
    public void ToMesh(Mesh mesh, Facing facing = Facing.Normal, GlobalSurfaceType surfaceType = GlobalSurfaceType.Normal)
    {
        var indexByVertexKey = new Dictionary <Vertex, SortedDictionary <VertexKey, int> >();
        var trigs            = new List <int>();
        var verts            = new List <Vector3>();
        var norms            = new List <Vector3>();
        var meshuv           = new List <Vector2>();

        var vertexKeyComparer = new VertexKeyComparer();

        int MeshVertex(Halfedge e, Vector3 normal)
        {
            if (!indexByVertexKey.TryGetValue(e.vertex, out SortedDictionary <VertexKey, int> indices))
            {
                indices = new SortedDictionary <VertexKey, int>(vertexKeyComparer);
                indexByVertexKey[e.vertex] = indices;
            }
            VertexKey key = new VertexKey(normal, GetUV(e));

            if (!indices.TryGetValue(key, out int index))
            {
                index = verts.Count;
                verts.Add(e.vertex.p);
                norms.Add(normal);
                meshuv.Add(GetUV(e));
                indices.Add(key, index);
            }
            return(index);
        }

        int MeshVertexEdgeNormal(Halfedge e)
        {
            return(MeshVertex(e, GetNormal(e)));
        }

        if (surfaceType == GlobalSurfaceType.AutoSmoothAll || surfaceType == GlobalSurfaceType.SplitTriangleAll)
        {
            // No vertex duplication.
            foreach (Face f in faces)
            {
                List <Halfedge> edges = f.edges;
                int             p1    = 0;
                int             p2    = edges.Count - 1;
                while (p2 - p1 > 1)
                {
                    trigs.Add(edges[p1].vertex.index);
                    trigs.Add(edges[p1 + 1].vertex.index);
                    trigs.Add(edges[p2].vertex.index);
                    p1++;
                    if (p2 - p1 <= 1)
                    {
                        break;
                    }
                    trigs.Add(edges[p1].vertex.index);
                    trigs.Add(edges[p2 - 1].vertex.index);
                    trigs.Add(edges[p2].vertex.index);
                    p2--;
                }
            }
            mesh.vertices  = vertices.Select(v => v.p).ToArray();
            mesh.triangles = trigs.ToArray();
        }
        else
        {
            foreach (Face f in faces)
            {
                FaceType        faceType = GetFaceType(f);
                List <Halfedge> edges    = f.edges;
                if (surfaceType == GlobalSurfaceType.HardPolygonAll || faceType == FaceType.Polygonal)
                {
                    Vector3 normal = f.CalculateNormal();
                    int     p1     = 0;
                    int     p2     = edges.Count - 1;
                    while (p2 - p1 > 1)
                    {
                        trigs.Add(MeshVertex(edges[p1], normal));
                        trigs.Add(MeshVertex(edges[p1 + 1], normal));
                        trigs.Add(MeshVertex(edges[p2], normal));
                        p1++;
                        if (p2 - p1 <= 1)
                        {
                            break;
                        }
                        trigs.Add(MeshVertex(edges[p1], normal));
                        trigs.Add(MeshVertex(edges[p2 - 1], normal));
                        trigs.Add(MeshVertex(edges[p2], normal));
                        p2--;
                    }
                }
                else if (surfaceType == GlobalSurfaceType.HardTriangleAll || faceType == FaceType.Triangular)
                {
                    int p1 = 0;
                    int p2 = edges.Count - 1;
                    while (p2 - p1 > 1)
                    {
                        Vector3 normal1 = Vector3.Cross(edges[p1 + 1].vertex.p - edges[p1].vertex.p, edges[p2].vertex.p - edges[p1].vertex.p).normalized;
                        trigs.Add(MeshVertex(edges[p1], normal1));
                        trigs.Add(MeshVertex(edges[p1 + 1], normal1));
                        trigs.Add(MeshVertex(edges[p2], normal1));
                        p1++;
                        if (p2 - p1 <= 1)
                        {
                            break;
                        }
                        Vector3 normal2 = Vector3.Cross(edges[p2 - 1].vertex.p - edges[p1].vertex.p, edges[p2].vertex.p - edges[p1].vertex.p).normalized;
                        trigs.Add(MeshVertex(edges[p1], normal2));
                        trigs.Add(MeshVertex(edges[p2 - 1], normal2));
                        trigs.Add(MeshVertex(edges[p2], normal2));
                        p2--;
                    }
                }
                else if (faceType == FaceType.Smooth)
                {
                    int p1 = 0;
                    int p2 = edges.Count - 1;
                    while (p2 - p1 > 1)
                    {
                        trigs.Add(MeshVertexEdgeNormal(edges[p1]));
                        trigs.Add(MeshVertexEdgeNormal(edges[p1 + 1]));
                        trigs.Add(MeshVertexEdgeNormal(edges[p2]));
                        p1++;
                        if (p2 - p1 <= 1)
                        {
                            break;
                        }
                        trigs.Add(MeshVertexEdgeNormal(edges[p1]));
                        trigs.Add(MeshVertexEdgeNormal(edges[p2 - 1]));
                        trigs.Add(MeshVertexEdgeNormal(edges[p2]));
                        p2--;
                    }
                }
                else if (faceType == FaceType.Directinal1 || faceType == FaceType.Directinal2)
                {
                    if (edges.Count > 4)
                    {
                        throw new Exception("Directional smooth can only apply to quad or triangle faces!");
                    }
                    Vector3[] localNormals = edges.Select((e, i) => CalculateDirectionalNormal(e, faceType, i, edges.Count)).ToArray();
                    if (edges.Count == 4)
                    {
                        trigs.Add(MeshVertex(edges[0], localNormals[0]));
                        trigs.Add(MeshVertex(edges[1], localNormals[1]));
                        trigs.Add(MeshVertex(edges[3], localNormals[3]));
                        trigs.Add(MeshVertex(edges[1], localNormals[1]));
                        trigs.Add(MeshVertex(edges[2], localNormals[2]));
                        trigs.Add(MeshVertex(edges[3], localNormals[3]));
                    }
                    else
                    {
                        trigs.Add(MeshVertex(edges[0], localNormals[0]));
                        trigs.Add(MeshVertex(edges[1], localNormals[1]));
                        trigs.Add(MeshVertex(edges[2], localNormals[2]));
                    }
                }
            }
            mesh.vertices  = verts.ToArray();
            mesh.triangles = trigs.ToArray();
            mesh.normals   = norms.ToArray();
            mesh.uv        = meshuv.ToArray();
        }

        if (facing != Facing.Normal || surfaceType == GlobalSurfaceType.SplitTriangleAll)
        {
            // Extra processing through mesh builder.
            MeshBuilder meshBuilder = new MeshBuilder(mesh);
            if (facing == Facing.Flipped)
            {
                meshBuilder.Invert();
            }
            else if (facing == Facing.TwoSided)
            {
                meshBuilder.AddOtherSide();
            }
            if (surfaceType == GlobalSurfaceType.SplitTriangleAll)
            {
                meshBuilder.SplitAllTriangles();
            }
            meshBuilder.ToMesh(mesh);
        }

        // Finalize the mesh.
        if (surfaceType == GlobalSurfaceType.AutoSmoothAll)
        {
            mesh.RecalculateNormals();
        }
        mesh.RecalculateBounds();
    }