public static void ZQuad( IModel m, int texX, int texY, int texWidth, int texHeight,
     float x1, float x2, float y1, float y2, float z)
 {
     m.vertices[m.index++] = new ModelVertex( x1, y1, z, texX, texY + texHeight );
     m.vertices[m.index++] = new ModelVertex( x1, y2, z, texX, texY );
     m.vertices[m.index++] = new ModelVertex( x2, y2, z, texX + texWidth, texY );
     m.vertices[m.index++] = new ModelVertex( x2, y1, z, texX + texWidth, texY + texHeight );
 }
 public static void YQuad( IModel m, int texX, int texY, int texWidth, int texHeight,
     float x1, float x2, float z1, float z2, float y)
 {
     m.vertices[m.index++] = new ModelVertex( x1, y, z2, texX, texY + texHeight );
     m.vertices[m.index++] = new ModelVertex( x1, y, z1, texX, texY );
     m.vertices[m.index++] = new ModelVertex( x2, y, z1, texX + texWidth, texY );
     m.vertices[m.index++] = new ModelVertex( x2, y, z2, texX + texWidth, texY + texHeight );
 }
        /// <summary>Builds a box model assuming the follow texture layout:<br/>
        /// let SW = sides width, BW = body width, BH = body height<br/>
        /// ┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┈┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┃S┈┈┈┈┈┈┈┈┈┈┈S┃S┈┈┈┈front┈┈┈S┃S┈┈┈back┈┈┈┈S┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┃W┈┈┈┈┈┈┈┈┈W┃W┈┈┈┈tex┈┈┈W┃W┈┈┈┈tex┈┈┈┈W┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┈┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┣━━━━━━━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━━━━━━━━╋━━━━━━━━━━━━┃ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈SW┈┈┈┈┈┈┃┈┈┈┈┈SW┈┈┈┈┃ <br/>
        /// ┃B┈┈┈left┈┈┈┈┈B┃B┈┈bottom┈┈B┃B┈┈┈right┈┈┈┈B┃B┈┈┈┈top┈┈┈B┃ <br/>
        /// ┃H┈┈┈tex┈┈┈┈┈H┃H┈┈tex┈┈┈┈┈H┃H┈┈┈tex┈┈┈┈┈H┃H┈┈┈┈tex┈┈┈H┃ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈SW┈┈┈┈┈┈┃┈┈┈┈┈SW┈┈┈┈┃ <br/>
        /// ┗━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━━━━┛ </summary>
        public static ModelPart BuildRotatedBox( IModel m, BoxDesc desc )
        {
            int sidesW = desc.SidesW, bodyW = desc.BodyW, bodyH = desc.BodyH;
            float x1 = desc.X1, y1 = desc.Y1, z1 = desc.Z1;
            float x2 = desc.X2, y2 = desc.Y2, z2 = desc.Z2;
            int x = desc.TexX, y = desc.TexY;

            YQuad( m, x + sidesW + bodyW + sidesW, y + sidesW, bodyW, bodyH, x1, x2, z1, z2, y2 ); // top
            YQuad( m, x + sidesW, y + sidesW, bodyW, bodyH, x2, x1, z1, z2, y1 ); // bottom
            ZQuad( m, x + sidesW, y, bodyW, sidesW, x2, x1, y1, y2, z1 ); // front
            ZQuad( m, x + sidesW + bodyW, y, bodyW, sidesW, x1, x2, y2, y1, z2 ); // back
            XQuad( m, x, y + sidesW, sidesW, bodyH, y2, y1, z2, z1, x2 ); // left
            XQuad( m, x + sidesW + bodyW, y + sidesW, sidesW, bodyH, y1, y2, z2, z1, x1 ); // right

            // rotate left and right 90 degrees
            for( int i = m.index - 8; i < m.index; i++ ) {
                ModelVertex vertex = m.vertices[i];
                float z = vertex.Z; vertex.Z = vertex.Y; vertex.Y = z;
                m.vertices[i] = vertex;
            }
            return new ModelPart( m.index - 6 * 4, 6 * 4, desc.RotX, desc.RotY, desc.RotZ );
        }
 public static void XQuad( IModel m, int texX, int texY, int texWidth, int texHeight,
     float z1, float z2, float y1, float y2, float x)
 {
     m.vertices[m.index++] = new ModelVertex( x, y1, z1, texX, texY + texHeight );
     m.vertices[m.index++] = new ModelVertex( x, y2, z1, texX, texY );
     m.vertices[m.index++] = new ModelVertex( x, y2, z2, texX + texWidth, texY );
     m.vertices[m.index++] = new ModelVertex( x, y1, z2, texX + texWidth, texY + texHeight );
 }
        /// <summary>Builds a box model assuming the follow texture layout:<br/>
        /// let SW = sides width, BW = body width, BH = body height<br/>
        /// ┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┈┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┃S┈┈┈┈┈┈┈┈┈┈┈S┃S┈┈┈┈top┈┈┈┈S┃S┈┈bottom┈┈┈S┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┃W┈┈┈┈┈┈┈┈┈W┃W┈┈┈┈tex┈┈┈W┃W┈┈┈┈tex┈┈┈┈W┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┈┃┈┈┈┈┈┈┈┈┈┈┈┈┃ <br/>
        /// ┣━━━━━━━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━━━━━━━━╋━━━━━━━━━━━━┃ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┈┃┈┈┈┈┈SW┈┈┈┈┃ <br/>
        /// ┃B┈┈┈left┈┈┈┈┈B┃B┈┈front┈┈┈┈B┃B┈┈┈right┈┈┈┈B┃B┈┈┈back┈┈┈B┃ <br/>
        /// ┃H┈┈┈tex┈┈┈┈┈H┃H┈┈tex┈┈┈┈┈H┃H┈┈┈tex┈┈┈┈┈H┃H┈┈┈┈tex┈┈┈H┃ <br/>
        /// ┃┈┈┈┈┈SW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┃┈┈┈┈┈BW┈┈┈┈┈┈┃┈┈┈┈┈SW┈┈┈┈┃ <br/>
        /// ┗━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━━━━━━━┛ </summary>
        public static ModelPart BuildBox( IModel m, BoxDesc desc )
        {
            int sidesW = desc.SidesW, bodyW = desc.BodyW, bodyH = desc.BodyH;
            float x1 = desc.X1, y1 = desc.Y1, z1 = desc.Z1;
            float x2 = desc.X2, y2 = desc.Y2, z2 = desc.Z2;
            int x = desc.TexX, y = desc.TexY;

            YQuad( m, x + sidesW, y, bodyW, sidesW, x2, x1, z2, z1, y2 ); // top
            YQuad( m, x + sidesW + bodyW, y, bodyW, sidesW, x2, x1, z2, z1, y1 ); // bottom
            ZQuad( m, x + sidesW, y + sidesW, bodyW, bodyH, x2, x1, y1, y2, z1 ); // front
            ZQuad( m, x + sidesW + bodyW + sidesW, y + sidesW, bodyW, bodyH, x1, x2, y1, y2, z2 ); // back
            XQuad( m, x, y + sidesW, sidesW, bodyH, z2, z1, y1, y2, x2 ); // left
            XQuad( m, x + sidesW + bodyW, y + sidesW, sidesW, bodyH, z1, z2, y1, y2, x1 ); // right
            return new ModelPart( m.index - 6 * 4, 6 * 4, desc.RotX, desc.RotY, desc.RotZ );
        }