示例#1
0
        /// <summary>
        /// Generates a mesh from supplied polygons, particularly useful for visualising a brush's polygons on a MeshFilter
        /// </summary>
        /// <param name="polygons">Polygons.</param>
        /// <param name="mesh">Mesh to be written to. Prior to settings the mesh buffers - if the existing mesh is null it will be set to a new one, otherwise the existing mesh is cleared</param>
        /// <param name="polygonIndices">Maps triangle index (input) to polygon index (output). i.e. int polyIndex = polygonIndices[triIndex];</param>
        public static void GenerateMeshFromPolygons(Polygon[] polygons, ref Mesh mesh, out List <int> polygonIndices)
        {
            if (mesh == null)
            {
                mesh = new Mesh();
            }
            mesh.Clear();
            //	        mesh = new Mesh();
            List <Vector3> vertices  = new List <Vector3>();
            List <Vector3> normals   = new List <Vector3>();
            List <Vector2> uvs       = new List <Vector2>();
            List <Color>   colors    = new List <Color>();
            List <int>     triangles = new List <int>();

            // Maps triangle index (input) to polygon index (output). i.e. int polyIndex = polygonIndices[triIndex];
            polygonIndices = new List <int>();

            // Set up an indexer that tracks unique vertices, so that we reuse vertex data appropiately
            VertexList vertexList = new VertexList();

            // Iterate through every polygon and triangulate
            for (int i = 0; i < polygons.Length; i++)
            {
                Polygon    polygon = polygons[i];
                List <int> indices = new List <int>();

                for (int j = 0; j < polygon.Vertices.Length; j++)
                {
                    // Each vertex must know about its shared data for geometry tinting
                    //polygon.Vertices[j].Shared = polygon.SharedBrushData;
                    // If the vertex is already in the indexer, fetch the index otherwise add it and get the added index
                    int index = vertexList.AddOrGet(polygon.Vertices[j]);
                    // Put each vertex index in an array for use in the triangle generation
                    indices.Add(index);
                }

                // Triangulate the n-sided polygon and allow vertex reuse by using indexed geometry
                for (int j = 2; j < indices.Count; j++)
                {
                    triangles.Add(indices[0]);
                    triangles.Add(indices[j - 1]);
                    triangles.Add(indices[j]);

                    // Map that this triangle is from the specified polygon (so we can map back from triangles to polygon)
                    polygonIndices.Add(i);
                }
            }

            // Create the relevant buffers from the vertex array
            for (int i = 0; i < vertexList.Vertices.Count; i++)
            {
                vertices.Add(vertexList.Vertices[i].Position);
                normals.Add(vertexList.Vertices[i].Normal);
                uvs.Add(vertexList.Vertices[i].UV);
                //	                colors.Add(((SharedBrushData)indexer.Vertices[i].Shared).BrushTintColor);
            }

            // Set the mesh buffers
            mesh.vertices  = vertices.ToArray();
            mesh.normals   = normals.ToArray();
            mesh.colors    = colors.ToArray();
            mesh.uv        = uvs.ToArray();
            mesh.triangles = triangles.ToArray();
        }
示例#2
0
        public static string ExportToString(Transform transform, List <Polygon> polygons, Material defaultMaterial)
        {
            // If a transform is provided, convert the world positions and normals to local to the transform
            if (transform != null)
            {
                for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
                {
                    Polygon polygon = polygons[polygonIndex];
                    for (int vertexIndex = 0; vertexIndex < polygon.Vertices.Length; vertexIndex++)
                    {
                        Vertex vertex = polygon.Vertices[vertexIndex];
                        vertex.Position = transform.InverseTransformPoint(vertex.Position);
                        vertex.Normal   = transform.InverseTransformDirection(vertex.Normal);
                    }
                }
            }

            // Create polygon subsets for each material
            Dictionary <Material, List <Polygon> > polygonMaterialTable = new Dictionary <Material, List <Polygon> >();

            // Iterate through every polygon adding it to the appropiate material list
            foreach (Polygon polygon in polygons)
            {
                if (polygon.UserExcludeFromFinal)
                {
                    continue;
                }

                Material material = polygon.Material;
                if (material == null)
                {
                    material = defaultMaterial;
                }
                if (!polygonMaterialTable.ContainsKey(material))
                {
                    polygonMaterialTable.Add(material, new List <Polygon>());
                }

                polygonMaterialTable[material].Add(polygon);
            }

            // Use a string builder as this should allow faster concatenation
            StringBuilder stringBuilder = new StringBuilder();

            OBJVertexList vertexList = new OBJVertexList();

            int positionIndexOffset = 0;
            int uvIndexOffset       = 0;
            int normalIndexOffset   = 0;

            int meshIndex = 1;

            // Create a separate mesh for polygons of each material so that we batch by material
            foreach (KeyValuePair <Material, List <Polygon> > polygonMaterialGroup in polygonMaterialTable)
            {
                List <List <OBJFaceVertex> > faces = new List <List <OBJFaceVertex> >(polygonMaterialGroup.Value.Count);

                // Iterate through every polygon and triangulate
                foreach (Polygon polygon in polygonMaterialGroup.Value)
                {
                    List <OBJFaceVertex> faceVertices = new List <OBJFaceVertex>(polygon.Vertices.Length);

                    for (int i = 0; i < polygon.Vertices.Length; i++)
                    {
                        OBJFaceVertex faceVertex = vertexList.AddOrGet(polygon.Vertices[i]);
                        faceVertices.Add(faceVertex);
                    }

                    faces.Add(faceVertices);
                }

                List <Vector3> positions = vertexList.Positions;
                List <Vector2> uvs       = vertexList.UVs;
                List <Vector3> normals   = vertexList.Normals;

                // Start a new group for the mesh
                stringBuilder.AppendLine("g Mesh" + meshIndex);

                // Write all the positions
                stringBuilder.AppendLine("# Vertex Positions: " + (positions.Count - positionIndexOffset));

                for (int i = positionIndexOffset; i < positions.Count; i++)
                {
                    stringBuilder.AppendLine("v " + WriteVector3(positions[i]));
                }

                // Write all the texture coordinates (UVs)
                stringBuilder.AppendLine("# Vertex UVs: " + (uvs.Count - uvIndexOffset));

                for (int i = uvIndexOffset; i < uvs.Count; i++)
                {
                    stringBuilder.AppendLine("vt " + WriteVector2(uvs[i]));
                }

                // Write all the normals
                stringBuilder.AppendLine("# Vertex Normals: " + (normals.Count - normalIndexOffset));

                for (int i = normalIndexOffset; i < normals.Count; i++)
                {
                    stringBuilder.AppendLine("vn " + WriteVector3(normals[i]));
                }

                // Write all the faces
                stringBuilder.AppendLine("# Faces: " + faces.Count);

                for (int i = 0; i < faces.Count; i++)
                {
                    stringBuilder.Append("f ");
                    for (int j = faces[i].Count - 1; j >= 0; j--)
                    {
                        stringBuilder.Append((faces[i][j].PositionIndex) + "/" + (faces[i][j].UVIndex) + "/" + (faces[i][j].NormalIndex) + " ");
                    }
                    stringBuilder.AppendLine();
                }

                // Add some padding between this and the next mesh
                stringBuilder.AppendLine();
                stringBuilder.AppendLine();

                meshIndex++;

                // Update the offsets so that the next pass only writes new vertex information
                positionIndexOffset = positions.Count;
                uvIndexOffset       = uvs.Count;
                normalIndexOffset   = normals.Count;
            }

            return(stringBuilder.ToString());
        }
示例#3
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);
        }
示例#4
0
        /// <summary>
        /// Generates a sphere of radius 2
        /// </summary>
        /// <returns>Polygons to be supplied to a brush.</returns>
        /// <param name="lateralCount">Vertex count up from the south pole to the north pole.</param>
        /// <param name="longitudinalCount">Vertex count around the sphere equator.</param>
        public static Polygon[] GeneratePolarSphere(int lateralCount = 6, int longitudinalCount = 12)
        {
            Polygon[] polygons = new Polygon[lateralCount * longitudinalCount];

            float angleDelta        = 1f / lateralCount;
            float longitudinalDelta = 1f / longitudinalCount;

            // Generate tris for the top and bottom, then quads for the rest
            for (int i = 0; i < lateralCount; i++)
            {
                for (int j = 0; j < longitudinalCount; j++)
                {
                    Vertex[] vertices;

                    if (i == lateralCount - 1)
                    {
                        vertices = new Vertex[] {
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector2(i * (1f / lateralCount), (j + 1) * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector2((i + 1) * (1f / lateralCount), (j + 1) * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector2(i * (1f / lateralCount), j * (1f / longitudinalCount))),
                        };
                    }
                    else if (i > 0)
                    {
                        vertices = new Vertex[] {
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector2(i * (1f / lateralCount), (j + 1) * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector2((i + 1) * (1f / lateralCount), (j + 1) * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector2((i + 1) * (1f / lateralCount), j * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector2(i * (1f / lateralCount), j * (1f / longitudinalCount))),
                        };
                    }
                    else                     // i == 0
                    {
                        vertices = new Vertex[] {
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * i * angleDelta),
                                                   Mathf.Sin(Mathf.PI * i * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector2(i * (1f / lateralCount), (j + 1) * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * (j + 1) * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * (j + 1) * longitudinalDelta)
                                                   ),
                                       new Vector2((i + 1) * (1f / lateralCount), (j + 1) * (1f / longitudinalCount))),
                            new Vertex(new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector3(Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Cos(2 * Mathf.PI * j * longitudinalDelta),
                                                   Mathf.Cos(Mathf.PI * (i + 1) * angleDelta),
                                                   Mathf.Sin(Mathf.PI * (i + 1) * angleDelta) * Mathf.Sin(2 * Mathf.PI * j * longitudinalDelta)
                                                   ),
                                       new Vector2((i + 1) * (1f / lateralCount), j * (1f / longitudinalCount))),
                        };
                    }

                    for (int d = 0; d < vertices.Length; d++)
                    {
                        vertices[d].UV = new Vector2(vertices[d].UV.y, 1 - vertices[d].UV.x);
                    }

                    polygons[i + j * lateralCount] = new Polygon(vertices, null, false, false);
                }
            }

            return(polygons);
        }
示例#5
0
        /// <summary>
        /// Finds the UV for a supplied position on a polygon, note this internally handles situations where vertices overlap or are colinear which the other version of this method does not
        /// </summary>
        /// <returns>The UV for the supplied position.</returns>
        /// <param name="polygon">Polygon.</param>
        /// <param name="newPosition">Position to find the UV for.</param>
        public static Vector2 GetUVForPosition(Polygon polygon, Vector3 newPosition)
        {
            int vertexIndex1 = 0;
            int vertexIndex2 = 0;
            int vertexIndex3 = 0;

            // Account for overlapping vertices
            for (int i = vertexIndex1 + 1; i < polygon.Vertices.Length; i++)
            {
                if (!polygon.Vertices[i].Position.EqualsWithEpsilon(polygon.Vertices[vertexIndex1].Position))
                {
                    vertexIndex2 = i;
                    break;
                }
            }

            for (int i = vertexIndex2 + 1; i < polygon.Vertices.Length; i++)
            {
                if (!polygon.Vertices[i].Position.EqualsWithEpsilon(polygon.Vertices[vertexIndex2].Position))
                {
                    vertexIndex3 = i;
                    break;
                }
            }

            // Now account for the fact that the picked three vertices might be collinear
            Vector3 pos1 = polygon.Vertices[vertexIndex1].Position;
            Vector3 pos2 = polygon.Vertices[vertexIndex2].Position;
            Vector3 pos3 = polygon.Vertices[vertexIndex3].Position;

            Plane plane = new Plane(pos1, pos2, pos3);

            if (plane.normal == Vector3.zero)
            {
                for (int i = 2; i < polygon.Vertices.Length; i++)
                {
                    vertexIndex3 = i;

                    pos3 = polygon.Vertices[vertexIndex3].Position;

                    Plane tempPlane = new Plane(pos1, pos2, pos3);

                    if (tempPlane.normal != Vector3.zero)
                    {
                        break;
                    }
                }
                plane = new Plane(pos1, pos2, pos3);
            }

            // Should now have a good set of positions, so continue

            Vector3 planePoint = MathHelper.ClosestPointOnPlane(newPosition, plane);

            Vector2 uv1 = polygon.Vertices[vertexIndex1].UV;
            Vector2 uv2 = polygon.Vertices[vertexIndex2].UV;
            Vector2 uv3 = polygon.Vertices[vertexIndex3].UV;

            // 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));

            // find the uv corresponding to point f (uv1/uv2/uv3 are associated to p1/p2/p3):
            Vector2 uv = uv1 * a1 + uv2 * a2 + uv3 * a3;

            return(uv);
        }
示例#6
0
        /// <summary>
        /// Generates a cube (size 2,2,2)
        /// </summary>
        /// <returns>Polygons to be supplied to a brush.</returns>
        public static Polygon[] GenerateCube()
        {
            Polygon[] polygons = new Polygon[6];

            // Polygons and vertices are created in a clockwise order

            // Polygons are created in this order: back, left, front, right, bottom, top

            // Vertices with those polygons are created in this order: BR, BL, TL, TR (when viewed aligned with the UV)

            // Therefore to move the two bottom vertices of the left face, you would pick the second face (index 1) and
            // then	manipulate the first two vertices (indexes 0 and 1)

            // Back
            polygons[0] = new Polygon(new Vertex[] {
                new Vertex(new Vector3(-1, -1, 1), new Vector3(0, 0, 1), new Vector2(1, 0)),
                new Vertex(new Vector3(1, -1, 1), new Vector3(0, 0, 1), new Vector2(0, 0)),
                new Vertex(new Vector3(1, 1, 1), new Vector3(0, 0, 1), new Vector2(0, 1)),
                new Vertex(new Vector3(-1, 1, 1), new Vector3(0, 0, 1), new Vector2(1, 1)),
            }, null, false, false);

            // Left
            polygons[1] = new Polygon(new Vertex[] {
                new Vertex(new Vector3(-1, -1, -1), new Vector3(-1, 0, 0), new Vector2(1, 0)),
                new Vertex(new Vector3(-1, -1, 1), new Vector3(-1, 0, 0), new Vector2(0, 0)),
                new Vertex(new Vector3(-1, 1, 1), new Vector3(-1, 0, 0), new Vector2(0, 1)),
                new Vertex(new Vector3(-1, 1, -1), new Vector3(-1, 0, 0), new Vector2(1, 1)),
            }, null, false, false);

            // Front
            polygons[2] = new Polygon(new Vertex[] {
                new Vertex(new Vector3(1, -1, 1), new Vector3(1, 0, 0), new Vector2(1, 0)),
                new Vertex(new Vector3(1, -1, -1), new Vector3(1, 0, 0), new Vector2(0, 0)),
                new Vertex(new Vector3(1, 1, -1), new Vector3(1, 0, 0), new Vector2(0, 1)),
                new Vertex(new Vector3(1, 1, 1), new Vector3(1, 0, 0), new Vector2(1, 1)),
            }, null, false, false);

            // Right
            polygons[3] = new Polygon(new Vertex[] {
                new Vertex(new Vector3(1, -1, -1), new Vector3(0, 0, -1), new Vector2(1, 0)),
                new Vertex(new Vector3(-1, -1, -1), new Vector3(0, 0, -1), new Vector2(0, 0)),
                new Vertex(new Vector3(-1, 1, -1), new Vector3(0, 0, -1), new Vector2(0, 1)),
                new Vertex(new Vector3(1, 1, -1), new Vector3(0, 0, -1), new Vector2(1, 1)),
            }, null, false, false);

            // Bottom
            polygons[4] = new Polygon(new Vertex[] {
                new Vertex(new Vector3(-1, -1, -1), new Vector3(0, -1, 0), new Vector2(1, 0)),
                new Vertex(new Vector3(1, -1, -1), new Vector3(0, -1, 0), new Vector2(0, 0)),
                new Vertex(new Vector3(1, -1, 1), new Vector3(0, -1, 0), new Vector2(0, 1)),
                new Vertex(new Vector3(-1, -1, 1), new Vector3(0, -1, 0), new Vector2(1, 1)),
            }, null, false, false);

            // Top
            polygons[5] = new Polygon(new Vertex[] {
                new Vertex(new Vector3(-1, 1, -1), new Vector3(0, 1, 0), new Vector2(1, 0)),
                new Vertex(new Vector3(-1, 1, 1), new Vector3(0, 1, 0), new Vector2(0, 0)),
                new Vertex(new Vector3(1, 1, 1), new Vector3(0, 1, 0), new Vector2(0, 1)),
                new Vertex(new Vector3(1, 1, -1), new Vector3(0, 1, 0), new Vector2(1, 1)),
            }, null, false, false);

            return(polygons);
        }
 static bool IsPolygonCeiling(Polygon polygon)
 {
     return(Vector3.Dot(polygon.Plane.normal, Vector3.up) < -0.99f);
 }
        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();
        }
 static bool IsPolygonFloor(Polygon polygon)
 {
     return(Vector3.Dot(polygon.Plane.normal, Vector3.up) > 0.99f);
 }
        /// <summary>
        /// Constructs a polygon from an unordered coplanar set of positions
        /// </summary>
        /// <param name="sourcePositions"></param>
        /// <param name="removeExtraPositions"></param>
        /// <returns></returns>
        public static Polygon ConstructPolygon(List <Vector3> sourcePositions, bool removeExtraPositions)
        {
            List <Vector3> positions;

            if (removeExtraPositions)
            {
                positions = new List <Vector3>();
                for (int i = 0; i < sourcePositions.Count; i++)
                {
                    Vector3 sourcePosition = sourcePositions[i];
                    bool    contained      = false;

                    for (int j = 0; j < positions.Count; j++)
                    {
                        if (positions[j].EqualsWithEpsilonLower(sourcePosition))
                        {
                            contained = true;
                            break;
                        }
                    }

                    if (!contained)
                    {
                        positions.Add(sourcePosition);
                    }
                }
            }
            else
            {
                positions = sourcePositions;
            }



            // If positions is smaller than 3 then we can't construct a polygon. This could happen if you try to cut the
            // tip off a very, very thin brush. While the plane and the brushes would intersect, the actual
            // cross-sectional area is near zero and too small to create a valid polygon. In this case simply return
            // null to indicate polygon creation was impossible
            if (positions.Count < 3)
            {
                return(null);
            }

            // Find center point, so we can sort the positions around it
            Vector3 center = positions[0];

            for (int i = 1; i < positions.Count; i++)
            {
                center += positions[i];
            }

            center *= 1f / positions.Count;

            if (positions.Count < 3)
            {
                Debug.LogError("Position count is below 3, this is probably unhandled");
            }

            // Find the plane
            UnityEngine.Plane plane = new UnityEngine.Plane(positions[0], positions[1], positions[2]);



            // Rotation to go from the polygon's plane to XY plane (for sorting)
            Quaternion cancellingRotation;

            if (plane.normal != Vector3.zero)
            {
                cancellingRotation = Quaternion.Inverse(Quaternion.LookRotation(plane.normal));
            }
            else
            {
                cancellingRotation = Quaternion.identity;
            }

            // Rotate the center point onto the plane too
            Vector3 rotatedCenter = cancellingRotation * center;

            // Sort the positions, passing the rotation to put the positions on XY plane and the rotated center point
            IComparer <Vector3> comparer = new SortVectorsClockwise(cancellingRotation, rotatedCenter);

            positions.Sort(comparer);

            // Create the vertices from the positions
            Vertex[] newPolygonVertices = new Vertex[positions.Count];
            for (int i = 0; i < positions.Count; i++)
            {
                newPolygonVertices[i] = new Vertex(positions[i], -plane.normal, (cancellingRotation * positions[i]) * 0.5f);
            }
            Polygon newPolygon = new Polygon(newPolygonVertices, null, false, false);

            if (newPolygon.Plane.normal == Vector3.zero)
            {
                Debug.LogError("Zero normal found, this leads to invalid polyhedron-point tests");
                return(null);
                // hacky
                //				if(removeExtraPositions)
                //				{
                //					Polygon.Vector3ComparerEpsilon equalityComparer = new Polygon.Vector3ComparerEpsilon();
                //					List<Vector3> testFoo = newPolygonVertices.Select(item => item.Position).Distinct(equalityComparer).ToList();
                //				}
            }
            return(newPolygon);
        }
        internal static bool SplitCoplanarPolygonsByPlane(List <Polygon> polygons, // Source polygons that will be split
                                                          Plane splitPlane,
                                                          out List <Polygon> polygonsFront,
                                                          out List <Polygon> polygonsBack)
        {
            polygonsFront = new List <Polygon>();
            polygonsBack  = new List <Polygon>();

            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
            {
                Polygon.PolygonPlaneRelation planeRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);

                // Polygon has been found to span both sides of the plane, attempt to split into two pieces
                if (planeRelation == Polygon.PolygonPlaneRelation.Spanning)
                {
                    Polygon frontPolygon;
                    Polygon backPolygon;
                    Vertex  newVertex1;
                    Vertex  newVertex2;

                    // Attempt to split the polygon
                    if (Polygon.SplitPolygon(polygons[polygonIndex], out frontPolygon, out backPolygon, out newVertex1, out newVertex2, splitPlane))
                    {
                        // If the split algorithm was successful (produced two valid polygons) then add each polygon to
                        // their respective points and track the intersection points
                        polygonsFront.Add(frontPolygon);
                        polygonsBack.Add(backPolygon);
                    }
                    else
                    {
                        // Two valid polygons weren't generated, so use the valid one
                        if (frontPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;
                        }
                        else if (backPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.Behind;
                        }
                        else
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;

                            Debug.LogError("Polygon splitting has resulted in two zero area polygons. This is unhandled.");
                            //							Polygon.PolygonPlaneRelation secondplaneRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);
                        }
                    }
                }

                // If the polygon is on one side of the plane or the other
                if (planeRelation != Polygon.PolygonPlaneRelation.Spanning)
                {
                    if (planeRelation == Polygon.PolygonPlaneRelation.Behind)
                    {
                        polygonsBack.Add(polygons[polygonIndex]);
                    }
                    else
                    {
                        polygonsFront.Add(polygons[polygonIndex]);
                    }
                }
            }

            if (polygonsBack.Count >= 1 &&
                polygonsFront.Count >= 1)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        internal static bool SplitPolygonsByPlane(List <Polygon> polygons,       // Source polygons that will be split
                                                  Plane splitPlane,
                                                  bool excludeNewPolygons,       // Whether new polygons should be marked as excludeFromBuild
                                                  out List <Polygon> polygonsFront,
                                                  out List <Polygon> polygonsBack)
        {
            polygonsFront = new List <Polygon>();
            polygonsBack  = new List <Polygon>();

            // First of all make sure splitting actually needs to occur (we'll get bad issues if
            // we try splitting geometry when we don't need to)
            if (!GeometryHelper.PolygonsIntersectPlane(polygons, splitPlane))
            {
                return(false);
            }

            // These are the vertices that will be used in the new caps
            List <Vertex> newVertices = new List <Vertex>();

            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
            {
                Polygon.PolygonPlaneRelation planeRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);

                // Polygon has been found to span both sides of the plane, attempt to split into two pieces
                if (planeRelation == Polygon.PolygonPlaneRelation.Spanning)
                {
                    Polygon frontPolygon;
                    Polygon backPolygon;
                    Vertex  newVertex1;
                    Vertex  newVertex2;

                    // Attempt to split the polygon
                    if (Polygon.SplitPolygon(polygons[polygonIndex], out frontPolygon, out backPolygon, out newVertex1, out newVertex2, splitPlane))
                    {
                        // If the split algorithm was successful (produced two valid polygons) then add each polygon to
                        // their respective points and track the intersection points
                        polygonsFront.Add(frontPolygon);
                        polygonsBack.Add(backPolygon);

                        newVertices.Add(newVertex1);
                        newVertices.Add(newVertex2);
                    }
                    else
                    {
                        // Two valid polygons weren't generated, so use the valid one
                        if (frontPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;
                        }
                        else if (backPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.Behind;
                        }
                        else
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;

                            Debug.LogError("Polygon splitting has resulted in two zero area polygons. This is unhandled.");
                            //							Polygon.PolygonPlaneRelation secondplaneRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);
                        }
                    }
                }

                // If the polygon is on one side of the plane or the other
                if (planeRelation != Polygon.PolygonPlaneRelation.Spanning)
                {
                    // Make sure any points that are coplanar on non-straddling polygons are still used in polygon
                    // construction
                    for (int vertexIndex = 0; vertexIndex < polygons[polygonIndex].Vertices.Length; vertexIndex++)
                    {
                        if (Polygon.ComparePointToPlane(polygons[polygonIndex].Vertices[vertexIndex].Position, splitPlane) == Polygon.PointPlaneRelation.On)
//						if(Polygon.ComparePointToPlane2(polygons[polygonIndex].Vertices[vertexIndex].Position, splitPlane) == Polygon.PointPlaneRelation.On)
                        {
                            newVertices.Add(polygons[polygonIndex].Vertices[vertexIndex]);
                        }
                    }

                    if (planeRelation == Polygon.PolygonPlaneRelation.Behind)
                    {
                        polygonsBack.Add(polygons[polygonIndex]);
                    }
                    else
                    {
                        polygonsFront.Add(polygons[polygonIndex]);
                    }
                }
            }

            // If any splits occured or coplanar vertices are found. (For example if you're splitting a sphere at the
            // equator then no polygons will be split but there will be a bunch of coplanar vertices!)
            if (newVertices.Count > 0 &&
                polygonsBack.Count >= 3 &&
                polygonsFront.Count >= 3)
            {
                // HACK: This code is awful, because we end up with lots of duplicate vertices
                List <Vector3> positions = new List <Vector3>(newVertices.Count);
                for (int i = 0; i < newVertices.Count; i++)
                {
                    positions.Add(newVertices[i].Position);
                }

                Polygon newPolygon = PolygonFactory.ConstructPolygon(positions, true);

                // Assuming it was possible to create a polygon
                if (newPolygon != null)
                {
                    if (!MathHelper.PlaneEqualsLooser(newPolygon.Plane, splitPlane))
                    {
                        // Polygons are sometimes constructed facing the wrong way, possibly due to a winding order
                        // mismatch. If the two normals are opposite, flip the new polygon
                        if (Vector3.Dot(newPolygon.Plane.normal, splitPlane.normal) < -0.9f)
                        {
                            newPolygon.Flip();
                        }
                    }

                    newPolygon.ExcludeFromFinal = excludeNewPolygons;

                    polygonsFront.Add(newPolygon);

                    newPolygon = newPolygon.DeepCopy();
                    newPolygon.Flip();

                    newPolygon.ExcludeFromFinal = excludeNewPolygons;


                    if (newPolygon.Plane.normal == Vector3.zero)
                    {
                        Debug.LogError("Invalid Normal! Shouldn't be zero. This is unexpected since extraneous positions should have been removed!");
                        //						Polygon fooNewPolygon = PolygonFactory.ConstructPolygon(positions, true);
                    }

                    polygonsBack.Add(newPolygon);
                }
                return(true);
            }
            else
            {
                // It wasn't possible to create the polygon, for example the constructed polygon was too small
                // This could happen if you attempt to clip the tip off a long but thin brush, the plane-polyhedron test
                // would say they intersect but in reality the resulting polygon would be near zero area
                return(false);
            }
        }
示例#13
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);
        }