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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return(polygons);
        }
示例#3
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);
        }
示例#4
0
        /// <summary>
        /// Exports the supplied polygons to a OBJ format string, typically you'll use ExportToFile rather than ExportToString
        /// </summary>
        /// <returns>The OBJ file contents.</returns>
        /// <param name="transform">If a transform is provided, the vertex positions and normals are converted from world space to local to the transform.</param>
        /// <param name="polygons">Polygons to export.</param>
        /// <param name="defaultMaterial">Default material to use if none present on polygon.</param>
        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));

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

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

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

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

                for (int i = 0; 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 + positionIndexOffset) + "/" + (faces[i][j].UVIndex + uvIndexOffset) + "/" + (faces[i][j].NormalIndex + normalIndexOffset) + " ");
                    }
                    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;

                vertexList.ResetForNext();
            }

            return(stringBuilder.ToString());
        }