TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
8 / 8
100.0%
Branches:
7 / 14
50.0%
Functions:
1 / 1, 1 excl
100.0%

layers/roughness.h
Line Branch Exec Source
1 /// @file
2 /// @brief `RoughnessLayer`, fine self-affine roughness from octaves of Perlin noise.
3 #pragma once
4
5 #include "terraingen/layers/fade.h"
6 #include "terraingen/layers/layer.h"
7 #include "terraingen/util/surface.h"
8
9 #include <array>
10 #include <cstdint>
11 #include <vector>
12
13 namespace terraingen {
14
15 /// The roughness a `RoughnessLayer` adds: RMS slope over a baseline and Hurst exponent, as
16 /// Shepard et al. (2001) give it.
17 struct RoughnessOptions {
18 4 double rmsSlope = 0.15; ///< RMS slope (rise over run) over `baseline`.
19 4 double baseline = 0.25; ///< Baseline the RMS slope is given over (m).
20 4 double hurst = 0.8; ///< Hurst exponent, in (0, 1].
21 4 double maxWavelength = 4.0; ///< Longest octave (m).
22 4 double minWavelength = 0.01; ///< Shortest octave (m); octaves halve down to it.
23 4 std::uint32_t seed = 1; ///< Varies the octaves' offsets and rotations.
24 /// How octaves too fine to resolve fade out, by samples per wavelength.
25 4 ResolutionFade fade{};
26
27
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
4 bool operator==(const RoughnessOptions&) const = default;
28 };
29
30 /// Checks roughness options.
31 /// @throws std::invalid_argument for a non-positive `rmsSlope` or `baseline`, a `hurst` outside
32 /// (0, 1], wavelengths that do not satisfy 0 < `minWavelength` <= `maxWavelength` or that span more
33 /// than 40 octaves, or an invalid `fade`.
34 void ValidateRoughnessOptions(const RoughnessOptions& options);
35
36 /// The structure function of `PerlinNoise2`: mean squared difference of values a lag `r` apart
37 /// (lattice units), over positions, directions and seeds; 0 for `r` <= 0.
38 double PerlinStructureFunction(double r);
39
40 /// The structure function of `PerlinNoise3` at a lag `r` (lattice units) in a random 3D
41 /// direction; 0 for `r` <= 0.
42 double Perlin3StructureFunction(double r);
43
44 /// Fine roughness: octaves of Perlin noise halving in wavelength from `maxWavelength` to
45 /// `minWavelength`, amplitudes growing as wavelength^H.
46 ///
47 /// Amplitudes are scaled so the RMS slope over `baseline` is `rmsSlope` with every octave
48 /// resolved. Octaves are rotated and offset so their lattices do not line up, and fade out at
49 /// spacings too coarse to resolve them.
50 class RoughnessLayer final : public FormulaLayer {
51 public:
52 /// On a sphere each octave is 3D Perlin noise at the 3D point, its lattice turned by a uniform
53 /// random rotation.
54 /// @throws std::invalid_argument as `ValidateRoughnessOptions`.
55 explicit RoughnessLayer(RoughnessOptions options, Surface surface = {});
56
57 /// The RMS slope (rise over run) over `baseline` metres with every octave resolved.
58 double RmsSlope(double baseline) const;
59
60 /// The octaves' wavelengths in metres, longest first.
61 std::vector<double> Wavelengths() const;
62
63 /// The options the layer was made with.
64 const RoughnessOptions& Options() const {
65 return options_;
66 }
67
68 protected:
69 float HeightAt(float height, double x, double y, double spacing,
70 const Ground* ground) const override;
71
72 private:
73 struct Octave {
74 double wavelength;
75 double amplitude;
76 double cos;
77 double sin;
78 double offsetX;
79 double offsetY;
80 std::uint32_t seed;
81 std::array<double, 9> rotation{};
82 double offsetZ = 0.0;
83 };
84
85 /// Octave `i` of `wavelength`, before its amplitude is scaled to the RMS slope.
86 Octave MakeOctave(std::uint32_t i, double wavelength) const;
87 /// The noise of one octave at (`x`, `y`), in [-1, 1].
88 double OctaveNoise(const Octave& octave, double x, double y) const;
89
90 RoughnessOptions options_;
91 std::vector<Octave> octaves_;
92 };
93
94 } // namespace terraingen
95