// Given a face, splits it into a uniform grid and extrudes each grid face
        // out and back in again, making an exhaust shape.
        private void AddExhaustToFace(GenMesh genmesh, GenMeshFace faceForExhaust)
        {
            // The more square the face is, the more grid divisions it might have
            var num_cuts = Random.Range(1, (int)(4 - faceForExhaust.AspectRatio));
            var result   = genmesh.Subdivide(faceForExhaust, num_cuts);

            var exhaust_length = Random.Range(0.1f, 0.2f);
            var scaleOuter     = 1f / Random.Range(1.3f, 1.6f);
            var scale_inner    = 1f / Random.Range(1.05f, 1.1f);

            for (var i = 0; i < result.Count(); i++)
            {
                var face = result[i];
                face.MaterialIndex = 2;// Material.hull_dark;

                face = ExtrudeFace(genmesh, face, exhaust_length);
                ScaleFace(genmesh, face, scaleOuter, scaleOuter, scaleOuter);

                face = ExtrudeFace(genmesh, face, 0);
                ScaleFace(genmesh, face, scaleOuter * 0.9f, scaleOuter * 0.9f, scaleOuter * 0.9f);

                var extruded_face_list = new List <GenMeshFace>();
                face = ExtrudeFace(genmesh, face, -exhaust_length * 0.9f, extruded_face_list);

                foreach (var extruded_face in extruded_face_list)
                {
                    extruded_face.MaterialIndex = 3;// Material.exhaust_burn
                }
                ScaleFace(genmesh, face, scale_inner, scale_inner, scale_inner);
            }
        }
        private void AddDiscToFace(GenMesh genmesh, GenMeshFace fac)
        {
            var faceWidth  = fac.Width;
            var faceHeight = fac.Height;
            var depth      = 0.125f * Mathf.Min(faceWidth, faceHeight);

            genmesh.CreateCylinder(
                32,
                depth * 3,
                depth * 4,
                depth,
                GetFaceMatrix(fac, fac.CalculateCenterBounds() + fac.Normal * depth * 0.5f));

            genmesh.CreateCylinder(
                32,
                depth * 1.25f,
                depth * 2.25f,
                0.0f,
                GetFaceMatrix(fac, fac.CalculateCenterBounds() + fac.Normal * depth * 1.05f));

            /*
             * for vert in result['verts']:
             * for face in vert.link_faces:
             * face.material_index = Material.glow_disc
             *
             */
        }
        private void AddGridToFace(GenMesh genmesh, GenMeshFace fac)
        {
            var result     = genmesh.Subdivide(fac, Random.Range(2, 4));
            var gridLength = Random.Range(0.025f, 0.15f);
            var scale      = 0.8f;

            for (var i = 0; i < result.Length; i++)
            {
                var face             = result[i];
                var materialIndex    = Random.value > 0.5f ? 1 /*Material.hull_lights*/ : 4 /*Material.hull*/;
                var extrudedFaceList = new List <GenMeshFace>();

                face = ExtrudeFace(genmesh, face, gridLength, extrudedFaceList);

                foreach (var f in extrudedFaceList)
                {
                    if (Mathf.Abs(face.Normal.z) < 0.707) // # side face
                    {
                        f.MaterialIndex = materialIndex;
                    }
                }

                ScaleFace(genmesh, face, scale, scale, scale);
            }
        }
        private void AddSphereToFace(GenMesh genmesh, GenMeshFace fac)
        {
            var sphereSize   = Random.Range(0.4f, 1f) * Mathf.Min(fac.Width, fac.Height);
            var sphereMatrix = GetFaceMatrix(fac, fac.CalculateCenterBounds() - fac.Normal * Random.Range(0f, sphereSize * 0.5f));

            genmesh.CreateIcosphere(3, sphereSize, sphereMatrix);

            /*
             * for vert in result['verts']:
             * for face in vert.link_faces:
             * face.material_index = Material.hull
             */
        }
        private void AddWeaponsToFace(GenMesh genmesh, GenMeshFace fac)
        {
            var horizontalStep = Random.Range(1, 3);
            var verticalStep   = Random.Range(1, 3);
            var numSegments    = 16;

            var weaponSize  = 0.5f * Mathf.Min(fac.Width / (horizontalStep + 2), fac.Height / (verticalStep + 2));
            var weaponDepth = weaponSize * 0.2f;

            for (var h = 0; h < horizontalStep; h++)
            {
                var top    = Vector3.Lerp(fac.LeftTop.Coordinates, fac.RightTop.Coordinates, (float)(h + 1) / (horizontalStep + 1));
                var bottom = Vector3.Lerp(fac.LeftBottom.Coordinates, fac.RightBottom.Coordinates, (float)(h + 1) / (horizontalStep + 1));

                for (var v = 0; v < verticalStep; v++)
                {
                    var pos        = Vector3.Lerp(top, bottom, (float)(v + 1) / (verticalStep + 1));
                    var faceMatrix = GetFaceMatrix(fac, pos + fac.Normal * weaponDepth * 0.5f) *
                                     Matrix4x4.Rotate(Quaternion.AngleAxis(Random.Range(0, 90), new Vector3(0, 0, 1)));


                    // Turret foundation
                    genmesh.CreateCylinder(numSegments, weaponSize * 0.9f, weaponSize, weaponDepth, faceMatrix);

                    // Turret left guard
                    var leftGuardMat = faceMatrix *
                                       Matrix4x4.Rotate(Quaternion.AngleAxis(90, new Vector3(0, 1, 0))) *
                                       Matrix4x4.Translate(new Vector3(0, 0, weaponSize * 0.6f));
                    genmesh.CreateCylinder(numSegments, weaponSize * 0.6f, weaponSize * 0.5f, weaponDepth * 2, leftGuardMat);

                    // Turret right guard
                    var rightGuardMat = faceMatrix *
                                        Matrix4x4.Rotate(Quaternion.AngleAxis(90, new Vector3(0, 1, 0))) *
                                        Matrix4x4.Translate(new Vector3(0, 0, weaponSize * -0.6f));
                    genmesh.CreateCylinder(numSegments, weaponSize * 0.5f, weaponSize * 0.6f, weaponDepth * 2, rightGuardMat);

                    // Turret housing
                    var upwardAngle    = Random.Range(0, 45);
                    var turretHouseMat = faceMatrix *
                                         Matrix4x4.Rotate(Quaternion.AngleAxis(upwardAngle, new Vector3(1, 0, 0))) *
                                         Matrix4x4.Translate(new Vector3(0, weaponSize * -0.4f, 0));
                    genmesh.CreateCylinder(8, weaponSize * 0.4f, weaponSize * 0.4f, weaponDepth * 5, turretHouseMat);

                    // Turret barrels L + R
                    genmesh.CreateCylinder(8, weaponSize * 0.1f, weaponSize * 0.1f, weaponDepth * 6, turretHouseMat *
                                           Matrix4x4.Translate(new Vector3(weaponSize * 0.2f, 0, -weaponSize)));
                    genmesh.CreateCylinder(8, weaponSize * 0.1f, weaponSize * 0.1f, weaponDepth * 6, turretHouseMat *
                                           Matrix4x4.Translate(new Vector3(weaponSize * -0.2f, 0, -weaponSize)));
                }
            }
        }
        private GenMeshFace ExtrudeFace(GenMesh genmesh, GenMeshFace face, float distance, List <GenMeshFace> extrudedFaces = null)
        {
            var newFaces = genmesh.ExtrudeDiscreetFace(face);

            if (extrudedFaces != null)
            {
                extrudedFaces.AddRange(newFaces);
            }

            var newFace = newFaces[0];

            genmesh.Translate(newFace.Normal * distance, newFace.Vertices);

            return(newFace);
        }
        private void AddSurfaceAntennaToFace(GenMesh genmesh, GenMeshFace fac)
        {
            var horizontalStep = Random.Range(4, 10);
            var verticalStep   = Random.Range(4, 10);

            for (var h = 0; h < horizontalStep; h++)
            {
                var top    = Vector3.Lerp(fac.LeftTop.Coordinates, fac.RightTop.Coordinates, ((float)h + 1) / (horizontalStep + 1));
                var bottom = Vector3.Lerp(fac.LeftBottom.Coordinates, fac.RightBottom.Coordinates, ((float)h + 1) / (horizontalStep + 1));

                for (var v = 0; v < verticalStep; v++)
                {
                    if (Random.value > 0.9f)
                    {
                        var pos           = Vector3.Lerp(top, bottom, ((float)v + 1) / (verticalStep + 1));
                        var faceSize      = Mathf.Sqrt(fac.Area());
                        var depth         = Random.Range(0.1f, 1.5f) * faceSize;
                        var depthShort    = depth * Random.Range(0.02f, 0.15f);
                        var baseDiameter  = Random.Range(0.005f, 0.05f);
                        var materialIndex = Random.value > 0.5f ? 0 /*Material.hull*/ : 1;/*Material.hull_dark*/

                        // Spire
                        var numSegments = Random.Range(3, 6);
                        genmesh.CreateCylinder(numSegments, 0, baseDiameter, depth, GetFaceMatrix(fac, pos + fac.Normal * depth * 0.5f));

                        //for vert in result['verts']:
                        //    for vert_face in vert.link_faces:
                        //        vert_face.material_index = material_index
                        //    }

                        // Base
                        genmesh.CreateCylinder(
                            numSegments,
                            baseDiameter * Random.Range(1f, 1.5f),
                            baseDiameter * Random.Range(1.5f, 2f),
                            depthShort,
                            GetFaceMatrix(fac, pos + fac.Normal * depthShort * 0.45f));

                        //    for vert in result['verts']:
                        //for vert_face in vert.link_faces:
                        //    vert_face.material_index = material_index
                    }
                }
            }
        }
        private GenMeshFace RibbedExtrudeFace(GenMesh genmesh, GenMeshFace face, float distance, int numberOfRibs = 3, float ribScale = 0.9f)
        {
            var distancePerRib = distance / numberOfRibs;
            var newFace        = face;

            for (var i = 0; i < numberOfRibs; i++)
            {
                newFace = ExtrudeFace(genmesh, newFace, distancePerRib * 0.25f);
                newFace = ExtrudeFace(genmesh, newFace, 0.0f);
                ScaleFace(genmesh, newFace, ribScale, ribScale, ribScale);
                newFace = ExtrudeFace(genmesh, newFace, distancePerRib * 0.5f);
                newFace = ExtrudeFace(genmesh, newFace, 0.0f);
                ScaleFace(genmesh, newFace, 1 / ribScale, 1 / ribScale, 1 / ribScale);
                newFace = ExtrudeFace(genmesh, newFace, distancePerRib * 0.25f);
            }

            return(newFace);
        }
        public static GenMesh CreateCylinder(int numberOfSegments, float cylinderSize1, float cylinderSize2, float cylinderDepth)
        {
            var mesh        = new GenMesh();
            var lowerCircle = new List <GenMeshVertex>();
            var upperCircle = new List <GenMeshVertex>();

            for (var i = 0; i < numberOfSegments; i++)
            {
                lowerCircle.Add(new GenMeshVertex(new Vector3(
                                                      Mathf.Cos((float)i / numberOfSegments * Mathf.PI * 2) * cylinderSize1 / 2,
                                                      Mathf.Sin((float)i / numberOfSegments * Mathf.PI * 2) * cylinderSize1 / 2,
                                                      -cylinderDepth / 2
                                                      )));

                upperCircle.Add(new GenMeshVertex(new Vector3(
                                                      Mathf.Cos((float)i / numberOfSegments * Mathf.PI * 2) * cylinderSize2 / 2,
                                                      Mathf.Sin((float)i / numberOfSegments * Mathf.PI * 2) * cylinderSize2 / 2,
                                                      cylinderDepth / 2)));
            }

            for (var i = 0; i < numberOfSegments; i++)
            {
                mesh.Faces.Add(new GenMeshSquareFace(
                                   upperCircle[i],
                                   upperCircle[(i + 1) % numberOfSegments],
                                   lowerCircle[(i + 1) % numberOfSegments],
                                   lowerCircle[i]
                                   ));
            }

            mesh.Faces.Add(new GenMeshComplexFace(lowerCircle.ToArray(),
                                                  BowyerWatson.GetTris(lowerCircle.Select(e => (Vector2)e.Coordinates * 100))));

            mesh.Faces.Add(new GenMeshComplexFace(upperCircle.ToArray(),
                                                  BowyerWatson.GetTris(lowerCircle.Select(e => (Vector2)e.Coordinates * 100), true)));

            return(mesh);
        }
        public static GenMesh CreateCube(float size = 1)
        {
            var mesh = new GenMesh();

            // create 8 vertices the notation is XYZ so for vertex that's on top face on the left top it will be LTT
            var LTT = new GenMeshVertex(new Vector3(-size, +size, -size));
            var RTT = new GenMeshVertex(new Vector3(+size, +size, -size));
            var RTB = new GenMeshVertex(new Vector3(+size, +size, +size));
            var LTB = new GenMeshVertex(new Vector3(-size, +size, +size));

            var LBT = new GenMeshVertex(new Vector3(-size, -size, -size));
            var RBT = new GenMeshVertex(new Vector3(+size, -size, -size));
            var RBB = new GenMeshVertex(new Vector3(+size, -size, +size));
            var LBB = new GenMeshVertex(new Vector3(-size, -size, +size));

            // create 6 faces

            // top face
            mesh.Faces.Add(new GenMeshSquareFace(RTT, RTB, LTB, LTT));

            // left face
            mesh.Faces.Add(new GenMeshSquareFace(LTB, LBB, LBT, LTT));

            // right face
            mesh.Faces.Add(new GenMeshSquareFace(RTT, RBT, RBB, RTB));

            // front face
            mesh.Faces.Add(new GenMeshSquareFace(RTB, RBB, LBB, LTB));

            // back face
            mesh.Faces.Add(new GenMeshSquareFace(LTT, LBT, RBT, RTT));

            // bottom face
            mesh.Faces.Add(new GenMeshSquareFace(LBT, LBB, RBB, RBT));

            return(mesh);
        }
        private void AddCylindersToFace(GenMesh genmesh, GenMeshFace fac)
        {
            var horizontalStep   = Random.Range(1, 3);
            var verticalStep     = Random.Range(1, 3);
            var numberOfSegments = Random.Range(6, 12);
            var faceWidth        = fac.Width;
            var faceHeight       = fac.Height;
            var cylinderDepth    = 1.3f * Mathf.Min(faceWidth / (horizontalStep + 2), faceHeight / (verticalStep + 2));
            var cylinderSize     = cylinderDepth * 0.5f;

            for (var h = 0; h < horizontalStep; h++)
            {
                var top    = Vector3.Lerp(fac.LeftTop.Coordinates, fac.RightTop.Coordinates, ((float)h + 1) / (horizontalStep + 1));
                var bottom = Vector3.Lerp(fac.LeftBottom.Coordinates, fac.RightBottom.Coordinates, ((float)h + 1) / (horizontalStep + 1));

                for (var v = 0; v < verticalStep; v++)
                {
                    var pos            = Vector3.Lerp(top, bottom, ((float)v + 1) / (verticalStep + 1));
                    var cylinderMatrix = GetFaceMatrix(fac, pos) * Matrix4x4.Rotate(Quaternion.AngleAxis(90, new Vector3(0, 1, 0)));

                    genmesh.CreateCylinder(numberOfSegments, cylinderSize, cylinderSize, cylinderDepth, cylinderMatrix);
                }
            }
        }
 private void ScaleFace(GenMesh genmesh, GenMeshFace face, float sx, float sy, float sz)
 {
     genmesh.Scale(new Vector3(sx, sy, sz), GetFaceMatrix(face).inverse, face.Vertices);
 }
        private void Generate(GenMesh genmesh)
        {
            var scaleFactor = Random.Range(0.75f, 2.0f);
            var scaleVector = Vector3.one * scaleFactor;

            genmesh.Scale(scaleVector, genmesh.Vertices);

            var faces = genmesh.Faces.ToArray();

            for (var f = 0; f < faces.Length; f++)
            {
                var face = faces[f];

                if (Mathf.Abs(face.Normal.x) > 0.5f)
                {
                    var hullSegmentLength    = Random.Range(0.3f, 1.0f);
                    var numberOfHullSegments = Random.Range(numHullSegmentsMin, numHullSegmentsMax);

                    for (var i = 0; i < numberOfHullSegments; i++)
                    {
                        var isLastHullSegment = i == numberOfHullSegments - 1;
                        var val = Random.value;

                        if (val > 0.1f)
                        {
                            // Most of the time, extrude out the face with some random deviations
                            face = this.ExtrudeFace(genmesh, face, hullSegmentLength);

                            if (Random.value > 0.75f)
                            {
                                face = this.ExtrudeFace(genmesh, face, hullSegmentLength * 0.25f);
                            }

                            // Maybe apply some scaling
                            if (Random.value > 0.5f)
                            {
                                var sy = Random.Range(1.2f, 1.5f);
                                var sz = Random.Range(1.2f, 1.5f);

                                if (isLastHullSegment || Random.value > 0.5f)
                                {
                                    sy = 1f / sy;
                                    sz = 1f / sz;
                                }

                                this.ScaleFace(genmesh, face, 1f, sy, sz);
                            }

                            // Maybe apply some sideways translation
                            if (Random.value > 0.5f)
                            {
                                var sidewaysTranslation = new Vector3(0f, 0f, Random.Range(0.1f, 0.4f) * scaleVector.z * hullSegmentLength);

                                if (Random.value > 0.5f)
                                {
                                    sidewaysTranslation = -sidewaysTranslation;
                                }

                                genmesh.Translate(sidewaysTranslation, face.Vertices);
                            }

                            // Maybe add some rotation around Z axis
                            if (Random.value > 0.5f)
                            {
                                var angle = 5f;
                                if (Random.value > 0.5f)
                                {
                                    angle = -angle;
                                }

                                var quaterion = Quaternion.AngleAxis(angle, new Vector3(0, 0, 1));
                                genmesh.Rotate(face.Vertices, new Vector3(0, 0, 0), quaterion);
                            }
                        }
                        else
                        {
                            // Rarely, create a ribbed section of the hull
                            var ribScale = Random.Range(0.75f, 0.95f);
                            face = this.RibbedExtrudeFace(genmesh, face, hullSegmentLength, Random.Range(2, 4), ribScale);
                        }
                    }
                }
            }

            //Add some large asymmetrical sections of the hull that stick out
            if (createAsymmetrySegments)
            {
                var potentialFaces = genmesh.Faces.ToArray();
                for (var f = 0; f < potentialFaces.Length; f++)
                {
                    var face = potentialFaces[f];

                    if (face.AspectRatio > 4f)
                    {
                        continue;
                    }

                    if (Random.value > 0.85f)
                    {
                        var hullPieceLength = Random.Range(0.1f, 0.4f);
                        var totalSegments   = Random.Range(numAsymmetrySegmentsMin, numAsymmetrySegmentsMax);

                        for (var i = 0; i < totalSegments; i++)
                        {
                            face = ExtrudeFace(genmesh, face, hullPieceLength);

                            // Maybe apply some scaling
                            if (Random.value > 0.25f)
                            {
                                var s = 1f / Random.Range(1.1f, 1.5f);
                                ScaleFace(genmesh, face, s, s, s);
                            }
                        }
                    }
                }
            }

            // Now the basic hull shape is built, let's categorize + add detail to all the faces
            if (createFaceDetail)
            {
                var engineFaces   = new List <GenMeshFace>();
                var gridFaces     = new List <GenMeshFace>();
                var antennaFaces  = new List <GenMeshFace>();
                var weaponFaces   = new List <GenMeshFace>();
                var sphereFaces   = new List <GenMeshFace>();
                var discFaces     = new List <GenMeshFace>();
                var cylinderFaces = new List <GenMeshFace>();

                faces = genmesh.Faces.ToArray();
                for (var f = 0; f < faces.Length; f++)
                {
                    var face = faces[f];

                    // Skip any long thin faces as it'll probably look stupid
                    if (face.AspectRatio > 3)
                    {
                        continue;
                    }

                    // Spin the wheel! Let's categorize + assign some materials
                    var val = Random.value;

                    if (face.Normal.x < -0.9f)
                    {
                        if (!engineFaces.Any() || val > 0.75f)
                        {
                            engineFaces.Add(face);
                        }
                        else if (val > 0.5f)
                        {
                            cylinderFaces.Add(face);
                        }
                        else if (val > 0.25f)
                        {
                            gridFaces.Add(face);
                        }
                        else
                        {
                            face.MaterialIndex = 1;//Material.hull_lights
                        }
                    }
                    else if (face.Normal.x > 0.9f) // front face
                    {
                        if (Vector3.Dot(face.Normal, face.CalculateCenterBounds()) > 0 && val > 0.7f)
                        {
                            antennaFaces.Add(face); // front facing antenna
                            face.MaterialIndex = 1; // Material.hull_lights
                        }
                        else if (val > 0.4f)
                        {
                            gridFaces.Add(face);
                        }
                        else
                        {
                            face.MaterialIndex = 1;// Material.hull_lights
                        }
                    }
                    else if (face.Normal.y > 0.9f) // top face
                    {
                        if (Vector3.Dot(face.Normal, face.CalculateCenterBounds()) > 0 && val > 0.7f)
                        {
                            antennaFaces.Add(face);  // top facing antenna
                        }
                        else if (val > 0.6f)
                        {
                            gridFaces.Add(face);
                        }
                        else if (val > 0.3f)
                        {
                            cylinderFaces.Add(face);
                        }
                    }
                    else if (face.Normal.y < -0.9f) // bottom face
                    {
                        if (val > 0.75f)
                        {
                            discFaces.Add(face);
                        }
                        else if (val > 0.5f)
                        {
                            gridFaces.Add(face);
                        }
                        else if (val > 0.25f)
                        {
                            weaponFaces.Add(face);
                        }
                    }
                    else if (Mathf.Abs(face.Normal.z) > 0.9f) // side face
                    {
                        if (!weaponFaces.Any() || val > 0.75f)
                        {
                            weaponFaces.Add(face);
                        }
                        else if (val > 0.6f)
                        {
                            gridFaces.Add(face);
                        }
                        else if (val > 0.4f)
                        {
                            sphereFaces.Add(face);
                        }
                        else
                        {
                            face.MaterialIndex = 1;// Material.hull_lights
                        }
                    }
                }

                // Now we've categorized, let's actually add the detail
                foreach (var fac in engineFaces)
                {
                    AddExhaustToFace(genmesh, fac);
                }

                foreach (var fac in gridFaces)
                {
                    AddGridToFace(genmesh, fac);
                }

                foreach (var fac in antennaFaces)
                {
                    AddSurfaceAntennaToFace(genmesh, fac);
                }

                foreach (var fac in weaponFaces)
                {
                    AddWeaponsToFace(genmesh, fac);
                }

                foreach (var fac in sphereFaces)
                {
                    AddSphereToFace(genmesh, fac);
                }

                foreach (var fac in discFaces)
                {
                    AddDiscToFace(genmesh, fac);
                }

                foreach (var fac in cylinderFaces)
                {
                    AddCylindersToFace(genmesh, fac);
                }
            }

            // Apply horizontal symmetry sometimes
            if (allowHorizontalSymmetry && Random.value > 0.5f)
            {
                genmesh.Symmetrize(Axis.Horizontal);
            }

            // Apply vertical symmetry sometimes - this can cause spaceship "islands", so disabled by default
            if (allowHorizontalSymmetry && Random.value > 0.5f)
            {
                genmesh.Symmetrize(Axis.Vertical);
            }

            if (applyBevelModifier)
            {
                // TODO
            }
        }
Пример #14
0
        public override GenMeshFace[] Subdivide(int numberOfCuts)
        {
            var steps = numberOfCuts + 2;

            var topSize    = (this.RightTop.Coordinates - this.LeftTop.Coordinates).magnitude;
            var bottomSize = (this.RightBottom.Coordinates - this.LeftBottom.Coordinates).magnitude;
            var leftSize   = (this.LeftTop.Coordinates - this.LeftBottom.Coordinates).magnitude;
            var rightSize  = (this.RightTop.Coordinates - this.RightBottom.Coordinates).magnitude;

            var result = new List <GenMeshFace>();

            var topPoints    = new List <Vector3>();
            var bottomPoints = new List <Vector3>();
            var leftPoints   = new List <Vector3>();
            var rightPoints  = new List <Vector3>();


            for (var i = 0; i < steps; i++)
            {
                // horizontal
                var hfrom = Vector3.Lerp(this.LeftTop.Coordinates, this.RightTop.Coordinates, ((float)i) / (steps - 1));
                var hto   = Vector3.Lerp(this.LeftBottom.Coordinates, this.RightBottom.Coordinates, ((float)i) / (steps - 1));

                // vertical
                var vfrom = Vector3.Lerp(this.LeftTop.Coordinates, this.LeftBottom.Coordinates, ((float)i) / (steps - 1));
                var vto   = Vector3.Lerp(this.RightTop.Coordinates, this.RightBottom.Coordinates, ((float)i) / (steps - 1));

                topPoints.Add(hfrom);
                bottomPoints.Add(hto);
                leftPoints.Add(vfrom);
                rightPoints.Add(vto);
            }

            var points = new Vector3[steps, steps];

            for (var x = 0; x < steps; x++)
            {
                for (var y = 0; y < steps; y++)
                {
                    var top    = topPoints[x];
                    var bottom = bottomPoints[x];
                    var left   = leftPoints[y];
                    var right  = rightPoints[y];

                    Vector3 intersection;
                    if (!GenMesh.LineLineIntersection(out intersection, top, (bottom - top), left, (right - left)))
                    {
                        throw new InvalidOperationException("Points here should always intersect");
                    }

                    points[x, y] = intersection;
                }
            }

            for (var x = 0; x < steps - 1; x++)
            {
                for (var y = 0; y < steps - 1; y++)
                {
                    result.Add(new GenMeshSquareFace(
                                   new GenMeshVertex(points[x, y]),
                                   new GenMeshVertex(points[x, y + 1]),
                                   new GenMeshVertex(points[x + 1, y + 1]),
                                   new GenMeshVertex(points[x + 1, y])));
                }
            }

            return(result.ToArray());
        }