Пример #1
0
    public static Color32 CalcFaceColor(
        ConwayPoly conway,
        Color[] colors,
        PolyHydraEnums.ColorMethods colorMethod,
        int i)
    {
        Color32 color;
        var     face     = conway.Faces[i];
        var     faceRole = conway.FaceRoles[i];

        switch (colorMethod)
        {
        case PolyHydraEnums.ColorMethods.ByRole:
            color = colors[(int)faceRole];
            break;

        case PolyHydraEnums.ColorMethods.BySides:
            color = colors[face.Sides % colors.Length];
            break;

        case PolyHydraEnums.ColorMethods.ByFaceDirection:
            color = colors[CalcDirectionIndex(face, colors.Length - 1)];
            break;

        case PolyHydraEnums.ColorMethods.ByTags:
            var c = new Color();
            if (conway.FaceTags[i].Count > 0)
            {
                string htmlColor = conway.FaceTags[i].First(t => t.Item1.StartsWith("#")).Item1;
                if (!(ColorUtility.TryParseHtmlString(htmlColor, out c)))
                {
                    if (!ColorUtility.TryParseHtmlString(htmlColor.Replace("#", ""), out c))
                    {
                        c = Color.white;
                    }
                }

                color = c;
            }
            else
            {
                color = Color.white;
            }

            break;

        default:
            color = Color.white;
            break;
        }

        return(color);
    }
Пример #2
0
    //  new Color(1.0f, 0.75f, 0.75f),
    //  new Color(1.0f, 0.5f, 0.5f),
    //  new Color(0.8f, 0.4f, 0.4f),
    //  new Color(0.8f, 0.8f, 0.8f),
    //  new Color(0.5f, 0.6f, 0.6f),
    //  new Color(0.6f, 0.0f, 0.0f),
    //  new Color(1.0f, 1.0f, 1.0f),
    //  new Color(0.6f, 0.6f, 0.6f),
    //  new Color(0.5f, 1.0f, 0.5f),
    //  new Color(0.5f, 0.5f, 1.0f),
    //  new Color(0.5f, 1.0f, 1.0f),
    //  new Color(1.0f, 0.5f, 1.0f),

    public static Mesh BuildMeshFromConwayPoly(
        ConwayPoly conway,
        bool generateSubmeshes = false,
        Color[] colors         = null,
        PolyHydraEnums.ColorMethods colorMethod = PolyHydraEnums.ColorMethods.ByRole,
        PolyHydraEnums.UVMethods uvMethod       = PolyHydraEnums.UVMethods.FirstEdge,
        bool largeMeshFormat = true
        )
    {
        Vector2 calcUV(Vector3 point, Vector3 xAxis, Vector3 yAxis)
        {
            float u, v;

            u  = Vector3.Project(point, xAxis).magnitude;
            u *= Vector3.Dot(point, xAxis) > 0 ? 1 : -1;
            v  = Vector3.Project(point, yAxis).magnitude;
            v *= Vector3.Dot(point, yAxis) > 0  ? 1 : -1;
            return(new Vector2(u, v));
        }

        if (colors == null)
        {
            colors = DefaultFaceColors;
        }
        var target = new Mesh();

        if (largeMeshFormat)
        {
            target.indexFormat = IndexFormat.UInt32;
        }
        var meshTriangles  = new List <int>();
        var meshVertices   = new List <Vector3>();
        var meshNormals    = new List <Vector3>();
        var meshColors     = new List <Color32>();
        var meshUVs        = new List <Vector2>();
        var edgeUVs        = new List <Vector2>();
        var barycentricUVs = new List <Vector3>();
        var miscUVs1       = new List <Vector4>();
        var miscUVs2       = new List <Vector4>();

        List <ConwayPoly.Roles> uniqueRoles = null;
        List <int>    uniqueSides           = null;
        List <string> uniqueTags            = null;

        var submeshTriangles = new List <List <int> >();

        // TODO
        // var hasNaked = conway.HasNaked();

        // Strip down to Face-Vertex structure
        var points      = conway.ListVerticesByPoints();
        var faceIndices = conway.ListFacesByVertexIndices();

        // Add faces
        int index = 0;

        if (generateSubmeshes)
        {
            switch (colorMethod)
            {
            case PolyHydraEnums.ColorMethods.ByRole:
                uniqueRoles = new HashSet <ConwayPoly.Roles>(conway.FaceRoles).ToList();
                for (int i = 0; i < uniqueRoles.Count; i++)
                {
                    submeshTriangles.Add(new List <int>());
                }
                break;

            case PolyHydraEnums.ColorMethods.BySides:
                for (int i = 0; i < colors.Length; i++)
                {
                    submeshTriangles.Add(new List <int>());
                }
                break;

            case PolyHydraEnums.ColorMethods.ByFaceDirection:
                for (int i = 0; i < colors.Length; i++)
                {
                    submeshTriangles.Add(new List <int>());
                }
                break;

            case PolyHydraEnums.ColorMethods.ByTags:
                var flattenedTags = conway.FaceTags.SelectMany(d => d.Select(i => i.Item1));
                uniqueTags = new HashSet <string>(flattenedTags).ToList();
                for (int i = 0; i < uniqueTags.Count + 1; i++)
                {
                    submeshTriangles.Add(new List <int>());
                }
                break;
            }
        }

        for (var i = 0; i < faceIndices.Length; i++)
        {
            var faceIndex    = faceIndices[i];
            var face         = conway.Faces[i];
            var faceNormal   = face.Normal;
            var faceCentroid = face.Centroid;

            ConwayPoly.Roles faceRole = conway.FaceRoles[i];

            // Axes for UV mapping

            Vector3 xAxis = Vector3.right;
            Vector3 yAxis = Vector3.up;
            switch (uvMethod)
            {
            case PolyHydraEnums.UVMethods.FirstEdge:
                xAxis = face.Halfedge.Vector;
                yAxis = Vector3.Cross(xAxis, faceNormal);
                break;

            case PolyHydraEnums.UVMethods.BestEdge:
                xAxis = face.GetBestEdge().Vector;
                yAxis = Vector3.Cross(xAxis, faceNormal);
                break;

            case PolyHydraEnums.UVMethods.FirstVertex:
                yAxis = face.Centroid - face.GetVertices()[0].Position;
                xAxis = Vector3.Cross(yAxis, faceNormal);
                break;

            case PolyHydraEnums.UVMethods.BestVertex:
                yAxis = face.Centroid - face.GetBestEdge().Vertex.Position;
                xAxis = Vector3.Cross(yAxis, faceNormal);
                break;

            case PolyHydraEnums.UVMethods.ObjectAligned:
                // Align towards the highest vertex or edge midpoint (measured in the y direction)
                Vertex   chosenVert = face.GetVertices().OrderBy(vert => vert.Position.y).First();
                Halfedge chosenEdge = face.GetHalfedges().OrderBy(edge => edge.Midpoint.y).First();
                Vector3  chosenPoint;
                if (chosenVert.Position.y > chosenEdge.Midpoint.y + 0.01f)                          // favour edges slightly
                {
                    chosenPoint = chosenVert.Position;
                }
                else
                {
                    chosenPoint = chosenEdge.Midpoint;
                }

                yAxis = face.Centroid - chosenPoint;
                xAxis = Vector3.Cross(yAxis, faceNormal);
                break;
            }

            Color32 color = CalcFaceColor(conway, colors, colorMethod, i);

            float faceScale = 0;
            foreach (var v in face.GetVertices())
            {
                faceScale += Vector3.Distance(v.Position, faceCentroid);
            }
            faceScale /= face.Sides;

            var miscUV1 = new Vector4(faceScale, face.Sides, faceCentroid.magnitude, ((float)i) / faceIndices.Length);
            var miscUV2 = new Vector4(faceCentroid.x, faceCentroid.y, faceCentroid.z, i);

            var faceTris = new List <int>();

            if (face.Sides > 3)
            {
                for (var edgeIndex = 0; edgeIndex < faceIndex.Count; edgeIndex++)
                {
                    meshVertices.Add(faceCentroid);
                    meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis));
                    faceTris.Add(index++);
                    edgeUVs.Add(new Vector2(0, 0));
                    barycentricUVs.Add(new Vector3(0, 0, 1));

                    meshVertices.Add(points[faceIndex[edgeIndex]]);
                    meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis));
                    faceTris.Add(index++);
                    edgeUVs.Add(new Vector2(1, 1));
                    barycentricUVs.Add(new Vector3(0, 1, 0));

                    meshVertices.Add(points[faceIndex[(edgeIndex + 1) % face.Sides]]);
                    meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis));
                    faceTris.Add(index++);
                    edgeUVs.Add(new Vector2(1, 1));
                    barycentricUVs.Add(new Vector3(1, 0, 0));

                    meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3));
                    meshColors.AddRange(Enumerable.Repeat(color, 3));
                    miscUVs1.AddRange(Enumerable.Repeat(miscUV1, 3));
                    miscUVs2.AddRange(Enumerable.Repeat(miscUV2, 3));
                }
            }
            else
            {
                meshVertices.Add(points[faceIndex[0]]);
                meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis));
                faceTris.Add(index++);
                barycentricUVs.Add(new Vector3(0, 0, 1));

                meshVertices.Add(points[faceIndex[1]]);
                meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis));
                faceTris.Add(index++);
                barycentricUVs.Add(new Vector3(0, 1, 0));

                meshVertices.Add(points[faceIndex[2]]);
                meshUVs.Add(calcUV(meshVertices[index], xAxis, yAxis));
                faceTris.Add(index++);
                barycentricUVs.Add(new Vector3(1, 0, 0));

                edgeUVs.AddRange(Enumerable.Repeat(new Vector2(1, 1), 3));
                meshNormals.AddRange(Enumerable.Repeat(faceNormal, 3));
                meshColors.AddRange(Enumerable.Repeat(color, 3));
                miscUVs1.AddRange(Enumerable.Repeat(miscUV1, 3));
                miscUVs2.AddRange(Enumerable.Repeat(miscUV2, 3));
            }

            if (generateSubmeshes)
            {
                switch (colorMethod)
                {
                case PolyHydraEnums.ColorMethods.ByRole:
                    int uniqueRoleIndex = uniqueRoles.IndexOf(faceRole);
                    submeshTriangles[uniqueRoleIndex].AddRange(faceTris);
                    break;

                case PolyHydraEnums.ColorMethods.BySides:
                    submeshTriangles[face.Sides].AddRange(faceTris);
                    break;

                case PolyHydraEnums.ColorMethods.ByFaceDirection:
                    submeshTriangles[CalcDirectionIndex(face, colors.Length - 1)].AddRange(faceTris);
                    break;

                case PolyHydraEnums.ColorMethods.ByTags:
                    if (conway.FaceTags[i].Count > 0)
                    {
                        string htmlColor      = conway.FaceTags[i].First(t => t.Item1.StartsWith("#")).Item1;
                        int    uniqueTagIndex = uniqueTags.IndexOf(htmlColor);
                        submeshTriangles[uniqueTagIndex + 1].AddRange(faceTris);
                    }
                    else
                    {
                        submeshTriangles[0].AddRange(faceTris);
                    }
                    break;
                }
            }
            else
            {
                meshTriangles.AddRange(faceTris);
            }
        }

        target.vertices = meshVertices.Select(x => Jitter(x)).ToArray();
        target.normals  = meshNormals.ToArray();
        if (generateSubmeshes)
        {
            target.subMeshCount = submeshTriangles.Count;
            for (var i = 0; i < submeshTriangles.Count; i++)
            {
                target.SetTriangles(submeshTriangles[i], i);
            }
        }
        else
        {
            target.triangles = meshTriangles.ToArray();
        }

        target.colors32 = meshColors.ToArray();
        target.SetUVs(0, meshUVs);
        target.SetUVs(1, edgeUVs);
        target.SetUVs(2, barycentricUVs);
        target.SetUVs(3, miscUVs1);
        target.SetUVs(4, miscUVs2);

        target.RecalculateTangents();
        return(target);
    }