/// <summary>
        /// Creates a mesh by reading the <see cref="Heightmap"/> and
        /// caches the result. If a mesh of the same resolution has already
        /// been created, it is returned and (optionally) added to the scene.
        /// In order to construct a mesh, the <see cref="HeightmapResolution"/>
        /// must be greater than or equal to the <see cref="MeshResolution"/>.
        /// </summary>
        /// <param name="addToScene">Optionally disable adding the Mesh directly to the scene</param>
        public MeshData CreateMesh(bool addToScene = true)
        {
            MeshData computed = FindComputedForResolution((int)MeshResolution);

            if (computed != default(MeshData))
            {
                return(computed);
            }

            Vector3[] vertices  = new Vector3[(int)MeshResolution * (int)MeshResolution];
            int       increment = HeightmapResolution / (int)MeshResolution;

            for (int x = 0; x < (int)MeshResolution; x += increment)
            {
                for (int z = 0; z < (int)MeshResolution; z += increment)
                {
                    Vector2 localXZ = PositionToLocal(x, z, (int)MeshResolution);

                    lock (_asyncMeshLock) {
                        float y = GetHeightAmplifiedAt(x, z);
                        vertices[x / increment + z / increment * (int)MeshResolution] = new Vector3(localXZ.x, y, localXZ.y);
                    }
                }
            }

            MeshData md = MeshDataFromVertices(vertices);

            ComputedMeshes.Add(new KeyValuePair <int, MeshData>((int)MeshResolution, md));

            if (addToScene)
            {
                var mf = _tile.GetMeshFilter();
                _tile.GetMeshRenderer();

                mf.sharedMesh = md.Mesh;
            }

            return(md);
        }
 /// <summary>
 /// Find the <see cref="ComputedMeshes"/> that has the passed
 /// resolution as a key.
 /// </summary>
 /// <param name="resolution">Resolution to search for</param>
 /// <returns>MeshData if found, default(MeshData) otherwise</returns>
 private MeshData FindComputedForResolution(int resolution)
 {
     return(ComputedMeshes.Find(kvp => kvp.Key == resolution).Value);
 }
 /// <summary>
 /// Whether this TileMesh has already computed a mesh
 /// with the passed resolution.
 /// </summary>
 /// <param name="res">resolution to check</param>
 public bool HasMeshAtResolution(Resolution res)
 {
     return(ComputedMeshes.Exists(kvp => kvp.Key == (int)res));
 }