/// <summary>
        /// Sets the terrain splat texture at the passed index to the same
        /// information provided in the passed material.
        /// </summary>
        /// <param name="index">Splat index to apply material to (0 - 3)</param>
        /// <param name="splat"></param>
        /// <param name="mat">Material to apply</param>
        void SetMaterialForSplatIndex(int index, SplatSetting splat, Material mat)
        {
            //Main Texture
            mat.SetTexture("_Splat" + index, splat.Diffuse);
            mat.SetTextureScale("_Splat" + index, splat.Tiling);
            mat.SetTextureOffset("_Splat" + index, splat.Offset);

            //Normal Texture
            mat.SetTexture("_Normal" + index, splat.Normal);
            mat.SetTextureScale("_Normal" + index, splat.Tiling);
            mat.SetTextureOffset("_Normal" + index, splat.Offset);

            //Smoothness
            mat.SetFloat("_Smoothness" + index, splat.Smoothness);
        }
        /// <summary>
        /// Calculates the weights that can be used to create a splatmap
        /// based on the passed sample and splats.
        /// </summary>
        /// <param name="sample">Sample to base calculation on</param>
        /// <param name="splat">Splat setting to base calculation on</param>
        /// <returns>Weight values in the same order of the </returns>
        float[] CalculateWeights(MeshSampler.MeshSample sample)
        {
            float height = sample.Height;
            float angle  = sample.Angle;

            float[] weights = new float[SplatSettings.Count];

            var orderMap = new Dictionary <PlacementType, int>()
            {
                { PlacementType.ElevationRange, 0 },
                { PlacementType.Angle, 1 }
            };
            List <SplatSetting> ordered = SplatSettings
                                          .OrderBy(s => orderMap[s.PlacementType]) //Order elevation before angle
                                                                                   //.OrderBy(s => s.MinRange)                //Order lower ranges
                                                                                   //.OrderBy(s => s.IsMinHeight)             //Order min height first
                                          .ToList();

            for (int i = 0; i < SplatSettings.Count; i++)
            {
                SplatSetting splat = ordered[i];

                float min = splat.IsMinHeight ? float.MinValue : splat.MinRange;
                float max = splat.IsMaxHeight ? float.MaxValue : splat.MaxRange;

                switch (splat.PlacementType)
                {
                case PlacementType.Angle:
                    if (angle > splat.AngleMin && angle < splat.AngleMax)
                    {
                        float factor = Mathf.Clamp01(((angle - splat.AngleMin)) / splat.Blend);
                        weights[i] = factor;
                    }

                    break;

                case PlacementType.ElevationRange:
                    if (height > min && height < max)
                    {
                        if (i > 0)                                   //Can blend up
                        {
                            float factor = Mathf.Clamp01((splat.Blend - (height - min)) / splat.Blend);
                            weights[i - 1] = factor;
                            weights[i]     = 1 - factor;
                        }
                        else
                        {
                            weights[i] = 1f;
                        }
                    }

                    break;
                }
            }

            //Normalize weights
            float sum = weights.Sum();

            for (var i = 0; i < weights.Length; i++)
            {
                weights[i] /= sum;
            }

            return(weights);
        }