public static void Create(GameObject gameObject, float height, CelestialBody celestialBody)
        {
            float radius = 1;

            if (celestialBody == null)
            {
                radius = height;
            }
            MeshFilter filter = gameObject.AddComponent <MeshFilter>();
            Mesh       mesh   = filter.mesh;

            mesh.Clear();

            List <Vector3>         vertList = new List <Vector3>();
            Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>();

            int recursionLevel = 4;

            if (celestialBody != null)
            {
                recursionLevel = 6;
            }

            // create 12 vertices of a icosahedron
            float t = (1f + Mathf.Sqrt(5f)) / 2f;

            vertList.Add(new Vector3(-1f, t, 0f).normalized *radius);
            vertList.Add(new Vector3(1f, t, 0f).normalized *radius);
            vertList.Add(new Vector3(-1f, -t, 0f).normalized *radius);
            vertList.Add(new Vector3(1f, -t, 0f).normalized *radius);

            vertList.Add(new Vector3(0f, -1f, t).normalized *radius);
            vertList.Add(new Vector3(0f, 1f, t).normalized *radius);
            vertList.Add(new Vector3(0f, -1f, -t).normalized *radius);
            vertList.Add(new Vector3(0f, 1f, -t).normalized *radius);

            vertList.Add(new Vector3(t, 0f, -1f).normalized *radius);
            vertList.Add(new Vector3(t, 0f, 1f).normalized *radius);
            vertList.Add(new Vector3(-t, 0f, -1f).normalized *radius);
            vertList.Add(new Vector3(-t, 0f, 1f).normalized *radius);


            // create 20 triangles of the icosahedron
            List <TriangleIndices> faces = new List <TriangleIndices>();

            // 5 faces around point 0
            faces.Add(new TriangleIndices(0, 11, 5));
            faces.Add(new TriangleIndices(0, 5, 1));
            faces.Add(new TriangleIndices(0, 1, 7));
            faces.Add(new TriangleIndices(0, 7, 10));
            faces.Add(new TriangleIndices(0, 10, 11));

            // 5 adjacent faces
            faces.Add(new TriangleIndices(1, 5, 9));
            faces.Add(new TriangleIndices(5, 11, 4));
            faces.Add(new TriangleIndices(11, 10, 2));
            faces.Add(new TriangleIndices(10, 7, 6));
            faces.Add(new TriangleIndices(7, 1, 8));

            // 5 faces around point 3
            faces.Add(new TriangleIndices(3, 9, 4));
            faces.Add(new TriangleIndices(3, 4, 2));
            faces.Add(new TriangleIndices(3, 2, 6));
            faces.Add(new TriangleIndices(3, 6, 8));
            faces.Add(new TriangleIndices(3, 8, 9));

            // 5 adjacent faces
            faces.Add(new TriangleIndices(4, 9, 5));
            faces.Add(new TriangleIndices(2, 4, 11));
            faces.Add(new TriangleIndices(6, 2, 10));
            faces.Add(new TriangleIndices(8, 6, 7));
            faces.Add(new TriangleIndices(9, 8, 1));


            // refine triangles
            for (int i = 0; i < recursionLevel; i++)
            {
                List <TriangleIndices> faces2 = new List <TriangleIndices>();
                foreach (var tri in faces)
                {
                    // replace triangle by 4 triangles
                    int a = getMiddlePoint(tri.v1, tri.v2, ref vertList, ref middlePointIndexCache, radius);
                    int b = getMiddlePoint(tri.v2, tri.v3, ref vertList, ref middlePointIndexCache, radius);
                    int c = getMiddlePoint(tri.v3, tri.v1, ref vertList, ref middlePointIndexCache, radius);

                    faces2.Add(new TriangleIndices(tri.v1, a, c));
                    faces2.Add(new TriangleIndices(tri.v2, b, a));
                    faces2.Add(new TriangleIndices(tri.v3, c, b));
                    faces2.Add(new TriangleIndices(a, b, c));
                }
                faces = faces2;
            }

            Vector3[] normals = new Vector3[vertList.Count];
            for (int i = 0; i < normals.Length; i++)
            {
                normals[i] = vertList[i].normalized;
            }

            if (celestialBody != null)
            {
                for (int i = 0; i < vertList.Count; i++)
                {
                    Vector3d rotVert = Tools.RotateY(vertList[i], .5 * Math.PI);
                    float    value   = (float)(height + celestialBody.pqsController.GetSurfaceHeight(rotVert));
                    vertList[i] *= value;
                }
            }

            mesh.vertices = vertList.ToArray();

            List <int> triList = new List <int>();

            for (int i = 0; i < faces.Count; i++)
            {
                triList.Add(faces[i].v1);
                triList.Add(faces[i].v2);
                triList.Add(faces[i].v3);
            }
            mesh.triangles = triList.ToArray();

            float          invPi2 = 1 / (2 * Mathf.PI);
            float          invPi  = 1 / (Mathf.PI);
            List <Vector2> uvList = new List <Vector2>();

            for (int i = 0; i < vertList.Count; i++)
            {
                Vector2 uv     = new Vector2();
                Vector3 normal = vertList[i].normalized;
                uv.x = 0.5f + invPi2 * Mathf.Atan2(normal.z, normal.x);
                uv.y = 0.5f - invPi * Mathf.Asin(normal.y);
                uvList.Add(uv);
            }
            mesh.uv = uvList.ToArray();

            mesh.normals = normals;
            Tools.CalculateMeshTangents(mesh);

            mesh.RecalculateBounds();
            mesh.Optimize();
        }