public static void ExtrudePolygonOld(Polygon sourcePolygon, out Polygon[] outputPolygons, out Quaternion rotation)
        {
            float extrusionDistance = 1;

            Polygon newPolygon = sourcePolygon.DeepCopy();

            newPolygon.UniqueIndex = -1;
            newPolygon.Flip();

            Vector3 normal = sourcePolygon.Plane.normal;

            Polygon oppositePolygon = sourcePolygon.DeepCopy();

            oppositePolygon.UniqueIndex = -1;

            Vertex[] vertices = oppositePolygon.Vertices;
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Position += normal;
            }
            oppositePolygon.SetVertices(vertices);

            Polygon[] brushSides = new Polygon[sourcePolygon.Vertices.Length];

            for (int i = 0; i < newPolygon.Vertices.Length; i++)
            {
                Vertex vertex1 = newPolygon.Vertices[i].DeepCopy();
                Vertex vertex2 = newPolygon.Vertices[(i + 1) % newPolygon.Vertices.Length].DeepCopy();

                Vector2 uvDelta = vertex2.UV - vertex1.UV;

                float sourceDistance = Vector3.Distance(vertex1.Position, vertex2.Position);

                Vector2 rotatedUVDelta = uvDelta.Rotate(90) * (extrusionDistance / sourceDistance);

                Vertex vertex3 = vertex1.DeepCopy();
                vertex3.Position += normal * extrusionDistance;
                vertex3.UV       += rotatedUVDelta;

                Vertex vertex4 = vertex2.DeepCopy();
                vertex4.Position += normal * extrusionDistance;
                vertex4.UV       += rotatedUVDelta;

                Vertex[] newVertices = new Vertex[] { vertex1, vertex2, vertex4, vertex3 };

                brushSides[i] = new Polygon(newVertices, sourcePolygon.Material, false, false);
                brushSides[i].Flip();
                brushSides[i].ResetVertexNormals();
            }

            List <Polygon> polygons = new List <Polygon>();

            polygons.Add(newPolygon);
            polygons.Add(oppositePolygon);
            polygons.AddRange(brushSides);

            outputPolygons = polygons.ToArray();
            rotation       = Quaternion.identity;
        }
        public static Polygon[] GenerateCylinder(int sideCount = 20)
        {
            Polygon[] polygons = new Polygon[sideCount * 3];

            float angleDelta = Mathf.PI * 2 / sideCount;

            for (int i = 0; i < sideCount; i++)
            {
                polygons[i] = new Polygon(new Vertex[]
                {
                    new Vertex(new Vector3(Mathf.Sin(i * angleDelta), -1, Mathf.Cos(i * angleDelta)),
                               new Vector3(Mathf.Sin(i * angleDelta), 0, Mathf.Cos(i * angleDelta)),
                               new Vector2(i * (1f / sideCount), 0)),
                    new Vertex(new Vector3(Mathf.Sin((i + 1) * angleDelta), -1, Mathf.Cos((i + 1) * angleDelta)),
                               new Vector3(Mathf.Sin((i + 1) * angleDelta), 0, Mathf.Cos((i + 1) * angleDelta)),
                               new Vector2((i + 1) * (1f / sideCount), 0)),
                    new Vertex(new Vector3(Mathf.Sin((i + 1) * angleDelta), 1, Mathf.Cos((i + 1) * angleDelta)),
                               new Vector3(Mathf.Sin((i + 1) * angleDelta), 0, Mathf.Cos((i + 1) * angleDelta)),
                               new Vector2((i + 1) * (1f / sideCount), 1)),
                    new Vertex(new Vector3(Mathf.Sin(i * angleDelta), 1, Mathf.Cos(i * angleDelta)),
                               new Vector3(Mathf.Sin(i * angleDelta), 0, Mathf.Cos(i * angleDelta)),
                               new Vector2(i * (1f / sideCount), 1)),
                }, null, false, false);
            }

            Vertex capCenterVertex = new Vertex(new Vector3(0, 1, 0), Vector3.up, new Vector2(0, 0));

            for (int i = 0; i < sideCount; i++)
            {
                Vertex vertex1 = new Vertex(new Vector3(Mathf.Sin(i * angleDelta), 1, Mathf.Cos(i * angleDelta)), Vector3.up, new Vector2(Mathf.Sin(i * angleDelta), Mathf.Cos(i * angleDelta)));
                Vertex vertex2 = new Vertex(new Vector3(Mathf.Sin((i + 1) * angleDelta), 1, Mathf.Cos((i + 1) * angleDelta)), Vector3.up, new Vector2(Mathf.Sin((i + 1) * angleDelta), Mathf.Cos((i + 1) * angleDelta)));

                Vertex[] capVertices = new Vertex[] { vertex1, vertex2, capCenterVertex.DeepCopy() };
                polygons[sideCount + i] = new Polygon(capVertices, null, false, false);
            }

            capCenterVertex = new Vertex(new Vector3(0, -1, 0), Vector3.down, new Vector2(0, 0));

            for (int i = 0; i < sideCount; i++)
            {
                Vertex vertex1 = new Vertex(new Vector3(Mathf.Sin(i * -angleDelta), -1, Mathf.Cos(i * -angleDelta)), Vector3.down, new Vector2(Mathf.Sin(i * angleDelta), Mathf.Cos(i * angleDelta)));
                Vertex vertex2 = new Vertex(new Vector3(Mathf.Sin((i + 1) * -angleDelta), -1, Mathf.Cos((i + 1) * -angleDelta)), Vector3.down, new Vector2(Mathf.Sin((i + 1) * angleDelta), Mathf.Cos((i + 1) * angleDelta)));

                Vertex[] capVertices = new Vertex[] { vertex1, vertex2, capCenterVertex.DeepCopy() };
                polygons[sideCount * 2 + i] = new Polygon(capVertices, null, false, false);
            }

            return(polygons);
        }
Exemple #3
0
        /// <summary>
        /// Adapted from GetUVForPosition
        /// </summary>
        public static Vertex GetVertexForPosition(Vertex vertex1, Vertex vertex2, Vertex vertex3,
                                                  Vector3 newPosition)
        {
            Vector3 pos1 = vertex1.Position;
            Vector3 pos2 = vertex2.Position;
            Vector3 pos3 = vertex3.Position;

            //Plane plane = new Plane(pos1,pos2,pos3); // TODO Is it safe to replace this with the polygon Plane property?
            //Vector3 planePoint = MathHelper.ClosestPointOnPlane(newPosition, plane);
            Vector3 planePoint = newPosition;
            // calculate vectors from point f to vertices p1, p2 and p3:
            Vector3 f1 = pos1 - planePoint;
            Vector3 f2 = pos2 - planePoint;
            Vector3 f3 = pos3 - planePoint;

            // calculate the areas (parameters order is essential in this case):
            Vector3 va  = Vector3.Cross(pos1 - pos2, pos1 - pos3); // main triangle cross product
            Vector3 va1 = Vector3.Cross(f2, f3);                   // p1's triangle cross product
            Vector3 va2 = Vector3.Cross(f3, f1);                   // p2's triangle cross product
            Vector3 va3 = Vector3.Cross(f1, f2);                   // p3's triangle cross product

            float a = va.magnitude;                                // main triangle area

            // calculate barycentric coordinates with sign:
            float a1 = va1.magnitude / a * Mathf.Sign(Vector3.Dot(va, va1));
            float a2 = va2.magnitude / a * Mathf.Sign(Vector3.Dot(va, va2));
            float a3 = va3.magnitude / a * Mathf.Sign(Vector3.Dot(va, va3));

            Vertex vertex = vertex1.DeepCopy();

            // Interpolate normal and UV based on the barycentric coordinates
            vertex.Normal = vertex1.Normal * a1 + vertex2.Normal * a2 + vertex3.Normal * a3;
            vertex.UV     = vertex1.UV * a1 + vertex2.UV * a2 + vertex3.UV * a3;
            // Interpolate the color, slightly more complex as need to implicit cast from Color32 to Color and back for interpolation
            Color color1 = vertex1.Color;
            Color color2 = vertex1.Color;
            Color color3 = vertex1.Color;

            vertex.Color = color1 * a1 + color2 * a2 + color3 * a3;

            return(vertex);
        }
Exemple #4
0
        /// <summary>
        /// Generates a cone of height and radius 2. If the <see cref="sideCount"/> is 3, generates a triangular-based pyramid.
        /// </summary>
        /// <param name="sideCount">Side count for the cone (if 3, generates a triangular-based pyramid.).</param>
        /// <returns>Polygons to be supplied to a brush.</returns>
        public static Polygon[] GenerateCone(int sideCount = 20)
        {
            Polygon[] polygons = new Polygon[sideCount * 2];

            // the cone generator will create a slightly distorted off-center output for 3 sides.
            // if the user sets the side count to 3 we will generate a triangular-based pyramid.
            if (sideCount == 3)
            {
                polygons    = new Polygon[sideCount + 1];
                polygons[0] = new Polygon(new Vertex[]
                {
                    new Vertex(new Vector3(0, -1, -1), new Vector3(0.8402f, 0.2425f, -0.4851f), new Vector2(0.0000f, 0.0000f)),
                    new Vertex(new Vector3(0, 1, 0), new Vector3(0.8402f, 0.2425f, -0.4851f), new Vector2(0.5000f, 1.0000f)),
                    new Vertex(new Vector3(1, -1, 1), new Vector3(0.8402f, 0.2425f, -0.4851f), new Vector2(1.0000f, 0.0000f)),
                }, null, false, false);
                polygons[1] = new Polygon(new Vertex[]
                {
                    new Vertex(new Vector3(1, -1, 1), new Vector3(-0.0000f, 0.2425f, 0.9701f), new Vector2(0.0000f, 0.0000f)),
                    new Vertex(new Vector3(0, 1, 0), new Vector3(-0.0000f, 0.2425f, 0.9701f), new Vector2(0.5000f, 1.0000f)),
                    new Vertex(new Vector3(-1, -1, 1), new Vector3(-0.0000f, 0.2425f, 0.9701f), new Vector2(1.0000f, 0.0000f)),
                }, null, false, false);
                polygons[2] = new Polygon(new Vertex[]
                {
                    new Vertex(new Vector3(-1, -1, 1), new Vector3(-0.8402f, 0.2425f, -0.4851f), new Vector2(0.0000f, 0.0000f)),
                    new Vertex(new Vector3(0, 1, 0), new Vector3(-0.8402f, 0.2425f, -0.4851f), new Vector2(0.5000f, 1.0000f)),
                    new Vertex(new Vector3(0, -1, -1), new Vector3(-0.8402f, 0.2425f, -0.4851f), new Vector2(1.0000f, 0.0000f)),
                }, null, false, false);
                polygons[3] = new Polygon(new Vertex[]
                {
                    new Vertex(new Vector3(0, -1, -1), Vector3.down, new Vector2(0.0000f, 0.0000f)),
                    new Vertex(new Vector3(1, -1, 1), Vector3.down, new Vector2(1.0000f, 1.0000f)),
                    new Vertex(new Vector3(-1, -1, 1), Vector3.down, new Vector2(1.0000f, 0.0000f)),
                }, null, false, false);
                return(polygons);
            }

            float angleDelta = Mathf.PI * 2 / sideCount;

            for (int i = 0; i < sideCount; i++)
            {
                Vector3 normal = new Vector3(Mathf.Sin((i + 0.5f) * angleDelta), 0, Mathf.Cos((i + 0.5f) * angleDelta));

                polygons[i] = new Polygon(new Vertex[]
                {
                    new Vertex(new Vector3(Mathf.Sin(i * angleDelta), -1, Mathf.Cos(i * angleDelta)),
                               normal,
                               new Vector2(i * (1f / sideCount), 0)),
                    new Vertex(new Vector3(Mathf.Sin((i + 1) * angleDelta), -1, Mathf.Cos((i + 1) * angleDelta)),
                               normal,
                               new Vector2((i + 1) * (1f / sideCount), 0)),
                    new Vertex(new Vector3(0, 1, 0),
                               normal,
                               new Vector2((((i + 1) * (1f / sideCount)) + (i * (1f / sideCount))) / 2.0f, 1.0f)),
                }, null, false, false);
            }

            Vertex capCenterVertex = new Vertex(new Vector3(0, -1, 0), Vector3.down, new Vector2(0, 0));

            for (int i = 0; i < sideCount; i++)
            {
                Vertex vertex1 = new Vertex(new Vector3(Mathf.Sin(i * -angleDelta), -1, Mathf.Cos(i * -angleDelta)), Vector3.down, new Vector2(Mathf.Sin(i * angleDelta), Mathf.Cos(i * angleDelta)));
                Vertex vertex2 = new Vertex(new Vector3(Mathf.Sin((i + 1) * -angleDelta), -1, Mathf.Cos((i + 1) * -angleDelta)), Vector3.down, new Vector2(Mathf.Sin((i + 1) * angleDelta), Mathf.Cos((i + 1) * angleDelta)));

                Vertex[] capVertices = new Vertex[] { vertex1, vertex2, capCenterVertex.DeepCopy() };
                polygons[sideCount + i] = new Polygon(capVertices, null, false, false);
            }

            return(polygons);
        }
Exemple #5
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);
        }
Exemple #6
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);
        }
        public static void ExtrudePolygon(Polygon sourcePolygon, out Polygon[] outputPolygons, out Quaternion rotation)
        {
            float extrusionDistance = 1;

            Polygon basePolygon = sourcePolygon.DeepCopy();

            basePolygon.UniqueIndex = -1;

            rotation = Quaternion.LookRotation(basePolygon.Plane.normal);
            Quaternion cancellingRotation = Quaternion.Inverse(rotation);

            Vertex[] vertices = basePolygon.Vertices;
//			Vector3 offsetPosition = vertices[0].Position;

            for (int i = 0; i < vertices.Length; i++)
            {
//				vertices[i].Position -= offsetPosition;
                vertices[i].Position = cancellingRotation * vertices[i].Position;

                vertices[i].Normal = cancellingRotation * vertices[i].Normal;
            }

//			Vector3 newOffsetPosition = vertices[0].Position;
//			Vector3 delta = newOffsetPosition - offsetPosition;
//			for (int i = 0; i < vertices.Length; i++)
//			{
//				vertices[i].Position += delta;
//			}

            basePolygon.SetVertices(vertices);

            Vector3 normal          = basePolygon.Plane.normal;
            Polygon oppositePolygon = basePolygon.DeepCopy();

            oppositePolygon.UniqueIndex = -1;

            basePolygon.Flip();

            vertices = oppositePolygon.Vertices;
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Position += normal;
            }
            oppositePolygon.SetVertices(vertices);

            Polygon[] brushSides = new Polygon[sourcePolygon.Vertices.Length];

            for (int i = 0; i < basePolygon.Vertices.Length; i++)
            {
                Vertex vertex1 = basePolygon.Vertices[i].DeepCopy();
                Vertex vertex2 = basePolygon.Vertices[(i + 1) % basePolygon.Vertices.Length].DeepCopy();

                Vector2 uvDelta = vertex2.UV - vertex1.UV;

                float sourceDistance = Vector3.Distance(vertex1.Position, vertex2.Position);

                Vector2 rotatedUVDelta = uvDelta.Rotate(90) * (extrusionDistance / sourceDistance);

                Vertex vertex3 = vertex1.DeepCopy();
                vertex3.Position += normal * extrusionDistance;
                vertex3.UV       += rotatedUVDelta;

                Vertex vertex4 = vertex2.DeepCopy();
                vertex4.Position += normal * extrusionDistance;
                vertex4.UV       += rotatedUVDelta;

                Vertex[] newVertices = new Vertex[] { vertex1, vertex2, vertex4, vertex3 };

                brushSides[i] = new Polygon(newVertices, sourcePolygon.Material, false, false);
                brushSides[i].Flip();
                brushSides[i].ResetVertexNormals();
            }

            List <Polygon> polygons = new List <Polygon>();

            polygons.Add(basePolygon);
            polygons.Add(oppositePolygon);
            polygons.AddRange(brushSides);

            outputPolygons = polygons.ToArray();
        }
Exemple #8
0
        /// <summary>
        /// Creates a brush by extruding a supplied polygon by a specified extrusion distance.
        /// </summary>
        /// <param name="sourcePolygon">Source polygon, typically transformed into world space.</param>
        /// <param name="extrusionDistance">Extrusion distance, this is the height (or depth) of the created geometry perpendicular to the source polygon.</param>
        /// <param name="outputPolygons">Output brush polygons.</param>
        /// <param name="rotation">The rotation to be supplied to the new brush transform.</param>
        public static void ExtrudePolygon(Polygon sourcePolygon, float extrusionDistance, out Polygon[] outputPolygons, out Quaternion rotation)
        {
            bool flipped = false;

            if (extrusionDistance < 0)
            {
                sourcePolygon.Flip();
                extrusionDistance = -extrusionDistance;
                flipped           = true;
            }

            // Create base polygon
            Polygon basePolygon = sourcePolygon.DeepCopy();

            basePolygon.UniqueIndex = -1;

            rotation = Quaternion.LookRotation(basePolygon.Plane.normal);
            Quaternion cancellingRotation = Quaternion.Inverse(rotation);

            Vertex[] vertices = basePolygon.Vertices;

            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Position = cancellingRotation * vertices[i].Position;

                vertices[i].Normal = cancellingRotation * vertices[i].Normal;
            }

            basePolygon.SetVertices(vertices);

            // Create the opposite polygon by duplicating the base polygon, offsetting and flipping
            Vector3 normal          = basePolygon.Plane.normal;
            Polygon oppositePolygon = basePolygon.DeepCopy();

            oppositePolygon.UniqueIndex = -1;

            basePolygon.Flip();

            vertices = oppositePolygon.Vertices;
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i].Position += normal * extrusionDistance;
//				vertices[i].UV.x *= -1; // Flip UVs
            }
            oppositePolygon.SetVertices(vertices);

            // Now create each of the brush side polygons
            Polygon[] brushSides = new Polygon[sourcePolygon.Vertices.Length];

            for (int i = 0; i < basePolygon.Vertices.Length; i++)
            {
                Vertex vertex1 = basePolygon.Vertices[i].DeepCopy();
                Vertex vertex2 = basePolygon.Vertices[(i + 1) % basePolygon.Vertices.Length].DeepCopy();

                // Create new UVs for the sides, otherwise we'll get distortion

                float sourceDistance = Vector3.Distance(vertex1.Position, vertex2.Position);
                float uvDistance     = Vector2.Distance(vertex1.UV, vertex2.UV);

                float uvScale = sourceDistance / uvDistance;

                vertex1.UV = Vector2.zero;
                if (flipped)
                {
                    vertex2.UV = new Vector2(-sourceDistance / uvScale, 0);
                }
                else
                {
                    vertex2.UV = new Vector2(sourceDistance / uvScale, 0);
                }

                Vector2 uvDelta = vertex2.UV - vertex1.UV;

                Vector2 rotatedUVDelta = uvDelta.Rotate(90) * (extrusionDistance / sourceDistance);

                Vertex vertex3 = vertex1.DeepCopy();
                vertex3.Position += normal * extrusionDistance;
                vertex3.UV       += rotatedUVDelta;

                Vertex vertex4 = vertex2.DeepCopy();
                vertex4.Position += normal * extrusionDistance;
                vertex4.UV       += rotatedUVDelta;

                Vertex[] newVertices = new Vertex[] { vertex1, vertex2, vertex4, vertex3 };

                brushSides[i] = new Polygon(newVertices, sourcePolygon.Material, false, false);
                brushSides[i].Flip();
                brushSides[i].ResetVertexNormals();
            }

            List <Polygon> polygons = new List <Polygon>();

            polygons.Add(basePolygon);
            polygons.Add(oppositePolygon);
            polygons.AddRange(brushSides);

            outputPolygons = polygons.ToArray();
        }