Exemplo n.º 1
0
        public static bool SplitPolygonAtEdge(Polygon polygon, Edge edge, out Vertex newVertex)
        {
            newVertex = null;

            List <Vertex> vertices = new List <Vertex>(polygon.Vertices);

            for (int i = 0; i < polygon.Vertices.Length; i++)
            {
                Vector3 position1 = polygon.Vertices[i].Position;
                Vector3 position2 = polygon.Vertices[(i + 1) % polygon.Vertices.Length].Position;

                if ((edge.Vertex1.Position.EqualsWithEpsilon(position1) && edge.Vertex2.Position.EqualsWithEpsilon(position2)) ||
                    (edge.Vertex1.Position.EqualsWithEpsilon(position2) && edge.Vertex2.Position.EqualsWithEpsilon(position1)))
                {
                    newVertex = Vertex.Lerp(polygon.Vertices[i], polygon.Vertices[(i + 1) % polygon.Vertices.Length], 0.5f);
                    vertices.Insert(i + 1, newVertex);
                    break;
                }
            }

            if (vertices.Count == polygon.Vertices.Length)
            {
                // Could not add vertex to adjacent polygon
                return(false);
            }

            polygon.SetVertices(vertices.ToArray());

            return(true);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates an ico-sphere of radius 2. Unlike a polar-sphere this has a more even distribution of vertices.
        /// </summary>
        /// <returns>Polygons to be supplied to a brush.</returns>
        /// <param name="iterationCount">Number of times the surface is subdivided, values of 1 or 2 are recommended.</param>
        public static Polygon[] GenerateIcoSphere(int iterationCount)
        {
            // Derived from http://blog.andreaskahler.com/2009/06/creating-icosphere-mesh-in-code.html
            float   longestDimension = (1 + Mathf.Sqrt(5f)) / 2f;
            Vector3 sourceVector     = new Vector3(0, 1, longestDimension);

            // Make the longest dimension 1, so the icosphere fits in a 2,2,2 cube
            sourceVector.Normalize();

            Vertex[] vertices = new Vertex[]
            {
                new Vertex(new Vector3(-sourceVector.y, +sourceVector.z, sourceVector.x), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(sourceVector.y, +sourceVector.z, sourceVector.x), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(-sourceVector.y, -sourceVector.z, sourceVector.x), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(sourceVector.y, -sourceVector.z, sourceVector.x), Vector3.zero, Vector2.zero),

                new Vertex(new Vector3(sourceVector.x, -sourceVector.y, +sourceVector.z), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(sourceVector.x, +sourceVector.y, +sourceVector.z), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(sourceVector.x, -sourceVector.y, -sourceVector.z), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(sourceVector.x, +sourceVector.y, -sourceVector.z), Vector3.zero, Vector2.zero),

                new Vertex(new Vector3(+sourceVector.z, sourceVector.x, -sourceVector.y), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(+sourceVector.z, sourceVector.x, +sourceVector.y), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(-sourceVector.z, sourceVector.x, -sourceVector.y), Vector3.zero, Vector2.zero),
                new Vertex(new Vector3(-sourceVector.z, sourceVector.x, +sourceVector.y), Vector3.zero, Vector2.zero),
            };

            Polygon[] polygons = new Polygon[]
            {
                new Polygon(new Vertex[] { vertices[0].DeepCopy(), vertices[1].DeepCopy(), vertices[7].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[0].DeepCopy(), vertices[5].DeepCopy(), vertices[1].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[0].DeepCopy(), vertices[7].DeepCopy(), vertices[10].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[0].DeepCopy(), vertices[10].DeepCopy(), vertices[11].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[0].DeepCopy(), vertices[11].DeepCopy(), vertices[5].DeepCopy() }, null, false, false),

                new Polygon(new Vertex[] { vertices[7].DeepCopy(), vertices[1].DeepCopy(), vertices[8].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[1].DeepCopy(), vertices[5].DeepCopy(), vertices[9].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[10].DeepCopy(), vertices[7].DeepCopy(), vertices[6].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[11].DeepCopy(), vertices[10].DeepCopy(), vertices[2].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[5].DeepCopy(), vertices[11].DeepCopy(), vertices[4].DeepCopy() }, null, false, false),

                new Polygon(new Vertex[] { vertices[3].DeepCopy(), vertices[2].DeepCopy(), vertices[6].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[3].DeepCopy(), vertices[4].DeepCopy(), vertices[2].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[3].DeepCopy(), vertices[6].DeepCopy(), vertices[8].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[3].DeepCopy(), vertices[8].DeepCopy(), vertices[9].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[3].DeepCopy(), vertices[9].DeepCopy(), vertices[4].DeepCopy() }, null, false, false),

                new Polygon(new Vertex[] { vertices[6].DeepCopy(), vertices[2].DeepCopy(), vertices[10].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[2].DeepCopy(), vertices[4].DeepCopy(), vertices[11].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[8].DeepCopy(), vertices[6].DeepCopy(), vertices[7].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[9].DeepCopy(), vertices[8].DeepCopy(), vertices[1].DeepCopy() }, null, false, false),
                new Polygon(new Vertex[] { vertices[4].DeepCopy(), vertices[9].DeepCopy(), vertices[5].DeepCopy() }, null, false, false),
            };

            // Refine
            for (int i = 0; i < iterationCount; i++)
            {
                Polygon[] newPolygons = new Polygon[polygons.Length * 4];
                for (int j = 0; j < polygons.Length; j++)
                {
                    Vertex a = Vertex.Lerp(polygons[j].Vertices[0], polygons[j].Vertices[1], 0.5f);
                    Vertex b = Vertex.Lerp(polygons[j].Vertices[1], polygons[j].Vertices[2], 0.5f);
                    Vertex c = Vertex.Lerp(polygons[j].Vertices[2], polygons[j].Vertices[0], 0.5f);

                    a.Position = a.Position.normalized;
                    b.Position = b.Position.normalized;
                    c.Position = c.Position.normalized;

                    newPolygons[j * 4 + 0] = new Polygon(new Vertex[] { polygons[j].Vertices[0].DeepCopy(), a.DeepCopy(), c.DeepCopy() }, null, false, false);
                    newPolygons[j * 4 + 1] = new Polygon(new Vertex[] { polygons[j].Vertices[1].DeepCopy(), b.DeepCopy(), a.DeepCopy() }, null, false, false);
                    newPolygons[j * 4 + 2] = new Polygon(new Vertex[] { polygons[j].Vertices[2].DeepCopy(), c.DeepCopy(), b.DeepCopy() }, null, false, false);
                    newPolygons[j * 4 + 3] = new Polygon(new Vertex[] { a.DeepCopy(), b.DeepCopy(), c.DeepCopy() }, null, false, false);
                }
                polygons = newPolygons;
            }

            for (int i = 0; i < polygons.Length; i++)
            {
                bool anyAboveHalf = false;

                for (int j = 0; j < polygons[i].Vertices.Length; j++)
                {
                    Vector3 normal = polygons[i].Vertices[j].Position.normalized;
                    polygons[i].Vertices[j].Normal = normal;
                    float piReciprocal = 1f / Mathf.PI;
                    float u            = 0.5f - 0.5f * Mathf.Atan2(normal.x, -normal.z) * piReciprocal;
                    float v            = 1f - Mathf.Acos(normal.y) * piReciprocal;

                    if (Mathf.Abs(u) < 0.01f ||
                        Mathf.Abs(1 - Mathf.Abs(u)) < 0.01f)
                    {
                        if (polygons[i].Plane.normal.x > 0)
                        {
                            u = 0;
                        }
                        else
                        {
                            u = 1;
                        }
                    }

                    if (u > 0.75f)
                    {
                        anyAboveHalf = true;
                    }

                    //Debug.Log(u);
                    polygons[i].Vertices[j].UV = new Vector2(u, v);

                    //const float kOneOverPi = 1.0 / 3.14159265;
                    //float u = 0.5 - 0.5 * atan(N.x, -N.z) * kOneOverPi;
                    //float v = 1.0 - acos(N.y) * kOneOverPi;
                }

                if (anyAboveHalf)
                {
                    for (int j = 0; j < polygons[i].Vertices.Length; j++)
                    {
                        Vector2 uv = polygons[i].Vertices[j].UV;
                        if (uv.x < 0.5f)
                        {
                            uv.x += 1;
                        }
                        polygons[i].Vertices[j].UV = uv;
                    }
                }
            }

            return(polygons);
        }
Exemplo n.º 3
0
        public static bool SplitPolygon(Polygon polygon, out Polygon frontPolygon, out Polygon backPolygon, out Vertex newVertex1, out Vertex newVertex2, UnityEngine.Plane clipPlane)
        {
            newVertex1 = null;
            newVertex2 = null;

            List <Vertex> frontVertices = new List <Vertex>();
            List <Vertex> backVertices  = new List <Vertex>();

            for (int i = 0; i < polygon.vertices.Length; i++)
            {
                int previousIndex = i - 1;
                if (previousIndex < 0)
                {
                    previousIndex = polygon.vertices.Length - 1;
                }

                Vertex currentVertex  = polygon.vertices[i];
                Vertex previousVertex = polygon.vertices[previousIndex];

                PointPlaneRelation currentRelation  = ComparePointToPlane(currentVertex.Position, clipPlane);
                PointPlaneRelation previousRelation = ComparePointToPlane(previousVertex.Position, clipPlane);

                if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.InFront)
                {
                    // Front add current
                    frontVertices.Add(currentVertex);
                }
                else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.InFront)
                {
                    float  interpolant  = Edge.IntersectsPlane(clipPlane, previousVertex.Position, currentVertex.Position);
                    Vertex intersection = Vertex.Lerp(previousVertex, currentVertex, interpolant);

                    // Front add intersection, add current
                    frontVertices.Add(intersection);
                    frontVertices.Add(currentVertex);

                    // Back add intersection
                    backVertices.Add(intersection.DeepCopy());

                    newVertex2 = intersection;
                }
                else if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.Behind)
                {
                    // Reverse order here so that clipping remains consistent for either CW or CCW testing
                    float  interpolant  = Edge.IntersectsPlane(clipPlane, currentVertex.Position, previousVertex.Position);
                    Vertex intersection = Vertex.Lerp(currentVertex, previousVertex, interpolant);

                    // Front add intersection
                    frontVertices.Add(intersection);

                    // Back add intersection, current
                    backVertices.Add(intersection.DeepCopy());
                    backVertices.Add(currentVertex);

                    newVertex1 = intersection;
                }
                else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.Behind)
                {
                    // Back add current
                    backVertices.Add(currentVertex);
                }
                else if (currentRelation == PointPlaneRelation.On)
                {
                    // Front add current
                    frontVertices.Add(currentVertex);

                    // Back add current
                    backVertices.Add(currentVertex.DeepCopy());

                    if (previousRelation == PointPlaneRelation.InFront)
                    {
                        newVertex1 = currentVertex;
                    }
                    else if (previousRelation == PointPlaneRelation.Behind)
                    {
                        newVertex2 = currentVertex;
                    }
                    else
                    {
                        //						throw new System.Exception("Unhandled polygon configuration");
                    }
                }
                else if (currentRelation == PointPlaneRelation.Behind)
                {
                    backVertices.Add(currentVertex);
                }
                else if (currentRelation == PointPlaneRelation.InFront)
                {
                    frontVertices.Add(currentVertex);
                }
                else
                {
                    throw new System.Exception("Unhandled polygon configuration");
                }
            }
            //			Debug.Log("done");

            frontPolygon = new Polygon(frontVertices.ToArray(), polygon.Material, polygon.ExcludeFromFinal, polygon.UserExcludeFromFinal, polygon.uniqueIndex);
            backPolygon  = new Polygon(backVertices.ToArray(), polygon.Material, polygon.ExcludeFromFinal, polygon.UserExcludeFromFinal, polygon.uniqueIndex);

            // Because of some floating point issues and some edge cases relating to splitting the tip of a very thin
            // polygon we can't reliable test that the polygon intersects a plane and will produce two valid pieces
            // so after splitting we need to do an additional test to check that each polygon is valid. If it isn't
            // then we mark that polygon as null and return false to indicate the split wasn't entirely successful

            bool splitNecessary = true;

            if (frontPolygon.vertices.Length < 3 || frontPolygon.Plane.normal == Vector3.zero)
            {
                frontPolygon   = null;
                splitNecessary = false;
            }

            if (backPolygon.vertices.Length < 3 || backPolygon.Plane.normal == Vector3.zero)
            {
                backPolygon    = null;
                splitNecessary = false;
            }

            return(splitNecessary);
        }