public FractionalBrownianMotionFunction(INoiseProvider provider, Random rng, double scale, int octaves, double persistence = 0.5, double lacunarity = 2.0, Func<double, double> octaveModifier = null, double? xPeriod = null, double? yPeriod = null, SampleMode mode = SampleMode.Sample2D) { _octaveModifier = octaveModifier; _octaves = new Tuple<double, IFunction2D>[octaves]; bool tiling = xPeriod != null || yPeriod != null; if (tiling && xPeriod == null) { xPeriod = yPeriod; } if (tiling && yPeriod == null) { yPeriod = xPeriod; } _maxAmplitude = 0.0; var amplitude = 1.0; var frequency = scale; for (var i = 0; i < octaves; i++) { IFunction2D noise; switch (mode) { case SampleMode.Sample2D: noise = provider.Create2D(rng, frequency); break; case SampleMode.Slice3D: noise = provider.Slice3D(rng, frequency); break; case SampleMode.Slice4D: noise = provider.Slice4D(rng, frequency); break; case SampleMode.Tileable2D: noise = provider.Create2D(rng, frequency, xPeriod.Value, yPeriod.Value); break; default: throw new InvalidOperationException(); } _octaves[i] = Tuple.Create(amplitude, noise); _maxAmplitude += amplitude; amplitude *= persistence; frequency *= lacunarity; } }
private IFunction2D CreateNoiseFunction(INoiseProvider provider, Random rng) { if (_octaves == 1 && _power == 1.0 && !_absoluteValue) { // Simple case that doesn't need fBm, so we can just return a basic noise function // to remove some overhead for benchmarking. switch (_mode) { case SampleMode.Sample2D: return provider.Create2D(rng, _scale); case SampleMode.Slice3D: return provider.Slice3D(rng, _scale); case SampleMode.Slice4D: return provider.Slice4D(rng, _scale); case SampleMode.Tileable2D: return provider.Create2D(rng, _scale, _size, _size); default: throw new InvalidOperationException(); } } Func<double, double> modifier = null; if (_absoluteValue) { if (_power == 1.0) { modifier = input => (1.0 - Math.Abs(input)) * 2.0 - 1.0; } else { modifier = input => Math.Pow(1.0 - Math.Abs(input), _power) * 2.0 - 1.0; } } else if (_power != 1.0) { modifier = input => input < 0 ? -Math.Pow(-input, _power) : Math.Pow(input, _power); } return provider.FractionalBrownianMotion(rng, _scale, _octaves, _persistence, _lacunarity, modifier, _size, _size, _mode); }