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
            }
        }