public static void AddArcVerts(List <Vertex3DColor> verts, Vector3 pos1, Vector3 pos2, float radius, Vector4 color)
        {
            // Project points onto sphere of given radius
            pos1.Normalize();
            pos2.Normalize();

            // Determine arc degree:
            double dot = Vector3.Dot(pos1, pos2);

            if (dot != 1)
            {
                double theta = Math.Acos(dot);
                pos2 *= radius;
                pos2 *= radius;
                double SineTheta = Math.Sin(theta);
                // Slerp = Sine(theta-angle)*pos1/Sine(theta) + Sine(angle)*pos2/Sine(theta)
                // angle: 0 -> theta
                // iterate along arc, generating points each 0.2 degrees
                for (double angle = 0.0f; angle <= theta; angle += Math.PI / 1800.0f)
                {
                    Vector3       pAngle = (float)(Math.Sin(theta - angle) / SineTheta) * pos1 + (float)(Math.Sin(angle) / SineTheta) * pos2;
                    Vertex3DColor vertex = new Vertex3DColor(pAngle, color);
                    verts.Add(vertex);
                }
            }
        }
        static public IComplexGeometry CreateIcosphere(int subDivisions)
        {
            Vertex3DColor[] verts  = new Vertex3DColor[12];
            Vector4         color  = new Vector4(0.2f, 0.2f, 1.0f, 1.0f);
            Vector4         color2 = new Vector4(1.0f, 0.2f, 1.0f, 1.0f);
            Vector4         color3 = new Vector4(0.2f, 1.0f, 1.0f, 1.0f);

            const float t = 1.61803398875f;                                                 // approximation of golden ratio

            verts[0] = new Vertex3DColor(Vector3.Normalize(new Vector3(-1, t, 0)), color2); // Subdivision generates Sierpinski triangle at pole
            verts[1] = new Vertex3DColor(Vector3.Normalize(new Vector3(1, t, 0)), color);
            verts[2] = new Vertex3DColor(Vector3.Normalize(new Vector3(-1, -t, 0)), color);
            verts[3] = new Vertex3DColor(Vector3.Normalize(new Vector3(1, -t, 0)), color3); // Subdivision generates Sierpinski triangle at other pole

            verts[4] = new Vertex3DColor(Vector3.Normalize(new Vector3(0, -1, t)), color);
            verts[5] = new Vertex3DColor(Vector3.Normalize(new Vector3(0, 1, t)), color);
            verts[6] = new Vertex3DColor(Vector3.Normalize(new Vector3(0, -1, -t)), color);
            verts[7] = new Vertex3DColor(Vector3.Normalize(new Vector3(0, 1, -t)), color);

            verts[8]  = new Vertex3DColor(Vector3.Normalize(new Vector3(t, 0, -1)), color);
            verts[9]  = new Vertex3DColor(Vector3.Normalize(new Vector3(t, 0, 1)), color);
            verts[10] = new Vertex3DColor(Vector3.Normalize(new Vector3(-t, 0, -1)), color);
            verts[11] = new Vertex3DColor(Vector3.Normalize(new Vector3(-t, 0, 1)), color);
            var mesh    = new Mesh <Vertex3DColor>(verts);
            var indices = new List <uint>();

            AddIndices(ref indices, 0, 1, 7);
            AddIndices(ref indices, 0, 5, 1);
            AddIndices(ref indices, 0, 11, 5);
            AddIndices(ref indices, 0, 10, 11);
            AddIndices(ref indices, 0, 7, 10);

            AddIndices(ref indices, 1, 5, 9);
            AddIndices(ref indices, 5, 4, 9);
            AddIndices(ref indices, 5, 11, 4);
            AddIndices(ref indices, 11, 2, 4);
            AddIndices(ref indices, 11, 10, 2);

            AddIndices(ref indices, 10, 6, 2);
            AddIndices(ref indices, 10, 7, 6);
            AddIndices(ref indices, 7, 8, 6);
            AddIndices(ref indices, 7, 1, 8);
            AddIndices(ref indices, 1, 9, 8);

            AddIndices(ref indices, 3, 4, 2);
            AddIndices(ref indices, 3, 2, 6);
            AddIndices(ref indices, 3, 6, 8);
            AddIndices(ref indices, 3, 8, 9);
            AddIndices(ref indices, 3, 9, 4);

            var geometry  = new ComplexGeometry <Vertex3DColor>(mesh, indices.ToArray());
            int vertCount = geometry.SubDivide(subDivisions);

            return(geometry);
        }