Example #1
0
        /* This error function was taken from http://www.volume-gfx.com/
         * However, it has a major flaw when points sampled have a very similar value
         * The only way to fix it is to sample from more points, have a maximum container size, or sample random points
         * This can still lead to the error falsely being calculated as negligible though for certain functions, such as noise functions
         * The only way (to my knowledge) is to sample points on a uniform grid as the original DMC paper suggests
         * It can be done efficiently though, like sampling the corners and mid points initially, then the in-between points, etc
         * And breaking early if the error exceeds the threshold
         */
        public float GetError(float threshold)
        {
            float error = 0;

            float[]   values           = new float[4];
            Vector2[] positions        = new Vector2[5];
            Vector2[] middle_positions =
            {
                new Vector2(0.5f, 0.0f),
                new Vector2(0.0f, 0.5f),
                new Vector2(0.5f, 0.5f),
                new Vector2(1.0f, 0.5f),
                new Vector2(0.5f, 1.0f)
            };

            for (int i = 0; i < 5; i++)
            {
                positions[i] = position + size * middle_positions[i];
                if (i < 4)
                {
                    values[i] = Sampler.Sample(position + size * new Vector2(i / 2, i % 2));
                }
            }

            for (int i = 0; i < 5; i++)
            {
                float   center_value = Sampler.Sample(positions[i]);
                Vector2 gradient     = Sampler.GetGradient(positions[i]);

                float interpolated = Interpolate(values[0], values[1], values[2], values[3], middle_positions[i]);
                float mag          = Math.Max(1.0f, gradient.Length());

                error += Math.Abs(center_value - interpolated) / mag;
                if (error >= threshold)
                {
                    break;
                }
            }

            return(error);
        }