/// <summary>
        /// Generates a tetris "Block"
        /// </summary>
        /// <param name="random">The randomizer to use</param>
        /// <param name="pieceID">The ID of the piece</param>
        /// <param name="minSize">The minimal size</param>
        /// <param name="maxSize">The maximal size</param>
        /// <param name="roundedDecimals">The number of decimal places</param>
        /// <returns>The generated piece</returns>
        public static VariablePiece GenerateTetrisBlock(Random random, ref int pieceID, double minSize, double maxSize, int roundedDecimals)
        {
            VariablePiece piece = new VariablePiece();

            piece.ID = ++pieceID;
            piece.AddComponent(0, 0, 0,
                               Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals),
                               Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals),
                               Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals));
            piece.Seal();
            return(piece);
        }
        /// <summary>
        /// Generates a tetris "L"
        /// </summary>
        /// <param name="random">The randomizer to use</param>
        /// <param name="pieceID">The ID of the piece</param>
        /// <param name="minSize">The minimal size</param>
        /// <param name="maxSize">The maximal size</param>
        /// <param name="roundedDecimals">The number of decimal places</param>
        /// <returns>The generated piece</returns>
        public static VariablePiece GenerateTetrisL(Random random, ref int pieceID, double minSize, double maxSize, int roundedDecimals, double lengthBreak)
        {
            double        length      = Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals);
            double        width       = Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals);
            double        height      = Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals);
            double        breakLength = length * lengthBreak;
            double        breakHeight = height * lengthBreak;
            VariablePiece piece       = new VariablePiece();

            piece.ID = ++pieceID;
            piece.AddComponent(0, 0, 0, breakLength, width, height);
            piece.AddComponent(breakLength, 0, 0, length - breakLength, width, breakHeight);
            piece.Seal();
            return(piece);
        }
        /// <summary>
        /// Generates a set of pieces
        /// </summary>
        /// <param name="count">The number of pieces to generate</param>
        /// <param name="minSize">The minimal size of the pieces</param>
        /// <param name="maxSize">The maximal size of the pieces</param>
        /// <param name="minEquals">The number of minimal equals</param>
        /// <param name="maxEquals">The number of maximal equals</param>
        /// <param name="seed">The seed used for generation</param>
        /// <param name="roundedDecimals">The number of decimal places</param>
        /// <returns>The generated pieces</returns>
        public static List <VariablePiece> GeneratePieces(int count, double minSize, double maxSize, int minEquals, int maxEquals, int seed = 0, int roundedDecimals = 0)
        {
            // Init
            Random random = new Random(seed);
            List <VariablePiece> pieces = new List <VariablePiece>();

            // Generate as many pieces as desired
            for (int i = 0; i < count;)
            {
                // Init piece
                VariablePiece piece = new VariablePiece()
                {
                    ID = i,
                };
                // Add the parallelepiped component
                piece.AddComponent(0, 0, 0,
                                   Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals),
                                   Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals),
                                   Math.Round(minSize + random.NextDouble() * (maxSize - minSize), roundedDecimals));
                // Seal it
                piece.Seal();
                // Possibly make it non rotatable
                double forbiddenOrientationsChance = random.NextDouble();
                if (forbiddenOrientationsChance > 0.9)
                {
                    piece.ForbiddenOrientations = new HashSet <int>(MeshConstants.ORIENTATIONS.Except(MeshConstants.ORIENTATIONS_THIS_SIDE_UP));
                }
                // Possibly give a non-standard material
                double materialChance = random.NextDouble();
                if (materialChance > 0.8)
                {
                    if (materialChance > 0.9)
                    {
                        piece.Material = new Material()
                        {
                            MaterialClass = MaterialClassification.Explosive
                        };
                    }
                    else
                    {
                        piece.Material = new Material()
                        {
                            MaterialClass = MaterialClassification.FlammableGas
                        };
                    }
                }
                // Possibly make piece not stackable
                double stackableChance = random.NextDouble();
                if (stackableChance > 0.9)
                {
                    piece.Stackable = false;
                }
                // Clone the piece to generate sufficient 'equals'
                int equalCount = random.Next(minEquals, maxEquals + 1);
                for (int j = 0; i < count && j < equalCount; j++, i++)
                {
                    VariablePiece clonePiece = piece.Clone();
                    clonePiece.ID = i + 1;
                    pieces.Add(clonePiece);
                }
            }

            // Return
            return(pieces);
        }