TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
97 / 97
100.0%
Branches:
19 / 19
100.0%
Functions:
5 / 5
100.0%

noise/simplex.h
Line Branch Exec Source
1 /// @file
2 /// @brief Simplex noise in 2D and 3D.
3 #pragma once
4
5 #include "terraingen/noise/perlin.h"
6
7 namespace terraingen {
8
9 namespace detail {
10
11 /// The contribution (0.5 - r^2)^4 dot(g, d) of one simplex corner; 0 for r^2 >= 0.5.
12 /// @param ci Corner x on the skewed lattice, wrapped to 32 bits.
13 /// @param cj Corner y on the skewed lattice, wrapped to 32 bits.
14 /// @param dx Offset x from the corner, unskewed.
15 /// @param dy Offset y from the corner, unskewed.
16 2706174 inline float SimplexCorner(uint32_t ci, uint32_t cj, float dx, float dy, uint32_t seed) {
17 2706174 const float t = 0.5f - dx * dx - dy * dy;
18
2/2
✓ Branch 0 taken 257458 times.
✓ Branch 1 taken 2448716 times.
2706174 if (t <= 0.0f) {
19 257458 return 0.0f;
20 }
21 2448716 const float t2 = t * t;
22 2448716 return t2 * t2 * PerlinGradient2(PerlinCornerHash(ci, cj, seed), dx, dy);
23 }
24
25 /// The contribution (0.5 - r^2)^4 dot(g, d) of one corner of a 3D simplex, with `PerlinNoise3`'s
26 /// gradients and corner hash; 0 for r^2 >= 0.5.
27 1142812 inline float SimplexCorner3(uint32_t ci, uint32_t cj, uint32_t ck, float dx, float dy, float dz,
28 uint32_t seed) {
29 1142812 const float t = 0.5f - dx * dx - dy * dy - dz * dz;
30
2/2
✓ Branch 0 taken 302245 times.
✓ Branch 1 taken 840567 times.
1142812 if (t <= 0.0f) {
31 302245 return 0.0f;
32 }
33 840567 const float t2 = t * t;
34 840567 return t2 * t2 * PerlinGradient3(PerlinCornerHash3(ci, cj, ck, seed), dx, dy, dz);
35 }
36
37 } // namespace detail
38
39 /// 2D simplex noise at a point in lattice units, with the gradients and corner hash of
40 /// `PerlinNoise2`.
41 /// @return Noise in [-1, 1].
42 902058 inline float SimplexNoise2(float x, float y, uint32_t seed) {
43 902058 constexpr float kSkew = 0.366025403784438647f; // (sqrt(3) - 1) / 2
44 902058 constexpr float kUnskew = 0.211324865405187118f; // (3 - sqrt(3)) / 6
45 902058 constexpr float kScale = 99.0f;
46
47 902058 const float skew = (x + y) * kSkew;
48 902058 const float cellX = floor(x + skew);
49 902058 const float cellY = floor(y + skew);
50 902058 const float unskew = (cellX + cellY) * kUnskew;
51 902058 const float x0 = x - (cellX - unskew);
52 902058 const float y0 = y - (cellY - unskew);
53
54
2/2
✓ Branch 0 taken 453651 times.
✓ Branch 1 taken 448407 times.
902058 const uint32_t stepX = x0 > y0 ? 1u : 0u;
55 902058 const uint32_t stepY = 1u - stepX;
56 902058 const float x1 = x0 - float(stepX) + kUnskew;
57 902058 const float y1 = y0 - float(stepY) + kUnskew;
58 902058 const float x2 = x0 - 1.0f + 2.0f * kUnskew;
59 902058 const float y2 = y0 - 1.0f + 2.0f * kUnskew;
60
61 902058 const uint32_t i = uint32_t(int32_t(cellX));
62 902058 const uint32_t j = uint32_t(int32_t(cellY));
63 902058 return kScale * (detail::SimplexCorner(i, j, x0, y0, seed) +
64 902058 detail::SimplexCorner(i + stepX, j + stepY, x1, y1, seed) +
65 902058 detail::SimplexCorner(i + 1u, j + 1u, x2, y2, seed));
66 }
67
68 /// 3D simplex noise (Perlin 2001, Gustavson 2005) at a lattice cell and fraction, on the
69 /// tetrahedral lattice skewed by (x + y + z) / 3. The skew is split into integer and fractional
70 /// parts, so points far from the origin keep the precision of their fraction.
71 /// @return Noise in [-1, 1].
72 285703 inline float SimplexNoise3(LatticePoint3 point, uint32_t seed) {
73 285703 constexpr float kScale = 76.0f;
74 285703 const int32_t cellSum = int32_t(uint32_t(point.ix) + uint32_t(point.iy) + uint32_t(point.iz));
75 285703 int32_t third = cellSum / 3;
76
2/2
✓ Branch 0 taken 97557 times.
✓ Branch 1 taken 188146 times.
285703 if (cellSum - 3 * third < 0) {
77 97557 third -= 1;
78 }
79 285703 const float remainder = float(cellSum - 3 * third);
80 285703 const float skew = (remainder + point.fx + point.fy + point.fz) / 3.0f;
81 285703 const float stepX = floor(point.fx + skew);
82 285703 const float stepY = floor(point.fy + skew);
83 285703 const float stepZ = floor(point.fz + skew);
84 285703 const float unskew = (remainder + stepX + stepY + stepZ) / 6.0f;
85 285703 const float x0 = point.fx - stepX + unskew;
86 285703 const float y0 = point.fy - stepY + unskew;
87 285703 const float z0 = point.fz - stepZ + unskew;
88
89 285703 uint32_t i1 = 0u;
90 285703 uint32_t j1 = 0u;
91 285703 uint32_t k1 = 0u;
92 285703 uint32_t i2 = 0u;
93 285703 uint32_t j2 = 0u;
94 285703 uint32_t k2 = 0u;
95
2/2
✓ Branch 0 taken 143114 times.
✓ Branch 1 taken 142589 times.
285703 if (x0 >= y0) {
96
2/2
✓ Branch 0 taken 47859 times.
✓ Branch 1 taken 95255 times.
143114 if (y0 >= z0) {
97 47859 i1 = 1u;
98 47859 i2 = 1u;
99 47859 j2 = 1u;
100
2/2
✓ Branch 0 taken 47811 times.
✓ Branch 1 taken 47444 times.
95255 } else if (x0 >= z0) {
101 47811 i1 = 1u;
102 47811 i2 = 1u;
103 47811 k2 = 1u;
104 } else {
105 47444 k1 = 1u;
106 47444 i2 = 1u;
107 47444 k2 = 1u;
108 }
109
2/2
✓ Branch 0 taken 49119 times.
✓ Branch 1 taken 93470 times.
142589 } else if (y0 < z0) {
110 49119 k1 = 1u;
111 49119 j2 = 1u;
112 49119 k2 = 1u;
113
2/2
✓ Branch 0 taken 48491 times.
✓ Branch 1 taken 44979 times.
93470 } else if (x0 < z0) {
114 48491 j1 = 1u;
115 48491 j2 = 1u;
116 48491 k2 = 1u;
117 } else {
118 44979 j1 = 1u;
119 44979 i2 = 1u;
120 44979 j2 = 1u;
121 }
122 285703 constexpr float kUnskew = 1.0f / 6.0f;
123 285703 const float x1 = x0 - float(i1) + kUnskew;
124 285703 const float y1 = y0 - float(j1) + kUnskew;
125 285703 const float z1 = z0 - float(k1) + kUnskew;
126 285703 const float x2 = x0 - float(i2) + 2.0f * kUnskew;
127 285703 const float y2 = y0 - float(j2) + 2.0f * kUnskew;
128 285703 const float z2 = z0 - float(k2) + 2.0f * kUnskew;
129 285703 const float x3 = x0 - 1.0f + 3.0f * kUnskew;
130 285703 const float y3 = y0 - 1.0f + 3.0f * kUnskew;
131 285703 const float z3 = z0 - 1.0f + 3.0f * kUnskew;
132
133 285703 const uint32_t i = uint32_t(point.ix) + uint32_t(third) + uint32_t(int32_t(stepX));
134 285703 const uint32_t j = uint32_t(point.iy) + uint32_t(third) + uint32_t(int32_t(stepY));
135 285703 const uint32_t k = uint32_t(point.iz) + uint32_t(third) + uint32_t(int32_t(stepZ));
136 285703 const float sum = detail::SimplexCorner3(i, j, k, x0, y0, z0, seed) +
137 285703 detail::SimplexCorner3(i + i1, j + j1, k + k1, x1, y1, z1, seed) +
138 285703 detail::SimplexCorner3(i + i2, j + j2, k + k2, x2, y2, z2, seed) +
139 285703 detail::SimplexCorner3(i + 1u, j + 1u, k + 1u, x3, y3, z3, seed);
140
1/1
✓ Branch 1 taken 285703 times.
285703 return clamp(kScale * sum, -1.0f, 1.0f);
141 }
142
143 /// 3D simplex noise at a point in lattice units.
144 /// @return Noise in [-1, 1].
145 28101 inline float SimplexNoise3(float x, float y, float z, uint32_t seed) {
146 28101 return SimplexNoise3(SplitLattice3(x, y, z), seed);
147 }
148
149 } // namespace terraingen
150